diff options
-rw-r--r-- | doc/design/memory_map.txt | 29 | ||||
-rw-r--r-- | makefile | 9 | ||||
-rw-r--r-- | src/bootloader.asm | 464 | ||||
-rw-r--r-- | src/kernel/link.ld | 14 | ||||
-rw-r--r-- | src/kernel/main.c | 2 |
5 files changed, 216 insertions, 302 deletions
diff --git a/doc/design/memory_map.txt b/doc/design/memory_map.txt index 74ac2d5..fdf9f74 100644 --- a/doc/design/memory_map.txt +++ b/doc/design/memory_map.txt @@ -1,20 +1,17 @@ 0x0000 - 0x03ff : interrupt vector table 0x0400 - 0x04ff : bios data area -0x0500 - 0x05ff : structure pointers - 0x00 : fat - 0x04 : root directory - 0x08 : kernel - 0x0c : file handle array - 0x10 : process array -0x0600 - 0x1fff : not assigned -0x2000 - 0x3fff : memory map - for each word : 1 page - 0x0000 = free - 0x0001 = unavailable - 0x0002 = kernel - other = process number -0x4000 - 0x6fff : not assigned +0x0500 - 0x05ff : global info + 0x00 dword : fat pointer + 0x04 dword : root directory pointer + 0x08 word : usable memory from 0 to 1MiB in kiB + 0x0a word : usable memory from 1MiB to 16MiB in kiB + 0x0c dword : bootloader: + lower word: low memory usage by bootloader in kiB, + upper word: kernel image length in kiB + kernel: + file handle array pointer + 0x10 dword : process array pointer + 0x14 word : usable memory from 16MiB up in 64s of kiB +0x0600 - 0x6fff : not assigned -0x7000 - 0x7bff : bootloader scratch - 0x7000 : memory map bios buffer 0x7c00 - 0x7fff : bootloader
\ No newline at end of file @@ -9,8 +9,13 @@ floppy: bootloader fs bootloader: obj nasm src/bootloader.asm -o obj/bootloader.bin -kernel: fs - gcc src/kernel/*.c -o out/fs/kernel.sys -ffreestanding -nostdlib -m32 -T src/kernel/link.ld +kernel: obj fs + gcc src/kernel/*.c -o obj/kernel.elf -ffreestanding -nostdlib -m32 -fno-asynchronous-unwind-tables + ld obj/kernel.elf -o obj/kernel-stripped.elf -T src/kernel/link.ld -s --orphan-handling=discard -m elf_i386 + objcopy obj/kernel-stripped.elf out/fs/kernel.sys -O binary + +clean: + rm -r obj out fs: out mkdir -p out/fs 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 diff --git a/src/kernel/link.ld b/src/kernel/link.ld index 64dd0be..aeb8974 100644 --- a/src/kernel/link.ld +++ b/src/kernel/link.ld @@ -1,11 +1,13 @@ -OUTPUT_FORMAT(binary) +MEMORY { + kload : ORIGIN = 0x01000000, LENGTH = 0x01000000 +} + SECTIONS { . = 0x01000000; .text : { - main = .; + _start = .; *(.text) - } - .rodata : { *(.rodata) } - .data : { *(.data) } - .bss : { *(.bss) } + } >kload + .rodata : { *(.rodata) } >kload + .data : { *(.data) *(.bss) } >kload }
\ No newline at end of file diff --git a/src/kernel/main.c b/src/kernel/main.c index 6a8630b..9ad9d1c 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -23,7 +23,7 @@ OF THIS SOFTWARE. #include "proc.h" #include "misc.h" -void main(void) { +void _start(void) { *(uint16_t *)0x0000200e = 0x0000; *(uint32_t *)0x0000050c = (uint32_t)allocate_pages(16 * sizeof(struct file_handle_info), 2); |