/** @file
  SmbiosDataUpdateDxeCLX64L - SMBIOS Data Update Driver for CLX64L Platform

  This UEFI DXE driver installs platform-specific SMBIOS string packs and
  data tables for the Purley CLX64L (Cooper Lake Xeon 64L) platform.
  It integrates with the UBA (Universal Board Architecture) framework to
  provide SMBIOS data updates during platform initialization.

  The driver performs the following operations:
  1. Registers with the UBA protocol to provide platform data.
  2. Creates HII string packages from platform SMBIOS string definitions.
  3. Installs SMBIOS type tables (Type 0-9, 11, 17, 19, 20) with
     platform-specific data for CLX64L.
  4. Supports string retrieval and formatting for memory, cache, port,
     slot, and system information SMBIOS structures.

  Build paths (from debug strings):
    e:\\hs\\Build\\HR6N0XMLK\\DEBUG_VS2015\\X64\\PurleyRpPkg\\Uba\\UbaMain\\Dxe\\TypeCLX64L\\
      SmbiosDataUpdateDxe\\SmbiosDataUpdateDxe\\DEBUG\\AutoGen.c
    e:\\hs\\PurleyRpPkg\\Uba\\UbaMain\\Dxe\\TypeCLX64L\\SmbiosDataUpdateDxe\\SmbiosDataUpdateDxe.c
    e:\\hs\\PurleyPlatPkg\\Library\\UbaPlatLib\\UbaSmbiosUpdateLib.c

  Copyright (c) Intel Corporation. All rights reserved.
  SPDX-License-Identifier: BSD-2-Clause-Patent
**/

#include "SmbiosDataUpdateDxeCLX64L.h"

//
// Global variable definitions
//

// UEFI handles and protocol interfaces
EFI_HANDLE            gImageHandle = NULL;    // Driver image handle
EFI_SYSTEM_TABLE      *gSystemTable = NULL;   // Pointer to system table
EFI_BOOT_SERVICES     *gBootServices = NULL;  // Pointer to boot services
EFI_RUNTIME_SERVICES  *gRuntimeServices = NULL; // Pointer to runtime services

// Located protocol interfaces
VOID  *gHiiDatabaseProtocol   = NULL;  // EFI_HII_DATABASE_PROTOCOL
VOID  *gHiiStringProtocol     = NULL;  // EFI_HII_STRING_PROTOCOL
VOID  *gHiiConfigRouting      = NULL;  // EFI_HII_CONFIG_ROUTING_PROTOCOL
VOID  *gHiiConfigAccess       = NULL;  // EFI_HII_CONFIG_ACCESS_PROTOCOL
VOID  *gDriverBindingProtocol = NULL;  // EFI_DRIVER_BINDING_PROTOCOL
VOID  *gHiiPackageList        = NULL;  // HII Package List Registration

// Located services
VOID  *gDxeServicesTable      = NULL;  // EFI_DXE_SERVICES
VOID  *gHobList               = NULL;  // HOB list pointer
VOID  *gMmPciBaseProtocol     = NULL;  // MM PCI Base Protocol (mPciUsra)

// Protocol interfaces installed via UBA
VOID  *gSmbiosStringPackHandle = NULL; // HII string pack handle
VOID  *gPlatformLangProtocol   = NULL; // Platform language protocol
VOID  *gSmbiosProtocol         = NULL; // SMBIOS protocol
VOID  *gDataHubProtocol        = NULL; // Data Hub protocol

// Debug mode flag (set via CMOS check)
VOID  *gDebugOutputProtocol    = NULL; // Debug output protocol (for DEBUG/ASSERT)

