OvmfPkg/Xen: export AcpiTable installation into AcpiPlatformLib

This makes the function reuseable by bhyve.

Signed-off-by: Corvin Köhne <corvink@FreeBSD.org>
Reviewed-by: Anthony PERARD <anthony.perard@citrix.com>
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
This commit is contained in:
Corvin Köhne 2023-06-06 11:21:38 +02:00 committed by mergify[bot]
parent f211292711
commit 1288c5415c
5 changed files with 254 additions and 261 deletions

View File

@ -4,6 +4,8 @@
SPDX-License-Identifier: BSD-2-Clause-Patent SPDX-License-Identifier: BSD-2-Clause-Patent
**/ **/
#include <Protocol/AcpiTable.h>
/** /**
Searches and returns the address of the ACPI Root System Description Pointer (RSDP) in system memory. Searches and returns the address of the ACPI Root System Description Pointer (RSDP) in system memory.
@ -22,3 +24,26 @@ GetAcpiRsdpFromMemory (
IN UINT64 EndAddress, IN UINT64 EndAddress,
OUT EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER **RsdpPtr OUT EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER **RsdpPtr
); );
/**
Get Acpi tables from the RSDP structure. And installs ACPI tables
into the RSDT/XSDT using InstallAcpiTable. Some signature of the installed
ACPI tables are: FACP, APIC, HPET, WAET, SSDT, FACS, DSDT.
@param AcpiProtocol Protocol instance pointer.
@return EFI_SUCCESS The table was successfully inserted.
@return EFI_INVALID_PARAMETER Either AcpiTableBuffer is NULL, TableHandle is
NULL, or AcpiTableBufferSize and the size
field embedded in the ACPI table pointed to
by AcpiTableBuffer are not in sync.
@return EFI_OUT_OF_RESOURCES Insufficient resources exist to complete the
request.
**/
EFI_STATUS
EFIAPI
InstallAcpiTablesFromRsdp (
IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol,
IN EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp
);

View File

