summaryrefslogtreecommitdiffhomepage
path: root/src/loader/acpi.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/loader/acpi.c')
-rw-r--r--src/loader/acpi.c92
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);
+}