2024-05-26 02:33:18 -04:00
|
|
|
#include <kernel/acpi.h>
|
|
|
|
#include <kernel/strcmp.h>
|
2024-05-27 14:18:37 -04:00
|
|
|
#include <kernel/vga.h>
|
|
|
|
#include <kernel/printf.h>
|
|
|
|
#include <kernel/kernel.h>
|
2024-05-20 05:59:07 -04:00
|
|
|
|
2024-05-21 22:07:04 -04:00
|
|
|
struct rsdp *acpi_locate_rsdp() {
|
2024-05-20 05:59:07 -04:00
|
|
|
char *ptr = (char *)BIOS_START;
|
|
|
|
char *str = RSDP_SIG;
|
|
|
|
|
|
|
|
while ((uint32_t)ptr <= (uint32_t)BIOS_END - RSDP_SIG_LEN) {
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < RSDP_SIG_LEN; i++) {
|
|
|
|
if (ptr[i] != str[i])
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (i == RSDP_SIG_LEN) {
|
|
|
|
return (struct rsdp *)ptr;
|
|
|
|
}
|
|
|
|
ptr++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int acpi_validate_rsdp_checksum(struct rsdp *s) {
|
|
|
|
uint8_t *bytes = (uint8_t *)s;
|
|
|
|
uint8_t sum = 0;
|
|
|
|
for (int i = 0; i < RSDP_SIZE; i++) {
|
|
|
|
sum += bytes[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
return (sum & 0x0F) == 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int acpi_validate_sdt_checksum(struct ACPISDTHeader *s) {
|
|
|
|
uint8_t sum = 0;
|
|
|
|
for (uint32_t i = 0; i < s->Length; i++) {
|
|
|
|
sum += ((char *)s)[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
return sum == 0;
|
|
|
|
}
|
2024-05-21 22:07:04 -04:00
|
|
|
|
|
|
|
void *acpi_locate_sdt(struct rsdt *rsdt, const char sig[4]) {
|
|
|
|
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)) {
|
|
|
|
if (acpi_validate_sdt_checksum(h))
|
|
|
|
return (void *) h;
|
|
|
|
else
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2024-05-27 14:18:37 -04:00
|
|
|
|
|
|
|
int acpi_init(struct kernel_context *ctx) {
|
|
|
|
struct rsdp *found_rsdp = acpi_locate_rsdp();
|
|
|
|
if (!found_rsdp) {
|
|
|
|
set_color(VGA_COLOR_RED);
|
|
|
|
printf("Failed to find RSDP signature\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (found_rsdp->Revision == ACPI_VER_1) {
|
|
|
|
if (!acpi_validate_rsdp_checksum(found_rsdp)) {
|
|
|
|
set_color(VGA_COLOR_RED);
|
|
|
|
printf("RSDP has an invalid checksum\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
ctx->rsdp = found_rsdp;
|
|
|
|
ctx->xsdp = 0;
|
|
|
|
|
|
|
|
if (!acpi_validate_sdt_checksum((struct ACPISDTHeader *)found_rsdp->RsdtAddress)) {
|
|
|
|
set_color(VGA_COLOR_RED);
|
|
|
|
printf("RSDT has an invalid checksum\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
ctx->rsdt = (struct rsdt*)found_rsdp->RsdtAddress;
|
|
|
|
|
|
|
|
} else if (found_rsdp->Revision == ACPI_VER_OTHER) {
|
|
|
|
set_color(VGA_COLOR_RED);
|
|
|
|
printf("ACPI versions higher than 1.0 are not yet supported because I'm lazy\n");
|
|
|
|
return 0;
|
|
|
|
} else {
|
|
|
|
set_color(VGA_COLOR_RED);
|
|
|
|
printf("Invalid RSDP\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
printf("[KERNEL] Using ACPI v1.0\n");
|
|
|
|
|
|
|
|
struct fadt *fadt = acpi_locate_sdt(ctx->rsdt, "FACP");
|
|
|
|
if (!fadt) {
|
|
|
|
set_color(VGA_COLOR_RED);
|
|
|
|
printf("Failed to find FADT\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
printf("[KERNEL] Found FADT at 0x%x\n", fadt);
|
|
|
|
if (fadt->Flags & 1)
|
|
|
|
printf("[KERNEL] Legacy devices are supported\n");
|
|
|
|
else {
|
|
|
|
/*
|
|
|
|
set_color(VGA_COLOR_RED);
|
|
|
|
printf("Legacy devices are not supported. I'm too lazy to support modern devices, bye bye.\n");
|
|
|
|
goto halt;
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|