@ -65,3 +65,188 @@ GetAcpiRsdpFromMemory (
return EFI_NOT_FOUND; return EFI_NOT_FOUND;
} }
EFI_STATUS
EFIAPI
InstallAcpiTablesFromRsdp (
IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol,
IN EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp
)
{
EFI_STATUS Status;
UINTN TableHandle;
EFI_ACPI_DESCRIPTION_HEADER *Rsdt;
EFI_ACPI_DESCRIPTION_HEADER *Xsdt;
VOID *CurrentTableEntry;
UINTN CurrentTablePointer;
EFI_ACPI_DESCRIPTION_HEADER *CurrentTable;
UINTN Index;
UINTN NumberOfTableEntries;
EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *Fadt2Table;
EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE *Fadt1Table;
EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs2Table;
EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs1Table;
EFI_ACPI_DESCRIPTION_HEADER *DsdtTable;
Fadt2Table = NULL;
Fadt1Table = NULL;
Facs2Table = NULL;
Facs1Table = NULL;
DsdtTable = NULL;
TableHandle = 0;
NumberOfTableEntries = 0;
//
// If XSDT table is find, just install its tables.
// Otherwise, try to find and install the RSDT tables.
//
if (Rsdp->XsdtAddress) {
//
// Retrieve the addresses of XSDT and
// calculate the number of its table entries.
//
Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)Rsdp->XsdtAddress;
NumberOfTableEntries =
(Xsdt->Length - sizeof (EFI_ACPI_DESCRIPTION_HEADER)) / sizeof (UINT64);
//
// Install ACPI tables found in XSDT.
//
for (Index = 0; Index < NumberOfTableEntries; Index++) {
//
// Get the table entry from XSDT
//
CurrentTableEntry =
(VOID *)((UINT8 *)Xsdt + sizeof (EFI_ACPI_DESCRIPTION_HEADER) +
Index * sizeof (UINT64));
CurrentTablePointer = (UINTN)*(UINT64 *)CurrentTableEntry;
CurrentTable = (EFI_ACPI_DESCRIPTION_HEADER *)CurrentTablePointer;
//
// Install the XSDT tables
//
Status = AcpiProtocol->InstallAcpiTable (
AcpiProtocol,
CurrentTable,
CurrentTable->Length,
&TableHandle
);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Get the FACS and DSDT table address from the table FADT
//
if (!AsciiStrnCmp ((CHAR8 *)&CurrentTable->Signature, "FACP", 4)) {
Fadt2Table = (EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *)(UINTN)
CurrentTablePointer;
Facs2Table = (EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *)(UINTN)
Fadt2Table->FirmwareCtrl;
DsdtTable = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)Fadt2Table->Dsdt;
}
}
} else if (Rsdp->RsdtAddress) {
//
// Retrieve the addresses of RSDT and
// calculate the number of its table entries.
//
Rsdt = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)Rsdp->RsdtAddress;
NumberOfTableEntries =
(Rsdt->Length - sizeof (EFI_ACPI_DESCRIPTION_HEADER)) / sizeof (UINT32);
//
// Install ACPI tables found in XSDT.
//
for (Index = 0; Index < NumberOfTableEntries; Index++) {
//
// Get the table entry from RSDT
//
CurrentTableEntry =
(UINT32 *)((UINT8 *)Rsdt + sizeof (EFI_ACPI_DESCRIPTION_HEADER) +
Index * sizeof (UINT32));
CurrentTablePointer = *(UINT32 *)CurrentTableEntry;
CurrentTable = (EFI_ACPI_DESCRIPTION_HEADER *)CurrentTablePointer;
//
// Install the RSDT tables
//
Status = AcpiProtocol->InstallAcpiTable (
AcpiProtocol,
CurrentTable,
CurrentTable->Length,
&TableHandle
);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Get the FACS and DSDT table address from the table FADT
//
if (!AsciiStrnCmp ((CHAR8 *)&CurrentTable->Signature, "FACP", 4)) {
Fadt1Table = (EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE *)(UINTN)
CurrentTablePointer;
Facs1Table = (EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *)(UINTN)
Fadt1Table->FirmwareCtrl;
DsdtTable = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)Fadt1Table->Dsdt;
}
}
}
//
// Install the FACS table.
//
if (Fadt2Table) {
//
// FACS 2.0
//
Status = AcpiProtocol->InstallAcpiTable (
AcpiProtocol,
Facs2Table,
Facs2Table->Length,
&TableHandle
);
if (EFI_ERROR (Status)) {
return Status;
}
} else if (Fadt1Table) {
//
// FACS 1.0
//
Status = AcpiProtocol->InstallAcpiTable (
AcpiProtocol,
Facs1Table,
Facs1Table->Length,
&TableHandle
);
if (EFI_ERROR (Status)) {
return Status;
}
}
//
// Install DSDT table. If we reached this point without finding the DSDT,
// then we're out of sync with the hypervisor, and cannot continue.
//
if (DsdtTable == NULL) {
DEBUG ((DEBUG_ERROR, "%a: no DSDT found\n", __func__));
ASSERT (FALSE);
CpuDeadLoop ();
}
Status = AcpiProtocol->InstallAcpiTable (
AcpiProtocol,
DsdtTable,
DsdtTable->Length,
&TableHandle
);
if (EFI_ERROR (Status)) {
return Status;
}
return EFI_SUCCESS;
}

View File

