/* * Copyright (c) 2026, Chloe M. * Provided under the BSD-3 clause. * * Description: ACPI init * Author: Chloe M. */ #include #include #include #include #include #include #include #define DTRACE(Fmt, ...) \ TRACE("[ ACPI ]: " Fmt, ##__VA_ARGS__) static ACPI_RSDP *Rsdp; static ACPI_ROOT_SDT *RootSdt; static USIZE RootSdtEntries; static VOID AcpiPrintVendor(VOID) { UCHAR Revision; /* * On certain emulators this may become zero, just bump it up to * one because its behaviors are the same. */ Revision = Rsdp->Revision; if (Revision == 0) { ++Revision; } DTRACE("detected acpi %d.0 by %.6s\n", Revision, Rsdp->Oemid); } static VOID RsdpVerify(VOID) { UCHAR Checksum = 0; USIZE Idx; for (Idx = 0; Idx < Rsdp->Length; ++Idx) { Checksum += ((UCHAR *)Rsdp)[Idx]; } if ((Checksum & 0xFF) != 0) { KeKnot( KNOT_BAD_CHECKSUM, "Got bad checksum %x for ACPI RSDP\n", Checksum ); } DTRACE("checksum ok\n"); } VOID * AcpiQuery(const CHAR *Signature) { BOOLEAN IsMatch; ACPI_HEADER *Header; UPTR Pma; USIZE Idx; if (Signature == NULL) { return NULL; } for (Idx = 0; Idx < RootSdtEntries; ++Idx) { Pma = (UPTR)RootSdt->Tables[Idx]; Header = (ACPI_HEADER *)PMA_TO_VMA(Pma); IsMatch = !RtlMemCmp( Header->Signature, Signature, sizeof(Header->Signature) ); if (IsMatch) { return (VOID *)Header; } } return NULL; } VOID AcpiInit(VOID) { BPAL_HANDLE BpalHandle; KeBpalGetHandle(&BpalHandle); Rsdp = BpalHandle.RsdpBase; AcpiPrintVendor(); RsdpVerify(); /* Select the correct root sdt */ if (Rsdp->Revision < 2) { DTRACE("using rsdt as root sdt\n"); RootSdt = PMA_TO_VMA((UPTR)Rsdp->RsdtAddr); RootSdtEntries = (RootSdt->Header.Length - sizeof(RootSdt->Header)) / 4; } else { DTRACE("using xsdt as root sdt\n"); RootSdt = PMA_TO_VMA((UPTR)Rsdp->XsdtAddr); RootSdtEntries = (RootSdt->Header.Length - sizeof(RootSdt->Header)) / 8; } }