aboutsummaryrefslogtreecommitdiff
path: root/src/core/gdt.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/gdt.c')
-rw-r--r--src/core/gdt.c98
1 files changed, 98 insertions, 0 deletions
diff --git a/src/core/gdt.c b/src/core/gdt.c
new file mode 100644
index 0000000..8c1c70d
--- /dev/null
+++ b/src/core/gdt.c
@@ -0,0 +1,98 @@
+#include "gdt.h"
+#include "mem.h"
+
+struct GDT_REGISTER GDTR = { 0, 0 };
+GDT_TSS TSS;
+
+void gdt_memcpy(){
+ GDTR.limit=8*GDT_MAX_ENTRIES; // Each entry is 8 bytes and 8 entries
+ GDTR.base=0x800;
+ gdt_write_entry((GDT_ENTRY){0,0,0,0},0); // First one must be null
+
+ // ----- Kernel Segments
+ GDT_ENTRY cs_desc;
+ cs_desc.base=0;
+ cs_desc.limit=0xFFFFF;
+ cs_desc.flags=GDT_SZ|GDT_GR;
+ cs_desc.access=GDT_PR|GDT_PRVL_0|GDT_S|GDT_EXEC|GDT_RW;
+
+ GDT_ENTRY ds_desc;
+ ds_desc.base=0;
+ ds_desc.limit=0xFFFFF;
+ ds_desc.flags=GDT_SZ|GDT_GR;
+ ds_desc.access=GDT_PR|GDT_PRVL_0|GDT_S|GDT_RW;
+
+ GDT_ENTRY ss_desc;
+ ss_desc.base=0;
+ ss_desc.limit=0;
+ ss_desc.flags=GDT_SZ|GDT_GR;
+ ss_desc.access=GDT_PR|GDT_PRVL_0|GDT_S|GDT_RW|GDT_DC;
+
+ // Write GDT descriptors into memory
+ gdt_write_entry(cs_desc, 1);
+ gdt_write_entry(ds_desc, 2);
+ gdt_write_entry(ss_desc, 3);
+
+ // ----- User Segments
+ GDT_ENTRY ucs_desc;
+ ucs_desc.base=0; // With paging will take care of allocating the right address for each task
+ ucs_desc.limit=0xFFFFF;
+ ucs_desc.flags=GDT_SZ|GDT_GR;
+ ucs_desc.access=GDT_PR|GDT_PRVL_3|GDT_S|GDT_EXEC|GDT_RW|GDT_DC;
+
+ GDT_ENTRY uds_desc;
+ uds_desc.base=0;
+ uds_desc.limit=0xFFFFF;
+ uds_desc.flags=GDT_SZ|GDT_GR;
+ uds_desc.access=GDT_PR|GDT_PRVL_3|GDT_S|GDT_RW;
+
+ GDT_ENTRY uss_desc;
+ uss_desc.base=0; // Not used in stack descriptor
+ uss_desc.limit=0x64; // Define how much entry it can contains
+ uss_desc.flags=GDT_SZ|GDT_GR;
+ uss_desc.access=GDT_PR|GDT_PRVL_3|GDT_S|GDT_RW|GDT_DC;
+
+ // Write GDT descriptors into memory
+ gdt_write_entry(ucs_desc, 4); // Each entry is 64 bits (8 bytes)
+ gdt_write_entry(uds_desc, 5);
+ gdt_write_entry(uss_desc, 6);
+
+ // Init TSS segment
+ TSS.t_reserved=0;
+ TSS.io_map=0;
+
+ GDT_ENTRY tss_desc;
+ tss_desc.base=(u32)&TSS; // Not used in stack descriptor
+ tss_desc.limit=0x68; // Define how much bytes it occupies
+ tss_desc.flags=0;
+ tss_desc.access=0x89 | GDT_PRVL_3; // Note that 0x89 is specific to TSS!
+ gdt_write_entry(tss_desc, 7);
+
+}
+
+void gdt_write_entry(GDT_ENTRY entry, u32 id){
+ int descriptor[2];
+
+ // First row of the descriptor
+ descriptor[0]=(entry.limit & 0xFFFF)|(entry.base << 16);
+
+ // Format second row of the descriptor
+ u16 base=(entry.base >> 16) & 0xFF;
+ u16 access=entry.access & 0xFF;
+ u16 limit=(entry.limit >> 16) & 0xF; // Remember: limits it is on 20 bits so 4 last bits
+ u8 flags=entry.flags & 0xF;
+ u8 base2=entry.base >> 24; // Take the last 8 bits
+ descriptor[1]=base|access<<8|limit<<16|flags<<20|base2<<24;
+
+ // Copy descriptor into memory
+ memcpy(descriptor,(void*)GDTR.base+8*id,8); // Each entry is 64 bits (8 bytes)
+}
+
+int gdt_user_ds_base(){
+ char *addr=(char*)GDTR.base+48;
+ int *base0_15=(int*)addr+2;
+ int *base16_31=(int*)addr+7;
+ int base0_15_content=*base0_15 & 0xFFFF;
+ int base16_21_content=*base16_31 & 0xFFFF;
+ return(base16_21_content<<16 & base0_15_content);
+} \ No newline at end of file