Fixed small errors in PIC signalling, added code for allocation and MMIO mapping

This commit is contained in:
Conál Paxton 2026-02-15 05:55:36 -05:00
parent 4ca9447efa
commit d4e1c29f07
19 changed files with 1324 additions and 734 deletions

BIN
bin/os

Binary file not shown.

4
bochs.bxrc Normal file
View File

@ -0,0 +1,4 @@
vga: extension=vgahw
ata0-master: type=disk, path="image.hdd", mode=flat
boot: disk
memory: guest=1024, host=1024

View File

@ -1,3 +0,0 @@
vga: extension=vgahw
display_library: x, options="gui_debug"

26
flake.lock generated
View File

@ -1,26 +0,0 @@
{
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1770057536,
"narHash": "sha256-Y/Dqu+7StqRVlzQEbow5l2Ws02P9IrHO3eVnpVWbLTE=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "79faf5ae0424fe8cd1d07064a513667e6b6ae65a",
"type": "github"
},
"original": {
"owner": "NixOS",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"nixpkgs": "nixpkgs"
}
}
},
"root": "root",
"version": 7
}

BIN
image.hdd

Binary file not shown.

0
image.hdd.lock Normal file
View File

Binary file not shown.

View File

@ -1,6 +1,7 @@
obj/src/main.c.o: src/main.c src/../include/limine.h src/acpi.h \ obj/src/main.c.o: src/main.c src/../include/limine.h src/acpi.h \
src/common.h src/print.h src/common.h src/alloc.h src/print.h
src/../include/limine.h: src/../include/limine.h:
src/acpi.h: src/acpi.h:
src/common.h: src/common.h:
src/alloc.h:
src/print.h: src/print.h:

Binary file not shown.

View File

@ -1,17 +1,17 @@
#include "common.h" #include "common.h"
#include "print.h" #include "print.h"
#include "../include/limine.h" #include "../include/limine.h"
// credit to dreamportdev's OSDev-Notes and the OSDev Wiki for table layouts // credit to dreamportdev's OSDev-Notes and the OSDev Wiki for table layouts
// //
#include "acpi.h" #include "acpi.h"
#define RSDT_SIGNATURE "RSDT" #define RSDT_SIGNATURE "RSDT"
#define XSDT_SIGNATURE "XSDT" #define XSDT_SIGNATURE "XSDT"
static struct acpi_rsdt* rsdt; static struct acpi_rsdt* rsdt;
struct acpi_rsdp_header* rsdp; struct acpi_rsdp_header* rsdp;

View File

@ -1,44 +1,44 @@
#pragma once #pragma once
#include "common.h" #include "common.h"
#define RSDP_SIGNATURE "RSDT PTR " #define RSDP_SIGNATURE "RSDT PTR "
pstruct acpi_rsdp_header { pstruct acpi_rsdp_header {
u8 signature[8]; u8 signature[8];
u8 checksum; u8 checksum;
u8 OEMID[6]; u8 OEMID[6];
u8 revision; u8 revision;
/* /*
union { union {
struct acpi_rsdt* rsdt :32; struct acpi_rsdt* rsdt :32;
struct acpi_xsdt* xsdt :32; struct acpi_xsdt* xsdt :32;
} ptr; } ptr;
*/ */
u32 ptr32; u32 ptr32;
// v2 // v2
u32 len; u32 len;
u64 ptr64; u64 ptr64;
u8 extended_checksum; u8 extended_checksum;
u8 resv[3]; u8 resv[3];
}; };
struct acpi_rsdt { struct acpi_rsdt {
u8 signature[4]; u8 signature[4];
u32 len; u32 len;
u8 revision; u8 revision;
u8 checksum; u8 checksum;
u8 OEMID[6]; u8 OEMID[6];
u8 OEM_table_id[8]; u8 OEM_table_id[8];
u32 OEM_revision; u32 OEM_revision;
u32 creator_id; u32 creator_id;
u32 creator_revision; u32 creator_revision;
union { union {
u32 addrs32[]; u32 addrs32[];
u64 addrs64[]; u64 addrs64[];
}; };
}; };
extern struct acpi_rsdp_header* rsdp; extern struct acpi_rsdp_header* rsdp;

196
src/alloc.c Normal file
View File

@ -0,0 +1,196 @@
#include "alloc.h"
#include "common.h"
#include "print.h"
#include "../include/limine.h"
__attribute__((used, section(".limine_requests")))
static volatile struct limine_memmap_request mem_req = {
.id = LIMINE_MEMMAP_REQUEST_ID,
.revision = 0,
};
extern u32 fg, bg;
static void print_memmap_entry(struct limine_memmap_entry* entry) {
u32 savefg = fg;
u32 savebg = bg;
static const char* type_strs[] = {
"Usable",
"Reserved",
"ACPI Reclaimable",
"ACPI NVS",
"BAD!!!",
"Bootloader Reclaimable",
"Executable and Modules",
"Framebuffer",
"ACPI Tables",
};
static u32 type_colors[] = {
0x00AF00,
0xAF1F00,
0x7f7f00,
0x7f7f00,
0xFF0000,
0x007f7f,
0x408000,
0x0000FF,
0x00FF00
};
bg = type_colors[entry->type];
fg = ~bg;
u64 addr = entry->base;
u64 end = addr + entry->length;
print("[");
print(type_strs[entry->type]);
print("]");
print64(addr);
print(" - ");
print64(end);
print("\n");
fg = savefg;
bg = savebg;
}
static size_t total_pages;
static u8* alloc_start;
static u8* alloc_end;
static u8* alloc_next;
static u64* alloc_bitmap;
void alloc_init() {
print("Initializing Page Allocator\n");
if(!mem_req.response) {
print("Failed to get memory map :(\n)");
hang();
}
u64 largest_base = 0;
size_t largest_size = 0;
for(size_t i = 0; i < mem_req.response->entry_count; i++) {
struct limine_memmap_entry* entry = mem_req.response->entries[i];
print_memmap_entry(entry);
if(entry->type == LIMINE_MEMMAP_USABLE) {
if(entry->length > largest_size) {
largest_base = entry->base;
largest_size = entry->length;
print("\t\\LARGEST USABLE: ");
print64(entry->length >> 20);
print("MiB\n");
}
}
}
if(!largest_size) {
print("Couldn't find a free page!!!\n");
hang();
}
total_pages = largest_size / PAGE_SIZE;
size_t usage_bitmap_size = (total_pages + 7) / 8;
total_pages -= (usage_bitmap_size + PAGE_SIZE-1) / PAGE_SIZE;
alloc_bitmap = (u64*)(phys_to_virt(largest_base));
alloc_start = (u8*)(phys_to_virt(largest_base + usage_bitmap_size));
alloc_next = alloc_start;
alloc_end = (u8*)(phys_to_virt(largest_base + largest_size));
}
static size_t page(void* addr) {
return ((u8*)addr - alloc_start) / PAGE_SIZE;
}
static void* addr(size_t page) {
return alloc_start + page*PAGE_SIZE;
}
static void usepage(size_t page) {
size_t idx = page / 64;
size_t bit = page & 63;
alloc_bitmap[idx] |= (1 << bit);
}
static void usepagerange(size_t page, size_t len) {
for(size_t i = 0; i < len; len++) {
usepage(i + page);
}
}
static void unusepage(size_t page) {
size_t idx = page / 64;
size_t bit = page & 63;
alloc_bitmap[idx] &= ~(1 << bit);
}
static void unusepagerange(size_t page, size_t len) {
for(size_t i = 0; i < len; len++) {
unusepage(i+page);
}
}
static u8 getpageusage(size_t page) {
return (alloc_bitmap[page / 8] >> (page & 7)) & 1;
}
void dealloc(void* addr, size_t size) {
// adjust to page size
size_t pages = (size+PAGE_SIZE-1) / PAGE_SIZE;
unusepagerange(page(addr), pages);
}
void* alloc(size_t size) {
size_t pages = (size + PAGE_SIZE - 1) / PAGE_SIZE;
size_t page = 0;
if(pages == 0 || pages >= total_pages) {
return NULL;
}
size_t consecutive = 0;
for(size_t i = 0; i < pages; i++) {
u64 word = alloc_bitmap[i];
if(word == 0) {
if(!consecutive)
page = i * 64;
consecutive += 64;
if(consecutive >= pages) {
usepagerange(page, pages);
return addr(page);
}
continue;
}
if(word == ~0ULL) {
consecutive = 0;
page = -1;
}
for(size_t bit = 0; bit < 64; bit++) {
if((word & (1ULL << bit)) == 0) {
if(!consecutive)
page = i * 64 + bit;
if(++consecutive >= pages) {
usepagerange(page, pages);
return addr(pages);
}
} else {
consecutive = 0;
page = -1;
}
}
}
return NULL;
}

16
src/alloc.h Normal file
View File

