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
**/
#include <Protocol/AcpiTable.h>
/**
Searches and returns the address of the ACPI Root System Description Pointer (RSDP) in system memory.
@ -22,3 +24,26 @@ GetAcpiRsdpFromMemory (
IN UINT64 EndAddress,
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;
}
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/XenPlatformLib.h> // XenDetected()
#include <Library/AcpiPlatformLib.h> // InstallAcpiTablesFromMemory()
#include <Library/DebugLib.h> // DEBUG()
#include <Library/XenPlatformLib.h> // XenDetected()
#include "AcpiPlatform.h"
#define XEN_ACPI_PHYSICAL_ADDRESS 0x000EA020
#define XEN_BIOS_PHYSICAL_END 0x000FFFFF
/**
Effective entrypoint of Acpi Platform driver.
@ -28,10 +33,46 @@ InstallAcpiTables (
IN EFI_ACPI_TABLE_PROTOCOL *AcpiTable
)
{
EFI_STATUS Status;
EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *RsdpStructurePtr;
EFI_XEN_INFO *XenInfo;
EFI_STATUS Status;
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 {
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.h
EntryPoint.c
Xen.c
[Packages]
MdePkg/MdePkg.dec