2024-08-01 12:33:24 -04:00
|
|
|
#include <kernel/acpi.h>
|
|
|
|
#include <kernel/kernel.h>
|
|
|
|
|
2024-08-06 21:12:43 -04:00
|
|
|
extern kernel_ctx_t ctx;
|
|
|
|
|
2024-08-01 12:33:24 -04:00
|
|
|
rsdp_t *acpi_find_rsdp() {
|
|
|
|
char *ptr = (char *)(KERNEL_VMA + BIOS_START);
|
|
|
|
const char sig[RSDP_SIG_LEN] = RSDP_SIG;
|
|
|
|
|
|
|
|
for (; (uint32_t)ptr - KERNEL_VMA <= BIOS_END; ptr += 16) {
|
|
|
|
int i = 0;
|
|
|
|
for (; i < RSDP_SIG_LEN; i++)
|
|
|
|
if (ptr[i] != sig[i]) break;
|
|
|
|
|
|
|
|
if (i == RSDP_SIG_LEN) return (rsdp_t *)ptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2024-08-01 14:22:25 -04:00
|
|
|
uint8_t acpi_checksum(void *s, int size) {
|
2024-08-01 12:33:24 -04:00
|
|
|
uint32_t sum = 0;
|
|
|
|
for (int i = 0; i < size; i++) {
|
|
|
|
sum += ((uint8_t *)s)[i];
|
|
|
|
}
|
|
|
|
|
2024-08-01 14:22:25 -04:00
|
|
|
return (sum & 0xFF) == 0;
|
2024-08-01 12:33:24 -04:00
|
|
|
}
|
|
|
|
|
2024-08-01 14:22:25 -04:00
|
|
|
void *acpi_find_sdt(rsdt_t *rsdt, const char *sig) {
|
2024-08-01 12:33:24 -04:00
|
|
|
int entries = (rsdt->hdr.Length - sizeof(sdt_hdr_t)) / 4;
|
|
|
|
for (int i = 0; i < entries; i++) {
|
|
|
|
const char *ptr = (const char *)rsdt->other_tables[i];
|
|
|
|
int j = 0;
|
2024-08-01 14:22:25 -04:00
|
|
|
for (; j < 4; j++)
|
2024-08-01 12:33:24 -04:00
|
|
|
if (ptr[j] != sig[j]) break;
|
|
|
|
|
2024-08-01 14:22:25 -04:00
|
|
|
if (j == 4) return (void *)ptr;
|
2024-08-01 12:33:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2024-08-06 21:12:43 -04:00
|
|
|
|
|
|
|
bool acpi_init() {
|
|
|
|
rsdp_t *rsdp = acpi_find_rsdp();
|
|
|
|
if (!rsdp) {
|
|
|
|
LOG("Invalid RSDP\n");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
if (!acpi_checksum(rsdp, sizeof(rsdp_t))) {
|
|
|
|
LOG("Invalid RSDP checksum\n");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (rsdp->Revision == 0) LOG("Using ACPI version 1.0\n")
|
|
|
|
else if (rsdp->Revision == 2) {
|
|
|
|
LOG("ACPI versions higher than 1.0 are not currently supported!\n");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
rsdt_t *rsdt = (rsdt_t *)(rsdp->RsdtAddress);
|
|
|
|
if (!rsdt) {
|
|
|
|
LOG("Invalid RSDT\n");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
if (!acpi_checksum(rsdt, rsdt->hdr.Length)) {
|
|
|
|
LOG("Invalid RSDT checksum\n");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
ctx.rsdt = rsdt;
|
|
|
|
LOG("RSDT is valid\n");
|
|
|
|
|
|
|
|
void *mcfg = acpi_find_sdt(rsdt, "MCFG");
|
|
|
|
if (!mcfg) LOG("PCIe not supported\n");
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|