@ -0,0 +1,16 @@
#pragma once
#include "common.h"
static const size_t PAGE_SIZE = (1 << 12);
void alloc_init();
void* alloc(size_t size);
void dealloc(void* arg, size_t size);
static inline u64 virt_to_phys(void* virt) {
return (u64)virt - hhdm_offset;
}
static inline void* phys_to_virt(u64 phys) {
return (void*)(phys + hhdm_offset);
}

View File

@ -1,73 +1,131 @@
#include "common.h" #include "common.h"
#include "print.h" #include "print.h"
#include "map.h"
// stub of a PIC layout, we don't need the whole thing
// as we only care about initializing it to disable it // stub of a PIC layout, we don't need the whole thing
enum { // as we only care about initializing it to disable it
PIC_COMM_MASTER = 0x20, enum {
PIC_COMM_SLAVE = 0x21, PIC_COMM_MASTER = 0x20,
PIC_DATA_MASTER = 0xA0, PIC_COMM_SLAVE = 0xA0,
PIC_DATA_SLAVE = 0xA1, PIC_DATA_MASTER = 0x21,
}; PIC_DATA_SLAVE = 0xA1,
};
static void pic_disable() {
outb(PIC_DATA_MASTER, ~0); #define IOAPIC_REG_REDIR(n) (0x10 + 2(n))
outb(PIC_DATA_SLAVE, ~0);
} enum {
IOAPIC_REG_SELECT = 0x00,
static inline u64 rdmsr(u32 msr) { IOAPIC_REG_WINDOW = 0x10,
u32 hi, lo; };
asm volatile (
"rdmsr" // I/O APIC redirection entry bits
: "=a"(lo), "=d"(hi) #define IOAPIC_DST_PHYS (0 << 11)
: "c"(msr) #define IOAPIC_DST_LOGICAL (1 << 11)
); #define IOAPIC_MASKED (1 << 16)
#define IOAPIC_LVL_TRIGG (1 << 15)
return (((u64)hi) << 32) | (u64)lo; #define IOAPIC_EDGE_TRIGG (0 << 15)
} #define IOAPIC_ACTIVE_LOW (1 << 13)
#define IOAPIC_ACTIVE_HIGH (0 << 13)
static inline void wrmsr(u32 msr, u64 val) {
u32 eax = (u32) val; static void pic_init() {
u32 edx = (u32) (val >> 32); // Start initialization sequence
asm volatile ( outb(PIC_COMM_MASTER, 0x11); // ICW1: Initialize in cascading mode
"wrmsr" outb(PIC_DATA_MASTER, 0x20); // ICW2: Master PIC vector offset
: outb(PIC_DATA_MASTER, 0x04); // ICW3: Slave PIC at IRQ2
: "c"(msr), "a" (eax), "d" (edx) outb(PIC_DATA_MASTER, 0x01); // ICW4: 8086/88 (MCS-80 compatible)
);
} outb(PIC_COMM_SLAVE, 0x11); // ICW1: Initialize slave PIC
outb(PIC_DATA_SLAVE, 0x28); // ICW2: Slave PIC vector offset
outb(PIC_DATA_SLAVE, 0x02); // ICW3: It's connected to master PIC
static u64 apic_base; outb(PIC_DATA_SLAVE, 0x01); // ICW4: 8086/88 mode
u64 apic_get_local_base() { // Mask all interrupts
const u8 APIC_BASE_MSR = 0x1B; outb(PIC_DATA_MASTER, 0xFF);
outb(PIC_DATA_SLAVE, 0xFF);
u64 msr = rdmsr(APIC_BASE_MSR); }
return (apic_base = (msr & 0xfffff000)); static void pic_disable() {
} pic_init();
outb(PIC_DATA_MASTER, ~0);
static u64 apic_set_local_base(u64 base) { outb(PIC_DATA_SLAVE, ~0);
const u8 APIC_BASE_MSR = 0x1B; }
wrmsr(APIC_BASE_MSR, base & 0xfffff000); static inline u64 rdmsr(u32 msr) {
u32 hi, lo;
return base & 0xfffff000; asm volatile (
} "rdmsr"
: "=a"(lo), "=d"(hi)
static u32* apic_reg(u32 reg) { : "c"(msr)
return (u32*) (apic_base + reg); );
}
return (((u64)hi) << 32) | (u64)lo;
void apic_enable() { }
pic_disable();
print("\nPIC Disabled\n"); static inline void wrmsr(u32 msr, u64 val) {
apic_set_local_base(apic_get_local_base()); u32 eax = (u32) val;
volatile u32* reg = apic_reg(0xF0); u32 edx = (u32) (val >> 32);
print("Local Base Set\nReg 0xF0 at 0x"); asm volatile (
print64((u64) reg); "wrmsr"
// set enable flag :
*reg = (*reg | 0x100); : "c"(msr), "a" (eax), "d" (edx)
print("\nReg written\n"); );
} }
static u64 apic_base;
u64 apic_get_local_base() {
const u8 APIC_BASE_MSR = 0x1B;
u64 msr = rdmsr(APIC_BASE_MSR);
return (apic_base = (msr & 0xfffff000));
}
static u64 apic_set_local_base(u64 base) {
const u8 APIC_BASE_MSR = 0x1B;
wrmsr(APIC_BASE_MSR, base & 0xfffff000);
return base & 0xfffff000;
}
static u32* apic_reg(u32 reg) {
return (u32*) (apic_base + reg);
}
void apic_enable() {
pic_disable();
print("\nPIC Disabled\n");
apic_set_local_base(apic_get_local_base());
if(!map_mmio((u64)apic_base, 1<<12)) {
print("Failed to map APIC registers!\n");
hang();
}
volatile u32* reg = apic_reg(0xF0);
print("Reg 0xF0 at 0x");
print64((u64) reg);
// set enable flag
*reg = (*reg | 0x100);
print("\nReg written\n");
}
static u32* ioapic_base;
void ioapic_write(u8 reg, u32 value) {
ioapic_base[IOAPIC_REG_SELECT / 4] = reg;
ioapic_base[IOAPIC_REG_WINDOW / 4] = value;
}
u32 ioapic_read(u8 reg) {
ioapic_base[IOAPIC_REG_SELECT / 4] = reg;
return ioapic_base[IOAPIC_REG_WINDOW / 4];
}
void ioapic_init() {
}

View File

@ -1,42 +1,42 @@
#pragma once #pragma once
#include <stdbool.h> #include <stdbool.h>
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#define pstruct struct __attribute__((packed)) #define pstruct struct __attribute__((packed))
typedef uint8_t u8; typedef uint8_t u8;
typedef uint16_t u16; typedef uint16_t u16;
typedef uint32_t u32; typedef uint32_t u32;
typedef uint64_t u64; typedef uint64_t u64;
typedef int8_t i8; typedef int8_t i8;
typedef int16_t i16; typedef int16_t i16;
typedef int32_t i32; typedef int32_t i32;
typedef int64_t i64; typedef int64_t i64;
static inline void INT(int n) { static inline void INT(int n) {
asm volatile ( asm volatile (
"int %0" "int %0"
: :
: "i"(n) : "i"(n)
); );
} }
static inline void outb(u16 port, u8 value) { static inline void outb(u16 port, u8 value) {
asm volatile ("outb %0, %1" : : "a"(value), "Nd"(port)); asm volatile ("outb %0, %1" : : "a"(value), "Nd"(port));
} }
static inline void outw(u16 port, u16 value) { static inline void outw(u16 port, u16 value) {
asm volatile ("outw %0, %1" : : "a"(value), "Nd"(port)); asm volatile ("outw %0, %1" : : "a"(value), "Nd"(port));
} }
static inline void outd(u16 port, u32 value) { static inline void outd(u16 port, u32 value) {
asm volatile ("outl %0, %1" : : "a"(value), "Nd"(port)); asm volatile ("outl %0, %1" : : "a"(value), "Nd"(port));
} }
void* memcpy(void* restrict dst, const void* src, size_t n); void* memcpy(void* dst, const void* src, size_t n);
void* memset(void* s, int c, size_t n); void* memset(void* s, int c, size_t n);
void* memmove(void* dst, const void* src, size_t n); void* memmove(void* dst, const void* src, size_t n);
int memcmp(const void* s1, const void* s2, size_t n); int memcmp(const void* s1, const void* s2, size_t n);
void hang();
extern u64 hhdm_offset; extern u64 hhdm_offset;

564
src/int.c
View File

