diff options
author | Marvin Borner | 2019-11-10 19:50:14 +0100 |
---|---|---|
committer | Marvin Borner | 2019-11-10 19:50:14 +0100 |
commit | 7e06dfe06a0f7847eed105bc4f7ccb22df5228fc (patch) | |
tree | 446f7eeeb998b93da221d6bf14adca9df63dba69 /src/bootloader/loader.asm | |
parent | a30a9b21c3e0af7996a551381a8f41075bada7ad (diff) |
Added semi-working bootloader
Diffstat (limited to 'src/bootloader/loader.asm')
-rw-r--r-- | src/bootloader/loader.asm | 444 |
1 files changed, 444 insertions, 0 deletions
diff --git a/src/bootloader/loader.asm b/src/bootloader/loader.asm new file mode 100644 index 0000000..28e4562 --- /dev/null +++ b/src/bootloader/loader.asm @@ -0,0 +1,444 @@ +BITS 16 +ORG 0x7C00 + +; Save the boot drive id +mov [bootDriveID], dl + +jmp start + +; The print function +print: + mov ah, 0x0E + xor bh, bh + .print_L: + lodsb + test al, al + jz .print_end + int 0x10 + jmp .print_L + .print_end: + ret + +bootDriveID: db 0 + +dapack: + dapack_size: db 0x10 + dapack_null: db 0x00 + dapack_blkcount: dw 0x0001 + dapack_boffset: dw 0x9000 + dapack_bsegment: dw 0x0000 + dapack_start: dd 0x00000000 + dapack_upper_lba_bits: dd 0x00000000 + +readsector: + mov dword [dapack_start], eax + mov ah, 0x42 + mov dl, [bootDriveID] + xor bx, bx + mov ds, bx + mov si, dapack + int 0x13 + ret + +filenameLength dw 1 +filename dw 1 + +findfile: + mov bx, [esp+2] + mov ax, [esp+4] + mov [filenameLength], ax + mov ax, [esp+6] + mov [filename], ax + + .findfile_L: + mov al, [bx] + + test al, al + jz .findfile_notfound + + mov ah, [bx+32] + cmp ah, byte [filenameLength] + jnz .findfile_keep + + call findfile_check + test ax, ax + jz findfile_found + + .findfile_keep: + mov al, [bx] + xor ah, ah + add bx, ax + jmp .findfile_L + + .findfile_notfound: + xor ax, ax + inc ax + ret + + findfile_check: + pusha + add bx, 33 + mov ax, bx + + xor cx, cx + .findfile_check_L: + mov bx, [filename] + add bx, cx + mov dh, [bx] + mov bx, ax + add bx, cx + mov dl, [bx] + cmp dh, dl + jnz .findfile_check_fail + + inc cx + cmp cx, word [filenameLength] + jz .findfile_check_success + jmp .findfile_check_L + + .findfile_check_fail: + popa + xor ax, ax + inc ax + ret + .findfile_check_success: + popa + xor ax, ax + ret + + findfile_found: + xor ax, ax + ret + +LOAD_PVD: + mov eax, 0x10 + PVD_L: + call readsector + mov bx, [dapack_boffset] + mov bl, [bx] + cmp bl, 0x01 + jz PVD_FOUND + inc eax + jmp PVD_L + PVD_FOUND: + ret + +checkA20: + ; Stolen from https://wiki.osdev.org/A20_Line + pushf + push ds + push es + push di + push si + cli + xor ax, ax + mov es, ax + not ax + mov ds, ax + mov di, 0x0500 + mov si, 0x0510 + mov al, byte [es:di] + push ax + mov al, byte [ds:si] + push ax + mov byte [es:di], 0x00 + mov byte [ds:si], 0xFF + cmp byte [es:di], 0xFF + pop ax + mov byte [ds:si], al + pop ax + mov byte [es:di], al + mov ax, 0 + jz checkA20_exit + mov ax, 1 + checkA20_exit: + pop si + pop di + pop es + pop ds + popf + ret + +welcome db "Melvix", 0x0A, 0x0D, 0x00 +nolba db "BIOS lacks support for LBA addressing.", 0x00 +noboot db "Boot directory could not be found.", 0x00 +noa20 db "A20 could not be enabled.", 0 +loading db "Loading kernel...", 0x0A, 0x0D, 0x00 +nokernel db "kernel.bin could not be found!", 0 +booting db "Booting...", 0x0A, 0x0D, 0x00 +nomem db "BIOS does not support memory detection!", 0 +memno20 db "BIOS returns memory detection with 24 bytes. This has never been seen!", 0 + +start: + ; Check if LBA is supported by the BIOS. + mov ah, 0x41 + mov bx, 0x55AA + int 0x13 + jc lba_not_supported + cmp bx, 0xAA55 + jnz lba_not_supported + + call checkA20 + test ax, ax + jnz A20_ENABLED + + in al, 0x92 + or al, 2 + out 0x92, al + + call checkA20 + test ax, ax + jnz A20_ENABLED + + mov si, noa20 + call print + jmp $ + +A20_ENABLED: + ; Inspired by https://wiki.osdev.org/Unreal_Mode + cli + push ds + lgdt [gdtinfo] + + mov eax, cr0 + or al, 1 + mov cr0, eax + + jmp $+2 + + mov bx, 0x08 + mov ds, bx + + and al, 0xFE + mov cr0, eax + pop ds + + mov si, loading + call print + + call LOAD_PVD + + mov bx, 0x9000 + add bx, 156 + add bx, 2 + mov eax, dword [bx] + call readsector + + push boot + push boot_len + push 0x9000 + call findfile + add esp, 6 + test ax, ax + jz continue_BOOT + + mov si, noboot + call print + jmp $ + +continue_BOOT: + mov word [dapack_blkcount], 0x0001 + add bx, 2 + mov eax, [bx] + call readsector + + push kernelbin + push kernelbin_len + push 0x9000 + call findfile + add esp, 6 + test ax, ax + jz continue_KERNEL + + mov si, nokernel + call print + jmp $ + +continue_KERNEL: + mov word [dapack_blkcount], 1 + mov word [dapack_boffset], 0x9000 + + push bx + add bx, 10 + mov eax, [bx] + xor edx, edx + mov ebx, 2048 + div ebx + inc eax + pop bx + push eax + + add bx, 2 + mov eax, [bx] + push eax + + ; Offsetless count. + xor ecx, ecx +LOAD_KERNEL: + mov eax, [esp] + add eax, ecx + call readsector + + mov eax, ecx + shl eax, 11 + add eax, 0x200000 + + push ecx + xor ecx, ecx + .LOAD_KERNEL_L: + mov ebx, ecx + add ebx, 0x9000 + mov ebx, dword [ebx] + + mov edx, ebx + mov ebx, eax + add ebx, ecx + mov dword [ebx], edx + + add ecx, 4 + cmp ecx, 2048 + jl .LOAD_KERNEL_L + pop ecx + + inc ecx + cmp ecx, dword [esp+4] + jl LOAD_KERNEL + +mov si, booting +call print + +mov dl, [bootDriveID] +mov byte [0x9000], dl + +mov di, 0xA000 +mov eax, 0xE820 +xor ebx, ebx +mov ecx, 24 +mov edx, 0x534D4150 +int 0x15 + +jc BIOS_NO_MEM +cmp eax, 0x534D4150 +jnz BIOS_NO_MEM +cmp cl, 20 +jnz BIOS_MEM_NO20 + +MEM_L: + test ebx, ebx + jz MEM_FINISHED + + mov ax, di + xor ch, ch + add ax, cx + mov di, ax + + mov eax, 0xE820 + mov ecx, 24 + int 0x15 + jmp MEM_L + +MEM_FINISHED: + mov eax, cr0 + or al, 1 + mov cr0, eax + + mov ax, 0x08 + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + mov ss, ax + +; Infomation: https://wiki.osdev.org/ELF +mov ebx, 0x20002C +mov dl, byte [ebx] +push dx + +mov ebx, 0x20001C +mov ebx, dword [ebx] +push ebx + +xor dh, dh +PHT: + xor eax, eax + mov al, dh + shl eax, 5 + add eax, dword [esp] + add eax, 0x200000 + mov ebx, eax + + mov eax, dword [ebx] + cmp eax, 1 + jnz .PHT_ignore + + add ebx, 4 + mov eax, dword [ebx] + add eax, 0x200000 + push eax + + add ebx, 4 + mov eax, dword [ebx] + push eax + + add ebx, 8 + mov eax, dword [ebx] + push eax + + push dx + xor ecx, ecx + .MOVE_KERNEL_L: + mov ebx, [esp+10] + add ebx, ecx + mov ebx, dword [ebx] + + mov eax, ebx + mov ebx, dword [esp+6] + add ebx, ecx + mov dword [ebx], eax + + add ecx, 4 + cmp ecx, dword [esp+2] + jl .MOVE_KERNEL_L + pop dx + add esp, 12 + + .PHT_ignore: + inc dh + cmp dh, dl + jl PHT + +jmp (codedesc - gdt):protectedMode + +protectedMode: + BITS 32 + mov ebx, 0x100000 + mov eax, dword [ebx] + jmp eax + +BITS 16 +BIOS_NO_MEM: + mov si, nomem + call print + jmp $ +BIOS_MEM_NO20: + mov si, memno20 + call print + jmp $ + +gdtinfo: + dw gdt_end - gdt - 1 + dd gdt + gdt dd 0, 0 + flatdesc db 0xff, 0xff, 0, 0, 0, 10010010b, 11001111b, 0 + codedesc db 0xff, 0xff, 0, 0, 0, 10011010b, 11001111b, 0 + gdt_end: + +lba_not_supported: + mov si, nolba + call print + jmp $ + +boot db "BOOT" +boot_len equ ($ - boot) +kernelbin db "KERNEL.BIN", 0x3B, "1" +kernelbin_len equ ($ - kernelbin)
\ No newline at end of file |