diff --git a/Makefile b/Makefile index 09e5cc32..e1541a55 100644 --- a/Makefile +++ b/Makefile @@ -7,8 +7,8 @@ install: kernel cp kernel /mnt/kernel umount /mnt -kernel: start.o link.ld main.o vga.o - ld -m elf_i386 -T link.ld -o kernel start.o main.o vga.o +kernel: start.o link.ld main.o vga.o gdt.o + ld -m elf_i386 -T link.ld -o kernel *.o %.o: %.c gcc -Wall -m32 -O -fstrength-reduce -fomit-frame-pointer -finline-functions -nostdinc -fno-builtin -I./include -c -o $@ $< diff --git a/bootdisk.img b/bootdisk.img index 9bcd87cf..6424d2d6 100644 Binary files a/bootdisk.img and b/bootdisk.img differ diff --git a/gdt.c b/gdt.c new file mode 100644 index 00000000..a28296ec --- /dev/null +++ b/gdt.c @@ -0,0 +1,74 @@ +#include + +/* + * Global Descriptor Tablet Entry + */ +struct gdt_entry { + unsigned short limit_low; + unsigned short base_low; + unsigned char base_middle; + unsigned char access; + unsigned char granularity; + unsigned char base_high; +} __attribute__((packed)); + +/* + * GDT pointer + */ +struct gdt_ptr { + unsigned short limit; + unsigned int base; +} __attribute__((packed)); + +struct gdt_entry gdt[3]; +struct gdt_ptr gp; + +/* + * (ASM) gdt_flush + * Reloads the segment registers + */ +extern void gdt_flush(); + +/* + * gdt_set_gate + * Set a GDT descriptor + */ +void +gdt_set_gate( + int num, + unsigned long base, + unsigned long limit, + unsigned char access, + unsigned char gran + ) { + /* Base Address */ + gdt[num].base_low = (base & 0xFFFF); + gdt[num].base_middle = (base >> 16) & 0xFF; + gdt[num].base_high = (base >> 24) & 0xFF; + /* Limits */ + gdt[num].limit_low = (limit & 0xFFFF); + gdt[num].granularity = (limit >> 16) & 0X0F; + /* Granularity */ + gdt[num].granularity |= (gran & 0xF0); + /* Access flags */ + gdt[num].access = access; +} + +/* + * gdt_install + * Install the kernel's GDTs + */ +void +gdt_install() { + /* GDT pointer and limits */ + gp.limit = (sizeof(struct gdt_entry) * 3) - 1; + gp.base = &gdt; + /* NULL */ + gdt_set_gate(0, 0, 0, 0, 0); + /* Code segment */ + gdt_set_gate(1, 0, 0xFFFFFFFF, 0x9A, 0xCF); + /* Data segment */ + gdt_set_gate(2, 0, 0xFFFFFFFF, 0x92, 0xCF); + /* Go go go */ + gdt_flush(); +} diff --git a/include/system.h b/include/system.h index 961f9630..b3bd319e 100644 --- a/include/system.h +++ b/include/system.h @@ -16,4 +16,8 @@ extern void puts(unsigned char *str); extern void settextcolor(unsigned char forecolor, unsigned char backcolor); extern void init_video(); +/* GDT */ +extern void gdt_install(); +extern void gdt_set_gate(int num, unsigned long base, unsigned long limit, unsigned char access, unsigned char gran); + #endif diff --git a/main.c b/main.c index c3e826e6..19f82fd9 100644 --- a/main.c +++ b/main.c @@ -101,6 +101,7 @@ outportb( */ int main() { + gdt_install(); init_video(); puts("Hello world!\n"); for (;;); diff --git a/start.asm b/start.asm index 71bdb40e..acecfc21 100644 --- a/start.asm +++ b/start.asm @@ -32,6 +32,19 @@ stublet: jmp $ ; GDT +global gdt_flush +extern gp +gdt_flush: + lgdt [gp] + mov ax, 0x10 + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + mov ss, ax + jmp 0x08:flush2 +flush2: + ret ; Interrupt Service Routines