[PATCH v3 4/6] DynamicTablesPkg: DynamicTableManagerDxe: Added check for installed tables


Kun Qin
 

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

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@...>
Cc: Alexei Fedorov <Alexei.Fedorov@...>

Co-authored-by: Joe Lopez <joelopez@...>
Signed-off-by: Kun Qin <kuqin12@...>
Reviewed-by: Pierre Gondois <pierre.gondois@...>
---

Notes:
v2:
- Function description updates [Sami]
- Refactorized the table verification [Pierre]
=20=20=20=20
v3:
- Added descriptions for new structures [Pierre]
- Added check for SDT protocol PCD before using it [Pierre]

DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableManagerDxe.c =
| 214 ++++++++++++--------
DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableManagerDxe.inf=
| 4 +
2 files changed, 138 insertions(+), 80 deletions(-)

diff --git a/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableMa=
nagerDxe.c b/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableMa=
nagerDxe.c
index ed62299f9bbd..7f3deef08a66 100644
--- a/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableManagerDx=
e.c
+++ b/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableManagerDx=
e.c
@@ -10,6 +10,7 @@
#include <Library/DebugLib.h>=0D
#include <Library/PcdLib.h>=0D
#include <Library/UefiBootServicesTableLib.h>=0D
+#include <Protocol/AcpiSystemDescriptionTable.h>=0D
#include <Protocol/AcpiTable.h>=0D
=0D
// Module specific include files.=0D
@@ -22,6 +23,58 @@
#include <Protocol/DynamicTableFactoryProtocol.h>=0D
#include <SmbiosTableGenerator.h>=0D
=0D
+///=0D
+/// Bit definitions for acceptable ACPI table presence formats.=0D
+/// Currently only ACPI tables present in the ACPI info list and=0D
+/// already installed will count towards "Table Present" during=0D
+/// verification routine.=0D
+///=0D
+#define ACPI_TABLE_PRESENT_INFO_LIST BIT0=0D
+#define ACPI_TABLE_PRESENT_INSTALLED BIT1=0D
+=0D
+///=0D
+/// Order of ACPI table being verified during presence inspection.=0D
+///=0D
+#define ACPI_TABLE_VERIFY_FADT 0=0D
+#define ACPI_TABLE_VERIFY_MADT 1=0D
+#define ACPI_TABLE_VERIFY_GTDT 2=0D
+#define ACPI_TABLE_VERIFY_DSDT 3=0D
+#define ACPI_TABLE_VERIFY_DBG2 4=0D
+#define ACPI_TABLE_VERIFY_SPCR 5=0D
+#define ACPI_TABLE_VERIFY_COUNT 6=0D
+=0D
+///=0D
+/// Private data structure to verify the presence of mandatory=0D
+/// or optional ACPI tables.=0D
+///=0D
+typedef struct {=0D
+ /// ESTD ID for the ACPI table of interest.=0D
+ ESTD_ACPI_TABLE_ID EstdTableId;=0D
+ /// Standard UINT32 ACPI signature.=0D
+ UINT32 AcpiTableSignature;=0D
+ /// 4 character ACPI table name (the 5th char8 is for null terminator).=
=0D
+ CHAR8 AcpiTableName[sizeof (UINT32) + 1];=0D
+ /// Indicator on whether the ACPI table is required.=0D
+ BOOLEAN IsMandatory;=0D
+ /// Formats of verified presences, as defined by ACPI_TABLE_PRESENT_*=0D
+ /// This field should be initialized to 0 and will be populated during=0D
+ /// verification routine.=0D
+ UINT16 Presence;=0D
+} ACPI_TABLE_PRESENCE_INFO;=0D
+=0D
+///=0D
+/// We require the FADT, MADT, GTDT and the DSDT tables to boot.=0D
+/// This list also include optional ACPI tables: DBG2, SPCR.=0D
+///=0D
+ACPI_TABLE_PRESENCE_INFO mAcpiVerifyTables[ACPI_TABLE_VERIFY_COUNT] =3D {=
=0D
+ { EStdAcpiTableIdFadt, EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATU=
RE, "FADT", TRUE, 0 },=0D
+ { EStdAcpiTableIdMadt, EFI_ACPI_6_2_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGN=
ATURE, "MADT", TRUE, 0 },=0D
+ { EStdAcpiTableIdGtdt, EFI_ACPI_6_2_GENERIC_TIMER_DESCRIPTION_TABLE_SIGN=
ATURE, "GTDT", TRUE, 0 },=0D
+ { EStdAcpiTableIdDsdt, EFI_ACPI_6_2_DIFFERENTIATED_SYSTEM_DESCRIPTION_TA=
BLE_SIGNATURE, "DSDT", TRUE, 0 },=0D
+ { EStdAcpiTableIdDbg2, EFI_ACPI_6_2_DEBUG_PORT_2_TABLE_SIGNATURE, =
"DBG2", FALSE, 0 },=0D
+ { EStdAcpiTableIdSpcr, EFI_ACPI_6_2_SERIAL_PORT_CONSOLE_REDIRECTION_TABL=
E_SIGNATURE, "SPCR", FALSE, 0 },=0D
+};=0D
+=0D
/** This macro expands to a function that retrieves the ACPI Table=0D
List from the Configuration Manager.=0D
*/=0D
@@ -395,6 +448,7 @@ BuildAndInstallAcpiTable (
=0D
@retval EFI_SUCCESS Success.=0D
@retval EFI_NOT_FOUND If mandatory table is not found.=0D
+ @retval EFI_ALREADY_STARTED If mandatory table found in AcpiTableInfo =
is already installed.=0D
**/=0D
STATIC=0D
EFI_STATUS=0D
@@ -404,75 +458,71 @@ VerifyMandatoryTablesArePresent (
IN UINT32 AcpiTableCount=0D
)=0D
{=0D
- EFI_STATUS Status;=0D
- BOOLEAN FadtFound;=0D
- BOOLEAN MadtFound;=0D
- BOOLEAN GtdtFound;=0D
- BOOLEAN DsdtFound;=0D
- BOOLEAN Dbg2Found;=0D
- BOOLEAN SpcrFound;=0D
+ EFI_STATUS Status;=0D
+ UINTN Handle;=0D
+ UINTN Index;=0D
+ UINTN InstalledTableIndex;=0D
+ EFI_ACPI_DESCRIPTION_HEADER *DescHeader;=0D
+ EFI_ACPI_TABLE_VERSION Version;=0D
+ EFI_ACPI_SDT_PROTOCOL *AcpiSdt;=0D
=0D
- Status =3D EFI_SUCCESS;=0D
- FadtFound =3D FALSE;=0D
- MadtFound =3D FALSE;=0D
- GtdtFound =3D FALSE;=0D
- DsdtFound =3D FALSE;=0D
- Dbg2Found =3D FALSE;=0D
- SpcrFound =3D FALSE;=0D
ASSERT (AcpiTableInfo !=3D NULL);=0D
=0D
+ Status =3D EFI_SUCCESS;=0D
+=0D
+ // Check against the statically initialized ACPI tables to see if they a=
re in ACPI info list=0D
while (AcpiTableCount-- !=3D 0) {=0D
- switch (AcpiTableInfo[AcpiTableCount].AcpiTableSignature) {=0D
- case EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE:=0D
- FadtFound =3D TRUE;=0D
- break;=0D
- case EFI_ACPI_6_2_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE:=0D
- MadtFound =3D TRUE;=0D
- break;=0D
- case EFI_ACPI_6_2_GENERIC_TIMER_DESCRIPTION_TABLE_SIGNATURE:=0D
- GtdtFound =3D TRUE;=0D
- break;=0D
- case EFI_ACPI_6_2_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:=
=0D
- DsdtFound =3D TRUE;=0D
- break;=0D
- case EFI_ACPI_6_2_DEBUG_PORT_2_TABLE_SIGNATURE:=0D
- Dbg2Found =3D TRUE;=0D
- break;=0D
- case EFI_ACPI_6_2_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE:=0D
- SpcrFound =3D TRUE;=0D
- break;=0D
- default:=0D
+ for (Index =3D 0; Index < ACPI_TABLE_VERIFY_COUNT; Index++) {=0D
+ if (AcpiTableInfo[AcpiTableCount].AcpiTableSignature =3D=3D mAcpiVer=
ifyTables[Index].AcpiTableSignature) {=0D
+ mAcpiVerifyTables[Index].Presence |=3D ACPI_TABLE_PRESENT_INFO_LIS=
T;=0D
+ // Found this table, skip the rest.=0D
break;=0D
+ }=0D
}=0D
}=0D
=0D
- // We need at least the FADT, MADT, GTDT and the DSDT tables to boot=0D
- if (!FadtFound) {=0D
- DEBUG ((DEBUG_ERROR, "ERROR: FADT Table not found\n"));=0D
- Status =3D EFI_NOT_FOUND;=0D
- }=0D
+ // They also might be published already, so we can search from there=0D
+ if (FeaturePcdGet (PcdInstallAcpiSdtProtocol)) {=0D
+ AcpiSdt =3D NULL;=0D
+ Status =3D gBS->LocateProtocol (&gEfiAcpiSdtProtocolGuid, NULL, (VOID=
**)&AcpiSdt);=0D
=0D
- if (!MadtFound) {=0D
- DEBUG ((DEBUG_ERROR, "ERROR: MADT Table not found.\n"));=0D
- Status =3D EFI_NOT_FOUND;=0D
- }=0D
+ if (EFI_ERROR (Status) || (AcpiSdt =3D=3D NULL)) {=0D
+ DEBUG ((DEBUG_ERROR, "ERROR: Failed to locate ACPI SDT protocol (0x%=
p) - %r\n", AcpiSdt, Status));=0D
+ return Status;=0D
+ }=0D
=0D
- if (!GtdtFound) {=0D
- DEBUG ((DEBUG_ERROR, "ERROR: GTDT Table not found.\n"));=0D
- Status =3D EFI_NOT_FOUND;=0D
- }=0D
+ for (Index =3D 0; Index < ACPI_TABLE_VERIFY_COUNT; Index++) {=0D
+ Handle =3D 0;=0D
+ InstalledTableIndex =3D 0;=0D
+ do {=0D
+ Status =3D AcpiSdt->GetAcpiTable (InstalledTableIndex, (EFI_ACPI_S=
DT_HEADER **)&DescHeader, &Version, &Handle);=0D
+ if (EFI_ERROR (Status)) {=0D
+ break;=0D
+ }=0D
=0D
- if (!DsdtFound) {=0D
- DEBUG ((DEBUG_ERROR, "ERROR: DSDT Table not found.\n"));=0D
- Status =3D EFI_NOT_FOUND;=0D
- }=0D
+ InstalledTableIndex++;=0D
+ } while (DescHeader->Signature !=3D mAcpiVerifyTables[Index].AcpiTab=
leSignature);=0D
=0D
- if (!Dbg2Found) {=0D
- DEBUG ((DEBUG_WARN, "WARNING: DBG2 Table not found.\n"));=0D
+ if (!EFI_ERROR (Status)) {=0D
+ mAcpiVerifyTables[Index].Presence |=3D ACPI_TABLE_PRESENT_INSTALLE=
D;=0D
+ }=0D
+ }=0D
}=0D
=0D
- if (!SpcrFound) {=0D
- DEBUG ((DEBUG_WARN, "WARNING: SPCR Table not found.\n"));=0D
+ for (Index =3D 0; Index < ACPI_TABLE_VERIFY_COUNT; Index++) {=0D
+ if (mAcpiVerifyTables[Index].Presence =3D=3D 0) {=0D
+ if (mAcpiVerifyTables[Index].IsMandatory) {=0D
+ DEBUG ((DEBUG_ERROR, "ERROR: %a Table not found.\n", mAcpiVerifyTa=
bles[Index].AcpiTableName));=0D
+ Status =3D EFI_NOT_FOUND;=0D
+ } else {=0D
+ DEBUG ((DEBUG_WARN, "WARNING: %a Table not found.\n", mAcpiVerifyT=
ables[Index].AcpiTableName));=0D
+ }=0D
+ } else if (mAcpiVerifyTables[Index].Presence =3D=3D=0D
+ (ACPI_TABLE_PRESENT_INFO_LIST | ACPI_TABLE_PRESENT_INSTALLE=
D))=0D
+ {=0D
+ DEBUG ((DEBUG_ERROR, "ERROR: %a Table found while already published.=
\n", mAcpiVerifyTables[Index].AcpiTableName));=0D
+ Status =3D EFI_ALREADY_STARTED;=0D
+ }=0D
}=0D
=0D
return Status;=0D
@@ -489,8 +539,9 @@ VerifyMandatoryTablesArePresent (
@param [in] CfgMgrProtocol Pointer to the Configuration Manager=0D
Protocol Interface.=0D
=0D
- @retval EFI_SUCCESS Success.=0D
- @retval EFI_NOT_FOUND If a mandatory table or a generator is not found.=
=0D
+ @retval EFI_SUCCESS Success.=0D
+ @retval EFI_NOT_FOUND If a mandatory table or a generator is not=
found.=0D
+ @retval EFI_ALREADY_STARTED If mandatory table found in AcpiTableInfo =
is already installed.=0D
**/=0D
STATIC=0D
EFI_STATUS=0D
@@ -562,7 +613,7 @@ ProcessAcpiTables (
if (EFI_ERROR (Status)) {=0D
DEBUG ((=0D
DEBUG_ERROR,=0D
- "ERROR: Failed to find mandatory ACPI Table(s)."=0D
+ "ERROR: Failed to verify mandatory ACPI Table(s) presence."=0D
" Status =3D %r\n",=0D
Status=0D
));=0D
@@ -570,29 +621,32 @@ ProcessAcpiTables (
}=0D
=0D
// Add the FADT Table first.=0D
- for (Idx =3D 0; Idx < AcpiTableCount; Idx++) {=0D
- if (CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdFadt) =3D=3D=0D
- AcpiTableInfo[Idx].TableGeneratorId)=0D
- {=0D
- Status =3D BuildAndInstallAcpiTable (=0D
- TableFactoryProtocol,=0D
- CfgMgrProtocol,=0D
- AcpiTableProtocol,=0D
- &AcpiTableInfo[Idx]=0D
- );=0D
- if (EFI_ERROR (Status)) {=0D
- DEBUG ((=0D
- DEBUG_ERROR,=0D
- "ERROR: Failed to find build and install ACPI FADT Table." \=0D
- " Status =3D %r\n",=0D
- Status=0D
- ));=0D
- return Status;=0D
- }=0D
+ if ((mAcpiVerifyTables[ACPI_TABLE_VERIFY_FADT].Presence & ACPI_TABLE_PRE=
SENT_INSTALLED) =3D=3D 0) {=0D
+ // FADT is not yet installed=0D
+ for (Idx =3D 0; Idx < AcpiTableCount; Idx++) {=0D
+ if (CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdFadt) =3D=3D=0D
+ AcpiTableInfo[Idx].TableGeneratorId)=0D
+ {=0D
+ Status =3D BuildAndInstallAcpiTable (=0D
+ TableFactoryProtocol,=0D
+ CfgMgrProtocol,=0D
+ AcpiTableProtocol,=0D
+ &AcpiTableInfo[Idx]=0D
+ );=0D
+ if (EFI_ERROR (Status)) {=0D
+ DEBUG ((=0D
+ DEBUG_ERROR,=0D
+ "ERROR: Failed to find build and install ACPI FADT Table." \=0D
+ " Status =3D %r\n",=0D
+ Status=0D
+ ));=0D
+ return Status;=0D
+ }=0D
=0D
- break;=0D
- }=0D
- } // for=0D
+ break;=0D
+ }=0D
+ } // for=0D
+ }=0D
=0D
// Add remaining ACPI Tables=0D
for (Idx =3D 0; Idx < AcpiTableCount; Idx++) {=0D
diff --git a/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableMa=
nagerDxe.inf b/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTable=
ManagerDxe.inf
index 028c3d413cf8..ad8b3d037c16 100644
--- a/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableManagerDx=
e.inf
+++ b/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableManagerDx=
e.inf
@@ -34,8 +34,12 @@ [LibraryClasses]
UefiBootServicesTableLib=0D
UefiDriverEntryPoint=0D
=0D
+[FeaturePcd]=0D
+ gEfiMdeModulePkgTokenSpaceGuid.PcdInstallAcpiSdtProtocol ## CONSUMES=0D
+=0D
[Protocols]=0D
gEfiAcpiTableProtocolGuid # PROTOCOL ALWAYS_CONSUMED=
=0D
+ gEfiAcpiSdtProtocolGuid # PROTOCOL ALWAYS_CONSUMED=
=0D
=0D
gEdkiiConfigurationManagerProtocolGuid # PROTOCOL ALWAYS_CONSUMED=
=0D
gEdkiiDynamicTableFactoryProtocolGuid # PROTOCOL ALWAYS_CONSUMED=
=0D
--=20
2.37.1.windows.1

Join devel@edk2.groups.io to automatically receive all group messages.