2022-09-07 19:41:08 +02:00
|
|
|
#define MODULE "acpi/rsdt"
|
|
|
|
|
2022-09-05 16:13:51 +02:00
|
|
|
#include "acpi/RSDT.h"
|
|
|
|
#include "bootboot.h"
|
2022-09-07 10:33:22 +02:00
|
|
|
#include "log/Address.h"
|
2022-09-07 19:41:08 +02:00
|
|
|
#include "log/Log.h"
|
2022-09-07 10:33:22 +02:00
|
|
|
#include "memory/KernelMemoryManager.h"
|
2022-09-05 16:13:51 +02:00
|
|
|
#include "std/stdio.h"
|
|
|
|
#include "std/string.h"
|
|
|
|
|
|
|
|
extern BOOTBOOT bootboot;
|
|
|
|
|
|
|
|
ACPI::SDTHeader* ACPI::GetRSDTOrXSDT()
|
|
|
|
{
|
2022-09-07 19:41:08 +02:00
|
|
|
static void* cache = nullptr;
|
|
|
|
if (cache) return (SDTHeader*)cache;
|
|
|
|
kinfoln("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;
|
|
|
|
kinfoln("RSDT/XSDT physical address: %lx", (uint64_t)physical);
|
|
|
|
cache = KernelMemoryManager::get_unaligned_mapping(physical);
|
|
|
|
uint64_t numPages = 1;
|
|
|
|
while ((offset + ((SDTHeader*)cache)->Length) > (numPages * 4096))
|
|
|
|
{
|
|
|
|
kinfoln("RSDT/XSDT extends beyond the mapped page, mapping one more page");
|
|
|
|
KernelMemoryManager::release_unaligned_mappings(cache, numPages);
|
|
|
|
numPages++;
|
|
|
|
cache = KernelMemoryManager::get_unaligned_mappings(cache, numPages);
|
|
|
|
}
|
|
|
|
kinfoln("Mapped RSDT/XSDT to virtual address %lx, uses %ld pages", (uint64_t)cache, numPages);
|
|
|
|
SDTHeader* result = (SDTHeader*)cache;
|
|
|
|
char OEMID[7];
|
|
|
|
memcpy(OEMID, result->OEMID, 6);
|
|
|
|
OEMID[6] = 0;
|
|
|
|
kinfoln("OEMID: %s", OEMID);
|
|
|
|
char OEMTableID[9];
|
|
|
|
memcpy(OEMTableID, result->OEMTableID, 8);
|
|
|
|
OEMTableID[8] = 0;
|
|
|
|
kinfoln("OEMTableID: %s", OEMTableID);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ACPI::ValidateRSDTOrXSDT(ACPI::SDTHeader* rootSDT)
|
|
|
|
{
|
|
|
|
if (!ValidateSDTHeader(rootSDT)) return false;
|
|
|
|
if (strncmp(rootSDT->Signature, "XSDT", 4) == 0) return true;
|
|
|
|
if (strncmp(rootSDT->Signature, "RSDT", 4) == 0) return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ACPI::IsXSDT(ACPI::SDTHeader* rootSDT)
|
|
|
|
{
|
|
|
|
return strncmp(rootSDT->Signature, "XSDT", 4) == 0;
|
2022-09-05 16:13:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void* ACPI::FindTable(ACPI::SDTHeader* rootSDT, const char* signature)
|
|
|
|
{
|
2022-09-06 11:46:47 +02:00
|
|
|
bool isXSDT = (strncmp(rootSDT->Signature, "XSDT", 4) == 0);
|
|
|
|
int entries = (rootSDT->Length - sizeof(SDTHeader)) / (isXSDT ? 8 : 4);
|
2022-09-07 19:41:08 +02:00
|
|
|
kinfoln("Searching for table %s in the %s at %lx (table contains %d entries)", signature, isXSDT ? "XSDT" : "RSDT",
|
|
|
|
(uint64_t)rootSDT, entries);
|
2022-09-05 16:13:51 +02:00
|
|
|
|
|
|
|
for (int i = 0; i < entries; i++)
|
|
|
|
{
|
2022-09-07 19:41:08 +02:00
|
|
|
kinfoln("Testing for table %s in entry %d", signature, i);
|
2022-09-05 16:13:51 +02:00
|
|
|
SDTHeader* h;
|
2022-09-07 19:41:08 +02:00
|
|
|
if (isXSDT)
|
|
|
|
{
|
|
|
|
uint64_t reversedAddress = (uint64_t)((XSDT*)rootSDT)->PointerToOtherSDT[i];
|
|
|
|
uint64_t correctAddress = reversedAddress >> 32 | reversedAddress << 32;
|
|
|
|
h = (SDTHeader*)correctAddress;
|
|
|
|
}
|
2022-09-05 16:13:51 +02:00
|
|
|
else
|
2022-09-06 11:46:47 +02:00
|
|
|
{
|
|
|
|
uint32_t entry = ((RSDT*)rootSDT)->PointerToOtherSDT[i];
|
|
|
|
h = (SDTHeader*)(uint64_t)entry;
|
|
|
|
}
|
2022-09-07 19:41:08 +02:00
|
|
|
if (!h)
|
|
|
|
{
|
|
|
|
kinfoln("Entry points to null");
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
kinfoln("Physical address of entry: %lx", (uint64_t)h);
|
2022-09-07 10:33:22 +02:00
|
|
|
SDTHeader* realHeader = (SDTHeader*)KernelMemoryManager::get_unaligned_mapping(h);
|
2022-09-07 19:41:08 +02:00
|
|
|
kinfoln("Mapped entry to virtual address %lx", (uint64_t)realHeader);
|
|
|
|
if (!ValidateSDTHeader(realHeader))
|
|
|
|
{
|
|
|
|
kinfoln("Header is not valid, skipping this entry");
|
|
|
|
KernelMemoryManager::release_unaligned_mapping(realHeader);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
char tableSignature[5];
|
|
|
|
memcpy(tableSignature, h->Signature, 4);
|
|
|
|
tableSignature[4] = 0;
|
|
|
|
kinfoln("Comparing target signature (%s) to signature of entry (%s)", signature, tableSignature);
|
|
|
|
if (strncmp(h->Signature, signature, 4) == 0)
|
|
|
|
{
|
|
|
|
kinfoln("Found table %s", signature);
|
|
|
|
return (void*)realHeader;
|
|
|
|
}
|
|
|
|
kinfoln("Signatures do not match, unmapping entry and continuing");
|
2022-09-07 10:33:22 +02:00
|
|
|
KernelMemoryManager::release_unaligned_mapping(realHeader);
|
2022-09-05 16:13:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|