Luna/kernel/src/acpi/RSDT.cpp

103 lines
3.6 KiB
C++
Raw Normal View History

#define MODULE "acpi"
2022-09-05 16:13:51 +02:00
#include "acpi/RSDT.h"
#include "bootboot.h"
#include "log/Log.h"
#include "memory/MemoryManager.h"
2022-09-05 16:13:51 +02:00
#include "std/stdio.h"
#include "std/string.h"
extern BOOTBOOT bootboot;
2022-09-25 21:43:28 +02:00
ACPI::SDTHeader* ACPI::get_rsdt_or_xsdt()
2022-09-05 16:13:51 +02:00
{
static void* cache = nullptr;
if (cache) return (SDTHeader*)cache;
2022-09-08 17:03:17 +02:00
kdbgln("First time accessing the RSDT/XSDT, mapping it into memory");
void* physical = (void*)bootboot.arch.x86_64.acpi_ptr;
uint64_t offset = (uint64_t)physical % 4096;
2022-09-08 17:03:17 +02:00
kdbgln("RSDT/XSDT physical address: %lx", (uint64_t)physical);
cache = MemoryManager::get_unaligned_mapping(physical);
uint64_t numPages = 1;
while ((offset + ((SDTHeader*)cache)->Length) > (numPages * 4096))
{
2022-09-08 17:03:17 +02:00
kwarnln("RSDT/XSDT extends beyond the mapped page, mapping one more page");
MemoryManager::release_unaligned_mappings(cache, numPages);
numPages++;
cache = MemoryManager::get_unaligned_mappings(cache, numPages);
}
2022-09-08 17:03:17 +02:00
kdbgln("Mapped RSDT/XSDT to virtual address %lx, uses %ld pages", (uint64_t)cache, numPages);
SDTHeader* result = (SDTHeader*)cache;
return result;
}
2022-09-25 21:43:28 +02:00
bool ACPI::validate_rsdt_or_xsdt(ACPI::SDTHeader* root_sdt)
{
2022-09-25 21:43:28 +02:00
if (!validate_sdt_header(root_sdt)) return false;
if (strncmp(root_sdt->Signature, "XSDT", 4) == 0) return true;
if (strncmp(root_sdt->Signature, "RSDT", 4) == 0) return true;
return false;
}
2022-09-25 21:43:28 +02:00
bool ACPI::is_xsdt()
{
2022-09-10 18:42:40 +02:00
static bool cached = false;
static bool cache = false;
if (cached) return cache;
2022-09-25 21:43:28 +02:00
SDTHeader* rootSDT = get_rsdt_or_xsdt();
2022-09-10 18:42:40 +02:00
cache = (strncmp(rootSDT->Signature, "XSDT", 4) == 0);
cached = true;
return cache;
2022-09-05 16:13:51 +02:00
}
2022-09-25 21:43:28 +02:00
void* ACPI::find_table(ACPI::SDTHeader* root_sdt, const char* signature)
2022-09-05 16:13:51 +02:00
{
2022-09-25 21:43:28 +02:00
bool isXSDT = is_xsdt();
2022-10-06 17:13:34 +02:00
uint64_t entries = (root_sdt->Length - sizeof(SDTHeader)) / (isXSDT ? 8 : 4);
kdbgln("Searching for table %s in the %s at %lx (table contains %ld entries)", signature, isXSDT ? "XSDT" : "RSDT",
2022-09-25 21:43:28 +02:00
(uint64_t)root_sdt, entries);
2022-09-05 16:13:51 +02:00
2022-10-06 17:13:34 +02:00
for (uint64_t i = 0; i < entries; i++)
2022-09-05 16:13:51 +02:00
{
2022-10-06 17:13:34 +02:00
kdbgln("Testing for table %s in entry %ld", signature, i);
2022-09-05 16:13:51 +02:00
SDTHeader* h;
if (isXSDT)
{
2022-09-25 21:43:28 +02:00
uint64_t reversedAddress = (uint64_t)((XSDT*)root_sdt)->other_sdt[i];
uint64_t correctAddress = reversedAddress >> 32 | reversedAddress << 32;
h = (SDTHeader*)correctAddress;
}
2022-09-05 16:13:51 +02:00
else
{
2022-09-25 21:43:28 +02:00
uint32_t entry = ((RSDT*)root_sdt)->other_sdt[i];
h = (SDTHeader*)(uint64_t)entry;
}
if (!h)
{
2022-10-06 17:13:34 +02:00
kwarnln("Entry %ld in the %s points to null", i, isXSDT ? "XSDT" : "RSDT");
continue;
}
2022-09-08 17:03:17 +02:00
kdbgln("Physical address of entry: %lx", (uint64_t)h);
SDTHeader* realHeader = (SDTHeader*)MemoryManager::get_unaligned_mapping(h);
2022-09-08 17:03:17 +02:00
kdbgln("Mapped entry to virtual address %lx", (uint64_t)realHeader);
2022-09-25 21:43:28 +02:00
if (!validate_sdt_header(realHeader))
{
2022-10-06 17:13:34 +02:00
kwarnln("Header of entry %ld is not valid, skipping this entry", i);
MemoryManager::release_unaligned_mapping(realHeader);
continue;
}
char tableSignature[5];
memcpy(tableSignature, h->Signature, 4);
tableSignature[4] = 0;
2022-09-08 17:03:17 +02:00
kdbgln("Comparing target signature (%s) to signature of entry (%s)", signature, tableSignature);
if (strncmp(h->Signature, signature, 4) == 0)
{
2022-09-08 17:03:17 +02:00
kdbgln("Found table %s", signature);
return (void*)realHeader;
}
2022-09-08 17:03:17 +02:00
kdbgln("Signatures do not match, unmapping entry and continuing");
MemoryManager::release_unaligned_mapping(realHeader);
2022-09-05 16:13:51 +02:00
}
return NULL;
}