summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/bootloader.asm213
-rw-r--r--src/kernel/main.c26
-rw-r--r--src/kernel/vga.c71
-rw-r--r--src/kernel/vga.h31
4 files changed, 293 insertions, 48 deletions
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 <stdint.h>
+
+#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