fixed mostly everything, works on my real hardware, turns out bochs just hates me

This commit is contained in:
Hopeless Tyromancy 2026-02-15 22:17:48 -05:00
parent 07e8015800
commit 69baa26d9b
24 changed files with 1110 additions and 1048 deletions

BIN
bin/os

Binary file not shown.

26
flake.lock generated Normal file
View File

@ -0,0 +1,26 @@
{
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1771205900,
"narHash": "sha256-GDTqgUN8pI8lE55wTdaFOS+xwwOOz/w055SbCLLFTqA=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "805ba342d424b11deabad6e1597372a3cfb39a59",
"type": "github"
},
"original": {
"owner": "NixOS",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"nixpkgs": "nixpkgs"
}
}
},
"root": "root",
"version": 7
}

BIN
image.hdd

Binary file not shown.

View File

@ -1,4 +1,5 @@
obj/src/int.c.o: src/int.c src/apic.h src/common.h src/print.h obj/src/int.c.o: src/int.c src/apic.h src/common.h src/print.h src/kbd.h
src/apic.h: src/apic.h:
src/common.h: src/common.h:
src/print.h: src/print.h:
src/kbd.h:

Binary file not shown.

View File

@ -1,9 +1,9 @@
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/apic.h src/alloc.h src/map.h src/print.h src/common.h src/alloc.h src/apic.h src/map.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/apic.h:
src/alloc.h: src/alloc.h:
src/apic.h:
src/map.h: src/map.h:
src/print.h: src/print.h:

Binary file not shown.

View File

@ -10,8 +10,6 @@
#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

@ -2,10 +2,8 @@
#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;
@ -41,4 +39,4 @@ struct acpi_rsdt {
}; };
}; };
extern struct acpi_rsdp_header* rsdp; extern struct acpi_rsdp_header *rsdp;

View File

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

View File

@ -3,14 +3,11 @@
static const size_t PAGE_SIZE = (1 << 12); static const size_t PAGE_SIZE = (1 << 12);
void alloc_init(); void alloc_init();
void* alloc(size_t size); void *alloc(size_t size);
void dealloc(void* arg, size_t size); void dealloc(void *arg, size_t size);
static inline u64 virt_to_phys(void* virt) { static inline u64 virt_to_phys(void *virt) { return (u64)virt - hhdm_offset; }
return (u64)virt - hhdm_offset;
static inline void *phys_to_virt(u64 phys) {
return (void *)(phys + hhdm_offset);
} }
static inline void* phys_to_virt(u64 phys) {
return (void*)(phys + hhdm_offset);
}

View File

