rk/kmain.c
2024-05-20 17:39:20 -04:00

126 lines
3.4 KiB
C

#include <multiboot.h>
#include <acpi.h>
#include <vga.h>
#include <printf.h>
#include <strcmp.h>
struct kernel_context {
struct rsdp *rsdp;
struct xsdp *xsdp;
struct rsdt *rsdt;
};
struct kernel_context ctx = {0};
void *acpi_find_sdt(void *RootSDT, const char sig[4]) {
struct rsdt *rsdt = (struct rsdt *) RootSDT;
int entries = (rsdt->h.Length - sizeof(rsdt->h)) / 4;
for (int i = 0; i < entries; i++)
{
struct ACPISDTHeader *h = (struct ACPISDTHeader *) rsdt->other_sdt[i];
if (!strncmp(h->Signature, sig, 4))
return (void *) h;
}
return 0;
}
uint16_t readw(uint32_t addr, uint32_t offset, uint8_t bus, uint8_t slot, uint8_t func) {
uint32_t lbus = (uint32_t)bus;
uint32_t lslot = (uint32_t)slot;
uint32_t lfunc = (uint32_t)func;
uint32_t address = addr + offset + ((lbus) << 20 | lslot << 15 | lfunc << 12);
return *(uint16_t *)address;
}
uint8_t readb(uint32_t addr, uint32_t offset, uint8_t bus, uint8_t slot, uint8_t func) {
uint32_t lbus = (uint32_t)bus;
uint32_t lslot = (uint32_t)slot;
uint32_t lfunc = (uint32_t)func;
uint32_t address = addr + offset + ((lbus) << 20 | lslot << 15 | lfunc << 12);
return *(uint8_t *)address;
}
uint32_t readd(uint32_t addr, uint32_t offset, uint8_t bus, uint8_t slot, uint8_t func) {
uint32_t lbus = (uint32_t)bus;
uint32_t lslot = (uint32_t)slot;
uint32_t lfunc = (uint32_t)func;
uint32_t address = addr + offset + ((lbus) << 20 | lslot << 15 | lfunc << 12);
return *(uint32_t *)address;
}
void kmain(struct multiboot_info *info) {
clear_screen();
// Check if the bootloader gave us the upper and lower memory
if (!(info->flags & 0x1)) goto halt;
struct rsdp *found_rsdp = acpi_search_for_rsdp();
if (!found_rsdp) {
printf("Failed to find RSDP signature\n");
goto halt;
}
printf("RSDP detected at 0x%X\n", found_rsdp);
if (found_rsdp->Revision == ACPI_VER_1) {
// ACPI v1.0 is being used
if (!acpi_validate_rsdp_checksum(found_rsdp)) {
printf("RSDP has an invalid checksum\n");
goto halt;
}
ctx.rsdp = found_rsdp;
ctx.xsdp = 0;
if (!acpi_validate_sdt_checksum((struct ACPISDTHeader *)found_rsdp->RsdtAddress)) {
printf("RSDT has an invalid checksum\n");
goto halt;
}
ctx.rsdt = (struct rsdt*)found_rsdp->RsdtAddress;
printf("RSDT detected at 0x%X\n", found_rsdp->RsdtAddress);
} else if (found_rsdp->Revision == ACPI_VER_OTHER) {
printf("ACPI versions higher than 1.0 are not supported\n");
goto halt;
} else {
printf("Invalid RSDP\n");
goto halt;
}
printf("Using ACPI v1.0\n");
struct mcfg *mcfg = acpi_find_sdt(ctx.rsdt, "MCFG");
if (!mcfg) {
printf("Failed to find MCFG\n");
goto halt;
}
printf("Detected MCFG at 0x%X\n", mcfg);
int entries = (mcfg->h.Length - 44) / 16;
for (int i = 0; i < entries; i++) {
uint32_t addr = (uint32_t)mcfg->entries[i].base_addr;
for (int j = 0; j < 256; j++) {
for (int k = 0; k < 8; k++) {
uint32_t word = readd(addr, 8, i, j, k);
if (word != 0xFFFFFFFF && word) {
printf("%08X\n", word >> 8);
}
}
}
}
halt:
for (;;) {}
}