diff --git a/service/ptos/drivers/acpi/acpi.c b/service/ptos/drivers/acpi/acpi.c new file mode 100644 index 0000000..5870d4b --- /dev/null +++ b/service/ptos/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) { + KeBugCheck( + BUGCHECK_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/service/ptos/head/drivers/acpi/acpi.h b/service/ptos/head/drivers/acpi/acpi.h new file mode 100644 index 0000000..9ca7e79 --- /dev/null +++ b/service/ptos/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/service/ptos/head/drivers/acpi/tables.h b/service/ptos/head/drivers/acpi/tables.h new file mode 100644 index 0000000..3bcd7b6 --- /dev/null +++ b/service/ptos/head/drivers/acpi/tables.h @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2026, Chloe M. + * Provided under the BSD-3 clause. + * + * Description: ACPI definitions + * Author: Chloe M. + */ + +#ifndef _ACPI_TABLES_H_ +#define _ACPI_TABLES_H_ 1 + +#include + +/* MADT APIC header types */ +#define APIC_TYPE_LOCAL_APIC 0 +#define APIC_TYPE_IO_APIC 1 +#define APIC_TYPE_INTERRUPT_OVERRIDE 2 + +#define OEMID_SIZE 6 + +typedef struct PACKED { + CHAR Signature[4]; + ULONG Length; + UCHAR Revision; + UCHAR Checksum; + CHAR Oemid[OEMID_SIZE]; + CHAR OemTableId[8]; + ULONG OemRevision; + ULONG CreatorId; + ULONG CreatorRevision; +} ACPI_HEADER; + +typedef struct PACKED { + UQUAD Signature; + UCHAR Checksum; + CHAR Oemid[OEMID_SIZE]; + UCHAR Revision; + ULONG RsdtAddr; + + /* Reserved if revision < 2 */ + ULONG Length; + UQUAD XsdtAddr; + UCHAR ExtChecksum; + UCHAR Reserved[3]; +} ACPI_RSDP; + +/* + * XSDT or RSDT depending on the revision within the + * header + */ +typedef struct PACKED { + ACPI_HEADER Header; + ULONG Tables[]; +} ACPI_ROOT_SDT; + +typedef struct PACKED { + ACPI_HEADER Header; + ULONG LapicAddr; + ULONG Flags; +} ACPI_MADT; + +typedef struct PACKED { + UCHAR Type; + UCHAR Length; +} ACPI_APIC_HEADER; + +typedef struct PACKED { + ACPI_APIC_HEADER Header; + UCHAR ProcessorId; + UCHAR ApicId; + ULONG Flags; +} ACPI_LOCAL_APIC; + +typedef struct PACKED { + UCHAR AddressSpaceId; + UCHAR RegisterBitWidth; + UCHAR RegisterBitOffset; + UCHAR Reserved; + UQUAD Address; +} ACPI_GAS; + +/* + * ACPI Address Space ID definitions for GAS + * + * See section 5.2.3.2 of the ACPI software programming + * manual. + * + * XXX: 0x0B->0x7E is reserved as well as 0x80->0xBF + * and 0xC0->0xFF is OEM defined. Values other than + * the ones specified below are either garbage or + * OEM specific values. + */ +#define ACPI_GAS_SYSMEM 0x00 /* System memory space */ +#define ACPI_GAS_SYSIO 0x01 /* System I/O space */ +#define ACPI_GAS_PCICONF 0x02 /* PCI configuration space */ +#define ACPI_GAS_EC 0x03 /* Embedded controller */ +#define ACPI_GAS_SMBUS 0x04 /* System management bus */ +#define ACPI_GAS_CMOS 0x05 /* System CMOS */ +#define ACPI_GAS_PCIBAR 0x06 /* PCI BAR target */ +#define ACPI_GAS_IPMI 0x07 /* IPMI (sensor monitoring) */ +#define ACPI_GAS_GPIO 0x08 /* General Purpose I/O */ +#define ACPI_GAS_GSBUS 0x09 /* GenericSerialBus */ +#define ACPI_GAS_PLATCOM 0x0A /* Platform Communications Channel */ + +/* + * ACPI address size definitions for GAS + * + * See section 5.2.3.2 of the ACPI software programming + * manual. + */ +#define ACPI_GAS_UNDEF 0 /* Undefined (legacy reasons) */ +#define ACPI_GAS_BYTE 1 /* Byte access */ +#define ACPI_GAS_WORD 2 /* Word access */ +#define ACPI_GAS_DWORD 3 /* Dword access */ +#define ACPI_GAS_QWORD 4 /* Qword access */ + +typedef struct PACKED { + ACPI_HEADER Header; + UCHAR HardwareRevId; + UCHAR ComparatorCount : 5; + UCHAR CounterSize : 1; + UCHAR Reserved : 1; + UCHAR LegacyReplacement : 1; + USHORT PciVendorId; + ACPI_GAS Gas; + UCHAR HpetNumber; + USHORT MinimumTick; + UCHAR PageProtection; +} ACPI_HPET; + +#endif /* _ACPI_TABLES_H_ */ diff --git a/service/ptos/ke/init.c b/service/ptos/ke/init.c index a7dbf63..4adb66e 100644 --- a/service/ptos/ke/init.c +++ b/service/ptos/ke/init.c @@ -16,6 +16,7 @@ #include #include #include +#include #include /* Globals */ @@ -89,6 +90,9 @@ KiKernelInit(VOID) /* Phase 2 init of bootstrap core */ HalKpcrP2Init(&BootstrapCore); + /* Initialize ACPI */ + AcpiInit(); + /* Initialize the root process */ InitializeRootProcess(); }