Fix segment error in GRUB
diff --git a/src/kernel/Makefile b/src/kernel/Makefile
index 16c5628..f8f2117 100644
--- a/src/kernel/Makefile
+++ b/src/kernel/Makefile
@@ -12,7 +12,8 @@
paging.o \
switch_table.o \
scan_codes.o
-CFLAGS = -nostdlib -nostdinc -fno-builtin -fno-stack-protector -ffreestanding -m32 -O2 -g
+CFLAGS = -nostdlib -nostdinc -fno-builtin -fno-stack-protector -ffreestanding \
+ -m32 -O2 -g -Wall -Wno-unused-function -Wno-unused-variable
LDFLAGS = -Tlink.ld -melf_i386
ASMFLAGS = -felf
QEMUFLAGS = -d cpu_reset
diff --git a/src/kernel/boot.s b/src/kernel/boot.s
index d80261a..e235516 100644
--- a/src/kernel/boot.s
+++ b/src/kernel/boot.s
@@ -16,6 +16,9 @@
STACK_SIZE equ 0x4000
+
+;;;;;;;;;;;;;;;;;;;;; DATA ;;;;;;;;;;;;;;;;;;;;;
+
[section .data align = 0x1000]
page_directory:
dd 0b010000011 ; Identity map first 4 megs
@@ -23,6 +26,59 @@
dd 0b010000011 ; Map kernel memory to zero page too
times (1024 - KERNEL_PAGE_NUMBER - 1) dd 0
+gdt:
+ ;; First entry, null segment
+ dw 0 ; zero limit
+ dw 0 ; base low
+
+ db 0 ; base middle
+ db 0 ; access
+ db 0 ; granularity
+ db 0 ; base high
+
+ ;; Second entry, code segment
+ dw 0xffffffff ; max limit
+ dw 0
+
+ db 0
+ db 0x9a ; access
+ db 0xcf ; granularity
+ db 0
+
+ ;; Third entry, data segment
+ dw 0xffffffff ; max limit
+ dw 0
+
+ db 0
+ db 0x92 ; access
+ db 0xcf ; granularity
+ db 0
+
+ ;; Fourth entry, user code segment
+ dw 0xffffffff ; max limit
+ dw 0
+
+ db 0
+ db 0xfa ; access
+ db 0xcf ; granularity
+ db 0
+
+ ;; Fifth entry, user data segment
+ dw 0xffffffff ; max limit
+ dw 0
+
+ db 0
+ db 0xf2 ; access
+ db 0xcf ; granularity
+ db 0
+
+gdt_pointer:
+ dw (8 * 5 - 1) ; sizeof(gdt entry) * 5 - 1
+ dd (gdt - KERNEL_VIRTUAL_BASE) ; Remember, PHYSICAL address
+
+
+;;;;;;;;;;;;;;;;;;;;; CODE ;;;;;;;;;;;;;;;;;;;;;
+
[bits 32]
[section .text]
[global mboot]
@@ -43,9 +99,21 @@
[global start]
[extern kmain] ; C code
-start equ (_start - KERNEL_VIRTUAL_BASE)
+start equ (_start)
_start:
+ ;; First set up GDT
+ mov eax, (gdt_pointer - KERNEL_VIRTUAL_BASE)
+ lgdt [eax] ; Load GDT
+
+ mov ax, 0x10 ; Offset of data segment
+ mov ds, ax
+ mov es, ax
+ mov fs, ax
+ mov gs, ax
+ mov ss, ax
+
+enable_paging:
mov ecx, (page_directory - KERNEL_VIRTUAL_BASE) ; Physical address
mov cr3, ecx
diff --git a/src/kernel/main.c b/src/kernel/main.c
index 59fc65c..a866852 100644
--- a/src/kernel/main.c
+++ b/src/kernel/main.c
@@ -8,6 +8,7 @@
int kmain(void *mboot)
{
init_paging();
+ init_vga();
vga_clear();
vga_set_color(LIGHT_BLUE, BLACK);
diff --git a/src/kernel/paging.c b/src/kernel/paging.c
index 458de21..9da17dc 100644
--- a/src/kernel/paging.c
+++ b/src/kernel/paging.c
@@ -94,7 +94,7 @@
kpanic("first_free_frame failed! no free frames");
}
-void alloc_frame(uint *page, bool for_kernel, bool writable)
+void alloc_frame(uint *page, bool user, bool writable)
{
if (*page >> 12)
return; /* frame already allocated */
@@ -102,6 +102,7 @@
uint frame = first_free_frame();
// kprintf("first_free_frame found %d\n", frame);
set_frame(frame * 0x1000); /* mark as mapped */
+ *page = frame | 1 | writable << 1 | user << 2;
}
void free_frame(uint page)
@@ -109,7 +110,8 @@
clear_frame(page / 0x1000);
}
-void map_4mb(size_t virt_start, size_t phys_start, bool user, bool rw)
+void map_4mb(uint *dir, size_t virt_start, size_t phys_start, bool user,
+ bool rw)
{
uint page = virt_start / 0x1000;
uint table = virt_start >> 22;
@@ -119,15 +121,46 @@
set_frame(page + i);
}
- page_directory[table] = 0b10000011;
+ dir[table] = 0b10000011;
+}
+
+uint *get_or_create_table(uint *dir, uint table, bool user, bool rw)
+{
+ if (dir[table] >> 12)
+ {
+ return (uint *)(size_t)(dir[table] ^ 0xfff);
+ }
+
+ uint *page_table = kmalloc_a(sizeof(uint[1024]));
+ dir[table] = (uint)page_table | 1 | rw << 1 | user << 2;
+ return page_table;
+}
+
+void map_page(uint *dir, size_t virt_start, bool user, bool rw)
+{
+ uint page = virt_start / 0x1000;
+ uint table = virt_start >> 22;
+ uint frame = first_free_frame();
+
+ // If 4mb map OR (maps to table AND table maps page)
+ if ((dir[table] & 1 && dir[table] & 1 << 7) ||
+ (dir[table] >> 12 && ((uint *)(size_t)dir[table])[page] & 1))
+ {
+ return;
+ }
+
+ set_frame(frame);
+ uint *t = get_or_create_table(dir, table, user, rw);
+ alloc_frame(t + page, user, rw);
}
/* paging stuff */
void init_paging()
{
+ frames = kmalloc_a(0x1000);
memset(page_directory, 0, 1024 * 4);
- page_directory[KERNEL_PAGE_NUMBER] = 0b10000011;
+ map_4mb(page_directory, (size_t)KERNEL_VIRTUAL_BASE, 0, false, false);
load_page_directory((uint)page_directory - 0xC0000000);
add_interrupt_handler(14, page_fault);
diff --git a/src/kernel/vga.c b/src/kernel/vga.c
index de5e998..9edbdc4 100644
--- a/src/kernel/vga.c
+++ b/src/kernel/vga.c
@@ -1,5 +1,6 @@
#include "vga.h"
#include "io.h"
+#include "paging.h"
#include "log.h"
static uint cursor_x = 0;
@@ -7,16 +8,18 @@
static ushort color = WHITE;
-static ushort *fb = (ushort *)(0xB8000 + 0xC0000000);
+static ushort *fb = (ushort *)PHYS_TO_VIRT(0xB8000);
static void move_cursor()
{
- ushort loc = cursor_y * 80 + cursor_x;
- outb(0x3d4, 14); // Setting high cursor byte
- outb(0x3d4, loc >> 8);
+ ushort pos = cursor_y * 80 + cursor_x;
- outb(0x3d4, 15); // low byte
- outb(0x3d4, loc & 0xff);
+ outb(0x3d4, 0x0e);
+ outb(0x3d5, pos >> 8);
+ outb(0x3d4, 0x0f);
+ outb(0x3d5, pos & 0xff);
+
+ io_wait();
}
static void scroll()
@@ -39,7 +42,7 @@
void vga_set_color(enum vga_colors fg, enum vga_colors bg)
{
- color = (bg << 4) | fg & 0xf;
+ color = (bg << 4) | (fg & 0xf);
}
void vga_put(char c)
@@ -108,8 +111,8 @@
static bool vga_put_nibble(uchar n, bool first)
{
-// if (first && n == 0)
-// return true;
+ // if (first && n == 0)
+ // return true;
if (n <= 9)
vga_put('0' + n);
@@ -131,3 +134,18 @@
first = vga_put_nibble(byte & 0x0f, first);
}
}
+
+void init_vga()
+{
+ return;
+
+ outb(0x3D4, 0x09); // set maximum scan line register to 15
+ outb(0x3D5, 15);
+
+ outb(0x3D4, 0x0B); // set the cursor end line to 15
+ outb(0x3D5, 15);
+
+ outb(0x3D4, 0x0A); // set the cursor start line to 14 and enable cursor
+ // visibility
+ outb(0x3D5, 10);
+}
diff --git a/src/kernel/vga.h b/src/kernel/vga.h
index 9c7ba16..d68a6d9 100644
--- a/src/kernel/vga.h
+++ b/src/kernel/vga.h
@@ -28,3 +28,5 @@
void vga_putx(uint x);
void vga_clear();
void vga_write(char *c);
+
+void init_vga();