diff --git a/arch/i386/boot.s b/arch/i386/boot.s index a00dde8..16fa856 100755 --- a/arch/i386/boot.s +++ b/arch/i386/boot.s @@ -35,25 +35,6 @@ _start: .size _start, . - _start - -# GDT segment register setup -.global gdt_flush -.extern gp -gdt_flush: - lgdt (gp) #load the GDT with the special pointer - mov %eax,0x10 #offset from GDT to data segment - mov %eax, %ds - mov %eax, %es - mov %eax, %fs - mov %eax, %gs - mov %eax, %ss - - pushl 12(%esp) - push $flush2 - ljmp *(%esp) #long jump -flush2: - ret #return to c code - .global idt_load .extern idtp idt_load: diff --git a/arch/i386/gdt.s b/arch/i386/gdt.s new file mode 100755 index 0000000..e4fd2b4 --- /dev/null +++ b/arch/i386/gdt.s @@ -0,0 +1,17 @@ +; This file is written with Intel ASM Syntax. + +[GLOBAL load_gdt] ; Allows the C code to call gdt_flush(). + +load_gdt: + mov eax, [esp+4] ; Get the pointer to the GDT, passed as a parameter. + lgdt [eax] ; Load the new GDT pointer + + mov ax, 0x10 ; 0x10 is the offset in the GDT to our data segment + mov ds, ax ; Load all data segment selectors + mov es, ax + mov fs, ax + mov gs, ax + mov ss, ax + jmp 0x08:.flush ; 0x08 is the offset to our code segment: Far jump! +.flush: + ret \ No newline at end of file diff --git a/arch/i386/make.config b/arch/i386/make.config index 44f0c86..157deaa 100755 --- a/arch/i386/make.config +++ b/arch/i386/make.config @@ -5,4 +5,5 @@ KERNEL_ARCH_LIBS= KERNEL_ARCH_OBJS= \ $(ARCHDIR)/boot.o \ +$(ARCHDIR)/gdt.o \ $(ARCHDIR)/tty.o \ No newline at end of file diff --git a/include/kernel/serial.h b/include/kernel/serial.h index 2522681..18b20ba 100755 --- a/include/kernel/serial.h +++ b/include/kernel/serial.h @@ -1,4 +1,6 @@ #pragma once +#include +#include extern void init_serial(); diff --git a/kernel/gdt.c b/kernel/gdt.c index c872a23..a182bc4 100755 --- a/kernel/gdt.c +++ b/kernel/gdt.c @@ -1,27 +1,31 @@ #include +#include +#include +#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; + uint16_t low_limit; + uint16_t low_base; + uint8_t middle_base; + uint8_t access; + uint8_t granular; + uint8_t high_base; } __attribute__((packed)); //Prevent compiler optimisation by packing struct gdt_ptr { - unsigned short limit; + uint16_t limit; unsigned int base; } __attribute__((packed)); struct gdt_item gdt[3]; //3-entry gdt struct gdt_ptr gp; -extern void gdt_flush(); +extern void load_gdt(uint32_t); -void gdt_set_gate(int num, unsigned long base, - unsigned long limit, unsigned char access, - unsigned char gran) { +void gdt_set_gate(int num, uint32_t base, + uint32_t limit, uint8_t access, + uint8_t gran) { //Implementation taken from osdever.net gdt[num].low_base = (base & 0xFFFF); gdt[num].middle_base = (base >> 16) & 0xFF; @@ -38,6 +42,7 @@ void gdt_install() { gp.limit = (sizeof(struct gdt_item) * 3) - 1; gp.base = (unsigned int)&gdt; + gdt_set_gate(0, 0, 0, 0, 0); //NULL item //Code Segment - base 0, 4KiB granularity, 4GiB limit @@ -47,5 +52,5 @@ void gdt_install() { gdt_set_gate(2, 0, 0xFFFFFFFF, 0x92, 0xCF); //Apply changes - gdt_flush(); + load_gdt((uint32_t) &gp); } \ No newline at end of file diff --git a/kernel/kernel.c b/kernel/kernel.c index 7d123de..2b3c781 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -11,9 +11,12 @@ int kernel_main(void) { // Prepare the serial console. init_serial(); - serial_print(0x3F8, "[INFO] Serial ready."); - // Prepare the GDT - //gdt_install(); + serial_print(0x3F8, "[INFO] Serial ready."); + + // Prepare the GDT + serial_print(0x3F8, "[INFO] Beginning GDT subroutine."); + gdt_install(); + // Prepare interrupts //idt_install(); diff --git a/makefile b/makefile index e77edb4..a8da3dc 100755 --- a/makefile +++ b/makefile @@ -61,6 +61,9 @@ red.kernel: $(OBJS) $(ARCHDIR)/linker.ld $(ARCHDIR)/crtbegin.o $(ARCHDIR)/crtend.o: OBJ=`$(CC) $(CFLAGS) $(LDFLAGS) -print-file-name=$(@F)` && cp "$$OBJ" $@ + +$(ARCHDIR)/gdt.o: + nasm -f elf $(ARCHDIR)/gdt.s .c.o: $(CC) -MD -c $< -o $@ -std=gnu11 $(CFLAGS) $(CPPFLAGS)