diff --git a/DynamicTablesPkg/Drivers/DynamicTableFactoryDxe/DynamicTableFactory.h b/DynamicTablesPkg/Drivers/DynamicTableFactoryDxe/DynamicTableFactory.h index b160dcf8add..d33d2168468 100644 --- a/DynamicTablesPkg/Drivers/DynamicTableFactoryDxe/DynamicTableFactory.h +++ b/DynamicTablesPkg/Drivers/DynamicTableFactoryDxe/DynamicTableFactory.h @@ -49,6 +49,13 @@ typedef struct DynamicTableFactoryInfo { CustomDtTableGeneratorList[FixedPcdGet16 ( PcdMaxCustomDTGenerators )]; + + /// An array for holding a map of SMBIOS handles and the CM Object + /// token used to build the SMBIOS record. + SMBIOS_HANDLE_MAP + SmbiosHandleMap[FixedPcdGet16 ( + PcdMaxSmbiosHandleMapEntries + )]; } EDKII_DYNAMIC_TABLE_FACTORY_INFO; /** Return a pointer to the ACPI table generator. diff --git a/DynamicTablesPkg/Drivers/DynamicTableFactoryDxe/DynamicTableFactoryDxe.c b/DynamicTablesPkg/Drivers/DynamicTableFactoryDxe/DynamicTableFactoryDxe.c index 6d6d3fa7467..87ea602f999 100644 --- a/DynamicTablesPkg/Drivers/DynamicTableFactoryDxe/DynamicTableFactoryDxe.c +++ b/DynamicTablesPkg/Drivers/DynamicTableFactoryDxe/DynamicTableFactoryDxe.c @@ -44,6 +44,9 @@ EDKII_DYNAMIC_TABLE_FACTORY_PROTOCOL DynamicTableFactoryProtocol = { GetDtTableGenerator, RegisterDtTableGenerator, DeregisterDtTableGenerator, + AddSmbiosHandle, + FindSmbiosHandle, + FindSmbiosHandleEx, &TableFactoryInfo }; @@ -65,6 +68,12 @@ DynamicTableFactoryDxeInitialize ( ) { EFI_STATUS Status; + UINTN Idx; + + for (Idx = 0; Idx < FixedPcdGet16(PcdMaxSmbiosHandleMapEntries); Idx++) { + TableFactoryInfo.SmbiosHandleMap[Idx].SmbiosTblHandle = SMBIOS_HANDLE_PI_RESERVED; + TableFactoryInfo.SmbiosHandleMap[Idx].SmbiosCmToken = 0; + } Status = gBS->InstallProtocolInterface ( &ImageHandle, diff --git a/DynamicTablesPkg/Drivers/DynamicTableFactoryDxe/DynamicTableFactoryDxe.inf b/DynamicTablesPkg/Drivers/DynamicTableFactoryDxe/DynamicTableFactoryDxe.inf index 29ed3dc2e50..e4fd4860f98 100644 --- a/DynamicTablesPkg/Drivers/DynamicTableFactoryDxe/DynamicTableFactoryDxe.inf +++ b/DynamicTablesPkg/Drivers/DynamicTableFactoryDxe/DynamicTableFactoryDxe.inf @@ -44,6 +44,7 @@ gEdkiiDynamicTablesPkgTokenSpaceGuid.PcdMaxCustomACPIGenerators gEdkiiDynamicTablesPkgTokenSpaceGuid.PcdMaxCustomSMBIOSGenerators gEdkiiDynamicTablesPkgTokenSpaceGuid.PcdMaxCustomDTGenerators + gEdkiiDynamicTablesPkgTokenSpaceGuid.PcdMaxSmbiosHandleMapEntries [Protocols] gEdkiiDynamicTableFactoryProtocolGuid # PRODUCES diff --git a/DynamicTablesPkg/Drivers/DynamicTableFactoryDxe/SmbiosTableFactory/SmbiosTableFactory.c b/DynamicTablesPkg/Drivers/DynamicTableFactoryDxe/SmbiosTableFactory/SmbiosTableFactory.c index 87795919f84..74d4fc8a163 100644 --- a/DynamicTablesPkg/Drivers/DynamicTableFactoryDxe/SmbiosTableFactory/SmbiosTableFactory.c +++ b/DynamicTablesPkg/Drivers/DynamicTableFactoryDxe/SmbiosTableFactory/SmbiosTableFactory.c @@ -12,6 +12,7 @@ #include #include #include +#include #include // Module specific include files. @@ -24,6 +25,70 @@ extern EDKII_DYNAMIC_TABLE_FACTORY_INFO TableFactoryInfo; +/** Add a new entry to the SMBIOS table Map. + + @param [in] Smbios SMBIOS Protocol pointer. + @param [in] SmbiosHandle SMBIOS Handle to be added. + @param [in] CmObjectToken CmObjectToken of the CM_OBJECT used to build the SMBIOS Table + @param [in] GeneratorId Smbios Table Generator Id. + + @retval EFI_SUCCESS Successfully added/generated the handle. + @retval EFI_OUT_OF_RESOURCESNULL Failure to add/generate the handle. +**/ +EFI_STATUS +EFIAPI +AddSmbiosHandle ( + IN EFI_SMBIOS_PROTOCOL *Smbios, + IN SMBIOS_HANDLE *SmbiosHandle, + IN CM_OBJECT_TOKEN CmObjectToken, + IN SMBIOS_TABLE_GENERATOR_ID GeneratorId + ) +{ + EFI_STATUS Status; + UINTN Index; + + Status = EFI_OUT_OF_RESOURCES; + + for (Index = 0; Index < FixedPcdGet16(PcdMaxSmbiosHandleMapEntries); Index++) { + if (TableFactoryInfo.SmbiosHandleMap[Index].SmbiosTblHandle == SMBIOS_HANDLE_PI_RESERVED) { + TableFactoryInfo.SmbiosHandleMap[Index].SmbiosTblHandle = *SmbiosHandle; + TableFactoryInfo.SmbiosHandleMap[Index].SmbiosCmToken = CmObjectToken; + TableFactoryInfo.SmbiosHandleMap[Index].SmbiosGeneratorId = GeneratorId; + Status = EFI_SUCCESS; + break; + } + } + + return Status; +} + +/** Return a pointer to the SMBIOS table Map. + + @param [in] GeneratorId The CmObjectToken to look up an SMBIOS Handle. + + @retval SMBIOS_HANDLE_MAP if the CmObjectToken is found. + @retval NULL if not found. +**/ +SMBIOS_HANDLE_MAP * +EFIAPI +FindSmbiosHandle ( + CM_OBJECT_TOKEN CmObjectToken + ) +{ + UINTN Index; + SMBIOS_HANDLE_MAP *SmbiosHandleMap; + + SmbiosHandleMap = NULL; + for (Index = 0; Index < FixedPcdGet16(PcdMaxSmbiosHandleMapEntries); Index++) { + if (TableFactoryInfo.SmbiosHandleMap[Index].SmbiosCmToken == CmObjectToken) { + SmbiosHandleMap = &TableFactoryInfo.SmbiosHandleMap[Index]; + break; + } + } + + return SmbiosHandleMap; +} + /** Return a pointer to the SMBIOS table generator. @param [in] This Pointer to the Dynamic Table Factory Protocol. @@ -229,3 +294,44 @@ DeregisterSmbiosTableGenerator ( DEBUG ((DEBUG_INFO, "Deregistering %s\n", Generator->Description)); return EFI_SUCCESS; } + +/** Find and return SMBIOS handle based on associated CM object token. + + @param [in] GeneratorId SMBIOS generator ID used to build the SMBIOS Table. + @param [in] CmObjectToken Token of the CM_OBJECT used to build the SMBIOS Table. + + @return SMBIOS handle of the table associated with SmbiosGeneratorId and + CmObjectToken if found. Otherwise, returns 0xFFFF. +**/ +SMBIOS_HANDLE +EFIAPI +FindSmbiosHandleEx ( + IN SMBIOS_TABLE_GENERATOR_ID GeneratorId, + IN CM_OBJECT_TOKEN CmObjToken + ) +{ + SMBIOS_HANDLE_MAP *HandleMap; + + if (CmObjToken == CM_NULL_TOKEN) { + return SMBIOS_HANDLE_INVALID; + } + + HandleMap = FindSmbiosHandle (CmObjToken); + if (HandleMap == NULL) { + return SMBIOS_HANDLE_INVALID; + } + + if (HandleMap->SmbiosGeneratorId != GeneratorId) { + DEBUG (( + DEBUG_ERROR, + "%a: Expect ID %d but get %d\n", + __func__, + GeneratorId, + HandleMap->SmbiosGeneratorId + )); + ASSERT (FALSE); + return SMBIOS_HANDLE_INVALID; + } + + return HandleMap->SmbiosTblHandle; +} diff --git a/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/AcpiTableBuilder.c b/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/AcpiTableBuilder.c new file mode 100644 index 00000000000..31bd35d30e0 --- /dev/null +++ b/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/AcpiTableBuilder.c @@ -0,0 +1,769 @@ +/** @file + Acpi Table Manager Dxe + + Copyright (c) 2017 - 2019, ARM Limited. All rights reserved. + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include +#include +#include + +// Module specific include files. +#include +#include +#include +#include +#include +#include +#include +#include "DynamicTableManagerDxe.h" + +/// +/// We require the FADT, MADT, GTDT and the DSDT tables to boot. +/// This list also include optional ACPI tables: DBG2, SPCR. +/// +STATIC ACPI_TABLE_PRESENCE_INFO *mAcpiVerifyTables; +STATIC UINT32 mAcpiVerifyTablesCount; +STATIC INT32 mAcpiVerifyTablesFadtIndex; + +/** 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 < mAcpiVerifyTablesCount; 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 < mAcpiVerifyTablesCount; 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 < mAcpiVerifyTablesCount; 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 ((mAcpiVerifyTablesFadtIndex >= 0) && + ((mAcpiVerifyTables[mAcpiVerifyTablesFadtIndex].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. +**/ +VOID +EFIAPI +AcpiTableProtocolReady ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + 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; + } + + // 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 = GetCgfMgrInfo (CfgMgrProtocol, &CfgMfrInfo); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: Failed to get Configuration Manager info. Status = %r\n", + Status + )); + return; + } + + 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 = GetAcpiTablePresenceInfo ( + &mAcpiVerifyTables, + &mAcpiVerifyTablesCount, + &mAcpiVerifyTablesFadtIndex + ); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return; + } + + Status = ProcessAcpiTables (TableFactoryProtocol, CfgMgrProtocol); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: ACPI Table processing failure. Status = %r\n", + Status + )); + } + Status = gBS->CloseEvent (Event); + ASSERT_EFI_ERROR (Status); + +} diff --git a/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableManagerDxe.c b/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableManagerDxe.c index dfccccb8395..c24f0281f12 100644 --- a/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableManagerDxe.c +++ b/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableManagerDxe.c @@ -8,10 +8,9 @@ **/ #include +#include #include #include -#include -#include // Module specific include files. #include @@ -21,645 +20,25 @@ #include #include #include -#include -#include "DynamicTableManagerDxe.h" +STATIC VOID *AcpiTableProtocolRegistration; +STATIC VOID *SmbiosProtocolRegistration; -/// -/// We require the FADT, MADT, GTDT and the DSDT tables to boot. -/// This list also include optional ACPI tables: DBG2, SPCR. -/// -STATIC ACPI_TABLE_PRESENCE_INFO *mAcpiVerifyTables; -STATIC UINT32 mAcpiVerifyTablesCount; -STATIC INT32 mAcpiVerifyTablesFadtIndex; - -/** 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 +extern +VOID 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 - )); - } +SmbiosProtocolReady ( + IN EFI_EVENT Event, + IN VOID *Context + ); - // 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 +extern +VOID 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 < mAcpiVerifyTablesCount; 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 < mAcpiVerifyTablesCount; 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 < mAcpiVerifyTablesCount; 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 ((mAcpiVerifyTablesFadtIndex >= 0) && - ((mAcpiVerifyTables[mAcpiVerifyTablesFadtIndex].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; -} +AcpiTableProtocolReady ( + IN EFI_EVENT Event, + IN VOID *Context + ); /** Entrypoint of Dynamic Table Manager Dxe. @@ -687,82 +66,33 @@ DynamicTableManagerDxeInitialize ( 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, + EFI_EVENT AcpiEvent; + EFI_EVENT SmbiosEvent; + + AcpiEvent = EfiCreateProtocolNotifyEvent ( + &gEfiAcpiTableProtocolGuid, + TPL_CALLBACK, + AcpiTableProtocolReady, + NULL, + &AcpiTableProtocolRegistration + ); + if (AcpiEvent == NULL) { + DEBUG ((DEBUG_ERROR, "%a: Failed to ACPI create protocol event\r\n", __func__)); + return EFI_OUT_OF_RESOURCES; + } + + SmbiosEvent = EfiCreateProtocolNotifyEvent ( + &gEfiSmbiosProtocolGuid, + TPL_CALLBACK, + SmbiosProtocolReady, NULL, - (VOID **)&CfgMgrProtocol + &SmbiosProtocolRegistration ); - 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 = GetAcpiTablePresenceInfo ( - &mAcpiVerifyTables, - &mAcpiVerifyTablesCount, - &mAcpiVerifyTablesFadtIndex - ); - if (EFI_ERROR (Status)) { - ASSERT_EFI_ERROR (Status); - return Status; - } - - Status = ProcessAcpiTables (TableFactoryProtocol, CfgMgrProtocol); - if (EFI_ERROR (Status)) { - DEBUG (( - DEBUG_ERROR, - "ERROR: ACPI Table processing failure. Status = %r\n", - Status - )); + if (SmbiosEvent == NULL) { + DEBUG ((DEBUG_ERROR, "%a: Failed to SMBIOS create protocol event\r\n", __func__)); + gBS->CloseEvent (AcpiEvent); + return EFI_OUT_OF_RESOURCES; } - return Status; + return EFI_SUCCESS; } diff --git a/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableManagerDxe.inf b/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableManagerDxe.inf index c982b24c2a3..31b44a341ae 100644 --- a/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableManagerDxe.inf +++ b/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableManagerDxe.inf @@ -1,7 +1,7 @@ ## @file -# Module that drives the table generation and installation process. +# Module that drives the table generation and installation process. # -# Copyright (c) 2017 - 2019, ARM Limited. All rights reserved. +# Copyright (c) 2017 - 2022, Arm Limited. All rights reserved. # Copyright (c) 2024 Advanced Micro Devices, Inc. All rights reserved. # # SPDX-License-Identifier: BSD-2-Clause-Patent @@ -24,6 +24,10 @@ [Sources] DynamicTableManagerDxe.c DynamicTableManagerDxe.h + SmbiosTableDispatcher.c + SmbiosTableDispatcher.h + AcpiTableBuilder.c + SmbiosTableBuilder.c [Sources.ARM, Sources.AARCH64] Arm/ArmDynamicTableManager.c @@ -39,6 +43,7 @@ [LibraryClasses] PrintLib TableHelperLib + UefiLib UefiBootServicesTableLib UefiDriverEntryPoint @@ -48,12 +53,11 @@ [Protocols] gEfiAcpiTableProtocolGuid # PROTOCOL ALWAYS_CONSUMED gEfiAcpiSdtProtocolGuid # PROTOCOL ALWAYS_CONSUMED - + gEfiSmbiosProtocolGuid # PROTOCOL ALWAYS_CONSUMED gEdkiiConfigurationManagerProtocolGuid # PROTOCOL ALWAYS_CONSUMED gEdkiiDynamicTableFactoryProtocolGuid # PROTOCOL ALWAYS_CONSUMED [Depex] - gEfiAcpiTableProtocolGuid AND gEdkiiConfigurationManagerProtocolGuid AND gEdkiiDynamicTableFactoryProtocolGuid diff --git a/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/SmbiosTableBuilder.c b/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/SmbiosTableBuilder.c new file mode 100644 index 00000000000..cb54bf5618b --- /dev/null +++ b/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/SmbiosTableBuilder.c @@ -0,0 +1,613 @@ +/** @file + Dynamic Table Manager Dxe + + Copyright (c) 2017 - 2019, ARM Limited. All rights reserved. + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include +#include + +// Module specific include files. +#include +#include +#include +#include +#include +#include +#include +#include + +/** This macro expands to a function that retrieves the SMBIOS Table + List from the Configuration Manager. +*/ +GET_OBJECT_LIST ( + EObjNameSpaceStandard, + EStdObjSmbiosTableList, + CM_STD_OBJ_SMBIOS_TABLE_INFO + ) + +/** A helper function to build and install an SMBIOS table. + + This is a helper function that invokes the Table generator interface + for building an SMBIOS table. It uses the SmbiosProtocol 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 SMBIOS table Generator. + @param [in] SmbiosProtocol Pointer to the SMBIOS protocol. + @param [in] SmbiosTableInfo Pointer to the SMBIOS 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 +BuildAndInstallSingleSmbiosTable ( + IN CONST EDKII_DYNAMIC_TABLE_FACTORY_PROTOCOL *CONST TableFactoryProtocol, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, + IN CONST SMBIOS_TABLE_GENERATOR *CONST Generator, + IN EFI_SMBIOS_PROTOCOL *SmbiosProtocol, + IN CM_STD_OBJ_SMBIOS_TABLE_INFO *CONST SmbiosTableInfo + ) +{ + EFI_STATUS Status; + EFI_STATUS Status1; + SMBIOS_STRUCTURE *SmbiosTable; + CM_OBJECT_TOKEN CmObjToken; + EFI_SMBIOS_HANDLE TableHandle; + + SmbiosTable = NULL; + Status = Generator->BuildSmbiosTable ( + Generator, + TableFactoryProtocol, + SmbiosTableInfo, + CfgMgrProtocol, + &SmbiosTable, + &CmObjToken + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: Failed to Build Table." \ + " TableGeneratorId = 0x%x. Status = %r\n", + SmbiosTableInfo->TableGeneratorId, + Status + )); + // Free any allocated resources. + goto exit_handler; + } + + if (SmbiosTable == NULL) { + Status = EFI_NOT_FOUND; + goto exit_handler; + } + + TableHandle = SMBIOS_HANDLE_PI_RESERVED; + + // Install SMBIOS table + Status = SmbiosProtocol->Add ( + SmbiosProtocol, + NULL, + &TableHandle, + SmbiosTable + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: Failed to Install SMBIOS Table. Status = %r\n", + Status + )); + // Free any allocated resources. + goto exit_handler; + } + + Status = TableFactoryProtocol->AddSmbiosHandle ( + SmbiosProtocol, + &TableHandle, + CmObjToken, + SmbiosTableInfo->TableGeneratorId + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: Failed to Add SMBIOS Handle. Status = %r\n", + Status + )); + // Free any allocated resources. + goto exit_handler; + } + + DEBUG (( + DEBUG_INFO, + "INFO: SMBIOS Table installed. Status = %r\n", + Status + )); + +exit_handler: + // Free any resources allocated for generating the tables. + if (Generator->FreeTableResources != NULL) { + Status1 = Generator->FreeTableResources ( + Generator, + TableFactoryProtocol, + SmbiosTableInfo, + CfgMgrProtocol, + &SmbiosTable + ); + if (EFI_ERROR (Status1)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: Failed to Free Table Resources." \ + "TableGeneratorId = 0x%x. Status = %r\n", + SmbiosTableInfo->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 SMBIOS tables. + + This is a helper function that invokes the Table generator interface + for building SMBIOS tables. It uses the SmbiosProtocol to install the + tables, 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 SmbiosTable generator. + @param [in] SmbiosProtocol Pointer to the Smbios protocol. + @param [in] SmbiosTableInfo Pointer to the SMBIOS 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 +BuildAndInstallMultipleSmbiosTables ( + IN CONST EDKII_DYNAMIC_TABLE_FACTORY_PROTOCOL *CONST TableFactoryProtocol, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, + IN CONST SMBIOS_TABLE_GENERATOR *CONST Generator, + IN EFI_SMBIOS_PROTOCOL *SmbiosProtocol, + IN CM_STD_OBJ_SMBIOS_TABLE_INFO *CONST SmbiosTableInfo + ) +{ + EFI_STATUS Status; + EFI_STATUS Status1; + SMBIOS_STRUCTURE **SmbiosTable; + CM_OBJECT_TOKEN *CmObjToken; + EFI_SMBIOS_HANDLE TableHandle; + UINTN TableCount; + UINTN Index; + + TableCount = 0; + Status = Generator->BuildSmbiosTableEx ( + Generator, + TableFactoryProtocol, + SmbiosTableInfo, + CfgMgrProtocol, + &SmbiosTable, + &CmObjToken, + &TableCount + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: Failed to Build Table." \ + " TableGeneratorId = 0x%x. Status = %r\n", + SmbiosTableInfo->TableGeneratorId, + Status + )); + // Free any allocated resources. + goto exit_handler; + } + + if ((SmbiosTable == NULL) || (TableCount == 0)) { + Status = EFI_NOT_FOUND; + DEBUG (( + DEBUG_ERROR, + "%a: TableCount %u SmbiosTable %p \n", + __func__, + TableCount, + SmbiosTable + )); + goto exit_handler; + } + + for (Index = 0; Index < TableCount; Index++) { + TableHandle = SMBIOS_HANDLE_PI_RESERVED; + + // Install SMBIOS table + Status = SmbiosProtocol->Add ( + SmbiosProtocol, + NULL, + &TableHandle, + SmbiosTable[Index] + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: Failed to Install SMBIOS Table. Status = %r\n", + Status + )); + // Free any allocated resources. + goto exit_handler; + } + + Status = TableFactoryProtocol->AddSmbiosHandle ( + SmbiosProtocol, + &TableHandle, + CmObjToken[Index], + SmbiosTableInfo->TableGeneratorId + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: Failed to Add SMBIOS Handle. Status = %r\n", + Status + )); + // Free any allocated resources. + goto exit_handler; + } + + DEBUG (( + DEBUG_INFO, + "INFO: SMBIOS Table installed. Status = %r\n", + Status + )); + } + +exit_handler: + // Free any resources allocated for generating the tables. + if (Generator->FreeTableResourcesEx != NULL) { + Status1 = Generator->FreeTableResourcesEx ( + Generator, + TableFactoryProtocol, + SmbiosTableInfo, + CfgMgrProtocol, + &SmbiosTable, + &CmObjToken, + TableCount + ); + if (EFI_ERROR (Status1)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: Failed to Free Table Resources." \ + "TableGeneratorId = 0x%x. Status = %r\n", + SmbiosTableInfo->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 SMBIOS table. It uses the SmbiosProtocol 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] SmbiosProtocol Pointer to the SMBIOS protocol. + @param [in] SmbiosTableInfo Pointer to the SMBIOS 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. +**/ +EFI_STATUS +EFIAPI +BuildAndInstallSmbiosTable ( + IN CONST EDKII_DYNAMIC_TABLE_FACTORY_PROTOCOL *CONST TableFactoryProtocol, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, + IN EFI_SMBIOS_PROTOCOL *SmbiosProtocol, + IN CM_STD_OBJ_SMBIOS_TABLE_INFO *CONST SmbiosTableInfo + ) +{ + EFI_STATUS Status; + CONST SMBIOS_TABLE_GENERATOR *Generator; + + ASSERT (TableFactoryProtocol != NULL); + ASSERT (CfgMgrProtocol != NULL); + ASSERT (SmbiosProtocol != NULL); + ASSERT (SmbiosTableInfo != NULL); + + DEBUG (( + DEBUG_INFO, + "INFO: EStdObjSmbiosTableList: Address = 0x%p," \ + " TableGeneratorId = 0x%x\n", + SmbiosTableInfo, + SmbiosTableInfo->TableGeneratorId + )); + + Generator = NULL; + Status = TableFactoryProtocol->GetSmbiosTableGenerator ( + TableFactoryProtocol, + SmbiosTableInfo->TableGeneratorId, + &Generator + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: Table Generator not found." \ + " TableGeneratorId = 0x%x. Status = %r\n", + SmbiosTableInfo->TableGeneratorId, + Status + )); + return Status; + } + + if (Generator == NULL) { + return EFI_NOT_FOUND; + } + + DEBUG (( + DEBUG_INFO, + "INFO: Generator found : %s\n", + Generator->Description + )); + + if (Generator->BuildSmbiosTableEx != NULL) { + Status = BuildAndInstallMultipleSmbiosTables ( + TableFactoryProtocol, + CfgMgrProtocol, + Generator, + SmbiosProtocol, + SmbiosTableInfo + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: Failed to find build and install SMBIOS Tables." \ + " Status = %r\n", + Status + )); + } + } else if (Generator->BuildSmbiosTable != NULL) { + Status = BuildAndInstallSingleSmbiosTable ( + TableFactoryProtocol, + CfgMgrProtocol, + Generator, + SmbiosProtocol, + SmbiosTableInfo + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: Failed to find build and install SMBIOS Table." \ + " Status = %r\n", + Status + )); + } + } else { + Status = EFI_INVALID_PARAMETER; + DEBUG (( + DEBUG_ERROR, + "ERROR: Table Generator does not implement the" \ + "SMBIOS_TABLE_GENERATOR_BUILD_TABLE interface." \ + " TableGeneratorId = 0x%x. Status = %r\n", + SmbiosTableInfo->TableGeneratorId, + Status + )); + } + + return Status; +} + +/** Generate and install SMBIOS tables. + + The function gathers the information necessary for installing the + SMBIOS 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. +**/ +STATIC +EFI_STATUS +EFIAPI +ProcessSmbiosTables ( + IN CONST EDKII_DYNAMIC_TABLE_FACTORY_PROTOCOL *CONST TableFactoryProtocol, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol + ) +{ + EFI_STATUS Status; + EFI_SMBIOS_PROTOCOL *SmbiosProtocol; + CM_STD_OBJ_SMBIOS_TABLE_INFO *SmbiosTableInfo; + UINT32 SmbiosTableCount; + + Status = gBS->LocateProtocol (&gEfiSmbiosProtocolGuid, NULL, (VOID **)&SmbiosProtocol); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Could not locate SMBIOS protocol. %r\n", Status)); + return Status; + } + + Status = GetEStdObjSmbiosTableList ( + CfgMgrProtocol, + CM_NULL_TOKEN, + &SmbiosTableInfo, + &SmbiosTableCount + ); + if (EFI_ERROR (Status)) { + if (Status != EFI_NOT_FOUND) { + // If the SMBIOS table list is not found the platform may not be publishing SMBIOS tables + // Log a warning and return success. + DEBUG (( DEBUG_WARN, "WARNING: Failed to get SMBIOS table List. Status = %r\n", Status)); + Status = EFI_SUCCESS; + } else { + DEBUG (( + DEBUG_ERROR, + "ERROR: Failed to get SMBIOS Table List. Status = %r\n", + Status + )); + } + return Status; + } + + if (SmbiosTableCount == 0) { + DEBUG (( + DEBUG_ERROR, + "ERROR: EStdObjSmbiosTableList: SmbiosTableCount = %d\n", + SmbiosTableCount + )); + return EFI_NOT_FOUND; + } + + DEBUG (( + DEBUG_INFO, + "INFO: EStdObjSmbiosTableList: SmbiosTableCount = %d\n", + SmbiosTableCount + )); + + InitSmbiosTableDispatcher (SmbiosTableInfo, SmbiosTableCount); + + Status = DispatchSmbiosTables ( + TableFactoryProtocol, + CfgMgrProtocol, + SmbiosProtocol, + SmbiosTableInfo, + SmbiosTableCount + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: Failed to install SMBIOS Tables.Status = %r\n", + Status + )); + } + + return Status; +} + +/** Callback function for SMBIOS Protocol . + + Callback function for SMBIOS protocol that installs SMBIOS tables + that use the DynamicTables Package. + + @param Event + @param Context + + @retval None +**/ +VOID +EFIAPI +SmbiosProtocolReady ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + 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; + } + + // 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 = GetCgfMgrInfo (CfgMgrProtocol, &CfgMfrInfo); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: Failed to get Configuration Manager info. Status = %r\n", + Status + )); + return; + } + + 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 = ProcessSmbiosTables (TableFactoryProtocol, CfgMgrProtocol); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: SMBIOS Table processing failure. Status = %r\n", + Status + )); + } + + Status = gBS->CloseEvent (Event); + ASSERT_EFI_ERROR (Status); +} diff --git a/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/SmbiosTableDispatcher.c b/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/SmbiosTableDispatcher.c new file mode 100644 index 00000000000..d4d5450158b --- /dev/null +++ b/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/SmbiosTableDispatcher.c @@ -0,0 +1,672 @@ +/** @file + Dynamic Smbios Table Dispatcher + + Copyright (c) 2022 - 2023, Arm Limited. All rights reserved. + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ +#include +#include + +#include +#include + +/** + The SMBIOS dispatcher state table. + + The SMBIOS dispatcher state table is used to establish the dependency + order in which the SMBIOS tables are installed. This allows the SMBIOS + dispatcher to dispatch the dependent tables for installation before the + parent table is installed. + The SMBIOS_TABLE_DISPATCHER.Dependency[] field is used to establish the + dependency list. + Elements in the Dependency list are resolved by increasing index. However, + all orders are equivalent as: + - the Parent SMBIOS table will only be installed once all dependencies + have been satisfied. + - no cyclic dependency is allowed. + The dependency list is terminated by SMTT_NULL. + + The SMBIOS dispatcher dispatches the tables that have the default + order (OrderDef) set before the ordered SMBIOS tables are dispatched. + The SMBIOS_TABLE_DISPATCHER.Order field is used to establish the + dispatch order. + + The order specified in the SMBIOS dispatcher table must be unique for all + orders other than OrderDef. The dependency walk is only done for tables + that have the default dispatch order. +*/ +STATIC +SMBIOS_TABLE_DISPATCHER mSmBiosDispatcher[MAX_SMBIOS_TABLES] = { + SMBIOS_TABLE_DEP (SMBIOS_TYPE_BIOS_INFORMATION, OrderDef, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL), + SMBIOS_TABLE_DEP (SMBIOS_TYPE_SYSTEM_INFORMATION, OrderDef, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL), + SMBIOS_TABLE_DEP (SMBIOS_TYPE_BASEBOARD_INFORMATION, OrderL1, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL), + SMBIOS_TABLE_DEP (SMBIOS_TYPE_SYSTEM_ENCLOSURE, OrderDef, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL), + SMBIOS_TABLE_DEP (SMBIOS_TYPE_PROCESSOR_INFORMATION, OrderDef, SMBIOS_TYPE_CACHE_INFORMATION, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL), + SMBIOS_TABLE_DEP (SMBIOS_TYPE_MEMORY_CONTROLLER_INFORMATION, OrderDef, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL), + SMBIOS_TABLE_DEP (SMBIOS_TYPE_MEMORY_MODULE_INFORMATON, OrderDef, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL), + SMBIOS_TABLE_DEP (SMBIOS_TYPE_CACHE_INFORMATION, OrderDef, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL), + SMBIOS_TABLE_DEP (SMBIOS_TYPE_PORT_CONNECTOR_INFORMATION, OrderDef, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL), + SMBIOS_TABLE_DEP (SMBIOS_TYPE_SYSTEM_SLOTS, OrderDef, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL), + SMBIOS_TABLE_DEP (SMBIOS_TYPE_ONBOARD_DEVICE_INFORMATION, OrderDef, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL), + SMBIOS_TABLE_DEP (SMBIOS_TYPE_OEM_STRINGS, OrderDef, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL), + SMBIOS_TABLE_DEP (SMBIOS_TYPE_SYSTEM_CONFIGURATION_OPTIONS, OrderDef, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL), + SMBIOS_TABLE_DEP (SMBIOS_TYPE_BIOS_LANGUAGE_INFORMATION, OrderDef, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL), + SMBIOS_TABLE_DEP (SMBIOS_TYPE_GROUP_ASSOCIATIONS, OrderL4, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL), + SMBIOS_TABLE_DEP (SMBIOS_TYPE_SYSTEM_EVENT_LOG, OrderDef, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL), + SMBIOS_TABLE_DEP (SMBIOS_TYPE_PHYSICAL_MEMORY_ARRAY, OrderDef, SMBIOS_TYPE_32BIT_MEMORY_ERROR_INFORMATION, SMBIOS_TYPE_64BIT_MEMORY_ERROR_INFORMATION, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL), + SMBIOS_TABLE_DEP (SMBIOS_TYPE_MEMORY_DEVICE, OrderDef, SMBIOS_TYPE_PHYSICAL_MEMORY_ARRAY, SMBIOS_TYPE_32BIT_MEMORY_ERROR_INFORMATION, SMBIOS_TYPE_64BIT_MEMORY_ERROR_INFORMATION, SMTT_NULL, SMTT_NULL, SMTT_NULL), + SMBIOS_TABLE_DEP (SMBIOS_TYPE_32BIT_MEMORY_ERROR_INFORMATION, OrderDef, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL), + SMBIOS_TABLE_DEP (SMBIOS_TYPE_MEMORY_ARRAY_MAPPED_ADDRESS, OrderDef, SMBIOS_TYPE_PHYSICAL_MEMORY_ARRAY, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL), + SMBIOS_TABLE_DEP (SMBIOS_TYPE_MEMORY_DEVICE_MAPPED_ADDRESS, OrderDef, SMBIOS_TYPE_MEMORY_DEVICE, SMBIOS_TYPE_MEMORY_ARRAY_MAPPED_ADDRESS, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL), + SMBIOS_TABLE_DEP (SMBIOS_TYPE_BUILT_IN_POINTING_DEVICE, OrderDef, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL), + SMBIOS_TABLE_DEP (SMBIOS_TYPE_PORTABLE_BATTERY, OrderDef, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL), + SMBIOS_TABLE_DEP (SMBIOS_TYPE_SYSTEM_RESET, OrderDef, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL), + SMBIOS_TABLE_DEP (SMBIOS_TYPE_HARDWARE_SECURITY, OrderDef, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL), + SMBIOS_TABLE_DEP (SMBIOS_TYPE_SYSTEM_POWER_CONTROLS, OrderDef, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL), + SMBIOS_TABLE_DEP (SMBIOS_TYPE_VOLTAGE_PROBE, OrderDef, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL), + SMBIOS_TABLE_DEP (SMBIOS_TYPE_COOLING_DEVICE, OrderDef, SMBIOS_TYPE_TEMPERATURE_PROBE, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL), + SMBIOS_TABLE_DEP (SMBIOS_TYPE_TEMPERATURE_PROBE, OrderDef, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL), + SMBIOS_TABLE_DEP (SMBIOS_TYPE_ELECTRICAL_CURRENT_PROBE, OrderDef, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL), + SMBIOS_TABLE_DEP (SMBIOS_TYPE_OUT_OF_BAND_REMOTE_ACCESS, OrderDef, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL), + SMBIOS_TABLE_DEP (SMBIOS_TYPE_BOOT_INTEGRITY_SERVICE, OrderDef, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL), + SMBIOS_TABLE_DEP (SMBIOS_TYPE_SYSTEM_BOOT_INFORMATION, OrderDef, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL), + SMBIOS_TABLE_DEP (SMBIOS_TYPE_64BIT_MEMORY_ERROR_INFORMATION, OrderDef, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL), + SMBIOS_TABLE_DEP (SMBIOS_TYPE_MANAGEMENT_DEVICE, OrderDef, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL), + SMBIOS_TABLE_DEP (SMBIOS_TYPE_MANAGEMENT_DEVICE_COMPONENT, OrderDef, SMBIOS_TYPE_MANAGEMENT_DEVICE, SMBIOS_TYPE_VOLTAGE_PROBE, SMBIOS_TYPE_COOLING_DEVICE, SMBIOS_TYPE_TEMPERATURE_PROBE, SMBIOS_TYPE_ELECTRICAL_CURRENT_PROBE, SMBIOS_TYPE_MANAGEMENT_DEVICE_THRESHOLD_DATA), + SMBIOS_TABLE_DEP (SMBIOS_TYPE_MANAGEMENT_DEVICE_THRESHOLD_DATA, OrderDef, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL), + SMBIOS_TABLE_DEP (SMBIOS_TYPE_MEMORY_CHANNEL, OrderDef, SMBIOS_TYPE_MEMORY_DEVICE, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL), + SMBIOS_TABLE_DEP (SMBIOS_TYPE_IPMI_DEVICE_INFORMATION, OrderDef, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL), + SMBIOS_TABLE_DEP (SMBIOS_TYPE_SYSTEM_POWER_SUPPLY, OrderDef, SMBIOS_TYPE_VOLTAGE_PROBE, SMBIOS_TYPE_COOLING_DEVICE, SMBIOS_TYPE_ELECTRICAL_CURRENT_PROBE, SMTT_NULL, SMTT_NULL, SMTT_NULL), + SMBIOS_TABLE_DEP (SMBIOS_TYPE_ADDITIONAL_INFORMATION, OrderL3, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL), + SMBIOS_TABLE_DEP (SMBIOS_TYPE_ONBOARD_DEVICES_EXTENDED_INFORMATION, OrderDef, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL), + SMBIOS_TABLE_DEP (SMBIOS_TYPE_MANAGEMENT_CONTROLLER_HOST_INTERFACE, OrderDef, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL), + SMBIOS_TABLE_DEP (SMBIOS_TYPE_TPM_DEVICE, OrderDef, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL), + SMBIOS_TABLE_DEP (SMBIOS_TYPE_PROCESSOR_ADDITIONAL_INFORMATION, OrderDef, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL), + SMBIOS_TABLE_DEP (SMBIOS_TYPE_FIRMWARE_INVENTORY_INFORMATION, OrderL2, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL), + SMBIOS_TABLE_DEP (SMBIOS_TYPE_STRING_PROPERTY_INFORMATION, OrderL5, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL, SMTT_NULL) +}; + +#if !defined (MDEPKG_NDEBUG) + +/** + A string table describing the SMBIOS dispatcher states. +*/ +STATIC +CONST CHAR8 *SmbiosTableStateTxt[] = { + "StNotPresent", + "StPresent", + "StDispatched" +}; + +/** + Print the SMBIOS Table Dispatcher state information. + + @param [in] Verbose Print detailed report +**/ +STATIC +VOID +EFIAPI +PrintDispatcherStatus ( + IN BOOLEAN Verbose + ) +{ + UINTN Index; + + DEBUG ((DEBUG_VERBOSE, "Dispatcher Status:\n")); + for (Index = 0; Index < ARRAY_SIZE (mSmBiosDispatcher); Index++) { + if ((!Verbose) && (mSmBiosDispatcher[Index].State == StNotPresent)) { + continue; + } + + DEBUG (( + DEBUG_VERBOSE, + "%02d: %10a [%02d, %02d, %02d, %02d, %02d]\n", + mSmBiosDispatcher[Index].TableType, + SmbiosTableStateTxt[mSmBiosDispatcher[Index].State], + mSmBiosDispatcher[Index].Dependency[0], + mSmBiosDispatcher[Index].Dependency[1], + mSmBiosDispatcher[Index].Dependency[2], + mSmBiosDispatcher[Index].Dependency[3], + mSmBiosDispatcher[Index].Dependency[4] + )); + } // for + + DEBUG ((DEBUG_VERBOSE, "\n")); +} + +#define DEBUG_PRINT_DISPATCHER_STATUS(Verbose) PrintDispatcherStatus (Verbose) +#else +#define DEBUG_PRINT_DISPATCHER_STATUS(x) +#endif + +/** + Initialise the SMBIOS table dispatcher. + + @param [in] SmbiosTableInfo Pointer to the list of SMBIOS tables to be + installed. + @param [in] SmbiosTableCount Count of SMBIOS tables to be installed. +**/ +VOID +EFIAPI +InitSmbiosTableDispatcher ( + IN CM_STD_OBJ_SMBIOS_TABLE_INFO *SmbiosTableInfo, + IN UINT32 SmbiosTableCount + ) +{ + UINTN Index; + SMBIOS_TABLE_TYPE TableType; + + // Search for the list of SMBIOS tables presented + // for installation and update the dispatcher status. + for (Index = 0; Index < SmbiosTableCount; Index++) { + TableType = SmbiosTableInfo[Index].TableType; + ASSERT (TableType < MAX_SMBIOS_TABLES); + ASSERT (mSmBiosDispatcher[TableType].State != StPresent); + mSmBiosDispatcher[TableType].State = StPresent; + } + + DEBUG_PRINT_DISPATCHER_STATUS (FALSE); +} + +/** Dispatch the SMBIOS table. + + @param [in] Disp Pointer to the SMBIOS table dispatcher + object for the table to dispatch. + @param [in] TableFactoryProtocol Pointer to the Table Factory Protocol + interface. + @param [in] CfgMgrProtocol Pointer to the Configuration Manager + Protocol Interface. + @param [in] SmbiosProtocol Pointer to the SMBIOS protocol. + @param [in] SmbiosTableInfo Pointer to the SMBIOS table Info. + @param [in] SmbiosTableCount Count of SMBIOS table info objects. + + @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 +DispatchTable ( + IN SMBIOS_TABLE_DISPATCHER *CONST Disp, + IN CONST EDKII_DYNAMIC_TABLE_FACTORY_PROTOCOL *CONST TableFactoryProtocol, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, + IN EFI_SMBIOS_PROTOCOL *SmbiosProtocol, + IN CM_STD_OBJ_SMBIOS_TABLE_INFO *CONST SmbiosTableInfo, + IN CONST UINT32 SmbiosTableCount + ) +{ + UINTN Index; + EFI_STATUS Status; + BOOLEAN Found; + + if (Disp == NULL) { + return EFI_INVALID_PARAMETER; + } + + Found = FALSE; + + // Update the dispatcher state to dispatched. + Disp->State = StDispatched; + // Find the SMBIOS table info matching the TableType + for (Index = 0; Index < SmbiosTableCount; Index++) { + if (SmbiosTableInfo[Index].TableType == Disp->TableType) { + Found = TRUE; + break; + } + } + + if (!Found) { + ASSERT (0); + return EFI_NOT_FOUND; + } + + // Install the SMBIOS table + Status = BuildAndInstallSmbiosTable ( + TableFactoryProtocol, + CfgMgrProtocol, + SmbiosProtocol, + &SmbiosTableInfo[Index] + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: Failed to install SMBIOS Table." \ + " Id = %d Status = %r\n", + SmbiosTableInfo[Index].TableGeneratorId, + Status + )); + } + + return Status; +} + +/** Schedule the dispatch of a default ordered SMBIOS table. + + The SMBIOS dispatcher state table is used to establish the dependency + order in which the SMBIOS tables are installed. This allows the SMBIOS + dispatcher to dispatch the dependent tables for installation before the + parent table is installed. + The SMBIOS_TABLE_DISPATCHER.Dependency[] field is used to establish the + dependency list. + Elements in the Dependency list are resolved by increasing index. However, + all orders are equivalent as: + - the Parent SMBIOS table will only be installed once all dependencies + have been satisfied. + - no cyclic dependency is allowed. + The dependency list is terminated by SMTT_NULL. + + @param [in] TableType The SMBIOS table type to schedule for + dispatch. + @param [in] TableFactoryProtocol Pointer to the Table Factory Protocol + interface. + @param [in] CfgMgrProtocol Pointer to the Configuration Manager + Protocol Interface. + @param [in] SmbiosProtocol Pointer to the SMBIOS protocol. + @param [in] SmbiosTableInfo Pointer to the SMBIOS table Info. + @param [in] SmbiosTableCount Count of SMBIOS table info objects. + + @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. + @retval EFI_NO_MAPPING A dependent table may be optional and + may not be in the list of tables to install. + @retval EFI_ALREADY_STARTED A table may be in the dependency list of + multiple tables and would have been installed + when one of the other parent table's dependency + list was fulfilled. +**/ +STATIC +EFI_STATUS +EFIAPI +DispatchDefaultOrderedSmbiosTable ( + IN CONST SMBIOS_TABLE_TYPE TableType, + IN CONST EDKII_DYNAMIC_TABLE_FACTORY_PROTOCOL *CONST TableFactoryProtocol, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, + IN EFI_SMBIOS_PROTOCOL *SmbiosProtocol, + IN CM_STD_OBJ_SMBIOS_TABLE_INFO *CONST SmbiosTableInfo, + IN CONST UINT32 SmbiosTableCount + ) +{ + EFI_STATUS Status; + UINTN Index; + SMBIOS_TABLE_DISPATCHER *Disp; + SMBIOS_TABLE_TYPE DepTableType; + + DEBUG ((DEBUG_VERBOSE, "->DP %02d\n", TableType)); + Disp = &mSmBiosDispatcher[TableType]; + + if (Disp->Order != OrderDef) { + DEBUG ((DEBUG_VERBOSE, "<-DP %d : EFI_INVALID_PARAMETER\n", TableType)); + // The table being request for installation is + // not a default ordered table. + return EFI_INVALID_PARAMETER; + } + + if (Disp->State == StNotPresent) { + DEBUG ((DEBUG_VERBOSE, "<-DP %02d : EFI_NO_MAPPING\n", TableType)); + // A dependent table may be optional and therefore may + // not be in the list of tables to install. + return EFI_NO_MAPPING; + } + + if (Disp->State == StDispatched) { + DEBUG ((DEBUG_VERBOSE, "<-DP %02d : EFI_ALREADY_STARTED\n", TableType)); + // This table may be in the dependency list of multiple tables + // and would have been installed when one of the other parent + // table's dependency list was fulfilled. + return EFI_ALREADY_STARTED; + } + + // Table is present so check the dependency. + for (Index = 0; Index < MAX_SMBIOS_DEPENDENCY; Index++) { + DepTableType = Disp->Dependency[Index]; + // Check if the dependency list is terminated by SMTT_NULL. + if (DepTableType == SMTT_NULL) { + break; + } + + if (mSmBiosDispatcher[DepTableType].Order != OrderDef) { + // An incorrect dependency has been set. + // The default ordered SMBIOS tables must not have + // a dependency on ordered SMBIOS tables. + DEBUG (( + DEBUG_VERBOSE, + "<-DP %02d : EFI_INVALID_PARAMETER - Invalid dependency\n", + TableType + )); + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + Status = DispatchDefaultOrderedSmbiosTable ( + DepTableType, + TableFactoryProtocol, + CfgMgrProtocol, + SmbiosProtocol, + SmbiosTableInfo, + SmbiosTableCount + ); + if (EFI_ERROR (Status)) { + if ((Status == EFI_ALREADY_STARTED) || + (Status == EFI_NO_MAPPING)) + { + // Some dependencies may already be satisfied + // as other tables may also have similar + // dependencies i.e. EFI_ALREADY_STARTED + // Or + // the dependent table may be optional + // and not provided i.e. EFI_NO_MAPPING. + DEBUG (( + DEBUG_VERBOSE, + "<-DP %02d : Status = %r - treated as Success, continue\n", + TableType, + Status + )); + // Therefore, reset Status to success + Status = EFI_SUCCESS; + continue; + } + + DEBUG (( + DEBUG_VERBOSE, + "<-DP %02d : Status = %r\n", + TableType, + Status + )); + return Status; + } + } + + // All dependencies satisfied - dispatch SMBIOS table + Status = DispatchTable ( + Disp, + TableFactoryProtocol, + CfgMgrProtocol, + SmbiosProtocol, + SmbiosTableInfo, + SmbiosTableCount + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: Failed to install SMBIOS Table." \ + " TableType = %u Status = %r\n", + Disp->TableType, + Status + )); + } + + DEBUG_PRINT_DISPATCHER_STATUS (FALSE); + DEBUG ((DEBUG_VERBOSE, "<-DP %0d\n", TableType)); + return Status; +} + +/** Schedule the dispatch of ordered SMBIOS tables. + + The SMBIOS dispatcher dispatches the tables that have the default + order (OrderDef) set first before the ordered SMBIOS tables are + dispatched. + The SMBIOS_TABLE_DISPATCHER.Order field is used to establish the + dispatch order. + + @param [in] Order The dispatch order for the SMBIOS table type + to be scheduled for dispatch. + @param [in] TableFactoryProtocol Pointer to the Table Factory Protocol + interface. + @param [in] CfgMgrProtocol Pointer to the Configuration Manager + Protocol Interface. + @param [in] SmbiosProtocol Pointer to the SMBIOS protocol. + @param [in] SmbiosTableInfo Pointer to the SMBIOS table Info. + @param [in] SmbiosTableCount Count of SMBIOS table info objects. + + @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 +DispatchOrderedSmbiosTables ( + IN CONST DISPATCH_ORDER Order, + IN CONST EDKII_DYNAMIC_TABLE_FACTORY_PROTOCOL *CONST TableFactoryProtocol, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, + IN EFI_SMBIOS_PROTOCOL *SmbiosProtocol, + IN CM_STD_OBJ_SMBIOS_TABLE_INFO *CONST SmbiosTableInfo, + IN CONST UINT32 SmbiosTableCount + ) +{ + EFI_STATUS Status; + UINTN Index; + SMBIOS_TABLE_DISPATCHER *Disp; + + DEBUG ((DEBUG_VERBOSE, "->DPO %d\n", Order)); + + if (Order == OrderDef) { + DEBUG ((DEBUG_VERBOSE, "<-DPO %d : EFI_INVALID_PARAMETER\n", Order)); + return EFI_INVALID_PARAMETER; + } + + Disp = NULL; + for (Index = 0; Index < ARRAY_SIZE (mSmBiosDispatcher); Index++) { + if (mSmBiosDispatcher[Index].Order == Order) { + Disp = &mSmBiosDispatcher[Index]; + break; + } + } // for + + if (Disp == NULL) { + // Table with specified order not found. + DEBUG ((DEBUG_VERBOSE, "<-DPO %d : EFI_INVALID_PARAMETER\n", Order)); + ASSERT (0); + return EFI_INVALID_PARAMETER; + } else if (Disp->State == StNotPresent) { + // An ordered table of this order is not present + // for installation. So, nothing to do here. + DEBUG (( + DEBUG_VERBOSE, + "<-DPO %a - %d {%u}: EFI_SUCCESS\n", + SmbiosTableStateTxt[Disp->State], + Order, + Disp->TableType + )); + return EFI_SUCCESS; + } else if (Disp->State == StDispatched) { + // Ordered tables are dispatched in their dispatch order and + // cannot be in the dependency list of any other table. + // Therefore, the table cannot be already dispatched. + DEBUG (( + DEBUG_VERBOSE, + "<-DPO %a - %d {%u}: EFI_INVALID_PARAMETER\n", + SmbiosTableStateTxt[Disp->State], + Order, + Disp->TableType + )); + + ASSERT (0); + return EFI_INVALID_PARAMETER; + } else if (Disp->State != StPresent) { + // Invalid state, at this point the only valid state + // should be StPresent, otherwise the state machine + // is incorrect. + DEBUG (( + DEBUG_VERBOSE, + "<-DPO %d - %d {%u}: EFI_INVALID_PARAMETER\n", + Disp->State, + Order, + Disp->TableType + )); + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + Status = DispatchTable ( + Disp, + TableFactoryProtocol, + CfgMgrProtocol, + SmbiosProtocol, + SmbiosTableInfo, + SmbiosTableCount + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: Failed to install SMBIOS Table." \ + " TableType = %u Status = %r\n", + Disp->TableType, + Status + )); + } + + DEBUG_PRINT_DISPATCHER_STATUS (FALSE); + DEBUG ((DEBUG_VERBOSE, "<-DPO %d {%u}\n", Order, Disp->TableType)); + return Status; +} + +/** Schedule the dispatch of SMBIOS tables. + + The SMBIOS dispatcher state table is used to establish the dependency + order in which the SMBIOS tables are installed. This allows the SMBIOS + dispatcher to dispatch the dependent tables for installation before the + parent table is installed. + The SMBIOS_TABLE_DISPATCHER.Dependency[] field is used to establish the + dependency list. + Elements in the Dependency list are resolved by increasing index. However, + all orders are equivalent as: + - the Parent SMBIOS table will only be installed once all dependencies + have been satisfied. + - no cyclic dependency is allowed. + The dependency list is terminated by SMTT_NULL. + + The SMBIOS dispatcher dispatches the tables that have the default + order (OrderDef) set before the ordered SMBIOS tables are dispatched. + The SMBIOS_TABLE_DISPATCHER.Order field is used to establish the + dispatch order. + + The order specified in the SMBIOS dispatcher table must be unique for all + orders other than OrderDef. The dependency walk is only done for tables + that have the default dispatch order. + + @param [in] TableFactoryProtocol Pointer to the Table Factory Protocol + interface. + @param [in] CfgMgrProtocol Pointer to the Configuration Manager + Protocol Interface. + @param [in] SmbiosProtocol Pointer to the SMBIOS protocol. + @param [in] SmbiosTableInfo Pointer to the SMBIOS table Info. + @param [in] SmbiosTableCount Count of SMBIOS table info objects. + + @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. +**/ +EFI_STATUS +EFIAPI +DispatchSmbiosTables ( + IN CONST EDKII_DYNAMIC_TABLE_FACTORY_PROTOCOL *CONST TableFactoryProtocol, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, + IN EFI_SMBIOS_PROTOCOL *SmbiosProtocol, + IN CM_STD_OBJ_SMBIOS_TABLE_INFO *CONST SmbiosTableInfo, + IN CONST UINT32 SmbiosTableCount + ) +{ + EFI_STATUS Status; + UINTN Index; + UINT8 Order; + SMBIOS_TABLE_TYPE TableType; + + if ((TableFactoryProtocol == NULL) || + (CfgMgrProtocol == NULL) || + (SmbiosProtocol == NULL) || + (SmbiosTableInfo == NULL) || + (SmbiosTableCount == 0)) + { + return EFI_INVALID_PARAMETER; + } + + // First dispatch the default ordered SMBIOS tables + for (Index = 0; Index < SmbiosTableCount; Index++) { + TableType = SmbiosTableInfo[Index].TableType; + ASSERT (TableType < MAX_SMBIOS_TABLES); + if (mSmBiosDispatcher[TableType].Order != OrderDef) { + // Skip if the table is not a default order table. + continue; + } + + Status = DispatchDefaultOrderedSmbiosTable ( + TableType, + TableFactoryProtocol, + CfgMgrProtocol, + SmbiosProtocol, + SmbiosTableInfo, + SmbiosTableCount + ); + if (EFI_ERROR (Status)) { + if ((Status == EFI_ALREADY_STARTED) || + (Status == EFI_NO_MAPPING)) + { + // Some dependencies may already be satisfied + // as other tables may also have similar + // dependencies i.e. EFI_ALREADY_STARTED + // Or + // the dependent table may be optional + // and not provided i.e. EFI_NO_MAPPING. + DEBUG (( + DEBUG_VERBOSE, + "TableType %02d : Status = %r - treated as Success, continue\n", + SmbiosTableInfo[Index].TableType, + Status + )); + // Therefore, reset Status to success + Status = EFI_SUCCESS; + continue; + } + + DEBUG (( + DEBUG_ERROR, + "ERROR: Failed to install SMBIOS Table." \ + " Id = %d Status = %r\n", + SmbiosTableInfo[Index].TableGeneratorId, + Status + )); + return Status; + } + } + + // Now dispatch the ordered SMBIOS tables + for (Order = OrderL1; Order < OrderMax; Order++) { + Status = DispatchOrderedSmbiosTables ( + (DISPATCH_ORDER)Order, + TableFactoryProtocol, + CfgMgrProtocol, + SmbiosProtocol, + SmbiosTableInfo, + SmbiosTableCount + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: Failed to install SMBIOS Table." \ + " Order = %d Status = %r\n", + Order, + Status + )); + break; + } + } + + return Status; +} diff --git a/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/SmbiosTableDispatcher.h b/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/SmbiosTableDispatcher.h new file mode 100644 index 00000000000..02860463a5d --- /dev/null +++ b/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/SmbiosTableDispatcher.h @@ -0,0 +1,180 @@ +/** @file + + Copyright (c) 2022 - 2023, Arm Limited. All rights reserved. + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef SMBIOS_TABLE_DISPATCHER_H_ +#define SMBIOS_TABLE_DISPATCHER_H_ + +#include +#include + +/** + A SMBIOS Table Type from the OEM range reserved for terminating + the SMBIOS table dispatch dependency. + + Note: According to the SMBIOS specification, Table Types 0 + through 127 (7Fh) are reserved for and defined by the + SMBIOS specification. + Types 128 through 256 (80h to FFh) are available for system and + OEM-specific information. + + This Dynamic SMBIOS table generation implementation defines + TableType FFh as a NULL table which is used by the Dynamic + SMBIOS table dispatcher to terminate the dependency list. +*/ +#define SMTT_NULL 0xFF + +/** + A macro defining the maximum number of dependendant SMBIOS tables + represented by the SMBIOS table dispatcher. +*/ +#define MAX_SMBIOS_DEPENDENCY 6 + +/** + A macro defining the maximum table types handled by the SMBIOS + table dispatcher. +*/ +#define MAX_SMBIOS_TABLES (SMBIOS_TYPE_STRING_PROPERTY_INFORMATION + 1) + +/** + A helper macro to populate the SMBIOS table dispatcher table +*/ +#define SMBIOS_TABLE_DEP(TableId, Order, Dep1, Dep2, Dep3, Dep4, Dep5, Dep6) \ + { \ + TableId, \ + Order, \ + StNotPresent, \ + { Dep1, Dep2, Dep3, Dep4, Dep5, Dep6 } \ + } + +/** + An enum describing the states of the SMBIOS table dispatcher. +*/ +typedef enum SmbiosTableState { + StNotPresent, ///< SMBIOS table is not present for installation. + StPresent, ///< SMBIOS table is present for installation. + StDispatched ///< SMBIOS table generators have been dispatched. +} SMBIOS_TABLE_STATE; + +/** + An enum describing the dispatch order for the SMBIOS tables. +*/ +typedef enum DispatchOrder { + OrderDef = 0, ///< Default dispatch order. + OrderL1, ///< Dispatch order 1. + OrderL2, ///< Dispatch order 2. + OrderL3, ///< Dispatch order 3. + OrderL4, ///< Dispatch order 4. + OrderL5, ///< Dispatch order 5. + OrderMax ///< Dispatch order Max. +} DISPATCH_ORDER; + +/** + A structure describing the dependencies for a SMBIOS table and + the dispatcher state information. +*/ +typedef struct SmBiosTableDispatcher { + /// SMBIOS Structure/Table Type + SMBIOS_TABLE_TYPE TableType; + /// SMBIOS table dispatch order + DISPATCH_ORDER Order; + /// SMBIOS dispatcher state + SMBIOS_TABLE_STATE State; + /// SMBIOS Structure/Table dependency list + /// The list is terminated using SMTT_NULL. + SMBIOS_TABLE_TYPE Dependency[MAX_SMBIOS_DEPENDENCY]; +} SMBIOS_TABLE_DISPATCHER; + +/** + A helper function to build and install a SMBIOS table. + + @param [in] TableFactoryProtocol Pointer to the Table Factory Protocol + interface. + @param [in] CfgMgrProtocol Pointer to the Configuration Manager + Protocol Interface. + @param [in] SmbiosProtocol Pointer to the SMBIOS protocol. + @param [in] SmbiosTableInfo Pointer to the SMBIOS 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. +**/ +EFI_STATUS +EFIAPI +BuildAndInstallSmbiosTable ( + IN CONST EDKII_DYNAMIC_TABLE_FACTORY_PROTOCOL *CONST TableFactoryProtocol, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, + IN EFI_SMBIOS_PROTOCOL *SmbiosProtocol, + IN CM_STD_OBJ_SMBIOS_TABLE_INFO *CONST SmbiosTableInfo + ); + +/** + Initialise the SMBIOS table dispatcher. + + @param SmbiosTableInfo Pointer to the list of SMBIOS tables to be installed. + @param SmbiosTableCount Count of SMBIOS tables to be installed. +**/ +VOID +EFIAPI +InitSmbiosTableDispatcher ( + IN CM_STD_OBJ_SMBIOS_TABLE_INFO *SmbiosTableInfo, + IN UINT32 SmbiosTableCount + ); + +/** Schedule the dispatch of SMBIOS tables. + + The SMBIOS dispatcher state table is used to establish the dependency + order in which the SMBIOS tables are installed. This allows the SMBIOS + dispatcher to dispatch the dependent tables for installation before the + parent table is installed. + The SMBIOS_TABLE_DISPATCHER.Dependency[] field is used to establish the + dependency list. + Elements in the Dependency list are resolved by increasing index. However, + all orders are equivalent as: + - the Parent SMBIOS table will only be installed once all dependencies + have been satisfied. + - no cyclic dependency is allowed. + The dependency list is terminated by SMTT_NULL. + + The SMBIOS dispatcher dispatches the tables that have the default + order (OrderDef) set before the ordered SMBIOS tables are dispatched. + The SMBIOS_TABLE_DISPATCHER.Order field is used to establish the + dispatch order. + + The order specified in the SMBIOS dispatcher table must be unique for all + orders other than OrderDef. The dependency walk is only done for tables + that have the default dispatch order. + + @param [in] TableFactoryProtocol Pointer to the Table Factory Protocol + interface. + @param [in] CfgMgrProtocol Pointer to the Configuration Manager + Protocol Interface. + @param [in] SmbiosProtocol Pointer to the SMBIOS protocol. + @param [in] SmbiosTableInfo Pointer to the SMBIOS table Info. + @param [in] SmbiosTableCount Count of SMBIOS table info objects. + + @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. +**/ +EFI_STATUS +EFIAPI +DispatchSmbiosTables ( + IN CONST EDKII_DYNAMIC_TABLE_FACTORY_PROTOCOL *CONST TableFactoryProtocol, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, + IN EFI_SMBIOS_PROTOCOL *SmbiosProtocol, + IN CM_STD_OBJ_SMBIOS_TABLE_INFO *CONST SmbiosTableInfo, + IN CONST UINT32 SmbiosTableCount + ); + +#endif // SMBIOS_TABLE_DISPATCHER_H_ diff --git a/DynamicTablesPkg/DynamicTablesPkg.dec b/DynamicTablesPkg/DynamicTablesPkg.dec index 2b3ad163191..9fa7c780e76 100644 --- a/DynamicTablesPkg/DynamicTablesPkg.dec +++ b/DynamicTablesPkg/DynamicTablesPkg.dec @@ -64,6 +64,10 @@ # Maximum number of Custom DT Generators gEdkiiDynamicTablesPkgTokenSpaceGuid.PcdMaxCustomDTGenerators|1|UINT16|0xC0000003 + # Maximum number of Entries in the SMBIOS Handle Map + # Note that a larger value may degrade performance. + gEdkiiDynamicTablesPkgTokenSpaceGuid.PcdMaxSmbiosHandleMapEntries|255|UINT16|0xC0000004 + # Non BSA Compliant 16550 Serial HID gEdkiiDynamicTablesPkgTokenSpaceGuid.PcdNonBsaCompliant16550SerialHid|""|VOID*|0x40000008 diff --git a/DynamicTablesPkg/Include/Protocol/DynamicTableFactoryProtocol.h b/DynamicTablesPkg/Include/Protocol/DynamicTableFactoryProtocol.h index b11fc0c9f1d..3a24ee7a18c 100644 --- a/DynamicTablesPkg/Include/Protocol/DynamicTableFactoryProtocol.h +++ b/DynamicTablesPkg/Include/Protocol/DynamicTableFactoryProtocol.h @@ -239,6 +239,15 @@ typedef struct DynamicTableFactoryProtocol { EDKII_DYNAMIC_TABLE_FACTORY_DEREGISTER_DT_TABLE_GENERATOR DeregisterDtTableGenerator; + EDKII_DYNAMIC_TABLE_FACTORY_SMBIOS_TABLE_ADD_HANDLE + AddSmbiosHandle; + + EDKII_DYNAMIC_TABLE_FACTORY_SMBIOS_TABLE_GET_HANDLE + GetSmbiosHandle; + + EDKII_DYNAMIC_TABLE_FACTORY_SMBIOS_TABLE_GET_HANDLE_EX + GetSmbiosHandleEx; + /** Pointer to the data structure that holds the list of registered table generators */ diff --git a/DynamicTablesPkg/Include/SmbiosTableGenerator.h b/DynamicTablesPkg/Include/SmbiosTableGenerator.h index 934d56c90dd..ebe90da4f97 100644 --- a/DynamicTablesPkg/Include/SmbiosTableGenerator.h +++ b/DynamicTablesPkg/Include/SmbiosTableGenerator.h @@ -10,7 +10,7 @@ #define SMBIOS_TABLE_GENERATOR_H_ #include - +#include #include #pragma pack(1) @@ -127,68 +127,216 @@ typedef enum StdSmbiosTableGeneratorId { typedef struct ConfigurationManagerProtocol EDKII_CONFIGURATION_MANAGER_PROTOCOL; typedef struct CmStdObjSmbiosTableInfo CM_STD_OBJ_SMBIOS_TABLE_INFO; typedef struct SmbiosTableGenerator SMBIOS_TABLE_GENERATOR; +typedef struct DynamicTableFactoryProtocol EDKII_DYNAMIC_TABLE_FACTORY_PROTOCOL; +typedef UINTN CM_OBJECT_TOKEN; + +/** An array for holding a map of SMBIOS handles and the CM Object + token used to build the SMBIOS record for a given SMBIOS Table Generator. + This array is maintained by the Dynamic Table Factory Protocol and is + used by SMBIOS table generators to look up other SMBIOS table handles that + the Table being generated needs to reference. +**/ +typedef struct SmbiosHandleCmObjMap { + SMBIOS_TABLE_GENERATOR_ID SmbiosGeneratorId; + SMBIOS_HANDLE SmbiosTblHandle; + CM_OBJECT_TOKEN SmbiosCmToken; +} SMBIOS_HANDLE_MAP; /** This function pointer describes the interface to SMBIOS table build functions provided by the SMBIOS table generator and called by the Table Manager to build an SMBIOS table. - - @param [in] Generator Pointer to the SMBIOS table generator. - @param [in] SmbiosTableInfo Pointer to the SMBIOS table information. - @param [in] CfgMgrProtocol Pointer to the Configuration Manager - Protocol interface. - @param [out] Table Pointer to the generated SMBIOS table. + The function will return a pointer to the SMBIOS table and a pointer + to the CM_OBJECT_TOKEN of the CM_OBJECT that was used to build the + SMBIOS table. + + @param [in] Generator Pointer to the SMBIOS table generator. + @param [in] TableFactoryProtocol Pointer to the Dynamic TableFactory Protocol. + @param [in] SmbiosTableInfo Pointer to the SMBIOS table information. + @param [in] CfgMgrProtocol Pointer to the Configuration Manager + Protocol interface. + @param [out] Table Pointer to the generated SMBIOS table. + @param [out] CmObjToken Pointer to the CM_OBJECT_TOKEN + for the SMBIOS table. @return EFI_SUCCESS If the table is generated successfully or other failure codes as returned by the generator. **/ typedef EFI_STATUS (*SMBIOS_TABLE_GENERATOR_BUILD_TABLE) ( IN CONST SMBIOS_TABLE_GENERATOR *Generator, + IN CONST EDKII_DYNAMIC_TABLE_FACTORY_PROTOCOL *CONST TableFactoryProtocol, IN CM_STD_OBJ_SMBIOS_TABLE_INFO *CONST SmbiosTableInfo, IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, - OUT SMBIOS_STRUCTURE **Table + OUT SMBIOS_STRUCTURE **Table, + OUT CM_OBJECT_TOKEN *CmObjToken ); /** This function pointer describes the interface to used by the Table Manager to give the generator an opportunity to free any resources allocated for building the SMBIOS table. - @param [in] Generator Pointer to the SMBIOS table generator. - @param [in] SmbiosTableInfo Pointer to the SMBIOS table information. - @param [in] CfgMgrProtocol Pointer to the Configuration Manager - Protocol interface. - @param [in] Table Pointer to the generated SMBIOS table. + @param [in] Generator Pointer to the SMBIOS table generator. + @param [in] TableFactoryProtocol Pointer to the Dynamic TableFactory Protocol. + @param [in] SmbiosTableInfo Pointer to the SMBIOS table information. + @param [in] CfgMgrProtocol Pointer to the Configuration Manager + Protocol interface. + @param [in] Table Pointer to the generated SMBIOS table. @return EFI_SUCCESS If freed successfully or other failure codes as returned by the generator. **/ typedef EFI_STATUS (*SMBIOS_TABLE_GENERATOR_FREE_TABLE) ( IN CONST SMBIOS_TABLE_GENERATOR *Generator, + IN CONST EDKII_DYNAMIC_TABLE_FACTORY_PROTOCOL *CONST TableFactoryProtocol, IN CONST CM_STD_OBJ_SMBIOS_TABLE_INFO *CONST SmbiosTableInfo, IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, IN SMBIOS_STRUCTURE **Table ); +/** This function pointer describes an extended interface to build SMBIOS + tables. The SMBIOS Table Generator can build multiple tables and returns + a pointer to the list of SMBIOS tables and to a list of the CM_OBJECT_TOKEN + of the CM_OBJECTS that were used to generate the SMBIOS tables. + Use te FreeTableResourcesEx to free any resources that may have been + allocated using this interface. + + @param [in] Generator Pointer to the SMBIOS table generator. + @param [in] TableFactoryProtocol Pointer to the Dynamic TableFactory Protocol. + @param [in] SmbiosTableInfo Pointer to the SMBIOS table information. + @param [in] CfgMgrProtocol Pointer to the Configuration Manager + Protocol interface. + @param [out] Table Pointer to a list of generated SMBIOS table(s). + @param [out] CmObjToken Pointer to the CM_OBJECT_TOKEN for the + SMBIOS table. + @param [out] TableCount Number of generated SMBIOS table(s). + + @return EFI_SUCCESS If the table is generated successfully or other + failure codes as returned by the generator. +**/ +typedef EFI_STATUS (*SMBIOS_TABLE_GENERATOR_BUILD_TABLEEX) ( + IN CONST SMBIOS_TABLE_GENERATOR *Generator, + IN CONST EDKII_DYNAMIC_TABLE_FACTORY_PROTOCOL *CONST TableFactoryProtocol, + IN CM_STD_OBJ_SMBIOS_TABLE_INFO *CONST SmbiosTableInfo, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, + OUT SMBIOS_STRUCTURE ***Table, + OUT CM_OBJECT_TOKEN **CmObjectToken, + OUT UINTN *CONST TableCount + ); + +/** This function pointer describes the interface used by the + Table Manager to give the generator an opportunity to free + any resources allocated for building the SMBIOS table. This interface + must be used in conjunction with BuildSmbiosTableEx. + + @param [in] Generator Pointer to the SMBIOS table generator. + @param [in] TableFactoryProtocol Pointer to the Dynamic TableFactory Protocol. + @param [in] SmbiosTableInfo Pointer to the SMBIOS table information. + @param [in] CfgMgrProtocol Pointer to the Configuration Manager + Protocol interface. + @param [in] Table Pointer to the generated SMBIOS table. + @param [in] CmObjToken Pointer to the CM_OBJECT_TOKEN for the + SMBIOS table. + @param [in] TableCount Number of generated SMBIOS table(s). + + @return EFI_SUCCESS If freed successfully or other failure codes + as returned by the generator. +**/ +typedef EFI_STATUS (*SMBIOS_TABLE_GENERATOR_FREE_TABLEEX) ( + IN CONST SMBIOS_TABLE_GENERATOR *Generator, + IN CONST EDKII_DYNAMIC_TABLE_FACTORY_PROTOCOL *CONST TableFactoryProtocol, + IN CONST CM_STD_OBJ_SMBIOS_TABLE_INFO *CONST SmbiosTableInfo, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, + IN SMBIOS_STRUCTURE ***Table, + IN CM_OBJECT_TOKEN **CmObjectToken, + IN CONST UINTN TableCount + ); + +/** This function pointer describes the interface to used by the + Table Manager to give the generator an opportunity to add + an SMBIOS Handle. + + This function is called by the Dynamic Table Manager to add a newly added + SMBIOS Table OR it can be called by an SMBIOS Table generator to create + and add a new SMBIOS Handle if there is a reference to another table and + if there is a generator for that table that hasn't been called yet. + + @param [in] Smbios Pointer to the SMBIOS protocol. + @param [in] SmbiosHandle Pointer to an SMBIOS handle. + @param [in] CmObjectToken The CM Object token for that is used to generate + SMBIOS record. + @param [in] GeneratorId The SMBIOS table generator Id. + + @retval EFI_SUCCESS Success. + @retval EFI_OUT_OF_RESOURCES Unable to add the handle. + @retval EFI_NOT_FOUND The requested generator is not found + in the list of registered generators. +**/ +typedef EFI_STATUS (EFIAPI *EDKII_DYNAMIC_TABLE_FACTORY_SMBIOS_TABLE_ADD_HANDLE)( + IN EFI_SMBIOS_PROTOCOL *Smbios, + IN SMBIOS_HANDLE *SmbiosHandle, + IN CM_OBJECT_TOKEN CmObjectToken, + IN SMBIOS_TABLE_GENERATOR_ID GeneratorId + ); + +/** This function pointer describes the interface to used by the + Table Manager to give the generator an opportunity to find + an SMBIOS Handle. + + This function is called by the SMBIOS table generator to find an SMBIOS + handle needed as part of generating an SMBIOS Table. + + @param [in] CmObjectToken The CM Object token used to generate the SMBIOS + record. + + @retval EFI_SUCCESS Success. + @retval EFI_NOT_FOUND The requested generator is not found + in the list of registered generators. +**/ +typedef SMBIOS_HANDLE_MAP *(EFIAPI *EDKII_DYNAMIC_TABLE_FACTORY_SMBIOS_TABLE_GET_HANDLE)( + IN CM_OBJECT_TOKEN CmObjectToken + ); + +/** Find and return SMBIOS handle based on associated CM object token. + + @param [in] GeneratorId SMBIOS generator ID used to build the SMBIOS Table. + @param [in] CmObjectToken Token of the CM_OBJECT used to build the SMBIOS Table. + + @return SMBIOS handle of the table associated with SmbiosTableId and + CmObjectToken if found. Otherwise, returns 0xFFFF. +**/ +typedef SMBIOS_HANDLE (EFIAPI *EDKII_DYNAMIC_TABLE_FACTORY_SMBIOS_TABLE_GET_HANDLE_EX)( + IN SMBIOS_TABLE_GENERATOR_ID GeneratorId, + IN CM_OBJECT_TOKEN CmObjToken + ); + /** The SMBIOS_TABLE_GENERATOR structure provides an interface that the Table Manager can use to invoke the functions to build SMBIOS tables. */ typedef struct SmbiosTableGenerator { /// The SMBIOS table generator ID. - SMBIOS_TABLE_GENERATOR_ID GeneratorID; + SMBIOS_TABLE_GENERATOR_ID GeneratorID; /// String describing the DT table /// generator. - CONST CHAR16 *Description; + CONST CHAR16 *Description; /// The SMBIOS table type. - SMBIOS_TYPE Type; + SMBIOS_TYPE Type; /// SMBIOS table build function pointer. - SMBIOS_TABLE_GENERATOR_BUILD_TABLE BuildSmbiosTable; + SMBIOS_TABLE_GENERATOR_BUILD_TABLE BuildSmbiosTable; + + /** The function to free any resources + allocated for building the SMBIOS table. + */ + SMBIOS_TABLE_GENERATOR_FREE_TABLE FreeTableResources; + + /// SMBIOS table extended build function pointer. + SMBIOS_TABLE_GENERATOR_BUILD_TABLEEX BuildSmbiosTableEx; /** The function to free any resources allocated for building the SMBIOS table. */ - SMBIOS_TABLE_GENERATOR_FREE_TABLE FreeTableResources; + SMBIOS_TABLE_GENERATOR_FREE_TABLEEX FreeTableResourcesEx; } SMBIOS_TABLE_GENERATOR; /** Register SMBIOS table factory generator. @@ -229,6 +377,68 @@ DeregisterSmbiosTableGenerator ( IN CONST SMBIOS_TABLE_GENERATOR *CONST Generator ); +/** Add SMBIOS Handle. + + This function is called by the Dynamic Table Manager to add an entry for + the newly created SMBIOS Table handle and the CM_OBJECT_TOKEN of the CM_OBJECT + used to generate the table for a given SMBIOS generator to the SMBIOS Handle + Map maintained by the DynamicTable Factory. + + @param [in] Smbios Pointer to the SMBIOS protocol. + @param [in] SmbiosHandle Pointer to an SMBIOS handle. + @param [in] CmObjectToken The CM Object token for that is used to generate + SMBIOS record. + @param [in] GeneratorId The SMBIOS table generator Id. + + @retval EFI_SUCCESS Success. + @retval EFI_OUT_OF_RESOURCES Unable to add the handle. + @retval EFI_NOT_FOUND The requested generator is not found + in the list of registered generators. +**/ +EFI_STATUS +EFIAPI +AddSmbiosHandle ( + IN EFI_SMBIOS_PROTOCOL *Smbios, + IN SMBIOS_HANDLE *SmbiosHandle, + IN CM_OBJECT_TOKEN CmObjectToken, + IN SMBIOS_TABLE_GENERATOR_ID GeneratorId + ); + +/** Find SMBIOS Handle given the CM Object token used to generate the SMBIOS + record. + + This function is called by the SMBIOS table generator to find an SMBIOS + handle map to reference a different SMBIOS table. + + @param [in] CmObjectToken The CM Object token used to generate the SMBIOS + record. + + @retval EFI_SUCCESS Success. + @retval EFI_NOT_FOUND The requested generator is not found + in the list of registered generators. +**/ +SMBIOS_HANDLE_MAP * +EFIAPI +FindSmbiosHandle ( + IN CM_OBJECT_TOKEN CmObjectToken + ); + +/** Find and return SMBIOS handle for a given associated CM object token for + an SMBIOS Table Generator. + + @param [in] GeneratorId SMBIOS generator ID used to build the SMBIOS Table. + @param [in] CmObjectToken Token of the CM_OBJECT used to build the SMBIOS Table. + + @return SMBIOS handle of the table associated with SmbiosTableId and + CmObjectToken if found. Otherwise, returns 0xFFFF. +**/ +SMBIOS_HANDLE +EFIAPI +FindSmbiosHandleEx ( + IN SMBIOS_TABLE_GENERATOR_ID GeneratorId, + IN CM_OBJECT_TOKEN CmObjToken + ); + #pragma pack() #endif // SMBIOS_TABLE_GENERATOR_H_ diff --git a/DynamicTablesPkg/Include/StandardNameSpaceObjects.h b/DynamicTablesPkg/Include/StandardNameSpaceObjects.h index 8ec3238225a..c81efbc2377 100644 --- a/DynamicTablesPkg/Include/StandardNameSpaceObjects.h +++ b/DynamicTablesPkg/Include/StandardNameSpaceObjects.h @@ -40,6 +40,20 @@ **/ typedef UINTN CM_OBJECT_TOKEN; +/** + A type representing a SMBIOS structure/table type. + + Types 0 through 127 (7Fh) are reserved for and defined by the + SMBIOS specification. + Types 128 through 256 (80h to FFh) are available for system and + OEM-specific information. + + Note: This Dynamic SMBIOS table generation implementation defines + TableType FFh as a NULL table which is used by the Dynamic + SMBIOS table dispatcher to terminate the dependency sequence. +*/ +typedef UINT8 SMBIOS_TABLE_TYPE; + /** The ESTD_OBJECT_ID enum describes the Object IDs in the Standard Namespace. */ @@ -127,6 +141,9 @@ typedef struct CmAStdObjAcpiTableInfo { to NULL. */ typedef struct CmStdObjSmbiosTableInfo { + /// SMBIOS Structure/Table Type + SMBIOS_TABLE_TYPE TableType; + /// The SMBIOS Table Generator ID SMBIOS_TABLE_GENERATOR_ID TableGeneratorId; diff --git a/MdePkg/Include/IndustryStandard/SmBios.h b/MdePkg/Include/IndustryStandard/SmBios.h index 1fd85fef1a7..74b49fc3ff4 100644 --- a/MdePkg/Include/IndustryStandard/SmBios.h +++ b/MdePkg/Include/IndustryStandard/SmBios.h @@ -28,6 +28,14 @@ SPDX-License-Identifier: BSD-2-Clause-Patent /// #define SMBIOS_HANDLE_PI_RESERVED 0xFFFE +/// +/// Reference SMBIOS 3.6, chapter 6.1.2. +/// Unless otherwise specified, when referring to another structure’s handle, the value +/// 0FFFFh is used to indicate that the referenced handle is not applicable or does not +/// exist. +/// +#define SMBIOS_HANDLE_INVALID 0xFFFF + /// /// Reference SMBIOS 2.6, chapter 3.1.3. /// Each text string is limited to 64 significant characters due to system MIF limitations. diff --git a/Readme.md b/Readme.md new file mode 100644 index 00000000000..3031a896778 --- /dev/null +++ b/Readme.md @@ -0,0 +1,237 @@ +# Introduction + +**DynamicTablesPkg** currently supports Arm architecture, and we welcome the +adoption by other architectures. + +This branch will be used to: + - Reorganise the code to streamline adoption by other architectures. + - Introduce Dynamic Tables support for RISC-V architecture + - Integrate Dynamic SMBIOS support + () + +## Goals + - Streamline adoption by other architectures. + - Minimise the impact of migration for existing platforms + - Reuse common code + - Maintain flexibility across architectural components + +# Dynamic Tables Framework + +The dynamic tables framework is designed to generate standardised +firmware tables that describe the hardware information at +run-time. A goal of standardised firmware is to have a common +firmware for a platform capable of booting both Windows and Linux +operating systems. + +Traditionally the firmware tables are handcrafted using ACPI +Source Language (ASL), Table Definition Language (TDL) and +C-code. This approach can be error prone and involves time +consuming debugging. In addition, it may be desirable to configure +platform hardware at runtime such as: configuring the number of +cores available for use by the OS, or turning SoC features ON or +OFF. + +The dynamic tables framework simplifies this by providing a set +of standard table generators, that are implemented as libraries. +These generators query a platform specific component, the +'Configuration Manager', to collate the information required +for generating the tables at run-time. + +The framework also provides the ability to implement custom/OEM +generators; thereby facilitating support for custom tables. The +custom generators can also utilize the existing standard generators +and override any functionality if needed. + +The framework currently implements a set of standard ACPI table +generators for Arm architecture, these include both data tables +and ASL tables. The ASL generation includes support for both +fixup, where a template AML code is patched, and additionally +provides an API to parse, search, generate and serialise the +AML bytecode. + +Although, the set of standard generators implement the functionality +required for Arm architecture; the framework is extensible, and +support for other architectures can be added. + +## Branch Owners + + - Sami Mujawar + - Pierre Gondois + +## Feature Summary + +### Dynamic Tables framework supports + - ACPI data tables + - AML tables + * AML Template Fixup + * AML Code Generation + +The framework currently supports the following table generators for Arm: + * DBG2 - Debug Port Table 2 + * DSDT - Differentiated system description table. This is essentially + a RAW table generator. + * FADT - Fixed ACPI Description Table + * GTDT - Generic Timer Description Table + * IORT - IO Remapping Table + * MADT - Multiple APIC Description Table + * MCFG - PCI Express memory mapped configuration space base address + Description Table + * SPCR - Serial Port Console Redirection Table + * SSDT - Secondary System Description Table. This is essentially + a RAW table generator. + * PCCT - Platform Communications Channel Table. + * PPTT - Processor Properties Topology Table. + * SRAT - System Resource Affinity Table. + * SSDT-CMN600 - SSDT Table for Arm CoreLink CMN-600 Coherent Mesh Network. + * SSDT-Cpu-Topology - SSDT Table for describing the CPU hierarchy. + * SSDT-PCIe - SSDT Table describing the PCIe. + * SSDT-Serial-Port - SSDT Table describing the Serial ports. + +## SMBIOS Support + - A SMBIOS String table helper library has been provided. + - Initial patches to add SMBIOS support are available at: + * SMBIOS Dispatcher () + * SMBIOS Table generation (). + +# Roadmap + +1. See [Related Modules](#related-modules) section below for details of + staging repositories and branches to be used for prototyping. +2. The design aspects and changes shall be discussed on the mailing list + with patches to support the details. +3. A new section in DynamicTablesPkg\Readme.md shall be added to reflect + the design updates, e.g. changes to CM Objects, Namespace definitions, etc. +4. The design changes should typically be supported by patches for the + DynamicTables core framework and demonstrate the impact on the platform + code by typically providing patches for at least one existing + platform (possibly edk2-platforms/Platform/ARM/[Juno | FVP]). +5. The design changes should be small and typically be reflected in separate + patch series. +6. The first phase would be to partition the codebase into common code vs + architectural specific code. This would involve moving files and + reflecting the associated changes such that the build does not break. +7. Define a new namespace *ArchCommon* for the common architectural components. +8. Identify the CM_ARM_OBJECTs that can be moved to the *ArchCommon* namespace. + As part of this identify if any object needs to be dropped, + e.g. EArmObjReserved29 +9. Identify overlap of SMBIOS objects with existing CM Objects. +10. Submit patches to move CM objects from Arm Namespace to *ArchCommon* + Namespace. Ideally one object (and any dependencies) should be moved + at a time. +11. Submit patches to migrate upstream platforms that use DynamicTablesPkg +12. Define a new namespace for RISC-V specific objects +13. Submit patches for enabling RISC-V +14. In the next phase support for Dynamic SMBIOS can be enabled. + +## Note: +- Periodically rebase with edk2 & edk2-platforms master branch to sync + with latest changes. +- Merge *reorg* updates after point 11 above to edk2 & edk2-platforms master + branch. +- Similarly, the RISC-V support can be merged after point 13. + +# Related Modules + +## edk2-staging +The *dynamictables-reorg* branch in the **edk2-staging** repository +contains the updates to streamline the adoption of Dynamic Tables +Framework by other architectures. + +## edk2-platforms +The *devel-dynamictables-reorg* branch in the **edk2-platforms** repository +contains the platform specific changes. + +# Related Links + +Source Code Repositories for staging:
+ +### 1. edk2 codebase
+ Repo:
+ Branch: *dynamictables-reorg* + +### 2. edk2-platforms codebase
+ Repo:
+ Branch: *devel-dynamictables-reorg* + +# Impacted Platforms + +| Platform | Location | Description | Migration Status | Known Issues | +| :---- | :----- | :---- | :--- | :--- | +| Arm Virt Kvmtool | edk2/ArmVirtPkg/KvmtoolCfgMgrDxe | Arm Kvmtool Guest firmware | | | +| FVP | edk2-platforms/Platform/ARM/VExpressPkg | Arm Fixed Virtual Platform | | | +| Juno | edk2-platforms/Platform/ARM/JunoPkg | Arm Juno Software Development Platform | | | +| N1SDP | edk2-platforms/Platform/ARM/N1Sdp | Arm Neoverse N1 Software Development Platform | | | +| Morello FVP | edk2-platforms/Platform/ARM/Morello | Arm Morello Fixed Virtual Platform | | | +| Morello | edk2-platforms/Platform/ARM/Morello | Arm Morello Software Development Platform | | | +| LX2160A | edk2-platforms/Silicon/NXP/LX2160A | NXP LX2160A | | | + + +# Prerequisites + +Ensure that the latest ACPICA iASL compiler is used for building *Dynamic Tables Framework*.
+*Dynamic Tables Framework* has been tested using the following iASL compiler version:
+ACPICA iASL compiler [Version 20230628](https://www.acpica.org/node/183), dated 28 June, 2023. + +# Build Instructions + +1. Set path for the iASL compiler. + +2. Set PACKAGES_PATH to point to the locations of the following repositories: + +Example: + +> set PACKAGES_PATH=%CD%\edk2;%CD%\edk2-platforms;%CD%\edk2-non-osi + + or + +> export PACKAGES_PATH=$PWD/edk2:$PWD/edk2-platforms:$PWD/edk2-non-osi + +3. To enable Dynamic tables framework the *'DYNAMIC_TABLES_FRAMEWORK'* +option must be defined for some platforms that support both traditional +ACPI tables as well as Dynamic Table generation. This can be passed as +a command line parameter to the edk2 build system. + +Example: + +Juno supports both traditional and dynamic ACPI tables. +>build -a AARCH64 -p Platform\ARM\JunoPkg\ArmJuno.dsc + -t GCC5 **-D DYNAMIC_TABLES_FRAMEWORK** + +or +FVP only supports dynamic ACPI table generation, so the preprocessor +flag is not required for the build. +>build -a AARCH64 -p Platform\ARM\VExpressPkg\ArmVExpress-FVP-AArch64.dsc + -t GCC5 + +# Documentation + +The documentation for the Dynamic Tables Framework is available at +DynamicTablesPkg\Readme.md. Additionally, Doxygen style documentation +is used in the code. + +# Guidelines for submitting patches + +1. Follow the standard edk2 coding guidelines for preparing patches.
+ The edk2-staging guidelines can be found at + + +2. To submit a patch for edk2-staging repo include the branch name in + the subject line of the commit message.
+ e.g. **[staging/dynamictables-reorg PATCH v<*n*> ]: Package/Module: Subject** + +3. To submit a patch for edk2-platforms staging repo include the branch + name in the subject line of the commit message.
+ e.g. **[platforms/devel-dynamictables-reorg PATCH v<*n*> ]: Package/Module: Subject** + + +# Stakeholders/Distribution List + + Please send a patch if you wished to be added/removed from the distribution + list below. + + - Sami Mujawar + - Pierre Gondois + - Yeo Reum Yun + +# Miscellaneous +