--- /dev/null
+/** @file\r
+ Dynamic Table Manager Dxe\r
+\r
+ Copyright (c) 2017 - 2019, ARM Limited. All rights reserved.\r
+\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <Library/DebugLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Protocol/AcpiTable.h>\r
+\r
+// Module specific include files.\r
+#include <AcpiTableGenerator.h>\r
+#include <ConfigurationManagerObject.h>\r
+#include <ConfigurationManagerHelper.h>\r
+#include <DeviceTreeTableGenerator.h>\r
+#include <Library/TableHelperLib.h>\r
+#include <Protocol/ConfigurationManagerProtocol.h>\r
+#include <Protocol/DynamicTableFactoryProtocol.h>\r
+#include <SmbiosTableGenerator.h>\r
+\r
+/** This macro expands to a function that retrieves the ACPI Table\r
+ List from the Configuration Manager.\r
+*/\r
+GET_OBJECT_LIST (\r
+ EObjNameSpaceStandard,\r
+ EStdObjAcpiTableList,\r
+ CM_STD_OBJ_ACPI_TABLE_INFO\r
+ )\r
+\r
+/** A helper function to build and install a single ACPI table.\r
+\r
+ This is a helper function that invokes the Table generator interface\r
+ for building an ACPI table. It uses the AcpiTableProtocol to install the\r
+ table, then frees the resources allocated for generating it.\r
+\r
+ @param [in] TableFactoryProtocol Pointer to the Table Factory Protocol\r
+ interface.\r
+ @param [in] CfgMgrProtocol Pointer to the Configuration Manager\r
+ Protocol Interface.\r
+ @param [in] Generator Pointer to the AcpiTable generator.\r
+ @param [in] AcpiTableProtocol Pointer to the AcpiTable protocol.\r
+ @param [in] AcpiTableInfo Pointer to the ACPI table Info.\r
+\r
+ @retval EFI_SUCCESS Success.\r
+ @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
+ @retval EFI_NOT_FOUND Required object is not found.\r
+ @retval EFI_BAD_BUFFER_SIZE Size returned by the Configuration Manager\r
+ is less than the Object size for the\r
+ requested object.\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+BuildAndInstallSingleAcpiTable (\r
+ IN CONST EDKII_DYNAMIC_TABLE_FACTORY_PROTOCOL * CONST TableFactoryProtocol,\r
+ IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol,\r
+ IN CONST ACPI_TABLE_GENERATOR * CONST Generator,\r
+ IN EFI_ACPI_TABLE_PROTOCOL * AcpiTableProtocol,\r
+ IN CONST CM_STD_OBJ_ACPI_TABLE_INFO * CONST AcpiTableInfo\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_STATUS Status1;\r
+ EFI_ACPI_DESCRIPTION_HEADER * AcpiTable;\r
+ UINTN TableHandle;\r
+\r
+ AcpiTable = NULL;\r
+ Status = Generator->BuildAcpiTable (\r
+ Generator,\r
+ AcpiTableInfo,\r
+ CfgMgrProtocol,\r
+ &AcpiTable\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+ "ERROR: Failed to Build Table." \\r
+ " TableGeneratorId = 0x%x. Status = %r\n",\r
+ AcpiTableInfo->TableGeneratorId,\r
+ Status\r
+ ));\r
+ // Free any allocated resources.\r
+ goto exit_handler;\r
+ }\r
+\r
+ if (AcpiTable == NULL) {\r
+ Status = EFI_NOT_FOUND;\r
+ goto exit_handler;\r
+ }\r
+\r
+ // Dump ACPI Table Header\r
+ DUMP_ACPI_TABLE_HEADER (AcpiTable);\r
+\r
+ // Install ACPI table\r
+ Status = AcpiTableProtocol->InstallAcpiTable (\r
+ AcpiTableProtocol,\r
+ AcpiTable,\r
+ AcpiTable->Length,\r
+ &TableHandle\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+ "ERROR: Failed to Install ACPI Table. Status = %r\n",\r
+ Status\r
+ ));\r
+ // Free any allocated resources.\r
+ goto exit_handler;\r
+ }\r
+\r
+ DEBUG ((\r
+ DEBUG_INFO,\r
+ "INFO: ACPI Table installed. Status = %r\n",\r
+ Status\r
+ ));\r
+\r
+exit_handler:\r
+ // Free any resources allocated for generating the tables.\r
+ if (Generator->FreeTableResources != NULL) {\r
+ Status1 = Generator->FreeTableResources (\r
+ Generator,\r
+ AcpiTableInfo,\r
+ CfgMgrProtocol,\r
+ &AcpiTable\r
+ );\r
+ if (EFI_ERROR (Status1)) {\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+ "ERROR: Failed to Free Table Resources." \\r
+ "TableGeneratorId = 0x%x. Status = %r\n",\r
+ AcpiTableInfo->TableGeneratorId,\r
+ Status1\r
+ ));\r
+ }\r
+\r
+ // Return the first error status in case of failure\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = Status1;\r
+ }\r
+ }\r
+ return Status;\r
+}\r
+\r
+/** A helper function to build and install multiple ACPI tables.\r
+\r
+ This is a helper function that invokes the Table generator interface\r
+ for building an ACPI table. It uses the AcpiTableProtocol to install the\r
+ table, then frees the resources allocated for generating it.\r
+\r
+ @param [in] TableFactoryProtocol Pointer to the Table Factory Protocol\r
+ interface.\r
+ @param [in] CfgMgrProtocol Pointer to the Configuration Manager\r
+ Protocol Interface.\r
+ @param [in] Generator Pointer to the AcpiTable generator.\r
+ @param [in] AcpiTableProtocol Pointer to the AcpiTable protocol.\r
+ @param [in] AcpiTableInfo Pointer to the ACPI table Info.\r
+\r
+ @retval EFI_SUCCESS Success.\r
+ @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
+ @retval EFI_NOT_FOUND Required object is not found.\r
+ @retval EFI_BAD_BUFFER_SIZE Size returned by the Configuration Manager\r
+ is less than the Object size for the\r
+ requested object.\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+BuildAndInstallMultipleAcpiTable (\r
+ IN CONST EDKII_DYNAMIC_TABLE_FACTORY_PROTOCOL * CONST TableFactoryProtocol,\r
+ IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol,\r
+ IN CONST ACPI_TABLE_GENERATOR * CONST Generator,\r
+ IN EFI_ACPI_TABLE_PROTOCOL * AcpiTableProtocol,\r
+ IN CONST CM_STD_OBJ_ACPI_TABLE_INFO * CONST AcpiTableInfo\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_STATUS Status1;\r
+ EFI_ACPI_DESCRIPTION_HEADER ** AcpiTable;\r
+ UINTN TableCount;\r
+ UINTN TableHandle;\r
+ UINTN Index;\r
+\r
+ AcpiTable = NULL;\r
+ TableCount = 0;\r
+ Status = Generator->BuildAcpiTableEx (\r
+ Generator,\r
+ AcpiTableInfo,\r
+ CfgMgrProtocol,\r
+ &AcpiTable,\r
+ &TableCount\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+ "ERROR: Failed to Build Table." \\r
+ " TableGeneratorId = 0x%x. Status = %r\n",\r
+ AcpiTableInfo->TableGeneratorId,\r
+ Status\r
+ ));\r
+ // Free any allocated resources.\r
+ goto exit_handler;\r
+ }\r
+\r
+ if ((AcpiTable == NULL) || (TableCount == 0)) {\r
+ Status = EFI_NOT_FOUND;\r
+ goto exit_handler;\r
+ }\r
+\r
+ for (Index = 0; Index < TableCount; Index++) {\r
+ // Dump ACPI Table Header\r
+ DUMP_ACPI_TABLE_HEADER (AcpiTable[Index]);\r
+ // Install ACPI table\r
+ Status = AcpiTableProtocol->InstallAcpiTable (\r
+ AcpiTableProtocol,\r
+ AcpiTable[Index],\r
+ AcpiTable[Index]->Length,\r
+ &TableHandle\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+ "ERROR: Failed to Install ACPI Table. Status = %r\n",\r
+ Status\r
+ ));\r
+ // Free any allocated resources.\r
+ goto exit_handler;\r
+ }\r
+\r
+ DEBUG ((\r
+ DEBUG_INFO,\r
+ "INFO: ACPI Table installed. Status = %r\n",\r
+ Status\r
+ ));\r
+ }\r
+\r
+exit_handler:\r
+ // Free any resources allocated for generating the tables.\r
+ if (Generator->FreeTableResourcesEx != NULL) {\r
+ Status1 = Generator->FreeTableResourcesEx (\r
+ Generator,\r
+ AcpiTableInfo,\r
+ CfgMgrProtocol,\r
+ &AcpiTable,\r
+ TableCount\r
+ );\r
+ if (EFI_ERROR (Status1)) {\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+ "ERROR: Failed to Free Table Resources." \\r
+ "TableGeneratorId = 0x%x. Status = %r\n",\r
+ AcpiTableInfo->TableGeneratorId,\r
+ Status1\r
+ ));\r
+ }\r
+\r
+ // Return the first error status in case of failure\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = Status1;\r
+ }\r
+ }\r
+ return Status;\r
+}\r
+\r
+/** A helper function to invoke a Table generator\r
+\r
+ This is a helper function that invokes the Table generator interface\r
+ for building an ACPI table. It uses the AcpiTableProtocol to install the\r
+ table, then frees the resources allocated for generating it.\r
+\r
+ @param [in] TableFactoryProtocol Pointer to the Table Factory Protocol\r
+ interface.\r
+ @param [in] CfgMgrProtocol Pointer to the Configuration Manager\r
+ Protocol Interface.\r
+ @param [in] AcpiTableProtocol Pointer to the AcpiTable protocol.\r
+ @param [in] AcpiTableInfo Pointer to the ACPI table Info.\r
+\r
+ @retval EFI_SUCCESS Success.\r
+ @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
+ @retval EFI_NOT_FOUND Required object is not found.\r
+ @retval EFI_BAD_BUFFER_SIZE Size returned by the Configuration Manager\r
+ is less than the Object size for the\r
+ requested object.\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+BuildAndInstallAcpiTable (\r
+ IN CONST EDKII_DYNAMIC_TABLE_FACTORY_PROTOCOL * CONST TableFactoryProtocol,\r
+ IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol,\r
+ IN EFI_ACPI_TABLE_PROTOCOL * AcpiTableProtocol,\r
+ IN CONST CM_STD_OBJ_ACPI_TABLE_INFO * CONST AcpiTableInfo\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ CONST ACPI_TABLE_GENERATOR * Generator;\r
+\r
+ ASSERT (TableFactoryProtocol != NULL);\r
+ ASSERT (CfgMgrProtocol != NULL);\r
+ ASSERT (AcpiTableProtocol != NULL);\r
+ ASSERT (AcpiTableInfo != NULL);\r
+\r
+ DEBUG ((\r
+ DEBUG_INFO,\r
+ "INFO: EStdObjAcpiTableList: Address = 0x%p," \\r
+ " TableGeneratorId = 0x%x\n",\r
+ AcpiTableInfo,\r
+ AcpiTableInfo->TableGeneratorId\r
+ ));\r
+\r
+ Generator = NULL;\r
+ Status = TableFactoryProtocol->GetAcpiTableGenerator (\r
+ TableFactoryProtocol,\r
+ AcpiTableInfo->TableGeneratorId,\r
+ &Generator\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+ "ERROR: Table Generator not found." \\r
+ " TableGeneratorId = 0x%x. Status = %r\n",\r
+ AcpiTableInfo->TableGeneratorId,\r
+ Status\r
+ ));\r
+ return Status;\r
+ }\r
+\r
+ if (Generator == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ DEBUG ((\r
+ DEBUG_INFO,\r
+ "INFO: Generator found : %s\n",\r
+ Generator->Description\r
+ ));\r
+\r
+ if (Generator->BuildAcpiTableEx != NULL) {\r
+ Status = BuildAndInstallMultipleAcpiTable (\r
+ TableFactoryProtocol,\r
+ CfgMgrProtocol,\r
+ Generator,\r
+ AcpiTableProtocol,\r
+ AcpiTableInfo\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+ "ERROR: Failed to find build and install ACPI Table." \\r
+ " Status = %r\n",\r
+ Status\r
+ ));\r
+ }\r
+ } else if (Generator->BuildAcpiTable != NULL) {\r
+ Status = BuildAndInstallSingleAcpiTable (\r
+ TableFactoryProtocol,\r
+ CfgMgrProtocol,\r
+ Generator,\r
+ AcpiTableProtocol,\r
+ AcpiTableInfo\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+ "ERROR: Failed to find build and install ACPI Table." \\r
+ " Status = %r\n",\r
+ Status\r
+ ));\r
+ }\r
+ } else {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+ "ERROR: Table Generator does not implement the" \\r
+ " ACPI_TABLE_GENERATOR_BUILD_TABLE interface." \\r
+ " TableGeneratorId = 0x%x. Status = %r\n",\r
+ AcpiTableInfo->TableGeneratorId,\r
+ Status\r
+ ));\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/** The function checks if the Configuration Manager has provided the\r
+ mandatory ACPI tables for installation.\r
+\r
+ @param [in] AcpiTableInfo Pointer to the ACPI Table Info list.\r
+ @param [in] AcpiTableCount Count of ACPI Table Info.\r
+\r
+ @retval EFI_SUCCESS Success.\r
+ @retval EFI_NOT_FOUND If mandatory table is not found.\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+VerifyMandatoryTablesArePresent (\r
+ IN CONST CM_STD_OBJ_ACPI_TABLE_INFO * CONST AcpiTableInfo,\r
+ IN UINT32 AcpiTableCount\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ BOOLEAN FadtFound;\r
+ BOOLEAN MadtFound;\r
+ BOOLEAN GtdtFound;\r
+ BOOLEAN DsdtFound;\r
+ BOOLEAN Dbg2Found;\r
+ BOOLEAN SpcrFound;\r
+\r
+ Status = EFI_SUCCESS;\r
+ FadtFound = FALSE;\r
+ MadtFound = FALSE;\r
+ GtdtFound = FALSE;\r
+ DsdtFound = FALSE;\r
+ Dbg2Found = FALSE;\r
+ SpcrFound = FALSE;\r
+ ASSERT (AcpiTableInfo != NULL);\r
+\r
+ while (AcpiTableCount-- != 0) {\r
+ switch (AcpiTableInfo[AcpiTableCount].AcpiTableSignature) {\r
+ case EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE:\r
+ FadtFound = TRUE;\r
+ break;\r
+ case EFI_ACPI_6_2_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE:\r
+ MadtFound = TRUE;\r
+ break;\r
+ case EFI_ACPI_6_2_GENERIC_TIMER_DESCRIPTION_TABLE_SIGNATURE:\r
+ GtdtFound = TRUE;\r
+ break;\r
+ case EFI_ACPI_6_2_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:\r
+ DsdtFound = TRUE;\r
+ break;\r
+ case EFI_ACPI_6_2_DEBUG_PORT_2_TABLE_SIGNATURE:\r
+ Dbg2Found = TRUE;\r
+ break;\r
+ case EFI_ACPI_6_2_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE:\r
+ SpcrFound = TRUE;\r
+ break;\r
+ default:\r
+ break;\r
+ }\r
+ }\r
+\r
+ // We need at least the FADT, MADT, GTDT and the DSDT tables to boot\r
+ if (!FadtFound) {\r
+ DEBUG ((DEBUG_ERROR,"ERROR: FADT Table not found\n"));\r
+ Status = EFI_NOT_FOUND;\r
+ }\r
+ if (!MadtFound) {\r
+ DEBUG ((DEBUG_ERROR, "ERROR: MADT Table not found.\n"));\r
+ Status = EFI_NOT_FOUND;\r
+ }\r
+ if (!GtdtFound) {\r
+ DEBUG ((DEBUG_ERROR, "ERROR: GTDT Table not found.\n"));\r
+ Status = EFI_NOT_FOUND;\r
+ }\r
+ if (!DsdtFound) {\r
+ DEBUG ((DEBUG_ERROR, "ERROR: DSDT Table not found.\n"));\r
+ Status = EFI_NOT_FOUND;\r
+ }\r
+ if (!Dbg2Found) {\r
+ DEBUG ((DEBUG_WARN, "WARNING: DBG2 Table not found.\n"));\r
+ }\r
+ if (!SpcrFound) {\r
+ DEBUG ((DEBUG_WARN, "WARNING: SPCR Table not found.\n"));\r
+ }\r
+ return Status;\r
+}\r
+\r
+/** Generate and install ACPI tables.\r
+\r
+ The function gathers the information necessary for installing the\r
+ ACPI tables from the Configuration Manager, invokes the generators\r
+ and installs them (via BuildAndInstallAcpiTable).\r
+\r
+ @param [in] TableFactoryProtocol Pointer to the Table Factory Protocol\r
+ interface.\r
+ @param [in] CfgMgrProtocol Pointer to the Configuration Manager\r
+ Protocol Interface.\r
+\r
+ @retval EFI_SUCCESS Success.\r
+ @retval EFI_NOT_FOUND If a mandatory table or a generator is not found.\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+ProcessAcpiTables (\r
+ IN CONST EDKII_DYNAMIC_TABLE_FACTORY_PROTOCOL * CONST TableFactoryProtocol,\r
+ IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_ACPI_TABLE_PROTOCOL * AcpiTableProtocol;\r
+ CM_STD_OBJ_ACPI_TABLE_INFO * AcpiTableInfo;\r
+ UINT32 AcpiTableCount;\r
+ UINT32 Idx;\r
+\r
+ ASSERT (TableFactoryProtocol != NULL);\r
+ ASSERT (CfgMgrProtocol != NULL);\r
+\r
+ // Find the AcpiTable protocol\r
+ Status = gBS->LocateProtocol (\r
+ &gEfiAcpiTableProtocolGuid,\r
+ NULL,\r
+ (VOID**)&AcpiTableProtocol\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+ "ERROR: Failed to find AcpiTable protocol. Status = %r\n",\r
+ Status\r
+ ));\r
+ return Status;\r
+ }\r
+\r
+ Status = GetEStdObjAcpiTableList (\r
+ CfgMgrProtocol,\r
+ CM_NULL_TOKEN,\r
+ &AcpiTableInfo,\r
+ &AcpiTableCount\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+ "ERROR: Failed to get ACPI Table List. Status = %r\n",\r
+ Status\r
+ ));\r
+ return Status;\r
+ }\r
+\r
+ if (0 == AcpiTableCount) {\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+ "ERROR: EStdObjAcpiTableList: AcpiTableCount = %d\n",\r
+ AcpiTableCount\r
+ ));\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ DEBUG ((\r
+ DEBUG_INFO,\r
+ "INFO: EStdObjAcpiTableList: AcpiTableCount = %d\n",\r
+ AcpiTableCount\r
+ ));\r
+\r
+ // Check if mandatory ACPI tables are present.\r
+ Status = VerifyMandatoryTablesArePresent (\r
+ AcpiTableInfo,\r
+ AcpiTableCount\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+ "ERROR: Failed to find mandatory ACPI Table(s)."\r
+ " Status = %r\n",\r
+ Status\r
+ ));\r
+ return Status;\r
+ }\r
+\r
+ // Add the FADT Table first.\r
+ for (Idx = 0; Idx < AcpiTableCount; Idx++) {\r
+ if (CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdFadt) ==\r
+ AcpiTableInfo[Idx].TableGeneratorId) {\r
+ Status = BuildAndInstallAcpiTable (\r
+ TableFactoryProtocol,\r
+ CfgMgrProtocol,\r
+ AcpiTableProtocol,\r
+ &AcpiTableInfo[Idx]\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+ "ERROR: Failed to find build and install ACPI FADT Table." \\r
+ " Status = %r\n",\r
+ Status\r
+ ));\r
+ return Status;\r
+ }\r
+ break;\r
+ }\r
+ } // for\r
+\r
+ // Add remaining ACPI Tables\r
+ for (Idx = 0; Idx < AcpiTableCount; Idx++) {\r
+ DEBUG ((\r
+ DEBUG_INFO,\r
+ "INFO: AcpiTableInfo[%d].TableGeneratorId = 0x%x\n",\r
+ Idx,\r
+ AcpiTableInfo[Idx].TableGeneratorId\r
+ ));\r
+\r
+ // Skip FADT Table since we have already added\r
+ if (CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdFadt) ==\r
+ AcpiTableInfo[Idx].TableGeneratorId) {\r
+ continue;\r
+ }\r
+\r
+ // Skip the Reserved table Generator ID for standard generators\r
+ if ((IS_GENERATOR_NAMESPACE_STD (AcpiTableInfo[Idx].TableGeneratorId)) &&\r
+ ((CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdReserved) >=\r
+ AcpiTableInfo[Idx].TableGeneratorId) ||\r
+ (CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdMax) <=\r
+ AcpiTableInfo[Idx].TableGeneratorId))) {\r
+ DEBUG ((\r
+ DEBUG_WARN,\r
+ "WARNING: Invalid ACPI Generator table ID = 0x%x, Skipping...\n",\r
+ AcpiTableInfo[Idx].TableGeneratorId\r
+ ));\r
+ continue;\r
+ }\r
+\r
+ Status = BuildAndInstallAcpiTable (\r
+ TableFactoryProtocol,\r
+ CfgMgrProtocol,\r
+ AcpiTableProtocol,\r
+ &AcpiTableInfo[Idx]\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+ "ERROR: Failed to find, build, and install ACPI Table." \\r
+ " Status = %r\n",\r
+ Status\r
+ ));\r
+ return Status;\r
+ }\r
+ } // for\r
+\r
+ return Status;\r
+}\r
+\r
+/** Entrypoint of Dynamic Table Manager Dxe.\r
+\r
+ The Dynamic Table Manager uses the Configuration Manager Protocol\r
+ to get the list of ACPI and SMBIOS tables to install. For each table\r
+ in the list it requests the corresponding ACPI/SMBIOS table factory for\r
+ a generator capable of building the ACPI/SMBIOS table.\r
+ If a suitable table generator is found, it invokes the generator interface\r
+ to build the table. The Dynamic Table Manager then installs the\r
+ table and invokes another generator interface to free any resources\r
+ allocated for building the table.\r
+\r
+ @param ImageHandle\r
+ @param SystemTable\r
+\r
+ @retval EFI_SUCCESS Success.\r
+ @retval EFI_OUT_OF_RESOURCES Memory allocation failed.\r
+ @retval EFI_NOT_FOUND Required interface/object was not found.\r
+ @retval EFI_INVALID_PARAMETER Some parameter is incorrect/invalid.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DynamicTableManagerDxeInitialize (\r
+ IN CONST EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE * CONST SystemTable\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EDKII_CONFIGURATION_MANAGER_PROTOCOL * CfgMgrProtocol;\r
+ CM_STD_OBJ_CONFIGURATION_MANAGER_INFO * CfgMfrInfo;\r
+ EDKII_DYNAMIC_TABLE_FACTORY_PROTOCOL * TableFactoryProtocol;\r
+\r
+ // Locate the Dynamic Table Factory\r
+ Status = gBS->LocateProtocol (\r
+ &gEdkiiDynamicTableFactoryProtocolGuid,\r
+ NULL,\r
+ (VOID**)&TableFactoryProtocol\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+ "ERROR: Failed to find Dynamic Table Factory protocol." \\r
+ " Status = %r\n",\r
+ Status\r
+ ));\r
+ return Status;\r
+ }\r
+\r
+ // Locate the Configuration Manager for the Platform\r
+ Status = gBS->LocateProtocol (\r
+ &gEdkiiConfigurationManagerProtocolGuid,\r
+ NULL,\r
+ (VOID**)&CfgMgrProtocol\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+ "ERROR: Failed to find Configuration Manager protocol. Status = %r\n",\r
+ Status\r
+ ));\r
+ return Status;\r
+ }\r
+\r
+ Status = GetCgfMgrInfo (CfgMgrProtocol, &CfgMfrInfo);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+ "ERROR: Failed to get Configuration Manager info. Status = %r\n",\r
+ Status\r
+ ));\r
+ return Status;\r
+ }\r
+\r
+ DEBUG ((\r
+ DEBUG_INFO,\r
+ "INFO: Configuration Manager Version = 0x%x, OemID = %c%c%c%c%c%c\n",\r
+ CfgMfrInfo->Revision,\r
+ CfgMfrInfo->OemId[0],\r
+ CfgMfrInfo->OemId[1],\r
+ CfgMfrInfo->OemId[2],\r
+ CfgMfrInfo->OemId[3],\r
+ CfgMfrInfo->OemId[4],\r
+ CfgMfrInfo->OemId[5]\r
+ ));\r
+\r
+ Status = ProcessAcpiTables (TableFactoryProtocol, CfgMgrProtocol);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+ "ERROR: ACPI Table processing failure. Status = %r\n",\r
+ Status\r
+ ));\r
+ }\r
+ return Status;\r
+}\r