diff options
Diffstat (limited to 'src/bootloader.asm')
-rw-r--r-- | src/bootloader.asm | 464 |
1 files changed, 187 insertions, 277 deletions
diff --git a/src/bootloader.asm b/src/bootloader.asm index 583c169..f18750c 100644 --- a/src/bootloader.asm +++ b/src/bootloader.asm @@ -15,275 +15,245 @@ ;TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE ;USE OR PERFORMANCE OF THIS SOFTWARE. -pointers: -.fat equ 0x0500 -.root_dir equ 0x0504 -.kernel equ 0x0508 - -fat_header: -.oem_name equ 0x7c03;mkfs.fat - ignored -.bytes_per_sector equ 0x7c0b;0x0200 - assumed -.sectors_per_cluster equ 0x7c0d;0x01 - assumed +kload equ 0x0010_0000 + +global_info:;0x0500 - 0x05ff (0x0515) +.fat equ 0x0500;dword - pointer +.root_dir equ 0x0504;dword - pointer +.low_mem equ 0x0508;word - usable memory from 0 to 1MiB in kiB +.mid_mem equ 0x050a;word - usable memory from 1MiB to 16MiB in kiB +.mem_used equ 0x050c;word - used memory from 0 to 1MiB in kiB +.kernel_s equ 0x050e;word - kernel image length in kiB + ;dword - kernel use +.high_mem equ 0x0514;word - usable memory from 16MiB up in 64s of kiB + +fat_header:;0x7c03 - 0x7c3d +.oem_name equ 0x7c03;mkfs.fat - +.bytes_per_sector equ 0x7c0b;0x0200 - +.sectors_per_cluster equ 0x7c0d;0x01 - .reserved_sectors equ 0x7c0e;0x0002 - handled -.n_fats equ 0x7c10;0x01 - assumed +.n_fats equ 0x7c10;0x01 - .root_dir_entries equ 0x7c11; - .n_sectors equ 0x7c13;0x0b40 - .media_type equ 0x7c15; - .sectors_per_fat equ 0x7c16; - handled .sectors_per_track equ 0x7c18;0x0012 - .sides equ 0x7c1a;0x0002 - -.hidden_sectors equ 0x7c1c;0x0000_0000 - assumed, top half used as scratch for sector number of cluster 0 -.long_sectors equ 0x7c20;0x0000_0000 - assumed -.drive_number equ 0x7c24; - ignored, used as scratch -.flags equ 0x7c25; - ignored -.signature equ 0x7c26;0x29 - halts on other values -.id equ 0x7c27; - ignored -.label equ 0x7c2b;PORTLAND OS - assumed -.fs_type equ 0x7c36;FAT12 - assumed +.hidden_sectors equ 0x7c1c;0x0000_0000 - +.long_sectors equ 0x7c20;0x0000_0000 - +.drive_number equ 0x7c24; - ignored, used as scratch for real drive number +.flags equ 0x7c25; - +.signature equ 0x7c26;0x29 - errors on other values +.id equ 0x7c27; - +.label equ 0x7c2b;PORTLAND OS - +.fs_type equ 0x7c36;FAT12 - errors on other values + +error_codes: +.bad_fat_header equ 0o000 +.insufficient_memory equ 0o001 +.no_kernel equ 0o002 +.kernel_too_big equ 0o003 org 0x7c3e bits 16 + ;Enable A20 line in al, 0x92 or al, 0x02 out 0x92, al + ;Load second sector of bootloader mov ah, 0x42 mov si, dap int 0x13 + ;Check FAT signature + test byte [fat_header.signature], 0x29 + jne bad_fat_header + test word [fat_header.fs_type], 0x4146;FA + jne bad_fat_header + test word [fat_header.fs_type + 2], 0x3154;T1 + jne bad_fat_header + test word [fat_header.fs_type + 4], 0x2032;2 + jne bad_fat_header + test word [fat_header.fs_type + 6], 0x2020; + jne bad_fat_header + + ;Store boot drive ID for later mov byte [fat_header.drive_number], dl memory: - mov bx, 0x2010 - mov eax, 0x0001_0001 -.clear: - mov dword [bx], eax - add bx, 4 - test bx, 0x4000 - jne .clear - - xor ax, ax - mov es, ax - mov si, 0x7000 - xor ebx, ebx - -.loop: - mov eax, 0x0000_e820 - mov ecx, 24 - mov edx, 0x534d_4150 + ;Get available low memory + int 0x12 + mov word [global_info.low_mem], ax + mov word [global_info.mem_used], 0x0020 + + ;Get available mid and high memory + xor dx, dx + mov ax, 0xe801 int 0x15 - jc .done - - test cl, 24 - jne .not_24 - - test byte [0x7014], 0x01 - jz .loop - -.not_24: - test dword [0x7010], 1 - jne .loop - - test byte [0x7003], 0 - jne .loop - - test dword [0x7004], 0 - jne .loop - - test dword [0x700c], 0 - je .check_lower - - mov dword [0x7008], 0xffff_ffff - -.check_lower: - test dword [0x7008], 0 - je .loop - - mov edx, ebx - mov ebx, dword [0x7000] - mov eax, ebx - add eax, dword [0x7008] - jnc .pagify - mov eax, 0xffff_ffff - -.pagify: - dec ebx - shr ebx, 12 - inc ebx - shr eax, 12 - dec eax - - test eax, 0xffff_f000 - jz .maxed - mov eax, 0x0000_0fff - -.maxed: - inc eax - test eax, ebx - je .next - - shl ebx, 1 - or ebx, 0x2000 - shl eax, 1 - add eax, 0x2000 - mov ecx, eax - - xor ax, ax -.free_loop: - mov word [ebx], ax - add ebx, 2 - test ebx, ecx - jne .free_loop - -.next: - mov ebx, edx - jmp .loop - -.done: - mov dword [0x2000], 0x0002_0002 - mov dword [0x2004], 0x0002_0002 - mov dword [0x2008], 0x0002_0002 - mov dword [0x200c], 0x0002_0002 - - test byte [fat_header.signature], 0x29 - jne halt - + test dx, dx + jnz .got + mov cx, ax + mov dx, bx +.got: + mov word [global_info.mid_mem], cx + mov word [global_info.high_mem], dx + + ;Load FAT + mov ax, word [fat_header.reserved_sectors] + mov word [dap.start], ax + xor eax, eax mov ax, word [fat_header.sectors_per_fat] - xor ecx, ecx - mov cx, word [fat_header.reserved_sectors] - - call allocate_and_load - - mov dword [pointers.fat], ebx + call load_low + mov dword [global_info.fat], ebx +load_root: + ;Load root directory + mov ax, word [fat_header.sectors_per_fat] + xor dh, dh + mov dl, word [fat_header.n_fats] + mul dx + add ax, [fat_header.reserved_sectors] + jnc .no_inc + inc dx +.no_inc: + mov word [dap.start], ax + mov word [dap.start + 2], dx mov ax, word [fat_header.root_dir_entries] - dec ax shr ax, 4 - inc ax + call load_low + mov dword [global_info.root_dir], ebx + ;Calculate end of root directory xor ecx, ecx - mov cx, word [fat_header.reserved_sectors] - add cx, word [fat_header.sectors_per_fat] - jnc .no_carry - or ecx, 0x0001_0000 -.no_carry: - - call allocate_and_load - - mov dword [pointers.root_dir], ebx - - xor edx, edx - mov dx, word [fat_header.root_dir_entries] - shl edx, 5 - add edx, ebx + mov cx, word [fat_header.root_dir_entries] + shl ecx, 5 + add ecx, ebx + jc insufficient_memory find_kernel: - mov eax, 0x6e_72_65_6b;kern - mov ecx, 0x20_20_6c_65;el - mov ebx, dword [pointers.root_dir] - + mov eax, 0x6e72_656b;kern + mov edx, 0x2020_6c65;el .loop: + ;Check name test dword [ebx], eax jne .next - test dword [ebx + 4], ecx + test dword [ebx + 4], edx jne .next - test word [ebx + 8], 0x79_73;sy + test word [ebx + 8], 0x7973;sy jne .next test byte [ebx + 10], 0x73;s je .found - .next: + ;Next record add ebx, 32 - test ebx, edx + test ebx, ecx jne .loop - jmp halt + ;Got to end of directory + mov dl, error_codes.no_kernel + jmp error + + ;ebx is pointer to entry + ;word [ebx + 26] is first cluster + ;dword [ebx + 28] is size .found: - mov byte [allocate_and_load.load], 0xc3;ret + ;Save size for later + mov eax, dword [ebx + 28] + shr eax, 10 + test eax, 0x003f_0000 + jz .store_size + mov dl, error_codes.kernel_too_big + jmp error +.store_size: + mov word [global_info.kernel_s], ax + + ;Save sector number for later + mov cx, [ebx + 26] + + ;find 1kiB buffer + mov ax, 2 + mov byte [load_low.ret_with_segment], 0xc3;ret + call load_low + shl ebx, 4 - mov eax, dword [ebx + 0x1c] - dec eax - shr eax, 9 - inc eax +load_kernel: + - test eax, 0xffff_0000 - jnz halt +load_low: + ;ax in : number of sectors + ;qword [dap.start] in : starting sector - push word [ebx + 0x1a] + ;Store length in DAP + mov word [dap.length], ax - call allocate_and_load + ;Calculate kiB used + dec ax + shr ax, 1 + inc ax + mov dx, ax + add ax, word [global_info.mem_usage] - mov dword [pointers.kernel], ebx + ;Fail if not enough is available + jc insufficient_memory + cmp ax, word [global_info.low_mem] + jg insufficient_memory - mov ax, word [fat_header.root_dir_entries] - dec ax - shr ax, 4 - dec ax - add ax, word [fat_header.reserved_sectors] - jc halt - add ax, word [fat_header.sectors_per_fat] - jc halt - mov word [fat_header.hidden_sectors + 2], ax + ;Check if address will fit in DAP + test ah, ah + jnz insufficient_memory -load_kernel: - mov word [dap.length], 0x0001 - mov word [dap.offset], bx - xor bx, bx - shr ebx, 4 - jmp .over_sig - -times $$ + 0x01fe - $ db 0 -dw 0xaa55 - -.over_sig: - test ebx, 0xffff_0000 - jnz halt + ;Commit usage + mov word [global_info.low_mem_usage], ax + + ;Put address into DAP + xor ebx, ebx + mov bh, al + shr bx, 2 mov word [dap.segment], bx + mov word [dap.offset], 0x0000 +.ret_with_segment: - xor edx, edx - pop dx - mov word [dap.start + 2], 0x0000 - mov ah, 0x42 + ;Load from disk mov si, dap -.loop: - mov cx, dx - add cx, word [fat_header.hidden_sectors + 2] - jc halt - - mov word [dap.start], cx - + mov ah, 0x42 int 0x13 + shl ebx, 4 + ret - mov ebx, dword [pointers.fat] - add ebx, edx - add ebx, edx - add ebx, edx - - xor edx, edx - mov dx, word [ebx + 1] - shl edx, 8 - mov dl, byte [ebx] - - add word [dap.segment], 0x0020 - jc halt - - mov ecx, edx - and ecx, 0x0ff8 - test ecx, 0x0ff8 - jne .loop - - mov ebx, dword [pointers.kernel] - - ;TODO +bad_fat_header: + mov dl, error_codes.bad_fat_header + jmp error + +insufficient_memory: + mov dl, error_codes.insufficient_memory + jmp error + +error: + ;Print error code (in octal) + mov ax, 0xb800 + mov ds, ax + mov word [0], 0x0f72;E + mov ax, 0x0f00 + mov al, dl + and al, 0x07 + or al, 0x30 + mov word [6], ax;bottom digit + shr dl, 3 + mov al, dl + and al, 0x07 + or al, 0x30 + mov word [4], ax;middle digit + shr dl, 3 + mov al, dl + or al, 0x30 + mov word [2], ax;top digit cli - - lgdt [gdt] - mov eax, cr0 - or al, 0x01 - mov cr0, eax - jmp 0x08:kernel_start;get start from file header +.halt: + hlt + jmp .halt gdt: dw 0x28 @@ -299,69 +269,9 @@ dw 0x0010 .length dw 0x0001 .offset dw 0x7e00 .segment dw 0x0000 -.start dd 0x0000_0001 -.start_h dd 0x0000_0000 - -;ecx = sector -;ax = sector count -;bx out = address of start -allocate_and_load: - mov word [dap.length], ax - mov dword [dap.start], ecx - - dec ax - shr ax, 3 - inc ax +.start dq 0x0000_0000_0000_0001 - mov bx, 0x200e - xor cx, cx - mov dx, 0x2200 - -.loop: - add bx, 2 - test bx, dx - je halt - - test word [bx], 0x0000 - je .eq - - xor cx, cx - jmp .loop - -.eq: - inc cx - test cx, ax - jne .loop - - dec ax - shl ax, 1 - sub bx, ax - mov dx, bx - - mov ax, 0x0002 -.mark_loop: - mov word [bx], ax - loop .mark_loop - - mov bx, dx - and ebx, 0x0000_dfff - shl ebx, 12 - -.load: - mov eax, ebx - mov word [dap.offset], ax - shr eax, 4 - and ax, 0xf000 - mov word [dap.segment], ax - - mov ah, 0x42 - mov si, dap - int 0x13 - - ret - -halt: - cli -.hlt: - hlt - jmp .hlt +memory_usage: +.low dw ;word - used memory from 0 to 1MiB in kiB +.mid dw 0x0000;word - used memory from 1MiB to 16MiB in kiB +.high dw 0x0000;word - used memory from 16MiB up in 64s of kiB
\ No newline at end of file |