From bc3165eeb80ab1b27d93e742d00c7237d68a6a7e Mon Sep 17 00:00:00 2001 From: Robbe Van Herck Date: Mon, 30 Dec 2019 13:59:02 +0100 Subject: [PATCH] Succesful ELF kernel boot! --- bootloader/main.asm | 86 +++++++++++++++++++++++++++++++++++++++------ 1 file changed, 75 insertions(+), 11 deletions(-) diff --git a/bootloader/main.asm b/bootloader/main.asm index 9931204..c369f98 100644 --- a/bootloader/main.asm +++ b/bootloader/main.asm @@ -1,12 +1,12 @@ DISK_ID EQU 0x81 +KERNEL_START EQU 0x100000 + +ELF_START EQU 0x8000 + org 0x7C00 bits 16 -; memory layout: -; 0x8000 -> ... = ELF file, unparsed -; 0x100000 -> ... = actual kernel - jmp .start [bits 16] @@ -154,7 +154,7 @@ call puthex .reset_disk_no_error: mov cx, 1 ; start at sector 1 -mov bx, 0x8000 ; write to 0x8000 +mov bx, ELF_START ; write to ELF_START push bx push cx .read_disk_loop: @@ -223,16 +223,80 @@ mov ss, ax ; set up stack mov esp, 0x090000 -; parse ELF file to 0x10000 +; parse elf file at ELF_START to KERNEL_START -; load memory position from ELF file -mov eax, [ds:0x8018] +; verify ELF header +mov esi, ELF_START +cmp dword [esi], 464C457Fh ; ELF magic +jne .invalid_elf +cmp word [esi+4], 0101h ; lsb 32 bit, little endian +jne .invalid_elf +cmp word [esi+18], 03 ; x86 architecture +jne .invalid_elf -jmp eax +; read the entrypoint and store it +mov eax, dword [esi+0x18] ; program entry position +mov dword [.entrypoint], eax + +mov cx, word [esi+0x2C] ; read phnum (number of program headers) +mov eax, dword [esi+0x1C] ; read phoff (offset of program header) + +; ebx is now ELF_START, esi jumps to the start of the program header +mov ebx, esi +add esi, eax + +; set up for loop +sub esi, 0x20 +inc cx + +.elf_ph_loop: +add esi, 0x20 +dec cx +jz .invalid_elf ; there is no valid code block +cmp word [esi], 1 ; check if p_type is loadable +jne .elf_ph_loop + +; add offset to ebx (ebx = pointer to code) +add ebx, dword [esi+0x04] + +; store p_filesz (ecx = size of the segment) +mov ecx, dword [esi+0x10] + +; calculate size of bss (edx = size of bss) +mov edx, dword [esi+0x14] +sub edx, ecx + +; check if ecx is zero +or ecx, ecx +jz .invalid_elf + +; set source +mov esi, ebx + +; set destination +mov edi, KERNEL_START + +; repeat ecx/4 times (because it moves 4 bytes at a time) +shr ecx, 2 + +; copy +repnz movsd + +; jump to start of kernel +jmp [.entrypoint] .end: jmp .end +.invalid_elf: +mov byte [ds:0x0B8000], 'E' +mov byte [ds:0x0B8001], 0x40 +mov byte [ds:0x0B8002], 'L' +mov byte [ds:0x0B8003], 0x40 +mov byte [ds:0x0B8004], 'F' +mov byte [ds:0x0B8005], 0x40 +jmp .end + .data: .str_no_A20: db "A20 not enabled" @@ -258,12 +322,12 @@ db 11001111b db 0 .gdt_end: - - .gdt_desc: dw .gdt_end - .gdt - 1 dd .gdt +.entrypoint: dd 0 + ; print padding nullbytes times 510 - ($ - $$) db 0