public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* Re: [edk2-devel] [PATCH v2 1/1] DynamicTablesPkg: Add SMBIOS table generation
       [not found] <173E4FD875129A15.17319@groups.io>
@ 2023-02-21 15:36 ` Girish Mahadevan
  0 siblings, 0 replies; only message in thread
From: Girish Mahadevan @ 2023-02-21 15:36 UTC (permalink / raw)
  To: devel, sami.mujawar, Alexei.Fedorov, pierre.gondois
  Cc: jbrasen, ashishsingha, nramirez

Hello Sami,

Mind taking a quick look whenever you have some bandwidth.

Thanks
Girish

On 1/27/2023 4:58 PM, Girish Mahadevan via groups.io wrote:
> External email: Use caution opening links or attachments
> 
> 
> Add the SMBIOS Table generator code to the DynamicTablesPkg.
> 
> This change includes adding new logic to the DynamicTableManager
> to process and add SMBIOS tables and augmenting the existing SMBIOS
> Factory generator to include installing multiple SMBIOS tables .
> Also included is running the SMBIOS and ACPI table generation as part
> of the SMBIOS and ACPI protocol GUID callback notifications respectively.
> 
> The change can be seen at
> https://github.com/gmahadevan/edk2-upstream/commits/RFC/smbios-dyntables
> 
> Signed-off-by: Girish Mahadevan <gmahadevan@nvidia.com>
> Reviewed-by: Jeff Brasen <jbrasen@nvidia.com>
> ---
>   .../DynamicTableFactory.h                     |   5 +
>   .../DynamicTableFactoryDxe.c                  |   7 +
>   .../SmbiosTableFactory/SmbiosTableFactory.c   |  66 ++
>   .../DynamicTableManagerDxe/AcpiTableBuilder.c | 732 ++++++++++++++++
>   .../DynamicTableManagerDxe.c                  | 794 +-----------------
>   .../DynamicTableManagerDxe.inf                |   5 +-
>   .../SmbiosTableBuilder.c                      | 608 ++++++++++++++
>   .../Include/ConfigurationManagerObject.h      |  18 +-
>   .../Protocol/DynamicTableFactoryProtocol.h    |   8 +
>   .../Include/SmbiosTableGenerator.h            | 165 +++-
>   10 files changed, 1653 insertions(+), 755 deletions(-)
>   create mode 100644 DynamicTablesPkg/Drivers/DynamicTableManagerDxe/AcpiTableBuilder.c
>   create mode 100644 DynamicTablesPkg/Drivers/DynamicTableManagerDxe/SmbiosTableBuilder.c
> 
> diff --git a/DynamicTablesPkg/Drivers/DynamicTableFactoryDxe/DynamicTableFactory.h b/DynamicTablesPkg/Drivers/DynamicTableFactoryDxe/DynamicTableFactory.h
> index b160dcf8ad..20e438ea70 100644
> --- a/DynamicTablesPkg/Drivers/DynamicTableFactoryDxe/DynamicTableFactory.h
> +++ b/DynamicTablesPkg/Drivers/DynamicTableFactoryDxe/DynamicTableFactory.h
> @@ -49,6 +49,11 @@ 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[MAX_SMBIOS_HANDLES];
>   } 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 6d6d3fa746..d0ee5d7b3b 100644
> --- a/DynamicTablesPkg/Drivers/DynamicTableFactoryDxe/DynamicTableFactoryDxe.c
> +++ b/DynamicTablesPkg/Drivers/DynamicTableFactoryDxe/DynamicTableFactoryDxe.c
> @@ -44,6 +44,8 @@ EDKII_DYNAMIC_TABLE_FACTORY_PROTOCOL  DynamicTableFactoryProtocol = {
>     GetDtTableGenerator,
>     RegisterDtTableGenerator,
>     DeregisterDtTableGenerator,
> +  AddSmbiosHandle,
> +  FindSmbiosHandle,
>     &TableFactoryInfo
>   };
> 
> @@ -65,7 +67,12 @@ DynamicTableFactoryDxeInitialize (
>     )
>   {
>     EFI_STATUS  Status;
> +  UINTN       Idx;
> 
> +  for (Idx = 0; Idx < MAX_SMBIOS_HANDLES; Idx++) {
> +    TableFactoryInfo.SmbiosHandleMap[Idx].SmbiosTblHandle = SMBIOS_HANDLE_PI_RESERVED;
> +    TableFactoryInfo.SmbiosHandleMap[Idx].SmbiosCmToken = 0;
> +  }
>     Status = gBS->InstallProtocolInterface (
>                     &ImageHandle,
>                     &gEdkiiDynamicTableFactoryProtocolGuid,
> diff --git a/DynamicTablesPkg/Drivers/DynamicTableFactoryDxe/SmbiosTableFactory/SmbiosTableFactory.c b/DynamicTablesPkg/Drivers/DynamicTableFactoryDxe/SmbiosTableFactory/SmbiosTableFactory.c
> index 87795919f8..b81724d2a0 100644
> --- a/DynamicTablesPkg/Drivers/DynamicTableFactoryDxe/SmbiosTableFactory/SmbiosTableFactory.c
> +++ b/DynamicTablesPkg/Drivers/DynamicTableFactoryDxe/SmbiosTableFactory/SmbiosTableFactory.c
> @@ -12,6 +12,7 @@
>   #include <IndustryStandard/SmBios.h>
>   #include <Library/BaseLib.h>
>   #include <Library/BaseMemoryLib.h>
> +#include <Library/MemoryAllocationLib.h>
>   #include <Library/DebugLib.h>
> 
>   // Module specific include files.
> @@ -24,6 +25,71 @@
> 
>   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, if the value SMBIOS_HANDLE_PI_RESERVED
> +                              is passed then a new SmbiosHandle is assigned.
> +  @param [in]  CmObjectToken  CmObjectToken of the CM_OBJECT used to build the SMBIOS Table
> +  @param [in]  SmbiosId       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 ESTD_SMBIOS_TABLE_ID  SmbiosId
> +  )
> +{
> +  EFI_STATUS  Status;
> +  UINTN       Index;
> +
> +  Status = EFI_OUT_OF_RESOURCES;
> +
> +  for (Index = 0; Index < MAX_SMBIOS_HANDLES; Index++) {
> +    if (TableFactoryInfo.SmbiosHandleMap[Index].SmbiosTblHandle == SMBIOS_HANDLE_PI_RESERVED) {
> +      TableFactoryInfo.SmbiosHandleMap[Index].SmbiosTblHandle = *SmbiosHandle;
> +      TableFactoryInfo.SmbiosHandleMap[Index].SmbiosCmToken   = CmObjectToken;
> +      TableFactoryInfo.SmbiosHandleMap[Index].SmbiosTableId   = SmbiosId;
> +      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 < MAX_SMBIOS_HANDLES; 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.
> diff --git a/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/AcpiTableBuilder.c b/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/AcpiTableBuilder.c
> new file mode 100644
> index 0000000000..5021eab748
> --- /dev/null
> +++ b/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/AcpiTableBuilder.c
> @@ -0,0 +1,732 @@
> +/** @file
> +  Dynamic Table Manager Dxe
> +
> +  Copyright (c) 2017 - 2019, ARM Limited. All rights reserved.
> +  Copyright (c) 2022 - 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include <Library/DebugLib.h>
> +#include <Library/UefiLib.h>
> +#include <Library/PcdLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Protocol/AcpiTable.h>
> +#include <Library/BaseMemoryLib.h>
> +
> +// Module specific include files.
> +#include <AcpiTableGenerator.h>
> +#include <ConfigurationManagerObject.h>
> +#include <ConfigurationManagerHelper.h>
> +#include <DeviceTreeTableGenerator.h>
> +#include <Library/TableHelperLib.h>
> +#include <Protocol/ConfigurationManagerProtocol.h>
> +#include <Protocol/DynamicTableFactoryProtocol.h>
> +
> +/** 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.
> +**/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +VerifyMandatoryTablesArePresent (
> +  IN CONST CM_STD_OBJ_ACPI_TABLE_INFO  *CONST  AcpiTableInfo,
> +  IN       UINT32                              AcpiTableCount
> +  )
> +{
> +  EFI_STATUS  Status;
> +  BOOLEAN     FadtFound;
> +  BOOLEAN     MadtFound;
> +  BOOLEAN     GtdtFound;
> +  BOOLEAN     DsdtFound;
> +  BOOLEAN     Dbg2Found;
> +  BOOLEAN     SpcrFound;
> +
> +  Status    = EFI_SUCCESS;
> +  FadtFound = FALSE;
> +  MadtFound = FALSE;
> +  GtdtFound = FALSE;
> +  DsdtFound = FALSE;
> +  Dbg2Found = FALSE;
> +  SpcrFound = FALSE;
> +  ASSERT (AcpiTableInfo != NULL);
> +
> +  while (AcpiTableCount-- != 0) {
> +    switch (AcpiTableInfo[AcpiTableCount].AcpiTableSignature) {
> +      case EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE:
> +        FadtFound = TRUE;
> +        break;
> +      case EFI_ACPI_6_2_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE:
> +        MadtFound = TRUE;
> +        break;
> +      case EFI_ACPI_6_2_GENERIC_TIMER_DESCRIPTION_TABLE_SIGNATURE:
> +        GtdtFound = TRUE;
> +        break;
> +      case EFI_ACPI_6_2_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:
> +        DsdtFound = TRUE;
> +        break;
> +      case EFI_ACPI_6_2_DEBUG_PORT_2_TABLE_SIGNATURE:
> +        Dbg2Found = TRUE;
> +        break;
> +      case EFI_ACPI_6_2_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE:
> +        SpcrFound = TRUE;
> +        break;
> +      default:
> +        break;
> +    }
> +  }
> +
> +  // We need at least the FADT, MADT, GTDT and the DSDT tables to boot
> +  if (!FadtFound) {
> +    DEBUG ((DEBUG_ERROR, "ERROR: FADT Table not found\n"));
> +    Status = EFI_NOT_FOUND;
> +  }
> +
> +  if (!MadtFound) {
> +    DEBUG ((DEBUG_ERROR, "ERROR: MADT Table not found.\n"));
> +    Status = EFI_NOT_FOUND;
> +  }
> +
> +  if (!GtdtFound) {
> +    DEBUG ((DEBUG_ERROR, "ERROR: GTDT Table not found.\n"));
> +    Status = EFI_NOT_FOUND;
> +  }
> +
> +  if (!DsdtFound) {
> +    DEBUG ((DEBUG_ERROR, "ERROR: DSDT Table not found.\n"));
> +    Status = EFI_NOT_FOUND;
> +  }
> +
> +  if (!Dbg2Found) {
> +    DEBUG ((DEBUG_WARN, "WARNING: DBG2 Table not found.\n"));
> +  }
> +
> +  if (!SpcrFound) {
> +    DEBUG ((DEBUG_WARN, "WARNING: SPCR Table not found.\n"));
> +  }
> +
> +  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.
> +**/
> +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 find mandatory ACPI Table(s)."
> +      " Status = %r\n",
> +      Status
> +      ));
> +    return Status;
> +  }
> +
> +  // Add the FADT Table first.
> +  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;
> +}
> +
> +/** Callback Function for Smbios table generation.
> +
> +  Callback function when SMBIOS protocol is installed, this function will then
> +  invoke the code to install the available SMBIOS tables.
> +
> +  @param  Event
> +  @param  Context
> +
> +  @retval None.
> +**/
> +VOID
> +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 = ProcessAcpiTables (TableFactoryProtocol, CfgMgrProtocol);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: ACPI Table processing failure. Status = %r\n",
> +      Status
> +      ));
> +  }
> +}
> diff --git a/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableManagerDxe.c b/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableManagerDxe.c
> index 1e9b811c40..242c40be3b 100644
> --- a/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableManagerDxe.c
> +++ b/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableManagerDxe.c
> @@ -2,704 +2,39 @@
>     Dynamic Table Manager Dxe
> 
>     Copyright (c) 2017 - 2019, ARM Limited. All rights reserved.
> +  Copyright (c) 2022 - 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
> 
>     SPDX-License-Identifier: BSD-2-Clause-Patent
> 
>   **/
> 
>   #include <Library/DebugLib.h>
> +#include <Library/UefiLib.h>
>   #include <Library/PcdLib.h>
>   #include <Library/UefiBootServicesTableLib.h>
> -#include <Protocol/AcpiSystemDescriptionTable.h>
> -#include <Protocol/AcpiTable.h>
> 
>   // Module specific include files.
> -#include <AcpiTableGenerator.h>
>   #include <ConfigurationManagerObject.h>
>   #include <ConfigurationManagerHelper.h>
> -#include <DeviceTreeTableGenerator.h>
>   #include <Library/TableHelperLib.h>
>   #include <Protocol/ConfigurationManagerProtocol.h>
> -#include <Protocol/DynamicTableFactoryProtocol.h>
> -#include <SmbiosTableGenerator.h>
> 
> -///
> -/// Bit definitions for acceptable ACPI table presence formats.
> -/// Currently only ACPI tables present in the ACPI info list and
> -/// already installed will count towards "Table Present" during
> -/// verification routine.
> -///
> -#define ACPI_TABLE_PRESENT_INFO_LIST  BIT0
> -#define ACPI_TABLE_PRESENT_INSTALLED  BIT1
> +STATIC VOID  *AcpiTableProtocolRegistration;
> +STATIC VOID  *SmbiosProtocolRegistration;
> 
> -///
> -/// Order of ACPI table being verified during presence inspection.
> -///
> -#define ACPI_TABLE_VERIFY_FADT   0
> -#define ACPI_TABLE_VERIFY_MADT   1
> -#define ACPI_TABLE_VERIFY_GTDT   2
> -#define ACPI_TABLE_VERIFY_DSDT   3
> -#define ACPI_TABLE_VERIFY_DBG2   4
> -#define ACPI_TABLE_VERIFY_SPCR   5
> -#define ACPI_TABLE_VERIFY_COUNT  6
> +extern
> +VOID
> +SmbiosProtocolReady (
> +  IN  EFI_EVENT  Event,
> +  IN  VOID       *Context
> +  );
> 
> -///
> -/// Private data structure to verify the presence of mandatory
> -/// or optional ACPI tables.
> -///
> -typedef struct {
> -  /// ESTD ID for the ACPI table of interest.
> -  ESTD_ACPI_TABLE_ID    EstdTableId;
> -  /// Standard UINT32 ACPI signature.
> -  UINT32                AcpiTableSignature;
> -  /// 4 character ACPI table name (the 5th char8 is for null terminator).
> -  CHAR8                 AcpiTableName[sizeof (UINT32) + 1];
> -  /// Indicator on whether the ACPI table is required.
> -  BOOLEAN               IsMandatory;
> -  /// Formats of verified presences, as defined by ACPI_TABLE_PRESENT_*
> -  /// This field should be initialized to 0 and will be populated during
> -  /// verification routine.
> -  UINT16                Presence;
> -} ACPI_TABLE_PRESENCE_INFO;
> -
> -///
> -/// We require the FADT, MADT, GTDT and the DSDT tables to boot.
> -/// This list also include optional ACPI tables: DBG2, SPCR.
> -///
> -ACPI_TABLE_PRESENCE_INFO  mAcpiVerifyTables[ACPI_TABLE_VERIFY_COUNT] = {
> -  { EStdAcpiTableIdFadt, EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE,            "FADT", TRUE,  0 },
> -  { EStdAcpiTableIdMadt, EFI_ACPI_6_2_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE,         "MADT", TRUE,  0 },
> -  { EStdAcpiTableIdGtdt, EFI_ACPI_6_2_GENERIC_TIMER_DESCRIPTION_TABLE_SIGNATURE,         "GTDT", TRUE,  0 },
> -  { EStdAcpiTableIdDsdt, EFI_ACPI_6_2_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE, "DSDT", TRUE,  0 },
> -  { EStdAcpiTableIdDbg2, EFI_ACPI_6_2_DEBUG_PORT_2_TABLE_SIGNATURE,                      "DBG2", FALSE, 0 },
> -  { EStdAcpiTableIdSpcr, EFI_ACPI_6_2_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE,   "SPCR", FALSE, 0 },
> -};
> -
> -/** This macro expands to a function that retrieves the ACPI Table
> -    List from the Configuration Manager.
> -*/
> -GET_OBJECT_LIST (
> -  EObjNameSpaceStandard,
> -  EStdObjAcpiTableList,
> -  CM_STD_OBJ_ACPI_TABLE_INFO
> -  )
> -
> -/** A helper function to build and install a single ACPI table.
> -
> -  This is a helper function that invokes the Table generator interface
> -  for building an ACPI table. It uses the AcpiTableProtocol to install the
> -  table, then frees the resources allocated for generating it.
> -
> -  @param [in]  TableFactoryProtocol Pointer to the Table Factory Protocol
> -                                    interface.
> -  @param [in]  CfgMgrProtocol       Pointer to the Configuration Manager
> -                                    Protocol Interface.
> -  @param [in]  Generator            Pointer to the AcpiTable generator.
> -  @param [in]  AcpiTableProtocol    Pointer to the AcpiTable protocol.
> -  @param [in]  AcpiTableInfo        Pointer to the ACPI table Info.
> -
> -  @retval EFI_SUCCESS           Success.
> -  @retval EFI_INVALID_PARAMETER A parameter is invalid.
> -  @retval EFI_NOT_FOUND         Required object is not found.
> -  @retval EFI_BAD_BUFFER_SIZE   Size returned by the Configuration Manager
> -                                is less than the Object size for the
> -                                requested object.
> -**/
> -STATIC
> -EFI_STATUS
> -EFIAPI
> -BuildAndInstallSingleAcpiTable (
> -  IN CONST EDKII_DYNAMIC_TABLE_FACTORY_PROTOCOL  *CONST  TableFactoryProtocol,
> -  IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL  *CONST  CfgMgrProtocol,
> -  IN CONST ACPI_TABLE_GENERATOR                  *CONST  Generator,
> -  IN       EFI_ACPI_TABLE_PROTOCOL                       *AcpiTableProtocol,
> -  IN CONST CM_STD_OBJ_ACPI_TABLE_INFO            *CONST  AcpiTableInfo
> -  )
> -{
> -  EFI_STATUS                   Status;
> -  EFI_STATUS                   Status1;
> -  EFI_ACPI_DESCRIPTION_HEADER  *AcpiTable;
> -  UINTN                        TableHandle;
> -
> -  AcpiTable = NULL;
> -  Status    = Generator->BuildAcpiTable (
> -                           Generator,
> -                           AcpiTableInfo,
> -                           CfgMgrProtocol,
> -                           &AcpiTable
> -                           );
> -  if (EFI_ERROR (Status)) {
> -    DEBUG ((
> -      DEBUG_ERROR,
> -      "ERROR: Failed to Build Table." \
> -      " TableGeneratorId = 0x%x. Status = %r\n",
> -      AcpiTableInfo->TableGeneratorId,
> -      Status
> -      ));
> -    // Free any allocated resources.
> -    goto exit_handler;
> -  }
> -
> -  if (AcpiTable == NULL) {
> -    Status = EFI_NOT_FOUND;
> -    goto exit_handler;
> -  }
> -
> -  // Dump ACPI Table Header
> -  DUMP_ACPI_TABLE_HEADER (AcpiTable);
> -
> -  // Install ACPI table
> -  Status = AcpiTableProtocol->InstallAcpiTable (
> -                                AcpiTableProtocol,
> -                                AcpiTable,
> -                                AcpiTable->Length,
> -                                &TableHandle
> -                                );
> -  if (EFI_ERROR (Status)) {
> -    DEBUG ((
> -      DEBUG_ERROR,
> -      "ERROR: Failed to Install ACPI Table. Status = %r\n",
> -      Status
> -      ));
> -    // Free any allocated resources.
> -    goto exit_handler;
> -  }
> -
> -  DEBUG ((
> -    DEBUG_INFO,
> -    "INFO: ACPI Table installed. Status = %r\n",
> -    Status
> -    ));
> -
> -exit_handler:
> -  // Free any resources allocated for generating the tables.
> -  if (Generator->FreeTableResources != NULL) {
> -    Status1 = Generator->FreeTableResources (
> -                           Generator,
> -                           AcpiTableInfo,
> -                           CfgMgrProtocol,
> -                           &AcpiTable
> -                           );
> -    if (EFI_ERROR (Status1)) {
> -      DEBUG ((
> -        DEBUG_ERROR,
> -        "ERROR: Failed to Free Table Resources." \
> -        "TableGeneratorId = 0x%x. Status = %r\n",
> -        AcpiTableInfo->TableGeneratorId,
> -        Status1
> -        ));
> -    }
> -
> -    // Return the first error status in case of failure
> -    if (!EFI_ERROR (Status)) {
> -      Status = Status1;
> -    }
> -  }
> -
> -  return Status;
> -}
> -
> -/** A helper function to build and install multiple ACPI tables.
> -
> -  This is a helper function that invokes the Table generator interface
> -  for building an ACPI table. It uses the AcpiTableProtocol to install the
> -  table, then frees the resources allocated for generating it.
> -
> -  @param [in]  TableFactoryProtocol Pointer to the Table Factory Protocol
> -                                    interface.
> -  @param [in]  CfgMgrProtocol       Pointer to the Configuration Manager
> -                                    Protocol Interface.
> -  @param [in]  Generator            Pointer to the AcpiTable generator.
> -  @param [in]  AcpiTableProtocol    Pointer to the AcpiTable protocol.
> -  @param [in]  AcpiTableInfo        Pointer to the ACPI table Info.
> -
> -  @retval EFI_SUCCESS           Success.
> -  @retval EFI_INVALID_PARAMETER A parameter is invalid.
> -  @retval EFI_NOT_FOUND         Required object is not found.
> -  @retval EFI_BAD_BUFFER_SIZE   Size returned by the Configuration Manager
> -                                is less than the Object size for the
> -                                requested object.
> -**/
> -STATIC
> -EFI_STATUS
> -EFIAPI
> -BuildAndInstallMultipleAcpiTable (
> -  IN CONST EDKII_DYNAMIC_TABLE_FACTORY_PROTOCOL  *CONST  TableFactoryProtocol,
> -  IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL  *CONST  CfgMgrProtocol,
> -  IN CONST ACPI_TABLE_GENERATOR                  *CONST  Generator,
> -  IN       EFI_ACPI_TABLE_PROTOCOL                       *AcpiTableProtocol,
> -  IN CONST CM_STD_OBJ_ACPI_TABLE_INFO            *CONST  AcpiTableInfo
> -  )
> -{
> -  EFI_STATUS                   Status;
> -  EFI_STATUS                   Status1;
> -  EFI_ACPI_DESCRIPTION_HEADER  **AcpiTable;
> -  UINTN                        TableCount;
> -  UINTN                        TableHandle;
> -  UINTN                        Index;
> -
> -  AcpiTable  = NULL;
> -  TableCount = 0;
> -  Status     = Generator->BuildAcpiTableEx (
> -                            Generator,
> -                            AcpiTableInfo,
> -                            CfgMgrProtocol,
> -                            &AcpiTable,
> -                            &TableCount
> -                            );
> -  if (EFI_ERROR (Status)) {
> -    DEBUG ((
> -      DEBUG_ERROR,
> -      "ERROR: Failed to Build Table." \
> -      " TableGeneratorId = 0x%x. Status = %r\n",
> -      AcpiTableInfo->TableGeneratorId,
> -      Status
> -      ));
> -    // Free any allocated resources.
> -    goto exit_handler;
> -  }
> -
> -  if ((AcpiTable == NULL) || (TableCount == 0)) {
> -    Status = EFI_NOT_FOUND;
> -    goto exit_handler;
> -  }
> -
> -  for (Index = 0; Index < TableCount; Index++) {
> -    // Dump ACPI Table Header
> -    DUMP_ACPI_TABLE_HEADER (AcpiTable[Index]);
> -    // Install ACPI table
> -    Status = AcpiTableProtocol->InstallAcpiTable (
> -                                  AcpiTableProtocol,
> -                                  AcpiTable[Index],
> -                                  AcpiTable[Index]->Length,
> -                                  &TableHandle
> -                                  );
> -    if (EFI_ERROR (Status)) {
> -      DEBUG ((
> -        DEBUG_ERROR,
> -        "ERROR: Failed to Install ACPI Table. Status = %r\n",
> -        Status
> -        ));
> -      // Free any allocated resources.
> -      goto exit_handler;
> -    }
> -
> -    DEBUG ((
> -      DEBUG_INFO,
> -      "INFO: ACPI Table installed. Status = %r\n",
> -      Status
> -      ));
> -  }
> -
> -exit_handler:
> -  // Free any resources allocated for generating the tables.
> -  if (Generator->FreeTableResourcesEx != NULL) {
> -    Status1 = Generator->FreeTableResourcesEx (
> -                           Generator,
> -                           AcpiTableInfo,
> -                           CfgMgrProtocol,
> -                           &AcpiTable,
> -                           TableCount
> -                           );
> -    if (EFI_ERROR (Status1)) {
> -      DEBUG ((
> -        DEBUG_ERROR,
> -        "ERROR: Failed to Free Table Resources." \
> -        "TableGeneratorId = 0x%x. Status = %r\n",
> -        AcpiTableInfo->TableGeneratorId,
> -        Status1
> -        ));
> -    }
> -
> -    // Return the first error status in case of failure
> -    if (!EFI_ERROR (Status)) {
> -      Status = Status1;
> -    }
> -  }
> -
> -  return Status;
> -}
> -
> -/** A helper function to invoke a Table generator
> -
> -  This is a helper function that invokes the Table generator interface
> -  for building an ACPI table. It uses the AcpiTableProtocol to install the
> -  table, then frees the resources allocated for generating it.
> -
> -  @param [in]  TableFactoryProtocol Pointer to the Table Factory Protocol
> -                                    interface.
> -  @param [in]  CfgMgrProtocol       Pointer to the Configuration Manager
> -                                    Protocol Interface.
> -  @param [in]  AcpiTableProtocol    Pointer to the AcpiTable protocol.
> -  @param [in]  AcpiTableInfo        Pointer to the ACPI table Info.
> -
> -  @retval EFI_SUCCESS           Success.
> -  @retval EFI_INVALID_PARAMETER A parameter is invalid.
> -  @retval EFI_NOT_FOUND         Required object is not found.
> -  @retval EFI_BAD_BUFFER_SIZE   Size returned by the Configuration Manager
> -                                is less than the Object size for the
> -                                requested object.
> -**/
> -STATIC
> -EFI_STATUS
> -EFIAPI
> -BuildAndInstallAcpiTable (
> -  IN CONST EDKII_DYNAMIC_TABLE_FACTORY_PROTOCOL  *CONST  TableFactoryProtocol,
> -  IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL  *CONST  CfgMgrProtocol,
> -  IN       EFI_ACPI_TABLE_PROTOCOL                       *AcpiTableProtocol,
> -  IN CONST CM_STD_OBJ_ACPI_TABLE_INFO            *CONST  AcpiTableInfo
> -  )
> -{
> -  EFI_STATUS                  Status;
> -  CONST ACPI_TABLE_GENERATOR  *Generator;
> -
> -  ASSERT (TableFactoryProtocol != NULL);
> -  ASSERT (CfgMgrProtocol != NULL);
> -  ASSERT (AcpiTableProtocol != NULL);
> -  ASSERT (AcpiTableInfo != NULL);
> -
> -  DEBUG ((
> -    DEBUG_INFO,
> -    "INFO: EStdObjAcpiTableList: Address = 0x%p," \
> -    " TableGeneratorId = 0x%x\n",
> -    AcpiTableInfo,
> -    AcpiTableInfo->TableGeneratorId
> -    ));
> -
> -  Generator = NULL;
> -  Status    = TableFactoryProtocol->GetAcpiTableGenerator (
> -                                      TableFactoryProtocol,
> -                                      AcpiTableInfo->TableGeneratorId,
> -                                      &Generator
> -                                      );
> -  if (EFI_ERROR (Status)) {
> -    DEBUG ((
> -      DEBUG_ERROR,
> -      "ERROR: Table Generator not found." \
> -      " TableGeneratorId = 0x%x. Status = %r\n",
> -      AcpiTableInfo->TableGeneratorId,
> -      Status
> -      ));
> -    return Status;
> -  }
> -
> -  if (Generator == NULL) {
> -    return EFI_NOT_FOUND;
> -  }
> -
> -  DEBUG ((
> -    DEBUG_INFO,
> -    "INFO: Generator found : %s\n",
> -    Generator->Description
> -    ));
> -
> -  if (Generator->BuildAcpiTableEx != NULL) {
> -    Status = BuildAndInstallMultipleAcpiTable (
> -               TableFactoryProtocol,
> -               CfgMgrProtocol,
> -               Generator,
> -               AcpiTableProtocol,
> -               AcpiTableInfo
> -               );
> -    if (EFI_ERROR (Status)) {
> -      DEBUG ((
> -        DEBUG_ERROR,
> -        "ERROR: Failed to find build and install ACPI Table." \
> -        " Status = %r\n",
> -        Status
> -        ));
> -    }
> -  } else if (Generator->BuildAcpiTable != NULL) {
> -    Status = BuildAndInstallSingleAcpiTable (
> -               TableFactoryProtocol,
> -               CfgMgrProtocol,
> -               Generator,
> -               AcpiTableProtocol,
> -               AcpiTableInfo
> -               );
> -    if (EFI_ERROR (Status)) {
> -      DEBUG ((
> -        DEBUG_ERROR,
> -        "ERROR: Failed to find build and install ACPI Table." \
> -        " Status = %r\n",
> -        Status
> -        ));
> -    }
> -  } else {
> -    Status = EFI_INVALID_PARAMETER;
> -    DEBUG ((
> -      DEBUG_ERROR,
> -      "ERROR: Table Generator does not implement the" \
> -      " ACPI_TABLE_GENERATOR_BUILD_TABLE interface." \
> -      " TableGeneratorId = 0x%x. Status = %r\n",
> -      AcpiTableInfo->TableGeneratorId,
> -      Status
> -      ));
> -  }
> -
> -  return Status;
> -}
> -
> -/** The function checks if the Configuration Manager has provided the
> -    mandatory ACPI tables for installation.
> -
> -  @param [in]  AcpiTableInfo      Pointer to the ACPI Table Info list.
> -  @param [in]  AcpiTableCount     Count of ACPI Table Info.
> -
> -  @retval EFI_SUCCESS           Success.
> -  @retval EFI_NOT_FOUND         If mandatory table is not found.
> -  @retval EFI_ALREADY_STARTED   If mandatory table found in AcpiTableInfo is already installed.
> -**/
> -STATIC
> -EFI_STATUS
> -EFIAPI
> -VerifyMandatoryTablesArePresent (
> -  IN CONST CM_STD_OBJ_ACPI_TABLE_INFO  *CONST  AcpiTableInfo,
> -  IN       UINT32                              AcpiTableCount
> -  )
> -{
> -  EFI_STATUS                   Status;
> -  UINTN                        Handle;
> -  UINTN                        Index;
> -  UINTN                        InstalledTableIndex;
> -  EFI_ACPI_DESCRIPTION_HEADER  *DescHeader;
> -  EFI_ACPI_TABLE_VERSION       Version;
> -  EFI_ACPI_SDT_PROTOCOL        *AcpiSdt;
> -
> -  ASSERT (AcpiTableInfo != NULL);
> -
> -  Status = EFI_SUCCESS;
> -
> -  // Check against the statically initialized ACPI tables to see if they are in ACPI info list
> -  while (AcpiTableCount-- != 0) {
> -    for (Index = 0; Index < ACPI_TABLE_VERIFY_COUNT; Index++) {
> -      if (AcpiTableInfo[AcpiTableCount].AcpiTableSignature == mAcpiVerifyTables[Index].AcpiTableSignature) {
> -        mAcpiVerifyTables[Index].Presence |= ACPI_TABLE_PRESENT_INFO_LIST;
> -        // Found this table, skip the rest.
> -        break;
> -      }
> -    }
> -  }
> -
> -  // They also might be published already, so we can search from there
> -  if (FeaturePcdGet (PcdInstallAcpiSdtProtocol)) {
> -    AcpiSdt = NULL;
> -    Status  = gBS->LocateProtocol (&gEfiAcpiSdtProtocolGuid, NULL, (VOID **)&AcpiSdt);
> -
> -    if (EFI_ERROR (Status) || (AcpiSdt == NULL)) {
> -      DEBUG ((DEBUG_ERROR, "ERROR: Failed to locate ACPI SDT protocol (0x%p) - %r\n", AcpiSdt, Status));
> -      return Status;
> -    }
> -
> -    for (Index = 0; Index < ACPI_TABLE_VERIFY_COUNT; Index++) {
> -      Handle              = 0;
> -      InstalledTableIndex = 0;
> -      do {
> -        Status = AcpiSdt->GetAcpiTable (InstalledTableIndex, (EFI_ACPI_SDT_HEADER **)&DescHeader, &Version, &Handle);
> -        if (EFI_ERROR (Status)) {
> -          break;
> -        }
> -
> -        InstalledTableIndex++;
> -      } while (DescHeader->Signature != mAcpiVerifyTables[Index].AcpiTableSignature);
> -
> -      if (!EFI_ERROR (Status)) {
> -        mAcpiVerifyTables[Index].Presence |= ACPI_TABLE_PRESENT_INSTALLED;
> -      }
> -    }
> -  }
> -
> -  // Reset the return Status value to EFI_SUCCESS. We do not fully care if the table look up has failed.
> -  Status = EFI_SUCCESS;
> -  for (Index = 0; Index < ACPI_TABLE_VERIFY_COUNT; Index++) {
> -    if (mAcpiVerifyTables[Index].Presence == 0) {
> -      if (mAcpiVerifyTables[Index].IsMandatory) {
> -        DEBUG ((DEBUG_ERROR, "ERROR: %a Table not found.\n", mAcpiVerifyTables[Index].AcpiTableName));
> -        Status = EFI_NOT_FOUND;
> -      } else {
> -        DEBUG ((DEBUG_WARN, "WARNING: %a Table not found.\n", mAcpiVerifyTables[Index].AcpiTableName));
> -      }
> -    } else if (mAcpiVerifyTables[Index].Presence ==
> -               (ACPI_TABLE_PRESENT_INFO_LIST | ACPI_TABLE_PRESENT_INSTALLED))
> -    {
> -      DEBUG ((DEBUG_ERROR, "ERROR: %a Table found while already published.\n", mAcpiVerifyTables[Index].AcpiTableName));
> -      Status = EFI_ALREADY_STARTED;
> -    }
> -  }
> -
> -  return Status;
> -}
> -
> -/** Generate and install ACPI tables.
> -
> -  The function gathers the information necessary for installing the
> -  ACPI tables from the Configuration Manager, invokes the generators
> -  and installs them (via BuildAndInstallAcpiTable).
> -
> -  @param [in]  TableFactoryProtocol Pointer to the Table Factory Protocol
> -                                    interface.
> -  @param [in]  CfgMgrProtocol       Pointer to the Configuration Manager
> -                                    Protocol Interface.
> -
> -  @retval EFI_SUCCESS           Success.
> -  @retval EFI_NOT_FOUND         If a mandatory table or a generator is not found.
> -  @retval EFI_ALREADY_STARTED   If mandatory table found in AcpiTableInfo is already installed.
> -**/
> -STATIC
> -EFI_STATUS
> -EFIAPI
> -ProcessAcpiTables (
> -  IN CONST EDKII_DYNAMIC_TABLE_FACTORY_PROTOCOL  *CONST  TableFactoryProtocol,
> -  IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL  *CONST  CfgMgrProtocol
> -  )
> -{
> -  EFI_STATUS                  Status;
> -  EFI_ACPI_TABLE_PROTOCOL     *AcpiTableProtocol;
> -  CM_STD_OBJ_ACPI_TABLE_INFO  *AcpiTableInfo;
> -  UINT32                      AcpiTableCount;
> -  UINT32                      Idx;
> -
> -  ASSERT (TableFactoryProtocol != NULL);
> -  ASSERT (CfgMgrProtocol != NULL);
> -
> -  // Find the AcpiTable protocol
> -  Status = gBS->LocateProtocol (
> -                  &gEfiAcpiTableProtocolGuid,
> -                  NULL,
> -                  (VOID **)&AcpiTableProtocol
> -                  );
> -  if (EFI_ERROR (Status)) {
> -    DEBUG ((
> -      DEBUG_ERROR,
> -      "ERROR: Failed to find AcpiTable protocol. Status = %r\n",
> -      Status
> -      ));
> -    return Status;
> -  }
> -
> -  Status = GetEStdObjAcpiTableList (
> -             CfgMgrProtocol,
> -             CM_NULL_TOKEN,
> -             &AcpiTableInfo,
> -             &AcpiTableCount
> -             );
> -  if (EFI_ERROR (Status)) {
> -    DEBUG ((
> -      DEBUG_ERROR,
> -      "ERROR: Failed to get ACPI Table List. Status = %r\n",
> -      Status
> -      ));
> -    return Status;
> -  }
> -
> -  if (0 == AcpiTableCount) {
> -    DEBUG ((
> -      DEBUG_ERROR,
> -      "ERROR: EStdObjAcpiTableList: AcpiTableCount = %d\n",
> -      AcpiTableCount
> -      ));
> -    return EFI_NOT_FOUND;
> -  }
> -
> -  DEBUG ((
> -    DEBUG_INFO,
> -    "INFO: EStdObjAcpiTableList: AcpiTableCount = %d\n",
> -    AcpiTableCount
> -    ));
> -
> -  // Check if mandatory ACPI tables are present.
> -  Status = VerifyMandatoryTablesArePresent (
> -             AcpiTableInfo,
> -             AcpiTableCount
> -             );
> -  if (EFI_ERROR (Status)) {
> -    DEBUG ((
> -      DEBUG_ERROR,
> -      "ERROR: Failed to verify mandatory ACPI Table(s) presence."
> -      " Status = %r\n",
> -      Status
> -      ));
> -    return Status;
> -  }
> -
> -  // Add the FADT Table first.
> -  if ((mAcpiVerifyTables[ACPI_TABLE_VERIFY_FADT].Presence & ACPI_TABLE_PRESENT_INSTALLED) == 0) {
> -    // FADT is not yet installed
> -    for (Idx = 0; Idx < AcpiTableCount; Idx++) {
> -      if (CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdFadt) ==
> -          AcpiTableInfo[Idx].TableGeneratorId)
> -      {
> -        Status = BuildAndInstallAcpiTable (
> -                   TableFactoryProtocol,
> -                   CfgMgrProtocol,
> -                   AcpiTableProtocol,
> -                   &AcpiTableInfo[Idx]
> -                   );
> -        if (EFI_ERROR (Status)) {
> -          DEBUG ((
> -            DEBUG_ERROR,
> -            "ERROR: Failed to find build and install ACPI FADT Table." \
> -            " Status = %r\n",
> -            Status
> -            ));
> -          return Status;
> -        }
> -
> -        break;
> -      }
> -    } // for
> -  }
> -
> -  // Add remaining ACPI Tables
> -  for (Idx = 0; Idx < AcpiTableCount; Idx++) {
> -    DEBUG ((
> -      DEBUG_INFO,
> -      "INFO: AcpiTableInfo[%d].TableGeneratorId = 0x%x\n",
> -      Idx,
> -      AcpiTableInfo[Idx].TableGeneratorId
> -      ));
> -
> -    // Skip FADT Table since we have already added
> -    if (CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdFadt) ==
> -        AcpiTableInfo[Idx].TableGeneratorId)
> -    {
> -      continue;
> -    }
> -
> -    // Skip the Reserved table Generator ID for standard generators
> -    if ((IS_GENERATOR_NAMESPACE_STD (AcpiTableInfo[Idx].TableGeneratorId)) &&
> -        ((CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdReserved)           >=
> -          AcpiTableInfo[Idx].TableGeneratorId)                           ||
> -         (CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdMax)                <=
> -          AcpiTableInfo[Idx].TableGeneratorId)))
> -    {
> -      DEBUG ((
> -        DEBUG_WARN,
> -        "WARNING: Invalid ACPI Generator table ID = 0x%x, Skipping...\n",
> -        AcpiTableInfo[Idx].TableGeneratorId
> -        ));
> -      continue;
> -    }
> -
> -    Status = BuildAndInstallAcpiTable (
> -               TableFactoryProtocol,
> -               CfgMgrProtocol,
> -               AcpiTableProtocol,
> -               &AcpiTableInfo[Idx]
> -               );
> -    if (EFI_ERROR (Status)) {
> -      DEBUG ((
> -        DEBUG_ERROR,
> -        "ERROR: Failed to find, build, and install ACPI Table." \
> -        " Status = %r\n",
> -        Status
> -        ));
> -      return Status;
> -    }
> -  } // for
> -
> -  return Status;
> -}
> +extern
> +VOID
> +AcpiTableProtocolReady (
> +  IN  EFI_EVENT  Event,
> +  IN  VOID       *Context
> +  );
> 
>   /** Entrypoint of Dynamic Table Manager Dxe.
> 
> @@ -727,72 +62,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,
> -                  NULL,
> -                  (VOID **)&CfgMgrProtocol
> -                  );
> -  if (EFI_ERROR (Status)) {
> -    DEBUG ((
> -      DEBUG_ERROR,
> -      "ERROR: Failed to find Configuration Manager protocol. Status = %r\n",
> -      Status
> -      ));
> -    return Status;
> -  }
> -
> -  Status = GetCgfMgrInfo (CfgMgrProtocol, &CfgMfrInfo);
> -  if (EFI_ERROR (Status)) {
> -    DEBUG ((
> -      DEBUG_ERROR,
> -      "ERROR: Failed to get Configuration Manager info. Status = %r\n",
> -      Status
> -      ));
> -    return Status;
> -  }
> -
> -  DEBUG ((
> -    DEBUG_INFO,
> -    "INFO: Configuration Manager Version = 0x%x, OemID = %c%c%c%c%c%c\n",
> -    CfgMfrInfo->Revision,
> -    CfgMfrInfo->OemId[0],
> -    CfgMfrInfo->OemId[1],
> -    CfgMfrInfo->OemId[2],
> -    CfgMfrInfo->OemId[3],
> -    CfgMfrInfo->OemId[4],
> -    CfgMfrInfo->OemId[5]
> -    ));
> -
> -  Status = ProcessAcpiTables (TableFactoryProtocol, CfgMgrProtocol);
> -  if (EFI_ERROR (Status)) {
> -    DEBUG ((
> -      DEBUG_ERROR,
> -      "ERROR: ACPI Table processing failure. Status = %r\n",
> -      Status
> -      ));
> -  }
> -
> -  return Status;
> +  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", __FUNCTION__));
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  SmbiosEvent = EfiCreateProtocolNotifyEvent (
> +            &gEfiSmbiosProtocolGuid,
> +            TPL_CALLBACK,
> +            SmbiosProtocolReady,
> +            NULL,
> +            &SmbiosProtocolRegistration
> +            );
> +  if (SmbiosEvent == NULL) {
> +    DEBUG ((DEBUG_ERROR, "%a: Failed to SMBIOS create protocol event\r\n", __FUNCTION__));
> +    gBS->CloseEvent (AcpiEvent);
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  return EFI_SUCCESS;
>   }
> diff --git a/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableManagerDxe.inf b/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableManagerDxe.inf
> index b09272d883..9d020f0264 100644
> --- a/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableManagerDxe.inf
> +++ b/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableManagerDxe.inf
> @@ -22,6 +22,8 @@
> 
>   [Sources]
>     DynamicTableManagerDxe.c
> +  SmbiosTableBuilder.c
> +  AcpiTableBuilder.c
>     SmbiosTableDispatcher.c
>     SmbiosTableDispatcher.h
> 
> @@ -33,6 +35,7 @@
>   [LibraryClasses]
>     PrintLib
>     TableHelperLib
> +  UefiLib
>     UefiBootServicesTableLib
>     UefiDriverEntryPoint
> 
> @@ -42,12 +45,12 @@
>   [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 0000000000..9ca690c16b
> --- /dev/null
> +++ b/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/SmbiosTableBuilder.c
> @@ -0,0 +1,608 @@
> +/** @file
> +  SMBIOS Table Builder
> +
> +  Copyright (c) 2017 - 2019, ARM Limited. All rights reserved.
> +  Copyright (c) 2022 - 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include <Library/DebugLib.h>
> +#include <Library/UefiLib.h>
> +#include <Library/PcdLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Protocol/Smbios.h>
> +#include <Library/BaseMemoryLib.h>
> +
> +// Module specific include files.
> +#include <ConfigurationManagerObject.h>
> +#include <ConfigurationManagerHelper.h>
> +#include <Library/TableHelperLib.h>
> +#include <Protocol/ConfigurationManagerProtocol.h>
> +#include <Protocol/DynamicTableFactoryProtocol.h>
> +#include <SmbiosTableGenerator.h>
> +#include <SmbiosTableDispatcher.h>
> +
> +/** 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]  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;
> +  SMBIOS_HANDLE_MAP  *HandleMap;
> +
> +  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;
> +  }
> +
> +  HandleMap = TableFactoryProtocol->GetSmbiosHandle (CmObjToken);
> +  if (HandleMap == NULL) {
> +    TableHandle = SMBIOS_HANDLE_PI_RESERVED;
> +  } else {
> +    TableHandle = HandleMap->SmbiosTblHandle;
> +  }
> +
> +  // 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;
> +  }
> +
> +  // If a new handle was generated then add it to the handle map.
> +  if (HandleMap == NULL) {
> +    TableFactoryProtocol->AddSmbiosHandle (
> +                            SmbiosProtocol,
> +                            &TableHandle,
> +                            CmObjToken,
> +                            SmbiosTableInfo->TableGeneratorId
> +                            );
> +  }
> +
> +  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]  AcpiTableInfo        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;
> +  SMBIOS_HANDLE_MAP  *HandleMap;
> +
> +  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",
> +      __FUNCTION__,
> +      TableCount,
> +      SmbiosTable
> +      ));
> +    goto exit_handler;
> +  }
> +
> +  for (Index = 0; Index < TableCount; Index++) {
> +    HandleMap = TableFactoryProtocol->GetSmbiosHandle (CmObjToken[Index]);
> +    if (HandleMap == NULL) {
> +      TableHandle = SMBIOS_HANDLE_PI_RESERVED;
> +    } else {
> +      TableHandle = HandleMap->SmbiosTblHandle;
> +    }
> +
> +    // 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;
> +    }
> +
> +    // If a new handle was generated then add it to the handle map.
> +    if (HandleMap == NULL) {
> +      TableFactoryProtocol->AddSmbiosHandle (
> +                              SmbiosProtocol,
> +                              &TableHandle,
> +                              CmObjToken[Index],
> +                              SmbiosTableInfo->TableGeneratorId
> +                              );
> +    }
> +
> +    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;
> +    }
> +  }
> +
> +  DEBUG ((DEBUG_ERROR, "%a: Returning %r\n", __FUNCTION__, Status));
> +  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
> +      ));
> +  }
> +
> +  DEBUG ((DEBUG_ERROR, "%a: Returning %r\n", __FUNCTION__, 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;
> +  UINT32                        Idx;
> +
> +  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)) {
> +    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
> +    ));
> +
> +  for (Idx = 0; Idx < SmbiosTableCount; Idx++) {
> +    Status = DispatchSmbiosTable (
> +               SmbiosTableInfo[Idx].TableType,
> +               TableFactoryProtocol,
> +               CfgMgrProtocol,
> +               SmbiosProtocol,
> +               SmbiosTableInfo,
> +               SmbiosTableCount
> +               );
> +    if (EFI_ERROR (Status)) {
> +      DEBUG ((
> +        DEBUG_ERROR,
> +        "ERROR: Failed to install SMBIOS Table." \
> +        " Id = %u Status = %r\n",
> +        SmbiosTableInfo[Idx].TableGeneratorId,
> +        Status
> +        ));
> +    }
> +  }
> +
> +  DEBUG ((DEBUG_ERROR, "%a: Returning %r\n", __FUNCTION__, Status));
> +  return Status;
> +}
> +
> +/** Callback Function for Smbios table generation.
> +
> +  Callback function when SMBIOS protocol is installed, this function will then
> +  invoke the code to install the available SMBIOS tables.
> +
> +  @param  Event
> +  @param  Context
> +
> +  @retval None.
> +**/
> +VOID
> +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
> +      ));
> +  }
> +}
> diff --git a/DynamicTablesPkg/Include/ConfigurationManagerObject.h b/DynamicTablesPkg/Include/ConfigurationManagerObject.h
> index 74ad25d5d9..0c97e70996 100644
> --- a/DynamicTablesPkg/Include/ConfigurationManagerObject.h
> +++ b/DynamicTablesPkg/Include/ConfigurationManagerObject.h
> @@ -31,6 +31,7 @@ Bits: [31:28] - Name Space ID
>                   0000 - Standard
>                   0001 - ARM
>                   1000 - Custom/OEM
> +                1010 - SMBIOS
>                   All other values are reserved.
> 
>   Bits: [27:16] - Reserved.
> @@ -105,9 +106,10 @@ typedef UINT32 CM_OBJECT_ID;
>       for the Configuration Manager Objects.
>   */
>   typedef enum ObjectNameSpaceID {
> -  EObjNameSpaceStandard,      ///< Standard Objects Namespace
> -  EObjNameSpaceArm,           ///< ARM Objects Namespace
> -  EObjNameSpaceOem = 0x8,     ///< OEM Objects Namespace
> +  EObjNameSpaceStandard,         ///< Standard Objects Namespace
> +  EObjNameSpaceArm,              ///< ARM Objects Namespace
> +  EObjNameSpaceOem    = 0x8,     ///< OEM Objects Namespace
> +  EObjNameSpaceSmbios = 0xA,     ///< SMBIOS Objects Namespace
>     EObjNameSpaceMax
>   } EOBJECT_NAMESPACE_ID;
> 
> @@ -192,4 +194,14 @@ typedef struct CmObjDescriptor {
>   #define CREATE_CM_OEM_OBJECT_ID(ObjectId) \
>             (CREATE_CM_OBJECT_ID (EObjNameSpaceOem, ObjectId))
> 
> +/** This macro returns a Configuration Manager Object ID
> +    in the SMBIOS Object Namespace.
> +
> +  @param [in] ObjectId    The Object ID.
> +
> +  @retval Returns an SMBIOS Configuration Manager Object ID.
> +**/
> +#define CREATE_CM_SMBIOS_OBJECT_ID(ObjectId) \
> +          (CREATE_CM_OBJECT_ID (EObjNameSpaceSmbios, ObjectId))
> +
>   #endif // CONFIGURATION_MANAGER_OBJECT_H_
> diff --git a/DynamicTablesPkg/Include/Protocol/DynamicTableFactoryProtocol.h b/DynamicTablesPkg/Include/Protocol/DynamicTableFactoryProtocol.h
> index b11fc0c9f1..0670a8fb27 100644
> --- a/DynamicTablesPkg/Include/Protocol/DynamicTableFactoryProtocol.h
> +++ b/DynamicTablesPkg/Include/Protocol/DynamicTableFactoryProtocol.h
> @@ -239,12 +239,20 @@ 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;
> +
>     /** Pointer to the data structure that holds the
>         list of registered table generators
>     */
>     EDKII_DYNAMIC_TABLE_FACTORY_INFO                          *TableFactoryInfo;
>   } EDKII_DYNAMIC_TABLE_FACTORY_PROTOCOL;
> 
> +
> +
>   /** The Dynamic Table Factory Protocol GUID.
>   */
>   extern EFI_GUID  gEdkiiDynamicTableFactoryProtocolGuid;
> diff --git a/DynamicTablesPkg/Include/SmbiosTableGenerator.h b/DynamicTablesPkg/Include/SmbiosTableGenerator.h
> index 934d56c90d..d81eb8f124 100644
> --- a/DynamicTablesPkg/Include/SmbiosTableGenerator.h
> +++ b/DynamicTablesPkg/Include/SmbiosTableGenerator.h
> @@ -10,7 +10,7 @@
>   #define SMBIOS_TABLE_GENERATOR_H_
> 
>   #include <IndustryStandard/SmBios.h>
> -
> +#include <Protocol/Smbios.h>
>   #include <TableGenerator.h>
> 
>   #pragma pack(1)
> @@ -121,12 +121,21 @@ typedef enum StdSmbiosTableGeneratorId {
>               ETableGeneratorNameSpaceStd,        \
>               TableId                             \
>               )
> +#define MAX_SMBIOS_HANDLES               (255)
> 
>   /** Forward declarations.
>   */
>   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;
> +
> +typedef struct SmbiosHandleCmObjMap {
> +  ESTD_SMBIOS_TABLE_ID  SmbiosTableId;
> +  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
> @@ -143,9 +152,11 @@ typedef struct SmbiosTableGenerator         SMBIOS_TABLE_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
> @@ -163,11 +174,105 @@ typedef EFI_STATUS (*SMBIOS_TABLE_GENERATOR_BUILD_TABLE) (
>   **/
>   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 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.
> +
> +  @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 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.
> +
> +  @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 (either generated by
> +                              SmbiosDxe Driver or  SMBIOS_HANDLE_PI_RESERVED
> +                              if a handle needs to be generated).
> +  @param [in]  CmObjectToken  The CM Object token for that is used to generate
> +                              SMBIOS record.
> +  @param [in]  SmbiosId       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 (*EDKII_DYNAMIC_TABLE_FACTORY_SMBIOS_TABLE_ADD_HANDLE) (
> +  IN  EFI_SMBIOS_PROTOCOL  *Smbios,
> +  IN  SMBIOS_HANDLE        *SmbiosHandle,
> +  IN  CM_OBJECT_TOKEN      CmObjectToken,
> +  IN ESTD_SMBIOS_TABLE_ID  SmbiosId
> +  );
> +
> +/** 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 * (*EDKII_DYNAMIC_TABLE_FACTORY_SMBIOS_TABLE_GET_HANDLE) (
> +  IN  CM_OBJECT_TOKEN      CmObjectToken
> +  );
> +
>   /** The SMBIOS_TABLE_GENERATOR structure provides an interface that the
>       Table Manager can use to invoke the functions to build SMBIOS tables.
>   */
> @@ -189,6 +294,14 @@ typedef struct SmbiosTableGenerator {
>         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_TABLEEX   FreeTableResourcesEx;
>   } SMBIOS_TABLE_GENERATOR;
> 
>   /** Register SMBIOS table factory generator.
> @@ -229,6 +342,54 @@ DeregisterSmbiosTableGenerator (
>     IN CONST SMBIOS_TABLE_GENERATOR                 *CONST  Generator
>     );
> 
> +/** Add 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 (either generated by
> +                              SmbiosDxe Driver or  SMBIOS_HANDLE_PI_RESERVED
> +                              if a handle needs to be generated).
> +  @param [in]  CmObjectToken  The CM Object token for that is used to generate
> +                              SMBIOS record.
> +  @param [in]  SmbiosId       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 ESTD_SMBIOS_TABLE_ID  SmbiosId
> +  );
> +
> +/** 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 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.
> +**/
> +SMBIOS_HANDLE_MAP *
> +EFIAPI
> +FindSmbiosHandle (
> +  IN CM_OBJECT_TOKEN CmObjectToken
> +  );
> +
>   #pragma pack()
> 
>   #endif // SMBIOS_TABLE_GENERATOR_H_
> --
> 2.17.1
> 
> 
> 
> 
> 
> 

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2023-02-21 15:36 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <173E4FD875129A15.17319@groups.io>
2023-02-21 15:36 ` [edk2-devel] [PATCH v2 1/1] DynamicTablesPkg: Add SMBIOS table generation Girish Mahadevan

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox