From c94252c3f2b8e686796981aff67314029077900f Mon Sep 17 00:00:00 2001 From: shockrah Date: Mon, 14 Oct 2019 00:23:37 -0700 Subject: [PATCH] Huge GDT update: GDT control is how I would like it to be but there are some issues, namely: 1. far jumping to flush the code segment crashes the whole os(not good) 2. Segment selectors seem fine apart from the code segment thing 3. some administrative issues regarding the structure of the project which is slowly making things painful --- gdt.c | 39 +++++++++++++++++++++++++++++++++++++++ gdt.h | 22 ++++++++++++++++------ gdt.s | 8 -------- gdt_seg.s | 17 +++++++++++++++++ kernel.c | 2 ++ loader.s | 6 +++++- makefile | 2 +- 7 files changed, 80 insertions(+), 16 deletions(-) create mode 100644 gdt.c delete mode 100644 gdt.s create mode 100644 gdt_seg.s diff --git a/gdt.c b/gdt.c new file mode 100644 index 0000000..35d2582 --- /dev/null +++ b/gdt.c @@ -0,0 +1,39 @@ +#include "gdt.h" +// Congirures a given gdt entry base on the entry index given +void gdt_configure_entry(u32 entry, u32 base, u32 limit, u8 access, u8 gran) { + // base address + gdt_entries[entry].low_base = (base & 0xffff); + gdt_entries[entry].middle_base = (base >> 16) & 0xff; + gdt_entries[entry].high_base = (base >> 24) & 0xff; + + // descriptor limits + gdt_entries[entry].low_limit = (limit & 0xffff); + gdt_entries[entry].granular = ((limit >> 16) & 0x0f); + + gdt_entries[entry].granular |= (gran & 0xf0); + gdt_entries[entry].access = access; +} + +// Configure the gdt pointer desribed in gdt.h as type GDT_PTR +void gdt_configure() { + // gdt_ptr configuration + gdt_ptr.size = (sizeof(struct GDT_Entry) * NO_GDT_ENTRIES) - 1; + + // First entry is just the null descriptor and is left along overall + gdt_configure_entry(0, 0, 0, 0, 0); + + // Second entry: code segment base adders + // Base address: 0 + // limit: 4GB + // Granularity: 4KB + // 32-bit opcodes + // Code segment selector + gdt_configure_entry(1, 0, 0xffffffff, 0x9a, 0xcf); + + // Finally the data segment + // All the same except the desriptor type specifies that its data + gdt_configure_entry(2, 0, 0xffffffff, 0x92, 0xcf); + + // Load in the new changes to the gdt + load_gdt(); +} diff --git a/gdt.h b/gdt.h index 21b22e6..d33730e 100644 --- a/gdt.h +++ b/gdt.h @@ -1,19 +1,29 @@ -#include "gdt.h" #include "types.h" -// Container for our gdt entries +#define NO_GDT_ENTRIES 3 struct GDT_Entry { -}; + u16 low_limit; + u16 low_base; + u8 middle_base; + u8 access; + u8 granular; + u8 high_base; +}__attribute__((packed)); -struct GDT { +// Contains the pointer to the first gdt entry as well as the size(of the whole table(?)) +struct GDT_PTR { u16 size; u32 address; }__attribute__((packed)); -struct GDT_Entry entries[2]; -struct GDT GDT_P; +struct GDT_Entry gdt_entries[NO_GDT_ENTRIES]; +struct GDT_PTR gdt_ptr; +// this func is actually taken care of in gdt_seg.s extern void load_gdt(); +void gdt_configure_entry(u32 entry, u32 base, u32 limit, u8 access, u8 gran); + +void gdt_configure(); diff --git a/gdt.s b/gdt.s deleted file mode 100644 index 0d683dd..0000000 --- a/gdt.s +++ /dev/null @@ -1,8 +0,0 @@ -global load_gdt - -; lgdt can only be used from assembly so here we are -extern GDT_PTR -load_gdt: - lgdt [eax] - ret - diff --git a/gdt_seg.s b/gdt_seg.s new file mode 100644 index 0000000..95023e9 --- /dev/null +++ b/gdt_seg.s @@ -0,0 +1,17 @@ +global load_gdt +extern gdt_ptr + +load_gdt: + lgdt [gdt_ptr] + mov ax, 0x10 ; offset in the gdt to our data segment + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + mov ss, ax + jmp 0x08:flush_cs ; far jump to the code segment + +flush_cs: + ret ; here we go back to the caller code but with our segments configured + + diff --git a/kernel.c b/kernel.c index 0076ed2..94046ce 100644 --- a/kernel.c +++ b/kernel.c @@ -9,6 +9,8 @@ GDT _GDT[6]; // because there are only 6 segments we care about u32 kinit() { init_segment_selectors(); // found in gdt.s } + +// called by the loader to do lots of fun things void kmain() { } diff --git a/loader.s b/loader.s index 086ca1d..e4cbd9a 100644 --- a/loader.s +++ b/loader.s @@ -5,10 +5,11 @@ global loader MAGIC_NUMBER equ 0x1BADB002 FLAGS equ 0x0 CHECKSUM equ -MAGIC_NUMBER +KERNEL_STACK_SIZE equ 4096 ; size in bytes of stack -KERNEL_STACK_SIZE equ 4096 +extern gdt_configure extern test_dispatcher section .text @@ -22,6 +23,9 @@ align 4 ; sets up our gdt and segment selectors for later use loader: + ; load the gdt that I setup + call load_gdt + ;call gdt_configure call test_dispatcher .loop: diff --git a/makefile b/makefile index 5a3b5b0..c9a38b6 100644 --- a/makefile +++ b/makefile @@ -3,7 +3,7 @@ ASM=nasm LINK=ld ISO=genisoimage -OBJECTS=interrupts.o interrupt_entry.o loader.o serial.o framebuffer.o ports.o stlio.o tests.o +OBJECTS=gdt_seg.o gdt.o loader.o serial.o framebuffer.o ports.o stlio.o tests.o AFLAGS=-f elf32 CFLAGS=-m32 -nostdlib -nostdinc -fno-builtin -fno-stack-protector -nostartfiles \ -nodefaultlibs -Wall -Wextra -Werror -c