--- /dev/null
+/*
+ * PROJECT: ReactOS HAL
+ * LICENSE: BSD - See COPYING.ARM in the top level directory
+ * FILE: hal/halx86/generic/acpi/halacpi.c
+ * PURPOSE: HAL ACPI Code
+ * PROGRAMMERS: ReactOS Portable Systems Group
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include <hal.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+LIST_ENTRY HalpAcpiTableCacheList;
+FAST_MUTEX HalpAcpiTableCacheLock;
+
+BOOLEAN HalpProcessedACPIPhase0;
+BOOLEAN HalpPhysicalMemoryMayAppearAbove4GB;
+
+FADT HalpFixedAcpiDescTable;
+PDEBUG_PORT_TABLE HalpDebugPortTable;
+PACPI_SRAT HalpAcpiSrat;
+PBOOT_TABLE HalpSimpleBootFlagTable;
+
+PHYSICAL_ADDRESS HalpMaxHotPlugMemoryAddress;
+PHYSICAL_ADDRESS HalpLowStubPhysicalAddress;
+PHARDWARE_PTE HalpPteForFlush;
+PVOID HalpVirtAddrForFlush;
+PVOID HalpLowStub;
+
+PACPI_BIOS_MULTI_NODE HalpAcpiMultiNode;
+
+LIST_ENTRY HalpAcpiTableMatchList;
+
+ULONG HalpInvalidAcpiTable;
+
+/* PRIVATE FUNCTIONS **********************************************************/
+
+PDESCRIPTION_HEADER
+NTAPI
+HalpAcpiGetCachedTable(IN ULONG Signature)
+{
+ PLIST_ENTRY ListHead, NextEntry;
+ PACPI_CACHED_TABLE CachedTable;
+
+ /* Loop cached tables */
+ ListHead = &HalpAcpiTableCacheList;
+ NextEntry = ListHead->Flink;
+ while (NextEntry != ListHead)
+ {
+ /* Get the table */
+ CachedTable = CONTAINING_RECORD(NextEntry, ACPI_CACHED_TABLE, Links);
+
+ /* Compare signatures */
+ if (CachedTable->Header.Signature == Signature) return &CachedTable->Header;
+
+ /* Keep going */
+ NextEntry = NextEntry->Flink;
+ }
+
+ /* Nothing found */
+ return NULL;
+}
+
+VOID
+NTAPI
+HalpAcpiCacheTable(IN PDESCRIPTION_HEADER TableHeader)
+{
+ PACPI_CACHED_TABLE CachedTable;
+
+ /* Get the cached table and link it */
+ CachedTable = CONTAINING_RECORD(TableHeader, ACPI_CACHED_TABLE, Header);
+ InsertTailList(&HalpAcpiTableCacheList, &CachedTable->Links);
+}
+
+PVOID
+NTAPI
+HalpAcpiCopyBiosTable(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
+ IN PDESCRIPTION_HEADER TableHeader)
+{
+ ULONG Size;
+ PFN_NUMBER PageCount;
+ PHYSICAL_ADDRESS PhysAddress;
+ PACPI_CACHED_TABLE CachedTable;
+ PDESCRIPTION_HEADER CopiedTable;
+
+ /* Size we'll need for the cached table */
+ Size = TableHeader->Length + FIELD_OFFSET(ACPI_CACHED_TABLE, Header);
+ if (LoaderBlock)
+ {
+ /* Phase 0: Convert to pages and use the HAL heap */
+ PageCount = BYTES_TO_PAGES(Size);
+ PhysAddress.LowPart = HalpAllocPhysicalMemory(LoaderBlock,
+ 0x1000000,
+ PageCount,
+ FALSE);
+ if (PhysAddress.LowPart)
+ {
+ /* Map it */
+ CachedTable = HalpMapPhysicalMemory64(PhysAddress, PageCount);
+ }
+ else
+ {
+ /* No memory, so nothing to map */
+ CachedTable = NULL;
+ }
+ }
+ else
+ {
+ /* Use Mm pool */
+ CachedTable = ExAllocatePoolWithTag(NonPagedPool, Size, ' laH');
+ }
+
+ /* Do we have the cached table? */
+ if (CachedTable)
+ {
+ /* Copy the data */
+ CopiedTable = &CachedTable->Header;
+ RtlCopyMemory(CopiedTable, TableHeader, TableHeader->Length);
+ }
+ else
+ {
+ /* Nothing to return */
+ CopiedTable = NULL;
+ }
+
+ /* Return the table */
+ return CopiedTable;
+}
+
+PVOID
+NTAPI
+HalpAcpiGetTableFromBios(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
+ IN ULONG Signature)
+{
+ PHYSICAL_ADDRESS PhysicalAddress;
+ PXSDT Xsdt;
+ PRSDT Rsdt;
+ PFADT Fadt;
+ PDESCRIPTION_HEADER Header = NULL;
+ ULONG TableLength;
+ CHAR CheckSum = 0;
+ ULONG Offset;
+ ULONG EntryCount, CurrentEntry;
+ PCHAR CurrentByte;
+ PFN_NUMBER PageCount;
+
+ /* Should not query the RSDT/XSDT by itself */
+ if ((Signature == RSDT_SIGNATURE) || (Signature == XSDT_SIGNATURE)) return NULL;
+
+ /* Special case request for DSDT, because the FADT points to it */
+ if (Signature == DSDT_SIGNATURE)
+ {
+ /* Grab the FADT */
+ Fadt = HalpAcpiGetTable(LoaderBlock, FADT_SIGNATURE);
+ if (Fadt)
+ {
+ /* Grab the DSDT address and assume 2 pages */
+ PhysicalAddress.LowPart = Fadt->dsdt;
+ TableLength = 2 * PAGE_SIZE;
+
+ /* Map it */
+ if (LoaderBlock)
+ {
+ /* Phase 0, use HAL heap */
+ Header = HalpMapPhysicalMemory64(PhysicalAddress, 2u);
+ }
+ else
+ {
+ /* Phase 1, use Mm */
+ Header = MmMapIoSpace(PhysicalAddress, 2 * PAGE_SIZE, 0);
+ }
+
+ /* Fail if we couldn't map it */
+ if (!Header)
+ {
+ DbgPrint("HAL: Failed to map ACPI table.\n");
+ return NULL;
+ }
+
+ /* Validate the signature */
+ DPRINT1("ACPI DSDT at 0x%p\n", Header);
+ if (Header->Signature != DSDT_SIGNATURE)
+ {
+ /* Fail and unmap */
+ if (LoaderBlock)
+ {
+ /* Using HAL heap */
+ HalpUnmapVirtualAddress(Header, 2);
+ }
+ else
+ {
+ /* Using Mm */
+ MmUnmapIoSpace(Header, 2 * PAGE_SIZE);
+ }
+
+ /* Didn't find anything */
+ return NULL;
+ }
+ }
+ else
+ {
+ /* Couldn't find it */
+ return NULL;
+ }
+ }
+ else
+ {
+ /* To find tables, we need the RSDT */
+ Rsdt = HalpAcpiGetTable(LoaderBlock, RSDT_SIGNATURE);
+ if (Rsdt)
+ {
+ /* Won't be using the XSDT */
+ Xsdt = NULL;
+ }
+ else
+ {
+ /* Only other choice is to use the XSDT */
+ Xsdt = HalpAcpiGetTable(LoaderBlock, XSDT_SIGNATURE);
+ if (!Xsdt) return NULL;
+
+ /* Won't be using the RSDT */
+ DPRINT1("ACPI XSDT at 0x%p\n", Xsdt);
+ Rsdt = NULL;
+ }
+
+ /* Smallest RSDT/XSDT is one without table entries */
+ Offset = FIELD_OFFSET(RSDT, Tables);
+ if (Xsdt)
+ {
+ /* Figure out total size of table and the offset */
+ TableLength = Xsdt->Header.Length;
+ if (TableLength < Offset) Offset = Xsdt->Header.Length;
+
+ /* The entries are each 64-bits, so count them */
+ EntryCount = (TableLength - Offset) / sizeof(PHYSICAL_ADDRESS);
+ }
+ else
+ {
+ /* Figure out total size of table and the offset */
+ TableLength = Rsdt->Header.Length;
+ if (TableLength < Offset) Offset = Rsdt->Header.Length;
+
+ /* The entries are each 32-bits, so count them */
+ EntryCount = (TableLength - Offset) / sizeof(ULONG);
+ }
+
+ /* Start at the beginning of the array and loop it */
+ for (CurrentEntry = 0; CurrentEntry < EntryCount; CurrentEntry++)
+ {
+ /* Are we using the XSDT? */
+ if (!Xsdt)
+ {
+ /* Read the 32-bit physical address */
+ PhysicalAddress.LowPart = Rsdt->Tables[CurrentEntry];
+ }
+ else
+ {
+ /* Read the 64-bit physical address */
+ PhysicalAddress = Xsdt->Tables[CurrentEntry];
+ }
+
+ /* Had we already mapped a table? */
+ if (Header)
+ {
+ /* Yes, unmap it */
+ if (LoaderBlock)
+ {
+ /* Using HAL heap */
+ HalpUnmapVirtualAddress(Header, 2);
+ }
+ else
+ {
+ /* Using Mm */
+ MmUnmapIoSpace(Header, 2 * PAGE_SIZE);
+ }
+ }
+
+ /* Now map this table */
+ if (!LoaderBlock)
+ {
+ /* Phase 1: Use HAL heap */
+ Header = MmMapIoSpace(PhysicalAddress, 2 * PAGE_SIZE, MmNonCached);
+ }
+ else
+ {
+ /* Phase 0: Use Mm */
+ Header = HalpMapPhysicalMemory64(PhysicalAddress, 2);
+ }
+
+ /* Check if we mapped it */
+ if (!Header)
+ {
+ /* Game over */
+ DbgPrint("HAL: Failed to map ACPI table.\n");
+ return NULL;
+ }
+
+ /* We found it, break out */
+ DPRINT("Found ACPI table %c%c%c%c at 0x%p\n",
+ Header->Signature & 0xFF,
+ (Header->Signature & 0xFF00) >> 8,
+ (Header->Signature & 0xFF0000) >> 16,
+ (Header->Signature & 0xFF000000) >> 24,
+ Header);
+ if (Header->Signature == Signature) break;
+ }
+
+ /* Did we end up here back at the last entry? */
+ if (CurrentEntry == EntryCount)
+ {
+ /* Yes, unmap the last table we processed */
+ if (LoaderBlock)
+ {
+ /* Using HAL heap */
+ HalpUnmapVirtualAddress(Header, 2);
+ }
+ else
+ {
+ /* Using Mm */
+ MmUnmapIoSpace(Header, 2 * PAGE_SIZE);
+ }
+
+ /* Didn't find anything */
+ return NULL;
+ }
+ }
+
+ /* Past this point, we assume something was found */
+ ASSERT(Header);
+
+ /* How many pages do we need? */
+ PageCount = BYTES_TO_PAGES(Header->Length);
+ if (PageCount != 2)
+ {
+ /* We assumed two, but this is not the case, free the current mapping */
+ if (LoaderBlock)
+ {
+ /* Using HAL heap */
+ HalpUnmapVirtualAddress(Header, 2);
+ }
+ else
+ {
+ /* Using Mm */
+ MmUnmapIoSpace(Header, 2 * PAGE_SIZE);
+ }
+
+ /* Now map this table using its correct size */
+ if (!LoaderBlock)
+ {
+ /* Phase 1: Use HAL heap */
+ Header = MmMapIoSpace(PhysicalAddress, PageCount << PAGE_SHIFT, MmNonCached);
+ }
+ else
+ {
+ /* Phase 0: Use Mm */
+ Header = HalpMapPhysicalMemory64(PhysicalAddress, PageCount);
+ }
+ }
+
+ /* Fail if the remapped failed */
+ if (!Header) return NULL;
+
+ /* All tables in ACPI 3.0 other than the FACP should have correct checksum */
+ if ((Header->Signature != FADT_SIGNATURE) || (Header->Revision > 2))
+ {
+ /* Go to the end of the table */
+ CheckSum = 0;
+ CurrentByte = (PCHAR)Header + Header->Length;
+ while (CurrentByte-- != (PCHAR)Header)
+ {
+ /* Add this byte */
+ CheckSum += *CurrentByte;
+ }
+
+ /* The correct checksum is always 0, anything else is illegal */
+ if (CheckSum) HalpInvalidAcpiTable = Header->Signature;
+ }
+
+ /* Return the table */
+ return Header;
+}
+
+PVOID
+NTAPI
+HalpAcpiGetTable(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
+ IN ULONG Signature)
+{
+ PFN_NUMBER PageCount;
+ PDESCRIPTION_HEADER TableAddress, BiosCopy;
+
+ /* See if we have a cached table? */
+ TableAddress = HalpAcpiGetCachedTable(Signature);
+ if (!TableAddress)
+ {
+ /* No cache, search the BIOS */
+ TableAddress = HalpAcpiGetTableFromBios(LoaderBlock, Signature);
+ if (TableAddress)
+ {
+ /* Found it, copy it into our own memory */
+ BiosCopy = HalpAcpiCopyBiosTable(LoaderBlock, TableAddress);
+
+ /* Get the pages, and unmap the BIOS copy */
+ PageCount = BYTES_TO_PAGES(TableAddress->Length);
+ if (LoaderBlock)
+ {
+ /* Phase 0, use the HAL heap */
+ HalpUnmapVirtualAddress(TableAddress, PageCount);
+ }
+ else
+ {
+ /* Phase 1, use Mm */
+ MmUnmapIoSpace(TableAddress, PageCount << 12);
+ }
+
+ /* Cache the bios copy */
+ TableAddress = BiosCopy;
+ if (BiosCopy) HalpAcpiCacheTable(BiosCopy);
+ }
+ }
+
+ /* Return the table */
+ return TableAddress;
+}
+
+PVOID
+NTAPI
+HalAcpiGetTable(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
+ IN ULONG Signature)
+{
+ PDESCRIPTION_HEADER TableHeader;
+
+ /* Is this phase0 */
+ if (LoaderBlock)
+ {
+ /* Initialize the cache first */
+ if (!NT_SUCCESS(HalpAcpiTableCacheInit(LoaderBlock))) return NULL;
+ }
+ else
+ {
+ /* Lock the cache */
+ ExAcquireFastMutex(&HalpAcpiTableCacheLock);
+ }
+
+ /* Get the table */
+ TableHeader = HalpAcpiGetTable(LoaderBlock, Signature);
+
+ /* Release the lock in phase 1 */
+ if (!LoaderBlock) ExReleaseFastMutex(&HalpAcpiTableCacheLock);
+
+ /* Return the table */
+ return TableHeader;
+}
+
+VOID
+NTAPI
+HalpNumaInitializeStaticConfiguration(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
+{
+ PACPI_SRAT SratTable;
+
+ /* Get the SRAT, bail out if it doesn't exist */
+ SratTable = HalAcpiGetTable(LoaderBlock, SRAT_SIGNATURE);
+ HalpAcpiSrat = SratTable;
+ if (!SratTable) return;
+}
+
+VOID
+NTAPI
+HalpGetHotPlugMemoryInfo(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
+{
+ PACPI_SRAT SratTable;
+
+ /* Get the SRAT, bail out if it doesn't exist */
+ SratTable = HalAcpiGetTable(LoaderBlock, SRAT_SIGNATURE);
+ HalpAcpiSrat = SratTable;
+ if (!SratTable) return;
+}
+
+VOID
+NTAPI
+HalpDynamicSystemResourceConfiguration(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
+{
+ /* For this HAL, it means to get hot plug memory information */
+ HalpGetHotPlugMemoryInfo(LoaderBlock);
+}
+
+VOID
+NTAPI
+HalpAcpiDetectMachineSpecificActions(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
+ IN PFADT DescriptionTable)
+{
+ /* Does this HAL specify something? */
+ if (HalpAcpiTableMatchList.Flink)
+ {
+ /* Great, but we don't support it */
+ DPRINT1("WARNING: Your HAL has specific ACPI hacks to apply!\n");
+ }
+}
+
+VOID
+NTAPI
+HalpInitBootTable(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
+{
+ PBOOT_TABLE BootTable;
+
+ /* Get the boot table */
+ BootTable = HalAcpiGetTable(LoaderBlock, BOOT_SIGNATURE);
+ HalpSimpleBootFlagTable = BootTable;
+ DPRINT1("ACPI BOOT at 0x%p\n", HalpSimpleBootFlagTable);
+
+ /* Validate it */
+ if ((BootTable) &&
+ (BootTable->Header.Length >= sizeof(BOOT_TABLE)) &&
+ (BootTable->CMOSIndex >= 9))
+ {
+ DPRINT1("ACPI Boot table found, but not supported!\n");
+ }
+ else
+ {
+ /* Invalid or doesn't exist, ignore it */
+ HalpSimpleBootFlagTable = 0;
+ }
+
+ /* Install the end of boot handler */
+// HalEndOfBoot = HalpEndOfBoot;
+}
+
+NTSTATUS
+NTAPI
+HalpAcpiFindRsdtPhase0(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
+ OUT PACPI_BIOS_MULTI_NODE* AcpiMultiNode)
+{
+ PCONFIGURATION_COMPONENT_DATA ComponentEntry;
+ PCONFIGURATION_COMPONENT_DATA Next = NULL;
+ PCM_PARTIAL_RESOURCE_LIST ResourceList;
+ PACPI_BIOS_MULTI_NODE NodeData;
+ ULONG NodeLength;
+ PFN_NUMBER PageCount;
+ PVOID MappedAddress;
+ PHYSICAL_ADDRESS PhysicalAddress;
+
+ /* Did we already do this once? */
+ if (HalpAcpiMultiNode)
+ {
+ /* Return what we know */
+ *AcpiMultiNode = HalpAcpiMultiNode;
+ return STATUS_SUCCESS;
+ }
+
+ /* Assume failure */
+ *AcpiMultiNode = NULL;
+
+ /* Find the multi function adapter key */
+ ComponentEntry = KeFindConfigurationNextEntry(LoaderBlock->ConfigurationRoot,
+ AdapterClass,
+ MultiFunctionAdapter,
+ 0,
+ &Next);
+ while (ComponentEntry)
+ {
+ /* Find the ACPI BIOS key */
+ if (!_stricmp(ComponentEntry->ComponentEntry.Identifier, "ACPI BIOS"))
+ {
+ /* Found it */
+ break;
+ }
+
+ /* Keep searching */
+ Next = ComponentEntry;
+ ComponentEntry = KeFindConfigurationNextEntry(LoaderBlock->ConfigurationRoot,
+ AdapterClass,
+ MultiFunctionAdapter,
+ NULL,
+ &Next);
+ }
+
+ /* Make sure we found it */
+ if (!ComponentEntry)
+ {
+ DbgPrint("**** HalpAcpiFindRsdtPhase0: did NOT find RSDT\n");
+ return STATUS_NOT_FOUND;
+ }
+
+ /* The configuration data is a resource list, and the BIOS node follows */
+ ResourceList = ComponentEntry->ConfigurationData;
+ NodeData = (PACPI_BIOS_MULTI_NODE)(ResourceList + 1);
+
+ /* How many E820 memory entries are there? */
+ NodeLength = sizeof(ACPI_BIOS_MULTI_NODE) +
+ (NodeData->Count - 1) * sizeof(ACPI_E820_ENTRY);
+
+ /* Convert to pages */
+ PageCount = BYTES_TO_PAGES(NodeLength);
+
+ /* Allocate the memory */
+ PhysicalAddress.LowPart = HalpAllocPhysicalMemory(LoaderBlock,
+ 0x1000000,
+ PageCount,
+ FALSE);
+ if (PhysicalAddress.LowPart)
+ {
+ /* Map it if the allocation worked */
+ MappedAddress = HalpMapPhysicalMemory64(PhysicalAddress, PageCount);
+ }
+ else
+ {
+ /* Otherwise we'll have to fail */
+ MappedAddress = NULL;
+ }
+
+ /* Save the multi node, bail out if we didn't find it */
+ HalpAcpiMultiNode = MappedAddress;
+ if (!MappedAddress) return STATUS_INSUFFICIENT_RESOURCES;
+
+ /* Copy the multi-node data */
+ RtlCopyMemory(MappedAddress, NodeData, NodeLength);
+
+ /* Return the data */
+ *AcpiMultiNode = HalpAcpiMultiNode;
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+HalpAcpiTableCacheInit(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
+{
+ PACPI_BIOS_MULTI_NODE AcpiMultiNode;
+ NTSTATUS Status = STATUS_SUCCESS;
+ PHYSICAL_ADDRESS PhysicalAddress;
+ PVOID MappedAddress;
+ ULONG TableLength;
+ PRSDT Rsdt;
+ PLOADER_PARAMETER_EXTENSION LoaderExtension;
+
+ /* Only initialize once */
+ if (HalpAcpiTableCacheList.Flink) return Status;
+
+ /* Setup the lock and table */
+ ExInitializeFastMutex(&HalpAcpiTableCacheLock);
+ InitializeListHead(&HalpAcpiTableCacheList);
+
+ /* Find the RSDT */
+ Status = HalpAcpiFindRsdtPhase0(LoaderBlock, &AcpiMultiNode);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ /* Map the RSDT */
+ if (LoaderBlock)
+ {
+ /* Phase0: Use HAL Heap to map the RSDT, we assume it's about 2 pages */
+ PhysicalAddress.QuadPart = AcpiMultiNode->RsdtAddress.QuadPart;
+ MappedAddress = HalpMapPhysicalMemory64(PhysicalAddress, 2);
+ }
+ else
+ {
+ /* Use an I/O map */
+ MappedAddress = MmMapIoSpace(PhysicalAddress, PAGE_SIZE * 2, MmNonCached);
+ }
+
+ /* Get the RSDT */
+ Rsdt = MappedAddress;
+ if (!MappedAddress)
+ {
+ /* Fail, no memory */
+ DbgPrint("HAL: Failed to map RSDT\n");
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ /* Validate it */
+ DPRINT1("ACPI RSDT at 0x%p\n", Rsdt);
+ if ((Rsdt->Header.Signature != RSDT_SIGNATURE) &&
+ (Rsdt->Header.Signature != XSDT_SIGNATURE))
+ {
+ /* Very bad: crash */
+ HalDisplayString("Bad RSDT pointer\n");
+ KeBugCheckEx(MISMATCHED_HAL, 4, __LINE__, 0, 0);
+ }
+
+ /* We assumed two pages -- do we need less or more? */
+ TableLength = ADDRESS_AND_SIZE_TO_SPAN_PAGES(PhysicalAddress.LowPart,
+ Rsdt->Header.Length);
+ if (TableLength != 2)
+ {
+ /* Are we in phase 0 or 1? */
+ if (!LoaderBlock)
+ {
+ /* Unmap the old table, remap the new one, using Mm I/O space */
+ MmUnmapIoSpace(MappedAddress, 2 * PAGE_SIZE);
+ MappedAddress = MmMapIoSpace(PhysicalAddress,
+ TableLength << PAGE_SHIFT,
+ MmNonCached);
+ }
+ else
+ {
+ /* Unmap the old table, remap the new one, using HAL heap */
+ HalpUnmapVirtualAddress(MappedAddress, 2);
+ MappedAddress = HalpMapPhysicalMemory64(PhysicalAddress, TableLength);
+ }
+
+ /* Get the remapped table */
+ Rsdt = MappedAddress;
+ if (!MappedAddress)
+ {
+ /* Fail, no memory */
+ DbgPrint("HAL: Couldn't remap RSDT\n");
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ }
+
+ /* Now take the BIOS copy and make our own local copy */
+ Rsdt = HalpAcpiCopyBiosTable(LoaderBlock, &Rsdt->Header);
+ if (!Rsdt)
+ {
+ /* Fail, no memory */
+ DbgPrint("HAL: Couldn't remap RSDT\n");
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ /* Get rid of the BIOS mapping */
+ if (LoaderBlock)
+ {
+ /* Use HAL heap */
+ HalpUnmapVirtualAddress(MappedAddress, TableLength);
+ }
+ else
+ {
+ /* Use Mm */
+ MmUnmapIoSpace(MappedAddress, TableLength << PAGE_SHIFT);
+ }
+
+ /* Cache the RSDT */
+ HalpAcpiCacheTable(&Rsdt->Header);
+
+ /* Check for compatible loader block extension */
+ LoaderExtension = LoaderBlock->Extension;
+ if (LoaderExtension->Size >= 0x58)
+ {
+ /* Compatible loader: did it provide an ACPI table override? */
+ if ((LoaderExtension->AcpiTable) && (LoaderExtension->AcpiTableSize))
+ {
+ /* Great, because we don't support it! */
+ DPRINT1("ACPI Table Overrides Not Supported!\n");
+ }
+ }
+
+ /* Done */
+ return Status;
+}
+
+VOID
+NTAPI
+HaliAcpiTimerInit(IN ULONG TimerPort,
+ IN ULONG TimerValExt)
+{
+ PAGED_CODE();
+
+ /* Is this in the init phase? */
+ if (!TimerPort )
+ {
+ /* Get the data from the FADT */
+ TimerPort = HalpFixedAcpiDescTable.pm_tmr_blk_io_port;
+ TimerValExt = HalpFixedAcpiDescTable.flags & ACPI_TMR_VAL_EXT;
+ }
+
+ /* FIXME: Now proceed to the timer initialization */
+ DPRINT1("ACPI Timer at: %Xh (EXT: %d)\n", TimerPort, TimerValExt);
+ //HalaAcpiTimerInit(TimerPort, TimerValExt);
+}
+
+NTSTATUS
+NTAPI
+HalpSetupAcpiPhase0(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
+{
+ NTSTATUS Status;
+ PFADT Fadt;
+ ULONG TableLength;
+ PHYSICAL_ADDRESS PhysicalAddress;
+
+ /* Only do this once */
+ DPRINT1("You are booting the ACPI HAL!\n");
+ if (HalpProcessedACPIPhase0) return STATUS_SUCCESS;
+
+ /* Setup the ACPI table cache */
+ Status = HalpAcpiTableCacheInit(LoaderBlock);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ /* Grab the FADT */
+ Fadt = HalAcpiGetTable(LoaderBlock, FADT_SIGNATURE);
+ if (!Fadt)
+ {
+ /* Fail */
+ DbgPrint("HAL: Didn't find the FACP\n");
+ return STATUS_NOT_FOUND;
+ }
+
+ /* Assume typical size, otherwise whatever the descriptor table says */
+ DPRINT1("ACPI FACP at 0x%p\n", Fadt);
+ TableLength = sizeof(FADT);
+ if (Fadt->Header.Length < sizeof(FADT)) TableLength = Fadt->Header.Length;
+
+ /* Copy it in the HAL static buffer */
+ RtlCopyMemory(&HalpFixedAcpiDescTable, Fadt, TableLength);
+
+ /* Anything special this HAL needs to do? */
+ HalpAcpiDetectMachineSpecificActions(LoaderBlock, &HalpFixedAcpiDescTable);
+
+ /* Get the debug table for KD */
+ HalpDebugPortTable = HalAcpiGetTable(LoaderBlock, DBGP_SIGNATURE);
+ DPRINT1("ACPI DBGP at 0x%p\n", HalpDebugPortTable);
+
+ /* Initialize NUMA through the SRAT */
+ HalpNumaInitializeStaticConfiguration(LoaderBlock);
+
+ /* Initialize hotplug through the SRAT */
+ HalpDynamicSystemResourceConfiguration(LoaderBlock);
+ DPRINT1("ACPI SRAT at 0x%p\n", HalpAcpiSrat);
+ if (HalpAcpiSrat)
+ {
+ DPRINT1("Your machine has a SRAT, but NUMA/HotPlug are not supported!\n");
+ }
+
+ /* Can there be memory higher than 4GB? */
+ if (HalpMaxHotPlugMemoryAddress.HighPart >= 1)
+ {
+ /* We'll need this for DMA later */
+ HalpPhysicalMemoryMayAppearAbove4GB = TRUE;
+ }
+
+ /* Setup the ACPI timer */
+ HaliAcpiTimerInit(0, 0);
+
+ /* Do we have a low stub address yet? */
+ if (!HalpLowStubPhysicalAddress.LowPart)
+ {
+ /* Allocate it */
+ HalpLowStubPhysicalAddress.LowPart = HalpAllocPhysicalMemory(LoaderBlock,
+ 0x100000,
+ 1,
+ FALSE);
+ if (HalpLowStubPhysicalAddress.LowPart)
+ {
+ /* Map it */
+ HalpLowStub = HalpMapPhysicalMemory64(HalpLowStubPhysicalAddress, 1);
+ }
+ }
+
+ /* Grab a page for flushes */
+ PhysicalAddress.QuadPart = 0x100000;
+ HalpVirtAddrForFlush = HalpMapPhysicalMemory64(PhysicalAddress, 1);
+ HalpPteForFlush = HalAddressToPte(HalpVirtAddrForFlush);
+
+ /* Don't do this again */
+ HalpProcessedACPIPhase0 = TRUE;
+
+ /* Setup the boot table */
+ HalpInitBootTable(LoaderBlock);
+
+ /* Return success */
+ return STATUS_SUCCESS;
+}
+
+/* EOF */