From cdc7b2ae532fd3a93e13784812f7501f2fd5c07a Mon Sep 17 00:00:00 2001 From: Benji Dial Date: Sat, 14 Dec 2019 18:31:34 -0500 Subject: more of bootloader, tiny kernel stub --- .gitignore | 2 + doc/design/memory_map.txt | 4 +- makefile | 17 +++- src/bootloader.asm | 213 +++++++++++++++++++++++++++++++++++----------- src/kernel/main.c | 26 ++++++ src/kernel/vga.c | 71 ++++++++++++++++ src/kernel/vga.h | 31 +++++++ 7 files changed, 313 insertions(+), 51 deletions(-) create mode 100644 .gitignore create mode 100644 src/kernel/main.c create mode 100644 src/kernel/vga.c create mode 100644 src/kernel/vga.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..38e34c6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +obj/ +out/ diff --git a/doc/design/memory_map.txt b/doc/design/memory_map.txt index 28aed8a..d51ebcf 100644 --- a/doc/design/memory_map.txt +++ b/doc/design/memory_map.txt @@ -1,7 +1,9 @@ 0x0000 - 0x03ff : interrupt vector table 0x0400 - 0x04ff : bios data area 0x0500 - 0x05ff : structure pointers - 0x00 dword : fat pointer + 0x00 : fat + 0x04 : root directory + 0x08 : kernel 0x0600 - 0x1fff : not assigned 0x2000 - 0x3fff : memory map for each word : 1 page diff --git a/makefile b/makefile index c3d4174..2c9d11c 100644 --- a/makefile +++ b/makefile @@ -1,10 +1,23 @@ -floppy: out bootloader - mkfs.fat -C -f 1 -F 12 -n "PORTLAND OS" -R 2 -S 512 out/floppy.img 1440 +floppy: out bootloader files + mkfs.fat -C -f 1 -F 12 -n "PORTLAND OS" -R 4 -S 512 out/floppy.img 1440 + mkdir out/floppy_mount + mount out/floppy.img out/floppy_mount + cp out/fs/* out/floppy_mount/ + umount out/floppy_mount dd if=obj/bootloader.bin of=out/floppy.img bs=1 seek=62 conv=notrunc bootloader: obj nasm src/bootloader.bin -o obj/bootloader.bin +kernel: obj out + gcc -c src/kernel/main.c -o obj/kmain.o -ffreestanding + gcc -c src/kernel/vga.c -o obj/kvga.o -ffreestanding + ld obj/kmain.o obj/kvga.o -o out/kernel.out -nostdlib --oformat=i386-aout + +files: kernel + mkdir out/fs + cp out/kernel.out out/fs/kernel.sys + obj: mkdir -p obj diff --git a/src/bootloader.asm b/src/bootloader.asm index e8ab91b..08d1daf 100644 --- a/src/bootloader.asm +++ b/src/bootloader.asm @@ -17,20 +17,22 @@ 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 - other values handled +.reserved_sectors equ 0x7c0e;0x0004 - other values handled .n_fats equ 0x7c10;0x01 - assumed -.directory_entries equ 0x7c11; - +.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 +.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 @@ -148,13 +150,165 @@ memory: 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 + 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] + + ;Parse kernel executable header, + ;Go through relocation tables, + ;Get kernel_start. + + 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 0x0003 +.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 -fat_allocate: mov bx, 0x200e xor cx, cx mov dx, 0x2200 @@ -189,50 +343,17 @@ fat_allocate: and ebx, 0x0000_dfff shl ebx, 12 - mov dword [pointers.fat], ebx - - mov dl, byte [fat_header.drive_number] - mov ax, word [fat_header.reserved_sectors] - mov word [dap.start], ax - mov word [dap.offset], bx - shr ebx, 16 - and bx, 0xf000 - mov word [dap.segment], bx +.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 0x15 - - mov ebx, dword [pointers.fat] - - ;fat loaded - load kernel - - cli - - lgdt [gdt] - mov eax, cr0 - or al, 0x01 - mov cr0, eax - jmp 0x08:pmode - -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 dq 1 + int 0x13 -allocate: - ;TODO ret halt: @@ -240,7 +361,3 @@ halt: .hlt: hlt jmp .hlt - -bits 32 -pmode: - diff --git a/src/kernel/main.c b/src/kernel/main.c new file mode 100644 index 0000000..079779c --- /dev/null +++ b/src/kernel/main.c @@ -0,0 +1,26 @@ +/* +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. +*/ + +#include "vga.h" + +void main(void) { + put_sz("Welcome to Portland version 0.0.8!\n"); + while (1) + put_sz("|\b/\b-\b\\\b"); +} diff --git a/src/kernel/vga.c b/src/kernel/vga.c new file mode 100644 index 0000000..046dda7 --- /dev/null +++ b/src/kernel/vga.c @@ -0,0 +1,71 @@ +/* +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. +*/ + +#include "vga.h" + +uint16_t cursor_pos = 0; +uint8_t color = 0xf0; +#define cols 80 +#define rows 25 + +void scroll(void) { + cursor_pos -= cols * 2; + uint32_t *limit = (uint32_t *)(VGA_BUFFER + cols * (rows - 1)); + for (uint32_t *i = (uint32_t *)VGA_BUFFER; i < limit; ++i) + *i = *(i + cols / 2); + limit += cols / 2; + uint32_t fill = (color * 0x0100 + (uint8_t)' ') * 0x00010001; + for (uint32_t *i = limit - cols / 2; i < limit; ++i) + *i = fill; +} + +void put_char(uint8_t ch) { + switch (ch) { + case '\b': + if (cursor_pos) + VGA_BUFFER[cursor_pos -= 2] = (uint8_t)' '; + break; + case '\t': + while ((cursor_pos % (cols * 2)) % 20) + put_char(' '); + break; + case '\n': + if ((cursor_pos = (cursor_pos / (cols * 2) + 1) * (cols * 2)) >= cols * rows * 2) + scroll(); + break; + default: + VGA_BUFFER[cursor_pos++] = ch; + VGA_BUFFER[cursor_pos++] = color; + if (cursor_pos == (cols * rows * 2)) + scroll(); + } +} + +void put_sz(uint8_t *sz) { + while (*sz) + put_char(*(sz++)); +} + +void move_cursor(uint8_t col, uint8_t row) { + cursor_pos = (col + row * cols) * 2; +} + +void set_color(uint8_t c) { + color = c; +} diff --git a/src/kernel/vga.h b/src/kernel/vga.h new file mode 100644 index 0000000..74a5d04 --- /dev/null +++ b/src/kernel/vga.h @@ -0,0 +1,31 @@ +/* +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. +*/ + +#include + +#ifndef VGA_H +#define VGA_H + +#define VGA_BUFFER ((uint8_t *)0x000b8000) +void put_char(uint8_t ch); +void put_sz(uint8_t *s); +void move_cursor(uint8_t col, uint8_t row); +void set_color(uint8_t c); + +#endif \ No newline at end of file -- cgit v1.2.3