From a3e0852ec782fe10e59ded42fe11a472a77458d4 Mon Sep 17 00:00:00 2001 From: Jenny Curle Date: Sat, 6 Apr 2019 20:00:11 +0100 Subject: [PATCH] Begin support for Global Descriptor Tables --- arch/i386/boot.s | 18 ++++++++++++++++ include/kernel/gdt.h | 4 ++++ kernel/gdt.c | 50 ++++++++++++++++++++++++++++++++++++++++++++ kernel/kernel.c | 5 ++++- makefile | 3 ++- 5 files changed, 78 insertions(+), 2 deletions(-) create mode 100755 include/kernel/gdt.h create mode 100755 kernel/gdt.c diff --git a/arch/i386/boot.s b/arch/i386/boot.s index 5504693..b1be172 100755 --- a/arch/i386/boot.s +++ b/arch/i386/boot.s @@ -10,12 +10,30 @@ .long FLAGS .long CHECKSUM +# C stack startup .section .bss .align 16 stack_bottom: .skip 16384 stack_top: +# GDT segment register setup +.global _gdt_flush +.extern _gp +_gdt_flush: + lgdt (_gp) #load the GDT with the special pointer + mov %ax, 0x10 #offset from GDT to data segment + mov %ds, ax + mov %es, ax + mov %fs, ax + mov %gs, ax + mov %ss, ax + jmp 0x08:flush2 #long jump +flush2: + ret #return to c code + + +# start function - calls kernel_main .section .text .global _start .type _start, @function diff --git a/include/kernel/gdt.h b/include/kernel/gdt.h new file mode 100755 index 0000000..780ba8f --- /dev/null +++ b/include/kernel/gdt.h @@ -0,0 +1,4 @@ +#pragma once + +void gdt_set_gate(int, unsigned long, unsigned long, unsigned char, unsigned char); +void gdt_install(); \ No newline at end of file diff --git a/kernel/gdt.c b/kernel/gdt.c new file mode 100755 index 0000000..f2bbd93 --- /dev/null +++ b/kernel/gdt.c @@ -0,0 +1,50 @@ +#include + +struct gdt_item { + unsigned short low_limit; + unsigned short low_base; + unsigned char middle_base; + unsigned char access; + unsigned char granular; + unsigned char high_base; +} __attribute__((packed)); //Prevent compiler optimisation by packing + +struct gdt_ptr { + unsigned short limit; + unsigned int base; +} __attribute__((packed)); + +struct gdt_item gdt[3]; //3-entry gdt +struct gdt_ptr gp; + +extern void gdt_flush(); + +void gdt_set_gate(int num, unsigned long base, + unsigned long limit, unsigned char access, + unsigned char gran) { + //Implementation taken from osdever.net + gdt[num].low_base = (base & 0xFFFF); + gdt[num].middle_base = (base >> 16) & 0xFF; + gdt[num].high_base = (base >> 24) & 0xFF; + + gdt[num].low_limit = (limit & 0xFFFF); + gdt[num].granular = ((limit >> 16) & 0x0F); + + gdt[num].granular != (gran & 0xF0); + gdt[num].access = access; +} + +void gdt_install() { + gp.limit = (sizeof(struct gdt_item) * 3) - 1; + gp.base = &gdt; + + gdt_set_gate(0, 0, 0, 0, 0); //NULL item + + //Code Segment - base 0, 4KiB granularity, 4GiB limit + gdt_set_gate(1, 0, 0xFFFFFFFF, 0x9A, 0xCF); + + //Data Segment - ditto + gdt_set_gate(2, 0, 0xFFFFFFFF, 0x92, 0xCF); + + //Apply changes + gdt_flush(); \ No newline at end of file diff --git a/kernel/kernel.c b/kernel/kernel.c index 893c8b3..77a7063 100755 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -1,8 +1,11 @@ //#include -#include "kernel/tty.h" +#include +#include int kernel_main(void) { + //Prepare the GDT + gdt_install() //Prepare the screen, and blank it out. screen_initialize(); diff --git a/makefile b/makefile index cd00da8..060d5ca 100755 --- a/makefile +++ b/makefile @@ -30,6 +30,7 @@ LIBS:=$(LIBS) $(KERNEL_ARCH_LIBS) KERNEL_OBJS= \ $(KERNEL_ARCH_OBJS) \ kernel/utils.o \ +kernel/gdt.o \ kernel/kernel.o OBJS=\ @@ -93,4 +94,4 @@ gen-iso: iso -include $(OBJS:.o=.d) - +