diff --git a/paw/stos/drivers/acpi/acpi.c b/paw/stos/drivers/acpi/acpi.c new file mode 100644 index 0000000..7e0a8d0 --- /dev/null +++ b/paw/stos/drivers/acpi/acpi.c @@ -0,0 +1,111 @@ +/* + * 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; + } +} diff --git a/paw/stos/head/drivers/acpi/acpi.h b/paw/stos/head/drivers/acpi/acpi.h new file mode 100644 index 0000000..fa91b2c --- /dev/null +++ b/paw/stos/head/drivers/acpi/acpi.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2026, Chloe M. + * Provided under the BSD-3 clause. + * + * Description: ACPI driver + * Author: Chloe M. + */ + +#ifndef _ACPI_ACPI_H_ +#define _ACPI_ACPI_H_ 1 + +#include + +/* + * Initialize ACPI + */ +VOID AcpiInit(VOID); + +/* + * Query an ACPI structure + * + * @Signature: Signature to query for + * + * Returns the virtual structure base on success, otherwise + * NULL on failure. + */ +VOID *AcpiQuery(const CHAR *Signature); + +#endif /* !_ACPI_ACPI_H_ */ diff --git a/paw/stos/init/init.c b/paw/stos/init/init.c index bf4f3a6..87f41ad 100644 --- a/paw/stos/init/init.c +++ b/paw/stos/init/init.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -71,4 +72,7 @@ KiKernelEntry(VOID) /* Initialize virtual memory */ MmInitVmm(); + + /* Initialize ACPI */ + AcpiInit(); }