diff options
Diffstat (limited to 'src/loader/acpi.c')
-rw-r--r-- | src/loader/acpi.c | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/src/loader/acpi.c b/src/loader/acpi.c new file mode 100644 index 0000000..f7e958c --- /dev/null +++ b/src/loader/acpi.c @@ -0,0 +1,92 @@ +// MIT License, Copyright (c) 2021 Marvin Borner + +#include <acpi.h> +#include <lib.h> +#include <pnc.h> + +/** + * General SDP + */ + +static u8 acpi_sdp_verify(struct sdp_header *header) +{ + u8 sum = 0; + + for (u32 i = 0; i < sizeof(struct rsdp); i++) + sum += (u8)(((u8 *)header)[i]); + + return sum == 0; +} + +/** + * General SDT + */ + +static u8 acpi_sdt_verify(struct sdt_header *header) +{ + u8 sum = 0; + + for (u32 i = 0; i < header->length; i++) + sum += (u8)(((u8 *)header)[i]); + + return sum == 0; +} + +static void *acpi_sdt_find(struct rsdt *rsdt, const char *signature) +{ + u32 entries = (rsdt->header.length - sizeof(rsdt->header)) / 4; + + for (u32 i = 0; i < entries; i++) { + struct sdt_header *header = (struct sdt_header *)rsdt->sdt_pointer[i]; + if (memcmp(header->signature, signature, 4) == 0) { + if (acpi_sdt_verify(header)) + return header; + else + break; + } + } + + return NULL; +} + +/** + * RSDP - points to RSDT + */ + +static struct rsdp *acpi_rsdp_find(void) +{ + // Main BIOS area + for (u32 i = 0xe0000; i < 0xfffff; i++) + if (memcmp((u32 *)i, RSDP_MAGIC, 8) == 0) + return (struct rsdp *)i; + + // Or first KB of EBDA? + u8 *ebda = (void *)(*((u16 *)0x40e) << 4); + for (u16 i = 0; i < 1024; i += 16) + if (memcmp(ebda + i, RSDP_MAGIC, 8) == 0) + return (struct rsdp *)(ebda + i); + + return NULL; +} + +/** + * Probe + */ + +void acpi_probe(void) +{ + struct rsdp *rsdp = acpi_rsdp_find(); + assert(rsdp && rsdp->header.revision == 0 && acpi_sdp_verify(&rsdp->header)); + struct rsdt *rsdt = rsdp->rsdt; + assert(rsdt && memcmp(rsdt->header.signature, RSDT_MAGIC, 4) == 0 && + acpi_sdt_verify(&rsdt->header)); + + struct madt *madt = acpi_sdt_find(rsdt, MADT_MAGIC); + struct fadt *fadt = acpi_sdt_find(rsdt, FADT_MAGIC); + struct hpet *hpet = acpi_sdt_find(rsdt, HPET_MAGIC); + + // TODO! + UNUSED(madt); + UNUSED(fadt); + UNUSED(hpet); +} |