aboutsummaryrefslogtreecommitdiff
path: root/src/bootloader/loader.asm
diff options
context:
space:
mode:
Diffstat (limited to 'src/bootloader/loader.asm')
-rw-r--r--src/bootloader/loader.asm444
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