This is my code:
gdtc.c:
Code: Select all
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
struct GDT {
uint32_t base;
uint32_t limit;
uint8_t type;
uint8_t flags;
};
extern void setGdt(uint8_t* limit, uint32_t base);
extern void reloadSegments(void);
void encodeGdtEntry(uint8_t *target, struct GDT source) {
if (source.limit > 0xFFFFF) {k_print("GDT cannot encode limits larger than 0xFFFFF");}
target[0] = source.limit & 0xFF;
target[1] = (source.limit >> 8) & 0xFF;
target[6] = (source.limit >> 16) & 0x0F;
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.flags << 4);
}
void gdt_init(uint8_t* buffer) {
struct GDT GdtEntries[5] = {
{0, 0, 0, 0}, // Selector 0x00 cannot be used
{0, 0xfffff, 0x9A, 0xC},// Selector 0x08 will be our code
{0, 0xfffff, 0x92, 0xC},// Selector 0x10 will be our data
{0, 0xfffff, 0xFA, 0xC},// Selector 0x18 will be user code
{0, 0xfffff, 0xF2, 0xC} // Selector 0x20 will be user data
};
for (int i = 0; i < 5; i++) encodeGdtEntry(buffer+i*8, GdtEntries[i]);
setGdt(buffer, 255);
reloadSegments();
}
Code: Select all
global setGdt
global reloadSegments
section .data:
gdtr DW 0 ; For limit storage
DD 0 ; For base storage
section .text
setGdt:
MOV AX, [esp + 4]
MOV [gdtr], AX
MOV EAX, [ESP + 8]
MOV [gdtr + 2], EAX
LGDT [gdtr]
RET
reloadSegments:
; Reload CS register containing code selector:
JMP 0x08:.reload_CS ; reboot occurs here
.reload_CS:
; Reload data segment registers:
MOV AX, 0x10 ; 0x10 is a stand-in for your data segment
MOV DS, AX
MOV ES, AX
MOV FS, AX
MOV GS, AX
MOV SS, AX
RET
Code: Select all
void gdt_init(uint8_t* buffer);
uint8_t gdt_buffer[256];
void kernel_main(void) {
for (int i = 0; i<256; i++) gdt_buffer[i] = 0;
gdt_init(gdt_buffer);
// rest of code
}