// http://wiki.osdev.org/GDT_Tutorial #include "lib/logger/log.h" #include "usermode.h" #define FOOLOS_MODULE_NAME "GDT" #include #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_init() { 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