From fdf8724c1cc2c21d3786d11b889d16aafd57d842 Mon Sep 17 00:00:00 2001 From: Matheus Date: Thu, 20 Apr 2023 20:09:12 -0300 Subject: [PATCH] acpi: table parsing --- kernel-src/arch/x86-64/acpi.c | 72 +++++++++++++++++++++++++++ kernel-src/arch/x86-64/main.c | 2 + kernel-src/include/x86-64/arch/acpi.h | 43 ++++++++++++++++ 3 files changed, 117 insertions(+) create mode 100644 kernel-src/arch/x86-64/acpi.c create mode 100644 kernel-src/include/x86-64/arch/acpi.h diff --git a/kernel-src/arch/x86-64/acpi.c b/kernel-src/arch/x86-64/acpi.c new file mode 100644 index 00000000..2af7e178 --- /dev/null +++ b/kernel-src/arch/x86-64/acpi.c @@ -0,0 +1,72 @@ +#include +#include +#include +#include +#include +#include + +static size_t headercount; +static sdtheader_t **headers; + +static volatile struct limine_rsdp_request rsdpreq = { + .id = LIMINE_RSDP_REQUEST, + .revision = 0 +}; + +bool acpi_checksumok(void *table) { + sdtheader_t *header = table; + uint8_t *ptr = table; + uint8_t sum = 0; + for (int i = 0; i < header->length; ++i) + sum += *ptr++; + + return sum == 0; +} + +void *acpi_findtable(char *sig, int n) { + for (size_t i = 0; i < headercount; ++i) { + if (headers[i] == NULL) + continue; + + if (strncmp(sig, headers[i]->sig, 4) == 0) { + if (n-- == 0) + return headers[i]; + } + } + return NULL; +} + +void acpi_init() { + // FIXME search if no response + __assert(rsdpreq.response); + rsdp_t *rsdp = rsdpreq.response->address; + + if (rsdp->revision == 0) { + printf("\e[93mACPI version 1.0 -- Using RSDT instead of XSDT.\e[0m\n"); + rsdt_t *rsdt = MAKE_HHDM((rsdt_t *)(uint64_t)rsdp->rsdt); + __assert(acpi_checksumok(rsdt)); + headercount = (rsdt->header.length - sizeof(sdtheader_t)) / sizeof(uint32_t); + headers = alloc(sizeof(sdtheader_t *) * headercount); + __assert(headers); + + for (size_t i = 0; i < headercount; ++i) { + void *addr = MAKE_HHDM((void *)(uint64_t)rsdt->tables[i]); + if (acpi_checksumok(addr)) + headers[i] = addr; + } + } else { + xsdt_t *xsdt = MAKE_HHDM((xsdt_t *)rsdp->xsdt); + __assert(acpi_checksumok(xsdt)); + headercount = (xsdt->header.length - sizeof(sdtheader_t)) / sizeof(uint64_t); + headers = alloc(sizeof(sdtheader_t *) * headercount); + __assert(headers); + + for (size_t i = 0; i < headercount; ++i) { + void *addr = MAKE_HHDM((void *)xsdt->tables[i]); + if (acpi_checksumok(addr)) + headers[i] = addr; + } + } + + printf("ACPI: %lu tables found\n", headercount); +} diff --git a/kernel-src/arch/x86-64/main.c b/kernel-src/arch/x86-64/main.c index 51293e89..3b8b2016 100644 --- a/kernel-src/arch/x86-64/main.c +++ b/kernel-src/arch/x86-64/main.c @@ -9,6 +9,7 @@ #include #include #include +#include static cpu_t bsp_cpu; @@ -24,5 +25,6 @@ void kernel_entry() { arch_mmu_init(); vmm_init(); alloc_init(); + acpi_init(); __assert(!"kernel entry end"); } diff --git a/kernel-src/include/x86-64/arch/acpi.h b/kernel-src/include/x86-64/arch/acpi.h new file mode 100644 index 00000000..018a270d --- /dev/null +++ b/kernel-src/include/x86-64/arch/acpi.h @@ -0,0 +1,43 @@ +#ifndef _ACPI_H +#define _ACPI_H + +#include +#include +#include + +typedef struct { + char sig[8]; + uint8_t checksum; + char oem[6]; + uint8_t revision; + uint32_t rsdt; + uint32_t length; + uint64_t xsdt; + uint8_t xchecksum; + uint8_t reserved[3]; +} __attribute__((packed)) rsdp_t; + +typedef struct { + char sig[4]; + uint32_t length; + uint8_t revision; + uint8_t cechksum; + char oemid[6]; + char oemtableid[8]; + uint32_t oemrevision; + uint32_t creatorrevision; +} __attribute__((packed)) sdtheader_t; + +typedef struct { + sdtheader_t header; + uint64_t tables[]; +} __attribute__((packed)) xsdt_t; + +typedef struct { + sdtheader_t header; + uint32_t tables[]; +} __attribute__((packed)) rsdt_t; + +void acpi_init(); + +#endif