@ -1,282 +1,282 @@
#include <stdint.h> #include <stdint.h>
// for debugging // for debugging
#include "print.h" #include "print.h"
#include "common.h" #include "common.h"
// for trap debugging // for trap debugging
u64 dbg_var = 0; u64 dbg_var = 0;
pstruct int_desc { pstruct int_desc {
u16 addr_low; u16 addr_low;
u16 selector; u16 selector;
u8 ist; u8 ist;
u8 flags; u8 flags;
u16 addr_mid; u16 addr_mid;
u32 addr_high; u32 addr_high;
u32 resv; u32 resv;
}; };
enum INT_DESC_FLAGS { enum INT_DESC_FLAGS {
ID_GATE_INT = 0b00001110, ID_GATE_INT = 0b00001110,
ID_GATE_TRAP = 0b00001111, ID_GATE_TRAP = 0b00001111,
ID_DPL = 0b00100000, ID_DPL = 0b00100000,
ID_PRESENT = 0b10000000, ID_PRESENT = 0b10000000,
}; };
#define CODE64_SELECTOR 0x28 #define CODE64_SELECTOR 0x28
struct int_desc idt[256]; struct int_desc idt[256];
void set_idt(u8 vect, void* handler, u8 dpl) { void set_idt(u8 vect, void* handler, u8 dpl) {
struct int_desc* ent = &idt[vect]; struct int_desc* ent = &idt[vect];
u64 addr = (u64) handler; u64 addr = (u64) handler;
ent->addr_low = addr & 0xFFFF; ent->addr_low = addr & 0xFFFF;
ent->addr_mid = (addr >> 16) & 0xFFFF; ent->addr_mid = (addr >> 16) & 0xFFFF;
ent->addr_high = addr >> 32; ent->addr_high = addr >> 32;
ent->selector = CODE64_SELECTOR; ent->selector = CODE64_SELECTOR;
ent->flags = ID_GATE_INT | dpl*ID_DPL | ID_PRESENT; ent->flags = ID_GATE_INT | dpl*ID_DPL | ID_PRESENT;
ent->ist = 0; ent->ist = 0;
} }
pstruct idtr { pstruct idtr {
u16 limit; u16 limit;
u64 base; u64 base;
}; };
#define IDTR_LIMIT (sizeof(struct int_desc)*256 - 1) #define IDTR_LIMIT (sizeof(struct int_desc)*256 - 1)
void load_idt(void* addr) { void load_idt(void* addr) {
struct idtr ir = (struct idtr) { struct idtr ir = (struct idtr) {
.limit = IDTR_LIMIT, .limit = IDTR_LIMIT,
.base = (u64) addr, .base = (u64) addr,
}; };
asm volatile("lidt %0" :: "m"(ir)); asm volatile("lidt %0" :: "m"(ir));
} }
extern void draw(u8 vect); extern void draw(u8 vect);
struct cpu_ctx { struct cpu_ctx {
u64 r15, r14, r13, r12, r11, r10, r9, r8, rdi, rsi, rdx, rcx, rbx, rax; u64 r15, r14, r13, r12, r11, r10, r9, r8, rdi, rsi, rdx, rcx, rbx, rax;
u64 vect; u64 vect;
u64 err; u64 err;
u64 iret_rip; u64 iret_rip;
u64 iret_cs; u64 iret_cs;
u64 iret_flags; u64 iret_flags;
u64 iret_rsp; u64 iret_rsp;
u64 iret_ss; u64 iret_ss;
}; };
struct cpu_ctx* interrupt_dispatch(struct cpu_ctx* ctx) { struct cpu_ctx* interrupt_dispatch(struct cpu_ctx* ctx) {
print("\n[IRQ "); print("\n[IRQ ");
print8(ctx->vect); print8(ctx->vect);
print("] with message: "); print("] with message: ");
print64(dbg_var); print64(dbg_var);
print("\n"); print("\n");
while(1); while(1);
return ctx; return ctx;
} }
__attribute__((naked)) __attribute__((naked))
void int_stub(void) { void int_stub(void) {
__asm__ volatile ( __asm__ volatile (
"push %%rax\n" "push %%rax\n"
"push %%rbx\n" "push %%rbx\n"
"push %%rcx\n" "push %%rcx\n"
"push %%rdx\n" "push %%rdx\n"
"push %%rsi\n" "push %%rsi\n"
"push %%rdi\n" "push %%rdi\n"
"push %%r8\n" "push %%r8\n"
"push %%r9\n" "push %%r9\n"
"push %%r10\n" "push %%r10\n"
"push %%r11\n" "push %%r11\n"
"push %%r12\n" "push %%r12\n"
"push %%r13\n" "push %%r13\n"
"push %%r14\n" "push %%r14\n"
"push %%r15\n" "push %%r15\n"
"mov %%rsp, %%rdi\n" "mov %%rsp, %%rdi\n"
"call interrupt_dispatch\n" "call interrupt_dispatch\n"
"mov %%rax, %%rsp\n" "mov %%rax, %%rsp\n"
"pop %%r15\n" "pop %%r15\n"
"pop %%r14\n" "pop %%r14\n"
"pop %%r13\n" "pop %%r13\n"
"pop %%r12\n" "pop %%r12\n"
"pop %%r11\n" "pop %%r11\n"
"pop %%r10\n" "pop %%r10\n"
"pop %%r9\n" "pop %%r9\n"
"pop %%r8\n" "pop %%r8\n"
"pop %%rdi\n" "pop %%rdi\n"
"pop %%rsi\n" "pop %%rsi\n"
"pop %%rdx\n" "pop %%rdx\n"
"pop %%rcx\n" "pop %%rcx\n"
"pop %%rbx\n" "pop %%rbx\n"
"pop %%rax\n" "pop %%rax\n"
"add $16, %%rsp\n" "add $16, %%rsp\n"
"iretq\n" "iretq\n"
: :
: :
: "memory" : "memory"
); );
} }
// Macro to generate interrupt stubs without error codes (push dummy 0) // Macro to generate interrupt stubs without error codes (push dummy 0)
#define ISR_NO_ERR(num) \ #define ISR_NO_ERR(num) \
__attribute__((naked)) void isr##num(void) { \ __attribute__((naked)) void isr##num(void) { \
asm volatile( \ asm volatile( \
"push $0\n" \ "push $0\n" \
"push %0\n" \ "push %0\n" \
"jmp int_stub\n" \ "jmp int_stub\n" \
: : "i"(num)); \ : : "i"(num)); \
} }
// Macro to generate interrupt stubs with error codes // Macro to generate interrupt stubs with error codes
#define ISR_ERR(num) \ #define ISR_ERR(num) \
__attribute__((naked)) void isr##num(void) { \ __attribute__((naked)) void isr##num(void) { \
asm volatile( \ asm volatile( \
"push %0\n" \ "push %0\n" \
"jmp int_stub\n" \ "jmp int_stub\n" \
: : "i"(num)); \ : : "i"(num)); \
} }
// CPU exceptions (0-31) // CPU exceptions (0-31)
ISR_NO_ERR(0) // Divide by zero ISR_NO_ERR(0) // Divide by zero
ISR_NO_ERR(1) // Debug ISR_NO_ERR(1) // Debug
ISR_NO_ERR(2) // NMI ISR_NO_ERR(2) // NMI
ISR_NO_ERR(3) // Breakpoint ISR_NO_ERR(3) // Breakpoint
ISR_NO_ERR(4) // Overflow ISR_NO_ERR(4) // Overflow
ISR_NO_ERR(5) // Bound range exceeded ISR_NO_ERR(5) // Bound range exceeded
ISR_NO_ERR(6) // Invalid opcode ISR_NO_ERR(6) // Invalid opcode
ISR_NO_ERR(7) // Device not available ISR_NO_ERR(7) // Device not available
ISR_ERR(8) // Double fault (pushes error code) ISR_ERR(8) // Double fault (pushes error code)
ISR_NO_ERR(9) // Coprocessor segment overrun ISR_NO_ERR(9) // Coprocessor segment overrun
ISR_ERR(10) // Invalid TSS (pushes error code) ISR_ERR(10) // Invalid TSS (pushes error code)
ISR_ERR(11) // Segment not present (pushes error code) ISR_ERR(11) // Segment not present (pushes error code)
ISR_ERR(12) // Stack-segment fault (pushes error code) ISR_ERR(12) // Stack-segment fault (pushes error code)
ISR_ERR(13) // General protection fault (pushes error code) ISR_ERR(13) // General protection fault (pushes error code)
ISR_ERR(14) // Page fault (pushes error code) ISR_ERR(14) // Page fault (pushes error code)
ISR_NO_ERR(15) // Reserved ISR_NO_ERR(15) // Reserved
ISR_NO_ERR(16) // x87 FPU error ISR_NO_ERR(16) // x87 FPU error
ISR_ERR(17) // Alignment check (pushes error code) ISR_ERR(17) // Alignment check (pushes error code)
ISR_NO_ERR(18) // Machine check ISR_NO_ERR(18) // Machine check
ISR_NO_ERR(19) // SIMD floating-point exception ISR_NO_ERR(19) // SIMD floating-point exception
ISR_NO_ERR(20) // Virtualization exception ISR_NO_ERR(20) // Virtualization exception
ISR_ERR(21) // Control protection exception (pushes error code) ISR_ERR(21) // Control protection exception (pushes error code)
ISR_NO_ERR(22) // Reserved ISR_NO_ERR(22) // Reserved
ISR_NO_ERR(23) // Reserved ISR_NO_ERR(23) // Reserved
ISR_NO_ERR(24) // Reserved ISR_NO_ERR(24) // Reserved
ISR_NO_ERR(25) // Reserved ISR_NO_ERR(25) // Reserved
ISR_NO_ERR(26) // Reserved ISR_NO_ERR(26) // Reserved
ISR_NO_ERR(27) // Reserved ISR_NO_ERR(27) // Reserved
ISR_NO_ERR(28) // Reserved ISR_NO_ERR(28) // Reserved
ISR_NO_ERR(29) // Reserved ISR_NO_ERR(29) // Reserved
ISR_ERR(30) // Security exception (pushes error code) ISR_ERR(30) // Security exception (pushes error code)
ISR_NO_ERR(31) // Reserved ISR_NO_ERR(31) // Reserved
// IRQs and user-defined interrupts (32-255) // IRQs and user-defined interrupts (32-255)
ISR_NO_ERR(32) ISR_NO_ERR(33) ISR_NO_ERR(34) ISR_NO_ERR(35) ISR_NO_ERR(32) ISR_NO_ERR(33) ISR_NO_ERR(34) ISR_NO_ERR(35)
ISR_NO_ERR(36) ISR_NO_ERR(37) ISR_NO_ERR(38) ISR_NO_ERR(39) ISR_NO_ERR(36) ISR_NO_ERR(37) ISR_NO_ERR(38) ISR_NO_ERR(39)
ISR_NO_ERR(40) ISR_NO_ERR(41) ISR_NO_ERR(42) ISR_NO_ERR(43) ISR_NO_ERR(40) ISR_NO_ERR(41) ISR_NO_ERR(42) ISR_NO_ERR(43)
ISR_NO_ERR(44) ISR_NO_ERR(45) ISR_NO_ERR(46) ISR_NO_ERR(47) ISR_NO_ERR(44) ISR_NO_ERR(45) ISR_NO_ERR(46) ISR_NO_ERR(47)
ISR_NO_ERR(48) ISR_NO_ERR(49) ISR_NO_ERR(50) ISR_NO_ERR(51) ISR_NO_ERR(48) ISR_NO_ERR(49) ISR_NO_ERR(50) ISR_NO_ERR(51)
ISR_NO_ERR(52) ISR_NO_ERR(53) ISR_NO_ERR(54) ISR_NO_ERR(55) ISR_NO_ERR(52) ISR_NO_ERR(53) ISR_NO_ERR(54) ISR_NO_ERR(55)
ISR_NO_ERR(56) ISR_NO_ERR(57) ISR_NO_ERR(58) ISR_NO_ERR(59) ISR_NO_ERR(56) ISR_NO_ERR(57) ISR_NO_ERR(58) ISR_NO_ERR(59)
ISR_NO_ERR(60) ISR_NO_ERR(61) ISR_NO_ERR(62) ISR_NO_ERR(63) ISR_NO_ERR(60) ISR_NO_ERR(61) ISR_NO_ERR(62) ISR_NO_ERR(63)
ISR_NO_ERR(64) ISR_NO_ERR(65) ISR_NO_ERR(66) ISR_NO_ERR(67) ISR_NO_ERR(64) ISR_NO_ERR(65) ISR_NO_ERR(66) ISR_NO_ERR(67)
ISR_NO_ERR(68) ISR_NO_ERR(69) ISR_NO_ERR(70) ISR_NO_ERR(71) ISR_NO_ERR(68) ISR_NO_ERR(69) ISR_NO_ERR(70) ISR_NO_ERR(71)
ISR_NO_ERR(72) ISR_NO_ERR(73) ISR_NO_ERR(74) ISR_NO_ERR(75) ISR_NO_ERR(72) ISR_NO_ERR(73) ISR_NO_ERR(74) ISR_NO_ERR(75)
ISR_NO_ERR(76) ISR_NO_ERR(77) ISR_NO_ERR(78) ISR_NO_ERR(79) ISR_NO_ERR(76) ISR_NO_ERR(77) ISR_NO_ERR(78) ISR_NO_ERR(79)
ISR_NO_ERR(80) ISR_NO_ERR(81) ISR_NO_ERR(82) ISR_NO_ERR(83) ISR_NO_ERR(80) ISR_NO_ERR(81) ISR_NO_ERR(82) ISR_NO_ERR(83)
ISR_NO_ERR(84) ISR_NO_ERR(85) ISR_NO_ERR(86) ISR_NO_ERR(87) ISR_NO_ERR(84) ISR_NO_ERR(85) ISR_NO_ERR(86) ISR_NO_ERR(87)
ISR_NO_ERR(88) ISR_NO_ERR(89) ISR_NO_ERR(90) ISR_NO_ERR(91) ISR_NO_ERR(88) ISR_NO_ERR(89) ISR_NO_ERR(90) ISR_NO_ERR(91)
ISR_NO_ERR(92) ISR_NO_ERR(93) ISR_NO_ERR(94) ISR_NO_ERR(95) ISR_NO_ERR(92) ISR_NO_ERR(93) ISR_NO_ERR(94) ISR_NO_ERR(95)
ISR_NO_ERR(96) ISR_NO_ERR(97) ISR_NO_ERR(98) ISR_NO_ERR(99) ISR_NO_ERR(96) ISR_NO_ERR(97) ISR_NO_ERR(98) ISR_NO_ERR(99)
ISR_NO_ERR(100) ISR_NO_ERR(101) ISR_NO_ERR(102) ISR_NO_ERR(103) ISR_NO_ERR(100) ISR_NO_ERR(101) ISR_NO_ERR(102) ISR_NO_ERR(103)
ISR_NO_ERR(104) ISR_NO_ERR(105) ISR_NO_ERR(106) ISR_NO_ERR(107) ISR_NO_ERR(104) ISR_NO_ERR(105) ISR_NO_ERR(106) ISR_NO_ERR(107)
ISR_NO_ERR(108) ISR_NO_ERR(109) ISR_NO_ERR(110) ISR_NO_ERR(111) ISR_NO_ERR(108) ISR_NO_ERR(109) ISR_NO_ERR(110) ISR_NO_ERR(111)
ISR_NO_ERR(112) ISR_NO_ERR(113) ISR_NO_ERR(114) ISR_NO_ERR(115) ISR_NO_ERR(112) ISR_NO_ERR(113) ISR_NO_ERR(114) ISR_NO_ERR(115)
ISR_NO_ERR(116) ISR_NO_ERR(117) ISR_NO_ERR(118) ISR_NO_ERR(119) ISR_NO_ERR(116) ISR_NO_ERR(117) ISR_NO_ERR(118) ISR_NO_ERR(119)
ISR_NO_ERR(120) ISR_NO_ERR(121) ISR_NO_ERR(122) ISR_NO_ERR(123) ISR_NO_ERR(120) ISR_NO_ERR(121) ISR_NO_ERR(122) ISR_NO_ERR(123)
ISR_NO_ERR(124) ISR_NO_ERR(125) ISR_NO_ERR(126) ISR_NO_ERR(127) ISR_NO_ERR(124) ISR_NO_ERR(125) ISR_NO_ERR(126) ISR_NO_ERR(127)
ISR_NO_ERR(128) ISR_NO_ERR(129) ISR_NO_ERR(130) ISR_NO_ERR(131) ISR_NO_ERR(128) ISR_NO_ERR(129) ISR_NO_ERR(130) ISR_NO_ERR(131)
ISR_NO_ERR(132) ISR_NO_ERR(133) ISR_NO_ERR(134) ISR_NO_ERR(135) ISR_NO_ERR(132) ISR_NO_ERR(133) ISR_NO_ERR(134) ISR_NO_ERR(135)
ISR_NO_ERR(136) ISR_NO_ERR(137) ISR_NO_ERR(138) ISR_NO_ERR(139) ISR_NO_ERR(136) ISR_NO_ERR(137) ISR_NO_ERR(138) ISR_NO_ERR(139)
ISR_NO_ERR(140) ISR_NO_ERR(141) ISR_NO_ERR(142) ISR_NO_ERR(143) ISR_NO_ERR(140) ISR_NO_ERR(141) ISR_NO_ERR(142) ISR_NO_ERR(143)
ISR_NO_ERR(144) ISR_NO_ERR(145) ISR_NO_ERR(146) ISR_NO_ERR(147) ISR_NO_ERR(144) ISR_NO_ERR(145) ISR_NO_ERR(146) ISR_NO_ERR(147)
ISR_NO_ERR(148) ISR_NO_ERR(149) ISR_NO_ERR(150) ISR_NO_ERR(151) ISR_NO_ERR(148) ISR_NO_ERR(149) ISR_NO_ERR(150) ISR_NO_ERR(151)
ISR_NO_ERR(152) ISR_NO_ERR(153) ISR_NO_ERR(154) ISR_NO_ERR(155) ISR_NO_ERR(152) ISR_NO_ERR(153) ISR_NO_ERR(154) ISR_NO_ERR(155)
ISR_NO_ERR(156) ISR_NO_ERR(157) ISR_NO_ERR(158) ISR_NO_ERR(159) ISR_NO_ERR(156) ISR_NO_ERR(157) ISR_NO_ERR(158) ISR_NO_ERR(159)
ISR_NO_ERR(160) ISR_NO_ERR(161) ISR_NO_ERR(162) ISR_NO_ERR(163) ISR_NO_ERR(160) ISR_NO_ERR(161) ISR_NO_ERR(162) ISR_NO_ERR(163)
ISR_NO_ERR(164) ISR_NO_ERR(165) ISR_NO_ERR(166) ISR_NO_ERR(167) ISR_NO_ERR(164) ISR_NO_ERR(165) ISR_NO_ERR(166) ISR_NO_ERR(167)
ISR_NO_ERR(168) ISR_NO_ERR(169) ISR_NO_ERR(170) ISR_NO_ERR(171) ISR_NO_ERR(168) ISR_NO_ERR(169) ISR_NO_ERR(170) ISR_NO_ERR(171)
ISR_NO_ERR(172) ISR_NO_ERR(173) ISR_NO_ERR(174) ISR_NO_ERR(175) ISR_NO_ERR(172) ISR_NO_ERR(173) ISR_NO_ERR(174) ISR_NO_ERR(175)
ISR_NO_ERR(176) ISR_NO_ERR(177) ISR_NO_ERR(178) ISR_NO_ERR(179) ISR_NO_ERR(176) ISR_NO_ERR(177) ISR_NO_ERR(178) ISR_NO_ERR(179)
ISR_NO_ERR(180) ISR_NO_ERR(181) ISR_NO_ERR(182) ISR_NO_ERR(183) ISR_NO_ERR(180) ISR_NO_ERR(181) ISR_NO_ERR(182) ISR_NO_ERR(183)
ISR_NO_ERR(184) ISR_NO_ERR(185) ISR_NO_ERR(186) ISR_NO_ERR(187) ISR_NO_ERR(184) ISR_NO_ERR(185) ISR_NO_ERR(186) ISR_NO_ERR(187)
ISR_NO_ERR(188) ISR_NO_ERR(189) ISR_NO_ERR(190) ISR_NO_ERR(191) ISR_NO_ERR(188) ISR_NO_ERR(189) ISR_NO_ERR(190) ISR_NO_ERR(191)
ISR_NO_ERR(192) ISR_NO_ERR(193) ISR_NO_ERR(194) ISR_NO_ERR(195) ISR_NO_ERR(192) ISR_NO_ERR(193) ISR_NO_ERR(194) ISR_NO_ERR(195)
ISR_NO_ERR(196) ISR_NO_ERR(197) ISR_NO_ERR(198) ISR_NO_ERR(199) ISR_NO_ERR(196) ISR_NO_ERR(197) ISR_NO_ERR(198) ISR_NO_ERR(199)
ISR_NO_ERR(200) ISR_NO_ERR(201) ISR_NO_ERR(202) ISR_NO_ERR(203) ISR_NO_ERR(200) ISR_NO_ERR(201) ISR_NO_ERR(202) ISR_NO_ERR(203)
ISR_NO_ERR(204) ISR_NO_ERR(205) ISR_NO_ERR(206) ISR_NO_ERR(207) ISR_NO_ERR(204) ISR_NO_ERR(205) ISR_NO_ERR(206) ISR_NO_ERR(207)
ISR_NO_ERR(208) ISR_NO_ERR(209) ISR_NO_ERR(210) ISR_NO_ERR(211) ISR_NO_ERR(208) ISR_NO_ERR(209) ISR_NO_ERR(210) ISR_NO_ERR(211)
ISR_NO_ERR(212) ISR_NO_ERR(213) ISR_NO_ERR(214) ISR_NO_ERR(215) ISR_NO_ERR(212) ISR_NO_ERR(213) ISR_NO_ERR(214) ISR_NO_ERR(215)
ISR_NO_ERR(216) ISR_NO_ERR(217) ISR_NO_ERR(218) ISR_NO_ERR(219) ISR_NO_ERR(216) ISR_NO_ERR(217) ISR_NO_ERR(218) ISR_NO_ERR(219)
ISR_NO_ERR(220) ISR_NO_ERR(221) ISR_NO_ERR(222) ISR_NO_ERR(223) ISR_NO_ERR(220) ISR_NO_ERR(221) ISR_NO_ERR(222) ISR_NO_ERR(223)
ISR_NO_ERR(224) ISR_NO_ERR(225) ISR_NO_ERR(226) ISR_NO_ERR(227) ISR_NO_ERR(224) ISR_NO_ERR(225) ISR_NO_ERR(226) ISR_NO_ERR(227)
ISR_NO_ERR(228) ISR_NO_ERR(229) ISR_NO_ERR(230) ISR_NO_ERR(231) ISR_NO_ERR(228) ISR_NO_ERR(229) ISR_NO_ERR(230) ISR_NO_ERR(231)
ISR_NO_ERR(232) ISR_NO_ERR(233) ISR_NO_ERR(234) ISR_NO_ERR(235) ISR_NO_ERR(232) ISR_NO_ERR(233) ISR_NO_ERR(234) ISR_NO_ERR(235)
ISR_NO_ERR(236) ISR_NO_ERR(237) ISR_NO_ERR(238) ISR_NO_ERR(239) ISR_NO_ERR(236) ISR_NO_ERR(237) ISR_NO_ERR(238) ISR_NO_ERR(239)
ISR_NO_ERR(240) ISR_NO_ERR(241) ISR_NO_ERR(242) ISR_NO_ERR(243) ISR_NO_ERR(240) ISR_NO_ERR(241) ISR_NO_ERR(242) ISR_NO_ERR(243)
ISR_NO_ERR(244) ISR_NO_ERR(245) ISR_NO_ERR(246) ISR_NO_ERR(247) ISR_NO_ERR(244) ISR_NO_ERR(245) ISR_NO_ERR(246) ISR_NO_ERR(247)
ISR_NO_ERR(248) ISR_NO_ERR(249) ISR_NO_ERR(250) ISR_NO_ERR(251) ISR_NO_ERR(248) ISR_NO_ERR(249) ISR_NO_ERR(250) ISR_NO_ERR(251)
ISR_NO_ERR(252) ISR_NO_ERR(253) ISR_NO_ERR(254) ISR_NO_ERR(255) ISR_NO_ERR(252) ISR_NO_ERR(253) ISR_NO_ERR(254) ISR_NO_ERR(255)
// Array of all ISR handlers for easy initialization // Array of all ISR handlers for easy initialization
void* isr_table[256] = { void* isr_table[256] = {
isr0, isr1, isr2, isr3, isr4, isr5, isr6, isr7, isr0, isr1, isr2, isr3, isr4, isr5, isr6, isr7,
isr8, isr9, isr10, isr11, isr12, isr13, isr14, isr15, isr8, isr9, isr10, isr11, isr12, isr13, isr14, isr15,
isr16, isr17, isr18, isr19, isr20, isr21, isr22, isr23, isr16, isr17, isr18, isr19, isr20, isr21, isr22, isr23,
isr24, isr25, isr26, isr27, isr28, isr29, isr30, isr31, isr24, isr25, isr26, isr27, isr28, isr29, isr30, isr31,
isr32, isr33, isr34, isr35, isr36, isr37, isr38, isr39, isr32, isr33, isr34, isr35, isr36, isr37, isr38, isr39,
isr40, isr41, isr42, isr43, isr44, isr45, isr46, isr47, isr40, isr41, isr42, isr43, isr44, isr45, isr46, isr47,
isr48, isr49, isr50, isr51, isr52, isr53, isr54, isr55, isr48, isr49, isr50, isr51, isr52, isr53, isr54, isr55,
isr56, isr57, isr58, isr59, isr60, isr61, isr62, isr63, isr56, isr57, isr58, isr59, isr60, isr61, isr62, isr63,
isr64, isr65, isr66, isr67, isr68, isr69, isr70, isr71, isr64, isr65, isr66, isr67, isr68, isr69, isr70, isr71,
isr72, isr73, isr74, isr75, isr76, isr77, isr78, isr79, isr72, isr73, isr74, isr75, isr76, isr77, isr78, isr79,
isr80, isr81, isr82, isr83, isr84, isr85, isr86, isr87, isr80, isr81, isr82, isr83, isr84, isr85, isr86, isr87,
isr88, isr89, isr90, isr91, isr92, isr93, isr94, isr95, isr88, isr89, isr90, isr91, isr92, isr93, isr94, isr95,
isr96, isr97, isr98, isr99, isr100, isr101, isr102, isr103, isr96, isr97, isr98, isr99, isr100, isr101, isr102, isr103,
isr104, isr105, isr106, isr107, isr108, isr109, isr110, isr111, isr104, isr105, isr106, isr107, isr108, isr109, isr110, isr111,
isr112, isr113, isr114, isr115, isr116, isr117, isr118, isr119, isr112, isr113, isr114, isr115, isr116, isr117, isr118, isr119,
isr120, isr121, isr122, isr123, isr124, isr125, isr126, isr127, isr120, isr121, isr122, isr123, isr124, isr125, isr126, isr127,
isr128, isr129, isr130, isr131, isr132, isr133, isr134, isr135, isr128, isr129, isr130, isr131, isr132, isr133, isr134, isr135,
isr136, isr137, isr138, isr139, isr140, isr141, isr142, isr143, isr136, isr137, isr138, isr139, isr140, isr141, isr142, isr143,
isr144, isr145, isr146, isr147, isr148, isr149, isr150, isr151, isr144, isr145, isr146, isr147, isr148, isr149, isr150, isr151,
isr152, isr153, isr154, isr155, isr156, isr157, isr158, isr159, isr152, isr153, isr154, isr155, isr156, isr157, isr158, isr159,
isr160, isr161, isr162, isr163, isr164, isr165, isr166, isr167, isr160, isr161, isr162, isr163, isr164, isr165, isr166, isr167,
isr168, isr169, isr170, isr171, isr172, isr173, isr174, isr175, isr168, isr169, isr170, isr171, isr172, isr173, isr174, isr175,
isr176, isr177, isr178, isr179, isr180, isr181, isr182, isr183, isr176, isr177, isr178, isr179, isr180, isr181, isr182, isr183,
isr184, isr185, isr186, isr187, isr188, isr189, isr190, isr191, isr184, isr185, isr186, isr187, isr188, isr189, isr190, isr191,
isr192, isr193, isr194, isr195, isr196, isr197, isr198, isr199, isr192, isr193, isr194, isr195, isr196, isr197, isr198, isr199,
isr200, isr201, isr202, isr203, isr204, isr205, isr206, isr207, isr200, isr201, isr202, isr203, isr204, isr205, isr206, isr207,
isr208, isr209, isr210, isr211, isr212, isr213, isr214, isr215, isr208, isr209, isr210, isr211, isr212, isr213, isr214, isr215,
isr216, isr217, isr218, isr219, isr220, isr221, isr222, isr223, isr216, isr217, isr218, isr219, isr220, isr221, isr222, isr223,
isr224, isr225, isr226, isr227, isr228, isr229, isr230, isr231, isr224, isr225, isr226, isr227, isr228, isr229, isr230, isr231,
isr232, isr233, isr234, isr235, isr236, isr237, isr238, isr239, isr232, isr233, isr234, isr235, isr236, isr237, isr238, isr239,
isr240, isr241, isr242, isr243, isr244, isr245, isr246, isr247, isr240, isr241, isr242, isr243, isr244, isr245, isr246, isr247,
isr248, isr249, isr250, isr251, isr252, isr253, isr254, isr255, isr248, isr249, isr250, isr251, isr252, isr253, isr254, isr255,
}; };
// Initialize all IDT entries // Initialize all IDT entries
void init_idt(void) { void init_idt(void) {
for (int i = 0; i < 256; i++) { for (int i = 0; i < 256; i++) {
set_idt(i, isr_table[i], 0); set_idt(i, isr_table[i], 0);
} }
load_idt(idt); load_idt(idt);
} }

