mirror of
https://github.com/ApfelTeeSaft/reactos.git
synced 2026-08-26 19:33:31 +00:00
[ACPI][UEFI] Use bootloader-provided ACPI root pointer in OSL (#8980)
Fix ACPI table discovery on the UEFI boot path by teaching the ACPI OSL to use the loader-provided ACPI root table information instead of relying only on legacy BIOS RSDP scanning: - Build a synthetic RSDP from the ACPI BIOS configuration node populated by the bootloader - Fallback to the old scan only if that data is unavailable - Keep full 64-bit physical addresses when mapping ACPI tables - Improve failure diagnostics if initialization still fails This lets ACPICA initialize from the UEFI-provided RSDT/XSDT path. CORE-11954 So QEMU Q35 on UEFI is now able to discover ACPI tables through the loader- provided root table path, which fixes 0x7B INACCESSIBLE_BOOT_DEVICE bugcheck: https://github.com/user-attachments/assets/25d4d9c9-4197-496b-84f9-e5642c65809d
This commit is contained in:
+193
-1
@@ -6,16 +6,190 @@
|
||||
|
||||
#include "precomp.h"
|
||||
|
||||
#include <arc/arc.h>
|
||||
#include <reactos/drivers/acpi/acpi.h>
|
||||
#include <pseh/pseh2.h>
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
#define TAG_ACPI_LOADER_RSDP_TABLE 'RpcA'
|
||||
|
||||
static PKINTERRUPT AcpiInterrupt;
|
||||
static BOOLEAN AcpiInterruptHandlerRegistered = FALSE;
|
||||
static ACPI_OSD_HANDLER AcpiIrqHandler = NULL;
|
||||
static PVOID AcpiIrqContext = NULL;
|
||||
static ULONG AcpiIrqNumber = 0;
|
||||
/* TODO: Replace these local declarations with <ndk/kefuncs.h> once the
|
||||
* acpi.sys build context can consume the required NDK dependencies cleanly.
|
||||
*/
|
||||
extern NTSYSAPI PLOADER_PARAMETER_BLOCK KeLoaderBlock;
|
||||
extern NTSYSAPI
|
||||
PCONFIGURATION_COMPONENT_DATA
|
||||
NTAPI
|
||||
KeFindConfigurationNextEntry(
|
||||
_In_ PCONFIGURATION_COMPONENT_DATA Child,
|
||||
_In_ CONFIGURATION_CLASS Class,
|
||||
_In_ CONFIGURATION_TYPE Type,
|
||||
_In_opt_ PULONG ComponentKey,
|
||||
_Inout_ PCONFIGURATION_COMPONENT_DATA *NextLink);
|
||||
|
||||
static ACPI_TABLE_RSDP *AcpiLoaderRsdp = NULL;
|
||||
|
||||
static
|
||||
UCHAR
|
||||
AcpiChecksumBuffer(
|
||||
_In_reads_bytes_(Length) const UCHAR *Buffer,
|
||||
_In_ ULONG Length)
|
||||
{
|
||||
ULONG Index;
|
||||
UCHAR Sum;
|
||||
|
||||
Sum = 0;
|
||||
for (Index = 0; Index < Length; ++Index)
|
||||
Sum = (UCHAR)(Sum + Buffer[Index]);
|
||||
|
||||
return (UCHAR)(0 - Sum);
|
||||
}
|
||||
|
||||
static
|
||||
PACPI_BIOS_MULTI_NODE
|
||||
AcpiGetLoaderAcpiBiosNode(VOID)
|
||||
{
|
||||
PCONFIGURATION_COMPONENT_DATA ComponentEntry = NULL;
|
||||
PCONFIGURATION_COMPONENT_DATA Next = NULL;
|
||||
PCM_PARTIAL_RESOURCE_LIST ResourceList;
|
||||
|
||||
if (!KeLoaderBlock || !KeLoaderBlock->ConfigurationRoot)
|
||||
return NULL;
|
||||
|
||||
ComponentEntry = KeFindConfigurationNextEntry(KeLoaderBlock->ConfigurationRoot,
|
||||
AdapterClass,
|
||||
MultiFunctionAdapter,
|
||||
NULL,
|
||||
&Next);
|
||||
while (ComponentEntry)
|
||||
{
|
||||
if ((ComponentEntry->ComponentEntry.Identifier != NULL) &&
|
||||
!_stricmp(ComponentEntry->ComponentEntry.Identifier, "ACPI BIOS"))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
Next = ComponentEntry;
|
||||
ComponentEntry = KeFindConfigurationNextEntry(KeLoaderBlock->ConfigurationRoot,
|
||||
AdapterClass,
|
||||
MultiFunctionAdapter,
|
||||
NULL,
|
||||
&Next);
|
||||
}
|
||||
|
||||
if (!ComponentEntry)
|
||||
return NULL;
|
||||
|
||||
ResourceList = ComponentEntry->ConfigurationData;
|
||||
if (!ResourceList ||
|
||||
(ComponentEntry->ComponentEntry.ConfigurationDataLength <
|
||||
FIELD_OFFSET(CM_PARTIAL_RESOURCE_LIST, PartialDescriptors[1]) +
|
||||
FIELD_OFFSET(ACPI_BIOS_MULTI_NODE, E820Entry)) ||
|
||||
(ResourceList->Count < 1) ||
|
||||
(ResourceList->PartialDescriptors[0].Type != CmResourceTypeDeviceSpecific))
|
||||
{
|
||||
DPRINT1("Loader ACPI BIOS node is missing valid device-specific data\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (PACPI_BIOS_MULTI_NODE)(ResourceList + 1);
|
||||
}
|
||||
|
||||
static
|
||||
ACPI_PHYSICAL_ADDRESS
|
||||
AcpiBuildLoaderRootPointer(VOID)
|
||||
{
|
||||
PACPI_BIOS_MULTI_NODE NodeData;
|
||||
ACPI_TABLE_HEADER *RootTable;
|
||||
PHYSICAL_ADDRESS PhysicalAddress;
|
||||
|
||||
if (AcpiLoaderRsdp != NULL)
|
||||
{
|
||||
PhysicalAddress = MmGetPhysicalAddress(AcpiLoaderRsdp);
|
||||
return (ACPI_PHYSICAL_ADDRESS)PhysicalAddress.QuadPart;
|
||||
}
|
||||
|
||||
NodeData = AcpiGetLoaderAcpiBiosNode();
|
||||
if (!NodeData || (NodeData->RsdtAddress.QuadPart == 0))
|
||||
goto Failure;
|
||||
|
||||
RootTable = MmMapIoSpace(NodeData->RsdtAddress, sizeof(*RootTable), MmNonCached);
|
||||
if (!RootTable)
|
||||
{
|
||||
DPRINT1("Unable to map loader ACPI root table at 0x%I64x\n",
|
||||
NodeData->RsdtAddress.QuadPart);
|
||||
goto Failure;
|
||||
}
|
||||
|
||||
AcpiLoaderRsdp = ExAllocatePoolZero(NonPagedPool,
|
||||
sizeof(*AcpiLoaderRsdp),
|
||||
TAG_ACPI_LOADER_RSDP_TABLE);
|
||||
if (!AcpiLoaderRsdp)
|
||||
{
|
||||
DPRINT1("Unable to allocate synthetic RSDP for loader ACPI tables\n");
|
||||
goto Failure;
|
||||
}
|
||||
|
||||
RtlCopyMemory(AcpiLoaderRsdp->Signature,
|
||||
ACPI_SIG_RSDP,
|
||||
sizeof(AcpiLoaderRsdp->Signature));
|
||||
RtlCopyMemory(AcpiLoaderRsdp->OemId, "ROS ", sizeof(AcpiLoaderRsdp->OemId));
|
||||
|
||||
if (RtlEqualMemory(RootTable->Signature, ACPI_SIG_XSDT, ACPI_NAMESEG_SIZE))
|
||||
{
|
||||
AcpiLoaderRsdp->Revision = 2;
|
||||
AcpiLoaderRsdp->Length = sizeof(*AcpiLoaderRsdp);
|
||||
AcpiLoaderRsdp->XsdtPhysicalAddress = NodeData->RsdtAddress.QuadPart;
|
||||
}
|
||||
else if (RtlEqualMemory(RootTable->Signature, ACPI_SIG_RSDT, ACPI_NAMESEG_SIZE))
|
||||
{
|
||||
if (NodeData->RsdtAddress.QuadPart > MAXULONG)
|
||||
{
|
||||
DPRINT1("Loader RSDT address does not fit in 32 bits: 0x%I64x\n",
|
||||
NodeData->RsdtAddress.QuadPart);
|
||||
goto Failure;
|
||||
}
|
||||
|
||||
AcpiLoaderRsdp->Revision = 0;
|
||||
AcpiLoaderRsdp->RsdtPhysicalAddress = NodeData->RsdtAddress.LowPart;
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINT1("Loader ACPI root table has unexpected signature '%.4s'\n",
|
||||
RootTable->Signature);
|
||||
goto Failure;
|
||||
}
|
||||
|
||||
AcpiLoaderRsdp->Checksum = AcpiChecksumBuffer((const UCHAR *)AcpiLoaderRsdp,
|
||||
ACPI_RSDP_CHECKSUM_LENGTH);
|
||||
if (AcpiLoaderRsdp->Revision >= 2)
|
||||
{
|
||||
AcpiLoaderRsdp->ExtendedChecksum =
|
||||
AcpiChecksumBuffer((const UCHAR *)AcpiLoaderRsdp,
|
||||
sizeof(*AcpiLoaderRsdp));
|
||||
}
|
||||
|
||||
MmUnmapIoSpace(RootTable, sizeof(*RootTable));
|
||||
PhysicalAddress = MmGetPhysicalAddress(AcpiLoaderRsdp);
|
||||
return (ACPI_PHYSICAL_ADDRESS)PhysicalAddress.QuadPart;
|
||||
|
||||
Failure:
|
||||
if (AcpiLoaderRsdp)
|
||||
{
|
||||
ExFreePoolWithTag(AcpiLoaderRsdp, TAG_ACPI_LOADER_RSDP_TABLE);
|
||||
AcpiLoaderRsdp = NULL;
|
||||
}
|
||||
if (RootTable)
|
||||
MmUnmapIoSpace(RootTable, sizeof(*RootTable));
|
||||
return 0;
|
||||
}
|
||||
|
||||
ACPI_STATUS
|
||||
AcpiOsInitialize (void)
|
||||
@@ -28,6 +202,8 @@ AcpiOsInitialize (void)
|
||||
AcpiDbgLayer = 0xFFFFFFFF;
|
||||
#endif
|
||||
|
||||
(VOID)AcpiBuildLoaderRootPointer();
|
||||
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
@@ -36,6 +212,15 @@ AcpiOsTerminate(void)
|
||||
{
|
||||
DPRINT("AcpiOsTerminate() called\n");
|
||||
|
||||
/* Release the synthetic RSDP built from the loader-provided ACPI tables.
|
||||
* ACPICA has already torn down its table mappings (AcpiUtSubsystemShutdown)
|
||||
* by the time it calls us, so nothing references this buffer anymore. */
|
||||
if (AcpiLoaderRsdp != NULL)
|
||||
{
|
||||
ExFreePoolWithTag(AcpiLoaderRsdp, TAG_ACPI_LOADER_RSDP_TABLE);
|
||||
AcpiLoaderRsdp = NULL;
|
||||
}
|
||||
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
@@ -44,9 +229,16 @@ AcpiOsGetRootPointer (
|
||||
void)
|
||||
{
|
||||
ACPI_PHYSICAL_ADDRESS pa = 0;
|
||||
PHYSICAL_ADDRESS PhysicalAddress;
|
||||
|
||||
DPRINT("AcpiOsGetRootPointer\n");
|
||||
|
||||
if (AcpiLoaderRsdp != NULL)
|
||||
{
|
||||
PhysicalAddress = MmGetPhysicalAddress(AcpiLoaderRsdp);
|
||||
return (ACPI_PHYSICAL_ADDRESS)PhysicalAddress.QuadPart;
|
||||
}
|
||||
|
||||
AcpiFindRootPointer(&pa);
|
||||
return pa;
|
||||
}
|
||||
@@ -114,7 +306,7 @@ AcpiOsMapMemory (
|
||||
|
||||
DPRINT("AcpiOsMapMemory(phys 0x%p size 0x%X)\n", phys, length);
|
||||
|
||||
Address.QuadPart = (ULONG)phys;
|
||||
Address.QuadPart = (ULONGLONG)phys;
|
||||
Ptr = MmMapIoSpace(Address, length, MmNonCached);
|
||||
if (!Ptr)
|
||||
{
|
||||
|
||||
+13
-5
@@ -282,19 +282,25 @@ Bus_StartFdo (
|
||||
|
||||
AcpiStatus = AcpiInitializeSubsystem();
|
||||
if(ACPI_FAILURE(AcpiStatus)){
|
||||
DPRINT1("Unable to AcpiInitializeSubsystem\n");
|
||||
DPRINT1("Unable to AcpiInitializeSubsystem: %s (0x%08X)\n",
|
||||
AcpiFormatException(AcpiStatus),
|
||||
AcpiStatus);
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
AcpiStatus = AcpiInitializeTables(NULL, 16, 0);
|
||||
if (ACPI_FAILURE(AcpiStatus)){
|
||||
DPRINT1("Unable to AcpiInitializeTables\n");
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
DPRINT1("Unable to AcpiInitializeTables: %s (0x%08X)\n",
|
||||
AcpiFormatException(AcpiStatus),
|
||||
AcpiStatus);
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
AcpiStatus = AcpiLoadTables();
|
||||
if(ACPI_FAILURE(AcpiStatus)){
|
||||
DPRINT1("Unable to AcpiLoadTables\n");
|
||||
DPRINT1("Unable to AcpiLoadTables: %s (0x%08X)\n",
|
||||
AcpiFormatException(AcpiStatus),
|
||||
AcpiStatus);
|
||||
AcpiTerminate();
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
@@ -309,7 +315,9 @@ Bus_StartFdo (
|
||||
/* Initialize ACPI bus manager */
|
||||
AcpiStatus = acpi_init();
|
||||
if (!ACPI_SUCCESS(AcpiStatus)) {
|
||||
DPRINT1("acpi_init() failed with status 0x%X\n", AcpiStatus);
|
||||
DPRINT1("acpi_init() failed: %s (0x%08X)\n",
|
||||
AcpiFormatException(AcpiStatus),
|
||||
AcpiStatus);
|
||||
AcpiTerminate();
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user