Initial commit
This commit is contained in:
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
*.bin
|
||||||
|
/kernel
|
||||||
26
build.sh
Executable file
26
build.sh
Executable file
@@ -0,0 +1,26 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
export LC_ALL=C
|
||||||
|
|
||||||
|
nasm -fbin -o 1.bin src/boot/x86/1.asm
|
||||||
|
nasm -DSTAGE2_SIZE=$(stat --printf="%s" 1.bin) -fbin -o 0.bin src/boot/x86/0.asm
|
||||||
|
|
||||||
|
i386-unknown-elf-gcc -s -Wl,--export-dynamic -fno-pic -flto -Os -mgeneral-regs-only -Isrc/kernel/ -ffreestanding -nostdlib -nostartfiles -o kernel src/kernel/x86/ppm.c src/kernel/x86/vpm.c src/kernel/x86/log.c src/kernel/tinyubsan.c src/kernel/main.c -fsanitize=undefined
|
||||||
|
|
||||||
|
dd if=/dev/zero of=drive.bin bs=1024 count=10240
|
||||||
|
/bin/echo -e 'mklabel msdos\nmkpart primary 8192b -1s\nquit\n' | parted drive.bin
|
||||||
|
[[ "$(udisksctl loop-setup -f drive.bin)" =~ (/dev/loop[0-9]+) ]] && LOOPDEV="${BASH_REMATCH[1]}"
|
||||||
|
sudo mkfs.ext2 -E root_perms=777 -b 1024 "${LOOPDEV}p1"
|
||||||
|
sleep 0.5
|
||||||
|
[[ "$(udisksctl mount -b ${LOOPDEV}p1)" =~ (/run/.+) ]] && MOUNTDIR="${BASH_REMATCH[1]}"
|
||||||
|
cp ./kernel "${MOUNTDIR}/kernel"
|
||||||
|
udisksctl unmount -b "${LOOPDEV}p1"
|
||||||
|
udisksctl loop-delete -b "${LOOPDEV}"
|
||||||
|
|
||||||
|
# Copy first stage bootloader without overwriting MBR
|
||||||
|
dd if=0.bin of=drive.bin bs=1 count=440 seek=0 conv=notrunc,nocreat
|
||||||
|
|
||||||
|
# Copy second stage bootloader, hope it's not too fat
|
||||||
|
dd if=1.bin of=drive.bin bs=1 seek=512 conv=notrunc,nocreat
|
||||||
53
src/boot/x86/0.asm
Normal file
53
src/boot/x86/0.asm
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
bits 16
|
||||||
|
org 0x7C00
|
||||||
|
|
||||||
|
jmp 0x0:_start
|
||||||
|
_start:
|
||||||
|
mov ax, 0
|
||||||
|
mov ds, ax
|
||||||
|
mov es, ax
|
||||||
|
mov ss, ax
|
||||||
|
mov fs, ax
|
||||||
|
mov gs, ax
|
||||||
|
|
||||||
|
mov ax, 0x2403
|
||||||
|
int 0x15
|
||||||
|
jc a20_ns
|
||||||
|
test ah, ah
|
||||||
|
jnz a20_ns
|
||||||
|
|
||||||
|
mov ax, 0x2402
|
||||||
|
int 0x15
|
||||||
|
jc a20_failed
|
||||||
|
test ah, ah
|
||||||
|
jnz a20_failed
|
||||||
|
test al, al
|
||||||
|
jnz a20_activated
|
||||||
|
|
||||||
|
mov ax, 0x2401
|
||||||
|
int 0x15
|
||||||
|
jc a20_failed
|
||||||
|
test ah, ah
|
||||||
|
jnz a20_failed
|
||||||
|
a20_activated:
|
||||||
|
|
||||||
|
mov ah, 0x02
|
||||||
|
mov al, (STAGE2_SIZE + 511) / 512
|
||||||
|
mov ch, 0
|
||||||
|
mov dh, 0
|
||||||
|
mov dl, 0x80
|
||||||
|
mov cl, 2
|
||||||
|
mov bx, 0x1000
|
||||||
|
int 0x13
|
||||||
|
|
||||||
|
jmp 0x0:0x1000
|
||||||
|
|
||||||
|
a20_ns:
|
||||||
|
a20_failed:
|
||||||
|
mov ax, 0xB800
|
||||||
|
mov ds, ax
|
||||||
|
mov [0], byte 'L'
|
||||||
|
jmp $
|
||||||
|
|
||||||
|
times 510 - ($ - $$) db 0
|
||||||
|
dw 0xAA55
|
||||||
337
src/boot/x86/1.asm
Normal file
337
src/boot/x86/1.asm
Normal file
@@ -0,0 +1,337 @@
|
|||||||
|
bits 16
|
||||||
|
org 0x1000
|
||||||
|
|
||||||
|
; This bootloader should get the kernel in a fully running state,
|
||||||
|
; instead of the kernel initializing itself
|
||||||
|
;
|
||||||
|
; It attempts to load a file named "kernel" from the root of an ext2
|
||||||
|
; partition, and set necessary state by peeking into the kernel's
|
||||||
|
; exported symbols, e.g. ppm_Bitmap.
|
||||||
|
;
|
||||||
|
; See 1_elf.asm and 1_fs.asm.
|
||||||
|
|
||||||
|
MBR_PARTITION_TABLE equ 0x7DBE
|
||||||
|
|
||||||
|
KERNEL_INITIAL_LOAD equ 0xA000
|
||||||
|
KERNEL_BASE equ 0x2000
|
||||||
|
|
||||||
|
PAGE_PRESENT equ 1
|
||||||
|
PAGE_RW equ 2
|
||||||
|
PAGE_GLOBAL equ 256
|
||||||
|
|
||||||
|
start:
|
||||||
|
mov esp, 0x1000
|
||||||
|
cld
|
||||||
|
|
||||||
|
push 0xB800
|
||||||
|
pop fs
|
||||||
|
mov bx, 0
|
||||||
|
.clear_screen:
|
||||||
|
mov [fs:bx], byte ' '
|
||||||
|
add bx, 2
|
||||||
|
cmp bx, 4000
|
||||||
|
jne .clear_screen
|
||||||
|
|
||||||
|
; Get first partition's starting LBA
|
||||||
|
mov eax, MBR_PARTITION_TABLE
|
||||||
|
mov ebx, [eax + 0x08]
|
||||||
|
mov [PARTITION_START], ebx
|
||||||
|
|
||||||
|
call ext2_test
|
||||||
|
jnc .exist
|
||||||
|
mov eax, msg_partition_not_found
|
||||||
|
call print_string
|
||||||
|
jmp $
|
||||||
|
.exist:
|
||||||
|
|
||||||
|
call find_kernel_inode
|
||||||
|
test eax, eax
|
||||||
|
jnz .kernel_found
|
||||||
|
mov eax, msg_kernel_not_found
|
||||||
|
call print_string
|
||||||
|
jmp $
|
||||||
|
.kernel_found:
|
||||||
|
|
||||||
|
call load_kernel
|
||||||
|
jnc .kernel_loaded
|
||||||
|
mov eax, msg_kernel_fail
|
||||||
|
call print_string
|
||||||
|
jmp $
|
||||||
|
.kernel_loaded:
|
||||||
|
|
||||||
|
; Use edi to dynamically allocate anything with an unknown size
|
||||||
|
; Start allocation immediately after the kernel's image
|
||||||
|
|
||||||
|
mov edi, [KERNEL_END]
|
||||||
|
add edi, 4095
|
||||||
|
and edi, ~4095
|
||||||
|
|
||||||
|
; Create template page directory and page table
|
||||||
|
; Necessary as the kernel will use this in vpm_create_space
|
||||||
|
|
||||||
|
mov eax, 0
|
||||||
|
mov ecx, 8192
|
||||||
|
rep stosb
|
||||||
|
|
||||||
|
sub edi, 8192
|
||||||
|
|
||||||
|
mov dword [edi + 0], edi ; First 4MB of memory will be identity mapped, with the exception of 0 - 0x1000
|
||||||
|
add dword [edi + 0], 4096 | PAGE_PRESENT | PAGE_RW | PAGE_GLOBAL
|
||||||
|
mov dword [edi + 4092], edi ; Recursively map last 4MB
|
||||||
|
add dword [edi + 4092], PAGE_PRESENT | PAGE_RW | PAGE_GLOBAL
|
||||||
|
|
||||||
|
mov ecx, 1
|
||||||
|
mov eax, 4096 | PAGE_PRESENT | PAGE_RW
|
||||||
|
.identity_map_lup:
|
||||||
|
mov dword [edi + 4096 + ecx * 4], eax
|
||||||
|
add eax, 4096
|
||||||
|
inc ecx
|
||||||
|
cmp ecx, 1024
|
||||||
|
jb .identity_map_lup
|
||||||
|
|
||||||
|
mov cr3, edi
|
||||||
|
|
||||||
|
add edi, 8192
|
||||||
|
|
||||||
|
; Get memory map, setup ppm_Bitmap
|
||||||
|
|
||||||
|
mov eax, string_ppm_Bitmap
|
||||||
|
call elf_find_symbol
|
||||||
|
mov eax, [eax + ELFSym.st_value]
|
||||||
|
add eax, KERNEL_BASE
|
||||||
|
mov [eax], edi
|
||||||
|
|
||||||
|
xor cx, cx
|
||||||
|
xor dx, dx
|
||||||
|
mov ax, 0xE801 ; do not care enough for E820 at the moment
|
||||||
|
int 0x15
|
||||||
|
jc short .err
|
||||||
|
cmp ah, 0x86
|
||||||
|
je short .err
|
||||||
|
cmp ah, 0x80
|
||||||
|
jne short .nerr
|
||||||
|
.err:
|
||||||
|
mov eax, msg_memory_fail
|
||||||
|
call print_string
|
||||||
|
jmp $
|
||||||
|
.nerr:
|
||||||
|
jcxz .useax
|
||||||
|
mov ax, cx ; amount of mem starting at 1MB, in kB units
|
||||||
|
mov bx, dx ; amount of mem starting at 16MB, in 64kB units
|
||||||
|
.useax:
|
||||||
|
mov [edi], dword 0x100000
|
||||||
|
mov [edi + 4], dword 0
|
||||||
|
movzx eax, ax
|
||||||
|
shr eax, 2 ; divide by 4 to get 4kB (page) units
|
||||||
|
mov [edi + 8], eax
|
||||||
|
mov [edi + 12], dword 0
|
||||||
|
add edi, 16
|
||||||
|
mov ecx, eax
|
||||||
|
add ecx, 7
|
||||||
|
shr ecx, 3 ; ecx = number of bytes belonging to bitmap
|
||||||
|
mov al, 0
|
||||||
|
rep stosb
|
||||||
|
|
||||||
|
; Save kernel's k_init
|
||||||
|
|
||||||
|
mov eax, string_k_init
|
||||||
|
call elf_find_symbol
|
||||||
|
test eax, eax
|
||||||
|
jnz .k_init_found
|
||||||
|
mov eax, msg_kernel_fail
|
||||||
|
call print_dword_hex
|
||||||
|
jmp $
|
||||||
|
.k_init_found:
|
||||||
|
mov eax, [eax + ELFSym.st_value]
|
||||||
|
add eax, KERNEL_BASE
|
||||||
|
mov [FUNC_k_init], eax
|
||||||
|
|
||||||
|
; Up to now, our stack is within 0-0x1000, which will be unmapped in
|
||||||
|
; protected mode, so lastly, we allocate 8kB for the kernel stack
|
||||||
|
add edi, 8192 + 15
|
||||||
|
add edi, ~15
|
||||||
|
mov esp, edi
|
||||||
|
|
||||||
|
; nasm doesn't support arithmetic on labels so we have to
|
||||||
|
; dynamically compute the TSS segment's base
|
||||||
|
mov eax, TSS
|
||||||
|
mov [GDT + 42], ax
|
||||||
|
shr eax, 16
|
||||||
|
mov [GDT + 44], al
|
||||||
|
mov [GDT + 47], ah
|
||||||
|
|
||||||
|
; Finally enter protected mode
|
||||||
|
cli
|
||||||
|
lgdt [GDT]
|
||||||
|
mov eax, cr0
|
||||||
|
or eax, 0x80000001
|
||||||
|
mov cr0, eax
|
||||||
|
jmp 0x08:.inPE
|
||||||
|
bits 32
|
||||||
|
.inPE:
|
||||||
|
mov ax, 0x10
|
||||||
|
mov ss, ax
|
||||||
|
mov ds, ax
|
||||||
|
mov es, ax
|
||||||
|
mov fs, ax
|
||||||
|
mov gs, ax
|
||||||
|
|
||||||
|
mov ax, 0x28
|
||||||
|
ltr ax
|
||||||
|
|
||||||
|
mov eax, [FUNC_k_init]
|
||||||
|
call eax
|
||||||
|
jmp $
|
||||||
|
|
||||||
|
bits 16
|
||||||
|
|
||||||
|
; compare C-strings in eax and ebx
|
||||||
|
; after calling, eax and ebx point to respective null terminators
|
||||||
|
streq:
|
||||||
|
push edx
|
||||||
|
.scanlup:
|
||||||
|
mov dl, [eax]
|
||||||
|
cmp dl, [ebx]
|
||||||
|
jnz .end
|
||||||
|
test dl, dl
|
||||||
|
jz .end
|
||||||
|
cmp byte [ebx], 0
|
||||||
|
jz .end
|
||||||
|
|
||||||
|
inc eax
|
||||||
|
inc ebx
|
||||||
|
jmp .scanlup
|
||||||
|
.end:
|
||||||
|
pushfd
|
||||||
|
.inceaxlup:
|
||||||
|
cmp byte [eax], 0
|
||||||
|
jz .endier
|
||||||
|
inc eax
|
||||||
|
jmp .inceaxlup
|
||||||
|
.endier:
|
||||||
|
.incebxlup:
|
||||||
|
cmp byte [ebx], 0
|
||||||
|
jz .endierier
|
||||||
|
inc ebx
|
||||||
|
jmp .incebxlup
|
||||||
|
.endierier:
|
||||||
|
popfd
|
||||||
|
pop edx
|
||||||
|
ret
|
||||||
|
|
||||||
|
print_char:
|
||||||
|
push ebx
|
||||||
|
mov ebx, [.offset]
|
||||||
|
mov [fs:ebx], al
|
||||||
|
pop ebx
|
||||||
|
add [.offset], dword 2
|
||||||
|
ret
|
||||||
|
.offset dd 0
|
||||||
|
|
||||||
|
print_string:
|
||||||
|
push ebx
|
||||||
|
push eax
|
||||||
|
mov ebx, eax
|
||||||
|
.lup:
|
||||||
|
cmp byte [ebx], 0
|
||||||
|
je .end
|
||||||
|
movzx eax, byte [ebx]
|
||||||
|
call print_char
|
||||||
|
inc ebx
|
||||||
|
jmp .lup
|
||||||
|
.end:
|
||||||
|
pop eax
|
||||||
|
pop ebx
|
||||||
|
ret
|
||||||
|
|
||||||
|
; in eax = dword to print
|
||||||
|
print_dword_hex:
|
||||||
|
pushad
|
||||||
|
mov ecx, 8
|
||||||
|
.lup:
|
||||||
|
rol eax, 4
|
||||||
|
push eax
|
||||||
|
and al, 15
|
||||||
|
cmp al, 10
|
||||||
|
jb .d
|
||||||
|
add al, 'A' - '0' - 10
|
||||||
|
.d:
|
||||||
|
add al, '0'
|
||||||
|
call print_char
|
||||||
|
pop eax
|
||||||
|
dec ecx
|
||||||
|
jnz .lup
|
||||||
|
mov al, 10
|
||||||
|
call print_char
|
||||||
|
popad
|
||||||
|
ret
|
||||||
|
|
||||||
|
%include "src/boot/x86/1_elf.asm"
|
||||||
|
%include "src/boot/x86/1_fs.asm"
|
||||||
|
|
||||||
|
DAPACK:
|
||||||
|
db 0x10
|
||||||
|
db 0
|
||||||
|
.blkcnt: dw 0
|
||||||
|
.db_add: dw READ_LBA_RESULT
|
||||||
|
dw 0
|
||||||
|
.d_lba: dd 0
|
||||||
|
dd 0
|
||||||
|
|
||||||
|
GDT:
|
||||||
|
; Use null descriptor space for gdtr
|
||||||
|
dw GDT.end - GDT - 1
|
||||||
|
dd GDT
|
||||||
|
dw 0
|
||||||
|
; Kernel code (08)
|
||||||
|
db 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x9A, 0xCF, 0x00
|
||||||
|
; Kernel data (10)
|
||||||
|
db 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x92, 0xCF, 0x00
|
||||||
|
; User code (18)
|
||||||
|
db 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFA, 0xCF, 0x00
|
||||||
|
; User data (20)
|
||||||
|
db 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xF2, 0xCF, 0x00
|
||||||
|
; TSS(filled later) (28)
|
||||||
|
db 0x07, 0x01, 0x00, 0x00, 0x00, 0x89, 0x00, 0x00
|
||||||
|
.end:
|
||||||
|
|
||||||
|
TSS:
|
||||||
|
dd 0
|
||||||
|
TSS.esp0:
|
||||||
|
dd 0
|
||||||
|
TSS.ss0:
|
||||||
|
dd 0
|
||||||
|
times 96 db 0
|
||||||
|
|
||||||
|
elf_DYNSTR_TABLE: dd 0
|
||||||
|
elf_DYNSYM_TABLE: dd 0
|
||||||
|
elf_DYNSYMS: dd 0
|
||||||
|
|
||||||
|
READ_LBA_RESULT: times 512 db 0
|
||||||
|
PARTITION_START: dd 0
|
||||||
|
INODES_PER_GROUP: dd 0
|
||||||
|
INODE_SIZE: dd 0
|
||||||
|
KERNEL_END: dd 0
|
||||||
|
|
||||||
|
FUNC_k_init: dd 0
|
||||||
|
|
||||||
|
string_reldyn: db ".rel.dyn", 0
|
||||||
|
string_dynstr: db ".dynstr", 0
|
||||||
|
string_dynsym: db ".dynsym", 0
|
||||||
|
string_ppm_Bitmap: db "ppm_Bitmap", 0
|
||||||
|
string_scheduler_spawn: db "scheduler_spawn", 0
|
||||||
|
string_k_init: db "k_init", 0
|
||||||
|
|
||||||
|
msg_partition_not_found: db "Failed to find partition.", 0
|
||||||
|
msg_kernel_not_found: db "Failed to find kernel.", 0
|
||||||
|
msg_kernel_fail: db "Failed to load kernel.", 0
|
||||||
|
msg_memory_fail: db "Failed to determine memory.", 0
|
||||||
|
|
||||||
|
; Align to sector size
|
||||||
|
times (512 - ($ - $$) % 512) % 512 db 0
|
||||||
|
|
||||||
|
AFTER_THIS equ $
|
||||||
|
|
||||||
|
BLOCK_SCRATCH1 equ AFTER_THIS
|
||||||
|
ext2_read_inode_bytes_SCRATCH equ (AFTER_THIS + 1024)
|
||||||
|
ext2_get_inode_data_SCRATCH equ (ext2_read_inode_bytes_SCRATCH + 1024)
|
||||||
279
src/boot/x86/1_elf.asm
Normal file
279
src/boot/x86/1_elf.asm
Normal file
@@ -0,0 +1,279 @@
|
|||||||
|
struc ELFHeader
|
||||||
|
.e_ident resb 16
|
||||||
|
.e_type resw 1
|
||||||
|
.e_machine resw 1
|
||||||
|
.e_version resd 1
|
||||||
|
.e_entry resd 1
|
||||||
|
.e_phoff resd 1
|
||||||
|
.e_shoff resd 1
|
||||||
|
.e_flags resd 1
|
||||||
|
.e_ehsize resw 1
|
||||||
|
.e_phentsize resw 1
|
||||||
|
.e_phnum resw 1
|
||||||
|
.e_shentsize resw 1
|
||||||
|
.e_shnum resw 1
|
||||||
|
.e_shstrndx resw 1
|
||||||
|
endstruc
|
||||||
|
|
||||||
|
struc ELFSection
|
||||||
|
.sh_name resd 1
|
||||||
|
.sh_type resd 1
|
||||||
|
.sh_flags resd 1
|
||||||
|
.sh_addr resd 1
|
||||||
|
.sh_offset resd 1
|
||||||
|
.sh_size resd 1
|
||||||
|
.sh_link resd 1
|
||||||
|
.sh_info resd 1
|
||||||
|
.sh_addralign resd 1
|
||||||
|
.sh_entsize resd 1
|
||||||
|
endstruc
|
||||||
|
|
||||||
|
struc ELFProgram
|
||||||
|
.p_type resd 1
|
||||||
|
.p_offset resd 1
|
||||||
|
.p_vaddr resd 1
|
||||||
|
.p_paddr resd 1
|
||||||
|
.p_filesz resd 1
|
||||||
|
.p_memsz resd 1
|
||||||
|
.p_flags resd 1
|
||||||
|
.p_align resd 1
|
||||||
|
endstruc
|
||||||
|
|
||||||
|
struc ELFSym
|
||||||
|
.st_name resd 1
|
||||||
|
.st_value resd 1
|
||||||
|
.st_size resd 1
|
||||||
|
.st_info resb 1
|
||||||
|
.st_other resb 1
|
||||||
|
.st_shndx resw 1
|
||||||
|
endstruc
|
||||||
|
|
||||||
|
; in eax = kernel file inode
|
||||||
|
load_kernel:
|
||||||
|
pushad
|
||||||
|
|
||||||
|
mov edi, ext2_get_inode_data_SCRATCH
|
||||||
|
call ext2_get_inode_data
|
||||||
|
|
||||||
|
mov esi, ext2_get_inode_data_SCRATCH
|
||||||
|
mov eax, 0
|
||||||
|
mov ecx, [ext2_get_inode_data_SCRATCH + 4] ; filesize
|
||||||
|
mov edi, KERNEL_INITIAL_LOAD
|
||||||
|
call ext2_read_inode_bytes
|
||||||
|
|
||||||
|
cmp dword [KERNEL_INITIAL_LOAD], 0x464C457F ;ELF signature
|
||||||
|
je .pass_signature
|
||||||
|
popad
|
||||||
|
stc
|
||||||
|
ret
|
||||||
|
.pass_signature:
|
||||||
|
|
||||||
|
; follow the LOAD program header instructions
|
||||||
|
|
||||||
|
movzx ecx, word [KERNEL_INITIAL_LOAD + ELFHeader.e_phnum]
|
||||||
|
movzx ebp, word [KERNEL_INITIAL_LOAD + ELFHeader.e_phentsize]
|
||||||
|
mov eax, KERNEL_INITIAL_LOAD
|
||||||
|
add eax, [eax + ELFHeader.e_phoff]
|
||||||
|
|
||||||
|
.lup0:
|
||||||
|
cmp dword [eax + ELFProgram.p_type], 1 ; PT_LOAD
|
||||||
|
jne .skip0
|
||||||
|
pushad
|
||||||
|
|
||||||
|
mov esi, [eax + ELFProgram.p_offset]
|
||||||
|
|
||||||
|
mov ecx, [eax + ELFProgram.p_memsz]
|
||||||
|
add ecx, esi
|
||||||
|
add ecx, 4095
|
||||||
|
and ecx, ~4095
|
||||||
|
and esi, ~4095
|
||||||
|
sub ecx, esi
|
||||||
|
|
||||||
|
add esi, KERNEL_INITIAL_LOAD
|
||||||
|
|
||||||
|
mov edi, [eax + ELFProgram.p_vaddr]
|
||||||
|
and edi, ~4095
|
||||||
|
add edi, KERNEL_BASE
|
||||||
|
|
||||||
|
test ecx, ecx
|
||||||
|
jz .skipcopy
|
||||||
|
rep movsb
|
||||||
|
.skipcopy:
|
||||||
|
|
||||||
|
mov edi, [eax + ELFProgram.p_vaddr]
|
||||||
|
add edi, KERNEL_BASE
|
||||||
|
add edi, [eax + ELFProgram.p_filesz]
|
||||||
|
|
||||||
|
mov ecx, [eax + ELFProgram.p_memsz]
|
||||||
|
sub ecx, [eax + ELFProgram.p_filesz]
|
||||||
|
|
||||||
|
test ecx, ecx
|
||||||
|
jz .skipbss
|
||||||
|
mov eax, 0
|
||||||
|
rep stosb
|
||||||
|
.skipbss:
|
||||||
|
|
||||||
|
cmp edi, [KERNEL_END]
|
||||||
|
jbe .maxkernelend
|
||||||
|
mov [KERNEL_END], edi
|
||||||
|
.maxkernelend:
|
||||||
|
|
||||||
|
popad
|
||||||
|
.skip0:
|
||||||
|
add eax, ebp
|
||||||
|
dec ecx
|
||||||
|
jnz .lup0
|
||||||
|
|
||||||
|
; fix up the relocations
|
||||||
|
|
||||||
|
mov esi, KERNEL_INITIAL_LOAD
|
||||||
|
mov eax, string_reldyn
|
||||||
|
call elf_find_array_section_by_name
|
||||||
|
.lup2:
|
||||||
|
mov ebx, [eax]
|
||||||
|
add dword [KERNEL_BASE + ebx], KERNEL_BASE
|
||||||
|
add eax, ebp
|
||||||
|
|
||||||
|
dec ecx
|
||||||
|
jnz .lup2
|
||||||
|
|
||||||
|
; Save .dynstr for elf_find_symbol to use
|
||||||
|
|
||||||
|
mov esi, KERNEL_INITIAL_LOAD
|
||||||
|
mov eax, string_dynstr
|
||||||
|
call elf_find_array_section_by_name
|
||||||
|
mov [elf_DYNSTR_TABLE], eax
|
||||||
|
|
||||||
|
; Save .dynsym for elf_find_symbol to use
|
||||||
|
|
||||||
|
mov esi, KERNEL_INITIAL_LOAD
|
||||||
|
mov eax, string_dynsym
|
||||||
|
call elf_find_array_section_by_name
|
||||||
|
mov [elf_DYNSYM_TABLE], eax
|
||||||
|
mov [elf_DYNSYMS], ecx
|
||||||
|
|
||||||
|
popad
|
||||||
|
clc
|
||||||
|
ret
|
||||||
|
|
||||||
|
; in esi = ptr to elf file
|
||||||
|
; in eax = section name ptr
|
||||||
|
; out eax = ptr to section data (or 0)
|
||||||
|
; out ebp = section entry size
|
||||||
|
; out ecx = section entry count
|
||||||
|
elf_find_array_section_by_name:
|
||||||
|
push ebx
|
||||||
|
push edx
|
||||||
|
|
||||||
|
; ebx = section name ptr
|
||||||
|
mov ebx, eax
|
||||||
|
|
||||||
|
; ebp = section table entry size
|
||||||
|
movzx ebp, word [esi + ELFHeader.e_shentsize]
|
||||||
|
|
||||||
|
movzx eax, word [esi + ELFHeader.e_shstrndx]
|
||||||
|
mul ebp
|
||||||
|
|
||||||
|
; edx = section table
|
||||||
|
mov edx, [esi + ELFHeader.e_shoff]
|
||||||
|
add edx, esi
|
||||||
|
|
||||||
|
; eax = string table
|
||||||
|
add eax, edx
|
||||||
|
mov eax, [eax + ELFSection.sh_offset]
|
||||||
|
add eax, esi
|
||||||
|
|
||||||
|
; ecx = section index counter
|
||||||
|
mov ecx, 0
|
||||||
|
.lup:
|
||||||
|
push eax
|
||||||
|
push ebx
|
||||||
|
add eax, [edx + ELFSection.sh_name]
|
||||||
|
call streq
|
||||||
|
pop ebx
|
||||||
|
pop eax
|
||||||
|
je .found
|
||||||
|
|
||||||
|
add edx, ebp
|
||||||
|
inc ecx
|
||||||
|
cmp cx, word [esi + ELFHeader.e_shnum]
|
||||||
|
jb .lup
|
||||||
|
|
||||||
|
mov eax, 0
|
||||||
|
jmp .notfound
|
||||||
|
.found:
|
||||||
|
|
||||||
|
; eax = section header
|
||||||
|
mov eax, ecx
|
||||||
|
mul ebp
|
||||||
|
add eax, [esi + ELFHeader.e_shoff]
|
||||||
|
add eax, esi
|
||||||
|
|
||||||
|
; ebp = section entry size
|
||||||
|
mov ebp, [eax + ELFSection.sh_entsize]
|
||||||
|
|
||||||
|
; ecx = entry count
|
||||||
|
mov ecx, 0
|
||||||
|
|
||||||
|
test ebp, ebp
|
||||||
|
jz .zeroentitysize
|
||||||
|
push eax
|
||||||
|
mov eax, [eax + ELFSection.sh_size]
|
||||||
|
mov edx, 0
|
||||||
|
div ebp
|
||||||
|
mov ecx, eax
|
||||||
|
pop eax
|
||||||
|
.zeroentitysize:
|
||||||
|
|
||||||
|
mov eax, [eax + ELFSection.sh_offset]
|
||||||
|
add eax, esi
|
||||||
|
|
||||||
|
.notfound:
|
||||||
|
pop edx
|
||||||
|
pop ebx
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
elf_find_symbol:
|
||||||
|
cmp dword [elf_DYNSTR_TABLE], 0
|
||||||
|
jnz .inited1
|
||||||
|
; table not loaded
|
||||||
|
ret
|
||||||
|
.inited1:
|
||||||
|
cmp dword [elf_DYNSYM_TABLE], 0
|
||||||
|
jnz .inited2
|
||||||
|
; table not loaded
|
||||||
|
ret
|
||||||
|
.inited2:
|
||||||
|
|
||||||
|
push edx
|
||||||
|
push ecx
|
||||||
|
push ebx
|
||||||
|
|
||||||
|
mov edx, [elf_DYNSYM_TABLE]
|
||||||
|
mov ecx, 0
|
||||||
|
|
||||||
|
.lup:
|
||||||
|
mov ebx, [elf_DYNSTR_TABLE]
|
||||||
|
add ebx, [edx + ELFSym.st_name]
|
||||||
|
push eax
|
||||||
|
call streq
|
||||||
|
pop eax
|
||||||
|
je .found
|
||||||
|
|
||||||
|
add edx, 16 ; symbol size
|
||||||
|
inc ecx
|
||||||
|
cmp ecx, [elf_DYNSYMS]
|
||||||
|
jne .lup
|
||||||
|
|
||||||
|
; symbol not found
|
||||||
|
mov edx, 0
|
||||||
|
|
||||||
|
.found:
|
||||||
|
mov eax, edx
|
||||||
|
|
||||||
|
pop ebx
|
||||||
|
pop ecx
|
||||||
|
pop edx
|
||||||
|
|
||||||
|
ret
|
||||||
248
src/boot/x86/1_fs.asm
Normal file
248
src/boot/x86/1_fs.asm
Normal file
@@ -0,0 +1,248 @@
|
|||||||
|
; Only searches first block of root directory
|
||||||
|
find_kernel_inode:
|
||||||
|
push edi
|
||||||
|
push esi
|
||||||
|
push ecx
|
||||||
|
|
||||||
|
mov eax, 2
|
||||||
|
mov edi, ext2_get_inode_data_SCRATCH
|
||||||
|
call ext2_get_inode_data
|
||||||
|
|
||||||
|
mov esi, ext2_get_inode_data_SCRATCH
|
||||||
|
mov eax, 0
|
||||||
|
mov edi, BLOCK_SCRATCH1
|
||||||
|
call ext2_read_inode_block
|
||||||
|
|
||||||
|
mov eax, 0 ; null inode
|
||||||
|
|
||||||
|
.lup:
|
||||||
|
cmp byte [edi + 6], 6 ; length of "kernel"
|
||||||
|
jne .skip
|
||||||
|
cmp [edi + 8], dword 'kern'
|
||||||
|
jne .skip
|
||||||
|
cmp [edi + 12], word 'el'
|
||||||
|
jne .skip
|
||||||
|
mov eax, [edi + 0] ; inode
|
||||||
|
jmp .end
|
||||||
|
.skip:
|
||||||
|
movzx ecx, word [edi + 4] ; record length
|
||||||
|
add edi, ecx
|
||||||
|
cmp edi, BLOCK_SCRATCH1 + 1024
|
||||||
|
jb .lup
|
||||||
|
|
||||||
|
.end:
|
||||||
|
pop ecx
|
||||||
|
pop esi
|
||||||
|
pop edi
|
||||||
|
ret
|
||||||
|
|
||||||
|
; in esi = ptr to inode structure
|
||||||
|
; in eax = start offset byte
|
||||||
|
; in ecx = number of bytes to read
|
||||||
|
; in es:edi = pointer to destination
|
||||||
|
ext2_read_inode_bytes:
|
||||||
|
pushad
|
||||||
|
|
||||||
|
push eax
|
||||||
|
and eax, 1023
|
||||||
|
mov [.BLOCK_OFFSET], eax
|
||||||
|
pop eax
|
||||||
|
|
||||||
|
mov [.BYTES_REMAINING], ecx
|
||||||
|
|
||||||
|
lea edx, [eax + ecx - 1]
|
||||||
|
shr edx, 10
|
||||||
|
shr eax, 10
|
||||||
|
|
||||||
|
mov ebp, eax
|
||||||
|
|
||||||
|
; ebp = start block
|
||||||
|
; eax = counter
|
||||||
|
; edx = end block (inclusive)
|
||||||
|
.lup:
|
||||||
|
push edi
|
||||||
|
mov edi, ext2_read_inode_bytes_SCRATCH
|
||||||
|
call ext2_read_inode_block
|
||||||
|
|
||||||
|
mov esi, edi
|
||||||
|
mov ecx, 1024
|
||||||
|
pop edi
|
||||||
|
|
||||||
|
cmp eax, ebp
|
||||||
|
jne .not_start
|
||||||
|
; dont copy entire block, only what we need
|
||||||
|
add esi, [.BLOCK_OFFSET]
|
||||||
|
sub ecx, [.BLOCK_OFFSET]
|
||||||
|
.not_start:
|
||||||
|
|
||||||
|
.copy:
|
||||||
|
; ensure byte count < remaining
|
||||||
|
cmp ecx, [.BYTES_REMAINING]
|
||||||
|
jbe .nomin
|
||||||
|
mov ecx, [.BYTES_REMAINING]
|
||||||
|
.nomin:
|
||||||
|
sub [.BYTES_REMAINING], ecx
|
||||||
|
rep movsb
|
||||||
|
|
||||||
|
inc eax
|
||||||
|
cmp eax, edx
|
||||||
|
jbe .lup
|
||||||
|
|
||||||
|
popad
|
||||||
|
ret
|
||||||
|
.BLOCK_OFFSET dd 0
|
||||||
|
.BYTES_REMAINING dd 0
|
||||||
|
|
||||||
|
; in esi = ptr to inode structure
|
||||||
|
; in eax = block number
|
||||||
|
; in es:edi = pointer to destination
|
||||||
|
ext2_read_inode_block:
|
||||||
|
pushad
|
||||||
|
|
||||||
|
cmp eax, 12
|
||||||
|
jae .skip
|
||||||
|
mov eax, [esi + 40 + eax * 4]
|
||||||
|
shl eax, 10
|
||||||
|
mov ecx, 1024
|
||||||
|
call read_absolute_bytes
|
||||||
|
.skip:
|
||||||
|
|
||||||
|
popad
|
||||||
|
ret
|
||||||
|
|
||||||
|
; in eax = inode number
|
||||||
|
; in es:edi = pointer to destination
|
||||||
|
ext2_get_inode_data:
|
||||||
|
pushad
|
||||||
|
mov edx, 0
|
||||||
|
dec eax
|
||||||
|
div dword [INODES_PER_GROUP]
|
||||||
|
; edx is now inode index in group
|
||||||
|
; eax is now block group index
|
||||||
|
call ext2_get_inode_table_index_from_block_group_index
|
||||||
|
; eax is now inode table block index
|
||||||
|
shl eax, 10
|
||||||
|
imul edx, dword [INODE_SIZE]
|
||||||
|
; edx is now inode offset within block group (bytes)
|
||||||
|
add eax, edx
|
||||||
|
mov ecx, [INODE_SIZE]
|
||||||
|
call read_absolute_bytes
|
||||||
|
popad
|
||||||
|
ret
|
||||||
|
|
||||||
|
ext2_get_inode_table_index_from_block_group_index:
|
||||||
|
push eax
|
||||||
|
mov eax, 4
|
||||||
|
call read_lba
|
||||||
|
pop eax
|
||||||
|
shl eax, 5 ;*32
|
||||||
|
mov eax, [READ_LBA_RESULT + eax + 8]
|
||||||
|
ret
|
||||||
|
|
||||||
|
ext2_test:
|
||||||
|
push eax
|
||||||
|
mov eax, 2
|
||||||
|
call read_lba
|
||||||
|
cmp [READ_LBA_RESULT + 56], word 0xEF53 ; ext2 signature
|
||||||
|
jne .fail
|
||||||
|
cmp [READ_LBA_RESULT + 24], word 0x0000 ; 1024 bytes per block
|
||||||
|
jne .fail
|
||||||
|
.signature_pass:
|
||||||
|
mov eax, [READ_LBA_RESULT + 40]
|
||||||
|
mov [INODES_PER_GROUP], eax
|
||||||
|
movzx eax, word [READ_LBA_RESULT + 88]
|
||||||
|
mov [INODE_SIZE], eax
|
||||||
|
pop eax
|
||||||
|
clc
|
||||||
|
ret
|
||||||
|
.fail:
|
||||||
|
pop eax
|
||||||
|
stc
|
||||||
|
ret
|
||||||
|
|
||||||
|
; in eax = starting byte
|
||||||
|
; in ecx = number of bytes to read
|
||||||
|
; in es:edi = pointer to destination
|
||||||
|
read_absolute_bytes:
|
||||||
|
pushad
|
||||||
|
|
||||||
|
cmp ecx, 0
|
||||||
|
jne .not_empty
|
||||||
|
; nothing to copy
|
||||||
|
ret
|
||||||
|
.not_empty:
|
||||||
|
|
||||||
|
push eax
|
||||||
|
and eax, 511
|
||||||
|
mov [.BLOCK_OFFSET], eax
|
||||||
|
pop eax
|
||||||
|
mov [.BYTES_REMAINING], ecx
|
||||||
|
|
||||||
|
lea edx, [eax + ecx - 1]
|
||||||
|
shr edx, 9
|
||||||
|
shr eax, 9
|
||||||
|
|
||||||
|
mov ebp, eax
|
||||||
|
|
||||||
|
; ebp = start sector
|
||||||
|
; eax = counter
|
||||||
|
; edx = end sector (inclusive)
|
||||||
|
.lup:
|
||||||
|
;call print_dword_hex
|
||||||
|
call read_lba
|
||||||
|
|
||||||
|
mov esi, READ_LBA_RESULT
|
||||||
|
mov ecx, 512
|
||||||
|
|
||||||
|
cmp eax, ebp
|
||||||
|
jne .not_start
|
||||||
|
; dont copy entire sector, only what we need
|
||||||
|
add esi, [.BLOCK_OFFSET]
|
||||||
|
sub ecx, [.BLOCK_OFFSET]
|
||||||
|
.not_start:
|
||||||
|
|
||||||
|
.copy:
|
||||||
|
; ensure byte count < remaining
|
||||||
|
cmp ecx, [.BYTES_REMAINING]
|
||||||
|
jbe .nomin
|
||||||
|
mov ecx, [.BYTES_REMAINING]
|
||||||
|
.nomin:
|
||||||
|
sub [.BYTES_REMAINING], ecx
|
||||||
|
rep movsb
|
||||||
|
|
||||||
|
inc eax
|
||||||
|
cmp eax, edx
|
||||||
|
jbe .lup
|
||||||
|
|
||||||
|
popad
|
||||||
|
ret
|
||||||
|
.BLOCK_OFFSET dd 0
|
||||||
|
.BYTES_REMAINING dd 0
|
||||||
|
|
||||||
|
; in eax = lba number
|
||||||
|
; out carry = error
|
||||||
|
read_lba:
|
||||||
|
push eax
|
||||||
|
push esi
|
||||||
|
push edx
|
||||||
|
add eax, dword [PARTITION_START]
|
||||||
|
.int:
|
||||||
|
mov [DAPACK.blkcnt], word 1
|
||||||
|
mov [DAPACK.d_lba], dword eax
|
||||||
|
mov si, DAPACK
|
||||||
|
mov ah, 0x42
|
||||||
|
mov dl, 0x80
|
||||||
|
int 0x13
|
||||||
|
cld
|
||||||
|
pop edx
|
||||||
|
pop esi
|
||||||
|
pop eax
|
||||||
|
ret
|
||||||
|
|
||||||
|
; in eax = lba number
|
||||||
|
; out carry = error
|
||||||
|
read_absolute_lba:
|
||||||
|
push eax
|
||||||
|
push esi
|
||||||
|
push edx
|
||||||
|
jmp read_lba.int
|
||||||
3
src/kernel/log.h
Normal file
3
src/kernel/log.h
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
void print(const char *fmt, ...);
|
||||||
17
src/kernel/main.c
Normal file
17
src/kernel/main.c
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
#include"log.h"
|
||||||
|
|
||||||
|
#include<stdint.h>
|
||||||
|
|
||||||
|
void k_init() {
|
||||||
|
uint8_t *ptr = (void*) 0xB8000;
|
||||||
|
ptr[0] = 'Y';
|
||||||
|
ptr[2] = 'o';
|
||||||
|
ptr[4] = ',';
|
||||||
|
ptr[6] = ' ';
|
||||||
|
ptr[8] = 'b';
|
||||||
|
ptr[10] = 'i';
|
||||||
|
ptr[12] = 't';
|
||||||
|
ptr[14] = 'c';
|
||||||
|
ptr[16] = 'h';
|
||||||
|
ptr[18] = '.';
|
||||||
|
}
|
||||||
18
src/kernel/ppm.h
Normal file
18
src/kernel/ppm.h
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include<stddef.h>
|
||||||
|
#include<stdbool.h>
|
||||||
|
#include<stdint.h>
|
||||||
|
|
||||||
|
typedef struct __attribute__((packed)) {
|
||||||
|
uint64_t start_ptr;
|
||||||
|
uint64_t page_count;
|
||||||
|
uint8_t bitmap[];
|
||||||
|
} PPMBitmap;
|
||||||
|
|
||||||
|
extern PPMBitmap *ppm_Bitmap;
|
||||||
|
|
||||||
|
size_t ppm_alloc(size_t page_count);
|
||||||
|
bool ppm_free(size_t start_ptr, size_t page_count);
|
||||||
|
|
||||||
|
size_t ppm_page_size();
|
||||||
180
src/kernel/tinyubsan.c
Normal file
180
src/kernel/tinyubsan.c
Normal file
@@ -0,0 +1,180 @@
|
|||||||
|
#include<stdint.h>
|
||||||
|
|
||||||
|
struct tu_source_location
|
||||||
|
{
|
||||||
|
const char *file;
|
||||||
|
uint32_t line;
|
||||||
|
uint32_t column;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct tu_type_descriptor
|
||||||
|
{
|
||||||
|
uint16_t kind;
|
||||||
|
uint16_t info;
|
||||||
|
char name[];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct tu_overflow_data
|
||||||
|
{
|
||||||
|
struct tu_source_location location;
|
||||||
|
struct tu_type_descriptor *type;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct tu_shift_out_of_bounds_data
|
||||||
|
{
|
||||||
|
struct tu_source_location location;
|
||||||
|
struct tu_type_descriptor *left_type;
|
||||||
|
struct tu_type_descriptor *right_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct tu_invalid_value_data
|
||||||
|
{
|
||||||
|
struct tu_source_location location;
|
||||||
|
struct tu_type_descriptor *type;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct tu_array_out_of_bounds_data
|
||||||
|
{
|
||||||
|
struct tu_source_location location;
|
||||||
|
struct tu_type_descriptor *array_type;
|
||||||
|
struct tu_type_descriptor *index_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct tu_type_mismatch_v1_data
|
||||||
|
{
|
||||||
|
struct tu_source_location location;
|
||||||
|
struct tu_type_descriptor *type;
|
||||||
|
unsigned char log_alignment;
|
||||||
|
unsigned char type_check_kind;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct tu_negative_vla_data
|
||||||
|
{
|
||||||
|
struct tu_source_location location;
|
||||||
|
struct tu_type_descriptor *type;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct tu_nonnull_return_data
|
||||||
|
{
|
||||||
|
struct tu_source_location location;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct tu_nonnull_arg_data
|
||||||
|
{
|
||||||
|
struct tu_source_location location;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct tu_unreachable_data
|
||||||
|
{
|
||||||
|
struct tu_source_location location;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct tu_invalid_builtin_data
|
||||||
|
{
|
||||||
|
struct tu_source_location location;
|
||||||
|
unsigned char kind;
|
||||||
|
};
|
||||||
|
|
||||||
|
void print(const char *fmt, ...);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
static void tu_print_location(const char *message, struct tu_source_location loc)
|
||||||
|
{
|
||||||
|
print("tinyubsan: %s at file %s, line %d, column %d\n", message, loc.file, loc.line, loc.column);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __ubsan_handle_add_overflow(struct tu_overflow_data *data)
|
||||||
|
{
|
||||||
|
tu_print_location("addition overflow", data->location);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __ubsan_handle_sub_overflow(struct tu_overflow_data *data)
|
||||||
|
{
|
||||||
|
tu_print_location("subtraction overflow", data->location);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __ubsan_handle_mul_overflow(struct tu_overflow_data *data)
|
||||||
|
{
|
||||||
|
tu_print_location("multiplication overflow", data->location);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __ubsan_handle_divrem_overflow(struct tu_overflow_data *data)
|
||||||
|
{
|
||||||
|
tu_print_location("division overflow", data->location);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __ubsan_handle_negate_overflow(struct tu_overflow_data *data)
|
||||||
|
{
|
||||||
|
tu_print_location("negation overflow", data->location);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __ubsan_handle_pointer_overflow(struct tu_overflow_data *data)
|
||||||
|
{
|
||||||
|
tu_print_location("pointer overflow", data->location);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __ubsan_handle_shift_out_of_bounds(struct tu_shift_out_of_bounds_data *data, void *lhs, void *rhs)
|
||||||
|
{
|
||||||
|
tu_print_location("shift out of bounds", data->location);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __ubsan_handle_load_invalid_value(struct tu_invalid_value_data *data)
|
||||||
|
{
|
||||||
|
tu_print_location("invalid load value", data->location);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __ubsan_handle_out_of_bounds(struct tu_array_out_of_bounds_data *data)
|
||||||
|
{
|
||||||
|
tu_print_location("array out of bounds", data->location);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __ubsan_handle_type_mismatch_v1(struct tu_type_mismatch_v1_data *data, uintptr_t ptr)
|
||||||
|
{
|
||||||
|
if (!ptr)
|
||||||
|
{
|
||||||
|
tu_print_location("use of NULL pointer", data->location);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (ptr & ((1 << data->log_alignment) - 1))
|
||||||
|
{
|
||||||
|
tu_print_location("use of misaligned pointer", data->location);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tu_print_location("no space for object", data->location);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void __ubsan_handle_vla_bound_not_positive(struct tu_negative_vla_data *data)
|
||||||
|
{
|
||||||
|
tu_print_location("variable-length argument is negative", data->location);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __ubsan_handle_nonnull_return(struct tu_nonnull_return_data *data)
|
||||||
|
{
|
||||||
|
tu_print_location("non-null return is null", data->location);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __ubsan_handle_nonnull_arg(struct tu_nonnull_arg_data *data)
|
||||||
|
{
|
||||||
|
tu_print_location("non-null argument is null", data->location);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __ubsan_handle_builtin_unreachable(struct tu_unreachable_data *data)
|
||||||
|
{
|
||||||
|
|
||||||
|
tu_print_location("unreachable code reached", data->location);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __ubsan_handle_invalid_builtin(struct tu_invalid_builtin_data *data)
|
||||||
|
{
|
||||||
|
|
||||||
|
tu_print_location("invalid builtin", data->location);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
8
src/kernel/vpm.h
Normal file
8
src/kernel/vpm.h
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include<stddef.h>
|
||||||
|
#include<stdint.h>
|
||||||
|
#include<stdbool.h>
|
||||||
|
|
||||||
|
uintptr_t vpm_map(uintptr_t cr3, bool kernel, uintptr_t virt, uintptr_t phys, size_t len_bytes);
|
||||||
|
void vpm_unmap(uintptr_t cr3, uintptr_t virt, size_t len_bytes);
|
||||||
51
src/kernel/x86/log.c
Normal file
51
src/kernel/x86/log.c
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
#include<log.h>
|
||||||
|
|
||||||
|
#include<stdarg.h>
|
||||||
|
#include<stddef.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char buf[256];
|
||||||
|
size_t i;
|
||||||
|
} Ctx;
|
||||||
|
|
||||||
|
static void add_char(Ctx *ctx, char c) {
|
||||||
|
if(ctx->i < sizeof(ctx->buf)) {
|
||||||
|
ctx->buf[ctx->i++] = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void print(const char *fmt, ...) {
|
||||||
|
Ctx ctx = {};
|
||||||
|
|
||||||
|
va_list args;
|
||||||
|
va_start(args, fmt);
|
||||||
|
|
||||||
|
while(*fmt) {
|
||||||
|
if(*fmt == '%') {
|
||||||
|
fmt++;
|
||||||
|
|
||||||
|
if(*fmt == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(*fmt == 's') {
|
||||||
|
fmt++;
|
||||||
|
|
||||||
|
const char *src = va_arg(args, const char*);
|
||||||
|
while(*src) {
|
||||||
|
add_char(&ctx, *src);
|
||||||
|
src++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fmt++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
add_char(&ctx, *fmt);
|
||||||
|
fmt++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(size_t i = 0; i < ctx.i; i++) {
|
||||||
|
asm volatile("outb %%al, $0xE9" :: "a"(ctx.buf[i]):);
|
||||||
|
}
|
||||||
|
}
|
||||||
93
src/kernel/x86/ppm.c
Normal file
93
src/kernel/x86/ppm.c
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
#include<ppm.h>
|
||||||
|
|
||||||
|
PPMBitmap *ppm_Bitmap;
|
||||||
|
|
||||||
|
static bool ppmbitmap_page_free(PPMBitmap *bm, size_t pg_idx) {
|
||||||
|
size_t byte_idx = pg_idx / 8;
|
||||||
|
int bit_idx = pg_idx % 8;
|
||||||
|
return (byte_idx >> bit_idx) & 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool ppm_find_free_range(size_t page_count, PPMBitmap **ret_bm, size_t *ret_pg_i) {
|
||||||
|
if(page_count == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
PPMBitmap *bm = ppm_Bitmap;
|
||||||
|
while(bm->page_count) {
|
||||||
|
size_t byte_count = (bm->page_count + 7) / 8;
|
||||||
|
|
||||||
|
size_t run = 0;
|
||||||
|
for(size_t i = 0; i < bm->page_count; i++) {
|
||||||
|
if(ppmbitmap_page_free(bm, i)) {
|
||||||
|
run++;
|
||||||
|
if(run == page_count) {
|
||||||
|
*ret_bm = bm;
|
||||||
|
*ret_pg_i = i - run + 1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
run = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bm = (void*) ((uintptr_t) bm + sizeof(*bm) + byte_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t ppm_alloc(size_t page_count) {
|
||||||
|
PPMBitmap *bm;
|
||||||
|
size_t pg_start;
|
||||||
|
if(!ppm_find_free_range(page_count, &bm, &pg_start)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(size_t pg = pg_start; pg < pg_start + page_count; pg++) {
|
||||||
|
size_t byte_idx = pg / 8;
|
||||||
|
int bit_idx = pg % 8;
|
||||||
|
bm->bitmap[byte_idx] |= (1 << bit_idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
return bm->start_ptr + pg_start * ppm_page_size();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ppm_free(size_t start_ptr, size_t page_count) {
|
||||||
|
if(start_ptr % ppm_page_size() != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t end_ptr = start_ptr + page_count * ppm_page_size();
|
||||||
|
|
||||||
|
PPMBitmap *bm = ppm_Bitmap;
|
||||||
|
while(bm->page_count) {
|
||||||
|
if(
|
||||||
|
(bm->start_ptr <= start_ptr && start_ptr < bm->start_ptr + bm->page_count * ppm_page_size())
|
||||||
|
&& (bm->start_ptr <= end_ptr && end_ptr < bm->start_ptr + bm->page_count * ppm_page_size())
|
||||||
|
) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
bm = (void*) ((uintptr_t) bm + sizeof(*bm) + (bm->page_count + 7) / 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(bm->page_count == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t start_pg = (start_ptr - bm->start_ptr) / ppm_page_size();
|
||||||
|
|
||||||
|
for(size_t pg = 0; pg < page_count; pg++) {
|
||||||
|
size_t byte_idx = (pg + start_pg) / 8;
|
||||||
|
int bit_idx = (pg + start_pg) % 8;
|
||||||
|
|
||||||
|
bm->bitmap[byte_idx] &= ~(1 << bit_idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t ppm_page_size() {
|
||||||
|
return 4096;
|
||||||
|
}
|
||||||
23
src/kernel/x86/vpm.c
Normal file
23
src/kernel/x86/vpm.c
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
#include"vpm.h"
|
||||||
|
|
||||||
|
static void invlpg(uintptr_t ptr) {
|
||||||
|
// if(INVLPG_SUPPORTED) {
|
||||||
|
asm volatile("invlpg %0" : : "m"(*(char*) ptr) : "memory");
|
||||||
|
// } else {
|
||||||
|
// print("Attempt to invlpg on 386\n");
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *move_4k_window(uintptr_t ptr) {
|
||||||
|
*(volatile uint32_t*) 0xFFFFFFF8 = ptr | 3;
|
||||||
|
invlpg(0xFFFFE000);
|
||||||
|
return (void*) 0xFFFFE000;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*uintptr_t vpm_map(uintptr_t cr3, bool kernel, uintptr_t virt, uintptr_t phys, size_t len_bytes) {
|
||||||
|
move_window(cr3);
|
||||||
|
}
|
||||||
|
|
||||||
|
void vpm_unmap(uintptr_t cr3, uintptr_t virt, size_t len_bytes) {
|
||||||
|
|
||||||
|
}*/
|
||||||
Reference in New Issue
Block a user