mirror of https://github.com/acidanthera/audk.git
799 lines
26 KiB
C
799 lines
26 KiB
C
/** @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;
|
|
}
|