280 lines
4.6 KiB
NASM
280 lines
4.6 KiB
NASM
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
|