diff options
Diffstat (limited to 'src/bootloader/hdd2.asm')
-rw-r--r-- | src/bootloader/hdd2.asm | 388 |
1 files changed, 388 insertions, 0 deletions
diff --git a/src/bootloader/hdd2.asm b/src/bootloader/hdd2.asm new file mode 100644 index 0000000..e289c39 --- /dev/null +++ b/src/bootloader/hdd2.asm @@ -0,0 +1,388 @@ +BITS 16 +ORG 0x8000 + +%define SECTOR_BUFFER 0x9000 +%define INODE_NBLOCKS 20 +%define INODE_DBP0 24 +%define INODE_SIBP 64 +%define INODE_DIBP 68 +%define INODE_TIBP 72 +%define INODE_QIBP 76 + +mov esp, 0xFFFF +jmp start + +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 + +last_maxlevel db 0 +getrecursive: + push edi + push esi + push ecx + + mov eax, edi + cmp al, byte [last_maxlevel] + jna .last_maxlevel_updated + mov byte [last_maxlevel], al + .last_maxlevel_updated: + + mov eax, esi + call 0x7c26 + + mov eax, dword [esp] + sub eax, 10 + + cmp byte [last_maxlevel], 1 + jna .check1 + mov ebx, 1 + shl ebx, 7 + sub eax, ebx + .check1: + cmp byte [last_maxlevel], 2 + jna .check2 + mov ebx, 1 + shl ebx, 14 + sub eax, ebx + .check2: + cmp byte [last_maxlevel], 3 + jna .check3 + mov ebx, 1 + shl ebx, 21 + sub eax, ebx + .check3: + mov ecx, dword [esp+8] + dec ecx + push ecx + shl ecx, 3 + sub ecx, dword [esp] + add esp, 4 + shr eax, cl + + mov eax, dword [SECTOR_BUFFER+(4*eax)] + + cmp dword [esp+8], 1 + jna .finish_recursion + mov edi, [esp+8] + dec edi + mov esi, eax + mov ecx, [esp] + call getrecursive + .finish_recursion: + mov byte [last_maxlevel], 0 + + pop ecx + pop esi + pop edi + ret + +get_block: + push ecx + push ebx + + xor ebx, ebx + inc ebx + shl ebx, 21 + add ebx, 9 + cmp ecx, ebx + jna .gtb1 + + mov edi, 4 + mov esi, dword [SECTOR_BUFFER+INODE_QIBP] + call getrecursive + jmp .get_block_end + + .gtb1: + xor ebx, ebx + inc ebx + shl ebx, 14 + add ebx, 9 + cmp ecx, ebx + jna .gtb2 + + mov edi, 3 + mov esi, dword [SECTOR_BUFFER+INODE_TIBP] + call getrecursive + jmp .get_block_end + + .gtb2: + xor ebx, ebx + inc ebx + shl ebx, 7 + add ebx, 9 + cmp ecx, ebx + jna .gtb3 + + mov edi, 2 + mov esi, dword [SECTOR_BUFFER+INODE_DIBP] + call getrecursive + jmp .get_block_end + + .gtb3: + cmp ecx, 9 + jna .gtb4 + + mov edi, 1 + mov esi, dword [SECTOR_BUFFER+INODE_SIBP] + call getrecursive + jmp .get_block_end + + .gtb4: + mov eax, SECTOR_BUFFER+INODE_DBP0 + mov eax, dword [eax+(4*ecx)] + + .get_block_end: + pop ebx + pop ecx + ret + +noa20 db "A20 could not be enabled.", 0 +loading db "Loading kernel...", 0x0A, 0x0D, 0x00 +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: + 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 0x7c07 + 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 0x7c07 + + mov word [0x7c1a], SECTOR_BUFFER + + mov eax, 3 + call 0x7c26 + mov edx, dword [SECTOR_BUFFER + INODE_NBLOCKS] + + xor ecx, ecx +LOAD_KERNEL: + push edx + + mov eax, 3 + call 0x7c26 + call get_block + call 0x7c26 + + mov eax, ecx + shl eax, 9 + add eax, 0x200000 + + push ecx + xor ecx, ecx + .LOAD_KERNEL_L: + mov ebx, ecx + add ebx, SECTOR_BUFFER + 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 + pop edx + cmp ecx, edx + jl LOAD_KERNEL + +mov si, booting +call 0x7c07 + +mov dl, [0x7c15] +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 0x7c07 + jmp $ +BIOS_MEM_NO20: + mov si, memno20 + call 0x7c07 + 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: + +kernelbin db "KERNEL.BIN", 0x3B, "1" +kernelbin_len equ ($ - kernelbin) |