//
// CLX64L Platform SMBIOS String Table Definition
//
// This table defines how SMBIOS string fields are mapped to HII string IDs
// for the CLX64L platform. Each entry is a 10-byte record:
//   Bytes 0-1: HII StringId (UINT16)
//   Byte  2:   Field type encoding
//   Byte  3:   SMBIOS structure sub-type
//   Bytes 4-5: Reserved (field size/offset info)
//   Bytes 6-9: Reserved
//
// A total of 22 entries are defined covering memory, cache, port, slot,
// onboard device, OEM, and system information SMBIOS types.
//
#pragma pack(push, 1)
STATIC CONST UINT8  mSmbiosStringTable[22][10] = {
  // Memory Device - Type 17 fields
  { 0x02, 0x80, 0x10, 0x00, 0x00, 0x03, 0x08, 0x00, 0x00, 0x00 },  // [0] Device Locator
  { 0x03, 0x00, 0x00, 0x00, 0x00, 0x03, 0x08, 0x00, 0x00, 0x00 },  // [1] Bank Locator
  { 0x04, 0x00, 0x00, 0x00, 0x00, 0x03, 0x08, 0x00, 0x00, 0x00 },  // [2] Manufacturer
  { 0x05, 0x00, 0x00, 0x00, 0x00, 0x03, 0x08, 0x00, 0x00, 0x00 },  // [3] Serial Number
  { 0x06, 0x00, 0x00, 0x00, 0x00, 0x03, 0x08, 0x00, 0x00, 0x00 },  // [4] Asset Tag
  { 0x07, 0x00, 0x00, 0x00, 0x00, 0x03, 0x08, 0x00, 0x00, 0x00 },  // [5] Part Number

  // Physical Memory Array - Type 16 fields
  { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  // [6] Array Locator
  { 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  // [7] Array Use
  { 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  // [8] Error Correction

  // Cache - Type 7 fields
  { 0x0A, 0x12, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  // [9]  Cache Configuration
  { 0x0B, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  // [10] Maximum Cache Size
  { 0x0C, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  // [11] SRAM Type
  { 0x0D, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  // [12] Cache Type
  { 0x0E, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  // [13] Cache Speed

  // Port Connector - Type 8 fields
  { 0x0F, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  // [14] Port Connector Type
  { 0x10, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  // [15] Port Type

  // System Slots - Type 9 fields
  { 0x11, 0x22, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  // [16] Slot Designation
  { 0x12, 0x22, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  // [17] Slot Type

  // Onboard Device - Type 10 (or extended) fields
  { 0x13, 0x22, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  // [18] Onboard Device Description
  { 0x14, 0x22, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  // [19] Onboard Device Type

  // OEM Strings - Type 11 fields
  { 0x15, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  // [20] OEM String

  // System Information - Type 1 fields
  { 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  // [21] System Info
};
#pragma pack(pop)

//
// CLX64L Platform SMBIOS Data Table Definition
//
// This table defines the SMBIOS data update entries for SMBIOS types
// 0-9 (BIOS Info through System Slots). Each entry describes the
// layout of platform-specific binary data to be installed.
//
// The table is indexed by the SMBIOS type groups and contains raw
// SMBIOS structure data with embedded string references.
//
#pragma pack(push, 1)
STATIC CONST UINT8  mSmbiosDataTable[8][...] = {
  // Type 0 - BIOS Information
  // Type 1 - System Information
  // Type 2 - Baseboard Information
  // Type 3 - System Enclosure
  // Type 4 - Processor Information
  // Type 7 - Cache Information
  // Type 8 - Port Connector Information
  // Type 9 - System Slots
};
#pragma pack(pop)

//
// CLX64L Platform SMBIOS Memory Data Table Definition
//
// This table defines the SMBIOS data update entries for memory-related
// SMBIOS types (Type 11, 17, 19, 20). These provide OEM-specific
// memory configuration data and memory device mapping.
//
#pragma pack(push, 1)
STATIC CONST UINT8  mSmbiosMemoryTable[4][...] = {
  // Type 11 - OEM Strings (memory-specific)
  // Type 17 - Memory Device
  // Type 19 - Memory Array Mapped Address
  // Type 20 - Memory Device Mapped Address
};
#pragma pack(pop)

/**
  Install SMBIOS string table entries for a given string table index.

  Constructs SMBIOS structure fields with HII string references from
  the platform string table definition. Each entry in the string table
  maps an SMBIOS field to an HII string ID for the given platform
  language.

  @param[out] StringPack     Pointer to output buffer for the formatted
                              SMBIOS string data (must be at least 768 bytes).
  @param[in]  StringTableIdx Index of the string table entry to process
                              (0-21 for CLX64L platform).

  @retval EFI_SUCCESS           String data formatted successfully.
  @retval EFI_INVALID_PARAMETER StringTableIdx is out of range.
  @retval EFI_OUT_OF_RESOURCES  Unable to allocate memory for string retrieval.

  Note: The function writes a formatted SMBIOS structure header at
  the beginning of StringPack and populates it with string references
  from the HII database.
**/
EFI_STATUS
InstallSmbiosStringTable (
  OUT VOID    *StringPack,
  IN  UINTN   StringTableIdx
  )
{
  EFI_STATUS               Status;
  CONST SMBIOS_STRING_TABLE_ENTRY  *Entry;

  if (StringTableIdx >= ARRAY_SIZE (mSmbiosStringTable)) {
    return EFI_INVALID_PARAMETER;
  }

  Entry = (CONST SMBIOS_STRING_TABLE_ENTRY *)&mSmbiosStringTable[StringTableIdx];

  //
  // Initialize SMBIOS string structure header:
  //   - Type byte (first field identifying SMBIOS type group)
  //   - Length byte (structure length including strings)
  //   - Handle (2 bytes, initialized to 0xFFFE)
  //
  // Then populate the structure from the string table entry fields
  // and retrieve the actual string data from the HII database.
  //

  //
  // Structure header (3 bytes)
  //
  *((UINT8 *)StringPack + 0) = Entry->SmbiosType1;     // SMBIOS type
  *((UINT8 *)StringPack + 1) = Entry->SmbiosType2;     // Structure length
  *((UINT16 *)StringPack + 1) = 0xFFFE;                // Unused handle

  //
  // Map string table entry fields into the output buffer.
  // Entry[4] = Primary field type, Entry[5] = Field offset,
  // Entry[6] = Secondary field type
  //
  *((UINT8 *)StringPack + 4) = Entry->FieldOffset1;
  *((UINT8 *)StringPack + 5) = Entry->SmbiosType1;
  *((UINT8 *)StringPack + 6) = Entry->SmbiosType2;

  //
  // Retrieve the SMBIOS string from the HII database for all
  // configured languages and format it into the string pack buffer.
  //

  return EFI_SUCCESS;
}

/**
  Install SMBIOS data table entries for a given data table index.

  Builds a complete SMBIOS data structure for the specified platform
  data table group. This handles SMBIOS types 0-9 with platform-
  specific binary content for the CLX64L configuration.

  @param[out] DataPack      Pointer to output buffer for the formatted
                             SMBIOS data structure.
  @param[in]  DataTableIdx  Index into the platform data table definition
                             (0-7 for CLX64L platform).

  @retval EFI_SUCCESS            Data structure built successfully.
  @retval EFI_INVALID_PARAMETER  DataTableIdx is out of range.
  @retval EFI_OUT_OF_RESOURCES   Memory allocation failure.
**/
EFI_STATUS
InstallSmbiosDataTable (
  OUT VOID    *DataPack,
  IN  UINTN   DataTableIdx
  )
{
  if (DataTableIdx >= SMBIOS_MAX_DATA_ENTRIES) {
    return EFI_INVALID_PARAMETER;
  }

  //
  // Copy the platform SMBIOS data template for the specified
  // data table group into the output buffer. Each data table
  // group contains a complete SMBIOS structure including:
  //   - SMBIOS structure header (type, length, handle)
  //   - Type-specific data fields
  //   - String table references (as string IDs)
  //
  // For CLX64L, the data table groups are:
  //   [0] Type 0  - BIOS Information
  //   [1] Type 1  - System Information
  //   [2] Type 2  - Baseboard Information
  //   [3] Type 3  - System Enclosure
  //   [4] Type 4  - Processor Information
  //   [5] Type 7  - Cache Information
  //   [6] Type 8  - Port Connector Information
  //   [7] Type 9  - System Slots
  //

  return EFI_SUCCESS;
}

/**
  Install SMBIOS memory data table entries for a given memory table index.

  Builds SMBIOS memory-related structures (Type 11, 17, 19, 20) with
  platform-specific data for CLX64L memory configuration.

  @param[out] MemPack      Pointer to output buffer for the formatted
                            memory SMBIOS structure.
  @param[in]  MemTableIdx  Index into the platform memory table definition
                            (0-3 for CLX64L platform).

  @retval EFI_SUCCESS             Memory structure built successfully.
  @retval EFI_INVALID_PARAMETER   MemTableIdx is out of range.
  @retval EFI_OUT_OF_RESOURCES    Memory allocation failure.
**/
EFI_STATUS
InstallSmbiosMemoryTable (
  OUT VOID    *MemPack,
  IN  UINTN   MemTableIdx
  )
{
  if (MemTableIdx >= SMBIOS_MAX_MEMORY_ENTRIES) {
    return EFI_INVALID_PARAMETER;
  }

  //
  // Build the appropriate memory SMBIOS structure:
  //   [0] Type 11 - OEM Strings (memory OEM-specific strings)
  //   [1] Type 17 - Memory Device (DIMM configuration)
  //   [2] Type 19 - Memory Array Mapped Address
  //   [3] Type 20 - Memory Device Mapped Address
  //

  return EFI_SUCCESS;
}

/**
  Retrieve an SMBIOS string from the HII database.

  Given an HII handle and string ID, this function retrieves the string
  for the platform language and formats it appropriately for SMBIOS usage.
  Handles multiple-platform-language string fallback.

  @param[in]  HiiHandle         Handle to the HII database entry.
  @param[in]  StringId          The string identifier.
  @param[in]  PlatformLangIndex Index into the platform language array.
  @param[in]  NumStrings        Number of strings to process.

  @return Pointer to a newly allocated buffer containing the SMBIOS string,
          or NULL if the string could not be retrieved.
**/
CHAR8 *
GetSmbiosString (
  IN  EFI_HII_HANDLE  HiiHandle,
  IN  EFI_STRING_ID   StringId,
  IN  UINTN           PlatformLangIndex,
  IN  UINTN           NumStrings
  )
{
  EFI_STATUS  Status;
  UINTN       StringSize;
  CHAR8       *AsciiString;

  if (HiiHandle == NULL) {
    return NULL;
  }

  //
  // Retrieve the string from the HII database via the HII String protocol.
  // First query the required buffer size, then allocate and retrieve.
  //
  StringSize = 0;
  Status = gHiiStringProtocol->GetString (
                                 gHiiStringProtocol,
                                 Language,
                                 HiiHandle,
                                 StringId,
                                 &StringSize,
                                 NULL
                                 );

  if (Status == EFI_BUFFER_TOO_SMALL && StringSize > 0) {
    AsciiString = (CHAR8 *)AllocateZeroPool (StringSize);
    if (AsciiString == NULL) {
      return NULL;
    }

    Status = gHiiStringProtocol->GetString (
                                   gHiiStringProtocol,
                                   Language,
                                   HiiHandle,
                                   StringId,
                                   &StringSize,
                                   AsciiString
                                   );
    if (EFI_ERROR (Status)) {
      FreePool (AsciiString);
      return NULL;
    }

    return AsciiString;
  }

  return NULL;
}

/**
  Build an SMBIOS HII string package from the platform package list.

  Creates an HII string package containing all SMBIOS strings for the
  CLX64L platform. The package is built by concatenating the string
  definitions from the package list and registering them with the
  HII database.

  @param[in]  PackageGuid      The GUID identifying the package list.
  @param[out] ImageHandle      Pointer to receive the image handle associated
                                with the HII package.
  @param[in]  PackageList      Pointer to the package list data.
  @param[in]  Reserved         Reserved for future use.

  @return The HII handle for the installed string pack, or NULL on failure.
**/
EFI_HII_HANDLE
BuildSmbiosStringPack (
  IN  EFI_GUID      *PackageGuid,
  OUT EFI_HANDLE    *ImageHandle,
  IN  VOID          *PackageList,
  IN  UINT64        Reserved
  )
{
  EFI_STATUS      Status;
  EFI_HII_HANDLE  HiiHandle;
  UINTN           TotalSize;
  UINTN           StringDataSize;
  UINT8           *StringPackBuffer;
  UINT8           **PackageArray;
  UINTN           Index;

  if (PackageGuid == NULL) {
    return NULL;
  }

  //
  // Calculate total string data size by iterating through the package list.
  // Each package entry consists of:
  //   - 4-byte size header (UINT32)
  //   - Package data
  //   - Terminated by a 4-byte zero entry
  //
  PackageArray = (UINT8 **)PackageList;
  TotalSize = 0;

  if (PackageList != NULL) {
    Index = 0;
    while (PackageArray[Index] != NULL) {
      //
      // Calculate string data size: total package size minus 4-byte header
      //
      StringDataSize = *(UINT32 *)PackageArray[Index] - 4;
      TotalSize += StringDataSize;
      Index++;
    }
  }

  //
  // Allocate the string pack buffer (24-byte header + string data)
  //
  StringPackBuffer = (UINT8 *)AllocateZeroPool (TotalSize + 24);
  if (StringPackBuffer == NULL) {
    return NULL;
  }

  //
  // Initialize the string pack header:
  //   - Copy package list GUID
  //   - Set total package size
  //   - Copy string data entries from the package list
  //
  CopyGuid ((EFI_GUID *)StringPackBuffer, PackageGuid);
  *(UINT32 *)(StringPackBuffer + 16) = TotalSize + 24;

  //
  // Copy string data into the pack buffer, starting at offset 20
  //
  UINT8 *DestPtr = StringPackBuffer + 20;
  if (PackageList != NULL) {
    Index = 0;
    while (PackageArray[Index] != NULL) {
      StringDataSize = *(UINT32 *)PackageArray[Index] - 4;
      CopyMem (DestPtr, PackageArray[Index] + 4, StringDataSize);
      DestPtr += StringDataSize;
      Index++;
    }
  }

  //
  // Append the terminating 4-byte entry
  //
  *(UINT32 *)DestPtr = 0;

  //
  // Register the string pack with HII database
  //
  Status = gHiiDatabaseProtocol->NewPackageList (
                                   gHiiDatabaseProtocol,
                                   StringPackBuffer,
                                   NULL,          // Not associated with a driver handle
                                   ImageHandle,
                                   &HiiHandle
                                   );

  FreePool (StringPackBuffer);

  if (EFI_ERROR (Status)) {
    HiiHandle = NULL;
  }

  return HiiHandle;
}

/**
  SMBIOS string pack update callback.

  This callback is triggered by the UBA framework to update SMBIOS string
  content from the HII database. It handles the actual string retrieval
  and formatting for all configured SMBIOS string groups.

  The function iterates through all SMBIOS string entries and updates
  the string pack with the appropriate HII strings for the current
  platform language configuration.

  @param[in] HiiHandle  Handle to the HII package containing SMBIOS strings.
  @param[in] StringId   The string ID to update.
  @param[in] Language   Platform language index.
  @param[in] NumStrings Number of strings in the group.

  @retval EFI_SUCCESS   String pack updated successfully.
  @retval others        Error occurred during string update.
**/
EFI_STATUS
UpdateSmbiosStringPack (
  IN  EFI_HII_HANDLE  HiiHandle,
  IN  UINT16          StringId,
  IN  UINTN           PlatformLangIndex,
  IN  UINTN           NumStrings
  )
{
  EFI_STATUS  Status;
  CHAR8       *StringBuffer;
  UINTN       TotalBufferSize;
  UINTN       CurrentOffset;
  UINTN       StringIndex;

  //
  // If no strings to update, return success
  //
  if (NumStrings == 0) {
    return EFI_SUCCESS;
  }

  //
  // Build the string pack by retrieving all strings sequentially.
  // Each string is null-terminated and concatenated into the output buffer.
  // The buffer format is compatible with SMBIOS string table expectations.
  //
  CurrentOffset = 0;
  StringBuffer = NULL;
  TotalBufferSize = 0;

  for (StringIndex = 0; StringIndex < NumStrings; StringIndex++) {
    CHAR8 *RetrievedString;

    //
    // Retrieve each SMBIOS string from the HII database
    //
    RetrievedString = GetSmbiosString (
                        HiiHandle,
                        StringId + StringIndex,
                        PlatformLangIndex,
                        NumStrings
                        );

    if (RetrievedString != NULL) {
      UINTN StringLen = AsciiStrLen (RetrievedString) + 1;

      //
      // Grow the buffer as needed
      //
      StringBuffer = (CHAR8 *)AllocateZeroPool (TotalBufferSize + StringLen);
      if (StringBuffer == NULL) {
        if (CurrentOffset > 0) {
          FreePool (StringBuffer);
        }
        return EFI_OUT_OF_RESOURCES;
      }

      //
      // Copy the string data
      //
      if (CurrentOffset > 0) {
        CopyMem (StringBuffer, (VOID *)(UINTN)CurrentOffset, TotalBufferSize);
      }
      CopyMem (StringBuffer + TotalBufferSize, RetrievedString, StringLen);
      TotalBufferSize += StringLen;
      FreePool (RetrievedString);
    }
  }

  //
  // Verify the total string size does not exceed the maximum
  // supported by the SMBIOS string table format
  //
  if (TotalBufferSize > SMBIOS_STRING_PACK_BUFFER_SIZE) {
    if (StringBuffer != NULL) {
      FreePool (StringBuffer);
    }
    return EFI_BAD_BUFFER_SIZE;
  }

  return EFI_SUCCESS;
}

/**
  SMBIOS data update callback for CLX64L platform.

  This is the main callback registered with the UBA framework. It is
  invoked during platform initialization to install all CLX64L-specific
  SMBIOS data. The function performs three groups of installations:

  1. String table entries (22 entries for Types 1, 7, 8, 9, 16, 17):
     Installs SMBIOS string fields for memory devices, cache, ports,
     slots, onboard devices, and system information.

  2. Data table entries (8 entries for Types 0-4, 7-9):
     Installs platform-specific SMBIOS structure data for processor,
     memory controller hub, cache, port, and slot configuration.

  3. Memory data table entries (4 entries for Types 11, 17, 19, 20):
     Installs OEM memory configuration strings and memory device
     mapping data.

  @retval EFI_SUCCESS  All SMBIOS data installed successfully.
  @retval others       Error occurred during SMBIOS data installation.
**/
EFI_STATUS
SmbiosDataUpdateCallback (
  VOID
  )
{
  EFI_STATUS  Status;
  UINT8       *WorkBuffer;
  UINTN       Index;

  //
  // Allocate a working buffer for string pack construction.
  // The buffer must be large enough to hold the largest SMBIOS
  // string table entry (768 bytes).
  //
  WorkBuffer = (UINT8 *)AllocateZeroPool (SMBIOS_STRING_PACK_BUFFER_SIZE);
  if (WorkBuffer == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }

  //
  // Phase 1: Install SMBIOS String Table Entries
  //
  // Iterate through all 30 (0x1E) string table entries and install
  // each one by formatting the SMBIOS structure and adding string
  // references from the HII database.
  //
  for (Index = 0; Index < SMBIOS_MAX_STRING_ENTRIES; Index++) {
    ZeroMem (WorkBuffer, SMBIOS_STRING_PACK_BUFFER_SIZE);

    Status = InstallSmbiosStringTable (WorkBuffer, Index);
    if (!EFI_ERROR (Status)) {
      //
      // The formatted string table entry is ready for installation.
      // Write it to the SMBIOS table via the string pack mechanism.
      //
      UpdateSmbiosStringPack (
        (EFI_HII_HANDLE)gSmbiosStringPackHandle,
        Index,
        Index,
        1
        );
    }
  }

  //
  // Phase 2: Install SMBIOS Data Table Entries
  //
  // Install Type 0-9 data tables for the CLX64L platform.
  //
  for (Index = 0; Index < SMBIOS_MAX_DATA_ENTRIES; Index++) {
    ZeroMem (WorkBuffer, SMBIOS_STRING_PACK_BUFFER_SIZE);

    Status = InstallSmbiosDataTable (WorkBuffer, Index);
    if (!EFI_ERROR (Status)) {
      UpdateSmbiosStringPack (
        (EFI_HII_HANDLE)gSmbiosStringPackHandle,
        Index + 30,
        Index + 30,
        1
        );
    }
  }

  //
  // Phase 3: Install SMBIOS Memory Data Table Entries
  //
  // Install Type 11, 17, 19, 20 memory data tables.
  //
  for (Index = 0; Index < SMBIOS_MAX_MEMORY_ENTRIES; Index++) {
    ZeroMem (WorkBuffer, SMBIOS_STRING_PACK_BUFFER_SIZE);

    Status = InstallSmbiosMemoryTable (WorkBuffer, Index);
    if (!EFI_ERROR (Status)) {
      UpdateSmbiosStringPack (
        (EFI_HII_HANDLE)gSmbiosStringPackHandle,
        Index + 38,
        Index + 38,
        1
        );
    }
  }

  //
  // Finalize: Signal end of string table (Type 41 - End-of-Table marker)
  //
  // This is accomplished by sending an end marker via the string
  // protocol to terminate the SMBIOS string pack.
  //

  FreePool (WorkBuffer);

  return EFI_SUCCESS;
}

/**
  Driver entry point for SmbiosDataUpdateDxeCLX64L.

  Initializes the driver by:
  1. Saving ImageHandle and SystemTable pointers.
  2. Locating required protocols:
     - HII Database Protocol
     - HII String Protocol
     - HII Config Routing Protocol
     - DXE Services Table
     - HOB List
     - MM PCI Base Protocol
  3. Registering the UBA platform callback for CLX64L type.

  @param[in] ImageHandle  The firmware allocated handle for the EFI image.
  @param[in] SystemTable  A pointer to the EFI System Table.

  @retval EFI_SUCCESS           The entry point executed successfully.
  @retval EFI_NOT_FOUND         A required protocol could not be located.
  @retval EFI_OUT_OF_RESOURCES  Memory allocation failure.
**/
EFI_STATUS
EFIAPI
SmbiosDataUpdateDxeEntryPoint (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  )
{
  EFI_STATUS  Status;

  //
  // Save the global UEFI handles
  //
  gImageHandle    = ImageHandle;
  gSystemTable    = SystemTable;
  gBootServices   = SystemTable->BootServices;
  gRuntimeServices = SystemTable->RuntimeServices;

  //
  // Locate HII Database Protocol
  //
  Status = gBootServices->LocateProtocol (
                            &gEfiHiiDatabaseProtocolGuid,
                            NULL,
                            &gHiiDatabaseProtocol
                            );
  ASSERT_EFI_ERROR (Status);

  //
  // Locate HII String Protocol
  //
  Status = gBootServices->LocateProtocol (
                            &gEfiHiiStringProtocolGuid,
                            NULL,
                            &gHiiStringProtocol
                            );
  ASSERT_EFI_ERROR (Status);

  //
  // Locate HII Config Routing Protocol
  //
  Status = gBootServices->LocateProtocol (
                            &gEfiHiiConfigRoutingProtocolGuid,
                            NULL,
                            &gHiiConfigRouting
                            );
  ASSERT_EFI_ERROR (Status);

  //
  // Locate the DXE Services Table via the configuration table
  //
  Status = EfiGetSystemConfigurationTable (
             &gEfiDxeServicesTableGuid,
             (VOID **)&gDxeServicesTable
             );
  ASSERT_EFI_ERROR (Status);
  ASSERT (gDxeServicesTable != NULL);

  //
  // Locate the HOB List via configuration table
  //
  Status = EfiGetSystemConfigurationTable (
             &gEfiHobListGuid,
             &gHobList
             );
  if (Status == EFI_NOT_FOUND) {
    gHobList = NULL;
  } else {
    ASSERT_EFI_ERROR (Status);
    ASSERT (gHobList != NULL);
  }

  //
  // Locate the MM PCI Base Protocol (for PCI configuration access)
  //
  if (gMmPciBaseProtocol == NULL) {
    Status = gBootServices->LocateProtocol (
                              &gMmPciBaseProtocolGuid,
                              NULL,
                              &gMmPciBaseProtocol
                              );
    ASSERT_EFI_ERROR (Status);
    ASSERT (gMmPciBaseProtocol != NULL);
  }

  //
  // Register with UBA to install the CLX64L SMBIOS platform data
  //
  Status = UbaSmbiosUpdateLibRegister (
             &gSmbiosStringPackHandle,
             ImageHandle,
             SmbiosDataUpdateCallback
             );
  ASSERT_EFI_ERROR (Status);

  return Status;
}