;Copyright 2019 Benji Dial ;Permission to use, copy, modify, and/or distribute this ;software for any purpose with or without fee is hereby ;granted, provided that the above copyright notice and this ;permission notice appear in all copies. ;THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ;ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL ;IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO ;EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, ;INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ;WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, ;WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER ;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 .reserved_sectors equ 0x7c0e;0x0002 - handled .n_fats equ 0x7c10;0x01 - assumed .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 org 0x7c3e bits 16 in al, 0x92 or al, 0x02 out 0x92, al mov ah, 0x42 mov si, dap int 0x13 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 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 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 mov ax, word [fat_header.root_dir_entries] dec ax shr ax, 4 inc ax 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 find_kernel: mov eax, 0x6e_72_65_6b;kern mov ecx, 0x20_20_6c_65;el mov ebx, dword [pointers.root_dir] .loop: test dword [ebx], eax jne .next test dword [ebx + 4], ecx jne .next test word [ebx + 8], 0x79_73;sy jne .next test byte [ebx + 10], 0x73;s je .found .next: add ebx, 32 test ebx, edx jne .loop jmp halt .found: mov byte [allocate_and_load.load], 0xc3;ret mov eax, dword [ebx + 0x1c] dec eax shr eax, 9 inc eax test eax, 0xffff_0000 jnz halt push word [ebx + 0x1a] call allocate_and_load mov dword [pointers.kernel], ebx 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 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 mov word [dap.segment], bx xor edx, edx pop dx mov word [dap.start + 2], 0x0000 mov ah, 0x42 mov si, dap .loop: mov cx, dx add cx, word [fat_header.hidden_sectors + 2] jc halt mov word [dap.start], cx int 0x13 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 cli lgdt [gdt] mov eax, cr0 or al, 0x01 mov cr0, eax jmp 0x08:kernel_start;get start from file header gdt: dw 0x28 dd gdt + 6 dq 0x0000_0000_0000_0000 dq 0x0040_9a00_0000_7fff;0x000000 - 0x007fff dq 0x0040_9200_0000_7fff dq 0x00c0_9a00_8000_0ff7;0x008000 - 0xffffff dq 0x00c0_9200_8000_0ff7 dap: 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 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