@ -7,10 +7,15 @@
**/ **/
#include <Library/AcpiPlatformLib.h> // InstallAcpiTablesFromMemory()
#include <Library/DebugLib.h> // DEBUG()
#include <Library/XenPlatformLib.h> // XenDetected() #include <Library/XenPlatformLib.h> // XenDetected()
#include "AcpiPlatform.h" #include "AcpiPlatform.h"
#define XEN_ACPI_PHYSICAL_ADDRESS 0x000EA020
#define XEN_BIOS_PHYSICAL_END 0x000FFFFF
/** /**
Effective entrypoint of Acpi Platform driver. Effective entrypoint of Acpi Platform driver.
@ -28,10 +33,46 @@ InstallAcpiTables (
IN EFI_ACPI_TABLE_PROTOCOL *AcpiTable IN EFI_ACPI_TABLE_PROTOCOL *AcpiTable
) )
{ {
EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *RsdpStructurePtr;
EFI_XEN_INFO *XenInfo;
EFI_STATUS Status; EFI_STATUS Status;
if (XenDetected ()) { if (XenDetected ()) {
Status = InstallXenTables (AcpiTable); //
// Detect the RSDP structure
//
//
// First look for PVH one
//
XenInfo = XenGetInfoHOB ();
ASSERT (XenInfo != NULL);
if (XenInfo->RsdpPvh != NULL) {
DEBUG ((
DEBUG_INFO,
"%a: Use ACPI RSDP table at 0x%p\n",
gEfiCallerBaseName,
XenInfo->RsdpPvh
));
RsdpStructurePtr = XenInfo->RsdpPvh;
} else {
//
// Otherwise, look for the HVM one
//
Status = GetAcpiRsdpFromMemory (
XEN_ACPI_PHYSICAL_ADDRESS,
XEN_BIOS_PHYSICAL_END,
&RsdpStructurePtr
);
if (EFI_ERROR (Status)) {
return Status;
}
}
Status = InstallAcpiTablesFromRsdp (
AcpiTable,
RsdpStructurePtr
);
} else { } else {
Status = EFI_UNSUPPORTED; Status = EFI_UNSUPPORTED;
} }

View File

@ -1,257 +0,0 @@
/** @file
OVMF ACPI Xen support
Copyright (C) 2021, Red Hat, Inc.
Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2012, Bei Guan <gbtju85@gmail.com>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include <Library/AcpiPlatformLib.h>
#include <Library/BaseLib.h> // CpuDeadLoop()
#include <Library/DebugLib.h> // DEBUG()
#include <Library/XenPlatformLib.h> // XenGetInfoHOB()
#include "AcpiPlatform.h"
#define XEN_ACPI_PHYSICAL_ADDRESS 0x000EA020
#define XEN_BIOS_PHYSICAL_END 0x000FFFFF
EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *XenAcpiRsdpStructurePtr = NULL;
/**
Get Xen Acpi tables from the RSDP structure. And installs Xen ACPI tables
into the RSDT/XSDT using InstallAcpiTable. Some signature of the installed
ACPI tables are: FACP, APIC, HPET, WAET, SSDT, FACS, DSDT.
@param AcpiProtocol Protocol instance pointer.
@return EFI_SUCCESS The table was successfully inserted.
@return EFI_INVALID_PARAMETER Either AcpiTableBuffer is NULL, TableHandle is
NULL, or AcpiTableBufferSize and the size
field embedded in the ACPI table pointed to
by AcpiTableBuffer are not in sync.
@return EFI_OUT_OF_RESOURCES Insufficient resources exist to complete the request.
**/
EFI_STATUS
EFIAPI
InstallXenTables (
IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol
)
{
EFI_STATUS Status;
UINTN TableHandle;
EFI_ACPI_DESCRIPTION_HEADER *Rsdt;
EFI_ACPI_DESCRIPTION_HEADER *Xsdt;
VOID *CurrentTableEntry;
UINTN CurrentTablePointer;
EFI_ACPI_DESCRIPTION_HEADER *CurrentTable;
UINTN Index;
UINTN NumberOfTableEntries;
EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *Fadt2Table;
EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE *Fadt1Table;
EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs2Table;
EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs1Table;
EFI_ACPI_DESCRIPTION_HEADER *DsdtTable;
EFI_XEN_INFO *XenInfo;
Fadt2Table = NULL;
Fadt1Table = NULL;
Facs2Table = NULL;
Facs1Table = NULL;
DsdtTable = NULL;
TableHandle = 0;
NumberOfTableEntries = 0;
//
// Detect the RSDP structure
//
//
// First look for PVH one
//
XenInfo = XenGetInfoHOB ();
ASSERT (XenInfo != NULL);
if (XenInfo->RsdpPvh != NULL) {
DEBUG ((
DEBUG_INFO,
"%a: Use ACPI RSDP table at 0x%p\n",
gEfiCallerBaseName,
XenInfo->RsdpPvh
));
XenAcpiRsdpStructurePtr = XenInfo->RsdpPvh;
} else {
//
// Otherwise, look for the HVM one
//
Status = GetAcpiRsdpFromMemory (
XEN_ACPI_PHYSICAL_ADDRESS,
XEN_BIOS_PHYSICAL_END,
&XenAcpiRsdpStructurePtr
);
if (EFI_ERROR (Status)) {
return Status;
}
}
//
// If XSDT table is find, just install its tables.
// Otherwise, try to find and install the RSDT tables.
//
if (XenAcpiRsdpStructurePtr->XsdtAddress) {
//
// Retrieve the addresses of XSDT and
// calculate the number of its table entries.
//
Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)
XenAcpiRsdpStructurePtr->XsdtAddress;
NumberOfTableEntries = (Xsdt->Length -
sizeof (EFI_ACPI_DESCRIPTION_HEADER)) /
sizeof (UINT64);
//
// Install ACPI tables found in XSDT.
//
for (Index = 0; Index < NumberOfTableEntries; Index++) {
//
// Get the table entry from XSDT
//
CurrentTableEntry = (VOID *)((UINT8 *)Xsdt +
sizeof (EFI_ACPI_DESCRIPTION_HEADER) +
Index * sizeof (UINT64));
CurrentTablePointer = (UINTN)*(UINT64 *)CurrentTableEntry;
CurrentTable = (EFI_ACPI_DESCRIPTION_HEADER *)CurrentTablePointer;
//
// Install the XSDT tables
//
Status = AcpiProtocol->InstallAcpiTable (
AcpiProtocol,
CurrentTable,
CurrentTable->Length,
&TableHandle
);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Get the FACS and DSDT table address from the table FADT
//
if (!AsciiStrnCmp ((CHAR8 *)&CurrentTable->Signature, "FACP", 4)) {
Fadt2Table = (EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *)
(UINTN)CurrentTablePointer;
Facs2Table = (EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *)
(UINTN)Fadt2Table->FirmwareCtrl;
DsdtTable = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)Fadt2Table->Dsdt;
}
}
} else if (XenAcpiRsdpStructurePtr->RsdtAddress) {
//
// Retrieve the addresses of RSDT and
// calculate the number of its table entries.
//
Rsdt = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)
XenAcpiRsdpStructurePtr->RsdtAddress;
NumberOfTableEntries = (Rsdt->Length -
sizeof (EFI_ACPI_DESCRIPTION_HEADER)) /
sizeof (UINT32);
//
// Install ACPI tables found in XSDT.
//
for (Index = 0; Index < NumberOfTableEntries; Index++) {
//
// Get the table entry from RSDT
//
CurrentTableEntry = (UINT32 *)((UINT8 *)Rsdt +
sizeof (EFI_ACPI_DESCRIPTION_HEADER) +
Index * sizeof (UINT32));
CurrentTablePointer = *(UINT32 *)CurrentTableEntry;
CurrentTable = (EFI_ACPI_DESCRIPTION_HEADER *)CurrentTablePointer;
//
// Install the RSDT tables
//
Status = AcpiProtocol->InstallAcpiTable (
AcpiProtocol,
CurrentTable,
CurrentTable->Length,
&TableHandle
);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Get the FACS and DSDT table address from the table FADT
//
if (!AsciiStrnCmp ((CHAR8 *)&CurrentTable->Signature, "FACP", 4)) {
Fadt1Table = (EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE *)
(UINTN)CurrentTablePointer;
Facs1Table = (EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *)
(UINTN)Fadt1Table->FirmwareCtrl;
DsdtTable = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)Fadt1Table->Dsdt;
}
}
}
//
// Install the FACS table.
//
if (Fadt2Table) {
//
// FACS 2.0
//
Status = AcpiProtocol->InstallAcpiTable (
AcpiProtocol,
Facs2Table,
Facs2Table->Length,
&TableHandle
);
if (EFI_ERROR (Status)) {
return Status;
}
} else if (Fadt1Table) {
//
// FACS 1.0
//
Status = AcpiProtocol->InstallAcpiTable (
AcpiProtocol,
Facs1Table,
Facs1Table->Length,
&TableHandle
);
if (EFI_ERROR (Status)) {
return Status;
}
}
//
// Install DSDT table. If we reached this point without finding the DSDT,
// then we're out of sync with the hypervisor, and cannot continue.
//
if (DsdtTable == NULL) {
DEBUG ((DEBUG_ERROR, "%a: no DSDT found\n", __func__));
ASSERT (FALSE);
CpuDeadLoop ();
}
Status = AcpiProtocol->InstallAcpiTable (
AcpiProtocol,
DsdtTable,
DsdtTable->Length,
&TableHandle
);
if (EFI_ERROR (Status)) {
return Status;
}
return EFI_SUCCESS;
}

View File

@ -25,7 +25,6 @@
AcpiPlatform.c AcpiPlatform.c
AcpiPlatform.h AcpiPlatform.h
EntryPoint.c EntryPoint.c
Xen.c
[Packages] [Packages]
MdePkg/MdePkg.dec MdePkg/MdePkg.dec