Reload GDT and segments from C in protected mode.

parent fee52c2e
Pipeline #59300467 failed with stages
in 64 minutes and 50 seconds
......@@ -15,6 +15,8 @@
#ifndef __ASSERTION_FAILED
#define __ASSERTION_FAILED
int __assertion_failed(const char *a, const char *func, const char *file, int line);
#include "stdio.h"
#include "stdlib.h"
......
#include <stdint.h>
#include <assert.h>
#include <stdio.h>
#include <string.h>
struct gdt_entry {
unsigned int limit_low : 16;
unsigned int base_low : 24;
// Access byte
unsigned int accessed : 1;
unsigned int read_write : 1; // Readable for code, writable for data
unsigned int conforming : 1; // Conforming for code, expand down for data
unsigned int code : 1; // 1 for code, 0 for data
unsigned int type : 1; // 1 for code/data, 0 for system segments (like TSS)
unsigned int DPL : 2; //priviledge level
unsigned int present : 1;
// Flags
unsigned int limit_high : 4;
unsigned int always_0 : 2;
unsigned int size : 1; // 1 for 32 bits, 0 for 16 bits
unsigned int gran : 1; // 1 for 4k page addressing, 0 for byte addressing
unsigned int base_high : 8;
} __attribute__((packed));
struct gdt_desc {
uint16_t size;
struct gdt_entry *offset;
} __attribute__((packed));
void reload_gdt(struct gdt_entry *gdt, int entry_num) {
struct gdt_desc desc;
desc.size = entry_num * 8 - 1;
desc.offset = gdt;
asm volatile("lgdt %0 \n\t"
"push $0x10 \n\t"
"push $reload_cs \n\t"
// TCC does not know retf
".byte 0xcb \n\t"
"reload_cs: \n\t"
"mov $0x18, %%ax \n\t"
// TCC generates a 0x66 prefix that does not look like right
/*"mov %%ax, %%ds \n\t"
"mov %%ax, %%es \n\t"
"mov %%ax, %%fs \n\t"
"mov %%ax, %%gs \n\t"
"mov %%ax, %%ss \n\t"*/
".byte 0x8e, 0xd8 \n\t"
".byte 0x8e, 0xc0 \n\t"
".byte 0x8e, 0xe0 \n\t"
".byte 0x8e, 0xe8 \n\t"
".byte 0x8e, 0xd0 \n\t"
: : "m" (desc));
printf("Still alive after reloading code and data segments!\n");
}
// Load GDT, code and data segments according to Linux Boot Protocol
void load_linux_gdt() {
assert(sizeof(struct gdt_desc) == 6);
assert(sizeof(struct gdt_entry) == 8);
// Random address, hoping that it does not bother anybody
struct gdt_entry *gdt = (struct gdt_entry*) 0x800;
memset(gdt, 0, sizeof(gdt[0]) * 4);
// 0x10: code segment
gdt[2].limit_low = 0xffff;
gdt[2].base_low = 0x000000;
gdt[2].accessed = 0;
gdt[2].read_write = 1;
gdt[2].conforming = 0;
gdt[2].code = 1;
gdt[2].type = 1;
gdt[2].DPL = 0;
gdt[2].present = 1;
gdt[2].limit_high = 0xf;
gdt[2].size = 1;
gdt[2].gran = 1;
gdt[2].base_high = 0x00;
// 0x18: data segment
gdt[3].limit_low = 0xffff;
gdt[3].base_low = 0x000000;
gdt[3].accessed = 0;
gdt[3].read_write = 1;
gdt[3].conforming = 0;
gdt[3].code = 0;
gdt[3].type = 1;
gdt[3].DPL = 0;
gdt[3].present = 1;
gdt[3].limit_high = 0xf;
gdt[3].size = 1;
gdt[3].gran = 1;
gdt[3].base_high = 0x00;
reload_gdt(gdt, 4);
}
int main() {
printf("Hello, continuing second world!\n");
load_linux_gdt();
return 0;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment