diff --git a/k/Makefile b/k/Makefile index 52aacbd..02ba1c9 100644 --- a/k/Makefile +++ b/k/Makefile @@ -30,7 +30,8 @@ OBJS = \ libvga.o \ list.o \ memory.o \ - serial.o + serial.o \ + gdt.o DEPS = $(OBJS:.o=.d) diff --git a/k/gdt.c b/k/gdt.c new file mode 100644 index 0000000..7901109 --- /dev/null +++ b/k/gdt.c @@ -0,0 +1,74 @@ +#include "gdt.h" + +static struct gdt gdt = { 0 }; + +static void create_kernel_ds() +{ +} + +static void create_kernel_cs() +{ +} + +static void create_gdt() +{ + create_kernel_ds(); + create_kernel_cs(); +} + +static void load_gdt() +{ + struct gdt_r gdtr; + gdtr.addr = (uint32_t)&gdt; + gdtr.limit = GDT_SIZE - 1; + + asm volatile("lgdt %0\n" + : + : "m" (gdtr) + : "memory"); +} + +static void load_ds() +{ + struct segment_selector selector; + selector.index = KERNEL_DS_INDEX; + selector.table_indicator = 0; + selector.rpl = 0; + + asm volatile("movw %0, %%ax\n" + "movw %%ax, %%ds\n" + "movw %%ax, %%fs\n" + "movw %%ax, %%gs\n" + "movw %%ax, %%ss\n" + : + : "m" (selector) + : "ax"); +} + +static void load_cs() +{ + struct segment_selector selector; + selector.index = KERNEL_CS_INDEX; + selector.table_indicator = 0; + selector.rpl = 0; + + asm volatile("pushl %0\n" + "pushl $1f\n" + "lret\n" + "1:\n" + : + : "m" (selector)); +} + +static void reload_segment_selectors() +{ + load_ds(); + load_cs(); +} + +void init_gdt() +{ + create_gdt(); + load_gdt(); + reload_segment_selectors(); +} diff --git a/k/gdt.h b/k/gdt.h index 2272b7f..269fb60 100644 --- a/k/gdt.h +++ b/k/gdt.h @@ -3,6 +3,12 @@ #include +#define GDT_NB_ENTRIES 3 +#define GDT_SIZE (GDT_NB_ENTRIES * sizeof(struct gdt_entry)) + +#define KERNEL_CS_INDEX 1 +#define KERNEL_DS_INDEX 2 + struct gdt_entry { uint16_t limit_1 : 16; @@ -20,4 +26,24 @@ struct gdt_entry uint8_t base_3 : 8; } __attribute__ ((packed)); +struct gdt +{ + struct gdt_entry entries[GDT_NB_ENTRIES]; +}; + +struct gdt_r +{ + uint32_t addr; + uint16_t limit; +} __attribute__ ((packed)); + +struct segment_selector +{ + uint8_t rpl : 2; + uint8_t table_indicator : 1; + uint16_t index : 13; +} __attribute__ ((packed)); + +void init_gdt(); + #endif /* !GDT_H */ diff --git a/k/serial.c b/k/serial.c index d18469c..570b7fe 100644 --- a/k/serial.c +++ b/k/serial.c @@ -24,12 +24,12 @@ void init_serial(void) int write(const char *buf, size_t count) { - int sent; + size_t sent; for(sent = 0; sent < count; ++sent) { u8 line_status = inb(COM1 + 5); - if (!line_status & EMPTY_TRANSMITTER) + if (!(line_status & EMPTY_TRANSMITTER)) break; outb(COM1, buf[sent]); }