Merge branch 'main' of git.chauvet.pro:starnakin/42_KFS
This commit is contained in:
commit
bdfac39bc9
@ -2,16 +2,8 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#define GDT_BASE 0x00000800
|
#define GDT_ADDRESS 0x00000800
|
||||||
// sizeof(Segment Descriptor) * nb(Segment Descriptor)
|
#define GDT_SIZE 7
|
||||||
#define GDT_SIZE 8 * 7
|
|
||||||
|
|
||||||
struct gdt_entry {
|
|
||||||
uint32_t limit;
|
|
||||||
uint32_t base;
|
|
||||||
uint8_t access_byte;
|
|
||||||
uint8_t flags;
|
|
||||||
};
|
|
||||||
|
|
||||||
// https://wiki.osdev.org/Global_Descriptor_Table#GDTR
|
// https://wiki.osdev.org/Global_Descriptor_Table#GDTR
|
||||||
struct gdt_descriptor {
|
struct gdt_descriptor {
|
||||||
@ -20,3 +12,21 @@ struct gdt_descriptor {
|
|||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
void initGdt();
|
void initGdt();
|
||||||
|
|
||||||
|
#define GDT_FLAG_64BIT_MODE 0b0010
|
||||||
|
#define GDT_FLAG_32BIT_MODE 0b0100
|
||||||
|
#define GDT_FLAG_PAGE_MODE 0b1000
|
||||||
|
#define GDT_FLAG_BYTE_MODE 0b1000
|
||||||
|
|
||||||
|
#define GDT_ACCESS_P_VALID 0b10000000
|
||||||
|
#define GDT_ACCESS_DPL_KERNEL_MODE 0b00000000
|
||||||
|
#define GDT_ACCESS_DPL_USER_MODE 0b01100000
|
||||||
|
#define GDT_ACCESS_S_CODE_OR_DATA 0b00010000
|
||||||
|
#define GDT_ACCESS_S_SYSTEM_SEGMENT 0b00010000
|
||||||
|
#define GDT_ACCESS_E_EXECUTABLE 0b00001000
|
||||||
|
#define GDT_ACCESS_E_NOT_EXECUTABLE 0b00000000
|
||||||
|
#define GDT_ACCESS_DC_CONFORM 0b00000100 // TODO UNDERSTAND THIS BIT
|
||||||
|
#define GDT_ACCESS_DC_NOT_CONFORM 0b00000000
|
||||||
|
#define GDT_ACCESS_RW_READABLE_FOR_CODE_WRITABLE_FOR_DATA 0b00000010
|
||||||
|
#define GDT_ACCESS_A_ACCESSED 0b00000001
|
||||||
|
#define GDT_ACCESS_A_NOT_ACCESSED 0b00000000
|
@ -1,86 +1,52 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "gdt.h"
|
#include "gdt.h"
|
||||||
#include "kprintf.h"
|
#include "kprintf.h"
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
|
|
||||||
extern void setGdt(void *);
|
extern void set_gdt(uint32_t gdt_ptr);
|
||||||
|
|
||||||
void encodeGdtEntry(uint8_t *target, struct gdt_entry source)
|
uint8_t gdt_entries[GDT_SIZE * 8];
|
||||||
|
struct gdt_descriptor *gdtr = (struct gdt_descriptor *) GDT_ADDRESS;
|
||||||
|
|
||||||
|
static void set_gdt_entry_value(uint8_t *target, uint32_t base, uint32_t limit, uint8_t access, uint8_t granularity)
|
||||||
{
|
{
|
||||||
// Check the limit to make sure that it can be encoded
|
if (limit > 0xFFFFF) {
|
||||||
if (source.limit > 0xFFFFF) {
|
kprintf(KERN_ERR, "GDT cannot encode limits larger than 0xFFFFF");
|
||||||
kprintf(KERN_ERR,
|
|
||||||
"GDT cannot encode limits larger than 0xFFFFF");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Encode the limit
|
// Encode the limit
|
||||||
target[0] = source.limit & 0xFF;
|
target[0] = limit & 0xFF;
|
||||||
target[1] = (source.limit >> 8) & 0xFF;
|
target[1] = (limit >> 8) & 0xFF;
|
||||||
target[6] = (source.limit >> 16) & 0x0F;
|
target[6] = (limit >> 16) & 0x0F;
|
||||||
|
|
||||||
// Encode the base
|
// Encode the base
|
||||||
target[2] = source.base & 0xFF;
|
target[2] = base & 0xFF;
|
||||||
target[3] = (source.base >> 8) & 0xFF;
|
target[3] = (base >> 8) & 0xFF;
|
||||||
target[4] = (source.base >> 16) & 0xFF;
|
target[4] = (base >> 16) & 0xFF;
|
||||||
target[7] = (source.base >> 24) & 0xFF;
|
target[7] = (base >> 24) & 0xFF;
|
||||||
|
|
||||||
// Encode the access byte
|
// Encode the access byte
|
||||||
target[5] = source.access_byte;
|
target[5] = access;
|
||||||
|
|
||||||
// Encode the flags
|
// Encode the flags
|
||||||
target[6] |= (source.flags << 4);
|
target[6] |= (granularity << 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t gdt_entries[8][7];
|
|
||||||
struct gdt_descriptor gdtr;
|
|
||||||
|
|
||||||
void initGdt()
|
void initGdt()
|
||||||
{
|
{
|
||||||
gdtr.size = GDT_SIZE - 1;
|
gdtr->size = 8 * GDT_SIZE - 1;
|
||||||
gdtr.base = GDT_BASE;
|
gdtr->base = (uint32_t) &gdt_entries;
|
||||||
|
|
||||||
struct gdt_entry gdt_entry_null_descriptor = {
|
set_gdt_entry_value(gdt_entries + 0x00, 0, 0, 0, 0); // Null segment
|
||||||
.base = 0, .limit = 0x00000000, .access_byte = 0x00, .flags = 0x0};
|
|
||||||
encodeGdtEntry(gdt_entries[0], gdt_entry_null_descriptor);
|
|
||||||
|
|
||||||
struct gdt_entry gdt_entry_kernel_mode_code_segment = {
|
set_gdt_entry_value(gdt_entries + 0x08, 0, 0xFFFFF, GDT_ACCESS_P_VALID | GDT_ACCESS_DPL_KERNEL_MODE | GDT_ACCESS_S_CODE_OR_DATA | GDT_ACCESS_E_EXECUTABLE | GDT_ACCESS_DC_NOT_CONFORM | GDT_ACCESS_RW_READABLE_FOR_CODE_WRITABLE_FOR_DATA | GDT_ACCESS_A_ACCESSED, GDT_FLAG_32BIT_MODE | GDT_FLAG_PAGE_MODE); // Kernel code
|
||||||
.base = 0, .limit = 0xFFFFF, .access_byte = 0x9A, .flags = 0xC};
|
set_gdt_entry_value(gdt_entries + 0x10, 0, 0xFFFFF, GDT_ACCESS_P_VALID | GDT_ACCESS_DPL_KERNEL_MODE | GDT_ACCESS_S_CODE_OR_DATA | GDT_ACCESS_E_NOT_EXECUTABLE | GDT_ACCESS_DC_NOT_CONFORM | GDT_ACCESS_RW_READABLE_FOR_CODE_WRITABLE_FOR_DATA | GDT_ACCESS_A_ACCESSED, GDT_FLAG_32BIT_MODE | GDT_FLAG_PAGE_MODE); // Kernel data
|
||||||
encodeGdtEntry(gdt_entries[1], gdt_entry_kernel_mode_code_segment);
|
set_gdt_entry_value(gdt_entries + 0x18, 0, 0x0, GDT_ACCESS_P_VALID | GDT_ACCESS_DPL_KERNEL_MODE | GDT_ACCESS_S_CODE_OR_DATA | GDT_ACCESS_E_NOT_EXECUTABLE | GDT_ACCESS_DC_CONFORM |GDT_ACCESS_RW_READABLE_FOR_CODE_WRITABLE_FOR_DATA | GDT_ACCESS_A_ACCESSED, GDT_FLAG_32BIT_MODE | GDT_FLAG_PAGE_MODE); // Kernel stack
|
||||||
|
|
||||||
struct gdt_entry gdt_entry_kernel_mode_data_segment = {
|
set_gdt_entry_value(gdt_entries + 0x20, 0, 0xFFFFF, GDT_ACCESS_P_VALID | GDT_ACCESS_DPL_USER_MODE | GDT_ACCESS_S_CODE_OR_DATA | GDT_ACCESS_E_EXECUTABLE | GDT_ACCESS_DC_CONFORM | GDT_ACCESS_RW_READABLE_FOR_CODE_WRITABLE_FOR_DATA | GDT_ACCESS_A_ACCESSED, GDT_FLAG_32BIT_MODE | GDT_FLAG_PAGE_MODE); // User code
|
||||||
.base = 0, .limit = 0xFFFFF, .access_byte = 0x92, .flags = 0xC};
|
set_gdt_entry_value(gdt_entries + 0x28, 0, 0xFFFFF, GDT_ACCESS_P_VALID | GDT_ACCESS_DPL_USER_MODE | GDT_ACCESS_S_CODE_OR_DATA | GDT_ACCESS_E_NOT_EXECUTABLE | GDT_ACCESS_DC_NOT_CONFORM | GDT_ACCESS_RW_READABLE_FOR_CODE_WRITABLE_FOR_DATA | GDT_ACCESS_A_ACCESSED, GDT_FLAG_32BIT_MODE | GDT_FLAG_PAGE_MODE); // User data
|
||||||
encodeGdtEntry(gdt_entries[2], gdt_entry_kernel_mode_data_segment);
|
set_gdt_entry_value(gdt_entries + 0x30, 0, 0xFFFFF, GDT_ACCESS_P_VALID | GDT_ACCESS_DPL_USER_MODE | GDT_ACCESS_S_CODE_OR_DATA | GDT_ACCESS_E_NOT_EXECUTABLE | GDT_ACCESS_DC_CONFORM | GDT_ACCESS_RW_READABLE_FOR_CODE_WRITABLE_FOR_DATA | GDT_ACCESS_A_ACCESSED, GDT_FLAG_32BIT_MODE | GDT_FLAG_PAGE_MODE); // User stack
|
||||||
|
|
||||||
struct gdt_entry gdt_entry_kernel_mode_stack_segment = { .base = 0x0,
|
set_gdt(((uint32_t) gdtr));
|
||||||
.limit = 0x0,
|
|
||||||
.access_byte = 0x97,
|
|
||||||
.flags = 0x0D };
|
|
||||||
encodeGdtEntry(gdt_entries[3], gdt_entry_kernel_mode_stack_segment);
|
|
||||||
|
|
||||||
struct gdt_entry gdt_entry_user_mode_code_segment = {
|
|
||||||
.base = 0, .limit = 0xFFFFF, .access_byte = 0xFA, .flags = 0xC};
|
|
||||||
encodeGdtEntry(gdt_entries[4], gdt_entry_user_mode_code_segment);
|
|
||||||
|
|
||||||
struct gdt_entry gdt_entry_user_mode_data_segment = {
|
|
||||||
.base = 0, .limit = 0xFFFFF, .access_byte = 0xF2, .flags = 0xC};
|
|
||||||
encodeGdtEntry(gdt_entries[5], gdt_entry_user_mode_data_segment);
|
|
||||||
|
|
||||||
struct gdt_entry gdt_entry_user_mode_stack_segment = { .base = 0x0,
|
|
||||||
.limit = 0x0,
|
|
||||||
.access_byte = 0xF7,
|
|
||||||
.flags = 0x0D };
|
|
||||||
encodeGdtEntry(gdt_entries[6], gdt_entry_user_mode_stack_segment);
|
|
||||||
|
|
||||||
memcpy((void *)gdtr.base, (void *)gdt_entries, (size_t)GDT_SIZE);
|
|
||||||
|
|
||||||
/* load the gdtr registry */
|
|
||||||
asm("lgdtl (gdtr)");
|
|
||||||
|
|
||||||
/* initiliaz the segments */
|
|
||||||
asm(" movw $0x10, %ax \n \
|
|
||||||
movw %ax, %ds \n \
|
|
||||||
movw %ax, %es \n \
|
|
||||||
movw %ax, %fs \n \
|
|
||||||
movw %ax, %gs \n \
|
|
||||||
ljmp $0x08, $next \n \
|
|
||||||
next: \n");
|
|
||||||
}
|
}
|
||||||
|
18
src/gdt/set_gdt.s
Normal file
18
src/gdt/set_gdt.s
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
.intel_syntax noprefix
|
||||||
|
|
||||||
|
.section .text
|
||||||
|
.global set_gdt
|
||||||
|
|
||||||
|
set_gdt:
|
||||||
|
mov eax, [esp+4] // 1st parameter : pointer to the IDT
|
||||||
|
lgdt [eax]
|
||||||
|
mov ax, 0x10 // 0x10 is the offset in the GDT to our data segment
|
||||||
|
mov ds, ax // Load all data segment selectors
|
||||||
|
mov fs, ax
|
||||||
|
mov gs, ax
|
||||||
|
mov es, ax
|
||||||
|
mov ax, 0x18 // 0x18 is the offset in the GDT to our kernel stack
|
||||||
|
mov ss, ax
|
||||||
|
jmp 0x08:.flush // 0x08 is the offset to our code segment: far jump on it
|
||||||
|
.flush:
|
||||||
|
ret
|
@ -1,6 +1,8 @@
|
|||||||
#include "gdt.h"
|
#include "gdt.h"
|
||||||
#include "shell.h"
|
#include "shell.h"
|
||||||
#include "terminal.h"
|
#include "terminal.h"
|
||||||
|
#include "power.h"
|
||||||
|
#include "gdt.h"
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
@ -22,6 +24,6 @@ void kernel_main(void)
|
|||||||
/* Initialize terminal interface */
|
/* Initialize terminal interface */
|
||||||
terminal_initialize();
|
terminal_initialize();
|
||||||
|
|
||||||
/* initGdt(); */
|
initGdt();
|
||||||
shell_init();
|
shell_init();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user