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