32bit_kernel/src/gdt.c

141 lines
4.4 KiB
C

#define __GDT__
#define __TSS__
#include "gdt.h"
#include <types.h>
#include "serial.h"
#include "debug.h"
#include "tss.h"
#include "userland.h"
void *memcpy(void *dest, const void *src, size_t n)
{
const char *s = src;
char *d = dest;
for (size_t i = 0; i < n; i++)
{
*d++ = *s++;
}
return dest;
}
struct tss user_land_tss;
struct segment_desc_param {
u16 Limit_1;
u32 Base;
u8 Type;
u8 S;
u8 DPL;
u8 P;
u8 Limit_2;
u8 AVL;
u8 L;
u8 D_B;
u8 G;
};
struct segdesc init_descriptor(struct segment_desc_param param)
{
struct segdesc descriptor;
descriptor.Limit_1 = param.Limit_1;
descriptor.Limit_2 = param.Limit_2;
descriptor.Base_1 = (u16) param.Base;
descriptor.Base_2 = (u8) (param.Base >> 16);
descriptor.Base_3 = (u8) (param.Base >> 24);
descriptor.Type = (param.Type & 0x000F);
descriptor.Flag_1 = param.S;
descriptor.Flag_1 |= (param.DPL << 1);
descriptor.Flag_1 |= (param.P << 3);
descriptor.Flag_2 = param.AVL;
descriptor.Flag_2 |= (param.L << 1);
descriptor.Flag_2 |= (param.D_B << 2);
descriptor.Flag_2 |= (param.G << 3);
return descriptor;
}
void init_gdt(void)
{
DEBUG_INFO("Initializing GDT");
DEBUG_INFO("GDT BASE ADDRESS: %d", (u32) &kgdtr);
DEBUG_INFO("GDT LIMIT: %d", sizeof(gdt) - 1);
kgdtr.limit = sizeof(gdt) - 1;
kgdtr.base = (u32) gdt;
gdt[0] = init_descriptor((struct segment_desc_param) { .Limit_1 = 0,
.Base = 0, .Type = 0, .S = 0, .DPL = 0, .P = 0,
.Limit_2 = 0, .AVL = 0, .L = 0, .D_B = 0, .G = 0 });
// Code
gdt[1] = init_descriptor((struct segment_desc_param) { .Limit_1 = 0xFFFF,
.Base = 0, .Type = 0x0B, .S = 1, .DPL = 0, .P = 1,
.Limit_2 = 0x0F, .AVL = 0, .L = 0, .D_B = 1, .G = 1 });
// Data
gdt[2] = init_descriptor((struct segment_desc_param) { .Limit_1 = 0xFFFF,
.Base = 0, .Type = 2, .S = 1, .DPL = 0, .P = 1,
.Limit_2 = 0x0F, .AVL = 0, .L = 0, .D_B = 1, .G = 1 });
// Code
gdt[3] = init_descriptor((struct segment_desc_param) { .Limit_1 = 0xFFFF,
.Base = 0, .Type = 0x0B, .S = 1, .DPL = 3, .P = 1,
.Limit_2 = 0x0F, .AVL = 0, .L = 0, .D_B = 1, .G = 1 });
// Data
gdt[4] = init_descriptor((struct segment_desc_param) { .Limit_1 = 0xFFFF,
.Base = 0, .Type = 2, .S = 1, .DPL = 3, .P = 1,
.Limit_2 = 0x0F, .AVL = 0, .L = 0, .D_B = 1, .G = 1 });
user_land_tss.ssp = 0x0;
user_land_tss.io_map_base_address = 0x0;
user_land_tss.ss0 = 0x10;
user_land_tss.esp0 = 0x20000;
DEBUG_INFO("TSS BASE ADDRESS: %d", (u32) &user_land_tss);
gdt[5] = init_descriptor((struct segment_desc_param) { .Limit_1 = sizeof(user_land_tss),
.Base = &user_land_tss, .Type = 0x09, .S = 0, .DPL = 3, .P = 1,
.Limit_2 = 0x00, .AVL = 0, .L = 0, .D_B = 0, .G = 0 });
for (int i = 0; i < sizeof(gdt) / 8; i++)
{
char *ptr = (char *) &gdt[i];
DEBUG_INFO("--------------------");
DEBUG_INFO("GDT[%d] : Entry number : %d", i, i * 8);
DEBUG_INFO("\tLIMIT : %d", (u16) ptr[0] | ((ptr[6] & 0x0F) << 16));
// TODO : Fix display of base address
DEBUG_INFO("\tBASE : %d", (u32) ptr[2] | ((u32) (((u8) ptr[4]) << 16)) | ((u32) (((u8) ptr[7]) << 24)));
DEBUG_INFO("\tTYPE : %b |Data 0 / Code 1|Expand Down 1|Writable 1|Accessed 1|", (u8) ptr[5] & 0x0F);
DEBUG_INFO("\tFlag : %b |Present 1|Level ring 0 / ring 1|System 0 / Code - Data 1|", (u8) ptr[5] >> 4);
DEBUG_INFO("\tFlag : %b |Granularity 1|16 bits 0 / 32 bits 1|64 bits 1|Available for system 1|", (u8) ptr[6] >> 4);
}
DEBUG_INFO("--------------------");
asm volatile ("lgdt (kgdtr)");
asm volatile (
"movw $0x10, %ax \n\
movw %ax, %ds \n\
movw %ax, %es \n\
movw %ax, %fs \n\
movw %ax, %gs \n\
movw %ax, %ss \n\
ljmp $0x08, $next \n\
next: \n"
);
DEBUG_INFO("SS0 %d", user_land_tss.ss0);
DEBUG_INFO("ESP0 %d", user_land_tss.esp0);
DEBUG_INFO("GDT LOADED");
}