View File

@ -1,246 +1,196 @@
#include <stdint.h> #include <stdint.h>
#include <stddef.h> #include <stddef.h>
#include <stdbool.h> #include <stdbool.h>
#include "../include/limine.h" #include "../include/limine.h"
#include "acpi.h" #include "acpi.h"
#include "common.h" #include "alloc.h"
#include "print.h" #include "common.h"
#include "print.h"
// credit owed to https://wiki.osdev.org/Limine_Bare_Bones for the limine setup code
// credit owed to https://wiki.osdev.org/Limine_Bare_Bones for the limine setup code
__attribute__((used, section(".limine_requests")))
static volatile u64 limine_base_revision[] = LIMINE_BASE_REVISION(4); __attribute__((used, section(".limine_requests")))
static volatile u64 limine_base_revision[] = LIMINE_BASE_REVISION(4);
__attribute__((used, section(".limine_requests")))
static volatile struct limine_framebuffer_request fb_req = { __attribute__((used, section(".limine_requests")))
.id = LIMINE_FRAMEBUFFER_REQUEST_ID, static volatile struct limine_framebuffer_request fb_req = {
.revision = 0 .id = LIMINE_FRAMEBUFFER_REQUEST_ID,
}; .revision = 0
};
__attribute__((used, section(".limine_requests")))
static volatile struct limine_memmap_request mem_req = { __attribute__((used, section(".limine_requests")))
.id = LIMINE_MEMMAP_REQUEST_ID, static volatile struct limine_hhdm_request hhdm_req = {
.revision = 0, .id = LIMINE_HHDM_REQUEST_ID,
}; .revision = 0
};
__attribute__((used, section(".limine_requests")))
static volatile struct limine_hhdm_request hhdm_req = { __attribute__((used, section(".limine_requests")))
.id = LIMINE_HHDM_REQUEST_ID, static volatile struct limine_rsdp_request rsdp_req = {
.revision = 0 .id = LIMINE_RSDP_REQUEST_ID,
}; .revision = 0
};
__attribute__((used, section(".limine_requests")))
static volatile struct limine_rsdp_request rsdp_req = { u64 hhdm_offset;
.id = LIMINE_RSDP_REQUEST_ID,
.revision = 0 __attribute__((used, section(".limine_requests_start")))
}; static volatile u64 limine_requests_start_marker[] = LIMINE_REQUESTS_START_MARKER;
u64 hhdm_offset; __attribute__((used, section(".limine_requests_end")))
static volatile u64 limine_requests_end_marker[] = LIMINE_REQUESTS_END_MARKER;
__attribute__((used, section(".limine_requests_start")))
static volatile u64 limine_requests_start_marker[] = LIMINE_REQUESTS_START_MARKER; void* memcpy(void* restrict dst, const void* src, size_t n) {
u8* restrict pdst = (u8* restrict)dst;
__attribute__((used, section(".limine_requests_end"))) const u8* restrict psrc = (const u8* restrict)src;
static volatile u64 limine_requests_end_marker[] = LIMINE_REQUESTS_END_MARKER;
for(size_t i = 0; i < n; i++) {
void* memcpy(void* restrict dst, const void* src, size_t n) { pdst[i] = psrc[i];
u8* restrict pdst = (u8* restrict)dst; }
const u8* restrict psrc = (const u8* restrict)src;
return dst;
for(size_t i = 0; i < n; i++) { }
pdst[i] = psrc[i];
} void* memset(void* s, int c, size_t n) {
u8* p = (u8*) s;
return dst;
} for(size_t i = 0; i < n; i++) {
p[i] = (u8)c;
void* memset(void* s, int c, size_t n) { }
u8* p = (u8*) s;
return s;
for(size_t i = 0; i < n; i++) { }
p[i] = (u8)c;
} void* memmove(void* dst, const void* src, size_t n) {
u8* restrict pdst = (u8* restrict)dst;
return s; const u8* restrict psrc = (const u8* restrict)src;
}
if(src > dst) {
void* memmove(void* dst, const void* src, size_t n) { for(size_t i = 0; i < n; i++) {
u8* restrict pdst = (u8* restrict)dst; pdst[i] = psrc[i];
const u8* restrict psrc = (const u8* restrict)src; }
} else if(src < dst) {
if(src > dst) { for(size_t i = n; i > 0; i--) {
for(size_t i = 0; i < n; i++) { pdst[i-1] = psrc[i-1];
pdst[i] = psrc[i]; }
} }
} else if(src < dst) {
for(size_t i = n; i > 0; i--) { return dst;
pdst[i-1] = psrc[i-1]; }
}
} int memcmp(const void* s1, const void* s2, size_t n) {
const u8* p1 = (const u8* )s1;
return dst; const u8* p2 = (const u8* )s2;
}
for(size_t i = 0; i < n; i++) {
int memcmp(const void* s1, const void* s2, size_t n) { if(p1[i] != p2[i]) {
const u8* p1 = (const u8* )s1; return p1[i] < p2[i] ? -1 : 1;
const u8* p2 = (const u8* )s2; }
}
for(size_t i = 0; i < n; i++) {
if(p1[i] != p2[i]) { return 0;
return p1[i] < p2[i] ? -1 : 1; }
}
} void hang() {
for(;;) {
return 0; asm ("hlt");
} }
}
static void hang() {
for(;;) {
asm ("hlt"); struct limine_framebuffer* fb;
}
} void draw(u8 vect) {
for(size_t y = 0; y < fb->height; y++) {
for(size_t x = 0; x < fb->width; x++) {
struct limine_framebuffer* fb; volatile u32* fb_ptr = fb->address;
fb_ptr[y * fb->width + x] = (
void draw(u8 vect) { (x + y) * 0x00010000 |
for(size_t y = 0; y < fb->height; y++) { (x ^ y) * 0x00000100 |
for(size_t x = 0; x < fb->width; x++) { (x - y) * 0x00000001
volatile u32* fb_ptr = fb->address; )*vect;
fb_ptr[y * fb->width + x] = ( }
(x + y) * 0x00010000 | }
(x ^ y) * 0x00000100 | }
(x - y) * 0x00000001
)*vect; extern void init_idt(void);
}
} extern u32 fg;
} extern u32 bg;
extern void init_idt(void);
extern u32 fg; u32 apic_get_local_base();
extern u32 bg; void apic_enable();
void print_memmap_entry(struct limine_memmap_entry* entry) { void setup_identity_mapping();
u32 savefg = fg;
u32 savebg = bg; void kmain() {
static const char* type_strs[] = { if(LIMINE_BASE_REVISION_SUPPORTED(limine_base_revision) == false) {
"Usable", hang();
"Reserved", }
"ACPI Reclaimable",
"ACPI NVS", if(fb_req.response == NULL || fb_req.response->framebuffer_count < 1) {
"BAD!!!", hang();
"Bootloader Reclaimable", }
"Executable and Modules",
"Framebuffer", fb = fb_req.response->framebuffers[0];
"ACPI Tables",
}; print_init(fb);
init_idt();
static u32 type_colors[] = {
0x00AF00,
0xAF1F00,
0x7f7f00, if(!hhdm_req.response) {
0x7f7f00, print("Failed to get higher half direct mapping\n.");
0xFF0000, hang();
0x007f7f, }
0x408000,
0x0000FF, hhdm_offset = hhdm_req.response->offset;
0x00FF00
}; if(!rsdp_req.response) {
print ("Failed to find rsdp\n.");
bg = type_colors[entry->type]; hang();
fg = ~bg; }
u64 addr = entry->base; alloc_init();
u64 end = addr + entry->length;
print("["); rsdp = (struct acpi_rsdp_header*)(rsdp_req.response->address);
print(type_strs[entry->type]);
print("]");
print64(addr); print("Found RSDP @ 0x");
print(" - "); print64((u64)rsdp);
print64(end); put('\n');
print("\n");
fg = savefg; print("With signature: ");
bg = savebg; printn((char*)rsdp->signature, sizeof(rsdp->signature));
}
print(" v");
print8(rsdp->revision);
print("\nRSDT at 0x");
u32 apic_get_local_base(); struct acpi_rsdt* rsdt =
void apic_enable(); (struct acpi_rsdt*)(
(rsdp->revision? rsdp->ptr64:rsdp->ptr32) + hhdm_offset
void kmain() { );
if(LIMINE_BASE_REVISION_SUPPORTED(limine_base_revision) == false) { print64((u64)rsdt);
hang(); print("\nSDT Signature: ");
}
if(fb_req.response == NULL || fb_req.response->framebuffer_count < 1) { printn((const char*) rsdt->signature, sizeof(rsdt->signature));
hang(); print("\nAPIC Local Base: ");
}
/* I should check cpuid to ensure its supported but it will
fb = fb_req.response->framebuffers[0]; * be for my machines ;^) */
/* APIC stuff */
print_init(fb); u32 r = 0xDEADBEEF;
init_idt(); r = apic_get_local_base();
print32(r);
if(!mem_req.response) {
print("Failed to get memory map :(\n)"); apic_enable();
hang();
} print("\nAPIC Enabled");
if(!hhdm_req.response) { hang();
print("Failed to get higher half direct mapping\n.");
hang(); }
}
hhdm_offset = hhdm_req.response->offset;
if(!rsdp_req.response) {
print ("Failed to find rsdp\n.");
hang();
}
rsdp = (struct acpi_rsdp_header*)(rsdp_req.response->address);
for(size_t i = 0; i < mem_req.response->entry_count; i++) {
print_memmap_entry(mem_req.response->entries[i]);
}
print("Found RSDP @ 0x");
print64((u64)rsdp);
put('\n');
print("With signature: ");
printn((char*)rsdp->signature, sizeof(rsdp->signature));
print(" v");
print8(rsdp->revision);
print("\nRSDT at 0x");
struct acpi_rsdt* rsdt =
(struct acpi_rsdt*)(
(rsdp->revision? rsdp->ptr64:rsdp->ptr32) + hhdm_offset
);
print64((u64)rsdt);
print("\nSDT Signature: ");
printn((const char*) rsdt->signature, sizeof(rsdt->signature));
print("\nAPIC Local Base: ");
/* I should check cpuid to ensure its supported but it will
* be for my machines ;^) */
/* APIC stuff */
u32 r = 0xDEADBEEF;
r = apic_get_local_base();
print32(r);
apic_enable();
print("\nAPIC Enabled");
hang();
}

