Initial commit
This commit is contained in:
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
|
||||
Reference in New Issue
Block a user