126 lines
3.4 KiB
C
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 (;;) {}
|
|
}
|