388
src/map.c Normal file
View File

@ -0,0 +1,388 @@
#include "alloc.h"
#include "common.h"
#include "print.h"
// MMIO (Memory-Mapped I/O) Mapping for ACPI and other hardware registers
//
// CRITICAL: MMIO regions are NOT regular RAM!
// - They're not in Limine's memory map as "usable"
// - They're often above the RAM limit
// - Limine does NOT map them automatically
// - You must manually map them before accessing
// Page table entry structure
struct page_entry {
u64 present : 1;
u64 writable : 1;
u64 user : 1;
u64 write_through : 1;
u64 cache_disabled : 1; // IMPORTANT for MMIO!
u64 accessed : 1;
u64 dirty : 1;
u64 huge_page : 1;
u64 global : 1;
u64 unused : 3;
u64 frame : 40;
u64 reserved : 11;
u64 no_execute : 1;
};
extern u64 hhdm_offset;
// Get current page tables
static u64 get_cr3() {
u64 cr3;
asm volatile("mov %%cr3, %0" : "=r"(cr3));
return cr3 & ~0xFFF;
}
static u64 alloc_page_table() {
void* a = alloc((1<<12) / PAGE_SIZE);
return a? virt_to_phys(a) : 0;
}
// Get or create a page table entry at any level
static struct page_entry* get_or_create_table(struct page_entry *table, u64 index) {
if (!table[index].present) {
u64 new_table_phys = alloc_page_table();
if (new_table_phys == 0) {
return NULL;
}
table[index].present = 1;
table[index].writable = 1;
table[index].user = 0;
table[index].frame = new_table_phys >> 12;
}
u64 next_table_phys = (u64)table[index].frame << 12;
return (struct page_entry*)phys_to_virt(next_table_phys);
}
// Map a MMIO page with proper cache settings
// physical_addr: Physical address of MMIO region
// size: Size in bytes (will be rounded up to 4KB pages)
// Returns: Virtual address to access the MMIO region
void* map_mmio(u64 physical_addr, u64 size) {
print("Mapping MMIO region:\n");
print(" Physical: 0x");
print64(physical_addr);
print("\n Size: 0x");
print64(size);
print(" (");
print64(size);
print(" bytes)\n");
// Align physical address down to page boundary
u64 phys_base = physical_addr & ~(PAGE_SIZE-1);
u64 offset_in_page = physical_addr & (PAGE_SIZE-1);
// Calculate number of pages needed
u64 total_size = size + offset_in_page;
u64 num_pages = (total_size + PAGE_SIZE - 1) / PAGE_SIZE;
print(" Aligned physical: 0x");
print64(phys_base);
print("\n Offset in page: 0x");
print64(offset_in_page);
print("\n Pages needed: ");
print64(num_pages);
print("\n");
// For MMIO, we typically map to the HHDM region
// Virtual address = Physical address + HHDM offset
u64 virt_base = phys_base + hhdm_offset;
print(" Target virtual: 0x");
print64(virt_base);
print("\n");
// Get current page tables
u64 pml4_phys = get_cr3();
struct page_entry *pml4 = (struct page_entry*)phys_to_virt(pml4_phys);
// Map each page
for (u64 i = 0; i < num_pages; i++) {
u64 current_phys = phys_base + (i * PAGE_SIZE);
u64 current_virt = virt_base + (i * PAGE_SIZE);
// Extract indices
u64 pml4_index = (current_virt >> 39) & 0x1FF;
u64 pdpt_index = (current_virt >> 30) & 0x1FF;
u64 pd_index = (current_virt >> 21) & 0x1FF;
u64 pt_index = (current_virt >> 12) & 0x1FF;
// Walk/create page table hierarchy
struct page_entry *pdpt = get_or_create_table(pml4, pml4_index);
if (!pdpt) {
print("ERROR: Failed to get/create PDPT\n");
return NULL;
}
struct page_entry *pd = get_or_create_table(pdpt, pdpt_index);
if (!pd) {
print("ERROR: Failed to get/create PD\n");
return NULL;
}
struct page_entry *pt = get_or_create_table(pd, pd_index);
if (!pt) {
print("ERROR: Failed to get/create PT\n");
return NULL;
}
// Map the page with MMIO-appropriate settings
pt[pt_index].present = 1;
pt[pt_index].writable = 1;
pt[pt_index].user = 0;
pt[pt_index].cache_disabled = 1; // CRITICAL: Disable caching for MMIO!
pt[pt_index].write_through = 0;
pt[pt_index].no_execute = 1; // Don't execute from MMIO
pt[pt_index].frame = current_phys >> 12;
// Flush TLB for this page
asm volatile("invlpg (%0)" :: "r"(current_virt) : "memory");
}
print(" MMIO mapped successfully!\n");
print(" Access at virtual: 0x");
print64(virt_base + offset_in_page);
print("\n\n");
// Return virtual address (with original offset)
return (void*)(virt_base + offset_in_page);
}
// Unmap MMIO region
void unmap_mmio(void *virtual_addr, u64 size) {
u64 virt_base = (u64)virtual_addr & ~0xFFF;
u64 num_pages = (size + ((u64)virtual_addr & 0xFFF) + 0xFFF) / 4096;
u64 pml4_phys = get_cr3();
struct page_entry *pml4 = (struct page_entry*)phys_to_virt(pml4_phys);
for (u64 i = 0; i < num_pages; i++) {
u64 current_virt = virt_base + (i * 4096);
u64 pml4_index = (current_virt >> 39) & 0x1FF;
u64 pdpt_index = (current_virt >> 30) & 0x1FF;
u64 pd_index = (current_virt >> 21) & 0x1FF;
u64 pt_index = (current_virt >> 12) & 0x1FF;
if (!pml4[pml4_index].present) continue;
struct page_entry *pdpt = phys_to_virt((u64)pml4[pml4_index].frame << 12);
if (!pdpt[pdpt_index].present) continue;
struct page_entry *pd = phys_to_virt((u64)pdpt[pdpt_index].frame << 12);
if (!pd[pd_index].present) continue;
struct page_entry *pt = phys_to_virt((u64)pd[pd_index].frame << 12);
if (!pt[pt_index].present) continue;
// Clear the entry
*((u64*)&pt[pt_index]) = 0;
// Flush TLB
asm volatile("invlpg (%0)" :: "r"(current_virt) : "memory");
}
}
// Check if a physical address is already mapped
int is_mapped(u64 physical_addr) {
u64 virtual_addr = physical_addr + hhdm_offset;
u64 pml4_phys = get_cr3();
struct page_entry *pml4 = phys_to_virt(pml4_phys);
u64 pml4_index = (virtual_addr >> 39) & 0x1FF;
u64 pdpt_index = (virtual_addr >> 30) & 0x1FF;
u64 pd_index = (virtual_addr >> 21) & 0x1FF;
u64 pt_index = (virtual_addr >> 12) & 0x1FF;
if (!pml4[pml4_index].present) return 0;
struct page_entry *pdpt = phys_to_virt((u64)pml4[pml4_index].frame << 12);
if (!pdpt[pdpt_index].present) return 0;
// Check for 1GB huge page
if (pdpt[pdpt_index].huge_page) return 1;
struct page_entry *pd = phys_to_virt((u64)pdpt[pdpt_index].frame << 12);
if (!pd[pd_index].present) return 0;
// Check for 2MB huge page
if (pd[pd_index].huge_page) return 1;
struct page_entry *pt = phys_to_virt((u64)pd[pd_index].frame << 12);
return pt[pt_index].present;
}
// Read from ACPI register (8-bit)
u8 acpi_read8(void *mmio_base, u64 offset) {
volatile u8 *addr = (volatile u8*)((u64)mmio_base + offset);
return *addr;
}
// Read from ACPI register (16-bit)
u16 acpi_read16(void *mmio_base, u64 offset) {
volatile u16 *addr = (volatile u16*)((u64)mmio_base + offset);
return *addr;
}
// Read from ACPI register (32-bit)
u32 acpi_read32(void *mmio_base, u64 offset) {
volatile u32 *addr = (volatile u32*)((u64)mmio_base + offset);
return *addr;
}
// Read from ACPI register (64-bit)
u64 acpi_read64(void *mmio_base, u64 offset) {
volatile u64 *addr = (volatile u64*)((u64)mmio_base + offset);
return *addr;
}
// Write to ACPI register (8-bit)
void acpi_write8(void *mmio_base, u64 offset, u8 value) {
volatile u8 *addr = (volatile u8*)((u64)mmio_base + offset);
*addr = value;
}
// Write to ACPI register (16-bit)
void acpi_write16(void *mmio_base, u64 offset, u16 value) {
volatile u16 *addr = (volatile u16*)((u64)mmio_base + offset);
*addr = value;
}
// Write to ACPI register (32-bit)
void acpi_write32(void *mmio_base, u64 offset, u32 value) {
volatile u32 *addr = (volatile u32*)((u64)mmio_base + offset);
*addr = value;
}
// Write to ACPI register (64-bit)
void acpi_write64(void *mmio_base, u64 offset, u64 value) {
volatile u64 *addr = (volatile u64*)((u64)mmio_base + offset);
*addr = value;
}
// Example: Map and access ACPI PM1a Control Block
void* map_acpi_pm1a_control(u64 physical_addr) {
print("Mapping ACPI PM1a Control Block...\n");
// PM1a Control is typically 2 bytes, but map at least one page
void *mmio = map_mmio(physical_addr, 4096);
if (mmio) {
print("PM1a Control Block mapped at virtual: 0x");
print64((u64)mmio);
print("\n");
}
return mmio;
}
// Example: Map ACPI tables (FADT, MADT, etc.)
void* map_acpi_table(u64 physical_addr, u64 size) {
print("Mapping ACPI table...\n");
print(" Physical: 0x");
print64(physical_addr);
print("\n Size: ");
print64(size);
print(" bytes\n");
void *table = map_mmio(physical_addr, size);
if (table) {
print("ACPI table mapped at virtual: 0x");
print64((u64)table);
print("\n");
}
return table;
}
void print_page_mapping(u64 virtual_addr) {
print("Page mapping for virtual 0x");
print64(virtual_addr);
print(":\n");
u64 pml4_phys = get_cr3();
struct page_entry *pml4 = phys_to_virt(pml4_phys);
u64 pml4_index = (virtual_addr >> 39) & 0x1FF;
u64 pdpt_index = (virtual_addr >> 30) & 0x1FF;
u64 pd_index = (virtual_addr >> 21) & 0x1FF;
u64 pt_index = (virtual_addr >> 12) & 0x1FF;
print(" Indices: PML4[");
print64(pml4_index);
print("] PDPT[");
print64(pdpt_index);
print("] PD[");
print64(pd_index);
print("] PT[");
print64(pt_index);
print("]\n");
if (!pml4[pml4_index].present) {
print(" PML4 entry not present!\n");
return;
}
print(" PML4 entry present, frame=0x");
print64((u64)pml4[pml4_index].frame << 12);
print("\n");
struct page_entry *pdpt = phys_to_virt((u64)pml4[pml4_index].frame << 12);
if (!pdpt[pdpt_index].present) {
print(" PDPT entry not present!\n");
return;
}
print(" PDPT entry present, frame=0x");
print64((u64)pdpt[pdpt_index].frame << 12);
print("\n");
if (pdpt[pdpt_index].huge_page) {
print(" 1GB huge page!\n");
return;
}
struct page_entry *pd = phys_to_virt((u64)pdpt[pdpt_index].frame << 12);
if (!pd[pd_index].present) {
print(" PD entry not present!\n");
return;
}
print(" PD entry present, frame=0x");
print64((u64)pd[pd_index].frame << 12);
print("\n");
if (pd[pd_index].huge_page) {
print(" 2MB huge page!\n");
return;
}
struct page_entry *pt = phys_to_virt((u64)pd[pd_index].frame << 12);
if (!pt[pt_index].present) {
print(" PT entry not present!\n");
return;
}
print(" PT entry present:\n");
print(" Physical frame: 0x");
print64((u64)pt[pt_index].frame << 12);
print("\n Writable: ");
print64(pt[pt_index].writable);
print("\n Cache disabled: ");
print64(pt[pt_index].cache_disabled);
print("\n No execute: ");
print64(pt[pt_index].no_execute);
print("\n");
}

6
src/map.h Normal file
View File

@ -0,0 +1,6 @@
#pragma once
#include "common.h"
void* map_mmio(u64, u64);