DynamicTablesPkg: DynamicTableManagerDxe: Added check for installed tables

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3997

This change added an extra step to allow check for installed ACPI tables.

For FADT, MADT, GTDT, DSDT, DBG2 and SPCR tables, either pre-installed or
supplied through AcpiTableInfo can be accepted.

An extra check for FADT ACPI table existence during installation step is
also added.

Cc: Sami Mujawar <Sami.Mujawar@arm.com>
Cc: Alexei Fedorov <Alexei.Fedorov@arm.com>

Co-authored-by: Joe Lopez <joelopez@microsoft.com>
Signed-off-by: Kun Qin <kuqin12@gmail.com>
Reviewed-by: Pierre Gondois <pierre.gondois@arm.com>
Reviewed-by: Sami Mujawar <sami.mujawar@Arm.com>
Tested-by: Sami Mujawar <sami.mujawar@arm.com>
This commit is contained in:
Kun Qin 2022-07-05 12:31:07 -07:00 committed by mergify[bot]
parent d9c8a9cf11
commit 5236d47854
2 changed files with 144 additions and 84 deletions

View File

@ -10,6 +10,7 @@
#include <Library/DebugLib.h>
#include <Library/PcdLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Protocol/AcpiSystemDescriptionTable.h>
#include <Protocol/AcpiTable.h>
// Module specific include files.
@ -22,6 +23,58 @@
#include <Protocol/DynamicTableFactoryProtocol.h>
#include <SmbiosTableGenerator.h>
///
/// Bit definitions for acceptable ACPI table presence formats.
/// Currently only ACPI tables present in the ACPI info list and
/// already installed will count towards "Table Present" during
/// verification routine.
///
#define ACPI_TABLE_PRESENT_INFO_LIST BIT0
#define ACPI_TABLE_PRESENT_INSTALLED BIT1
///
/// Order of ACPI table being verified during presence inspection.
///
#define ACPI_TABLE_VERIFY_FADT 0
#define ACPI_TABLE_VERIFY_MADT 1
#define ACPI_TABLE_VERIFY_GTDT 2
#define ACPI_TABLE_VERIFY_DSDT 3
#define ACPI_TABLE_VERIFY_DBG2 4
#define ACPI_TABLE_VERIFY_SPCR 5
#define ACPI_TABLE_VERIFY_COUNT 6
///
/// Private data structure to verify the presence of mandatory
/// or optional ACPI tables.
///
typedef struct {
/// ESTD ID for the ACPI table of interest.
ESTD_ACPI_TABLE_ID EstdTableId;
/// Standard UINT32 ACPI signature.
UINT32 AcpiTableSignature;
/// 4 character ACPI table name (the 5th char8 is for null terminator).
CHAR8 AcpiTableName[sizeof (UINT32) + 1];
/// Indicator on whether the ACPI table is required.
BOOLEAN IsMandatory;
/// Formats of verified presences, as defined by ACPI_TABLE_PRESENT_*
/// This field should be initialized to 0 and will be populated during
/// verification routine.
UINT16 Presence;
} ACPI_TABLE_PRESENCE_INFO;
///
/// We require the FADT, MADT, GTDT and the DSDT tables to boot.
/// This list also include optional ACPI tables: DBG2, SPCR.
///
ACPI_TABLE_PRESENCE_INFO mAcpiVerifyTables[ACPI_TABLE_VERIFY_COUNT] = {
{ EStdAcpiTableIdFadt, EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE, "FADT", TRUE, 0 },
{ EStdAcpiTableIdMadt, EFI_ACPI_6_2_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE, "MADT", TRUE, 0 },
{ EStdAcpiTableIdGtdt, EFI_ACPI_6_2_GENERIC_TIMER_DESCRIPTION_TABLE_SIGNATURE, "GTDT", TRUE, 0 },
{ EStdAcpiTableIdDsdt, EFI_ACPI_6_2_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE, "DSDT", TRUE, 0 },
{ EStdAcpiTableIdDbg2, EFI_ACPI_6_2_DEBUG_PORT_2_TABLE_SIGNATURE, "DBG2", FALSE, 0 },
{ EStdAcpiTableIdSpcr, EFI_ACPI_6_2_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE, "SPCR", FALSE, 0 },
};
/** This macro expands to a function that retrieves the ACPI Table
List from the Configuration Manager.
*/
@ -395,6 +448,7 @@ BuildAndInstallAcpiTable (
@retval EFI_SUCCESS Success.
@retval EFI_NOT_FOUND If mandatory table is not found.
@retval EFI_ALREADY_STARTED If mandatory table found in AcpiTableInfo is already installed.
**/
STATIC
EFI_STATUS
@ -404,75 +458,73 @@ VerifyMandatoryTablesArePresent (
IN UINT32 AcpiTableCount
)
{
EFI_STATUS Status;
BOOLEAN FadtFound;
BOOLEAN MadtFound;
BOOLEAN GtdtFound;
BOOLEAN DsdtFound;
BOOLEAN Dbg2Found;
BOOLEAN SpcrFound;
EFI_STATUS Status;
UINTN Handle;
UINTN Index;
UINTN InstalledTableIndex;
EFI_ACPI_DESCRIPTION_HEADER *DescHeader;
EFI_ACPI_TABLE_VERSION Version;
EFI_ACPI_SDT_PROTOCOL *AcpiSdt;
Status = EFI_SUCCESS;
FadtFound = FALSE;
MadtFound = FALSE;
GtdtFound = FALSE;
DsdtFound = FALSE;
Dbg2Found = FALSE;
SpcrFound = FALSE;
ASSERT (AcpiTableInfo != NULL);
Status = EFI_SUCCESS;
// Check against the statically initialized ACPI tables to see if they are in ACPI info list
while (AcpiTableCount-- != 0) {
switch (AcpiTableInfo[AcpiTableCount].AcpiTableSignature) {
case EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE:
FadtFound = TRUE;
break;
case EFI_ACPI_6_2_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE:
MadtFound = TRUE;
break;
case EFI_ACPI_6_2_GENERIC_TIMER_DESCRIPTION_TABLE_SIGNATURE:
GtdtFound = TRUE;
break;
case EFI_ACPI_6_2_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:
DsdtFound = TRUE;
break;
case EFI_ACPI_6_2_DEBUG_PORT_2_TABLE_SIGNATURE:
Dbg2Found = TRUE;
break;
case EFI_ACPI_6_2_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE:
SpcrFound = TRUE;
break;
default:
for (Index = 0; Index < ACPI_TABLE_VERIFY_COUNT; Index++) {
if (AcpiTableInfo[AcpiTableCount].AcpiTableSignature == mAcpiVerifyTables[Index].AcpiTableSignature) {
mAcpiVerifyTables[Index].Presence |= ACPI_TABLE_PRESENT_INFO_LIST;
// Found this table, skip the rest.
break;
}
}
}
// We need at least the FADT, MADT, GTDT and the DSDT tables to boot
if (!FadtFound) {
DEBUG ((DEBUG_ERROR, "ERROR: FADT Table not found\n"));
Status = EFI_NOT_FOUND;
// They also might be published already, so we can search from there
if (FeaturePcdGet (PcdInstallAcpiSdtProtocol)) {
AcpiSdt = NULL;
Status = gBS->LocateProtocol (&gEfiAcpiSdtProtocolGuid, NULL, (VOID **)&AcpiSdt);
if (EFI_ERROR (Status) || (AcpiSdt == NULL)) {
DEBUG ((DEBUG_ERROR, "ERROR: Failed to locate ACPI SDT protocol (0x%p) - %r\n", AcpiSdt, Status));
return Status;
}
for (Index = 0; Index < ACPI_TABLE_VERIFY_COUNT; Index++) {
Handle = 0;
InstalledTableIndex = 0;
do {
Status = AcpiSdt->GetAcpiTable (InstalledTableIndex, (EFI_ACPI_SDT_HEADER **)&DescHeader, &Version, &Handle);
if (EFI_ERROR (Status)) {
break;
}
InstalledTableIndex++;
} while (DescHeader->Signature != mAcpiVerifyTables[Index].AcpiTableSignature);
if (!EFI_ERROR (Status)) {
mAcpiVerifyTables[Index].Presence |= ACPI_TABLE_PRESENT_INSTALLED;
}
}
}
if (!MadtFound) {
DEBUG ((DEBUG_ERROR, "ERROR: MADT Table not found.\n"));
Status = EFI_NOT_FOUND;
}
if (!GtdtFound) {
DEBUG ((DEBUG_ERROR, "ERROR: GTDT Table not found.\n"));
Status = EFI_NOT_FOUND;
}
if (!DsdtFound) {
DEBUG ((DEBUG_ERROR, "ERROR: DSDT Table not found.\n"));
Status = EFI_NOT_FOUND;
}
if (!Dbg2Found) {
DEBUG ((DEBUG_WARN, "WARNING: DBG2 Table not found.\n"));
}
if (!SpcrFound) {
DEBUG ((DEBUG_WARN, "WARNING: SPCR Table not found.\n"));
// Reset the return Status value to EFI_SUCCESS. We do not fully care if the table look up has failed.
Status = EFI_SUCCESS;
for (Index = 0; Index < ACPI_TABLE_VERIFY_COUNT; Index++) {
if (mAcpiVerifyTables[Index].Presence == 0) {
if (mAcpiVerifyTables[Index].IsMandatory) {
DEBUG ((DEBUG_ERROR, "ERROR: %a Table not found.\n", mAcpiVerifyTables[Index].AcpiTableName));
Status = EFI_NOT_FOUND;
} else {
DEBUG ((DEBUG_WARN, "WARNING: %a Table not found.\n", mAcpiVerifyTables[Index].AcpiTableName));
}
} else if (mAcpiVerifyTables[Index].Presence ==
(ACPI_TABLE_PRESENT_INFO_LIST | ACPI_TABLE_PRESENT_INSTALLED))
{
DEBUG ((DEBUG_ERROR, "ERROR: %a Table found while already published.\n", mAcpiVerifyTables[Index].AcpiTableName));
Status = EFI_ALREADY_STARTED;
}
}
return Status;
@ -489,8 +541,9 @@ VerifyMandatoryTablesArePresent (
@param [in] CfgMgrProtocol Pointer to the Configuration Manager
Protocol Interface.
@retval EFI_SUCCESS Success.
@retval EFI_NOT_FOUND If a mandatory table or a generator is not found.
@retval EFI_SUCCESS Success.
@retval EFI_NOT_FOUND If a mandatory table or a generator is not found.
@retval EFI_ALREADY_STARTED If mandatory table found in AcpiTableInfo is already installed.
**/
STATIC
EFI_STATUS
@ -562,7 +615,7 @@ ProcessAcpiTables (
if (EFI_ERROR (Status)) {
DEBUG ((
DEBUG_ERROR,
"ERROR: Failed to find mandatory ACPI Table(s)."
"ERROR: Failed to verify mandatory ACPI Table(s) presence."
" Status = %r\n",
Status
));
@ -570,29 +623,32 @@ ProcessAcpiTables (
}
// Add the FADT Table first.
for (Idx = 0; Idx < AcpiTableCount; Idx++) {
if (CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdFadt) ==
AcpiTableInfo[Idx].TableGeneratorId)
{
Status = BuildAndInstallAcpiTable (
TableFactoryProtocol,
CfgMgrProtocol,
AcpiTableProtocol,
&AcpiTableInfo[Idx]
);
if (EFI_ERROR (Status)) {
DEBUG ((
DEBUG_ERROR,
"ERROR: Failed to find build and install ACPI FADT Table." \
" Status = %r\n",
Status
));
return Status;
}
if ((mAcpiVerifyTables[ACPI_TABLE_VERIFY_FADT].Presence & ACPI_TABLE_PRESENT_INSTALLED) == 0) {
// FADT is not yet installed
for (Idx = 0; Idx < AcpiTableCount; Idx++) {
if (CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdFadt) ==
AcpiTableInfo[Idx].TableGeneratorId)
{
Status = BuildAndInstallAcpiTable (
TableFactoryProtocol,
CfgMgrProtocol,
AcpiTableProtocol,
&AcpiTableInfo[Idx]
);
if (EFI_ERROR (Status)) {
DEBUG ((
DEBUG_ERROR,
"ERROR: Failed to find build and install ACPI FADT Table." \
" Status = %r\n",
Status
));
return Status;
}
break;
}
} // for
break;
}
} // for
}
// Add remaining ACPI Tables
for (Idx = 0; Idx < AcpiTableCount; Idx++) {

View File

@ -34,8 +34,12 @@
UefiBootServicesTableLib
UefiDriverEntryPoint
[FeaturePcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdInstallAcpiSdtProtocol ## CONSUMES
[Protocols]
gEfiAcpiTableProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiAcpiSdtProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEdkiiConfigurationManagerProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEdkiiDynamicTableFactoryProtocolGuid # PROTOCOL ALWAYS_CONSUMED