@ -1,6 +1,6 @@
#include "common.h" #include "common.h"
#include "print.h"
#include "map.h" #include "map.h"
#include "print.h"
// stub of a PIC layout, we don't need the whole thing // stub of a PIC layout, we don't need the whole thing
// as we only care about initializing it to disable it // as we only care about initializing it to disable it
@ -11,7 +11,7 @@ enum {
PIC_DATA_SLAVE = 0xA1, PIC_DATA_SLAVE = 0xA1,
}; };
#define IOAPIC_REG_REDIR(n) (0x10 + 2*(n)) #define IOAPIC_REG_REDIR(n) (0x10 + 2 * (n))
enum { enum {
IOAPIC_REG_SELECT = 0x00, IOAPIC_REG_SELECT = 0x00,
@ -27,7 +27,6 @@ enum {
#define IOAPIC_ACTIVE_LOW (1 << 13) #define IOAPIC_ACTIVE_LOW (1 << 13)
#define IOAPIC_ACTIVE_HIGH (0 << 13) #define IOAPIC_ACTIVE_HIGH (0 << 13)
static void pic_init() { static void pic_init() {
// Start initialization sequence // Start initialization sequence
outb(PIC_COMM_MASTER, 0x11); // ICW1: Initialize in cascading mode outb(PIC_COMM_MASTER, 0x11); // ICW1: Initialize in cascading mode
@ -35,10 +34,10 @@ static void pic_init() {
outb(PIC_DATA_MASTER, 0x04); // ICW3: Slave PIC at IRQ2 outb(PIC_DATA_MASTER, 0x04); // ICW3: Slave PIC at IRQ2
outb(PIC_DATA_MASTER, 0x01); // ICW4: 8086/88 (MCS-80 compatible) outb(PIC_DATA_MASTER, 0x01); // ICW4: 8086/88 (MCS-80 compatible)
outb(PIC_COMM_SLAVE, 0x11); // ICW1: Initialize slave PIC outb(PIC_COMM_SLAVE, 0x11); // ICW1: Initialize slave PIC
outb(PIC_DATA_SLAVE, 0x28); // ICW2: Slave PIC vector offset outb(PIC_DATA_SLAVE, 0x28); // ICW2: Slave PIC vector offset
outb(PIC_DATA_SLAVE, 0x02); // ICW3: It's connected to master PIC outb(PIC_DATA_SLAVE, 0x02); // ICW3: It's connected to master PIC
outb(PIC_DATA_SLAVE, 0x01); // ICW4: 8086/88 mode outb(PIC_DATA_SLAVE, 0x01); // ICW4: 8086/88 mode
// Mask all interrupts // Mask all interrupts
outb(PIC_DATA_MASTER, 0xFF); outb(PIC_DATA_MASTER, 0xFF);
@ -53,26 +52,17 @@ static void pic_disable() {
static inline u64 rdmsr(u32 msr) { static inline u64 rdmsr(u32 msr) {
u32 hi, lo; u32 hi, lo;
asm volatile ( asm volatile("rdmsr" : "=a"(lo), "=d"(hi) : "c"(msr));
"rdmsr"
: "=a"(lo), "=d"(hi)
: "c"(msr)
);
return (((u64)hi) << 32) | (u64)lo; return (((u64)hi) << 32) | (u64)lo;
} }
static inline void wrmsr(u32 msr, u64 val) { static inline void wrmsr(u32 msr, u64 val) {
u32 eax = (u32) val; u32 eax = (u32)val;
u32 edx = (u32) (val >> 32); u32 edx = (u32)(val >> 32);
asm volatile ( asm volatile("wrmsr" : : "c"(msr), "a"(eax), "d"(edx));
"wrmsr"
:
: "c"(msr), "a" (eax), "d" (edx)
);
} }
static u64 apic_base; static u64 apic_base;
u64 apic_get_local_base() { u64 apic_get_local_base() {
@ -96,12 +86,10 @@ static u64 apic_set_local_base(u64 base) {
return base & 0xfffff000; return base & 0xfffff000;
} }
u32* apic_reg(u32 reg) { u32 *apic_reg(u32 reg) { return (u32 *)(hhdm_offset + apic_base + reg); }
return (u32*) (hhdm_offset + apic_base + reg);
}
void send_eoi() { void send_eoi() {
volatile u32* reg= apic_reg(0xB0); volatile u32 *reg = apic_reg(0xB0);
*reg = 0; *reg = 0;
} }
@ -111,14 +99,14 @@ void apic_enable() {
apic_set_local_base(apic_get_local_base()); apic_set_local_base(apic_get_local_base());
if(!map_mmio((u64)apic_base, 1<<12)) { if (!map_mmio((u64)apic_base, 1 << 12)) {
print("Failed to map APIC registers!\n"); print("Failed to map APIC registers!\n");
hang(); hang();
} }
volatile u32* spurious = apic_reg(0xF0); volatile u32 *spurious = apic_reg(0xF0);
print("Reg 0xF0 at 0x"); print("Reg 0xF0 at 0x");
print64((u64) spurious); print64((u64)spurious);
print("\nSpurious: "); print("\nSpurious: ");
print32(*spurious); print32(*spurious);
// set enable flag // set enable flag
@ -128,23 +116,23 @@ void apic_enable() {
print("\n"); print("\n");
// TPR = 0 (accept all interrupts) // TPR = 0 (accept all interrupts)
volatile u32* tpr = apic_reg(0x80); volatile u32 *tpr = apic_reg(0x80);
*tpr = 0; *tpr = 0;
// Mask all LVT antries except LINT0 (0x21) // Mask all LVT antries except LINT0 (0x21)
volatile u32* timer = apic_reg(0x320); volatile u32 *timer = apic_reg(0x320);
*timer = (1 << 16); *timer = (1 << 16);
volatile u32* LINT0 = apic_reg(0x350); volatile u32 *LINT0 = apic_reg(0x350);
*LINT0 = (7 << 8); *LINT0 = (7 << 8);
// *LINT0 = (1 << 16); // *LINT0 = (1 << 16);
volatile u32* LINT1 = apic_reg(0x360); volatile u32 *LINT1 = apic_reg(0x360);
*LINT1 = (1 << 16); *LINT1 = (1 << 16);
volatile u32* Error = apic_reg(0x370); volatile u32 *Error = apic_reg(0x370);
*Error = (1 << 16); *Error = (1 << 16);
} }
static volatile u32* ioapic_base; static volatile u32 *ioapic_base;
void ioapic_write(u8 reg, u32 value) { void ioapic_write(u8 reg, u32 value) {
ioapic_base[IOAPIC_REG_SELECT / 4] = reg; ioapic_base[IOAPIC_REG_SELECT / 4] = reg;
@ -157,62 +145,62 @@ u32 ioapic_read(u8 reg) {
} }
void ioapic_init() { void ioapic_init() {
// simply assume it is at the default address // simply assume it is at the default address
ioapic_base = map_mmio(0xFEC00000, 4096); ioapic_base = map_mmio(0xFEC00000, 4096);
print("IOAPIC BASE: "); print("IOAPIC BASE: ");
print64((u64)ioapic_base); print64((u64)ioapic_base);
print("\nIOAPIC Version:"); print("\nIOAPIC Version:");
ioapic_base[0] = 0x01; ioapic_base[0] = 0x01;
print32(ioapic_base[4]); print32(ioapic_base[4]);
print("\n"); print("\n");
// mask all IRQs // mask all IRQs
for(size_t i = 0; i < 24; i++) { for (size_t i = 0; i < 24; i++) {
u8 vect = 0x20 + i; u8 vect = 0x20 + i;
u32 low = vect | IOAPIC_MASKED | IOAPIC_DST_PHYS | IOAPIC_EDGE_TRIGG | IOAPIC_ACTIVE_HIGH; u32 low = vect | IOAPIC_MASKED | IOAPIC_DST_PHYS | IOAPIC_EDGE_TRIGG |
u32 high = 0; IOAPIC_ACTIVE_HIGH;
u32 high = 0;
ioapic_write(0x10 + i*2, low); ioapic_write(0x10 + i * 2, low);
ioapic_write(0x10 + i*2 + 1, high); ioapic_write(0x10 + i * 2 + 1, high);
} }
// setup keyboard by selecting IRQ1 // setup keyboard by selecting IRQ1
u8 irq = 1; u8 irq = 1;
u8 vect = 0x21; u8 vect = 0x21;
u8 cpu = 0; u8 cpu = 0;
u32 low = ioapic_read(IOAPIC_REG_REDIR(irq)); u32 low = ioapic_read(IOAPIC_REG_REDIR(irq));
u32 high = ioapic_read(IOAPIC_REG_REDIR(irq)+1); u32 high = ioapic_read(IOAPIC_REG_REDIR(irq) + 1);
print("Current redirection for IRQ");
print8(irq);
print(": ");
print32(low);
print(" ");
print32(high);
print("\n");
print("Current redirection for IRQ"); // Configure keyboard - UNMASKED (no IOAPIC_MASKED bit!)
print8(irq); low = vect | IOAPIC_DST_PHYS | IOAPIC_EDGE_TRIGG | IOAPIC_ACTIVE_HIGH;
print(": "); high = (cpu << 24);
print32(low);
print(" ");
print32(high);
print("\n");
// Configure keyboard - UNMASKED (no IOAPIC_MASKED bit!) ioapic_write(IOAPIC_REG_REDIR(irq), low);
low = vect | IOAPIC_DST_PHYS | IOAPIC_EDGE_TRIGG | IOAPIC_ACTIVE_HIGH; ioapic_write(IOAPIC_REG_REDIR(irq) + 1, high);
high = (cpu << 24);
ioapic_write(IOAPIC_REG_REDIR(irq), low); low = ioapic_read(IOAPIC_REG_REDIR(irq));
ioapic_write(IOAPIC_REG_REDIR(irq)+1, high); high = ioapic_read(IOAPIC_REG_REDIR(irq) + 1);
// Verify it worked
low = ioapic_read(IOAPIC_REG_REDIR(irq)); print("Current redirection for IRQ");
high = ioapic_read(IOAPIC_REG_REDIR(irq)+1); print8(irq);
// Verify it worked print(": ");
print("Current redirection for IRQ"); print32(low);
print8(irq); print(" ");
print(": "); print32(high);
print32(low); print("\n");
print(" "); if (low & IOAPIC_MASKED) {
print32(high); print(" [STILL MASKED (BAD)]\n");
print("\n"); } else {
if (low & IOAPIC_MASKED) { print(" [UNMASKED (GOOD)]\n");
print(" [STILL MASKED (BAD)]\n"); }
} else {
print(" [UNMASKED (GOOD)]\n");
}
} }

View File

@ -8,4 +8,4 @@ void send_eoi();
void ioapic_write(u8 reg, u32 value); void ioapic_write(u8 reg, u32 value);
u32 ioapic_read(u8 reg); u32 ioapic_read(u8 reg);
void ioapic_init(); void ioapic_init();
u32* apic_reg(u32 reg); u32 *apic_reg(u32 reg);

View File

@ -6,54 +6,46 @@
#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("int %0" : : "i"(n)); }
asm volatile (
"int %0"
:
: "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));
} }
static inline u8 inb(u16 port) { static inline u8 inb(u16 port) {
u8 value; u8 value;
asm volatile ("inb %w1, %b0" : "=a"(value) : "Nd"(port) : "memory"); asm volatile("inb %w1, %b0" : "=a"(value) : "Nd"(port) : "memory");
return value; return value;
} }
static inline u16 inw(u16 port) { static inline u16 inw(u16 port) {
u16 value; u16 value;
asm volatile ("inw %w1, %b0" : "=a"(value) : "Nd"(port) : "memory"); asm volatile("inw %w1, %b0" : "=a"(value) : "Nd"(port) : "memory");
return value; return value;
} }
static inline u32 ind(u16 port) { static inline u32 ind(u16 port) {
u32 value; u32 value;
asm volatile ("ind %w1, %b0" : "=a"(value) : "Nd"(port) : "memory"); asm volatile("ind %w1, %b0" : "=a"(value) : "Nd"(port) : "memory");
return value; return value;
} }
void *memcpy(void *dst, const void *src, size_t n);
void *memset(void *s, int c, size_t n);
void* memcpy(void* dst, const void* src, size_t n); void *memmove(void *dst, const void *src, size_t n);
void* memset(void* s, int c, size_t n); int memcmp(const void *s1, const void *s2, size_t n);
void* memmove(void* dst, const void* src, size_t n);
int memcmp(const void* s1, const void* s2, size_t n);
void hang(); void hang();
extern u64 hhdm_offset; extern u64 hhdm_offset;

View File

@ -2,11 +2,9 @@
#include "common.h" #include "common.h"
void* memcpy(void* restrict dst, const void* src, size_t n); void *memcpy(void *restrict 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);
static int isprint(int ch) { static int isprint(int ch) { return (u8)(ch - ' ') <= ('~' - ' '); }
return (u8)(ch-' ') <= ('~'-' ');
}

View File

@ -25,100 +25,20 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#define FONT_HEIGHT 6 #define FONT_HEIGHT 6
static u32 font[] = { static u32 font[] = {
0x0, 0x0, 0x8021084, 0x294a, 0x15f52bea, 0x8fa38be, 0x33a22e60,
0x8021084, 0x2e94d8a2, 0x1084, 0x10421088, 0x4421082, 0xa23880, 0x471000,
0x294a, 0x4420000, 0x70000, 0xc600000, 0x2222200, 0x1d3ad72e, 0x3e4214c4,
0x15f52bea, 0x3e22222e, 0x1d18320f, 0x210fc888, 0x1d183c3f, 0x1d17844c, 0x222221f,
0x8fa38be, 0x1d18ba2e, 0x210f463e, 0xc6018c0, 0x4401000, 0x10411100, 0xe03800,
0x33a22e60, 0x4441040, 0x802322e, 0x3c1ef62e, 0x231fc544, 0x1f18be2f, 0x3c10862e,
0x2e94d8a2, 0x1f18c62f, 0x3e10bc3f, 0x210bc3f, 0x1d1c843e, 0x2318fe31, 0x3e42109f,
0x1084, 0xc94211f, 0x23149d31, 0x3e108421, 0x231ad6bb, 0x239cd671, 0x1d18c62e,
0x10421088, 0x217c62f, 0x30eac62e, 0x2297c62f, 0x1d141a2e, 0x842109f, 0x1d18c631,
0x4421082, 0x8454631, 0x375ad631, 0x22a21151, 0x8421151, 0x3e22221f, 0x1842108c,
0xa23880, 0x20820820, 0xc421086, 0x4544, 0x3e000000, 0x82, 0x1c97b000,
0x471000, 0xe949c21, 0x1c10b800, 0x1c94b908, 0x1c549800, 0x2211c4c, 0xe87252e,
0x4420000, 0x12949c21, 0xc210040, 0x6210802, 0x12519521, 0xc210842, 0x235aac00,
0x70000, 0x12949c00, 0xc949800, 0x213a526, 0x3087252e, 0x2149800, 0xe837000,
0xc600000, 0xc213c42, 0xe94a400, 0x464a400, 0x155ac400, 0x36426c00, 0xe872529,
0x2222200, 0x1e223c00, 0x1843188c, 0x8421084, 0xc463086, 0x6d800, 0x3fffffff,
0x1d3ad72e,
0x3e4214c4,
0x3e22222e,
0x1d18320f,
0x210fc888,
0x1d183c3f,
0x1d17844c,
0x222221f,
0x1d18ba2e,
0x210f463e,
0xc6018c0,
0x4401000,
0x10411100,
0xe03800,
0x4441040,
0x802322e,
0x3c1ef62e,
0x231fc544,
0x1f18be2f,
0x3c10862e,
0x1f18c62f,
0x3e10bc3f,
0x210bc3f,
0x1d1c843e,
0x2318fe31,
0x3e42109f,
0xc94211f,
0x23149d31,
0x3e108421,
0x231ad6bb,
0x239cd671,
0x1d18c62e,
0x217c62f,
0x30eac62e,
0x2297c62f,
0x1d141a2e,
0x842109f,
0x1d18c631,
0x8454631,
0x375ad631,
0x22a21151,
0x8421151,
0x3e22221f,
0x1842108c,
0x20820820,
0xc421086,
0x4544,
0x3e000000,
0x82,
0x1c97b000,
0xe949c21,
0x1c10b800,
0x1c94b908,
0x1c549800,
0x2211c4c,
0xe87252e,
0x12949c21,
0xc210040,
0x6210802,
0x12519521,
0xc210842,
0x235aac00,
0x12949c00,
0xc949800,
0x213a526,
0x3087252e,
0x2149800,
0xe837000,
0xc213c42,
0xe94a400,
0x464a400,
0x155ac400,
0x36426c00,
0xe872529,
0x1e223c00,
0x1843188c,
0x8421084,
0xc463086,
0x6d800,
0x3fffffff,
}; };

408
src/int.c
View File

@ -3,10 +3,9 @@
#include "apic.h" #include "apic.h"
// for debugging // for debugging
#include "print.h" #include "print.h"
#include "kbd.h"
#include "common.h" #include "common.h"
// for trap debugging // for trap debugging
u64 dbg_var = 0; u64 dbg_var = 0;
@ -21,26 +20,25 @@ pstruct int_desc {
}; };
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;
} }
@ -49,15 +47,15 @@ pstruct idtr {
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);
@ -75,204 +73,226 @@ struct cpu_ctx {
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");
if(ctx->vect == 0x21) {
send_eoi(); kbd_handler();
}
return ctx; return ctx;
} }
__attribute__((naked)) __attribute__((naked)) void int_stub(void) {
void int_stub(void) { __asm__ volatile("push %%rax\n"
__asm__ volatile ( "push %%rbx\n"
"push %%rax\n" "push %%rcx\n"
"push %%rbx\n" "push %%rdx\n"
"push %%rcx\n" "push %%rsi\n"
"push %%rdx\n" "push %%rdi\n"
"push %%rsi\n" "push %%r8\n"
"push %%rdi\n" "push %%r9\n"
"push %%r8\n" "push %%r10\n"
"push %%r9\n" "push %%r11\n"
"push %%r10\n" "push %%r12\n"
"push %%r11\n" "push %%r13\n"
"push %%r12\n" "push %%r14\n"
"push %%r13\n" "push %%r15\n"
"push %%r14\n" "mov %%rsp, %%rdi\n"
"push %%r15\n" "call interrupt_dispatch\n"
"mov %%rsp, %%rdi\n" "mov %%rax, %%rsp\n"
"call interrupt_dispatch\n" "pop %%r15\n"
"mov %%rax, %%rsp\n" "pop %%r14\n"
"pop %%r15\n" "pop %%r13\n"
"pop %%r14\n" "pop %%r12\n"
"pop %%r13\n" "pop %%r11\n"
"pop %%r12\n" "pop %%r10\n"
"pop %%r11\n" "pop %%r9\n"
"pop %%r10\n" "pop %%r8\n"
"pop %%r9\n" "pop %%rdi\n"
"pop %%r8\n" "pop %%rsi\n"
"pop %%rdi\n" "pop %%rdx\n"
"pop %%rsi\n" "pop %%rcx\n"
"pop %%rdx\n" "pop %%rbx\n"
"pop %%rcx\n" "pop %%rax\n"
"pop %%rbx\n" "add $16, %%rsp\n"
"pop %%rax\n" "iretq\n"
"add $16, %%rsp\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(36) ISR_NO_ERR(37) ISR_NO_ERR(38) ISR_NO_ERR(39) ISR_NO_ERR(33) ISR_NO_ERR(34) ISR_NO_ERR(35) ISR_NO_ERR(36) ISR_NO_ERR(37) ISR_NO_ERR(
ISR_NO_ERR(40) ISR_NO_ERR(41) ISR_NO_ERR(42) ISR_NO_ERR(43) 38) ISR_NO_ERR(39) 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(
ISR_NO_ERR(48) ISR_NO_ERR(49) ISR_NO_ERR(50) ISR_NO_ERR(51) 48) ISR_NO_ERR(49) ISR_NO_ERR(50) ISR_NO_ERR(51) ISR_NO_ERR(52) ISR_NO_ERR(53)
ISR_NO_ERR(52) ISR_NO_ERR(53) ISR_NO_ERR(54) ISR_NO_ERR(55) ISR_NO_ERR(54) ISR_NO_ERR(55) ISR_NO_ERR(56) ISR_NO_ERR(57) ISR_NO_ERR(
ISR_NO_ERR(56) ISR_NO_ERR(57) ISR_NO_ERR(58) ISR_NO_ERR(59) 58) ISR_NO_ERR(59) ISR_NO_ERR(60) ISR_NO_ERR(61) ISR_NO_ERR(62)
ISR_NO_ERR(60) ISR_NO_ERR(61) ISR_NO_ERR(62) ISR_NO_ERR(63) ISR_NO_ERR(63) ISR_NO_ERR(64) ISR_NO_ERR(65) ISR_NO_ERR(66) ISR_NO_ERR(
ISR_NO_ERR(64) ISR_NO_ERR(65) ISR_NO_ERR(66) ISR_NO_ERR(67) 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(
ISR_NO_ERR(72) ISR_NO_ERR(73) ISR_NO_ERR(74) ISR_NO_ERR(75) 76) ISR_NO_ERR(77) ISR_NO_ERR(78) ISR_NO_ERR(79) ISR_NO_ERR(80)
ISR_NO_ERR(76) ISR_NO_ERR(77) ISR_NO_ERR(78) ISR_NO_ERR(79) ISR_NO_ERR(81) ISR_NO_ERR(82) ISR_NO_ERR(83) ISR_NO_ERR(
ISR_NO_ERR(80) ISR_NO_ERR(81) ISR_NO_ERR(82) ISR_NO_ERR(83) 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(
ISR_NO_ERR(88) ISR_NO_ERR(89) ISR_NO_ERR(90) ISR_NO_ERR(91) 91) ISR_NO_ERR(92) ISR_NO_ERR(93) ISR_NO_ERR(94)
ISR_NO_ERR(92) ISR_NO_ERR(93) ISR_NO_ERR(94) ISR_NO_ERR(95) ISR_NO_ERR(95) ISR_NO_ERR(96) ISR_NO_ERR(97) ISR_NO_ERR(
ISR_NO_ERR(96) ISR_NO_ERR(97) ISR_NO_ERR(98) ISR_NO_ERR(99) 98) ISR_NO_ERR(99) ISR_NO_ERR(100) ISR_NO_ERR(101)
ISR_NO_ERR(100) ISR_NO_ERR(101) ISR_NO_ERR(102) ISR_NO_ERR(103) ISR_NO_ERR(102) ISR_NO_ERR(103) ISR_NO_ERR(
ISR_NO_ERR(104) ISR_NO_ERR(105) ISR_NO_ERR(106) ISR_NO_ERR(107) 104) ISR_NO_ERR(105) ISR_NO_ERR(106)
ISR_NO_ERR(108) ISR_NO_ERR(109) ISR_NO_ERR(110) ISR_NO_ERR(111) ISR_NO_ERR(107) ISR_NO_ERR(108) ISR_NO_ERR(
ISR_NO_ERR(112) ISR_NO_ERR(113) ISR_NO_ERR(114) ISR_NO_ERR(115) 109) ISR_NO_ERR(110) ISR_NO_ERR(111)
ISR_NO_ERR(116) ISR_NO_ERR(117) ISR_NO_ERR(118) ISR_NO_ERR(119) ISR_NO_ERR(112) ISR_NO_ERR(113) ISR_NO_ERR(
ISR_NO_ERR(120) ISR_NO_ERR(121) ISR_NO_ERR(122) ISR_NO_ERR(123) 114) ISR_NO_ERR(115) ISR_NO_ERR(116)
ISR_NO_ERR(124) ISR_NO_ERR(125) ISR_NO_ERR(126) ISR_NO_ERR(127) ISR_NO_ERR(117) ISR_NO_ERR(118) ISR_NO_ERR(
ISR_NO_ERR(128) ISR_NO_ERR(129) ISR_NO_ERR(130) ISR_NO_ERR(131) 119) ISR_NO_ERR(120) ISR_NO_ERR(121)
ISR_NO_ERR(132) ISR_NO_ERR(133) ISR_NO_ERR(134) ISR_NO_ERR(135) ISR_NO_ERR(122) ISR_NO_ERR(
ISR_NO_ERR(136) ISR_NO_ERR(137) ISR_NO_ERR(138) ISR_NO_ERR(139) 123) ISR_NO_ERR(124)
ISR_NO_ERR(140) ISR_NO_ERR(141) ISR_NO_ERR(142) ISR_NO_ERR(143) ISR_NO_ERR(125) ISR_NO_ERR(
ISR_NO_ERR(144) ISR_NO_ERR(145) ISR_NO_ERR(146) ISR_NO_ERR(147) 126) ISR_NO_ERR(127)
ISR_NO_ERR(148) ISR_NO_ERR(149) ISR_NO_ERR(150) ISR_NO_ERR(151) ISR_NO_ERR(128) ISR_NO_ERR(
ISR_NO_ERR(152) ISR_NO_ERR(153) ISR_NO_ERR(154) ISR_NO_ERR(155) 129) ISR_NO_ERR(130)
ISR_NO_ERR(156) ISR_NO_ERR(157) ISR_NO_ERR(158) ISR_NO_ERR(159) ISR_NO_ERR(131) ISR_NO_ERR(
ISR_NO_ERR(160) ISR_NO_ERR(161) ISR_NO_ERR(162) ISR_NO_ERR(163) 132) ISR_NO_ERR(133)
ISR_NO_ERR(164) ISR_NO_ERR(165) ISR_NO_ERR(166) ISR_NO_ERR(167) ISR_NO_ERR(
ISR_NO_ERR(168) ISR_NO_ERR(169) ISR_NO_ERR(170) ISR_NO_ERR(171) 134) ISR_NO_ERR(135)
ISR_NO_ERR(172) ISR_NO_ERR(173) ISR_NO_ERR(174) ISR_NO_ERR(175) ISR_NO_ERR(136) ISR_NO_ERR(
ISR_NO_ERR(176) ISR_NO_ERR(177) ISR_NO_ERR(178) ISR_NO_ERR(179) 137) ISR_NO_ERR(138)
ISR_NO_ERR(180) ISR_NO_ERR(181) ISR_NO_ERR(182) ISR_NO_ERR(183) ISR_NO_ERR(139) ISR_NO_ERR(
ISR_NO_ERR(184) ISR_NO_ERR(185) ISR_NO_ERR(186) ISR_NO_ERR(187) 140) ISR_NO_ERR(141)
ISR_NO_ERR(188) ISR_NO_ERR(189) ISR_NO_ERR(190) ISR_NO_ERR(191) ISR_NO_ERR(142) ISR_NO_ERR(
ISR_NO_ERR(192) ISR_NO_ERR(193) ISR_NO_ERR(194) ISR_NO_ERR(195) 143)
ISR_NO_ERR(196) ISR_NO_ERR(197) ISR_NO_ERR(198) ISR_NO_ERR(199) 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(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(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(168) ISR_NO_ERR(169) ISR_NO_ERR(170) ISR_NO_ERR(171) ISR_NO_ERR(172) ISR_NO_ERR(173) ISR_NO_ERR(
ISR_NO_ERR(200) ISR_NO_ERR(201) ISR_NO_ERR(202) ISR_NO_ERR(203) 174) ISR_NO_ERR(175)
ISR_NO_ERR(204) ISR_NO_ERR(205) ISR_NO_ERR(206) ISR_NO_ERR(207) ISR_NO_ERR(
ISR_NO_ERR(208) ISR_NO_ERR(209) ISR_NO_ERR(210) ISR_NO_ERR(211) 176) ISR_NO_ERR(177)
ISR_NO_ERR(212) ISR_NO_ERR(213) ISR_NO_ERR(214) ISR_NO_ERR(215) ISR_NO_ERR(
ISR_NO_ERR(216) ISR_NO_ERR(217) ISR_NO_ERR(218) ISR_NO_ERR(219) 178) ISR_NO_ERR(179)
ISR_NO_ERR(220) ISR_NO_ERR(221) ISR_NO_ERR(222) ISR_NO_ERR(223) ISR_NO_ERR(
ISR_NO_ERR(224) ISR_NO_ERR(225) ISR_NO_ERR(226) ISR_NO_ERR(227) 180) ISR_NO_ERR(181)
ISR_NO_ERR(228) ISR_NO_ERR(229) ISR_NO_ERR(230) ISR_NO_ERR(231) ISR_NO_ERR(
ISR_NO_ERR(232) ISR_NO_ERR(233) ISR_NO_ERR(234) ISR_NO_ERR(235) 182) ISR_NO_ERR(183)
ISR_NO_ERR(236) ISR_NO_ERR(237) ISR_NO_ERR(238) ISR_NO_ERR(239) ISR_NO_ERR(
ISR_NO_ERR(240) ISR_NO_ERR(241) ISR_NO_ERR(242) ISR_NO_ERR(243) 184) ISR_NO_ERR(185)
ISR_NO_ERR(244) ISR_NO_ERR(245) ISR_NO_ERR(246) ISR_NO_ERR(247) ISR_NO_ERR(
ISR_NO_ERR(248) ISR_NO_ERR(249) ISR_NO_ERR(250) ISR_NO_ERR(251) 186)
ISR_NO_ERR(252) ISR_NO_ERR(253) ISR_NO_ERR(254) ISR_NO_ERR(255) ISR_NO_ERR(
187)
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(
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(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(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(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(
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(
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(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(
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,
isr8, isr9, isr10, isr11, isr12, isr13, isr14, isr15, isr9, isr10, isr11, isr12, isr13, isr14, isr15, isr16, isr17,
isr16, isr17, isr18, isr19, isr20, isr21, isr22, isr23, isr18, isr19, isr20, isr21, isr22, isr23, isr24, isr25, isr26,
isr24, isr25, isr26, isr27, isr28, isr29, isr30, isr31, isr27, isr28, isr29, isr30, isr31, isr32, isr33, isr34, isr35,
isr32, isr33, isr34, isr35, isr36, isr37, isr38, isr39, isr36, isr37, isr38, isr39, isr40, isr41, isr42, isr43, isr44,
isr40, isr41, isr42, isr43, isr44, isr45, isr46, isr47, isr45, isr46, isr47, isr48, isr49, isr50, isr51, isr52, isr53,
isr48, isr49, isr50, isr51, isr52, isr53, isr54, isr55, isr54, isr55, isr56, isr57, isr58, isr59, isr60, isr61, isr62,
isr56, isr57, isr58, isr59, isr60, isr61, isr62, isr63, 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, isr80,
isr72, isr73, isr74, isr75, isr76, isr77, isr78, isr79, isr81, isr82, isr83, isr84, isr85, isr86, isr87, isr88, isr89,
isr80, isr81, isr82, isr83, isr84, isr85, isr86, isr87, isr90, isr91, isr92, isr93, isr94, isr95, isr96, isr97, isr98,
isr88, isr89, isr90, isr91, isr92, isr93, isr94, isr95, isr99, isr100, isr101, isr102, isr103, isr104, isr105, isr106, isr107,
isr96, isr97, isr98, isr99, isr100, isr101, isr102, isr103, isr108, isr109, isr110, isr111, isr112, isr113, isr114, isr115, isr116,
isr104, isr105, isr106, isr107, isr108, isr109, isr110, isr111, isr117, isr118, isr119, isr120, isr121, isr122, isr123, isr124, isr125,
isr112, isr113, isr114, isr115, isr116, isr117, isr118, isr119, isr126, isr127, isr128, isr129, isr130, isr131, isr132, isr133, isr134,
isr120, isr121, isr122, isr123, isr124, isr125, isr126, isr127, isr135, isr136, isr137, isr138, isr139, isr140, isr141, isr142, isr143,
isr128, isr129, isr130, isr131, isr132, isr133, isr134, isr135, isr144, isr145, isr146, isr147, isr148, isr149, isr150, isr151, isr152,
isr136, isr137, isr138, isr139, isr140, isr141, isr142, isr143, isr153, isr154, isr155, isr156, isr157, isr158, isr159, isr160, isr161,
isr144, isr145, isr146, isr147, isr148, isr149, isr150, isr151, isr162, isr163, isr164, isr165, isr166, isr167, isr168, isr169, isr170,
isr152, isr153, isr154, isr155, isr156, isr157, isr158, isr159, isr171, isr172, isr173, isr174, isr175, isr176, isr177, isr178, isr179,
isr160, isr161, isr162, isr163, isr164, isr165, isr166, isr167, isr180, isr181, isr182, isr183, isr184, isr185, isr186, isr187, isr188,
isr168, isr169, isr170, isr171, isr172, isr173, isr174, isr175, isr189, isr190, isr191, isr192, isr193, isr194, isr195, isr196, isr197,
isr176, isr177, isr178, isr179, isr180, isr181, isr182, isr183, isr198, isr199, isr200, isr201, isr202, isr203, isr204, isr205, isr206,
isr184, isr185, isr186, isr187, isr188, isr189, isr190, isr191, isr207, isr208, isr209, isr210, isr211, isr212, isr213, isr214, isr215,
isr192, isr193, isr194, isr195, isr196, isr197, isr198, isr199, isr216, isr217, isr218, isr219, isr220, isr221, isr222, isr223, isr224,
isr200, isr201, isr202, isr203, isr204, isr205, isr206, isr207, isr225, isr226, isr227, isr228, isr229, isr230, isr231, isr232, isr233,
isr208, isr209, isr210, isr211, isr212, isr213, isr214, isr215, isr234, isr235, isr236, isr237, isr238, isr239, isr240, isr241, isr242,
isr216, isr217, isr218, isr219, isr220, isr221, isr222, isr223, isr243, isr244, isr245, isr246, isr247, isr248, isr249, isr250, isr251,
isr224, isr225, isr226, isr227, isr228, isr229, isr230, isr231, isr252, isr253, isr254, isr255,
isr232, isr233, isr234, isr235, isr236, isr237, isr238, isr239,
isr240, isr241, isr242, isr243, isr244, isr245, isr246, isr247,
isr248, isr249, isr250, isr251, isr252, isr253, isr254, isr255,
}; };
// Initialize all IDT entries // Initialize all IDT entries

133
src/kbd.c Normal file
View File

@ -0,0 +1,133 @@
#include "apic.h"
#include "common.h"
#include "print.h"
#include "kbd.h"
#define PIC1_COMMAND 0x20
#define PIC1_DATA 0x21
#define PIC_EOI 0x20
#define PS2_DATA_PORT 0x60
#define PS2_STATUS_PORT 0x64
// Scancode to ASCII mapping (US keyboard layout, simplified)
static const char scancode_to_ascii[] = {
0, 27, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0',
'-', '=', '\b', '\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
'o', 'p', '[', ']', '\n',
0, // Control
'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`',
0, // Left shift
'\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/',
0, // Right shift
'*',
0, // Alt
' ' // Space
};
static const char scancode_to_ascii_shift[] = {
0, 27, '!', '@', '#', '$', '%', '^', '&', '*', '(', ')',
'_', '+', '\b', '\t', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I',
'O', 'P', '{', '}', '\n',
0, // Control
'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"', '~',
0, // Left shift
'|', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '<', '>', '?',
0, // Right shift
'*',
0, // Alt
' ' // Space
};
static struct {
bool shift;
bool ctrl;
bool alt;
bool caps;
} kbd_state;
#define KBD_BUFFER_SIZE 1024
static struct {
char buff[KBD_BUFFER_SIZE];
volatile int read_pos;
volatile int write_pos;
} kbd_buff;
static void kbd_buffer_putc(char c) {
int next_pos = (kbd_buff.write_pos + 1) % KBD_BUFFER_SIZE;
if (next_pos != kbd_buff.read_pos) {
kbd_buff.buff[kbd_buff.write_pos] = c;
kbd_buff.write_pos = next_pos;
}
}
char kbd_buffer_getc() {
if (kbd_buff.read_pos == kbd_buff.write_pos) {
return 0;
}
char c = kbd_buff.buff[kbd_buff.read_pos];
kbd_buff.read_pos = (kbd_buff.read_pos + 1) % KBD_BUFFER_SIZE;
return c;
}
void kbd_handler() {
print("KBD HANDLER CALLED: scancode: ");
u8 scancode = inb(PS2_DATA_PORT);
print8(scancode);
print("\n");
bool released = (scancode & 0x80);
scancode &= 0x7F;
switch(scancode) {
case 0x2A:
case 0x36:
kbd_state.shift = !released;
break;
case 0x1D:
kbd_state.ctrl = !released;
break;
case 0x38:
kbd_state.alt = !released;
break;
case 0x3A:
if(!released) {
kbd_state.caps = !kbd_state.caps;
}
default:
break;
}
if(!released && scancode < sizeof(scancode_to_ascii)) {
char c = 0;
if(kbd_state.shift) {
c = scancode_to_ascii_shift[scancode];
} else {
c = scancode_to_ascii[scancode];
}
if(kbd_state.caps && c >= 'a' && c <= 'z') {
} else if(kbd_state.caps && c >= 'A' && c <= 'Z') {
c = c - 'A' + 'a';
}
if(c != 0) {
kbd_buffer_putc(c);
}
printn(&c, 1);
print("\n");
}
send_eoi();
}

2
src/kbd.h Normal file
View File

@ -0,0 +1,2 @@
#pragma once
void kbd_handler();

View File

@ -1,92 +1,92 @@
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h> #include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include "../include/limine.h" #include "../include/limine.h"
#include "acpi.h" #include "acpi.h"
#include "apic.h"
#include "alloc.h" #include "alloc.h"
#include "apic.h"
#include "common.h" #include "common.h"
#include "map.h" #include "map.h"
#include "print.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"))) __attribute__((
static volatile u64 limine_base_revision[] = LIMINE_BASE_REVISION(4); used,
section(".limine_requests"))) static volatile u64 limine_base_revision[] =
LIMINE_BASE_REVISION(4);
__attribute__((used, section(".limine_requests"))) __attribute__((
static volatile struct limine_framebuffer_request fb_req = { used,
.id = LIMINE_FRAMEBUFFER_REQUEST_ID, section(
.revision = 0 ".limine_requests"))) static volatile struct limine_framebuffer_request
}; fb_req = {.id = LIMINE_FRAMEBUFFER_REQUEST_ID, .revision = 0};
__attribute__((
used,
section(".limine_requests"))) static volatile struct limine_hhdm_request
hhdm_req = {.id = LIMINE_HHDM_REQUEST_ID, .revision = 0};
__attribute__((used, section(".limine_requests"))) __attribute__((
static volatile struct limine_hhdm_request hhdm_req = { used,
.id = LIMINE_HHDM_REQUEST_ID, section(".limine_requests"))) static volatile struct limine_rsdp_request
.revision = 0 rsdp_req = {.id = LIMINE_RSDP_REQUEST_ID, .revision = 0};
};
__attribute__((used, section(".limine_requests")))
static volatile struct limine_rsdp_request rsdp_req = {
.id = LIMINE_RSDP_REQUEST_ID,
.revision = 0
};
u64 hhdm_offset; u64 hhdm_offset;
__attribute__((used, section(".limine_requests_start"))) __attribute__((used, section(".limine_requests_start"))) static volatile u64
static volatile u64 limine_requests_start_marker[] = LIMINE_REQUESTS_START_MARKER; limine_requests_start_marker[] = LIMINE_REQUESTS_START_MARKER;
__attribute__((used, section(".limine_requests_end"))) __attribute__((used, section(".limine_requests_end"))) static volatile u64
static volatile u64 limine_requests_end_marker[] = LIMINE_REQUESTS_END_MARKER; limine_requests_end_marker[] = LIMINE_REQUESTS_END_MARKER;
void* memcpy(void* restrict dst, const void* src, size_t n) { void *memcpy(void *restrict dst, const void *src, size_t n) {
u8* restrict pdst = (u8* restrict)dst; u8 *restrict pdst = (u8 *restrict)dst;
const u8* restrict psrc = (const u8* restrict)src; const u8 *restrict psrc = (const u8 *restrict)src;
for(size_t i = 0; i < n; i++) { for (size_t i = 0; i < n; i++) {
pdst[i] = psrc[i]; pdst[i] = psrc[i];
} }
return dst; return dst;
} }
void* memset(void* s, int c, size_t n) { void *memset(void *s, int c, size_t n) {
u8* p = (u8*) s; u8 *p = (u8 *)s;
for(size_t i = 0; i < n; i++) { for (size_t i = 0; i < n; i++) {
p[i] = (u8)c; p[i] = (u8)c;
} }
return s; return s;
} }
void* memmove(void* dst, const void* src, size_t n) { void *memmove(void *dst, const void *src, size_t n) {
u8* restrict pdst = (u8* restrict)dst; u8 *restrict pdst = (u8 *restrict)dst;
const u8* restrict psrc = (const u8* restrict)src; const u8 *restrict psrc = (const u8 *restrict)src;
if(src > dst) { if (src > dst) {
for(size_t i = 0; i < n; i++) { for (size_t i = 0; i < n; i++) {
pdst[i] = psrc[i]; pdst[i] = psrc[i];
} }
} else if(src < dst) { } else if (src < dst) {
for(size_t i = n; i > 0; i--) { for (size_t i = n; i > 0; i--) {
pdst[i-1] = psrc[i-1]; pdst[i - 1] = psrc[i - 1];
} }
} }
return dst; return dst;
} }
int memcmp(const void* s1, const void* s2, size_t n) { int memcmp(const void *s1, const void *s2, size_t n) {
const u8* p1 = (const u8* )s1; const u8 *p1 = (const u8 *)s1;
const u8* p2 = (const u8* )s2; const u8 *p2 = (const u8 *)s2;
for(size_t i = 0; i < n; i++) { for (size_t i = 0; i < n; i++) {
if(p1[i] != p2[i]) { if (p1[i] != p2[i]) {
return p1[i] < p2[i] ? -1 : 1; return p1[i] < p2[i] ? -1 : 1;
} }
} }
@ -95,21 +95,18 @@ int memcmp(const void* s1, const void* s2, size_t n) {
} }
void hang() { void hang() {
for(;;) { for (;;) {
asm ("hlt"); asm("hlt");
} }
} }
struct limine_framebuffer *fb;
struct limine_framebuffer* fb;
void draw(u8 vect) { void draw(u8 vect) {
for(size_t y = 0; y < fb->height; y++) { for (size_t y = 0; y < fb->height; y++) {
for(size_t x = 0; x < fb->width; x++) { for (size_t x = 0; x < fb->width; x++) {
volatile u32* fb_ptr = fb->address; volatile u32 *fb_ptr = fb->address;
fb_ptr[y * fb->width + x] = ( fb_ptr[y * fb->width + x] = (((x ^ y) & 0xff) * 0x0F0003) * vect;
((x ^ y) & 0xff) * 0x0F0003
)*vect;
} }
} }
} }
@ -120,29 +117,30 @@ extern u32 fg;
extern u32 bg; extern u32 bg;
void enable_ps2_keyboard_interrupts(void) { void enable_ps2_keyboard_interrupts(void) {
// Read PS/2 configuration byte // Read PS/2 configuration byte
outb(0x64, 0x20); outb(0x64, 0x20);
while (!(inb(0x64) & 0x01)); // Wait for data while (!(inb(0x64) & 0x01))
u8 config = inb(0x60); ; // Wait for data
u8 config = inb(0x60);
// Enable keyboard interrupt (bit 0) and clock (clear bit 4) // Enable keyboard interrupt (bit 0) and clock (clear bit 4)
config |= 0x01; // Enable first port interrupt config |= 0x01; // Enable first port interrupt
config &= ~0x10; // Enable first port clock config &= ~0x10; // Enable first port clock
// Write config back // Write config back
outb(0x64, 0x60); outb(0x64, 0x60);
outb(0x60, config); outb(0x60, config);
// Enable keyboard port // Enable keyboard port
outb(0x64, 0xAE); outb(0x64, 0xAE);
} }
void kmain() { void kmain() {
if(LIMINE_BASE_REVISION_SUPPORTED(limine_base_revision) == false) { if (LIMINE_BASE_REVISION_SUPPORTED(limine_base_revision) == false) {
hang(); hang();
} }
if(fb_req.response == NULL || fb_req.response->framebuffer_count < 1) { if (fb_req.response == NULL || fb_req.response->framebuffer_count < 1) {
hang(); hang();
} }
@ -154,43 +152,39 @@ void kmain() {
bg = 0xFFFFFF; bg = 0xFFFFFF;
fg = 0x000000; fg = 0x000000;
if(!hhdm_req.response) { if (!hhdm_req.response) {
print("Failed to get higher half direct mapping\n."); print("Failed to get higher half direct mapping\n.");
hang(); hang();
} }
hhdm_offset = hhdm_req.response->offset; hhdm_offset = hhdm_req.response->offset;
if(!rsdp_req.response) { if (!rsdp_req.response) {
print ("Failed to find rsdp\n."); print("Failed to find rsdp\n.");
hang(); hang();
} }
alloc_init(); alloc_init();
rsdp = (struct acpi_rsdp_header *)(rsdp_req.response->address);
rsdp = (struct acpi_rsdp_header*)(rsdp_req.response->address);
print("Found RSDP @ 0x"); print("Found RSDP @ 0x");
print64((u64)rsdp); print64((u64)rsdp);
put('\n'); put('\n');
print("With signature: "); print("With signature: ");
printn((char*)rsdp->signature, sizeof(rsdp->signature)); printn((char *)rsdp->signature, sizeof(rsdp->signature));
print(" v"); print(" v");
print8(rsdp->revision); print8(rsdp->revision);
print("\nRSDT at 0x"); print("\nRSDT at 0x");
struct acpi_rsdt* rsdt = struct acpi_rsdt *rsdt =
(struct acpi_rsdt*)( (struct acpi_rsdt *)((rsdp->revision ? rsdp->ptr64 : rsdp->ptr32) +
(rsdp->revision? rsdp->ptr64:rsdp->ptr32) + hhdm_offset hhdm_offset);
);
print64((u64)rsdt); print64((u64)rsdt);
print("\nSDT Signature: "); print("\nSDT Signature: ");
printn((const char *)rsdt->signature, sizeof(rsdt->signature));
printn((const char*) rsdt->signature, sizeof(rsdt->signature));
print("\nAPIC Local Base: "); print("\nAPIC Local Base: ");
/* I should check cpuid to ensure its supported but it will /* I should check cpuid to ensure its supported but it will
@ -200,7 +194,7 @@ void kmain() {
print("APIC Enabled\n"); print("APIC Enabled\n");
ioapic_init(); ioapic_init();
if(!test_if_mapped((u64) apic_reg(0))) { if (!test_if_mapped((u64)apic_reg(0))) {
print("Mapping APIC registers failed :(\n"); print("Mapping APIC registers failed :(\n");
hang(); hang();
} }
@ -213,14 +207,15 @@ void kmain() {
print("Enabling keyboard\n"); print("Enabling keyboard\n");
enable_ps2_keyboard_interrupts(); enable_ps2_keyboard_interrupts();
outb(0x64, 0x20); // Read config outb(0x64, 0x20); // Read config
while (!(inb(0x64) & 0x01)); while (!(inb(0x64) & 0x01))
;
u8 config = inb(0x60); u8 config = inb(0x60);
asm volatile("sti"); asm volatile("sti");
print("Press a key NOW...\n"); print("Press a key NOW...\n");
volatile u32* tpr = apic_reg(0x80); volatile u32 *tpr = apic_reg(0x80);
print("TPR: 0x"); print("TPR: 0x");
print32(*tpr); print32(*tpr);
print("\n"); print("\n");
@ -228,30 +223,31 @@ void kmain() {
print("PS/2 config: 0x"); print("PS/2 config: 0x");
print8(config); print8(config);
if (!(config & 0x01)) { if (!(config & 0x01)) {
print("\nProblem: Bit 0 is 0 (interrupt disabled)\n"); print("\nProblem: Bit 0 is 0 (interrupt disabled)\n");
} else { } else {
print("\nOK: Bit 0 is 1 (interrupt enabled)\n"); print("\nOK: Bit 0 is 1 (interrupt enabled)\n");
} }
print("Press keys (polling test)...\n"); print("Press keys (polling test)...\n");
while (1) { while (1) {
if (inb(0x64) & 0x01) { // Data available if (inb(0x64) & 0x01) { // Data available
u8 code = inb(0x60); u8 code = inb(0x60);
print("Scan code: 0x"); print("Scan code: 0x");
print8(code); print8(code);
print("\n"); print("\n");
volatile u32* irr = apic_reg(0x210); volatile u32 *irr = apic_reg(0x210);
print32(*irr); print32(*irr);
irr = apic_reg(0x200); // IRR bits 31:0 irr = apic_reg(0x200); // IRR bits 31:0
u32* isr = apic_reg(0x100); // ISR bits 31:0 u32 *isr = apic_reg(0x100); // ISR bits 31:0
print("IRR: "); print32(*irr); print("IRR: ");
print(" ISR: "); print32(*isr); print32(*irr);
print("\n"); print(" ISR: ");
if (code == 0x01) break; // ESC print32(*isr);
} print("\n");
if (code == 0x01)
break; // ESC
}
} }
hang(); hang();
} }

725
src/map.c
View File

@ -12,11 +12,173 @@
// Page table entry structure // Page table entry structure
struct page_entry { 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);
if (!a) {
print("Failed to allocate page table\n");
}
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) {
print("failed to alloc\n");
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 >> 20);
print(" MiB)\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);
}
// Test correct mapping
int test_if_mapped(u64 virt_addr) {
// Try to read - if we get page fault, it's not mapped
// For now, just check the page tables manually
u64 pml4_idx = (virt_addr >> 39) & 0x1FF;
u64 pdpt_idx = (virt_addr >> 30) & 0x1FF;
u64 pd_idx = (virt_addr >> 21) & 0x1FF;
u64 pt_idx = (virt_addr >> 12) & 0x1FF;
// Get CR3
u64 cr3;
asm volatile("mov %%cr3, %0" : "=r"(cr3));
u64 pml4_phys = cr3 & ~0xFFF;
struct page_entry {
u64 present : 1; u64 present : 1;
u64 writable : 1; u64 writable : 1;
u64 user : 1; u64 user : 1;
u64 write_through : 1; u64 write_through : 1;
u64 cache_disabled : 1; // IMPORTANT for MMIO! u64 cache_disabled : 1;
u64 accessed : 1; u64 accessed : 1;
u64 dirty : 1; u64 dirty : 1;
u64 huge_page : 1; u64 huge_page : 1;
@ -25,451 +187,298 @@ struct page_entry {
u64 frame : 40; u64 frame : 40;
u64 reserved : 11; u64 reserved : 11;
u64 no_execute : 1; u64 no_execute : 1;
}; };
extern u64 hhdm_offset; // Access PML4
struct page_entry *pml4 = (struct page_entry *)(pml4_phys + hhdm_offset);
if (!pml4[pml4_idx].present) {
print(" PML4[");
print64(pml4_idx);
print("] NOT PRESENT\n");
return 0;
}
// Get current page tables // Access PDPT
static u64 get_cr3() { struct page_entry *pdpt =
u64 cr3; (struct page_entry *)(((u64)pml4[pml4_idx].frame << 12) + hhdm_offset);
asm volatile("mov %%cr3, %0" : "=r"(cr3));
return cr3 & ~0xFFF; if (!pdpt[pdpt_idx].present) {
print(" PDPT[");
print64(pdpt_idx);
print("] NOT PRESENT\n");
return 0;
}
// Access PD
struct page_entry *pd =
(struct page_entry *)(((u64)pdpt[pdpt_idx].frame << 12) + hhdm_offset);
if (!pd[pd_idx].present) {
print(" PD[");
print64(pd_idx);
print("] NOT PRESENT\n");
return 0;
}
// Access PT
struct page_entry *pt =
(struct page_entry *)(((u64)pd[pd_idx].frame << 12) + hhdm_offset);
if (!pt[pt_idx].present) {
print(" PT[");
print64(pt_idx);
print("] NOT PRESENT\n");
return 0;
}
print(" All levels present\n");
print(" Physical page: 0x");
print64((u64)pt[pt_idx].frame << 12);
print("\n");
print(" Cache disabled: ");
print8(pt[pt_idx].cache_disabled);
print("\n");
return 1;
} }
static u64 alloc_page_table() {
void* a = alloc((1<<12) / PAGE_SIZE);
if(!a) {
print("Failed to allocate page table\n");
}
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) {
print("failed to alloc\n");
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 >> 20);
print(" MiB)\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);
}
// Test correct mapping
int test_if_mapped(u64 virt_addr) {
// Try to read - if we get page fault, it's not mapped
// For now, just check the page tables manually
u64 pml4_idx = (virt_addr >> 39) & 0x1FF;
u64 pdpt_idx = (virt_addr >> 30) & 0x1FF;
u64 pd_idx = (virt_addr >> 21) & 0x1FF;
u64 pt_idx = (virt_addr >> 12) & 0x1FF;
// Get CR3
u64 cr3;
asm volatile("mov %%cr3, %0" : "=r"(cr3));
u64 pml4_phys = cr3 & ~0xFFF;
struct page_entry {
u64 present : 1;
u64 writable : 1;
u64 user : 1;
u64 write_through : 1;
u64 cache_disabled : 1;
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;
};
// Access PML4
struct page_entry *pml4 = (struct page_entry*)(pml4_phys + hhdm_offset);
if (!pml4[pml4_idx].present) {
print(" PML4[");
print64(pml4_idx);
print("] NOT PRESENT\n");
return 0;
}
// Access PDPT
struct page_entry *pdpt = (struct page_entry*)(((u64)pml4[pml4_idx].frame << 12) + hhdm_offset);
if (!pdpt[pdpt_idx].present) {
print(" PDPT[");
print64(pdpt_idx);
print("] NOT PRESENT\n");
return 0;
}
// Access PD
struct page_entry *pd = (struct page_entry*)(((u64)pdpt[pdpt_idx].frame << 12) + hhdm_offset);
if (!pd[pd_idx].present) {
print(" PD[");
print64(pd_idx);
print("] NOT PRESENT\n");
return 0;
}
// Access PT
struct page_entry *pt = (struct page_entry*)(((u64)pd[pd_idx].frame << 12) + hhdm_offset);
if (!pt[pt_idx].present) {
print(" PT[");
print64(pt_idx);
print("] NOT PRESENT\n");
return 0;
}
print(" All levels present\n");
print(" Physical page: 0x");
print64((u64)pt[pt_idx].frame << 12);
print("\n");
print(" Cache disabled: ");
print8(pt[pt_idx].cache_disabled);
print("\n");
return 1;
}
// Unmap MMIO region // Unmap MMIO region
void unmap_mmio(void *virtual_addr, u64 size) { void unmap_mmio(void *virtual_addr, u64 size) {
u64 virt_base = (u64)virtual_addr & ~0xFFF; u64 virt_base = (u64)virtual_addr & ~0xFFF;
u64 num_pages = (size + ((u64)virtual_addr & 0xFFF) + 0xFFF) / 4096; u64 num_pages = (size + ((u64)virtual_addr & 0xFFF) + 0xFFF) / 4096;
u64 pml4_phys = get_cr3(); u64 pml4_phys = get_cr3();
struct page_entry *pml4 = (struct page_entry*)phys_to_virt(pml4_phys); struct page_entry *pml4 = (struct page_entry *)phys_to_virt(pml4_phys);
for (u64 i = 0; i < num_pages; i++) { for (u64 i = 0; i < num_pages; i++) {
u64 current_virt = virt_base + (i * 4096); u64 current_virt = virt_base + (i * 4096);
u64 pml4_index = (current_virt >> 39) & 0x1FF; u64 pml4_index = (current_virt >> 39) & 0x1FF;
u64 pdpt_index = (current_virt >> 30) & 0x1FF; u64 pdpt_index = (current_virt >> 30) & 0x1FF;
u64 pd_index = (current_virt >> 21) & 0x1FF; u64 pd_index = (current_virt >> 21) & 0x1FF;
u64 pt_index = (current_virt >> 12) & 0x1FF; u64 pt_index = (current_virt >> 12) & 0x1FF;
if (!pml4[pml4_index].present) continue; if (!pml4[pml4_index].present)
struct page_entry *pdpt = phys_to_virt((u64)pml4[pml4_index].frame << 12); continue;
struct page_entry *pdpt = phys_to_virt((u64)pml4[pml4_index].frame << 12);
if (!pdpt[pdpt_index].present) continue; if (!pdpt[pdpt_index].present)
struct page_entry *pd = phys_to_virt((u64)pdpt[pdpt_index].frame << 12); continue;
struct page_entry *pd = phys_to_virt((u64)pdpt[pdpt_index].frame << 12);
if (!pd[pd_index].present) continue; if (!pd[pd_index].present)
struct page_entry *pt = phys_to_virt((u64)pd[pd_index].frame << 12); continue;
struct page_entry *pt = phys_to_virt((u64)pd[pd_index].frame << 12);
if (!pt[pt_index].present) continue; if (!pt[pt_index].present)
continue;
// Clear the entry // Clear the entry
*((u64*)&pt[pt_index]) = 0; *((u64 *)&pt[pt_index]) = 0;
// Flush TLB // Flush TLB
asm volatile("invlpg (%0)" :: "r"(current_virt) : "memory"); asm volatile("invlpg (%0)" ::"r"(current_virt) : "memory");
} }
} }
// Check if a physical address is already mapped // Check if a physical address is already mapped
int is_mapped(u64 physical_addr) { int is_mapped(u64 physical_addr) {
u64 virtual_addr = physical_addr + hhdm_offset; u64 virtual_addr = physical_addr + hhdm_offset;
u64 pml4_phys = get_cr3(); u64 pml4_phys = get_cr3();
struct page_entry *pml4 = phys_to_virt(pml4_phys); struct page_entry *pml4 = phys_to_virt(pml4_phys);
u64 pml4_index = (virtual_addr >> 39) & 0x1FF; u64 pml4_index = (virtual_addr >> 39) & 0x1FF;
u64 pdpt_index = (virtual_addr >> 30) & 0x1FF; u64 pdpt_index = (virtual_addr >> 30) & 0x1FF;
u64 pd_index = (virtual_addr >> 21) & 0x1FF; u64 pd_index = (virtual_addr >> 21) & 0x1FF;
u64 pt_index = (virtual_addr >> 12) & 0x1FF; u64 pt_index = (virtual_addr >> 12) & 0x1FF;
if (!pml4[pml4_index].present) return 0; if (!pml4[pml4_index].present)
struct page_entry *pdpt = phys_to_virt((u64)pml4[pml4_index].frame << 12); return 0;
struct page_entry *pdpt = phys_to_virt((u64)pml4[pml4_index].frame << 12);
if (!pdpt[pdpt_index].present) return 0; if (!pdpt[pdpt_index].present)
return 0;
// Check for 1GB huge page // Check for 1GB huge page
if (pdpt[pdpt_index].huge_page) return 1; if (pdpt[pdpt_index].huge_page)
return 1;
struct page_entry *pd = phys_to_virt((u64)pdpt[pdpt_index].frame << 12); struct page_entry *pd = phys_to_virt((u64)pdpt[pdpt_index].frame << 12);
if (!pd[pd_index].present) return 0; if (!pd[pd_index].present)
return 0;
// Check for 2MB huge page // Check for 2MB huge page
if (pd[pd_index].huge_page) return 1; if (pd[pd_index].huge_page)
return 1;
struct page_entry *pt = phys_to_virt((u64)pd[pd_index].frame << 12); struct page_entry *pt = phys_to_virt((u64)pd[pd_index].frame << 12);
return pt[pt_index].present; return pt[pt_index].present;
} }
// Read from ACPI register (8-bit) // Read from ACPI register (8-bit)
u8 acpi_read8(void *mmio_base, u64 offset) { u8 acpi_read8(void *mmio_base, u64 offset) {
volatile u8 *addr = (volatile u8*)((u64)mmio_base + offset); volatile u8 *addr = (volatile u8 *)((u64)mmio_base + offset);
return *addr; return *addr;
} }
// Read from ACPI register (16-bit) // Read from ACPI register (16-bit)
u16 acpi_read16(void *mmio_base, u64 offset) { u16 acpi_read16(void *mmio_base, u64 offset) {
volatile u16 *addr = (volatile u16*)((u64)mmio_base + offset); volatile u16 *addr = (volatile u16 *)((u64)mmio_base + offset);
return *addr; return *addr;
} }
// Read from ACPI register (32-bit) // Read from ACPI register (32-bit)
u32 acpi_read32(void *mmio_base, u64 offset) { u32 acpi_read32(void *mmio_base, u64 offset) {
volatile u32 *addr = (volatile u32*)((u64)mmio_base + offset); volatile u32 *addr = (volatile u32 *)((u64)mmio_base + offset);
return *addr; return *addr;
} }
// Read from ACPI register (64-bit) // Read from ACPI register (64-bit)
u64 acpi_read64(void *mmio_base, u64 offset) { u64 acpi_read64(void *mmio_base, u64 offset) {
volatile u64 *addr = (volatile u64*)((u64)mmio_base + offset); volatile u64 *addr = (volatile u64 *)((u64)mmio_base + offset);
return *addr; return *addr;
} }
// Write to ACPI register (8-bit) // Write to ACPI register (8-bit)
void acpi_write8(void *mmio_base, u64 offset, u8 value) { void acpi_write8(void *mmio_base, u64 offset, u8 value) {
volatile u8 *addr = (volatile u8*)((u64)mmio_base + offset); volatile u8 *addr = (volatile u8 *)((u64)mmio_base + offset);
*addr = value; *addr = value;
} }
// Write to ACPI register (16-bit) // Write to ACPI register (16-bit)
void acpi_write16(void *mmio_base, u64 offset, u16 value) { void acpi_write16(void *mmio_base, u64 offset, u16 value) {
volatile u16 *addr = (volatile u16*)((u64)mmio_base + offset); volatile u16 *addr = (volatile u16 *)((u64)mmio_base + offset);
*addr = value; *addr = value;
} }
// Write to ACPI register (32-bit) // Write to ACPI register (32-bit)
void acpi_write32(void *mmio_base, u64 offset, u32 value) { void acpi_write32(void *mmio_base, u64 offset, u32 value) {
volatile u32 *addr = (volatile u32*)((u64)mmio_base + offset); volatile u32 *addr = (volatile u32 *)((u64)mmio_base + offset);
*addr = value; *addr = value;
} }
// Write to ACPI register (64-bit) // Write to ACPI register (64-bit)
void acpi_write64(void *mmio_base, u64 offset, u64 value) { void acpi_write64(void *mmio_base, u64 offset, u64 value) {
volatile u64 *addr = (volatile u64*)((u64)mmio_base + offset); volatile u64 *addr = (volatile u64 *)((u64)mmio_base + offset);
*addr = value; *addr = value;
} }
// Example: Map and access ACPI PM1a Control Block // Example: Map and access ACPI PM1a Control Block
void* map_acpi_pm1a_control(u64 physical_addr) { void *map_acpi_pm1a_control(u64 physical_addr) {
print("Mapping ACPI PM1a Control Block...\n"); print("Mapping ACPI PM1a Control Block...\n");
// PM1a Control is typically 2 bytes, but map at least one page // PM1a Control is typically 2 bytes, but map at least one page
void *mmio = map_mmio(physical_addr, 4096); void *mmio = map_mmio(physical_addr, 4096);
if (mmio) { if (mmio) {
print("PM1a Control Block mapped at virtual: 0x"); print("PM1a Control Block mapped at virtual: 0x");
print64((u64)mmio); print64((u64)mmio);
print("\n"); print("\n");
} }
return mmio; return mmio;
} }
// Example: Map ACPI tables (FADT, MADT, etc.) // Example: Map ACPI tables (FADT, MADT, etc.)
void* map_acpi_table(u64 physical_addr, u64 size) { void *map_acpi_table(u64 physical_addr, u64 size) {
print("Mapping ACPI table...\n"); print("Mapping ACPI table...\n");
print(" Physical: 0x"); print(" Physical: 0x");
print64(physical_addr); print64(physical_addr);
print("\n Size: "); print("\n Size: ");
print64(size); print64(size);
print(" bytes\n"); print(" bytes\n");
void *table = map_mmio(physical_addr, size); void *table = map_mmio(physical_addr, size);
if (table) { if (table) {
print("ACPI table mapped at virtual: 0x"); print("ACPI table mapped at virtual: 0x");
print64((u64)table); print64((u64)table);
print("\n"); print("\n");
} }
return table; return table;
} }
void print_page_mapping(u64 virtual_addr) { void print_page_mapping(u64 virtual_addr) {
print("Page mapping for virtual 0x"); print("Page mapping for virtual 0x");
print64(virtual_addr); print64(virtual_addr);
print(":\n"); print(":\n");
u64 pml4_phys = get_cr3(); u64 pml4_phys = get_cr3();
struct page_entry *pml4 = phys_to_virt(pml4_phys); struct page_entry *pml4 = phys_to_virt(pml4_phys);
u64 pml4_index = (virtual_addr >> 39) & 0x1FF; u64 pml4_index = (virtual_addr >> 39) & 0x1FF;
u64 pdpt_index = (virtual_addr >> 30) & 0x1FF; u64 pdpt_index = (virtual_addr >> 30) & 0x1FF;
u64 pd_index = (virtual_addr >> 21) & 0x1FF; u64 pd_index = (virtual_addr >> 21) & 0x1FF;
u64 pt_index = (virtual_addr >> 12) & 0x1FF; u64 pt_index = (virtual_addr >> 12) & 0x1FF;
print(" Indices: PML4["); print(" Indices: PML4[");
print64(pml4_index); print64(pml4_index);
print("] PDPT["); print("] PDPT[");
print64(pdpt_index); print64(pdpt_index);
print("] PD["); print("] PD[");
print64(pd_index); print64(pd_index);
print("] PT["); print("] PT[");
print64(pt_index); print64(pt_index);
print("]\n"); print("]\n");
if (!pml4[pml4_index].present) { if (!pml4[pml4_index].present) {
print(" PML4 entry not present!\n"); print(" PML4 entry not present!\n");
return; return;
} }
print(" PML4 entry present, frame=0x"); print(" PML4 entry present, frame=0x");
print64((u64)pml4[pml4_index].frame << 12); print64((u64)pml4[pml4_index].frame << 12);
print("\n"); print("\n");
struct page_entry *pdpt = phys_to_virt((u64)pml4[pml4_index].frame << 12); struct page_entry *pdpt = phys_to_virt((u64)pml4[pml4_index].frame << 12);
if (!pdpt[pdpt_index].present) { if (!pdpt[pdpt_index].present) {
print(" PDPT entry not present!\n"); print(" PDPT entry not present!\n");
return; return;
} }
print(" PDPT entry present, frame=0x"); print(" PDPT entry present, frame=0x");
print64((u64)pdpt[pdpt_index].frame << 12); print64((u64)pdpt[pdpt_index].frame << 12);
print("\n"); print("\n");
if (pdpt[pdpt_index].huge_page) { if (pdpt[pdpt_index].huge_page) {
print(" 1GB huge page!\n"); print(" 1GB huge page!\n");
return; return;
} }
struct page_entry *pd = phys_to_virt((u64)pdpt[pdpt_index].frame << 12); struct page_entry *pd = phys_to_virt((u64)pdpt[pdpt_index].frame << 12);
if (!pd[pd_index].present) { if (!pd[pd_index].present) {
print(" PD entry not present!\n"); print(" PD entry not present!\n");
return; return;
} }
print(" PD entry present, frame=0x"); print(" PD entry present, frame=0x");
print64((u64)pd[pd_index].frame << 12); print64((u64)pd[pd_index].frame << 12);
print("\n"); print("\n");
if (pd[pd_index].huge_page) { if (pd[pd_index].huge_page) {
print(" 2MB huge page!\n"); print(" 2MB huge page!\n");
return; return;
} }
struct page_entry *pt = phys_to_virt((u64)pd[pd_index].frame << 12); struct page_entry *pt = phys_to_virt((u64)pd[pd_index].frame << 12);
if (!pt[pt_index].present) { if (!pt[pt_index].present) {
print(" PT entry not present!\n"); print(" PT entry not present!\n");
return; return;
} }
print(" PT entry present:\n"); print(" PT entry present:\n");
print(" Physical frame: 0x"); print(" Physical frame: 0x");
print64((u64)pt[pt_index].frame << 12); print64((u64)pt[pt_index].frame << 12);
print("\n Writable: "); print("\n Writable: ");
print64(pt[pt_index].writable); print64(pt[pt_index].writable);
print("\n Cache disabled: "); print("\n Cache disabled: ");
print64(pt[pt_index].cache_disabled); print64(pt[pt_index].cache_disabled);
print("\n No execute: "); print("\n No execute: ");
print64(pt[pt_index].no_execute); print64(pt[pt_index].no_execute);
print("\n"); print("\n");
} }

View File

@ -2,5 +2,5 @@
#include "common.h" #include "common.h"
void* map_mmio(u64, u64); void *map_mmio(u64, u64);
int test_if_mapped(u64 virt_addr); int test_if_mapped(u64 virt_addr);

View File

@ -9,17 +9,15 @@ static size_t row;
static size_t col; static size_t col;
static size_t term_width, term_height; static size_t term_width, term_height;
static size_t fb_width, fb_height; static size_t fb_width, fb_height;
static volatile u32* fb_scr; static volatile u32 *fb_scr;
#define TAB_STOP 4 #define TAB_STOP 4
// buffer at each edge for readability // buffer at each edge for readability
#define TERM_WIDTH (FONT_WIDTH+2) #define TERM_WIDTH (FONT_WIDTH + 2)
#define TERM_HEIGHT (FONT_HEIGHT+2) #define TERM_HEIGHT (FONT_HEIGHT + 2)
void print_init(struct limine_framebuffer *fb) {
void print_init(struct limine_framebuffer* fb) {
term_width = fb->width / TERM_WIDTH; term_width = fb->width / TERM_WIDTH;
term_height = fb->height / TERM_HEIGHT; term_height = fb->height / TERM_HEIGHT;
fb_width = fb->width; fb_width = fb->width;
@ -28,7 +26,8 @@ void print_init(struct limine_framebuffer* fb) {
} }
static void scrollback() { static void scrollback() {
memmove((void*)fb_scr, (void*)(fb_scr + fb_width*TERM_HEIGHT), fb_width*(fb_height-1)*sizeof(u32)); memmove((void *)fb_scr, (void *)(fb_scr + fb_width * TERM_HEIGHT),
fb_width * (fb_height - TERM_HEIGHT) * sizeof(u32));
} }
void put(int ch) { void put(int ch) {
@ -70,8 +69,9 @@ void put(int ch) {
for (size_t y = 0; y < TERM_HEIGHT; y++) { for (size_t y = 0; y < TERM_HEIGHT; y++) {
for (size_t x = 0; x < TERM_WIDTH; x++) { for (size_t x = 0; x < TERM_WIDTH; x++) {
size_t off = (py + y) * fb_width + (px + x); size_t off = (py + y) * fb_width + (px + x);
bool padding = (y == 0 || y == TERM_HEIGHT-1 || x == 0 || x == TERM_WIDTH-1); bool padding =
fb_scr[off] = ((~glyph & 1) | padding )? bg : fg; (y == 0 || y == TERM_HEIGHT - 1 || x == 0 || x == TERM_WIDTH - 1);
fb_scr[off] = ((~glyph & 1) | padding) ? bg : fg;
glyph >>= !padding; glyph >>= !padding;
} }
} }
@ -79,15 +79,14 @@ void put(int ch) {
col++; col++;
} }
void print(const char *msg) {
void print(const char* msg) { while (*msg) {
while(*msg) {
put(*(msg++)); put(*(msg++));
} }
} }
void printn(const char* msg, size_t len) { void printn(const char *msg, size_t len) {
while(len-->0) { while (len-- > 0) {
put(*(msg++)); put(*(msg++));
} }
} }
@ -95,8 +94,8 @@ void printn(const char* msg, size_t len) {
static u8 digits[] = "0123456789ABCDEF"; static u8 digits[] = "0123456789ABCDEF";
void print8(u8 n) { void print8(u8 n) {
put(digits[n>>4]); put(digits[n >> 4]);
put(digits[n&0xf]); put(digits[n & 0xf]);
} }
void print16(u16 n) { void print16(u16 n) {

View File

@ -1,16 +1,15 @@
#pragma once #pragma once
#include "common.h" #include "common.h"
struct limine_framebuffer; struct limine_framebuffer;
void put(int ch); void put(int ch);
void print(const char* msg); void print(const char *msg);
void printn(const char* msg, size_t len); void printn(const char *msg, size_t len);
void print64(u64 n); void print64(u64 n);
void print32(u32 n); void print32(u32 n);
void print16(u16 n); void print16(u16 n);
void print8(u8 n); void print8(u8 n);
void print_init(struct limine_framebuffer* fb); void print_init(struct limine_framebuffer *fb);