[edk2-devel] [edk2-platforms][PATCH v2 20/32] JadePkg: Add SMBIOS tables support

Leif Lindholm leif at nuviainc.com
Mon Jun 7 23:00:50 UTC 2021


On Wed, May 26, 2021 at 17:07:12 +0700, Nhi Pham wrote:
> From: Quan Nguyen <quan at os.amperecomputing.com>
> 
> This supports various SMBIOS tables type 0, 1, 2, 3, 4, 7, 8, 9, 11,
> 13, 16, 17, 19, 24 and 32.
> 
> SMBIOS Type 1, 2 and 3 are hardcoded as Host-BMC communication is not
> supported yet. And, this module does not support fixup tables to reflect
> changes of the system at booting time.
> 
> Cc: Thang Nguyen <thang at os.amperecomputing.com>
> Cc: Chuong Tran <chuong at os.amperecomputing.com>
> Cc: Phong Vo <phong at os.amperecomputing.com>
> Cc: Leif Lindholm <leif at nuviainc.com>
> Cc: Michael D Kinney <michael.d.kinney at intel.com>
> Cc: Ard Biesheuvel <ardb+tianocore at kernel.org>
> Cc: Nate DeSimone <nathaniel.l.desimone at intel.com>
> 
> Signed-off-by: Quan Nguyen <quan at os.amperecomputing.com>
> ---
>  Silicon/Ampere/AmpereSiliconPkg/AmpereSiliconPkg.dec                    |   12 +
>  Platform/Ampere/JadePkg/Jade.dsc                                        |   26 +
>  Platform/Ampere/JadePkg/Jade.fdf                                        |    8 +
>  Platform/Ampere/JadePkg/Drivers/SmbiosCpuDxe/SmbiosCpuDxe.inf           |   45 +
>  Platform/Ampere/JadePkg/Drivers/SmbiosMemInfoDxe/SmbiosMemInfoDxe.inf   |   45 +
>  Platform/Ampere/JadePkg/Drivers/SmbiosPlatformDxe/SmbiosPlatformDxe.inf |   52 +
>  Platform/Ampere/JadePkg/Drivers/SmbiosCpuDxe/SmbiosCpuDxe.c             |  709 +++++++++++++
>  Platform/Ampere/JadePkg/Drivers/SmbiosMemInfoDxe/SmbiosMemInfoDxe.c     |  705 +++++++++++++
>  Platform/Ampere/JadePkg/Drivers/SmbiosPlatformDxe/SmbiosPlatformDxe.c   | 1049 ++++++++++++++++++++
>  9 files changed, 2651 insertions(+)
> 
> diff --git a/Silicon/Ampere/AmpereSiliconPkg/AmpereSiliconPkg.dec b/Silicon/Ampere/AmpereSiliconPkg/AmpereSiliconPkg.dec
> index 0ac075047276..368136b5342f 100755
> --- a/Silicon/Ampere/AmpereSiliconPkg/AmpereSiliconPkg.dec
> +++ b/Silicon/Ampere/AmpereSiliconPkg/AmpereSiliconPkg.dec
> @@ -63,11 +63,23 @@ [PcdsFixedAtBuild]
>    gAmpereTokenSpaceGuid.PcdSmproNsMailboxIndex|0x1|UINT32|0x00000003
>    gAmpereTokenSpaceGuid.PcdPmproDbBaseReg|0x100001540000|UINT64|0x00000004
>  
> +  #
> +  # SMBIOS Type 1 Pcd
> +  #
> +  gAmpereTokenSpaceGuid.PcdSmbiosTables1MajorVersion|0|UINT8|0x00000005
> +  gAmpereTokenSpaceGuid.PcdSmbiosTables1MinorVersion|0|UINT8|0x00000006
> +
>  [PcdsFixedAtBuild, PcdsDynamic, PcdsDynamicEx]
>    #
>    # Firmware Volume Pcds
>    #
>    gAmpereTokenSpaceGuid.PcdFvBlockSize|0|UINT32|0xB0000001
>  
> +  #
> +  # SMBIOS, default or template values
> +  #
> +  # SMBIOS Type 0 - BIOS Information
> +  gAmpereTokenSpaceGuid.PcdSmbiosTables0BiosReleaseDate|"MM/DD/YYYY"|VOID*|0xB0000002 # Must follow this MM/DD/YYYY SMBIOS date format
> +
>    # NVRam Pcds
>    gAmpereTokenSpaceGuid.PcdNvramErased|FALSE|BOOLEAN|0xB0000009
> diff --git a/Platform/Ampere/JadePkg/Jade.dsc b/Platform/Ampere/JadePkg/Jade.dsc
> index 6aaa644ad298..9c7d7cad4915 100755
> --- a/Platform/Ampere/JadePkg/Jade.dsc
> +++ b/Platform/Ampere/JadePkg/Jade.dsc
> @@ -104,7 +104,22 @@ [PcdsFeatureFlag.common]
>    #
>    gEfiMdeModulePkgTokenSpaceGuid.PcdInstallAcpiSdtProtocol|TRUE
>  
> +[PcdsFixedAtBuild]
> +!ifdef $(FIRMWARE_VER)
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareVersionString|L"$(FIRMWARE_VER)"
> +!endif
> +
>  [PcdsFixedAtBuild.common]
> +  gAmpereTokenSpaceGuid.PcdSmbiosTables1MajorVersion|$(MAJOR_VER)
> +  gAmpereTokenSpaceGuid.PcdSmbiosTables1MinorVersion|$(MINOR_VER)
> +
> +  # Clearing BIT0 in this PCD prevents installing a 32-bit SMBIOS entry point,
> +  # if the entry point version is >= 3.0. AARCH64 OSes cannot assume the
> +  # presence of the 32-bit entry point anyway (because many AARCH64 systems
> +  # don't have 32-bit addressable physical RAM), and the additional allocations
> +  # below 4 GB needlessly fragment the memory map. So expose the 64-bit entry
> +  # point only, for entry point versions >= 3.0.
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdSmbiosEntryPointProvideMethod|0x2
>  
>  !if $(SECURE_BOOT_ENABLE) == TRUE
>    # Override the default values from SecurityPkg to ensure images
> @@ -114,6 +129,9 @@ [PcdsFixedAtBuild.common]
>    gEfiSecurityPkgTokenSpaceGuid.PcdRemovableMediaImageVerificationPolicy|0x04
>  !endif
>  
> +[PcdsDynamicDefault.common.DEFAULT]
> +  # SMBIOS Type 0 - BIOS Information
> +  gAmpereTokenSpaceGuid.PcdSmbiosTables0BiosReleaseDate|"MM/DD/YYYY"
>  
>  [PcdsPatchableInModule]
>    #
> @@ -148,3 +166,11 @@ [Components.common]
>    # VGA Aspeed
>    #
>    Drivers/ASpeed/ASpeedGopBinPkg/ASpeedAst2500GopDxe.inf
> +
> +  #
> +  # SMBIOS
> +  #
> +  MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.inf
> +  Platform/Ampere/JadePkg/Drivers/SmbiosPlatformDxe/SmbiosPlatformDxe.inf
> +  Platform/Ampere/JadePkg/Drivers/SmbiosCpuDxe/SmbiosCpuDxe.inf
> +  Platform/Ampere/JadePkg/Drivers/SmbiosMemInfoDxe/SmbiosMemInfoDxe.inf
> diff --git a/Platform/Ampere/JadePkg/Jade.fdf b/Platform/Ampere/JadePkg/Jade.fdf
> index ef24e6f1f8e0..3d5d857178b3 100755
> --- a/Platform/Ampere/JadePkg/Jade.fdf
> +++ b/Platform/Ampere/JadePkg/Jade.fdf
> @@ -340,4 +340,12 @@ [FV.FvMain]
>    INF RuleOverride=ACPITABLE Silicon/Ampere/AmpereAltraPkg/AcpiCommonTables/AcpiCommonTables.inf
>    INF RuleOverride=ACPITABLE Platform/Ampere/JadePkg/AcpiTables/AcpiTables.inf
>  
> +  #
> +  # SMBIOS
> +  #
> +  INF MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.inf
> +  INF Platform/Ampere/JadePkg/Drivers/SmbiosPlatformDxe/SmbiosPlatformDxe.inf
> +  INF Platform/Ampere/JadePkg/Drivers/SmbiosCpuDxe/SmbiosCpuDxe.inf
> +  INF Platform/Ampere/JadePkg/Drivers/SmbiosMemInfoDxe/SmbiosMemInfoDxe.inf
> +
>  !include Platform/Ampere/AmperePlatformPkg/FvRules.fdf.inc
> diff --git a/Platform/Ampere/JadePkg/Drivers/SmbiosCpuDxe/SmbiosCpuDxe.inf b/Platform/Ampere/JadePkg/Drivers/SmbiosCpuDxe/SmbiosCpuDxe.inf
> new file mode 100644
> index 000000000000..f723ad612a52
> --- /dev/null
> +++ b/Platform/Ampere/JadePkg/Drivers/SmbiosCpuDxe/SmbiosCpuDxe.inf
> @@ -0,0 +1,45 @@
> +#
> +# Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x0001001B
> +  BASE_NAME                      = SmbiosCpuDxe
> +  FILE_GUID                      = 4DD7C2E4-E6A6-11EA-8736-D3C56ABBB5C4
> +  MODULE_TYPE                    = DXE_DRIVER
> +  VERSION_STRING                 = 1.0
> +  ENTRY_POINT                    = SmbiosCpuDxeEntry
> +
> +[Sources]
> +  SmbiosCpuDxe.c
> +
> +[Packages]
> +  ArmPkg/ArmPkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  MdePkg/MdePkg.dec
> +  Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec
> +  Silicon/Ampere/AmpereSiliconPkg/AmpereSiliconPkg.dec
> +
> +[LibraryClasses]
> +  AmpereCpuLib
> +  ArmLib
> +  BaseLib
> +  BaseMemoryLib
> +  DebugLib
> +  HobLib
> +  MemoryAllocationLib
> +  UefiBootServicesTableLib
> +  UefiDriverEntryPoint
> +  UefiLib
> +
> +[Protocols]
> +  gEfiSmbiosProtocolGuid                     ## CONSUMED
> +
> +[Guids]
> +  gPlatformHobGuid
> +
> +[Depex]
> +  gEfiSmbiosProtocolGuid
> diff --git a/Platform/Ampere/JadePkg/Drivers/SmbiosMemInfoDxe/SmbiosMemInfoDxe.inf b/Platform/Ampere/JadePkg/Drivers/SmbiosMemInfoDxe/SmbiosMemInfoDxe.inf
> new file mode 100644
> index 000000000000..87b9123df856
> --- /dev/null
> +++ b/Platform/Ampere/JadePkg/Drivers/SmbiosMemInfoDxe/SmbiosMemInfoDxe.inf
> @@ -0,0 +1,45 @@
> +#
> +# Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x0001001B
> +  BASE_NAME                      = SmbiosMemInfoDxe
> +  FILE_GUID                      = ECF38190-EBF8-11EA-B646-830715BDF83A
> +  MODULE_TYPE                    = DXE_DRIVER
> +  VERSION_STRING                 = 1.0
> +  ENTRY_POINT                    = SmbiosMemInfoDxeEntry
> +
> +[Sources]
> +  SmbiosMemInfoDxe.c
> +
> +[Packages]
> +  ArmPkg/ArmPkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  MdePkg/MdePkg.dec
> +  Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec
> +  Silicon/Ampere/AmpereSiliconPkg/AmpereSiliconPkg.dec
> +
> +[LibraryClasses]
> +  AmpereCpuLib
> +  ArmLib
> +  BaseLib
> +  BaseMemoryLib
> +  DebugLib
> +  HobLib
> +  MemoryAllocationLib
> +  UefiBootServicesTableLib
> +  UefiDriverEntryPoint
> +  UefiLib
> +
> +[Protocols]
> +  gEfiSmbiosProtocolGuid                     ## CONSUMED
> +
> +[Guids]
> +  gPlatformHobGuid
> +
> +[Depex]
> +  gEfiSmbiosProtocolGuid
> diff --git a/Platform/Ampere/JadePkg/Drivers/SmbiosPlatformDxe/SmbiosPlatformDxe.inf b/Platform/Ampere/JadePkg/Drivers/SmbiosPlatformDxe/SmbiosPlatformDxe.inf
> new file mode 100755
> index 000000000000..73a601b0df08
> --- /dev/null
> +++ b/Platform/Ampere/JadePkg/Drivers/SmbiosPlatformDxe/SmbiosPlatformDxe.inf
> @@ -0,0 +1,52 @@
> +## @file
> +#
> +# Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x0001001B
> +  BASE_NAME                      = SmbiosPlatformDxe
> +  FILE_GUID                      = F0CC7D0B-CD83-4DDA-A5D4-613AB02D4E52
> +  MODULE_TYPE                    = DXE_DRIVER
> +  VERSION_STRING                 = 1.0
> +  ENTRY_POINT                    = SmbiosPlatformDxeEntry
> +
> +[Sources]
> +  SmbiosPlatformDxe.c
> +
> +[Packages]
> +  ArmPkg/ArmPkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  MdePkg/MdePkg.dec
> +  Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec
> +  Silicon/Ampere/AmpereSiliconPkg/AmpereSiliconPkg.dec
> +
> +[LibraryClasses]
> +  BaseLib
> +  BaseMemoryLib
> +  DebugLib
> +  HobLib
> +  MemoryAllocationLib
> +  UefiBootServicesTableLib
> +  UefiDriverEntryPoint
> +  UefiLib
> +
> +[Protocols]
> +  gEfiSmbiosProtocolGuid                     ## CONSUMED
> +
> +[Pcd]
> +  # Type 0
> +  gAmpereTokenSpaceGuid.PcdSmbiosTables0BiosReleaseDate
> +  gAmpereTokenSpaceGuid.PcdSmbiosTables1MajorVersion
> +  gAmpereTokenSpaceGuid.PcdSmbiosTables1MinorVersion
> +
> +  gArmTokenSpaceGuid.PcdFdSize
> +
> +[Guids]
> +  gPlatformHobGuid
> +
> +[Depex]
> +  gEfiSmbiosProtocolGuid
> diff --git a/Platform/Ampere/JadePkg/Drivers/SmbiosCpuDxe/SmbiosCpuDxe.c b/Platform/Ampere/JadePkg/Drivers/SmbiosCpuDxe/SmbiosCpuDxe.c
> new file mode 100644
> index 000000000000..659212a2cc90
> --- /dev/null
> +++ b/Platform/Ampere/JadePkg/Drivers/SmbiosCpuDxe/SmbiosCpuDxe.c
> @@ -0,0 +1,709 @@
> +/** @file
> +
> +  Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include <Uefi.h>
> +
> +#include <Guid/PlatformInfoHobGuid.h>
> +#include <Guid/SmBios.h>
> +#include <Library/AmpereCpuLib.h>
> +#include <Library/ArmLib.h>
> +#include <Library/ArmLib/ArmLibPrivate.h>
> +#include <Library/BaseLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/HobLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/PrintLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <PlatformInfoHob.h>
> +#include <Protocol/Smbios.h>
> +
> +#define CPU_CACHE_LEVEL_MAX 3
> +
> +#define MHZ_SCALE_FACTOR 1000000
> +
> +#define CACHE_SIZE(x)   (UINT16) (0x8000 | (x) >> 16)
> +#define CACHE_SIZE_2(x) (0x80000000 | (x) >> 16)
> +
> +#define TYPE4_ADDITIONAL_STRINGS                                  \
> +  "SOCKET 0\0"                       /* socket type */            \
> +  "Ampere(R)\0"                      /* manufacturer */           \
> +  "Ampere(R) Altra(R) Processor\0"   /* processor description */  \
> +  "NotSet\0"                         /* part number */
> +
> +#define TYPE7_ADDITIONAL_STRINGS                                  \
> +  "L1 Cache\0" /* L1 Cache  */
> +
> +//
> +// Type definition and contents of the default SMBIOS table.
> +// This table covers only the minimum structures required by
> +// the SMBIOS specification (section 6.2, version 3.0)
> +//
> +#pragma pack(1)
> +typedef struct {
> +  SMBIOS_TABLE_TYPE4 Base;
> +  CHAR8              Strings[sizeof (TYPE4_ADDITIONAL_STRINGS)];
> +} ARM_TYPE4;
> +
> +typedef struct {
> +  SMBIOS_TABLE_TYPE7 Base;
> +  CHAR8              Strings[sizeof (TYPE7_ADDITIONAL_STRINGS)];
> +} ARM_TYPE7;
> +
> +#pragma pack()
> +//-------------------------------------
> +//        SMBIOS Platform Common
> +//-------------------------------------
> +enum {
> +  ADDITIONAL_STR_INDEX_1 = 1,
> +  ADDITIONAL_STR_INDEX_2,
> +  ADDITIONAL_STR_INDEX_3,
> +  ADDITIONAL_STR_INDEX_4,
> +  ADDITIONAL_STR_INDEX_5,
> +  ADDITIONAL_STR_INDEX_6,
> +  ADDITIONAL_STR_INDEX_7,
> +  ADDITIONAL_STR_INDEX_8,
> +  ADDITIONAL_STR_INDEX_9,
> +  ADDITIONAL_STR_INDEX_MAX
> +};
> +
> +// Type 4 Processor Socket 0
> +STATIC ARM_TYPE4 mArmDefaultType4Sk0 = {
> +  {
> +    {                                        // SMBIOS_STRUCTURE Hdr
> +      EFI_SMBIOS_TYPE_PROCESSOR_INFORMATION, // UINT8 Type
> +      sizeof (SMBIOS_TABLE_TYPE4),           // UINT8 Length
> +      SMBIOS_HANDLE_PI_RESERVED,
> +    },
> +    ADDITIONAL_STR_INDEX_1,          // socket type
> +    3,                               // processor type CPU
> +    ProcessorFamilyIndicatorFamily2, // processor family, acquire from field2
> +    ADDITIONAL_STR_INDEX_2,          // manufacturer
> +    {{0,},{0.}},                     // processor id
> +    ADDITIONAL_STR_INDEX_3,          // version
> +    {0,0,0,0,0,1},                   // voltage
> +    0,                               // external clock
> +    3000,                            // max speed
> +    3000,                            // current speed
> +    0x41,                            // status
> +    ProcessorUpgradeOther,
> +    0xFFFF,                 // l1 cache handle
> +    0xFFFF,                 // l2 cache handle
> +    0xFFFF,                 // l3 cache handle
> +    0,                      // serial not set
> +    0,                      // asset not set
> +    ADDITIONAL_STR_INDEX_4, // part number
> +    80,                     // core count in socket
> +    80,                     // enabled core count in socket
> +    0,                      // threads per socket
> +    0xEC,                   // processor characteristics
> +    ProcessorFamilyARMv8,   // ARM core
> +  },
> +  TYPE4_ADDITIONAL_STRINGS
> +};
> +
> +// Type 4 Processor Socket 1
> +STATIC ARM_TYPE4 mArmDefaultType4Sk1 = {
> +  {
> +    {                                        // SMBIOS_STRUCTURE Hdr
> +      EFI_SMBIOS_TYPE_PROCESSOR_INFORMATION, // UINT8 Type
> +      sizeof (SMBIOS_TABLE_TYPE4),           // UINT8 Length
> +      SMBIOS_HANDLE_PI_RESERVED,
> +    },
> +    ADDITIONAL_STR_INDEX_1,          // socket type
> +    3,                               // processor type CPU
> +    ProcessorFamilyIndicatorFamily2, // processor family, acquire from field2
> +    ADDITIONAL_STR_INDEX_2,          // manufacturer
> +    {{0,},{0.}},                     // processor id
> +    ADDITIONAL_STR_INDEX_3,          // version
> +    {0,0,0,0,0,1},                   // voltage
> +    0,                               // external clock
> +    3000,                            // max speed
> +    3000,                            // current speed
> +    0x41,                            // status
> +    ProcessorUpgradeOther,
> +    0xFFFF,                 // l1 cache handle
> +    0xFFFF,                 // l2 cache handle
> +    0xFFFF,                 // l3 cache handle
> +    0,                      // serial not set
> +    0,                      // asset not set
> +    ADDITIONAL_STR_INDEX_4, // part number
> +    80,                     // core count in socket
> +    80,                     // enabled core count in socket
> +    0,                      // threads per socket
> +    0xEC,                   // processor characteristics
> +    ProcessorFamilyARMv8,   // ARM core
> +  },
> +  TYPE4_ADDITIONAL_STRINGS
> +};
> +
> +// Type 7 Cache Information
> +STATIC ARM_TYPE7 mArmDefaultType7Sk0L1 = {
> +  {
> +    {                                    // SMBIOS_STRUCTURE Hdr
> +      EFI_SMBIOS_TYPE_CACHE_INFORMATION, // UINT8 Type
> +      sizeof (SMBIOS_TABLE_TYPE7),       // UINT8 Length
> +      SMBIOS_HANDLE_PI_RESERVED,
> +    },
> +    ADDITIONAL_STR_INDEX_1,
> +    0x180,                  // L1 enabled, Write Back
> +    0x8001,                 // 64k i cache max
> +    0x8001,                 // 64k installed
> +    {0, 0, 0, 0, 0, 1},     // SRAM type
> +    {0, 0, 0, 0, 0, 1},     // SRAM type
> +    0,                      // unkown speed
> +    CacheErrorParity,       // parity checking
> +    CacheTypeUnified,       // Unified cache
> +    CacheAssociativity4Way, // 4-way
> +  },
> +  "L1 Cache\0"
> +};
> +
> +// Type 7 Cache Information
> +STATIC ARM_TYPE7 mArmDefaultType7Sk0L2 = {
> +  {
> +    {                                    // SMBIOS_STRUCTURE Hdr
> +      EFI_SMBIOS_TYPE_CACHE_INFORMATION, // UINT8 Type
> +      sizeof (SMBIOS_TABLE_TYPE7),       // UINT8 Length
> +      SMBIOS_HANDLE_PI_RESERVED,
> +    },
> +    ADDITIONAL_STR_INDEX_1,
> +    0x181,                  // L2 enabled, Write Back
> +    0x8010,                 // 1M cache max
> +    0x8010,                 // 1M installed
> +    {0, 0, 0, 0, 0, 1},     // SRAM type
> +    {0, 0, 0, 0, 0, 1},     // SRAM type
> +    0,                      // unkown speed
> +    CacheErrorSingleBit,    // single bit ECC
> +    CacheTypeUnified,       // Unified cache
> +    CacheAssociativity8Way, // 8-way
> +  },
> +  "L2 Cache\0"
> +};
> +
> +// Type 7 Cache Information
> +STATIC ARM_TYPE7 mArmDefaultType7Sk0L3 = {
> +  {
> +    {                                    // SMBIOS_STRUCTURE Hdr
> +      EFI_SMBIOS_TYPE_CACHE_INFORMATION, // UINT8 Type
> +      sizeof (SMBIOS_TABLE_TYPE7),       // UINT8 Length
> +      SMBIOS_HANDLE_PI_RESERVED,
> +    },
> +    ADDITIONAL_STR_INDEX_1,
> +    0x182,                   // L3 enabled, Write Back
> +    0x8200,                  // 32M cache max
> +    0x8200,                  // 32M installed
> +    {0, 0, 0, 0, 0, 1},      // SRAM type
> +    {0, 0, 0, 0, 0, 1},      // SRAM type
> +    0,                       // unkown speed
> +    CacheErrorParity,        // parity checking
> +    CacheTypeUnified,        // Unified cache
> +    CacheAssociativity16Way, // 16-way
> +  },
> +  "L3 Cache\0"
> +};
> +
> +// Type 7 Cache Information
> +STATIC ARM_TYPE7 mArmDefaultType7Sk1L1 = {
> +  {
> +    {                                    // SMBIOS_STRUCTURE Hdr
> +      EFI_SMBIOS_TYPE_CACHE_INFORMATION, // UINT8 Type
> +      sizeof (SMBIOS_TABLE_TYPE7),       // UINT8 Length
> +      SMBIOS_HANDLE_PI_RESERVED,
> +    },
> +    ADDITIONAL_STR_INDEX_1,
> +    0x180,                  // L1 enabled, Write Back
> +    0x8001,                 // 64k i cache max
> +    0x8001,                 // 64k installed
> +    {0, 0, 0, 0, 0, 1},     // SRAM type
> +    {0, 0, 0, 0, 0, 1},     // SRAM type
> +    0,                      // unkown speed
> +    CacheErrorParity,       // parity checking
> +    CacheTypeUnified,       // Unified cache
> +    CacheAssociativity4Way, // 4-way
> +  },
> +  "L1 Cache\0"
> +};
> +
> +// Type 7 Cache Information
> +STATIC ARM_TYPE7 mArmDefaultType7Sk1L2 = {
> +  {
> +    {                                    // SMBIOS_STRUCTURE Hdr
> +      EFI_SMBIOS_TYPE_CACHE_INFORMATION, // UINT8 Type
> +      sizeof (SMBIOS_TABLE_TYPE7),       // UINT8 Length
> +      SMBIOS_HANDLE_PI_RESERVED,
> +    },
> +    ADDITIONAL_STR_INDEX_1,
> +    0x181,                  // L2 enabled, Write Back
> +    0x8010,                 // 1M cache max
> +    0x8010,                 // 1M installed
> +    {0, 0, 0, 0, 0, 1},     // SRAM type
> +    {0, 0, 0, 0, 0, 1},     // SRAM type
> +    0,                      // unkown speed
> +    CacheErrorSingleBit,    // single bit ECC
> +    CacheTypeUnified,       // Unified cache
> +    CacheAssociativity8Way, // 8-way
> +  },
> +  "L2 Cache\0"
> +};
> +
> +// Type 7 Cache Information
> +STATIC ARM_TYPE7 mArmDefaultType7Sk1L3 = {
> +  {
> +    {                                    // SMBIOS_STRUCTURE Hdr
> +      EFI_SMBIOS_TYPE_CACHE_INFORMATION, // UINT8 Type
> +      sizeof (SMBIOS_TABLE_TYPE7),       // UINT8 Length
> +      SMBIOS_HANDLE_PI_RESERVED,
> +    },
> +    ADDITIONAL_STR_INDEX_1,
> +    0x182,                   // L3 enabled, Write Back
> +    0x8200,                  // 32M cache max
> +    0x8200,                  // 32M installed
> +    {0, 0, 0, 0, 0, 1},      // SRAM type
> +    {0, 0, 0, 0, 0, 1},      // SRAM type
> +    0,                       // unkown speed
> +    CacheErrorParity,        // parity checking
> +    CacheTypeUnified,        // Unified cache
> +    CacheAssociativity16Way, // 16-way
> +  },
> +  "L3 Cache\0"
> +};
> +
> +STATIC CONST VOID *DefaultCommonTables[] =
> +{
> +  &mArmDefaultType4Sk0,
> +  &mArmDefaultType4Sk1,
> +  NULL
> +};
> +
> +STATIC CONST VOID *DefaultType7Sk0Tables[] =
> +{
> +  &mArmDefaultType7Sk0L1,
> +  &mArmDefaultType7Sk0L2,
> +  &mArmDefaultType7Sk0L3,
> +  NULL
> +};
> +
> +STATIC CONST VOID *DefaultType7Sk1Tables[] =
> +{
> +  &mArmDefaultType7Sk1L1,
> +  &mArmDefaultType7Sk1L2,
> +  &mArmDefaultType7Sk1L3,
> +  NULL
> +};
> +
> +STATIC
> +UINT32
> +GetCacheConfig (
> +  UINT32 Level
> +  )
> +{
> +  UINT64  Val;
> +  BOOLEAN SupportWB;
> +  BOOLEAN SupportWT;
> +
> +  Val = ReadCCSIDR (Level);
> +  SupportWT = (Val & (1 << 31)) ? TRUE : FALSE;
> +  SupportWB = (Val & (1 << 30)) ? TRUE : FALSE;
> +  if (SupportWT && SupportWB) {
> +    return 2; /* Varies with Memory Address */
> +  }
> +
> +  if (SupportWT) {
> +    return 0;
> +  }
> +
> +  return 1; /* WB */
> +}
> +
> +STATIC
> +UINTN
> +GetStringPackSize (
> +  CHAR8 *StringPack
> +  )
> +{
> +  UINTN StrCount;
> +  CHAR8 *StrStart;
> +
> +  if ((*StringPack == 0) && (*(StringPack + 1) == 0)) {
> +    return 0;
> +  }
> +
> +  // String section ends in double-null (0000h)
> +  for (StrCount = 0, StrStart = StringPack;
> +       ((*StrStart != 0) || (*(StrStart + 1) != 0)); StrStart++, StrCount++)
> +  {
> +  }
> +
> +  return StrCount + 2; // Included the double NULL
> +}
> +
> +// Update String at String number to String Pack
> +EFI_STATUS
> +UpdateStringPack (
> +  CHAR8 *StringPack,
> +  CHAR8 *String,
> +  UINTN StringNumber
> +  )
> +{
> +  CHAR8 *StrStart;
> +  UINTN StrIndex;
> +  UINTN InputStrLen;
> +  UINTN TargetStrLen;
> +  UINTN BufferSize;
> +  CHAR8 *Buffer;
> +
> +  StrStart = StringPack;
> +  for (StrIndex = 1; StrIndex < StringNumber; StrStart++) {
> +    // A string ends in 00h
> +    if (*StrStart == 0) {
> +      StrIndex++;
> +    }
> +    // String section ends in double-null (0000h)
> +    if ((*StrStart == 0) && (*(StrStart + 1) == 0)) {
> +      return EFI_NOT_FOUND;
> +    }
> +  }
> +
> +  if (*StrStart == 0) {
> +    StrStart++;
> +  }
> +
> +  InputStrLen = AsciiStrLen (String);
> +  TargetStrLen = AsciiStrLen (StrStart);
> +  BufferSize = GetStringPackSize (StrStart + TargetStrLen + 1);
> +
> +  // Replace the String if length matched
> +  // OR this is the last string
> +  if (InputStrLen == TargetStrLen || (BufferSize == 0)) {
> +    CopyMem (StrStart, String, InputStrLen);
> +  }
> +  // Otherwise, buffer is needed to apply new string
> +  else {

Move else to same line as {

Apart from that, with the understanding that this is a work in
progress, but provides some value already:

Reviewed-by: Leif Lindholm <leif at nuviainc.com>

For the improvement works, I would appreciate if you could look at
what we've done so far both with regards to ArmPkg/Universal/Smbios
and the helper functions added for that, to see how we could reduce
the amount of platform-specific code.

/
    Leif

> +    Buffer = AllocateZeroPool (BufferSize);
> +    if (Buffer == NULL) {
> +      return EFI_OUT_OF_RESOURCES;
> +    }
> +
> +    CopyMem (Buffer, StrStart + TargetStrLen + 1, BufferSize);
> +    CopyMem (StrStart, String, InputStrLen + 1);
> +    CopyMem (StrStart + InputStrLen + 1, Buffer, BufferSize);
> +
> +    FreePool (Buffer);
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +STATIC
> +VOID
> +UpdateSmbiosType4 (
> +  PLATFORM_INFO_HOB  *PlatformHob
> +  )
> +{
> +  UINTN              Index;
> +  CHAR8              Str[40];
> +  CHAR8              *StringPack;
> +  SMBIOS_TABLE_TYPE4 *Table;
> +
> +  ASSERT (PlatformHob != NULL);
> +
> +  for (Index = 0; Index < GetNumberOfSupportedSockets (); Index++) {
> +    if (Index == 0) {
> +      Table = &mArmDefaultType4Sk0.Base;
> +      StringPack = mArmDefaultType4Sk0.Strings;
> +    } else {
> +      Table = &mArmDefaultType4Sk1.Base;
> +      StringPack = mArmDefaultType4Sk1.Strings;
> +    }
> +
> +    AsciiSPrint (Str, sizeof (Str), "CPU %d", Index);
> +    UpdateStringPack (StringPack, Str, ADDITIONAL_STR_INDEX_1);
> +
> +    Table->CoreCount = (UINT8)GetMaximumNumberOfCores ();
> +    Table->ThreadCount = (UINT8)GetMaximumNumberOfCores ();
> +    Table->EnabledCoreCount = (UINT8)GetNumberOfActiveCoresPerSocket (Index);
> +
> +    if (Table->EnabledCoreCount) {
> +      Table->CurrentSpeed = (UINT16)(PlatformHob->CpuClk / MHZ_SCALE_FACTOR);
> +      Table->ExternalClock = (UINT16)(PlatformHob->PcpClk / MHZ_SCALE_FACTOR);
> +      Table->MaxSpeed = (UINT16)(PlatformHob->CpuClk / MHZ_SCALE_FACTOR);
> +      if (PlatformHob->TurboCapability[Index]) {
> +        Table->MaxSpeed = (UINT16)(PlatformHob->TurboFrequency[Index]);
> +      }
> +    } else {
> +      Table->CurrentSpeed = 0;
> +      Table->ExternalClock = 0;
> +      Table->MaxSpeed = 0;
> +      Table->Status = 0;
> +    }
> +
> +    *((UINT32 *)&Table->ProcessorId) = (UINT32)ArmReadMidr ();
> +    *((UINT32 *)&Table->ProcessorId + 1) = 0;
> +    *((UINT8 *)&Table->Voltage) = 0x80 | PlatformHob->CoreVoltage[Index] / 100;
> +
> +    /* Type 4 Part number */
> +    if (Table->EnabledCoreCount) {
> +      if ((PlatformHob->ScuProductId[Index] & 0xff) == 0x01) {
> +        AsciiSPrint (
> +          Str,
> +          sizeof (Str),
> +          "Q%02d-%02X",
> +          PlatformHob->SkuMaxCore[Index],
> +          PlatformHob->SkuMaxTurbo[Index]
> +          );
> +      } else {
> +        AsciiSPrint (
> +          Str,
> +          sizeof (Str),
> +          "M%02d%02X",
> +          PlatformHob->SkuMaxCore[Index],
> +          PlatformHob->SkuMaxTurbo[Index]
> +          );
> +      }
> +
> +      UpdateStringPack (StringPack, Str, ADDITIONAL_STR_INDEX_4);
> +    }
> +  }
> +}
> +
> +STATIC
> +VOID
> +UpdateSmbiosType7 (
> +  PLATFORM_INFO_HOB  *PlatformHob
> +  )
> +{
> +  UINTN              Index;
> +  SMBIOS_TABLE_TYPE7 *Table;
> +
> +  ASSERT (PlatformHob != NULL);
> +
> +  for (Index = 0; Index < GetNumberOfSupportedSockets (); Index++) {
> +    if (Index == 0) {
> +      Table = &mArmDefaultType7Sk0L1.Base;
> +    } else {
> +      Table = &mArmDefaultType7Sk1L1.Base;
> +    }
> +
> +    Table->Associativity = (UINT8)CpuGetAssociativity (1);
> +    Table->CacheConfiguration = (1 << 7 | GetCacheConfig (1) << 8); /* Enabled, Internal, L1 */
> +    Table->MaximumCacheSize  = CACHE_SIZE (CpuGetCacheSize (1));
> +    Table->InstalledSize     = CACHE_SIZE (CpuGetCacheSize (1));
> +    Table->MaximumCacheSize2 = CACHE_SIZE_2 (CpuGetCacheSize (1));
> +    Table->InstalledSize2    = CACHE_SIZE_2 (CpuGetCacheSize (1));
> +
> +    if (Index == 0) {
> +      Table = &mArmDefaultType7Sk0L2.Base;
> +    } else {
> +      Table = &mArmDefaultType7Sk1L2.Base;
> +    }
> +
> +    Table->Associativity = (UINT8)CpuGetAssociativity (2);
> +    Table->CacheConfiguration = (1 << 7 | GetCacheConfig (2) << 8 | 1); /* Enabled, Internal, L2 */
> +    Table->MaximumCacheSize  = CACHE_SIZE (CpuGetCacheSize (2));
> +    Table->InstalledSize     = CACHE_SIZE (CpuGetCacheSize (2));
> +    Table->MaximumCacheSize2 = CACHE_SIZE_2 (CpuGetCacheSize (2));
> +    Table->InstalledSize2    = CACHE_SIZE_2 (CpuGetCacheSize (2));
> +
> +    if (Index == 0) {
> +      Table = &mArmDefaultType7Sk0L3.Base;
> +    } else {
> +      Table = &mArmDefaultType7Sk1L3.Base;
> +    }
> +
> +    // CpuGetCacheSize() not return L3 size, set it to 32MB
> +    Table->MaximumCacheSize  = CACHE_SIZE (32 << 20);
> +    Table->InstalledSize     = CACHE_SIZE (32 << 20);
> +    Table->MaximumCacheSize2 = CACHE_SIZE_2 (32 << 20);
> +    Table->InstalledSize2    = CACHE_SIZE_2 (32 << 20);
> +  }
> +
> +  if (GetNumberOfSupportedSockets () == 2 && GetNumberOfActiveCoresPerSocket (1) == 0) {
> +    mArmDefaultType7Sk1L1.Base.InstalledSize = 0;
> +    mArmDefaultType7Sk1L1.Base.InstalledSize2 = 0;
> +    mArmDefaultType7Sk1L2.Base.InstalledSize = 0;
> +    mArmDefaultType7Sk1L2.Base.InstalledSize2 = 0;
> +    mArmDefaultType7Sk1L3.Base.InstalledSize = 0;
> +    mArmDefaultType7Sk1L3.Base.InstalledSize2 = 0;
> +  }
> +
> +}
> +
> +STATIC
> +VOID
> +UpdateSmbiosInfo (
> +  VOID
> +  )
> +{
> +  VOID               *Hob;
> +  PLATFORM_INFO_HOB  *PlatformHob;
> +
> +  /* Get the Platform HOB */
> +  Hob = GetFirstGuidHob (&gPlatformHobGuid);
> +  ASSERT (Hob != NULL);
> +  if (Hob == NULL) {
> +    return;
> +  }
> +
> +  PlatformHob = (PLATFORM_INFO_HOB *)GET_GUID_HOB_DATA (Hob);
> +
> +  UpdateSmbiosType4 (PlatformHob);
> +  UpdateSmbiosType7 (PlatformHob);
> +}
> +
> +/**
> +   Install SMBIOS Type 7 table
> +
> +   @param  Smbios               SMBIOS protocol.
> +**/
> +EFI_STATUS
> +InstallType7Structures (
> +  IN EFI_SMBIOS_PROTOCOL *Smbios
> +  )
> +{
> +  EFI_STATUS         Status = EFI_SUCCESS;
> +  EFI_SMBIOS_HANDLE  SmbiosHandle;
> +  SMBIOS_TABLE_TYPE4 *Type4Table;
> +  CONST VOID         **Tables;
> +  UINTN              Index;
> +  UINTN              Level;
> +
> +  for ( Index = 0; Index < GetNumberOfSupportedSockets (); Index++ ) {
> +    if ( Index == 0) {
> +      Tables = DefaultType7Sk0Tables;
> +      Type4Table = &mArmDefaultType4Sk0.Base;
> +    } else {
> +      Tables = DefaultType7Sk1Tables;
> +      Type4Table = &mArmDefaultType4Sk1.Base;
> +    }
> +
> +    for (Level = 0; Level < CPU_CACHE_LEVEL_MAX; Level++ ) {
> +      SmbiosHandle = ((EFI_SMBIOS_TABLE_HEADER *)Tables[Level])->Handle;
> +      Status = Smbios->Add (
> +                         Smbios,
> +                         NULL,
> +                         &SmbiosHandle,
> +                         (EFI_SMBIOS_TABLE_HEADER *)Tables[Level]
> +                         );
> +      if (EFI_ERROR (Status)) {
> +        DEBUG ((
> +          DEBUG_ERROR,
> +          "%a: adding SMBIOS type 7 Socket %d L%d cache failed\n",
> +          __FUNCTION__,
> +          Index,
> +          Level + 1
> +          ));
> +        // stop adding rather than continuing
> +        return Status;
> +      }
> +
> +      // Save handle to Type 4
> +      if (Level == 0) { // L1 cache
> +        Type4Table->L1CacheHandle = SmbiosHandle;
> +      } else if (Level == 1) { // L2 cache
> +        Type4Table->L2CacheHandle = SmbiosHandle;
> +      } else if (Level == 2) { // L3 cache
> +        Type4Table->L3CacheHandle = SmbiosHandle;
> +      }
> +    }
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +   Install a whole table worth of structructures
> +
> +   @param  Smbios               SMBIOS protocol.
> +   @param  DefaultTables        A pointer to the default SMBIOS table structure.
> +**/
> +EFI_STATUS
> +InstallStructures (
> +  IN       EFI_SMBIOS_PROTOCOL *Smbios,
> +  IN CONST VOID                *DefaultTables[]
> +  )
> +{
> +  EFI_STATUS        Status = EFI_SUCCESS;
> +  EFI_SMBIOS_HANDLE SmbiosHandle;
> +  UINTN             Index;
> +
> +  for (Index = 0; Index < GetNumberOfSupportedSockets () && DefaultTables[Index] != NULL; Index++) {
> +    SmbiosHandle = ((EFI_SMBIOS_TABLE_HEADER *)DefaultTables[Index])->Handle;
> +    Status = Smbios->Add (
> +                       Smbios,
> +                       NULL,
> +                       &SmbiosHandle,
> +                       (EFI_SMBIOS_TABLE_HEADER *)DefaultTables[Index]
> +                       );
> +    if (EFI_ERROR (Status)) {
> +      DEBUG ((DEBUG_ERROR, "%a: adding %d failed\n", __FUNCTION__, Index));
> +
> +      // stop adding rather than continuing
> +      return Status;
> +    }
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +   Install all structures from the DefaultTables structure
> +
> +   @param  Smbios               SMBIOS protocol
> +
> +**/
> +EFI_STATUS
> +InstallAllStructures (
> +  IN EFI_SMBIOS_PROTOCOL *Smbios
> +  )
> +{
> +  EFI_STATUS Status = EFI_SUCCESS;
> +
> +  UpdateSmbiosInfo ();
> +
> +  // Install Type 7 structures
> +  InstallType7Structures (Smbios);
> +
> +  // Install Tables
> +  Status = InstallStructures (Smbios, DefaultCommonTables);
> +  ASSERT_EFI_ERROR (Status);
> +
> +  return Status;
> +}
> +
> +
> +EFI_STATUS
> +EFIAPI
> +SmbiosCpuDxeEntry (
> +  IN EFI_HANDLE       ImageHandle,
> +  IN EFI_SYSTEM_TABLE *SystemTable
> +  )
> +{
> +  EFI_STATUS          Status;
> +  EFI_SMBIOS_PROTOCOL *Smbios;
> +
> +  //
> +  // Find the SMBIOS protocol
> +  //
> +  Status = gBS->LocateProtocol (
> +                  &gEfiSmbiosProtocolGuid,
> +                  NULL,
> +                  (VOID **)&Smbios
> +                  );
> +
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "Unable to locate SMBIOS Protocol"));
> +    ASSERT_EFI_ERROR (Status);
> +    return Status;
> +  }
> +
> +  Status = InstallAllStructures (Smbios);
> +  DEBUG ((DEBUG_ERROR, "SmbiosCpu install: %r\n", Status));
> +
> +  return Status;
> +}
> diff --git a/Platform/Ampere/JadePkg/Drivers/SmbiosMemInfoDxe/SmbiosMemInfoDxe.c b/Platform/Ampere/JadePkg/Drivers/SmbiosMemInfoDxe/SmbiosMemInfoDxe.c
> new file mode 100644
> index 000000000000..a262239b53ba
> --- /dev/null
> +++ b/Platform/Ampere/JadePkg/Drivers/SmbiosMemInfoDxe/SmbiosMemInfoDxe.c
> @@ -0,0 +1,705 @@
> +/** @file
> +
> +  Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include <Uefi.h>
> +
> +#include <Guid/PlatformInfoHobGuid.h>
> +#include <Guid/SmBios.h>
> +#include <Library/AmpereCpuLib.h>
> +#include <Library/ArmLib.h>
> +#include <Library/BaseLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/HobLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/PrintLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <PlatformInfoHob.h>
> +#include <Protocol/Smbios.h>
> +
> +#define TYPE16_ADDITIONAL_STRINGS        \
> +  "\0" /* no string*/
> +
> +#define TYPE17_ADDITIONAL_STRINGS        \
> +  "Device Locator not set \0"  \
> +  "Bank Locator not set \0"    \
> +  "Manufacturer not set \0"    \
> +  "Serial Number not set \0"   \
> +  "Asset Tag not set \0"       \
> +  "Part Number not set \0"     \
> +
> +#define TYPE19_ADDITIONAL_STRINGS        \
> +  "\0" /* no string */
> +
> +//
> +// Type definition and contents of the default SMBIOS table.
> +// This table covers only the minimum structures required by
> +// the SMBIOS specification (section 6.2, version 3.0)
> +//
> +#pragma pack(1)
> +typedef struct {
> +  SMBIOS_TABLE_TYPE16 Base;
> +  CHAR8               Strings[sizeof (TYPE16_ADDITIONAL_STRINGS)];
> +} ARM_TYPE16;
> +
> +typedef struct {
> +  SMBIOS_TABLE_TYPE17 Base;
> +  CHAR8               Strings[sizeof (TYPE17_ADDITIONAL_STRINGS)];
> +} ARM_TYPE17;
> +
> +typedef struct {
> +  SMBIOS_TABLE_TYPE19 Base;
> +  CHAR8               Strings[sizeof (TYPE19_ADDITIONAL_STRINGS)];
> +} ARM_TYPE19;
> +
> +#pragma pack()
> +// Type 16 Physical Memory Array
> +STATIC ARM_TYPE16 mArmDefaultType16 = {
> +  {
> +    {                                        // SMBIOS_STRUCTURE Hdr
> +      EFI_SMBIOS_TYPE_PHYSICAL_MEMORY_ARRAY, // UINT8 Type
> +      sizeof (SMBIOS_TABLE_TYPE16),          // UINT8 Length
> +      SMBIOS_HANDLE_PI_RESERVED,
> +    },
> +    MemoryArrayLocationSystemBoard,   // on motherboard
> +    MemoryArrayUseSystemMemory,       // system RAM
> +    MemoryErrorCorrectionMultiBitEcc, // ECC RAM
> +    0x80000000,
> +    0xFFFE,   // No error information structure
> +    0x10,
> +    0x40000000000ULL,
> +  },
> +  TYPE16_ADDITIONAL_STRINGS
> +};
> +
> +// Type 17 Memory Device
> +STATIC ARM_TYPE17 mArmDefaultType17 = {
> +  {
> +    { // SMBIOS_STRUCTURE Hdr
> +      EFI_SMBIOS_TYPE_MEMORY_DEVICE,
> +      sizeof (SMBIOS_TABLE_TYPE17),
> +      SMBIOS_HANDLE_PI_RESERVED,
> +    },
> +    0xFFFF,                         // array to which this module belongs
> +    0xFFFE,                         // no errors
> +    72,                             // single DIMM with ECC
> +    64,                             // data width of this device (64-bits)
> +    0,                              // no module installed
> +    0x09,                           // DIMM
> +    1,                              // part of a set
> +    1,                              // device locator
> +    2,                              // bank locator
> +    MemoryTypeDdr4,                 // DDR4
> +    {},                             // type detail
> +    0,                              // ? MHz
> +    3,                              // manufacturer
> +    4,                              // serial
> +    5,                              // asset tag
> +    6,                              // part number
> +    0,                              // rank
> +  },
> +  TYPE17_ADDITIONAL_STRINGS
> +};
> +
> +// Type 19 Memory Array Mapped Address
> +STATIC ARM_TYPE19 mArmDefaultType19 = {
> +  {
> +    {  // SMBIOS_STRUCTURE Hdr
> +      EFI_SMBIOS_TYPE_MEMORY_ARRAY_MAPPED_ADDRESS,
> +      sizeof (SMBIOS_TABLE_TYPE19),
> +      SMBIOS_HANDLE_PI_RESERVED,
> +    },
> +    0xFFFFFFFF, // invalid, look at extended addr field
> +    0xFFFFFFFF,
> +    0xFFFF,    // handle
> +    1,
> +    0x0,
> +    0x0,
> +  },
> +  TYPE19_ADDITIONAL_STRINGS
> +};
> +
> +typedef struct _JEDEC_MF_ID {
> +  UINT8 VendorId;
> +  CHAR8 *ManufacturerString;
> +} JEDEC_MF_ID;
> +
> +JEDEC_MF_ID Bank0Table[] = {
> +  { 0x01, "AMD" },
> +  { 0x04, "Fujitsu" },
> +  { 0x07, "Hitachi" },
> +  { 0x89, "Intel" },
> +  { 0x10, "NEC" },
> +  { 0x97, "Texas Instrument" },
> +  { 0x98, "Toshiba" },
> +  { 0x1c, "Mitsubishi" },
> +  { 0x1f, "Atmel" },
> +  { 0x20, "STMicroelectronics" },
> +  { 0xa4, "IBM" },
> +  { 0x2c, "Micron Technology" },
> +  { 0xad, "SK Hynix" },
> +  { 0xb0, "Sharp" },
> +  { 0xb3, "IDT" },
> +  { 0x3e, "Oracle" },
> +  { 0xbf, "SST" },
> +  { 0x40, "ProMos/Mosel" },
> +  { 0xc1, "Infineon" },
> +  { 0xc2, "Macronix" },
> +  { 0x45, "SanDisk" },
> +  { 0xce, "Samsung" },
> +  { 0xda, "Winbond" },
> +  { 0xe0, "LG Semi" },
> +  { 0x62, "Sanyo" },
> +  { 0xff, "Undefined" }
> +};
> +
> +JEDEC_MF_ID Bank1Table[] = {
> +  { 0x98, "Kingston" },
> +  { 0xba, "PNY" },
> +  { 0x4f, "Transcend" },
> +  { 0x7a, "Apacer" },
> +  { 0xff, "Undefined" }
> +};
> +
> +JEDEC_MF_ID Bank2Table[] = {
> +  { 0x9e, "Corsair" },
> +  { 0xfe, "Elpida" },
> +  { 0xff, "Undefined" }
> +};
> +
> +JEDEC_MF_ID Bank3Table[] = {
> +  { 0x0b, "Nanya" },
> +  { 0x94, "Mushkin" },
> +  { 0x25, "Kingmax" },
> +  { 0xff, "Undefined" }
> +};
> +
> +JEDEC_MF_ID Bank4Table[] = {
> +  { 0xb0, "OCZ" },
> +  { 0xcb, "A-DATA" },
> +  { 0xcd, "G Skill" },
> +  { 0xef, "Team" },
> +  { 0xff, "Undefined" }
> +};
> +
> +JEDEC_MF_ID Bank5Table[] = {
> +  { 0x02, "Patriot" },
> +  { 0x9b, "Crucial" },
> +  { 0x51, "Qimonda" },
> +  { 0x57, "AENEON" },
> +  { 0xf7, "Avant" },
> +  { 0xff, "Undefined" }
> +};
> +
> +JEDEC_MF_ID Bank6Table[] = {
> +  { 0x34, "Super Talent" },
> +  { 0xd3, "Silicon Power" },
> +  { 0xff, "Undefined" }
> +};
> +
> +JEDEC_MF_ID Bank7Table[] = {
> +  { 0xff, "Undefined" }
> +};
> +
> +JEDEC_MF_ID *ManufacturerJedecIdBankTable[] = {
> +  Bank0Table,
> +  Bank1Table,
> +  Bank2Table,
> +  Bank3Table,
> +  Bank4Table,
> +  Bank5Table,
> +  Bank6Table,
> +  Bank7Table
> +};
> +
> +STATIC
> +UINTN
> +GetStringPackSize (
> +  CHAR8 *StringPack
> +  )
> +{
> +  UINTN StrCount;
> +  CHAR8 *StrStart;
> +
> +  if ((*StringPack == 0) && (*(StringPack + 1) == 0)) {
> +    return 0;
> +  }
> +
> +  // String section ends in double-null (0000h)
> +  for (StrCount = 0, StrStart = StringPack;
> +       ((*StrStart != 0) || (*(StrStart + 1) != 0)); StrStart++, StrCount++)
> +  {
> +  }
> +
> +  return StrCount + 2; // Included the double NULL
> +}
> +
> +// Update String at String number to String Pack
> +EFI_STATUS
> +UpdateStringPack (
> +  CHAR8 *StringPack,
> +  CHAR8 *String,
> +  UINTN StringNumber
> +  )
> +{
> +  CHAR8 *StrStart;
> +  UINTN StrIndex;
> +  UINTN InputStrLen;
> +  UINTN TargetStrLen;
> +  UINTN BufferSize;
> +  CHAR8 *Buffer;
> +
> +  StrStart = StringPack;
> +  for (StrIndex = 1; StrIndex < StringNumber; StrStart++) {
> +    // A string ends in 00h
> +    if (*StrStart == 0) {
> +      StrIndex++;
> +    }
> +    // String section ends in double-null (0000h)
> +    if ((*StrStart == 0) && (*(StrStart + 1) == 0)) {
> +      return EFI_NOT_FOUND;
> +    }
> +  }
> +
> +  if (*StrStart == 0) {
> +    StrStart++;
> +  }
> +
> +  InputStrLen = AsciiStrLen (String);
> +  TargetStrLen = AsciiStrLen (StrStart);
> +  BufferSize = GetStringPackSize (StrStart + TargetStrLen + 1);
> +
> +  // Replace the String if length matched
> +  // OR this is the last string
> +  if ((InputStrLen == TargetStrLen) || (BufferSize == 0)) {
> +    CopyMem (StrStart, String, InputStrLen);
> +  }
> +  // Otherwise, buffer is needed to apply new string
> +  else {
> +    Buffer = AllocateZeroPool (BufferSize);
> +    if (Buffer == NULL) {
> +      return EFI_OUT_OF_RESOURCES;
> +    }
> +
> +    CopyMem (Buffer, StrStart + TargetStrLen + 1, BufferSize);
> +    CopyMem (StrStart, String, InputStrLen + 1);
> +    CopyMem (StrStart + InputStrLen + 1, Buffer, BufferSize);
> +
> +    FreePool (Buffer);
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +UINT8
> +GetMemoryType (
> +  IN UINT8 *SpdData
> +  )
> +{
> +  return (SpdData[2] == 0x08) ? 1 :    // DDR2
> +         (SpdData[2] == 0x0B) ? 2 :    // DDR3
> +         (SpdData[2] == 0x0C) ? 3 : 0; // DDR4
> +}
> +
> +EFI_STATUS
> +UpdateManufacturer (
> +  IN VOID  *Table,
> +  IN UINT8 *SpdData
> +  )
> +{
> +  EFI_STATUS  Status = EFI_SUCCESS;
> +  UINTN       i;
> +  UINT8       Data8;
> +  UINT8       MemType;
> +  JEDEC_MF_ID *IdTblPtr = NULL;
> +
> +  MemType = GetMemoryType (SpdData);
> +
> +  switch (MemType) {
> +  case 1:
> +    for (i = 0; i < 8; i++) {      // DDR2
> +      Data8 = SpdData[64 + i];
> +      if (Data8 != 0x7f) {
> +        break;
> +      }
> +    }
> +    break;
> +
> +  case 2:                    // DDR3
> +    i = SpdData[117] & 0x7f; // Remove parity bit
> +    Data8 = SpdData[118];
> +    break;
> +
> +  case 3:                    // DDR4
> +    i = SpdData[320] & 0x7f; // Remove parity bit
> +    Data8 = SpdData[321];
> +    break;
> +
> +  default:
> +    return EFI_UNSUPPORTED;  // Not supported
> +  }
> +
> +  if (i > 7) {
> +    i = 7;
> +  }
> +  IdTblPtr = ManufacturerJedecIdBankTable[i];
> +
> +  // Search in Manufacturer table
> +  while ((IdTblPtr->VendorId != Data8) && (IdTblPtr->VendorId != 0xff)) {
> +    IdTblPtr++;
> +  }
> +
> +  if (IdTblPtr->VendorId != 0xff) {
> +    Status = UpdateStringPack (
> +               ((ARM_TYPE17 *)Table)->Strings,
> +               IdTblPtr->ManufacturerString,
> +               ((ARM_TYPE17 *)Table)->Base.Manufacturer
> +               );
> +  }
> +
> +  return Status;
> +}
> +
> +EFI_STATUS
> +UpdateSerialNumber (
> +  IN VOID  *Table,
> +  IN UINT8 *SpdData
> +  )
> +{
> +  UINT8 MemType;
> +  UINTN Offset;
> +  CHAR8 Str[64];
> +
> +  MemType = GetMemoryType (SpdData);
> +
> +  switch (MemType) {
> +  case 1:
> +    Offset = 95;
> +    break;
> +
> +  case 2:                          // DDR3
> +    Offset = 122;
> +    break;
> +
> +  case 3:                          // DDR4
> +    Offset = 325;
> +    break;
> +
> +  default:
> +    return EFI_UNSUPPORTED;        // Not supported
> +  }
> +
> +  AsciiSPrint (
> +    Str,
> +    sizeof (Str),
> +    "%02X%02X%02X%02X",
> +    SpdData[Offset],
> +    SpdData[Offset + 1],
> +    SpdData[Offset + 2],
> +    SpdData[Offset + 3]
> +    );
> +
> +  return UpdateStringPack (
> +           ((ARM_TYPE17 *)Table)->Strings,
> +           Str,
> +           ((ARM_TYPE17 *)Table)->Base.SerialNumber
> +           );
> +}
> +
> +CHAR8
> +Printable (
> +  IN CHAR8 Character
> +  )
> +{
> +  if((Character >= 0x20) && (Character <= 0x7E)) {
> +    return Character;
> +  }
> +
> +  return ' ';
> +}
> +
> +EFI_STATUS
> +UpdatePartNumber (
> +  IN VOID  *Table,
> +  IN UINT8 *SpdData
> +  )
> +{
> +  UINT8 MemType;
> +  UINTN Offset;
> +  CHAR8 Str[64];
> +
> +  MemType = GetMemoryType (SpdData);
> +
> +  switch (MemType) {
> +  case 1:
> +    Offset = 73;
> +    break;
> +
> +  case 2:                          // DDR3
> +    Offset = 128;
> +    break;
> +
> +  case 3:                          // DDR4
> +    Offset = 329;
> +    break;
> +
> +  default:
> +    return EFI_UNSUPPORTED;        // Not supported
> +  }
> +
> +  AsciiSPrint (
> +    Str,
> +    sizeof (Str),
> +    "%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c",
> +    Printable (SpdData[Offset]),
> +    Printable (SpdData[Offset + 1]),
> +    Printable (SpdData[Offset + 2]),
> +    Printable (SpdData[Offset + 3]),
> +    Printable (SpdData[Offset + 4]),
> +    Printable (SpdData[Offset + 5]),
> +    Printable (SpdData[Offset + 6]),
> +    Printable (SpdData[Offset + 7]),
> +    Printable (SpdData[Offset + 8]),
> +    Printable (SpdData[Offset + 9]),
> +    Printable (SpdData[Offset + 10]),
> +    Printable (SpdData[Offset + 11]),
> +    Printable (SpdData[Offset + 12]),
> +    Printable (SpdData[Offset + 13]),
> +    Printable (SpdData[Offset + 14]),
> +    Printable (SpdData[Offset + 15]),
> +    Printable (SpdData[Offset + 16]),
> +    Printable (SpdData[Offset + 17])
> +    );
> +
> +  return UpdateStringPack (
> +           ((ARM_TYPE17 *)Table)->Strings,
> +           Str,
> +           ((ARM_TYPE17 *)Table)->Base.PartNumber
> +           );
> +}
> +
> +/**
> +   Install SMBIOS Type 16 17 and 19 table
> +
> +   @param  Smbios               SMBIOS protocol.
> +**/
> +EFI_STATUS
> +InstallMemStructures (
> +  IN EFI_SMBIOS_PROTOCOL *Smbios
> +  )
> +{
> +  EFI_STATUS         Status = EFI_SUCCESS;
> +  EFI_SMBIOS_HANDLE  SmbiosHandle;
> +  EFI_SMBIOS_HANDLE  Type16Handle;
> +  PLATFORM_INFO_HOB  *PlatformHob;
> +  PLATFORM_DIMM      *Dimm;
> +  CHAR8              *Table;
> +  VOID               *Hob;
> +  UINTN              Index;
> +  UINTN              SlotIndex;
> +  UINTN              MemRegionIndex;
> +  UINT64             MemorySize = 0;
> +  CHAR8              Str[64];
> +
> +  ASSERT (Smbios != NULL);
> +
> +  /* Get the Platform HOB */
> +  Hob = GetFirstGuidHob (&gPlatformHobGuid);
> +  ASSERT (Hob != NULL);
> +  if (Hob == NULL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  PlatformHob = (PLATFORM_INFO_HOB *)GET_GUID_HOB_DATA (Hob);
> +
> +  Table = AllocateZeroPool (sizeof (ARM_TYPE17));
> +  if (Table == NULL) {
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  for ( Index = 0; Index < GetNumberOfSupportedSockets (); Index++ ) {
> +    // Copy template to Type 16
> +    CopyMem (Table, (VOID *)&mArmDefaultType16, sizeof (ARM_TYPE16));
> +
> +    ((ARM_TYPE16 *)Table)->Base.MaximumCapacity = 0x80000000;
> +    ((ARM_TYPE16 *)Table)->Base.ExtendedMaximumCapacity = 0x40000000000ULL; /* 4TB per socket */
> +    ((ARM_TYPE16 *)Table)->Base.MemoryErrorCorrection = MemoryErrorCorrectionMultiBitEcc;
> +
> +    // Install Type 16 and hold the handle so that the subsequence type17/19 could use
> +    Type16Handle = ((ARM_TYPE16 *)Table)->Base.Hdr.Handle;
> +    Status = Smbios->Add (
> +                       Smbios,
> +                       NULL,
> +                       &Type16Handle,
> +                       (EFI_SMBIOS_TABLE_HEADER *)Table
> +                       );
> +    if (EFI_ERROR (Status)) {
> +      DEBUG ((DEBUG_ERROR, "%a: adding SMBIOS type 16 socket %d failed\n", __FUNCTION__, Index));
> +      FreePool (Table);
> +      // stop adding rather than continuing
> +      return Status;
> +    }
> +
> +    for (SlotIndex = 0; SlotIndex < PlatformHob->DimmList.BoardDimmSlots; SlotIndex++) {
> +      // Copy Tempplate to Type 17
> +      CopyMem (Table, (VOID *)&mArmDefaultType17, sizeof (ARM_TYPE17));
> +
> +      // Fill up type 17 table's content here
> +      Dimm = &PlatformHob->DimmList.Dimm[SlotIndex];
> +      if (Dimm->NodeId != Index) {
> +        continue;
> +      }
> +
> +      if (Dimm->Info.DimmStatus == DIMM_INSTALLED_OPERATIONAL) {
> +
> +        UpdateManufacturer ((VOID *)Table, Dimm->SpdData.Data);
> +        UpdateSerialNumber ((VOID *)Table, Dimm->SpdData.Data);
> +        UpdatePartNumber ((VOID *)Table, Dimm->SpdData.Data);
> +
> +        MemorySize = Dimm->Info.DimmSize * 1024;
> +        if (MemorySize >= 0x7FFF) {
> +          ((ARM_TYPE17 *)Table)->Base.Size = 0x7FFF;
> +          ((ARM_TYPE17 *)Table)->Base.ExtendedSize = MemorySize;
> +        } else {
> +          ((ARM_TYPE17 *)Table)->Base.Size = (UINT16)MemorySize;
> +          ((ARM_TYPE17 *)Table)->Base.ExtendedSize = 0;
> +        }
> +
> +        ((ARM_TYPE17 *)Table)->Base.MemoryType = 0x1A; /* DDR4 */
> +        ((ARM_TYPE17 *)Table)->Base.Speed = (UINT16)PlatformHob->DramInfo.MaxSpeed;
> +        ((ARM_TYPE17 *)Table)->Base.ConfiguredMemoryClockSpeed = (UINT16)PlatformHob->DramInfo.MaxSpeed;
> +        ((ARM_TYPE17 *)Table)->Base.Attributes = Dimm->Info.DimmNrRank & 0x0F;
> +        ((ARM_TYPE17 *)Table)->Base.ConfiguredVoltage = 1200;
> +        ((ARM_TYPE17 *)Table)->Base.MinimumVoltage = 1140;
> +        ((ARM_TYPE17 *)Table)->Base.MaximumVoltage = 1260;
> +        ((ARM_TYPE17 *)Table)->Base.DeviceSet = 0; // None
> +
> +        if (Dimm->Info.DimmType == UDIMM || Dimm->Info.DimmType == SODIMM) {
> +          ((ARM_TYPE17 *)Table)->Base.TypeDetail.Unbuffered = 1; /* BIT 14: unregistered */
> +        } else if (Dimm->Info.DimmType == RDIMM
> +                   || Dimm->Info.DimmType == LRDIMM
> +                   || Dimm->Info.DimmType == RSODIMM)
> +        {
> +          ((ARM_TYPE17 *)Table)->Base.TypeDetail.Registered = 1; /* BIT 13: registered */
> +        }
> +        /* FIXME: Determine if need to set technology to NVDIMM-* when supported */
> +        ((ARM_TYPE17 *)Table)->Base.MemoryTechnology = 0x3; // DRAM
> +      }
> +      AsciiSPrint (Str, sizeof (Str), "Socket %d DIMM %d", Index, SlotIndex);
> +      UpdateStringPack (((ARM_TYPE17 *)Table)->Strings, Str, ((ARM_TYPE17 *)Table)->Base.DeviceLocator);
> +      AsciiSPrint (Str, sizeof (Str), "Bank %d", SlotIndex);
> +      UpdateStringPack (((ARM_TYPE17 *)Table)->Strings, Str, ((ARM_TYPE17 *)Table)->Base.BankLocator);
> +      AsciiSPrint (Str, sizeof (Str), "Array %d Asset Tag %d", Index, SlotIndex);
> +      UpdateStringPack (((ARM_TYPE17 *)Table)->Strings, Str, ((ARM_TYPE17 *)Table)->Base.AssetTag);
> +
> +      // Update Type 16 handle
> +      ((ARM_TYPE17 *)Table)->Base.MemoryArrayHandle = Type16Handle;
> +
> +      // Install structure
> +      SmbiosHandle = ((ARM_TYPE17 *)Table)->Base.Hdr.Handle;
> +      Status = Smbios->Add (
> +                         Smbios,
> +                         NULL,
> +                         &SmbiosHandle,
> +                         (EFI_SMBIOS_TABLE_HEADER *)Table
> +                         );
> +      if (EFI_ERROR (Status)) {
> +        DEBUG ((
> +          DEBUG_ERROR,
> +          "%a: adding SMBIOS type 17 Socket %d Slot %d failed\n",
> +          __FUNCTION__,
> +          Index,
> +          SlotIndex
> +          ));
> +        FreePool (Table);
> +        // stop adding rather than continuing
> +        return Status;
> +      }
> +    }
> +
> +    for (MemRegionIndex = 0; MemRegionIndex < PlatformHob->DramInfo.NumRegion; MemRegionIndex++) {
> +      // Copy Tempplate to Type 19
> +      CopyMem (Table, (VOID *)&mArmDefaultType19, sizeof (ARM_TYPE19));
> +
> +      if (PlatformHob->DramInfo.NvdRegion[MemRegionIndex] > 0
> +          || PlatformHob->DramInfo.Socket[MemRegionIndex] != Index)
> +      {
> +        continue;
> +      }
> +
> +      ((ARM_TYPE19 *)Table)->Base.StartingAddress = 0xFFFFFFFF;
> +      ((ARM_TYPE19 *)Table)->Base.EndingAddress = 0xFFFFFFFF;
> +      ((ARM_TYPE19 *)Table)->Base.ExtendedStartingAddress = PlatformHob->DramInfo.Base[MemRegionIndex];
> +      ((ARM_TYPE19 *)Table)->Base.ExtendedEndingAddress = PlatformHob->DramInfo.Base[MemRegionIndex] +
> +                                                          PlatformHob->DramInfo.Size[MemRegionIndex] - 1;
> +
> +      if (MemorySize != 0) {
> +        ((ARM_TYPE19 *)Table)->Base.PartitionWidth = (PlatformHob->DramInfo.Size[MemRegionIndex] - 1) / MemorySize + 1;
> +      }
> +
> +      // Update Type 16 handle
> +      ((ARM_TYPE19 *)Table)->Base.MemoryArrayHandle = Type16Handle;
> +
> +      // Install structure
> +      SmbiosHandle = ((ARM_TYPE19 *)Table)->Base.Hdr.Handle;
> +      Status = Smbios->Add (
> +                         Smbios,
> +                         NULL,
> +                         &SmbiosHandle,
> +                         (EFI_SMBIOS_TABLE_HEADER *)Table
> +                         );
> +      if (EFI_ERROR (Status)) {
> +        DEBUG ((
> +          DEBUG_ERROR,
> +          "%a: adding SMBIOS type 19 Socket %d MemRegion %d failed\n",
> +          __FUNCTION__,
> +          Index,
> +          MemRegionIndex
> +          ));
> +        FreePool (Table);
> +        // stop adding rather than continuing
> +        return Status;
> +      }
> +    }
> +  }
> +
> +  FreePool (Table);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +EFI_STATUS
> +EFIAPI
> +SmbiosMemInfoDxeEntry (
> +  IN EFI_HANDLE       ImageHandle,
> +  IN EFI_SYSTEM_TABLE *SystemTable
> +  )
> +{
> +  EFI_STATUS          Status;
> +  EFI_SMBIOS_PROTOCOL *Smbios;
> +
> +  //
> +  // Find the SMBIOS protocol
> +  //
> +  Status = gBS->LocateProtocol (
> +                  &gEfiSmbiosProtocolGuid,
> +                  NULL,
> +                  (VOID **)&Smbios
> +                  );
> +
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "Unable to locate SMBIOS Protocol"));
> +    ASSERT_EFI_ERROR (Status);
> +    return Status;
> +  }
> +
> +  Status = InstallMemStructures (Smbios);
> +  DEBUG ((DEBUG_ERROR, "SmbiosMemInfoDxe install: %r\n", Status));
> +
> +  return Status;
> +}
> diff --git a/Platform/Ampere/JadePkg/Drivers/SmbiosPlatformDxe/SmbiosPlatformDxe.c b/Platform/Ampere/JadePkg/Drivers/SmbiosPlatformDxe/SmbiosPlatformDxe.c
> new file mode 100644
> index 000000000000..086fdd9749fb
> --- /dev/null
> +++ b/Platform/Ampere/JadePkg/Drivers/SmbiosPlatformDxe/SmbiosPlatformDxe.c
> @@ -0,0 +1,1049 @@
> +/** @file
> +
> +  Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include <Uefi.h>
> +
> +#include <Guid/PlatformInfoHobGuid.h>
> +#include <Guid/SmBios.h>
> +#include <Library/BaseLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/HobLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <PlatformInfoHob.h>
> +#include <Protocol/Smbios.h>
> +
> +// Type0 Data
> +#define VENDOR_TEMPLATE       "Ampere(R)\0"
> +#define BIOS_VERSION_TEMPLATE "TianoCore EDKII\0"
> +#define RELEASE_DATE_TEMPLATE "MM/DD/YYYY\0"
> +
> +#define TYPE0_ADDITIONAL_STRINGS                    \
> +  VENDOR_TEMPLATE       /* Vendor */         \
> +  BIOS_VERSION_TEMPLATE /* BiosVersion */    \
> +  RELEASE_DATE_TEMPLATE /* BiosReleaseDate */
> +
> +// Type1 Data
> +#define MANUFACTURER_TEMPLATE "Ampere(R)\0"
> +#define PRODUCT_NAME_TEMPLATE "Mt. Jade\0"
> +#define SYS_VERSION_TEMPLATE  "PR010\0"
> +#define SERIAL_TEMPLATE       "123456789ABCDEFF123456789ABCDEFF\0"
> +#define SKU_TEMPLATE          "FEDCBA9876543211FEDCBA9876543211\0"
> +#define FAMILY_TEMPLATE       "ARMv8\0"
> +
> +#define TYPE1_ADDITIONAL_STRINGS                  \
> +  MANUFACTURER_TEMPLATE /* Manufacturer */  \
> +  PRODUCT_NAME_TEMPLATE /* Product Name */  \
> +  SYS_VERSION_TEMPLATE  /* Version */       \
> +  SERIAL_TEMPLATE       /* Serial Number */ \
> +  SKU_TEMPLATE          /* SKU Number */    \
> +  FAMILY_TEMPLATE       /* Family */
> +
> +#define TYPE2_ADDITIONAL_STRINGS                   \
> +  MANUFACTURER_TEMPLATE /* Manufacturer */   \
> +  PRODUCT_NAME_TEMPLATE /* Product Name */   \
> +  "EVT2\0"              /* Version */        \
> +  "Serial Not Set\0"    /* Serial */         \
> +  "Base of Chassis\0"   /* board location */ \
> +  "FF\0"                /* Version */        \
> +  "FF\0"                /* Version */
> +
> +#define CHASSIS_VERSION_TEMPLATE    "None               \0"
> +#define CHASSIS_SERIAL_TEMPLATE     "Serial Not Set     \0"
> +#define CHASSIS_ASSET_TAG_TEMPLATE  "Asset Tag Not Set  \0"
> +
> +#define TYPE3_ADDITIONAL_STRINGS                 \
> +  MANUFACTURER_TEMPLATE      /* Manufacturer */ \
> +  CHASSIS_VERSION_TEMPLATE   /* Version */      \
> +  CHASSIS_SERIAL_TEMPLATE    /* Serial  */      \
> +  CHASSIS_ASSET_TAG_TEMPLATE /* Asset Tag */    \
> +  SKU_TEMPLATE               /* SKU Number */
> +
> +#define TYPE8_ADDITIONAL_STRINGS      \
> +  "VGA1 - Rear VGA Connector\0"       \
> +  "DB-15 Male (VGA)         \0"
> +
> +#define TYPE9_ADDITIONAL_STRINGS       \
> +  "Socket 0 Riser 1 x32 - Slot 1\0"
> +
> +#define TYPE11_ADDITIONAL_STRINGS       \
> +  "www.amperecomputing.com\0"
> +
> +#define TYPE13_ADDITIONAL_STRINGS       \
> +  "en|US|iso8859-1\0"
> +
> +#define TYPE41_ADDITIONAL_STRINGS       \
> +  "Onboard VGA\0"
> +
> +//
> +// Type definition and contents of the default SMBIOS table.
> +// This table covers only the minimum structures required by
> +// the SMBIOS specification (section 6.2, version 3.0)
> +//
> +#pragma pack(1)
> +typedef struct {
> +  SMBIOS_TABLE_TYPE0 Base;
> +  CHAR8              Strings[sizeof (TYPE0_ADDITIONAL_STRINGS)];
> +} ARM_TYPE0;
> +
> +typedef struct {
> +  SMBIOS_TABLE_TYPE1 Base;
> +  CHAR8              Strings[sizeof (TYPE1_ADDITIONAL_STRINGS)];
> +} ARM_TYPE1;
> +
> +typedef struct {
> +  SMBIOS_TABLE_TYPE2 Base;
> +  CHAR8              Strings[sizeof (TYPE2_ADDITIONAL_STRINGS)];
> +} ARM_TYPE2;
> +
> +typedef struct {
> +  SMBIOS_TABLE_TYPE3 Base;
> +  CHAR8              Strings[sizeof (TYPE3_ADDITIONAL_STRINGS)];
> +} ARM_TYPE3;
> +
> +typedef struct {
> +  SMBIOS_TABLE_TYPE8 Base;
> +  CHAR8              Strings[sizeof (TYPE8_ADDITIONAL_STRINGS)];
> +} ARM_TYPE8;
> +
> +typedef struct {
> +  SMBIOS_TABLE_TYPE9 Base;
> +  CHAR8              Strings[sizeof (TYPE9_ADDITIONAL_STRINGS)];
> +} ARM_TYPE9;
> +
> +typedef struct {
> +  SMBIOS_TABLE_TYPE11 Base;
> +  CHAR8               Strings[sizeof (TYPE11_ADDITIONAL_STRINGS)];
> +} ARM_TYPE11;
> +
> +typedef struct {
> +  SMBIOS_TABLE_TYPE13 Base;
> +  CHAR8               Strings[sizeof (TYPE13_ADDITIONAL_STRINGS)];
> +} ARM_TYPE13;
> +
> +typedef struct {
> +  SMBIOS_TABLE_TYPE41 Base;
> +  CHAR8               Strings[sizeof (TYPE41_ADDITIONAL_STRINGS)];
> +} ARM_TYPE41;
> +
> +#pragma pack()
> +
> +//-------------------------------------
> +//        SMBIOS Platform Common
> +//-------------------------------------
> +enum {
> +  ADDITIONAL_STR_INDEX_1 = 1,
> +  ADDITIONAL_STR_INDEX_2,
> +  ADDITIONAL_STR_INDEX_3,
> +  ADDITIONAL_STR_INDEX_4,
> +  ADDITIONAL_STR_INDEX_5,
> +  ADDITIONAL_STR_INDEX_6,
> +  ADDITIONAL_STR_INDEX_MAX
> +};
> +
> +
> +// Type 0 BIOS information
> +STATIC ARM_TYPE0 mArmDefaultType0 = {
> +  {
> +    {                                   // Header
> +      EFI_SMBIOS_TYPE_BIOS_INFORMATION, // UINT8 Type
> +      sizeof (SMBIOS_TABLE_TYPE0),      // UINT8 Length, The length of the structure's string-set is not included.
> +      SMBIOS_HANDLE_PI_RESERVED,
> +    },
> +
> +    ADDITIONAL_STR_INDEX_1,     // SMBIOS_TABLE_STRING       Vendor
> +    ADDITIONAL_STR_INDEX_2,     // SMBIOS_TABLE_STRING       BiosVersion
> +    0,                          // UINT16                    BiosSegment
> +    ADDITIONAL_STR_INDEX_3,     // SMBIOS_TABLE_STRING       BiosReleaseDate
> +    0,                          // UINT8                     BiosSize
> +
> +    // MISC_BIOS_CHARACTERISTICS BiosCharacteristics
> +    {
> +      0,0,0,0,0,0,
> +      1, // PCI supported
> +      0,
> +      1, // PNP supported
> +      0,
> +      1, // BIOS upgradable
> +      0, 0, 0,
> +      0, // Boot from CD
> +      1, // selectable boot
> +    },
> +
> +    // BIOSCharacteristicsExtensionBytes[2]
> +    {
> +      0,
> +      0,
> +    },
> +
> +    0,     // UINT8                     SystemBiosMajorRelease
> +    0,     // UINT8                     SystemBiosMinorRelease
> +
> +    // If the system does not have field upgradeable embedded controller
> +    // firmware, the value is 0FFh
> +    0xFF,  // UINT8                     EmbeddedControllerFirmwareMajorRelease
> +    0xFF   // UINT8                     EmbeddedControllerFirmwareMinorRelease
> +  },
> +
> +  // Text strings (unformatted area)
> +  TYPE0_ADDITIONAL_STRINGS
> +};
> +
> +// Type 1 System information
> +STATIC ARM_TYPE1 mArmDefaultType1 = {
> +  {
> +    { // Header
> +      EFI_SMBIOS_TYPE_SYSTEM_INFORMATION,
> +      sizeof (SMBIOS_TABLE_TYPE1),
> +      SMBIOS_HANDLE_PI_RESERVED,
> +    },
> +
> +    ADDITIONAL_STR_INDEX_1,                                                     // Manufacturer
> +    ADDITIONAL_STR_INDEX_2,                                                     // Product Name
> +    ADDITIONAL_STR_INDEX_3,                                                     // Version
> +    ADDITIONAL_STR_INDEX_4,                                                     // Serial Number
> +    { 0x12345678, 0x9ABC, 0xDEFF, { 0x12,0x34,0x56,0x78,0x9A,0xBC,0xDE,0xFF }}, // UUID
> +    SystemWakeupTypePowerSwitch,                                                // Wakeup type
> +    ADDITIONAL_STR_INDEX_5,                                                     // SKU Number
> +    ADDITIONAL_STR_INDEX_6,                                                     // Family
> +  },
> +
> +  // Text strings (unformatted)
> +  TYPE1_ADDITIONAL_STRINGS
> +};
> +
> +// Type 2 Baseboard
> +STATIC ARM_TYPE2 mArmDefaultType2 = {
> +  {
> +    {                                        // SMBIOS_STRUCTURE Hdr
> +      EFI_SMBIOS_TYPE_BASEBOARD_INFORMATION, // UINT8 Type
> +      sizeof (SMBIOS_TABLE_TYPE2),           // UINT8 Length
> +      SMBIOS_HANDLE_PI_RESERVED,
> +    },
> +    ADDITIONAL_STR_INDEX_1, // Manufacturer
> +    ADDITIONAL_STR_INDEX_2, // Product Name
> +    ADDITIONAL_STR_INDEX_3, // Version
> +    ADDITIONAL_STR_INDEX_4, // Serial
> +    0,                      // Asset tag
> +    {1},                    // motherboard, not replaceable
> +    ADDITIONAL_STR_INDEX_5, // location of board
> +    0xFFFF,                 // chassis handle
> +    BaseBoardTypeMotherBoard,
> +    0,
> +    {0},
> +  },
> +  TYPE2_ADDITIONAL_STRINGS
> +};
> +
> +// Type 3 Enclosure
> +STATIC CONST ARM_TYPE3 mArmDefaultType3 = {
> +  {
> +    {                                   // SMBIOS_STRUCTURE Hdr
> +      EFI_SMBIOS_TYPE_SYSTEM_ENCLOSURE, // UINT8 Type
> +      sizeof (SMBIOS_TABLE_TYPE3),      // UINT8 Length
> +      SMBIOS_HANDLE_PI_RESERVED,
> +    },
> +    ADDITIONAL_STR_INDEX_1,          // Manufacturer
> +    MiscChassisTypeRackMountChassis, // Rack-mounted chassis
> +    ADDITIONAL_STR_INDEX_2,          // version
> +    ADDITIONAL_STR_INDEX_3,          // serial
> +    ADDITIONAL_STR_INDEX_4,          // asset tag
> +    ChassisStateUnknown,             // boot chassis state
> +    ChassisStateSafe,                // power supply state
> +    ChassisStateSafe,                // thermal state
> +    ChassisSecurityStatusNone,       // security state
> +    {0,0,0,0},                       // OEM defined
> +    1,                               // 1U height
> +    2,                               // number of power cords
> +    0,                               // no contained elements
> +    3,                               // ContainedElementRecordLength;
> +  },
> +  TYPE3_ADDITIONAL_STRINGS
> +};
> +
> +// Type 8 Port Connector Information
> +STATIC CONST ARM_TYPE8 mArmDefaultType8Vga = {
> +  {
> +    {                                             // SMBIOS_STRUCTURE Hdr
> +      EFI_SMBIOS_TYPE_PORT_CONNECTOR_INFORMATION, // UINT8 Type
> +      sizeof (SMBIOS_TABLE_TYPE8),                // UINT8 Length
> +      SMBIOS_HANDLE_PI_RESERVED,
> +    },
> +    ADDITIONAL_STR_INDEX_1,       // InternalReferenceDesignator String
> +    PortConnectorTypeDB15Female,  // InternalConnectorType;
> +    ADDITIONAL_STR_INDEX_2,       // ExternalReferenceDesignator String
> +    PortTypeOther,                // ExternalConnectorType;
> +    PortTypeVideoPort,            // PortType;
> +  },
> +  "VGA1 - Rear VGA Connector\0" \
> +  "DB-15 Male (VGA)\0"
> +};
> +
> +// Type 8 Port Connector Information
> +STATIC CONST ARM_TYPE8 mArmDefaultType8USBFront = {
> +  {
> +    {                                             // SMBIOS_STRUCTURE Hdr
> +      EFI_SMBIOS_TYPE_PORT_CONNECTOR_INFORMATION, // UINT8 Type
> +      sizeof (SMBIOS_TABLE_TYPE8),                // UINT8 Length
> +      SMBIOS_HANDLE_PI_RESERVED,
> +    },
> +    ADDITIONAL_STR_INDEX_1,       // InternalReferenceDesignator String
> +    PortConnectorTypeUsb,         // InternalConnectorType;
> +    ADDITIONAL_STR_INDEX_2,       // ExternalReferenceDesignator String
> +    PortTypeOther,                // ExternalConnectorType;
> +    PortTypeUsb,                  // PortType;
> +  },
> +  "Front Panel USB 3.0\0"  \
> +  "USB\0"
> +};
> +
> +// Type 8 Port Connector Information
> +STATIC CONST ARM_TYPE8 mArmDefaultType8USBRear = {
> +  {
> +    {                                             // SMBIOS_STRUCTURE Hdr
> +      EFI_SMBIOS_TYPE_PORT_CONNECTOR_INFORMATION, // UINT8 Type
> +      sizeof (SMBIOS_TABLE_TYPE8),                // UINT8 Length
> +      SMBIOS_HANDLE_PI_RESERVED,
> +    },
> +    ADDITIONAL_STR_INDEX_1,       // InternalReferenceDesignator String
> +    PortConnectorTypeUsb,         // InternalConnectorType;
> +    ADDITIONAL_STR_INDEX_2,       // ExternalReferenceDesignator String
> +    PortTypeOther,                // ExternalConnectorType;
> +    PortTypeUsb,                  // PortType;
> +  },
> +  "Rear Panel USB 3.0\0"   \
> +  "USB\0"
> +};
> +
> +// Type 8 Port Connector Information
> +STATIC CONST ARM_TYPE8 mArmDefaultType8NetRJ45 = {
> +  {
> +    {                                             // SMBIOS_STRUCTURE Hdr
> +      EFI_SMBIOS_TYPE_PORT_CONNECTOR_INFORMATION, // UINT8 Type
> +      sizeof (SMBIOS_TABLE_TYPE8),                // UINT8 Length
> +      SMBIOS_HANDLE_PI_RESERVED,
> +    },
> +    ADDITIONAL_STR_INDEX_1,       // InternalReferenceDesignator String
> +    PortConnectorTypeRJ45,        // InternalConnectorType;
> +    ADDITIONAL_STR_INDEX_2,       // ExternalReferenceDesignator String
> +    PortConnectorTypeRJ45,        // ExternalConnectorType;
> +    PortTypeNetworkPort,          // PortType;
> +  },
> +  "RJ1 - BMC RJ45 Port\0" \
> +  "RJ45 Connector\0"
> +};
> +
> +// Type 8 Port Connector Information
> +STATIC CONST ARM_TYPE8 mArmDefaultType8NetOcp = {
> +  {
> +    {                                             // SMBIOS_STRUCTURE Hdr
> +      EFI_SMBIOS_TYPE_PORT_CONNECTOR_INFORMATION, // UINT8 Type
> +      sizeof (SMBIOS_TABLE_TYPE8),                // UINT8 Length
> +      SMBIOS_HANDLE_PI_RESERVED,
> +    },
> +    ADDITIONAL_STR_INDEX_1,       // InternalReferenceDesignator String
> +    PortTypeOther,                // InternalConnectorType;
> +    ADDITIONAL_STR_INDEX_2,       // ExternalReferenceDesignator String
> +    PortTypeOther,                // ExternalConnectorType;
> +    PortTypeNetworkPort,          // PortType;
> +  },
> +  "OCP1 - OCP NIC 3.0 Connector\0"  \
> +  "OCP NIC 3.0\0"
> +};
> +
> +// Type 8 Port Connector Information
> +STATIC CONST ARM_TYPE8 mArmDefaultType8Uart = {
> +  {
> +    {                                             // SMBIOS_STRUCTURE Hdr
> +      EFI_SMBIOS_TYPE_PORT_CONNECTOR_INFORMATION, // UINT8 Type
> +      sizeof (SMBIOS_TABLE_TYPE8),                // UINT8 Length
> +      SMBIOS_HANDLE_PI_RESERVED,
> +    },
> +    ADDITIONAL_STR_INDEX_1,        // InternalReferenceDesignator String
> +    PortTypeOther,                 // InternalConnectorType;
> +    ADDITIONAL_STR_INDEX_2,        // ExternalReferenceDesignator String
> +    PortConnectorTypeDB9Female,    // ExternalConnectorType;
> +    PortTypeSerial16550Compatible, // PortType;
> +  },
> +  "UART1 - BMC UART5 Connector\0"  \
> +  "DB-9 female\0"
> +};
> +
> +// Type 9 System Slots
> +STATIC ARM_TYPE9 mArmDefaultType9Sk0RiserX32Slot1 = {
> +  {
> +    {                               // SMBIOS_STRUCTURE Hdr
> +      EFI_SMBIOS_TYPE_SYSTEM_SLOTS, // UINT8 Type
> +      sizeof (SMBIOS_TABLE_TYPE9),  // UINT8 Length
> +      SMBIOS_HANDLE_PI_RESERVED,
> +    },
> +    ADDITIONAL_STR_INDEX_1,
> +    SlotTypePciExpressGen3,
> +    SlotDataBusWidth16X,
> +    SlotUsageAvailable,
> +    SlotLengthLong,
> +    0,
> +    {0, 0, 1}, // Provides 3.3 Volts
> +    {1},       // PME
> +    0,
> +    0,
> +    0,
> +  },
> +  "S0 Riser 1 x32 - Slot 1\0"
> +};
> +
> +// Type 9 System Slots
> +STATIC ARM_TYPE9 mArmDefaultType9Sk0RiserX32Slot2 = {
> +  {
> +    {                               // SMBIOS_STRUCTURE Hdr
> +      EFI_SMBIOS_TYPE_SYSTEM_SLOTS, // UINT8 Type
> +      sizeof (SMBIOS_TABLE_TYPE9),  // UINT8 Length
> +      SMBIOS_HANDLE_PI_RESERVED,
> +    },
> +    ADDITIONAL_STR_INDEX_1,
> +    SlotTypePciExpressGen3,
> +    SlotDataBusWidth8X,
> +    SlotUsageAvailable,
> +    SlotLengthLong,
> +    0,
> +    {0, 0, 1}, // Provides 3.3 Volts
> +    {1},       // PME
> +    4,
> +    0,
> +    0,
> +  },
> +  "S0 Riser x32 - Slot 2\0"
> +};
> +
> +// Type 9 System Slots
> +STATIC ARM_TYPE9 mArmDefaultType9Sk0RiserX32Slot3 = {
> +  {
> +    {                               // SMBIOS_STRUCTURE Hdr
> +      EFI_SMBIOS_TYPE_SYSTEM_SLOTS, // UINT8 Type
> +      sizeof (SMBIOS_TABLE_TYPE9),  // UINT8 Length
> +      SMBIOS_HANDLE_PI_RESERVED,
> +    },
> +    ADDITIONAL_STR_INDEX_1,
> +    SlotTypePciExpressGen3,
> +    SlotDataBusWidth8X,
> +    SlotUsageAvailable,
> +    SlotLengthLong,
> +    0,
> +    {0, 0, 1}, // Provides 3.3 Volts
> +    {1},       // PME
> +    5,
> +    0,
> +    0,
> +  },
> +  "S0 Riser x32 - Slot 3\0"
> +};
> +
> +// Type 9 System Slots
> +STATIC ARM_TYPE9 mArmDefaultType9Sk1RiserX24Slot1 = {
> +  {
> +    {                               // SMBIOS_STRUCTURE Hdr
> +      EFI_SMBIOS_TYPE_SYSTEM_SLOTS, // UINT8 Type
> +      sizeof (SMBIOS_TABLE_TYPE9),  // UINT8 Length
> +      SMBIOS_HANDLE_PI_RESERVED,
> +    },
> +    ADDITIONAL_STR_INDEX_1,
> +    SlotTypePciExpressGen3,
> +    SlotDataBusWidth8X,
> +    SlotUsageAvailable,
> +    SlotLengthLong,
> +    0,
> +    {0, 0, 1}, // Provides 3.3 Volts
> +    {1},       // PME
> +    7,
> +    0,
> +    0,
> +  },
> +  "S1 Riser x24 - Slot 1\0"
> +};
> +
> +// Type 9 System Slots
> +STATIC ARM_TYPE9 mArmDefaultType9Sk1RiserX24Slot2 = {
> +  {
> +    {                               // SMBIOS_STRUCTURE Hdr
> +      EFI_SMBIOS_TYPE_SYSTEM_SLOTS, // UINT8 Type
> +      sizeof (SMBIOS_TABLE_TYPE9),  // UINT8 Length
> +      SMBIOS_HANDLE_PI_RESERVED,
> +    },
> +    ADDITIONAL_STR_INDEX_1,
> +    SlotTypePciExpressGen3,
> +    SlotDataBusWidth8X,
> +    SlotUsageAvailable,
> +    SlotLengthLong,
> +    0,
> +    {0, 0, 1}, // Provides 3.3 Volts
> +    {1},       // PME
> +    8,
> +    0,
> +    0,
> +  },
> +  "S1 Riser x24 - Slot 2\0"
> +};
> +
> +// Type 9 System Slots
> +STATIC ARM_TYPE9 mArmDefaultType9Sk1RiserX24Slot3 = {
> +  {
> +    {                               // SMBIOS_STRUCTURE Hdr
> +      EFI_SMBIOS_TYPE_SYSTEM_SLOTS, // UINT8 Type
> +      sizeof (SMBIOS_TABLE_TYPE9),  // UINT8 Length
> +      SMBIOS_HANDLE_PI_RESERVED,
> +    },
> +    ADDITIONAL_STR_INDEX_1,
> +    SlotTypePciExpressGen3,
> +    SlotDataBusWidth8X,
> +    SlotUsageAvailable,
> +    SlotLengthLong,
> +    0,
> +    {0, 0, 1}, // Provides 3.3 Volts
> +    {1},       // PME
> +    9,
> +    0,
> +    0,
> +  },
> +  "S1 Riser x24 - Slot 3\0"
> +};
> +
> +// Type 9 System Slots
> +STATIC ARM_TYPE9 mArmDefaultType9Sk1RiserX8Slot1 = {
> +  {
> +    {                               // SMBIOS_STRUCTURE Hdr
> +      EFI_SMBIOS_TYPE_SYSTEM_SLOTS, // UINT8 Type
> +      sizeof (SMBIOS_TABLE_TYPE9),  // UINT8 Length
> +      SMBIOS_HANDLE_PI_RESERVED,
> +    },
> +    ADDITIONAL_STR_INDEX_1,
> +    SlotTypePciExpressGen3,
> +    SlotDataBusWidth8X,
> +    SlotUsageAvailable,
> +    SlotLengthLong,
> +    0,
> +    {0, 0, 1}, // Provides 3.3 Volts
> +    {1},       // PME
> +    8,
> +    0,
> +    0,
> +  },
> +  "S1 Riser x8 - Slot 1\0"
> +};
> +
> +// Type 9 System Slots
> +STATIC ARM_TYPE9 mArmDefaultType9Sk0OcpNic = {
> +  {
> +    {                               // SMBIOS_STRUCTURE Hdr
> +      EFI_SMBIOS_TYPE_SYSTEM_SLOTS, // UINT8 Type
> +      sizeof (SMBIOS_TABLE_TYPE9),  // UINT8 Length
> +      SMBIOS_HANDLE_PI_RESERVED,
> +    },
> +    ADDITIONAL_STR_INDEX_1,
> +    SlotTypePciExpressGen3,
> +    SlotDataBusWidth16X,
> +    SlotUsageAvailable,
> +    SlotLengthLong,
> +    0,
> +    {0, 0, 1}, // Provides 3.3 Volts
> +    {1},       // PME
> +    1,
> +    0,
> +    0,
> +  },
> +  "S0 OCP NIC 3.0\0"
> +};
> +
> +// Type 9 System Slots
> +STATIC ARM_TYPE9 mArmDefaultType9Sk1NvmeM2Slot1 = {
> +  {
> +    {                               // SMBIOS_STRUCTURE Hdr
> +      EFI_SMBIOS_TYPE_SYSTEM_SLOTS, // UINT8 Type
> +      sizeof (SMBIOS_TABLE_TYPE9),  // UINT8 Length
> +      SMBIOS_HANDLE_PI_RESERVED,
> +    },
> +    ADDITIONAL_STR_INDEX_1,
> +    SlotTypePciExpressGen3,
> +    SlotDataBusWidth4X,
> +    SlotUsageAvailable,
> +    SlotLengthLong,
> +    0,
> +    {0, 0, 1}, // Provides 3.3 Volts
> +    {1},       // PME
> +    5,
> +    0,
> +    0,
> +  },
> +  "S1 NVMe M.2 - Slot 1\0"
> +};
> +
> +// Type 9 System Slots
> +STATIC ARM_TYPE9 mArmDefaultType9Sk1NvmeM2Slot2 = {
> +  {
> +    {                               // SMBIOS_STRUCTURE Hdr
> +      EFI_SMBIOS_TYPE_SYSTEM_SLOTS, // UINT8 Type
> +      sizeof (SMBIOS_TABLE_TYPE9),  // UINT8 Length
> +      SMBIOS_HANDLE_PI_RESERVED,
> +    },
> +    ADDITIONAL_STR_INDEX_1,
> +    SlotTypePciExpressGen3,
> +    SlotDataBusWidth4X,
> +    SlotUsageAvailable,
> +    SlotLengthLong,
> +    0,
> +    {0, 0, 1}, // Provides 3.3 Volts
> +    {1},       // PME
> +    5,
> +    0,
> +    0,
> +  },
> +  "S1 NVMe M.2 - Slot 2\0"
> +};
> +
> +// Type 11 OEM Strings
> +STATIC ARM_TYPE11 mArmDefaultType11 = {
> +  {
> +    {                               // SMBIOS_STRUCTURE Hdr
> +      EFI_SMBIOS_TYPE_OEM_STRINGS,  // UINT8 Type
> +      sizeof (SMBIOS_TABLE_TYPE11), // UINT8 Length
> +      SMBIOS_HANDLE_PI_RESERVED,
> +    },
> +    ADDITIONAL_STR_INDEX_1
> +  },
> +  TYPE11_ADDITIONAL_STRINGS
> +};
> +
> +// Type 13 BIOS Language Information
> +STATIC ARM_TYPE13 mArmDefaultType13 = {
> +  {
> +    {                                            // SMBIOS_STRUCTURE Hdr
> +      EFI_SMBIOS_TYPE_BIOS_LANGUAGE_INFORMATION, // UINT8 Type
> +      sizeof (SMBIOS_TABLE_TYPE13),              // UINT8 Length
> +      SMBIOS_HANDLE_PI_RESERVED,
> +    },
> +    1,
> +    0,
> +    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
> +    1,
> +  },
> +  TYPE13_ADDITIONAL_STRINGS
> +};
> +
> +// Type 24 Hardware Security
> +STATIC SMBIOS_TABLE_TYPE24 mArmDefaultType24 = {
> +  {                                    // SMBIOS_STRUCTURE Hdr
> +    EFI_SMBIOS_TYPE_HARDWARE_SECURITY, // UINT8 Type
> +    sizeof (SMBIOS_TABLE_TYPE24),      // UINT8 Length
> +    SMBIOS_HANDLE_PI_RESERVED,
> +  },
> +  0
> +};
> +
> +// Type 32 System Boot Information
> +STATIC SMBIOS_TABLE_TYPE32 mArmDefaultType32 = {
> +  {                                          // SMBIOS_STRUCTURE Hdr
> +    EFI_SMBIOS_TYPE_SYSTEM_BOOT_INFORMATION, // UINT8 Type
> +    sizeof (SMBIOS_TABLE_TYPE32),            // UINT8 Length
> +    SMBIOS_HANDLE_PI_RESERVED,
> +  },
> +  {0, 0, 0, 0, 0, 0},
> +  0
> +};
> +
> +// Type 38 IPMI Device Information
> +STATIC SMBIOS_TABLE_TYPE38 mArmDefaultType38 = {
> +  {                                          // SMBIOS_STRUCTURE Hdr
> +    EFI_SMBIOS_TYPE_IPMI_DEVICE_INFORMATION, // UINT8 Type
> +    sizeof (SMBIOS_TABLE_TYPE38),            // UINT8 Length
> +    SMBIOS_HANDLE_PI_RESERVED,
> +  },
> +  IPMIDeviceInfoInterfaceTypeSSIF,
> +  0x20,
> +  0x20,
> +  0xFF,
> +  0x20
> +};
> +
> +// Type 41 Onboard Devices Extended Information
> +STATIC ARM_TYPE41 mArmDefaultType41 = {
> +  {
> +    { // SMBIOS_STRUCTURE Hdr
> +      EFI_SMBIOS_TYPE_ONBOARD_DEVICES_EXTENDED_INFORMATION,
> +      sizeof (SMBIOS_TABLE_TYPE41),
> +      SMBIOS_HANDLE_PI_RESERVED,
> +    },
> +    1,
> +    0x83,  // OnBoardDeviceExtendedTypeVideo, Enabled
> +    1,
> +    4,
> +    2,
> +    0,
> +  },
> +  TYPE41_ADDITIONAL_STRINGS
> +};
> +
> +// Type 42 System Boot Information
> +STATIC SMBIOS_TABLE_TYPE42 mArmDefaultType42 = {
> +  { // SMBIOS_STRUCTURE Hdr
> +    EFI_SMBIOS_TYPE_MANAGEMENT_CONTROLLER_HOST_INTERFACE,
> +    sizeof (SMBIOS_TABLE_TYPE42),
> +    SMBIOS_HANDLE_PI_RESERVED,
> +  },
> +  MCHostInterfaceTypeOemDefined,
> +  4,
> +  {0xFF, 0, 0, 0}
> +};
> +
> +STATIC CONST VOID *DefaultCommonTables[] =
> +{
> +  &mArmDefaultType0,
> +  &mArmDefaultType1,
> +  &mArmDefaultType2,
> +  &mArmDefaultType8Vga,
> +  &mArmDefaultType8USBFront,
> +  &mArmDefaultType8USBRear,
> +  &mArmDefaultType8NetRJ45,
> +  &mArmDefaultType8NetOcp,
> +  &mArmDefaultType8Uart,
> +  &mArmDefaultType9Sk0RiserX32Slot1,
> +  &mArmDefaultType9Sk0RiserX32Slot2,
> +  &mArmDefaultType9Sk0RiserX32Slot3,
> +  &mArmDefaultType9Sk1RiserX24Slot1,
> +  &mArmDefaultType9Sk1RiserX24Slot2,
> +  &mArmDefaultType9Sk1RiserX24Slot3,
> +  &mArmDefaultType9Sk1RiserX8Slot1,
> +  &mArmDefaultType9Sk0OcpNic,
> +  &mArmDefaultType9Sk1NvmeM2Slot1,
> +  &mArmDefaultType9Sk1NvmeM2Slot2,
> +  &mArmDefaultType11,
> +  &mArmDefaultType13,
> +  &mArmDefaultType24,
> +  &mArmDefaultType32,
> +  &mArmDefaultType38,
> +  &mArmDefaultType41,
> +  &mArmDefaultType42,
> +  NULL
> +};
> +
> +typedef struct {
> +  CHAR8 MonthNameStr[4]; // example "Jan", Compiler build date, month
> +  CHAR8 DigitStr[3];     // example "01", Smbios date format, month
> +} MonthStringDig;
> +
> +STATIC MonthStringDig MonthMatch[12] = {
> +  { "Jan", "01" },
> +  { "Feb", "02" },
> +  { "Mar", "03" },
> +  { "Apr", "04" },
> +  { "May", "05" },
> +  { "Jun", "06" },
> +  { "Jul", "07" },
> +  { "Aug", "08" },
> +  { "Sep", "09" },
> +  { "Oct", "10" },
> +  { "Nov", "11" },
> +  { "Dec", "12" }
> +};
> +
> +STATIC
> +VOID
> +ConstructBuildDate (
> +  OUT CHAR8 *DateBuf
> +  )
> +{
> +  UINTN i;
> +
> +  // GCC __DATE__ format is "Feb  2 1996"
> +  // If the day of the month is less than 10, it is padded with a space on the left
> +  CHAR8 *BuildDate = __DATE__;
> +
> +  // SMBIOS spec date string: MM/DD/YYYY
> +  CHAR8 SmbiosDateStr[sizeof (RELEASE_DATE_TEMPLATE)] = { 0 };
> +
> +  SmbiosDateStr[sizeof (RELEASE_DATE_TEMPLATE) - 1] = '\0';
> +
> +  SmbiosDateStr[2] = '/';
> +  SmbiosDateStr[5] = '/';
> +
> +  // Month
> +  for (i = 0; i < sizeof (MonthMatch) / sizeof (MonthMatch[0]); i++) {
> +    if (AsciiStrnCmp (&BuildDate[0], MonthMatch[i].MonthNameStr, AsciiStrLen (MonthMatch[i].MonthNameStr)) == 0) {
> +      CopyMem (&SmbiosDateStr[0], MonthMatch[i].DigitStr, AsciiStrLen (MonthMatch[i].DigitStr));
> +      break;
> +    }
> +  }
> +
> +  // Day
> +  CopyMem (&SmbiosDateStr[3], &BuildDate[4], 2);
> +  if (BuildDate[4] == ' ') {
> +    // day is less then 10, SAPCE filed by compiler, SMBIOS requires 0
> +    SmbiosDateStr[3] = '0';
> +  }
> +
> +  // Year
> +  CopyMem (&SmbiosDateStr[6], &BuildDate[7], 4);
> +
> +  CopyMem (DateBuf, SmbiosDateStr, AsciiStrLen (RELEASE_DATE_TEMPLATE));
> +}
> +
> +STATIC
> +UINT8
> +GetBiosVerMajor (
> +  VOID
> +  )
> +{
> +  return (PcdGet8 (PcdSmbiosTables1MajorVersion));
> +}
> +
> +STATIC
> +UINT8
> +GetBiosVerMinor (
> +  VOID
> +  )
> +{
> +  return (PcdGet8 (PcdSmbiosTables1MinorVersion));
> +}
> +
> +STATIC
> +EFI_STATUS
> +UpdateSmbiosType0 (
> +  PLATFORM_INFO_HOB  *PlatformHob
> +  )
> +{
> +  EFI_STATUS                          Status        = EFI_SUCCESS;
> +  MISC_BIOS_CHARACTERISTICS_EXTENSION *MiscExt      = NULL;
> +  CHAR8                               *ReleaseDateBuf = NULL;
> +  CHAR8                               *PcdReleaseDate = NULL;
> +  CHAR8                               AsciiVersion[32];
> +  UINTN                               Index;
> +
> +  //
> +  //  Update Type0 information
> +  //
> +  ReleaseDateBuf = &mArmDefaultType0.Strings[0]
> +                   + sizeof (VENDOR_TEMPLATE) - 1
> +                   + sizeof (BIOS_VERSION_TEMPLATE) - 1;
> +  PcdReleaseDate = (CHAR8 *)PcdGetPtr (PcdSmbiosTables0BiosReleaseDate);
> +
> +  if (AsciiStrnCmp (PcdReleaseDate, RELEASE_DATE_TEMPLATE, AsciiStrLen (RELEASE_DATE_TEMPLATE)) == 0) {
> +    // If PCD is still template date MM/DD/YYYY, use compiler date
> +    ConstructBuildDate (ReleaseDateBuf);
> +  } else {
> +    // PCD is updated somehow, use PCD date
> +    CopyMem (ReleaseDateBuf, PcdReleaseDate, AsciiStrLen (PcdReleaseDate));
> +  }
> +
> +  if (PcdGet32 (PcdFdSize) < SIZE_16MB) {
> +    mArmDefaultType0.Base.BiosSize = (PcdGet32 (PcdFdSize) / SIZE_64KB) - 1;
> +
> +    mArmDefaultType0.Base.ExtendedBiosSize.Size = 0;
> +    mArmDefaultType0.Base.ExtendedBiosSize.Unit = 0;
> +  } else {
> +    // TODO: Need to update Extended BIOS ROM Size
> +    mArmDefaultType0.Base.BiosSize = 0xFF;
> +
> +    // As a reminder
> +    ASSERT (FALSE);
> +  }
> +
> +  // Type0 BIOS Characteristics Extension Byte 1
> +  MiscExt = (MISC_BIOS_CHARACTERISTICS_EXTENSION *)&(mArmDefaultType0.Base.BIOSCharacteristicsExtensionBytes);
> +
> +  MiscExt->BiosReserved.AcpiIsSupported = 1;
> +
> +  // Type0 BIOS Characteristics Extension Byte 2
> +  MiscExt->SystemReserved.BiosBootSpecIsSupported = 1;
> +  MiscExt->SystemReserved.FunctionKeyNetworkBootIsSupported = 1;
> +  MiscExt->SystemReserved.UefiSpecificationSupported = 1;
> +
> +  // Type0 BIOS Release
> +  // TODO: to decide another way: If the system does not support the use of this
> +  // field, the value is 0FFh
> +  mArmDefaultType0.Base.SystemBiosMajorRelease = GetBiosVerMajor ();
> +  mArmDefaultType0.Base.SystemBiosMinorRelease = GetBiosVerMinor ();
> +
> +  /* Update SMBIOS Type 0 EC Info */
> +  CopyMem (
> +    (VOID *)&AsciiVersion,
> +    (VOID *)&PlatformHob->SmPmProVer,
> +    sizeof (PlatformHob->SmPmProVer)
> +    );
> +  /* The AsciiVersion is formated as "major.minor" */
> +  for (Index = 0; Index < (UINTN)AsciiStrLen (AsciiVersion); Index++) {
> +    if (AsciiVersion[Index] == '.') {
> +      AsciiVersion[Index] = '\0';
> +      break;
> +    }
> +  }
> +
> +  mArmDefaultType0.Base.EmbeddedControllerFirmwareMajorRelease =
> +    (UINT8)AsciiStrDecimalToUintn (AsciiVersion);
> +  mArmDefaultType0.Base.EmbeddedControllerFirmwareMinorRelease =
> +    (UINT8)AsciiStrDecimalToUintn (AsciiVersion + Index + 1);
> +
> +  return Status;
> +}
> +
> +STATIC
> +EFI_STATUS
> +InstallType3Structure (
> +  IN EFI_SMBIOS_PROTOCOL *Smbios
> +  )
> +{
> +  EFI_STATUS          Status = EFI_SUCCESS;
> +  EFI_SMBIOS_HANDLE   SmbiosHandle;
> +
> +  ASSERT (Smbios != NULL);
> +
> +  SmbiosHandle = ((EFI_SMBIOS_TABLE_HEADER*) &mArmDefaultType3)->Handle;
> +  Status = Smbios->Add (
> +                     Smbios,
> +                     NULL,
> +                     &SmbiosHandle,
> +                     (EFI_SMBIOS_TABLE_HEADER *)&mArmDefaultType3
> +                     );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "adding SMBIOS type 3 failed\n"));
> +    // stop adding rather than continuing
> +    return Status;
> +  }
> +
> +  // Save this handle to type 2 table
> +  mArmDefaultType2.Base.ChassisHandle = SmbiosHandle;
> +
> +  return Status;
> +}
> +
> +/**
> +   Install a whole table worth of structures
> +
> +   @param  Smbios               SMBIOS protocol.
> +   @param  DefaultTables        A pointer to the default SMBIOS table structure.
> +**/
> +EFI_STATUS
> +InstallStructures (
> +  IN       EFI_SMBIOS_PROTOCOL *Smbios,
> +  IN CONST VOID                *DefaultTables[]
> +  )
> +{
> +  EFI_STATUS        Status = EFI_SUCCESS;
> +  EFI_SMBIOS_HANDLE SmbiosHandle;
> +  UINTN             TableIndex;
> +
> +  ASSERT (Smbios != NULL);
> +
> +  for (TableIndex = 0; DefaultTables[TableIndex] != NULL; TableIndex++) {
> +    SmbiosHandle = ((EFI_SMBIOS_TABLE_HEADER *)DefaultTables[TableIndex])->Handle;
> +    Status = Smbios->Add (
> +                       Smbios,
> +                       NULL,
> +                       &SmbiosHandle,
> +                       (EFI_SMBIOS_TABLE_HEADER *)DefaultTables[TableIndex]
> +                       );
> +    if (EFI_ERROR (Status)) {
> +      DEBUG ((DEBUG_ERROR, "%a: adding %d failed\n", __FUNCTION__, TableIndex));
> +
> +      // stop adding rather than continuing
> +      return Status;
> +    }
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +STATIC
> +VOID
> +UpdateSmbiosInfo (
> +  VOID
> +  )
> +{
> +  VOID               *Hob;
> +  PLATFORM_INFO_HOB  *PlatformHob;
> +
> +  /* Get the Platform HOB */
> +  Hob = GetFirstGuidHob (&gPlatformHobGuid);
> +  ASSERT (Hob != NULL);
> +  if (Hob == NULL) {
> +    return;
> +  }
> +
> +  PlatformHob = (PLATFORM_INFO_HOB *)GET_GUID_HOB_DATA (Hob);
> +
> +  //
> +  //  Update Type0 information
> +  //
> +  UpdateSmbiosType0 (PlatformHob);
> +
> +}
> +
> +/**
> +   Install all structures from the DefaultTables structure
> +
> +   @param  Smbios               SMBIOS protocol
> +
> +**/
> +EFI_STATUS
> +InstallAllStructures (
> +  IN EFI_SMBIOS_PROTOCOL *Smbios
> +  )
> +{
> +  EFI_STATUS Status = EFI_SUCCESS;
> +
> +  ASSERT (Smbios != NULL);
> +
> +  // Update SMBIOS Tables
> +  UpdateSmbiosInfo ();
> +
> +  // Install Type 3 table
> +  InstallType3Structure (Smbios);
> +
> +  // Install Tables
> +  Status = InstallStructures (Smbios, DefaultCommonTables);
> +  ASSERT_EFI_ERROR (Status);
> +
> +  return Status;
> +}
> +
> +/**
> +   Installs SMBIOS information for ARM platforms
> +
> +   @param ImageHandle     Module's image handle
> +   @param SystemTable     Pointer of EFI_SYSTEM_TABLE
> +
> +   @retval EFI_SUCCESS    Smbios data successfully installed
> +   @retval Other          Smbios data was not installed
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +SmbiosPlatformDxeEntry (
> +  IN EFI_HANDLE       ImageHandle,
> +  IN EFI_SYSTEM_TABLE *SystemTable
> +  )
> +{
> +  EFI_STATUS          Status;
> +  EFI_SMBIOS_PROTOCOL *Smbios;
> +
> +  //
> +  // Find the SMBIOS protocol
> +  //
> +  Status = gBS->LocateProtocol (
> +                  &gEfiSmbiosProtocolGuid,
> +                  NULL,
> +                  (VOID **)&Smbios
> +                  );
> +
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  Status = InstallAllStructures (Smbios);
> +  DEBUG ((DEBUG_ERROR, "SmbiosPlatform install - %r\n", Status));
> +
> +  return Status;
> +}
> -- 
> 2.17.1
> 


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#76156): https://edk2.groups.io/g/devel/message/76156
Mute This Topic: https://groups.io/mt/83097118/1813853
Group Owner: devel+owner at edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [edk2-devel-archive at redhat.com]
-=-=-=-=-=-=-=-=-=-=-=-





More information about the edk2-devel-archive mailing list