From 592133af39074bbdc3d2d57105e3b9d4a0632d57 Mon Sep 17 00:00:00 2001 From: Matheus Date: Fri, 5 Aug 2022 17:27:01 -0300 Subject: [PATCH] ACPI tables support Added parsing for the (X)RSDT and RSDP, as well as table searching. --- src/arch/x86_64/acpi.c | 82 +++++++++++++++++++++++++++++ src/arch/x86_64/include/arch/acpi.h | 44 ++++++++++++++++ src/arch/x86_64/main.c | 3 ++ 3 files changed, 129 insertions(+) create mode 100644 src/arch/x86_64/acpi.c create mode 100644 src/arch/x86_64/include/arch/acpi.h diff --git a/src/arch/x86_64/acpi.c b/src/arch/x86_64/acpi.c new file mode 100644 index 00000000..330b3f4c --- /dev/null +++ b/src/arch/x86_64/acpi.c @@ -0,0 +1,82 @@ +#include +#include +#include +#include +#include +#include +#include + +static bool usersdt = false; +static sdt_t* sdt; +static size_t sdtentrycount; + + +static volatile struct limine_rsdp_request rsdpreq = { + .id = LIMINE_RSDP_REQUEST, + .revision = 0 +}; + +static bool checksumok(sdt_t* table){ + uint8_t sum; + uint8_t* ptr = (uint8_t*)table; + + for(size_t i = 0; i < table->length; ++i) + sum += *ptr++; + + return sum == 0; +} + +void* acpi_gettable(char* sig, size_t n){ + size_t ptrsize = usersdt ? 4 : 8; + + void* ptr = (char*)sdt + sizeof(sdt_t); + + + for(size_t i = 0; i < sdtentrycount; ++i){ + + sdt_t* table = usersdt ? (*(uint32_t*)ptr & 0xFFFFFFFF) : *(uint64_t*)ptr; + + table = (uint8_t*)table + (size_t)limine_hhdm_offset; + + if(!strncmp(sig, table->signature, 4)){ + if(n-- == 0) + return (uint8_t*)table + (size_t) limine_hhdm_offset; + + } + + ptr += ptrsize; + + } + + return NULL; + +} + +void acpi_init(){ + if(!rsdpreq.response){ + // TODO search for ourselves + _panic("No reponse for the RSDP request", 0); + } + + rsdp_t* rsdp = rsdpreq.response->address; + + printf("RSDP at: %p\n", rsdp); + + sdt = rsdp->xsdtaddr; + + if(rsdp->revision == 0){ + printf("WARNING: XSDT does not exist in revision 0, falling back to RSDT!\n"); + sdt = rsdp->rsdtaddr; + usersdt = true; + } + + sdt = (uint8_t*)sdt + (size_t)limine_hhdm_offset; + + sdtentrycount = (sdt->length - sizeof(sdt_t)) / (usersdt ? 4 : 8); + + printf("Root System Description Table address: %p with %lu tables\n", sdt, sdtentrycount); + + if(!checksumok(sdt)) + _panic("Invalid RSDT checksum!", 0); + +} diff --git a/src/arch/x86_64/include/arch/acpi.h b/src/arch/x86_64/include/arch/acpi.h new file mode 100644 index 00000000..0cd24ace --- /dev/null +++ b/src/arch/x86_64/include/arch/acpi.h @@ -0,0 +1,44 @@ +#ifndef _ACPI_H_INCLUDE +#define _ACPI_H_INCLUDE + +#include +#include + +typedef struct { + char signature[8]; + uint8_t checksum; + char oem[6]; + uint8_t revision; + uint32_t rsdtaddr; + + uint32_t length; + uint64_t xsdtaddr; + uint8_t xchecksum; +} __attribute__((packed))rsdp_t; + +typedef struct { + char signature[4]; + uint32_t length; + uint8_t revision; + uint8_t checksum; + char oem[6]; + char oemtable[8]; + uint32_t oemrevision; + uint32_t creator; + uint32_t creatorrevision; +} __attribute__((packed)) sdt_t; + +typedef struct { + sdt_t header; + uint64_t pointers[]; +} __attribute__((packed)) xsdt_t; + +typedef struct { + sdt_t header; + uint32_t pointers[]; +} __attribute__((packed)) rsdt_t; + +void* acpi_gettable(char* sig, size_t n); +void acpi_init(); + +#endif diff --git a/src/arch/x86_64/main.c b/src/arch/x86_64/main.c index a4bfb6b4..b357fcfc 100644 --- a/src/arch/x86_64/main.c +++ b/src/arch/x86_64/main.c @@ -8,6 +8,7 @@ #include #include #include +#include static volatile struct limine_terminal_request liminettyr = { .id = LIMINE_TERMINAL_REQUEST, @@ -56,6 +57,8 @@ void kmain(){ _panic("Failed to mount tmpfs", 0); initrd_parse(); + + acpi_init(); _panic("End of kmain()", 0);