# HG changeset patch # User John Tsiombikas # Date 1297833963 -7200 # Node ID 611b2d66420bd94f9f0c7c45101dfd1e18200501 # Parent 7e40f14617ed8c0ff7821942bb7ed800b0871650 segment descriptors diff -r 7e40f14617ed -r 611b2d66420b .gdbinit --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.gdbinit Wed Feb 16 07:26:03 2011 +0200 @@ -0,0 +1,2 @@ +file kernel.elf +target remote localhost:1234 diff -r 7e40f14617ed -r 611b2d66420b Makefile --- a/Makefile Thu Jan 13 20:24:10 2011 +0200 +++ b/Makefile Wed Feb 16 07:26:03 2011 +0200 @@ -1,6 +1,7 @@ # collect all of our C and assembly source files csrc = $(wildcard src/*.c) $(wildcard src/klibc/*.c) asmsrc = $(wildcard src/*.S) $(wildcard src/klibc/*.S) +dep = $(asmsrc:.S=.d) $(csrc:.c=.d) # each source file will generate one object file obj = $(asmsrc:.S=.o) $(csrc:.c=.o) @@ -20,6 +21,18 @@ $(bin): $(obj) ld -melf_i386 -o $@ -Ttext 0x100000 -e kentry $(obj) +-include $(dep) + +%.d: %.c + @$(CPP) $(CFLAGS) -MM -MT $(@:.d=.o) $< >$@ + +%.d: %.S + @$(CPP) $(ASFLAGS) -MM -MT $(@:.d=.o) $< >$@ + .PHONY: clean clean: rm -f $(obj) $(bin) + +.PHONY: cleandep +cleandep: + rm -f $(dep) diff -r 7e40f14617ed -r 611b2d66420b src/main.c --- a/src/main.c Thu Jan 13 20:24:10 2011 +0200 +++ b/src/main.c Wed Feb 16 07:26:03 2011 +0200 @@ -2,6 +2,7 @@ #include "vid.h" #include "term.h" #include +#include "segm.h" /* special keys */ enum { @@ -31,12 +32,13 @@ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 70 - 7f */ }; - void kmain(void) { clear_scr(); puts("kernel starting up"); + init_segm(); + set_text_color(YELLOW); puts(""); set_text_color(LTGRAY); @@ -49,7 +51,7 @@ } while(!(keypress & 1)); inb(c, 0x60); if(!(c & 0x80)) { - putchar(keycodes[c]); + putchar(keycodes[(int)c]); } } } diff -r 7e40f14617ed -r 611b2d66420b src/segm-asm.S --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/segm-asm.S Wed Feb 16 07:26:03 2011 +0200 @@ -0,0 +1,41 @@ + .data +off:.long 0 +seg:.short 0 + + .align + .short 0 +gdt_lim: + .short 0 +gdt_addr: + .long 0 + + .text +/* setup_selectors(uint16_t code, uint16_t data) + * loads the requested selectors to all the selector registers */ + .globl setup_selectors +setup_selectors: + /* setup data selectors */ + movl 8(%esp), %eax + movw %ax, %ss + movw %ax, %es + movw %ax, %ds + movw %ax, %gs + movw %ax, %fs + /* setup code selector */ + movl 4(%esp), %eax + movw %ax, (seg) + movl $ldcs, (off) + ljmp *off +ldcs: + ret + +/* set_gdt(uint32_t addr, uint16_t limit) + * loads the GDTR with the new address and limit for the GDT */ + .globl set_gdt +set_gdt: + movl 4(%esp), %eax + movl %eax, (gdt_addr) + movw 8(%esp), %ax + movw %ax, (gdt_lim) + lgdt (gdt_lim) + ret diff -r 7e40f14617ed -r 611b2d66420b src/segm.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/segm.c Wed Feb 16 07:26:03 2011 +0200 @@ -0,0 +1,57 @@ +#include +#include "segm.h" + +#define BIT_ACCESSED (1 << 8) +#define BIT_WR (1 << 9) +#define BIT_RD (1 << 9) +#define BIT_EXP_DOWN (1 << 10) +#define BIT_CONFORMING (1 << 10) +#define BIT_CODE (1 << 11) +#define BIT_NOSYS (1 << 12) +#define BIT_PRESENT (1 << 15) + +#define BIT_BIG (1 << 6) +#define BIT_DEFAULT (1 << 6) +#define BIT_GRAN (1 << 7) + +enum {TYPE_DATA, TYPE_CODE}; + +static void segm_desc(desc_t *desc, uint32_t base, uint32_t limit, int dpl, int type); + + +static desc_t gdt[4]; + + +void init_segm(void) +{ + memset(gdt, 0, sizeof gdt); + segm_desc(gdt + SEGM_KCODE, 0, 0xffffffff, 0, TYPE_CODE); + segm_desc(gdt + SEGM_KDATA, 0, 0xffffffff, 0, TYPE_DATA); + + set_gdt((uint32_t)gdt, sizeof gdt - 1); + + setup_selectors(selector(SEGM_KCODE, 0), selector(SEGM_KDATA, 0)); +} + +uint16_t selector(int idx, int rpl) +{ + return (idx << 3) | (rpl & 3); +} + +static void segm_desc(desc_t *desc, uint32_t base, uint32_t limit, int dpl, int type) +{ + desc->d[0] = limit & 0xffff; /* low order 16bits of limit */ + desc->d[1] = base & 0xffff; /* low order 16bits of base */ + + /* third 16bit part contains the last 8 bits of base, the 2 priviledge + * level bits starting on bit 13, present flag on bit 15, and type bits + * starting from bit 8 + */ + desc->d[2] = ((base >> 16) & 0xff) | ((dpl & 3) << 13) | BIT_PRESENT | + BIT_NOSYS | (type == TYPE_DATA ? BIT_WR : (BIT_RD | BIT_CODE)); + + /* last 16bit part contains the last nibble of limit, the last byte of + * base, and the granularity and deafult/big flags in bits 23 and 22 resp. + */ + desc->d[3] = ((limit >> 16) & 0xf) | ((base >> 16) & 0xff00) | BIT_GRAN | BIT_BIG; +} diff -r 7e40f14617ed -r 611b2d66420b src/segm.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/segm.h Wed Feb 16 07:26:03 2011 +0200 @@ -0,0 +1,21 @@ +#ifndef SEGM_H_ +#define SEGM_H_ + +#define SEGM_KCODE 1 +#define SEGM_KDATA 2 + +typedef struct { + uint16_t d[4]; +} desc_t; + +void init_segm(void); + +uint16_t selector(int idx, int rpl); + +/* these functions are implemented in segm-asm.S */ +void setup_selectors(uint16_t code, uint16_t data); +void set_gdt(uint32_t addr, uint16_t limit); + + + +#endif /* SEGM_H_ */