diff options
Diffstat (limited to 'kernel/GDT.c')
| -rw-r--r-- | kernel/GDT.c | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/kernel/GDT.c b/kernel/GDT.c new file mode 100644 index 0000000..4bc7ca2 --- /dev/null +++ b/kernel/GDT.c @@ -0,0 +1,136 @@ +// http://wiki.osdev.org/GDT_Tutorial +#include "lib/logger/log.h" +#include "usermode.h" +#define FOOLOS_MODULE_NAME "GDT" + +#include <stdint.h> +#define GDT_SIZE 6 + +extern sys_tss; + +typedef struct GDT_struct +{ + uint32_t base; + uint32_t limit; + uint32_t type; + +}GDT; + +//alternative +struct gdt_entry_bits +{ + unsigned int limit_low:16; + unsigned int base_low : 24; + //attribute byte split into bitfields + unsigned int accessed :1; + unsigned int read_write :1; //readable for code, writable for data + unsigned int conforming_expand_down :1; //conforming for code, expand down for data + unsigned int code :1; //1 for code, 0 for data + unsigned int always_1 :1; //should be 1 for everything but TSS and LDT + unsigned int DPL :2; //priveledge level + unsigned int present :1; + //and now into granularity + unsigned int limit_high :4; + unsigned int available :1; + unsigned int always_0 :1; //should always be 0 + unsigned int big :1; //32bit opcodes for code, uint32_t stack for data + unsigned int gran :1; //1 to use 4k page addressing, 0 for byte addressing + unsigned int base_high :8; +} __packed; //or __attribute__((packed)) + + +static GDT myGDT[GDT_SIZE]; +static uint8_t gdt_struct[GDT_SIZE*8]; + +/** + * \param target A pointer to the 8-byte GDT entry + * \param source An arbitrary structure describing the GDT entry + */ +void encodeGdtEntry(uint8_t *target, GDT source) +{ + // Check the limit to make sure that it can be encoded + if ((source.limit > 65536) && (source.limit & 0xFFF) != 0xFFF) + { + panic(FOOLOS_MODULE_NAME,"trying to set an invalid GDT source.limit!"); + } + if (source.limit > 65536) { + // Adjust granularity if required + source.limit = source.limit >> 12; + target[6] = 0xC0; + } else { + target[6] = 0x40; + } + + // Encode the limit + target[0] = source.limit & 0xFF; + target[1] = (source.limit >> 8) & 0xFF; + + // Encode the base + target[2] = source.base & 0xFF; + target[3] = (source.base >> 8) & 0xFF; + target[4] = (source.base >> 16) & 0xFF; + target[7] = (source.base >> 24) & 0xFF; + + target[5] = source.type; + target[6] |= (source.limit >> 16) & 0xF; + + // And... Type + + /* + +0 1 dw 0xffff ;limit +2 3 dw 0x0 ;base +4 db 0x0 ;base +5 db 10011010b ;flags +6 db 11001111b ;flags & seg.limit +7 db 0x0 ;base + */ + + +} + +void gdt_setup() +{ + log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"setting up Global Descriptor Table"); + //selector 0x0 + myGDT[0].base=0; + myGDT[0].limit=0; + myGDT[0].type=0; + + //selector 0x8 code + myGDT[1].base=0; + myGDT[1].limit=0xffffffff; + myGDT[1].type=0x9a; + + //selector 0x10 data + myGDT[2].base=0; + myGDT[2].limit=0xffffffff; + myGDT[2].type=0x92; + + //selector 0x18 code user + myGDT[3].base=0; + myGDT[3].limit=0xffffffff; + myGDT[3].type=0xFa; + + //selector 0x20 data user + myGDT[4].base=0; + myGDT[4].limit=0xffffffff; + myGDT[4].type=0xF2; + + //TSS 0x28 + myGDT[5].base=&sys_tss; //tss start? + myGDT[5].limit=sizeof(tss_struct); //tss end? + myGDT[5].type=0x89; + + + // transcript to format the processor wants + for(int i=0;i<GDT_SIZE;i++) + encodeGdtEntry(&gdt_struct[8*i],myGDT[i]); + + + // updat + install_tss(); + setup_gdt(&gdt_struct[0],8*GDT_SIZE); + + +} |
