/** @file | |
Dynamic Table Manager Dxe | |
Copyright (c) 2017 - 2019, ARM Limited. All rights reserved. | |
SPDX-License-Identifier: BSD-2-Clause-Patent | |
**/ | |
#include <Library/DebugLib.h> | |
#include <Library/PcdLib.h> | |
#include <Library/UefiBootServicesTableLib.h> | |
#include <Protocol/AcpiSystemDescriptionTable.h> | |
#include <Protocol/AcpiTable.h> | |
// Module specific include files. | |
#include <AcpiTableGenerator.h> | |
#include <ConfigurationManagerObject.h> | |
#include <ConfigurationManagerHelper.h> | |
#include <DeviceTreeTableGenerator.h> | |
#include <Library/TableHelperLib.h> | |
#include <Protocol/ConfigurationManagerProtocol.h> | |
#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. | |
*/ | |
GET_OBJECT_LIST ( | |
EObjNameSpaceStandard, | |
EStdObjAcpiTableList, | |
CM_STD_OBJ_ACPI_TABLE_INFO | |
) | |
/** A helper function to build and install a single ACPI table. | |
This is a helper function that invokes the Table generator interface | |
for building an ACPI table. It uses the AcpiTableProtocol to install the | |
table, then frees the resources allocated for generating it. | |
@param [in] TableFactoryProtocol Pointer to the Table Factory Protocol | |
interface. | |
@param [in] CfgMgrProtocol Pointer to the Configuration Manager | |
Protocol Interface. | |
@param [in] Generator Pointer to the AcpiTable generator. | |
@param [in] AcpiTableProtocol Pointer to the AcpiTable protocol. | |
@param [in] AcpiTableInfo Pointer to the ACPI table Info. | |
@retval EFI_SUCCESS Success. | |
@retval EFI_INVALID_PARAMETER A parameter is invalid. | |
@retval EFI_NOT_FOUND Required object is not found. | |
@retval EFI_BAD_BUFFER_SIZE Size returned by the Configuration Manager | |
is less than the Object size for the | |
requested object. | |
**/ | |
STATIC | |
EFI_STATUS | |
EFIAPI | |
BuildAndInstallSingleAcpiTable ( | |
IN CONST EDKII_DYNAMIC_TABLE_FACTORY_PROTOCOL *CONST TableFactoryProtocol, | |
IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, | |
IN CONST ACPI_TABLE_GENERATOR *CONST Generator, | |
IN EFI_ACPI_TABLE_PROTOCOL *AcpiTableProtocol, | |
IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo | |
) | |
{ | |
EFI_STATUS Status; | |
EFI_STATUS Status1; | |
EFI_ACPI_DESCRIPTION_HEADER *AcpiTable; | |
UINTN TableHandle; | |
AcpiTable = NULL; | |
Status = Generator->BuildAcpiTable ( | |
Generator, | |
AcpiTableInfo, | |
CfgMgrProtocol, | |
&AcpiTable | |
); | |
if (EFI_ERROR (Status)) { | |
DEBUG (( | |
DEBUG_ERROR, | |
"ERROR: Failed to Build Table." \ | |
" TableGeneratorId = 0x%x. Status = %r\n", | |
AcpiTableInfo->TableGeneratorId, | |
Status | |
)); | |
// Free any allocated resources. | |
goto exit_handler; | |
} | |
if (AcpiTable == NULL) { | |
Status = EFI_NOT_FOUND; | |
goto exit_handler; | |
} | |
// Dump ACPI Table Header | |
DUMP_ACPI_TABLE_HEADER (AcpiTable); | |
// Install ACPI table | |
Status = AcpiTableProtocol->InstallAcpiTable ( | |
AcpiTableProtocol, | |
AcpiTable, | |
AcpiTable->Length, | |
&TableHandle | |
); | |
if (EFI_ERROR (Status)) { | |
DEBUG (( | |
DEBUG_ERROR, | |
"ERROR: Failed to Install ACPI Table. Status = %r\n", | |
Status | |
)); | |
// Free any allocated resources. | |
goto exit_handler; | |
} | |
DEBUG (( | |
DEBUG_INFO, | |
"INFO: ACPI Table installed. Status = %r\n", | |
Status | |
)); | |
exit_handler: | |
// Free any resources allocated for generating the tables. | |
if (Generator->FreeTableResources != NULL) { | |
Status1 = Generator->FreeTableResources ( | |
Generator, | |
AcpiTableInfo, | |
CfgMgrProtocol, | |
&AcpiTable | |
); | |
if (EFI_ERROR (Status1)) { | |
DEBUG (( | |
DEBUG_ERROR, | |
"ERROR: Failed to Free Table Resources." \ | |
"TableGeneratorId = 0x%x. Status = %r\n", | |
AcpiTableInfo->TableGeneratorId, | |
Status1 | |
)); | |
} | |
// Return the first error status in case of failure | |
if (!EFI_ERROR (Status)) { | |
Status = Status1; | |
} | |
} | |
return Status; | |
} | |
/** A helper function to build and install multiple ACPI tables. | |
This is a helper function that invokes the Table generator interface | |
for building an ACPI table. It uses the AcpiTableProtocol to install the | |
table, then frees the resources allocated for generating it. | |
@param [in] TableFactoryProtocol Pointer to the Table Factory Protocol | |
interface. | |
@param [in] CfgMgrProtocol Pointer to the Configuration Manager | |
Protocol Interface. | |
@param [in] Generator Pointer to the AcpiTable generator. | |
@param [in] AcpiTableProtocol Pointer to the AcpiTable protocol. | |
@param [in] AcpiTableInfo Pointer to the ACPI table Info. | |
@retval EFI_SUCCESS Success. | |
@retval EFI_INVALID_PARAMETER A parameter is invalid. | |
@retval EFI_NOT_FOUND Required object is not found. | |
@retval EFI_BAD_BUFFER_SIZE Size returned by the Configuration Manager | |
is less than the Object size for the | |
requested object. | |
**/ | |
STATIC | |
EFI_STATUS | |
EFIAPI | |
BuildAndInstallMultipleAcpiTable ( | |
IN CONST EDKII_DYNAMIC_TABLE_FACTORY_PROTOCOL *CONST TableFactoryProtocol, | |
IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, | |
IN CONST ACPI_TABLE_GENERATOR *CONST Generator, | |
IN EFI_ACPI_TABLE_PROTOCOL *AcpiTableProtocol, | |
IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo | |
) | |
{ | |
EFI_STATUS Status; | |
EFI_STATUS Status1; | |
EFI_ACPI_DESCRIPTION_HEADER **AcpiTable; | |
UINTN TableCount; | |
UINTN TableHandle; | |
UINTN Index; | |
AcpiTable = NULL; | |
TableCount = 0; | |
Status = Generator->BuildAcpiTableEx ( | |
Generator, | |
AcpiTableInfo, | |
CfgMgrProtocol, | |
&AcpiTable, | |
&TableCount | |
); | |
if (EFI_ERROR (Status)) { | |
DEBUG (( | |
DEBUG_ERROR, | |
"ERROR: Failed to Build Table." \ | |
" TableGeneratorId = 0x%x. Status = %r\n", | |
AcpiTableInfo->TableGeneratorId, | |
Status | |
)); | |
// Free any allocated resources. | |
goto exit_handler; | |
} | |
if ((AcpiTable == NULL) || (TableCount == 0)) { | |
Status = EFI_NOT_FOUND; | |
goto exit_handler; | |
} | |
for (Index = 0; Index < TableCount; Index++) { | |
// Dump ACPI Table Header | |
DUMP_ACPI_TABLE_HEADER (AcpiTable[Index]); | |
// Install ACPI table | |
Status = AcpiTableProtocol->InstallAcpiTable ( | |
AcpiTableProtocol, | |
AcpiTable[Index], | |
AcpiTable[Index]->Length, | |
&TableHandle | |
); | |
if (EFI_ERROR (Status)) { | |
DEBUG (( | |
DEBUG_ERROR, | |
"ERROR: Failed to Install ACPI Table. Status = %r\n", | |
Status | |
)); | |
// Free any allocated resources. | |
goto exit_handler; | |
} | |
DEBUG (( | |
DEBUG_INFO, | |
"INFO: ACPI Table installed. Status = %r\n", | |
Status | |
)); | |
} | |
exit_handler: | |
// Free any resources allocated for generating the tables. | |
if (Generator->FreeTableResourcesEx != NULL) { | |
Status1 = Generator->FreeTableResourcesEx ( | |
Generator, | |
AcpiTableInfo, | |
CfgMgrProtocol, | |
&AcpiTable, | |
TableCount | |
); | |
if (EFI_ERROR (Status1)) { | |
DEBUG (( | |
DEBUG_ERROR, | |
"ERROR: Failed to Free Table Resources." \ | |
"TableGeneratorId = 0x%x. Status = %r\n", | |
AcpiTableInfo->TableGeneratorId, | |
Status1 | |
)); | |
} | |
// Return the first error status in case of failure | |
if (!EFI_ERROR (Status)) { | |
Status = Status1; | |
} | |
} | |
return Status; | |
} | |
/** A helper function to invoke a Table generator | |
This is a helper function that invokes the Table generator interface | |
for building an ACPI table. It uses the AcpiTableProtocol to install the | |
table, then frees the resources allocated for generating it. | |
@param [in] TableFactoryProtocol Pointer to the Table Factory Protocol | |
interface. | |
@param [in] CfgMgrProtocol Pointer to the Configuration Manager | |
Protocol Interface. | |
@param [in] AcpiTableProtocol Pointer to the AcpiTable protocol. | |
@param [in] AcpiTableInfo Pointer to the ACPI table Info. | |
@retval EFI_SUCCESS Success. | |
@retval EFI_INVALID_PARAMETER A parameter is invalid. | |
@retval EFI_NOT_FOUND Required object is not found. | |
@retval EFI_BAD_BUFFER_SIZE Size returned by the Configuration Manager | |
is less than the Object size for the | |
requested object. | |
**/ | |
STATIC | |
EFI_STATUS | |
EFIAPI | |
BuildAndInstallAcpiTable ( | |
IN CONST EDKII_DYNAMIC_TABLE_FACTORY_PROTOCOL *CONST TableFactoryProtocol, | |
IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, | |
IN EFI_ACPI_TABLE_PROTOCOL *AcpiTableProtocol, | |
IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo | |
) | |
{ | |
EFI_STATUS Status; | |
CONST ACPI_TABLE_GENERATOR *Generator; | |
ASSERT (TableFactoryProtocol != NULL); | |
ASSERT (CfgMgrProtocol != NULL); | |
ASSERT (AcpiTableProtocol != NULL); | |
ASSERT (AcpiTableInfo != NULL); | |
DEBUG (( | |
DEBUG_INFO, | |
"INFO: EStdObjAcpiTableList: Address = 0x%p," \ | |
" TableGeneratorId = 0x%x\n", | |
AcpiTableInfo, | |
AcpiTableInfo->TableGeneratorId | |
)); | |
Generator = NULL; | |
Status = TableFactoryProtocol->GetAcpiTableGenerator ( | |
TableFactoryProtocol, | |
AcpiTableInfo->TableGeneratorId, | |
&Generator | |
); | |
if (EFI_ERROR (Status)) { | |
DEBUG (( | |
DEBUG_ERROR, | |
"ERROR: Table Generator not found." \ | |
" TableGeneratorId = 0x%x. Status = %r\n", | |
AcpiTableInfo->TableGeneratorId, | |
Status | |
)); | |
return Status; | |
} | |
if (Generator == NULL) { | |
return EFI_NOT_FOUND; | |
} | |
DEBUG (( | |
DEBUG_INFO, | |
"INFO: Generator found : %s\n", | |
Generator->Description | |
)); | |
if (Generator->BuildAcpiTableEx != NULL) { | |
Status = BuildAndInstallMultipleAcpiTable ( | |
TableFactoryProtocol, | |
CfgMgrProtocol, | |
Generator, | |
AcpiTableProtocol, | |
AcpiTableInfo | |
); | |
if (EFI_ERROR (Status)) { | |
DEBUG (( | |
DEBUG_ERROR, | |
"ERROR: Failed to find build and install ACPI Table." \ | |
" Status = %r\n", | |
Status | |
)); | |
} | |
} else if (Generator->BuildAcpiTable != NULL) { | |
Status = BuildAndInstallSingleAcpiTable ( | |
TableFactoryProtocol, | |
CfgMgrProtocol, | |
Generator, | |
AcpiTableProtocol, | |
AcpiTableInfo | |
); | |
if (EFI_ERROR (Status)) { | |
DEBUG (( | |
DEBUG_ERROR, | |
"ERROR: Failed to find build and install ACPI Table." \ | |
" Status = %r\n", | |
Status | |
)); | |
} | |
} else { | |
Status = EFI_INVALID_PARAMETER; | |
DEBUG (( | |
DEBUG_ERROR, | |
"ERROR: Table Generator does not implement the" \ | |
" ACPI_TABLE_GENERATOR_BUILD_TABLE interface." \ | |
" TableGeneratorId = 0x%x. Status = %r\n", | |
AcpiTableInfo->TableGeneratorId, | |
Status | |
)); | |
} | |
return Status; | |
} | |
/** The function checks if the Configuration Manager has provided the | |
mandatory ACPI tables for installation. | |
@param [in] AcpiTableInfo Pointer to the ACPI Table Info list. | |
@param [in] AcpiTableCount Count of ACPI Table Info. | |
@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 | |
EFIAPI | |
VerifyMandatoryTablesArePresent ( | |
IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo, | |
IN UINT32 AcpiTableCount | |
) | |
{ | |
EFI_STATUS Status; | |
UINTN Handle; | |
UINTN Index; | |
UINTN InstalledTableIndex; | |
EFI_ACPI_DESCRIPTION_HEADER *DescHeader; | |
EFI_ACPI_TABLE_VERSION Version; | |
EFI_ACPI_SDT_PROTOCOL *AcpiSdt; | |
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) { | |
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; | |
} | |
} | |
} | |
// 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; | |
} | |
} | |
} | |
// 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; | |
} | |
/** Generate and install ACPI tables. | |
The function gathers the information necessary for installing the | |
ACPI tables from the Configuration Manager, invokes the generators | |
and installs them (via BuildAndInstallAcpiTable). | |
@param [in] TableFactoryProtocol Pointer to the Table Factory Protocol | |
interface. | |
@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_ALREADY_STARTED If mandatory table found in AcpiTableInfo is already installed. | |
**/ | |
STATIC | |
EFI_STATUS | |
EFIAPI | |
ProcessAcpiTables ( | |
IN CONST EDKII_DYNAMIC_TABLE_FACTORY_PROTOCOL *CONST TableFactoryProtocol, | |
IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol | |
) | |
{ | |
EFI_STATUS Status; | |
EFI_ACPI_TABLE_PROTOCOL *AcpiTableProtocol; | |
CM_STD_OBJ_ACPI_TABLE_INFO *AcpiTableInfo; | |
UINT32 AcpiTableCount; | |
UINT32 Idx; | |
ASSERT (TableFactoryProtocol != NULL); | |
ASSERT (CfgMgrProtocol != NULL); | |
// Find the AcpiTable protocol | |
Status = gBS->LocateProtocol ( | |
&gEfiAcpiTableProtocolGuid, | |
NULL, | |
(VOID **)&AcpiTableProtocol | |
); | |
if (EFI_ERROR (Status)) { | |
DEBUG (( | |
DEBUG_ERROR, | |
"ERROR: Failed to find AcpiTable protocol. Status = %r\n", | |
Status | |
)); | |
return Status; | |
} | |
Status = GetEStdObjAcpiTableList ( | |
CfgMgrProtocol, | |
CM_NULL_TOKEN, | |
&AcpiTableInfo, | |
&AcpiTableCount | |
); | |
if (EFI_ERROR (Status)) { | |
DEBUG (( | |
DEBUG_ERROR, | |
"ERROR: Failed to get ACPI Table List. Status = %r\n", | |
Status | |
)); | |
return Status; | |
} | |
if (0 == AcpiTableCount) { | |
DEBUG (( | |
DEBUG_ERROR, | |
"ERROR: EStdObjAcpiTableList: AcpiTableCount = %d\n", | |
AcpiTableCount | |
)); | |
return EFI_NOT_FOUND; | |
} | |
DEBUG (( | |
DEBUG_INFO, | |
"INFO: EStdObjAcpiTableList: AcpiTableCount = %d\n", | |
AcpiTableCount | |
)); | |
// Check if mandatory ACPI tables are present. | |
Status = VerifyMandatoryTablesArePresent ( | |
AcpiTableInfo, | |
AcpiTableCount | |
); | |
if (EFI_ERROR (Status)) { | |
DEBUG (( | |
DEBUG_ERROR, | |
"ERROR: Failed to verify mandatory ACPI Table(s) presence." | |
" Status = %r\n", | |
Status | |
)); | |
return Status; | |
} | |
// Add the FADT Table first. | |
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 | |
} | |
// Add remaining ACPI Tables | |
for (Idx = 0; Idx < AcpiTableCount; Idx++) { | |
DEBUG (( | |
DEBUG_INFO, | |
"INFO: AcpiTableInfo[%d].TableGeneratorId = 0x%x\n", | |
Idx, | |
AcpiTableInfo[Idx].TableGeneratorId | |
)); | |
// Skip FADT Table since we have already added | |
if (CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdFadt) == | |
AcpiTableInfo[Idx].TableGeneratorId) | |
{ | |
continue; | |
} | |
// Skip the Reserved table Generator ID for standard generators | |
if ((IS_GENERATOR_NAMESPACE_STD (AcpiTableInfo[Idx].TableGeneratorId)) && | |
((CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdReserved) >= | |
AcpiTableInfo[Idx].TableGeneratorId) || | |
(CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdMax) <= | |
AcpiTableInfo[Idx].TableGeneratorId))) | |
{ | |
DEBUG (( | |
DEBUG_WARN, | |
"WARNING: Invalid ACPI Generator table ID = 0x%x, Skipping...\n", | |
AcpiTableInfo[Idx].TableGeneratorId | |
)); | |
continue; | |
} | |
Status = BuildAndInstallAcpiTable ( | |
TableFactoryProtocol, | |
CfgMgrProtocol, | |
AcpiTableProtocol, | |
&AcpiTableInfo[Idx] | |
); | |
if (EFI_ERROR (Status)) { | |
DEBUG (( | |
DEBUG_ERROR, | |
"ERROR: Failed to find, build, and install ACPI Table." \ | |
" Status = %r\n", | |
Status | |
)); | |
return Status; | |
} | |
} // for | |
return Status; | |
} | |
/** Entrypoint of Dynamic Table Manager Dxe. | |
The Dynamic Table Manager uses the Configuration Manager Protocol | |
to get the list of ACPI and SMBIOS tables to install. For each table | |
in the list it requests the corresponding ACPI/SMBIOS table factory for | |
a generator capable of building the ACPI/SMBIOS table. | |
If a suitable table generator is found, it invokes the generator interface | |
to build the table. The Dynamic Table Manager then installs the | |
table and invokes another generator interface to free any resources | |
allocated for building the table. | |
@param ImageHandle | |
@param SystemTable | |
@retval EFI_SUCCESS Success. | |
@retval EFI_OUT_OF_RESOURCES Memory allocation failed. | |
@retval EFI_NOT_FOUND Required interface/object was not found. | |
@retval EFI_INVALID_PARAMETER Some parameter is incorrect/invalid. | |
**/ | |
EFI_STATUS | |
EFIAPI | |
DynamicTableManagerDxeInitialize ( | |
IN EFI_HANDLE ImageHandle, | |
IN EFI_SYSTEM_TABLE *SystemTable | |
) | |
{ | |
EFI_STATUS Status; | |
EDKII_CONFIGURATION_MANAGER_PROTOCOL *CfgMgrProtocol; | |
CM_STD_OBJ_CONFIGURATION_MANAGER_INFO *CfgMfrInfo; | |
EDKII_DYNAMIC_TABLE_FACTORY_PROTOCOL *TableFactoryProtocol; | |
// Locate the Dynamic Table Factory | |
Status = gBS->LocateProtocol ( | |
&gEdkiiDynamicTableFactoryProtocolGuid, | |
NULL, | |
(VOID **)&TableFactoryProtocol | |
); | |
if (EFI_ERROR (Status)) { | |
DEBUG (( | |
DEBUG_ERROR, | |
"ERROR: Failed to find Dynamic Table Factory protocol." \ | |
" Status = %r\n", | |
Status | |
)); | |
return Status; | |
} | |
// Locate the Configuration Manager for the Platform | |
Status = gBS->LocateProtocol ( | |
&gEdkiiConfigurationManagerProtocolGuid, | |
NULL, | |
(VOID **)&CfgMgrProtocol | |
); | |
if (EFI_ERROR (Status)) { | |
DEBUG (( | |
DEBUG_ERROR, | |
"ERROR: Failed to find Configuration Manager protocol. Status = %r\n", | |
Status | |
)); | |
return Status; | |
} | |
Status = GetCgfMgrInfo (CfgMgrProtocol, &CfgMfrInfo); | |
if (EFI_ERROR (Status)) { | |
DEBUG (( | |
DEBUG_ERROR, | |
"ERROR: Failed to get Configuration Manager info. Status = %r\n", | |
Status | |
)); | |
return Status; | |
} | |
DEBUG (( | |
DEBUG_INFO, | |
"INFO: Configuration Manager Version = 0x%x, OemID = %c%c%c%c%c%c\n", | |
CfgMfrInfo->Revision, | |
CfgMfrInfo->OemId[0], | |
CfgMfrInfo->OemId[1], | |
CfgMfrInfo->OemId[2], | |
CfgMfrInfo->OemId[3], | |
CfgMfrInfo->OemId[4], | |
CfgMfrInfo->OemId[5] | |
)); | |
Status = ProcessAcpiTables (TableFactoryProtocol, CfgMgrProtocol); | |
if (EFI_ERROR (Status)) { | |
DEBUG (( | |
DEBUG_ERROR, | |
"ERROR: ACPI Table processing failure. Status = %r\n", | |
Status | |
)); | |
} | |
return Status; | |
} |