#include "gdt.h" // Internal method extern void gdt_flush(uint32_t); // Defined on cpu/gdt.asm static gdt_entry_t construct_null_entry(); static gdt_entry_t construct_entry(gdt_access_t access); static void init_gdt(); gdt_entry_t gdt_entries[5]; gdt_ptr_t gdt_ptr; // This method will be called by the kernel void gdt_setup() { init_gdt(); } static void init_gdt() { gdt_ptr.limit = (sizeof(gdt_entry_t) * 5) - 1; gdt_ptr.base = (uint32_t)&gdt_entries; gdt_entry_t null_segment = construct_null_entry(); gdt_entry_t kernel_mode_code_segment = construct_entry( (struct gdt_access){ .type = GDT_CODE_TYPE_EXEC_READ, .dt = GDT_CODE_AND_DATA_DESCRIPTOR, .dpl = GDT_RING0, .p = GDT_SEGMENT_PRESENT } ); gdt_entry_t kernel_mode_data_segment = construct_entry( (struct gdt_access){ .type = GDT_DATA_TYPE_READ_WRITE, .dt = GDT_CODE_AND_DATA_DESCRIPTOR, .dpl = GDT_RING0, .p = GDT_SEGMENT_PRESENT } ); gdt_entry_t user_mode_code_segment = construct_entry( (struct gdt_access){ .type = GDT_CODE_TYPE_EXEC_READ, .dt = GDT_CODE_AND_DATA_DESCRIPTOR, .dpl = GDT_RING3, .p = GDT_SEGMENT_PRESENT } ); gdt_entry_t user_mode_data_segment = construct_entry( (struct gdt_access){ .type = GDT_DATA_TYPE_READ_WRITE, .dt = GDT_CODE_AND_DATA_DESCRIPTOR, .dpl = GDT_RING3, .p = GDT_SEGMENT_PRESENT } ); gdt_entries[0] = null_segment; gdt_entries[1] = kernel_mode_code_segment; gdt_entries[2] = kernel_mode_data_segment; gdt_entries[3] = user_mode_code_segment; gdt_entries[4] = user_mode_data_segment; gdt_flush((uint32_t)&gdt_ptr); } static gdt_entry_t construct_entry(gdt_access_t access) { gdt_entry_t entry = (struct gdt_entry_struct) { .base_low = GDT_BASE & 0xFFFF, .base_middle = (GDT_BASE >> 16) & 0xFF, .base_high = (GDT_BASE >> 24) & 0xFF, .limit_low = (GDT_LIMIT & 0xFFFF), .access = access, .granularity = (struct gdt_granularity) { .g = GDT_GRANULARITY_4K, .d = GDT_OPERAND_SIZE_32, .zero = 0, .seglen = GDT_SEGMENT_LENGTH } }; return entry; } // The only difference is in the access static gdt_entry_t construct_null_entry() { gdt_entry_t null_entry = (struct gdt_entry_struct) { .base_low = 0, .base_middle = 0, .base_high = 0, .limit_low = 0, .access = (struct gdt_access) { .p = 0, .dpl = 0, .dt = 0, .type = 0 }, .granularity = (struct gdt_granularity) { .g = 0, .d = 0, .zero = 0, .seglen = 0 } }; return null_entry; }