[edk2-devel] [PATCH v4 10/10] ArmPkg: Add Universal/Smbios, a generic SMBIOS library for ARM

Sami Mujawar sami.mujawar at arm.com
Tue Dec 29 15:10:22 UTC 2020


Hi Rebecca,

Apologies for the delay in reviewing this patch.
Please find my response inline marked [SAMI].

Regards,

Sami Mujawar

-----Original Message-----
From: devel at edk2.groups.io <devel at edk2.groups.io> On Behalf Of Rebecca Cran via groups.io
Sent: 07 December 2020 05:54 PM
To: devel at edk2.groups.io
Cc: Rebecca Cran <rebecca at nuviainc.com>; Michael D Kinney <michael.d.kinney at intel.com>; Liming Gao <gaoliming at byosoft.com.cn>; Zhiguang Liu <zhiguang.liu at intel.com>; Leif Lindholm <leif at nuviainc.com>; Ard Biesheuvel <Ard.Biesheuvel at arm.com>
Subject: [edk2-devel] [PATCH v4 10/10] ArmPkg: Add Universal/Smbios, a generic SMBIOS library for ARM

Much of the data for the SMBIOS tables is generic, and need not be
duplicated for each platform. This patch series introduces
ArmPkg/Universal/Smbios, which is largely copied from
edk2-platforms/Silicon/HiSilicon/Drivers/Smbios and generates SMBIOS
tables 0,1,2,3,4,713,32 and uses a combination of PCDs and calls into a
new OemMiscLib to get information which varies between platforms.

Signed-off-by: Rebecca Cran <rebecca at nuviainc.com>
---
 ArmPkg/ArmPkg.dec                                                                       |  14 +
 ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClassDxe.inf                   |  56 ++
 ArmPkg/Universal/Smbios/SmbiosMiscDxe/SmbiosMiscDxe.inf                                 |  86 ++
 ArmPkg/Include/Library/OemMiscLib.h                                                     |  95 +++
 ArmPkg/Universal/Smbios/SmbiosMiscDxe/SmbiosMisc.h                                      | 136 ++++
 ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClass.c                        | 835 ++++++++++++++++++++
 ArmPkg/Universal/Smbios/SmbiosMiscDxe/SmbiosMiscDataTable.c                             |  61 ++
 ArmPkg/Universal/Smbios/SmbiosMiscDxe/SmbiosMiscEntryPoint.c                            | 178 +++++
 ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type00/MiscBiosVendorData.c                       |  92 +++
 ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type00/MiscBiosVendorFunction.c                   | 263 ++++++
 ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type01/MiscSystemManufacturerData.c               |  35 +
 ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type01/MiscSystemManufacturerFunction.c           | 173 ++++
 ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type02/MiscBaseBoardManufacturerData.c            |  45 ++
 ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type02/MiscBaseBoardManufacturerFunction.c        | 201 +++++
 ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type03/MiscChassisManufacturerData.c              |  51 ++
 ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type03/MiscChassisManufacturerFunction.c          | 200 +++++
 ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type13/MiscNumberOfInstallableLanguagesData.c     |  32 +
 ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type13/MiscNumberOfInstallableLanguagesFunction.c | 154 ++++
 ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type32/MiscBootInformationData.c                  |  34 +
 ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type32/MiscBootInformationFunction.c              |  67 ++
 ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClassStrings.uni               |  23 +
 ArmPkg/Universal/Smbios/SmbiosMiscDxe/SmbiosMiscLibStrings.uni                          |  21 +
 ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type00/MiscBiosVendor.uni                         |  17 +
 ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type01/MiscSystemManufacturer.uni                 |  20 +
 ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type02/MiscBaseBoardManufacturer.uni              |  20 +
 ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type03/MiscChassisManufacturer.uni                |  17 +
 ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type13/MiscNumberOfInstallableLanguages.uni       |  42 +
 27 files changed, 2968 insertions(+)

diff --git a/ArmPkg/ArmPkg.dec b/ArmPkg/ArmPkg.dec
index eaf1072d9ef3..62683146ed40 100644
--- a/ArmPkg/ArmPkg.dec
+++ b/ArmPkg/ArmPkg.dec
@@ -115,6 +115,20 @@ [PcdsFixedAtBuild.common]
   # The Primary Core is ClusterId[0] & CoreId[0]
   gArmTokenSpaceGuid.PcdArmPrimaryCore|0|UINT32|0x00000037
 
+  #
+  # SMBIOS PCDs
+  #
+  gArmTokenSpaceGuid.PcdSystemProductName|L""|VOID*|0x30000053
+  gArmTokenSpaceGuid.PcdSystemVersion|L""|VOID*|0x30000054
+  gArmTokenSpaceGuid.PcdBaseBoardManufacturer|L""|VOID*|0x30000055
+  gArmTokenSpaceGuid.PcdBaseBoardProductName|L""|VOID*|0x30000056
+  gArmTokenSpaceGuid.PcdBaseBoardVersion|L""|VOID*|0x30000057
+  gArmTokenSpaceGuid.PcdProcessorManufacturer|L""|VOID*|0x30000071
+  gArmTokenSpaceGuid.PcdProcessorVersion|L""|VOID*|0x30000072
+  gArmTokenSpaceGuid.PcdProcessorSerialNumber|L""|VOID*|0x30000073
+  gArmTokenSpaceGuid.PcdProcessorAssetTag|L""|VOID*|0x30000074
+  gArmTokenSpaceGuid.PcdProcessorPartNumber|L""|VOID*|0x30000075
+
   #
   # ARM L2x0 PCDs
   #
diff --git a/ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClassDxe.inf b/ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClassDxe.inf
new file mode 100644
index 000000000000..35e8e830b797
--- /dev/null
+++ b/ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClassDxe.inf
@@ -0,0 +1,56 @@
+#/** @file
+#
+#    Copyright (c) 2015, Hisilicon Limited. All rights reserved.
+#    Copyright (c) 2015, Linaro Limited. All rights reserved.
+#
+#    SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#**/
+
+
+[Defines]
+  INF_VERSION                    = 1.29
+  BASE_NAME                      = ProcessorSubClass
+  FILE_GUID                      = f3fe0e33-ea38-4069-9fb5-be23407207c7
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = ProcessorSubClassEntryPoint
+
+[Sources]
+  ProcessorSubClass.c
+  ProcessorSubClassStrings.uni
+
+[Packages]
+  ArmPkg/ArmPkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  MdePkg/MdePkg.dec
+
+[LibraryClasses]
+  ArmLib
+  ArmSmcLib
+  BaseLib
+  BaseMemoryLib
+  DebugLib
+  HiiLib
+  IoLib
+  MemoryAllocationLib
+  OemMiscLib
+  PcdLib
+  PrintLib
+  UefiDriverEntryPoint
+
+[Protocols]
+  gEfiSmbiosProtocolGuid                       # PROTOCOL ALWAYS_CONSUMED
+
+[Pcd]
+  gArmTokenSpaceGuid.PcdProcessorManufacturer
+  gArmTokenSpaceGuid.PcdProcessorVersion
+  gArmTokenSpaceGuid.PcdProcessorSerialNumber
+  gArmTokenSpaceGuid.PcdProcessorAssetTag
+  gArmTokenSpaceGuid.PcdProcessorPartNumber
+
+[Guids]
+
+
+[Depex]
+  gEfiSmbiosProtocolGuid
diff --git a/ArmPkg/Universal/Smbios/SmbiosMiscDxe/SmbiosMiscDxe.inf b/ArmPkg/Universal/Smbios/SmbiosMiscDxe/SmbiosMiscDxe.inf
new file mode 100644
index 000000000000..2b31317451cd
--- /dev/null
+++ b/ArmPkg/Universal/Smbios/SmbiosMiscDxe/SmbiosMiscDxe.inf
@@ -0,0 +1,86 @@
+## @file
+# Component description file for SmbiosMisc instance.
+#
+# Parses the MiscSubclassDataTable and reports any generated data to the DataHub.
+#  All .uni file who tagged with "ToolCode="DUMMY"" in following file list is included by
+#  MiscSubclassDriver.uni file, the StrGather tool will expand MiscSubclassDriver.uni file
+#  and parse all .uni file.
+#
+# Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2015, Hisilicon Limited. All rights reserved.<BR>
+# Copyright (c) 2015, Linaro Limited. All rights reserved.<BR>
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#
+# Based on files under Nt32Pkg/MiscSubClassPlatformDxe/
+##
+
+
+[Defines]
+  INF_VERSION                    = 1.29
+  BASE_NAME                      = SmbiosMiscDxe
+  FILE_GUID                      = 7e5e26d4-0be9-401f-b5e1-1c2bda7ca777
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = SmbiosMiscEntryPoint
+
+[Sources]
+  SmbiosMisc.h
+  SmbiosMiscDataTable.c
+  SmbiosMiscEntryPoint.c
+  SmbiosMiscLibStrings.uni
+  Type00/MiscBiosVendorData.c
+  Type00/MiscBiosVendorFunction.c
+  Type01/MiscSystemManufacturerData.c
+  Type01/MiscSystemManufacturerFunction.c
+  Type02/MiscBaseBoardManufacturerData.c
+  Type02/MiscBaseBoardManufacturerFunction.c
+  Type03/MiscChassisManufacturerData.c
+  Type03/MiscChassisManufacturerFunction.c
+  Type13/MiscNumberOfInstallableLanguagesData.c
+  Type13/MiscNumberOfInstallableLanguagesFunction.c
+  Type32/MiscBootInformationData.c
+  Type32/MiscBootInformationFunction.c
+
+[Packages]
+  ArmPkg/ArmPkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  MdePkg/MdePkg.dec
+
+[LibraryClasses]
+  BaseLib
+  BaseMemoryLib
+  DebugLib
+  DevicePathLib
+  PcdLib
+  HiiLib
+  HobLib
+  MemoryAllocationLib
+  OemMiscLib
+  UefiBootServicesTableLib
+  UefiDriverEntryPoint
+  UefiLib
+  UefiRuntimeServicesTableLib
+
+[Protocols]
+  gEfiSmbiosProtocolGuid                       # PROTOCOL ALWAYS_CONSUMED
+
+[Pcd]
+  gArmTokenSpaceGuid.PcdFdSize
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareVendor
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareVersionString
+  gArmTokenSpaceGuid.PcdSystemProductName
+  gArmTokenSpaceGuid.PcdSystemVersion
+  gArmTokenSpaceGuid.PcdBaseBoardManufacturer
+  gArmTokenSpaceGuid.PcdBaseBoardProductName
+  gArmTokenSpaceGuid.PcdBaseBoardVersion
+  gArmTokenSpaceGuid.PcdFdBaseAddress
+
+[Guids]
+  gEfiGenericVariableGuid
+
+[Depex]
+  gEfiSmbiosProtocolGuid
+
+
diff --git a/ArmPkg/Include/Library/OemMiscLib.h b/ArmPkg/Include/Library/OemMiscLib.h
new file mode 100644
index 000000000000..4b70fb539e09
--- /dev/null
+++ b/ArmPkg/Include/Library/OemMiscLib.h
@@ -0,0 +1,95 @@
+/** @file
+*
+*  Copyright (c) 2015, Hisilicon Limited. All rights reserved.
+*  Copyright (c) 2015, Linaro Limited. All rights reserved.
+*
+*  SPDX-License-Identifier: BSD-2-Clause-Patent
+*
+**/
+
+
+#ifndef OEM_MISC_LIB_H_
+#define OEM_MISC_LIB_H_
+
+#include <Uefi.h>
+#include <IndustryStandard/SmBios.h>
+
+typedef enum
+{
+  CpuCacheL1 = 0,
+  CpuCacheL2,
+  CpuCacheL3,
+  CpuCacheL4,
+  CpuCacheL5,
+  CpuCacheL6,
+  CpuCacheL7,
+  CpuCacheLevelMax
+} CPU_CACHE_LEVEL;
+
+typedef struct
+{
+  UINT8 Voltage;        ///< Processor voltage
+  UINT16 CurrentSpeed;  ///< Current clock speed in MHz
+  UINT16 MaxSpeed;      ///< Maximum clock speed in MHz
+  UINT16 ExternalClock; ///< External clock speed in MHz
+  UINT16 CoreCount;     ///< Number of cores available
+  UINT16 CoresEnabled;  ///< Number of cores enabled
+  UINT16 ThreadCount;   ///< Number of threads per processor
+} MISC_PROCESSOR_DATA;
+
+typedef enum {
+    ProductNameType01,
+    SerialNumType01,
+    UuidType01,
+    SystemManufacturerType01,
+    AssertTagType02,
+    SerialNumberType02,
+    BoardManufacturerType02,
+    AssetTagType03,
+    SerialNumberType03,
+    VersionType03,
+    ChassisTypeType03,
+    ManufacturerType03,
+    SmbiosHiiStringFieldMax
+} SMBIOS_HII_STRING_FIELD;
+
+/*
+ * The following are functions that the each platform needs to
+ * implement in its OemMiscLib library.
+ */
+
+UINTN OemGetCpuFreq (
+  IN UINT8 ProcessorIndex
+  );
+
+BOOLEAN
+OemGetProcessorInformation (
+  IN UINTN ProcessorNumber,
+  IN OUT PROCESSOR_STATUS_DATA *ProcessorStatus,
+  IN OUT PROCESSOR_CHARACTERISTIC_FLAGS *ProcessorCharacteristics,
+  IN OUT MISC_PROCESSOR_DATA *MiscProcessorData
+  );
+
+BOOLEAN OemGetCacheInformation (
+  IN UINT8 CacheLevel,
+  IN OUT SMBIOS_TABLE_TYPE7 *SmbiosCacheTable
+  );
+
+UINT8 OemGetProcessorMaxSockets (VOID);
+
+EFI_STATUS OemGetChassisType (
+  OUT UINT8 *ChassisType
+  );
+
+BOOLEAN OemIsSocketPresent (
+  IN UINTN ProcessorIndex
+  );
+
+VOID
+UpdateSmbiosInfo (
+  IN EFI_HII_HANDLE          mHiiHandle,
+  IN EFI_STRING_ID           TokenToUpdate,
+  IN SMBIOS_HII_STRING_FIELD Offset
+  );
+
+#endif // OEM_MISC_LIB_H_
diff --git a/ArmPkg/Universal/Smbios/SmbiosMiscDxe/SmbiosMisc.h b/ArmPkg/Universal/Smbios/SmbiosMiscDxe/SmbiosMisc.h
new file mode 100644
index 000000000000..20840f40d04b
--- /dev/null
+++ b/ArmPkg/Universal/Smbios/SmbiosMiscDxe/SmbiosMisc.h
@@ -0,0 +1,136 @@
+/** @file
+  Header file for the SmbiosMisc Driver.
+
+  Based on files under Nt32Pkg/MiscSubClassPlatformDxe/
+
+  Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2015, Hisilicon Limited. All rights reserved.<BR>
+  Copyright (c) 2015, Linaro Limited. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef SMBIOS_MISC_H_
+#define SMBIOS_MISC_H_
+
+#include <Protocol/Smbios.h>
+#include <IndustryStandard/SmBios.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HiiLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/OemMiscLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PrintLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Guid/DebugMask.h>
+
+
+//
+// Data table entry update function.
+//
+typedef EFI_STATUS (EFIAPI EFI_MISC_SMBIOS_DATA_FUNCTION) (
+  IN  VOID                 *RecordData,
+  IN  EFI_SMBIOS_PROTOCOL  *Smbios
+  );
+
+
+//
+// Data table entry definition.
+//
+typedef struct {
+  //
+  // intermediate input data for SMBIOS record
+  //
+  VOID                              *RecordData;
+  EFI_MISC_SMBIOS_DATA_FUNCTION     *Function;
+} EFI_MISC_SMBIOS_DATA_TABLE;
+
+
+//
+// SMBIOS table extern definitions
+//
+#define MISC_SMBIOS_TABLE_EXTERNS(NAME1, NAME2, NAME3) \
+extern NAME1 NAME2 ## Data; \
+extern EFI_MISC_SMBIOS_DATA_FUNCTION NAME3 ## Function;
+
+
+//
+// SMBIOS data table entries
+//
+// This is used to define a pair of table structure pointer and functions
+// in order to iterate through the list of tables, populate them and add
+// them into the system.
+#define MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(NAME1, NAME2) \
+{ \
+  & NAME1 ## Data, \
+    NAME2 ## Function \
+}
+
+//
+// Global definition macros.
+//
+#define MISC_SMBIOS_TABLE_DATA(NAME1, NAME2) \
+  NAME1 NAME2 ## Data
+
+#define MISC_SMBIOS_TABLE_FUNCTION(NAME2) \
+  EFI_STATUS EFIAPI NAME2 ## Function( \
+  IN  VOID                  *RecordData, \
+  IN  EFI_SMBIOS_PROTOCOL   *Smbios \
+  )
+
+//
+// Data Table Array Entries
+//
+extern EFI_HII_HANDLE               mHiiHandle;
+
+typedef struct _EFI_TYPE13_BIOS_LANGUAGE_INFORMATION_STRING{
+  UINT8                               *LanguageSignature;
+  EFI_STRING_ID                       InstallableLanguageLongString;
+  EFI_STRING_ID                       InstallableLanguageAbbreviateString;
+} EFI_TYPE13_BIOS_LANGUAGE_INFORMATION_STRING;
+
+
+/**
+ Logs SMBIOS record.
+
+ @param [in]   Buffer         Pointer to the data buffer.
+ @param [in]   SmbiosHandle   Pointer for retrieve handle.
+
+**/
+EFI_STATUS
+LogSmbiosData (
+  IN       UINT8                      *Buffer,
+  IN  OUT  EFI_SMBIOS_HANDLE          *SmbiosHandle
+  );
+
+/**
+ Get Link Type Handle.
+
+ @param [in]   SmbiosType     Get this Type from SMBIOS table
+ @param [out]  HandleArray    Pointer to handle array which will be freed by caller
+ @param [out]  HandleCount    Pointer to handle count
+
+**/
+VOID
+GetLinkTypeHandle(
+  IN  UINT8                 SmbiosType,
+  OUT UINT16                **HandleArray,
+  OUT UINTN                 *HandleCount
+  );
+
+//
+// Data Table Array
+//
+extern EFI_MISC_SMBIOS_DATA_TABLE   mSmbiosMiscDataTable[];
+
+//
+// Data Table Array Entries
+//
+extern UINTN   mSmbiosMiscDataTableEntries;
+extern UINT8   SmbiosMiscDxeStrings[];
+
+#endif // SMBIOS_MISC_H_
diff --git a/ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClass.c b/ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClass.c
new file mode 100644
index 000000000000..bd91451b6382
--- /dev/null
+++ b/ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClass.c
@@ -0,0 +1,835 @@
+/** @file
+*  ProcessorSubClass.c
+*
+*  Copyright (c) 2020, NUVIA Inc. All rights reserved.<BR>
+*  Copyright (c) 2015, Hisilicon Limited. All rights reserved.
+*  Copyright (c) 2015, Linaro Limited. All rights reserved.
+*  SPDX-License-Identifier: BSD-2-Clause-Patent
+*
+**/
+
+#include <Uefi.h>
+#include <Protocol/Smbios.h>
+#include <IndustryStandard/ArmStdSmc.h>
+#include <IndustryStandard/SmBios.h>
+#include <Library/ArmLib.h>
+#include <Library/ArmSmcLib.h>
+#include <Library/ArmLib/ArmLibPrivate.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HiiLib.h>
+#include <Library/IoLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/OemMiscLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PrintLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+
+extern UINT8 ProcessorSubClassStrings[];
+
+#define CACHE_SOCKETED_SHIFT       3
+#define CACHE_LOCATION_SHIFT       5
+#define CACHE_ENABLED_SHIFT        7
+#define CACHE_OPERATION_MODE_SHIFT 8
+
+// Sets the HII variable `x` if `pcd` isn't empty
+#define SET_HII_STRING_IF_PCD_NOT_EMPTY(pcd, x)               \
+    x##Str = (CHAR16 *)PcdGetPtr (pcd); \
+    if (StrLen (x##Str) > 0) {                                \
+      HiiSetString (mHiiHandle, x, x##Str, NULL);             \
+    }                                                         \
+
+typedef enum {
+  CacheModeWriteThrough = 0,  ///< Cache is write-through
+  CacheModeWriteBack,         ///< Cache is write-back
+  CacheModeVariesWithAddress, ///< Cache mode varies by address
+  CacheModeUnknown,           ///< Cache mode is unknown
+  CacheModeMax
+} CACHE_OPERATION_MODE;
+
+typedef enum {
+  CacheLocationInternal = 0, ///< Cache is internal to the processor
+  CacheLocationExternal,     ///< Cache is external to the processor
+  CacheLocationReserved,     ///< Reserved
+  CacheLocationUnknown,      ///< Cache location is unknown
+  CacheLocationMax
+} CACHE_LOCATION;
+
+EFI_HII_HANDLE       mHiiHandle;
+
+EFI_SMBIOS_PROTOCOL  *mSmbios;
+
+SMBIOS_TABLE_TYPE4 mSmbiosProcessorTableTemplate = {
+    {                         // Hdr
+      EFI_SMBIOS_TYPE_PROCESSOR_INFORMATION, // Type
+      sizeof (SMBIOS_TABLE_TYPE4), // Length
+      0                       // Handle
+    },
+    1,                        // Socket
+    CentralProcessor,         // ProcessorType
+    ProcessorFamilyIndicatorFamily2, // ProcessorFamily
+    2,                        // ProcessorManufacture
[SAMI] Would defining a macro PROC_MANUFACTURER_STR_ID or an enum be helpful? Similarly, for other strings used across SMBIOS tables in this patch.
[/SAMI]
+    {                         // ProcessorId
+      {                       // Signature
+        0
+      },
+      {                       // FeatureFlags
+        0
+      }
+    },
+    3,                        // ProcessorVersion
+    {                         // Voltage
+      0
+    },
+    0,                        // ExternalClock
+    0,                        // MaxSpeed
+    0,                        // CurrentSpeed
+    0,                        // Status
+    ProcessorUpgradeUnknown,  // ProcessorUpgrade
+    0xFFFF,                   // L1CacheHandle
+    0xFFFF,                   // L2CacheHandle
+    0xFFFF,                   // L3CacheHandle
+    4,                        // SerialNumber
+    5,                        // AssetTag
+    6,                        // PartNumber
+    0,                        // CoreCount
+    0,                        //EnabledCoreCount
+    0,                        // ThreadCount
+    0,                        // ProcessorCharacteristics
+    ProcessorFamilyARM,       // ProcessorFamily2
+    0,                        // CoreCount2
+    0,                        // EnabledCoreCount2
+    0                         // ThreadCount2
+};
+
+
+/** Fetches the specified processor's frequency in Hz
+ *
+ * @param ProcessorNumber The processor number
+ *
+ * @return The clock frequency in MHz
+ *
+**/
+UINT16
+GetCpuFrequency (
+  IN  UINT8 ProcessorNumber
+  )
+{
+  return (UINT16)(OemGetCpuFreq (ProcessorNumber) / 1000 / 1000);
+}
+
+/** Gets a description of the specified cache
+ *
+ * @param[in] CacheLevel      Zero-based cache level (e.g. L1 cache is 0)
+ * @param[in] CacheSubLevel   Where the cache level has separate data and
+ *                            instruction caches, 0 is instruction and 1 is data
+ * @param[out] CacheSocketStr The description of the specified cache
+ *
+ * @return The number of Unicode characters in CacheSocketStr not including the
+ *         terminating NUL
+**/
+UINTN
+GetCacheSocketStr (
+  IN  UINT8     CacheLevel,
+  IN  UINT8     CacheSubLevel,
+  OUT CHAR16    *CacheSocketStr
+  )
+{
+  UINTN CacheSocketStrLen;
+
+  if (CacheLevel == CpuCacheL1
+      && CacheSubLevel == 0) {
+    CacheSocketStrLen = UnicodeSPrint (
+                          CacheSocketStr,
+                          SMBIOS_STRING_MAX_LENGTH - 1,
+                          L"L%x Instruction Cache",
+                          CacheLevel + 1);
+  } else if (CacheLevel == CpuCacheL1 && CacheSubLevel == 1) {
+    CacheSocketStrLen = UnicodeSPrint (CacheSocketStr,
+                          SMBIOS_STRING_MAX_LENGTH - 1,
+                          L"L%x Data Cache",
+                          CacheLevel + 1);
+  } else {
+    CacheSocketStrLen = UnicodeSPrint (CacheSocketStr,
+                          SMBIOS_STRING_MAX_LENGTH - 1,
+                          L"L%x Cache",
+                          CacheLevel + 1);
+  }
+
+  return CacheSocketStrLen;
+}
+
+/** Fills in the Type 7 record with the cache architecture information
+ *  read from the CPU registers.
+ *
+ * @param[in]     CacheLevel     Cache level (e.g. L1)
+ * @param[in]     CacheSubLevel  Type of cache (e.g. instruction)
+ * @param[in]     CcidxSupported Whether CCIDX is supported
+ * @param[in]     CacheType      The type of cache supported at this cache level
+ * @param[out]    Type7Record    The Type 7 record to fill in
+ *
+**/
+VOID
+SetCacheArchitectureInformation (
+  IN     UINT8                CacheLevel,
+  IN     UINT8                CacheSubLevel,
+  IN     BOOLEAN              CcidxSupported,
+  IN     CLIDR_CACHE_TYPE     CacheType,
+  OUT    SMBIOS_TABLE_TYPE7   *Type7Record
+  )
+{
+  CSSELR_DATA  Csselr;
+  CCSIDR_DATA  Ccsidr;
+  UINT8        Associativity;
+  UINT32       CacheSize32;
+  UINT16       CacheSize16;
+  UINT64       CacheSize64;
+
+  Csselr.Data = 0;
+  Csselr.Bits.Level = CacheLevel;
+
+  if (CacheSubLevel == 0) {
+    if (CacheType == ClidrCacheTypeInstructionOnly ||
+        CacheType == ClidrCacheTypeSeparate) {
+      Csselr.Bits.InD = CsselrCacheTypeInstruction;
+      Type7Record->SystemCacheType = CacheTypeInstruction;
+    } else {
+      Csselr.Bits.InD = CsselrCacheTypeDataOrUnified;
+      if (CacheType == ClidrCacheTypeDataOnly) {
+        Type7Record->SystemCacheType = CacheTypeData;
+      } else {
+        Type7Record->SystemCacheType = CacheTypeUnified;
+      }
+    }
+  } else {
+    Type7Record->SystemCacheType = CacheTypeData;
+    Csselr.Bits.InD = CsselrCacheTypeDataOrUnified;
+  }
+
+  // Read the CCSIDR register to get the cache architecture
+  Ccsidr.Data = ReadCCSIDR (Csselr.Data);
+
+  if (CcidxSupported) {
+    CacheSize64 = (UINT64)(1 << (Ccsidr.BitsCcidx.LineSize + 4)) *
+                                (Ccsidr.BitsCcidx.Associativity + 1) *
+                                (Ccsidr.BitsCcidx.NumSets + 1);
+    Associativity = Ccsidr.BitsCcidx.Associativity;
[SAMI] For AArch32 this would return the wrong NumSets, right? 
Probably a ReadCCSIDR2() function is needed here enveloped in MDE_CPU_ARM. 
Or 
The AArch32 version of ReadCCSIDR() reads the CCSIDR2 and returns the higher 32 bits when FEAT_CCIDX is implemented.
[/SAMI]

+  } else {
+    CacheSize64 = (1 << (Ccsidr.BitsNonCcidx.LineSize + 4)) *
+                        (Ccsidr.BitsNonCcidx.Associativity + 1) *
+                        (Ccsidr.BitsNonCcidx.NumSets + 1);
+    Associativity = Ccsidr.BitsNonCcidx.Associativity;
+  }
+
+  CacheSize64 /= 1024; // Minimum granularity is 1K
+
+  // Encode the cache size into the format SMBIOS wants
+  if (CacheSize64 < MAX_INT16) {
+    CacheSize16 = CacheSize64;
+    CacheSize32 = CacheSize16;
+  } else if ((CacheSize64 / 64) < MAX_INT16) {
+    CacheSize16 = (1 << 15) | (CacheSize64 / 64);
+    CacheSize32 = CacheSize16;
+  } else {
+    if ((CacheSize64 / 1024) <= 2047) {
+      CacheSize32 = CacheSize64;
+    } else {
+      CacheSize32 = (1 << 31) | (CacheSize64 / 64);
+    }
+
+    CacheSize16 = -1;
+  }
+
+  Type7Record->Associativity = Associativity + 1;
+  Type7Record->MaximumCacheSize = CacheSize16;
+  Type7Record->InstalledSize = CacheSize16;
+  Type7Record->MaximumCacheSize2 = CacheSize32;
+  Type7Record->InstalledSize2 = CacheSize32;
+
+  switch (Associativity + 1) {
+    case 2:
+      Type7Record->Associativity = CacheAssociativity2Way;
+      break;
+    case 4:
+      Type7Record->Associativity = CacheAssociativity4Way;
+      break;
+    case 8:
+      Type7Record->Associativity = CacheAssociativity8Way;
+      break;
+    case 16:
+      Type7Record->Associativity = CacheAssociativity16Way;
+      break;
+    case 12:
+      Type7Record->Associativity = CacheAssociativity12Way;
+      break;
+    case 24:
+      Type7Record->Associativity = CacheAssociativity24Way;
+      break;
+    case 32:
+      Type7Record->Associativity = CacheAssociativity32Way;
+      break;
+    case 48:
+      Type7Record->Associativity = CacheAssociativity48Way;
+      break;
+    case 64:
+      Type7Record->Associativity = CacheAssociativity64Way;
+      break;
+    case 20:
+      Type7Record->Associativity = CacheAssociativity20Way;
+      break;
+    default:
+      Type7Record->Associativity = CacheAssociativityOther;
+      break;
+  }
+
+  Type7Record->CacheConfiguration = (CacheModeUnknown << CACHE_OPERATION_MODE_SHIFT) |
+                                    (1 << CACHE_ENABLED_SHIFT) |
+                                    (CacheLocationUnknown << CACHE_LOCATION_SHIFT) |
+                                    (0 << CACHE_SOCKETED_SHIFT) |
+                                    CacheLevel;
+}
+
+
+/** Allocates and initializes an SMBIOS_TABLE_TYPE7 structure
+ *
+ * @param[in]  CacheLevel    The cache level (L1-L7)
+ * @param[in]  CacheSubLevel The type of cache
+ *
+ * @return A pointer to the Type 7 structure. Returns NULL on failure.
+ *
+**/
+SMBIOS_TABLE_TYPE7 *
+AllocateAndInitCacheInformation (
+  IN UINT8 CacheLevel,
+  IN UINT8 CacheSubLevel
+  )
+{
+  SMBIOS_TABLE_TYPE7          *Type7Record;
+  EFI_STRING                  CacheSocketStr;
+  UINTN                       CacheSocketStrLen;
+  UINTN                       StringBufferSize;
+  CHAR8                       *OptionalStrStart;
+  UINTN                       TableSize;
+
+  // Allocate and fetch the cache description
+  StringBufferSize = sizeof (CHAR16) * SMBIOS_STRING_MAX_LENGTH;
+  CacheSocketStr = AllocateZeroPool (StringBufferSize);
+  if (CacheSocketStr == NULL) {
+    return NULL;
+  }
+
+  CacheSocketStrLen = GetCacheSocketStr (CacheLevel, CacheSubLevel, CacheSocketStr);
+
+  TableSize = sizeof (SMBIOS_TABLE_TYPE7) + CacheSocketStrLen + 1 + 1;
+  Type7Record = AllocateZeroPool (TableSize);
+  if (Type7Record == NULL) {
+    FreePool(CacheSocketStr);
+    return NULL;
+  }
+
+  Type7Record->Hdr.Type = EFI_SMBIOS_TYPE_CACHE_INFORMATION;
+  Type7Record->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE7);
+  Type7Record->Hdr.Handle = SMBIOS_HANDLE_PI_RESERVED;
+
+  Type7Record->SocketDesignation = 1;
+
+  Type7Record->SupportedSRAMType.Unknown = 1;
+  Type7Record->CurrentSRAMType.Unknown = 1;
+  Type7Record->CacheSpeed = 0;
+  Type7Record->ErrorCorrectionType = CacheErrorUnknown;
+
+  OptionalStrStart = (CHAR8 *)(Type7Record + 1);
+  UnicodeStrToAsciiStrS (CacheSocketStr, OptionalStrStart, CacheSocketStrLen + 1);
+  FreePool (CacheSocketStr);
+
+  return Type7Record;
+}
+
+
+/**
+ * Add Type 7 SMBIOS Record for Cache Information.
+ *
+ * @param[in]    ProcessorNumber     Processor number of specified processor.
+ * @param[out]   L1CacheHandle       Pointer to the handle of the L1 Cache SMBIOS record.
+ * @param[out]   L2CacheHandle       Pointer to the handle of the L2 Cache SMBIOS record.
+ * @param[out]   L3CacheHandle       Pointer to the handle of the L3 Cache SMBIOS record.
+ *
+**/
+VOID
+AddSmbiosCacheTypeTable (
+  IN UINTN                  ProcessorIndex,
+  OUT EFI_SMBIOS_HANDLE     *L1CacheHandle,
+  OUT EFI_SMBIOS_HANDLE     *L2CacheHandle,
+  OUT EFI_SMBIOS_HANDLE     *L3CacheHandle
+  )
+{
+  EFI_STATUS                  Status;
+  SMBIOS_TABLE_TYPE7          *Type7Record;
+  EFI_SMBIOS_HANDLE           SmbiosHandle;
+  UINT8                       CacheLevel;
+  UINT8                       CacheSubLevel;
+  CLIDR_DATA                  Clidr;
+  BOOLEAN                     CcidxSupported;
+  UINT8                       MaxCacheLevel;
+
+  Status = EFI_SUCCESS;
+
+  MaxCacheLevel = 0;
+
+  // Read the CLIDR register to find out what caches are present.
+  Clidr.Data = ReadCLIDR ();
[SAMI] The ReadCLIDR() and similar functions would run on the current PE. I think this code would not work with a big.LITTLE system or a system that utilises a DSU with different CPUs.
Is the assumption here that all PEs in the system are same?
[/SAMI]
+
+  // Get the cache type for the L1 cache. If it's 0, there are no caches.
+  if (CLIDR_GET_CACHE_TYPE (Clidr.Data, 0) == ClidrCacheTypeNone) {
+    return;
+  }
+
+  for (CacheLevel = 1; CacheLevel < MAX_ARM_CACHE_LEVEL; CacheLevel++) {
+    if (CLIDR_GET_CACHE_TYPE (Clidr.Data, CacheLevel) == ClidrCacheTypeNone) {
+      MaxCacheLevel = CacheLevel;
+      break;
+    }
+  }
+
+  CcidxSupported = ArmIsCcidxImplemented ();
+
+  for (CacheLevel = 0; CacheLevel < MaxCacheLevel; CacheLevel++) {
+    Type7Record = NULL;
+
+    CLIDR_CACHE_TYPE CacheType = CLIDR_GET_CACHE_TYPE (Clidr.Data, CacheLevel);
+
+    // At each level of cache, we can have a single type (unified, instruction or data),
+    // or two types - separate data and instruction caches. If we have separate
+    // instruction and data caches, then on the first iteration (CacheSubLevel = 0)
+    // process the instruction cache.
+    for (CacheSubLevel = 0; CacheSubLevel <= 1; CacheSubLevel++) {
+      // If there's no separate data/instruction cache, skip the second iteration
+      if (CacheSubLevel > 0 && CacheType != ClidrCacheTypeSeparate) {
+        continue;
+      }
+
+      Type7Record = AllocateAndInitCacheInformation (CacheLevel, CacheSubLevel);
+      if (Type7Record == NULL) {
+        continue;
+      }
+
+      SetCacheArchitectureInformation(CacheLevel, CacheSubLevel, CcidxSupported,
+                                       CacheType, Type7Record);
+
+      // Allow the platform to fill in other information such as speed, SRAM type etc.
+      if (!OemGetCacheInformation (CacheLevel, Type7Record)) {
+        continue;
+      }
+
+      SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
+      // Finally, install the table
+      Status = mSmbios->Add (mSmbios, NULL, &SmbiosHandle,
+                             (EFI_SMBIOS_TABLE_HEADER *)Type7Record);
+      if (EFI_ERROR (Status)) {
+        continue;
+      }
+
+      // Config L1/L2/L3 Cache Handle
+      switch (CacheLevel) {
+        case CpuCacheL1:
+          *L1CacheHandle = SmbiosHandle;
+          break;
+        case CpuCacheL2:
+          *L2CacheHandle = SmbiosHandle;
+          break;
+        case CpuCacheL3:
+          *L3CacheHandle = SmbiosHandle;
+          break;
+        default:
+            break;
+      }
+    }
+  }
+}
+
+/** Fills in the Type 4 CPU processor ID field
+ *
+ * @param[out] Type4Record The SMBIOS Type 4 record to fill in
+ *
+**/
+VOID
+SetProcessorIdField (
+  OUT SMBIOS_TABLE_TYPE4 *Type4Record
+)
+{
+  ARM_SMC_ARGS Args;
+  INT32 SmcCallStatus;
+  INT32 Jep106Code;
+  INT32 SocRevision;
+  BOOLEAN Arm64SocIdSupported = FALSE;
+  UINT64 *ProcessorId;
+
+  Args.Arg0 = SMCCC_VERSION;
+  ArmCallSmc (&Args);
+  SmcCallStatus = (INT32)Args.Arg0;
+
+  if (SmcCallStatus < 0 || (SmcCallStatus >> 16) >= 1) {
+    Args.Arg0 = SMCCC_ARCH_FEATURES;
+    Args.Arg1 = SMCCC_ARCH_SOC_ID;
+    ArmCallSmc (&Args);
+
+    if (Args.Arg0 >= 0) {
+      PROCESSOR_CHARACTERISTIC_FLAGS *ProcessorCharacteristicFlags =
+        (PROCESSOR_CHARACTERISTIC_FLAGS*)&Type4Record->ProcessorCharacteristics;
+      Args.Arg0 = SMCCC_ARCH_SOC_ID;
+      Args.Arg1 = 0;
+      ArmCallSmc (&Args);
+      SmcCallStatus = (int)Args.Arg0;
+
+      if (SmcCallStatus >= 0) {
+        Arm64SocIdSupported = TRUE;
+        ProcessorCharacteristicFlags->ProcessorArm64SocId = 1;
+        Jep106Code = (int)Args.Arg0;
+      } else {
+        ProcessorCharacteristicFlags->ProcessorArm64SocId = 0;
+      }
+      Args.Arg0 = SMCCC_ARCH_SOC_ID;
+      Args.Arg1 = 1;
+      ArmCallSmc (&Args);
+      SmcCallStatus = (int)Args.Arg0;
+
+      if (SmcCallStatus >= 0) {
+        SocRevision = (int)Args.Arg0;
+      }
+    }
+  }
+
+  ProcessorId = (UINT64 *)&Type4Record->ProcessorId;
+
+  if (Arm64SocIdSupported) {
+    *ProcessorId = ((UINT64)Jep106Code << 32) | SocRevision;
+  } else {
+    *ProcessorId = ArmReadMidr ();
+  }
+}
+
+
+/** Allocates a Type 4 Processor Information structure and sets the
+ *  strings following the data fields.
+ *
+ * @param[out] Type4Record    The Type 4 structure to allocate and initialize
+ * @param[in]  ProcessorIndex The index of the processor socket
+ * @param[in]  Populated      Whether the specified processor socket is
+ *                            populated.
+ *
+ * @retval EFI_SUCCESS        The Type 4 structure was successfully
+ *                            allocated and the strings initialized.
[SAMI] Please also add EFI_OUT_OF_RESOURCES.
[/SAMI]
+**/
+EFI_STATUS
+AllocateType4AndSetProcessorInformationStrings (
+  SMBIOS_TABLE_TYPE4 **Type4Record,
+  UINT8 ProcessorIndex,
+  BOOLEAN Populated
+  )
+{
+  EFI_STATUS      Status;
+  EFI_STRING_ID   ProcessorManu;
+  EFI_STRING_ID   ProcessorVersion;
+  EFI_STRING_ID   SerialNumber;
+  EFI_STRING_ID   AssetTag;
+  EFI_STRING_ID   PartNumber;
+  EFI_STRING      ProcessorSocketStr;
+  EFI_STRING      ProcessorManuStr;
+  EFI_STRING      ProcessorVersionStr;
+  EFI_STRING      SerialNumberStr;
+  EFI_STRING      AssetTagStr;
+  EFI_STRING      PartNumberStr;
+  CHAR8           *OptionalStrStart;
+  CHAR8           *StrStart;
+  UINTN           ProcessorSocketStrLen;
+  UINTN           ProcessorManuStrLen;
+  UINTN           ProcessorVersionStrLen;
+  UINTN           SerialNumberStrLen;
+  UINTN           AssetTagStrLen;
+  UINTN           PartNumberStrLen;
+  UINTN           TotalSize;
+  UINTN           StringBufferSize;
+
+  Status = EFI_SUCCESS;
+
+  ProcessorManuStr    = NULL;
+  ProcessorVersionStr = NULL;
+  SerialNumberStr     = NULL;
+  AssetTagStr         = NULL;
+  PartNumberStr       = NULL;
+
+  ProcessorManu       = STRING_TOKEN (STR_PROCESSOR_UNKNOWN);
+  ProcessorVersion    = STRING_TOKEN (STR_PROCESSOR_UNKNOWN);
+  SerialNumber        = STRING_TOKEN (STR_PROCESSOR_UNKNOWN);
+  AssetTag            = STRING_TOKEN (STR_PROCESSOR_UNKNOWN);
+  PartNumber          = STRING_TOKEN (STR_PROCESSOR_UNKNOWN);
[SAMI] Minor optimisation may be possible by moving these initialisations in an else block if (Populated) { ... } else { // here}
[/SAMI]
+
+  if (Populated) {
+    ProcessorManu       = STRING_TOKEN (STR_PROCESSOR_MANUFACTURE);
+    ProcessorVersion    = STRING_TOKEN (STR_PROCESSOR_VERSION);
+    SerialNumber        = STRING_TOKEN (STR_PROCESSOR_SERIAL_NUMBER);
+    AssetTag            = STRING_TOKEN (STR_PROCESSOR_ASSET_TAG);
+    PartNumber          = STRING_TOKEN (STR_PROCESSOR_PART_NUMBER);
+
+    SET_HII_STRING_IF_PCD_NOT_EMPTY(PcdProcessorManufacturer, ProcessorManu);
+    SET_HII_STRING_IF_PCD_NOT_EMPTY(PcdProcessorVersion, ProcessorVersion);
+    SET_HII_STRING_IF_PCD_NOT_EMPTY(PcdProcessorSerialNumber, SerialNumber);
+    SET_HII_STRING_IF_PCD_NOT_EMPTY(PcdProcessorAssetTag, AssetTag);
+    SET_HII_STRING_IF_PCD_NOT_EMPTY(PcdProcessorPartNumber, PartNumber);
+  }
+
+  // Processor Socket Designation
+  StringBufferSize = sizeof (CHAR16) * SMBIOS_STRING_MAX_LENGTH;
+  ProcessorSocketStr = AllocateZeroPool (StringBufferSize);
+  if (ProcessorSocketStr == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  ProcessorSocketStrLen = UnicodeSPrint (ProcessorSocketStr, StringBufferSize,
+                                         L"CPU%02d", ProcessorIndex + 1);
+
+  // Processor Manufacture
+  ProcessorManuStr = HiiGetPackageString (&gEfiCallerIdGuid, ProcessorManu, NULL);
+  ProcessorManuStrLen = StrLen (ProcessorManuStr);
+
+  // Processor Version
+  ProcessorVersionStr = HiiGetPackageString (&gEfiCallerIdGuid, ProcessorVersion, NULL);
+  ProcessorVersionStrLen = StrLen (ProcessorVersionStr);
+
+  // Serial Number
+  SerialNumberStr = HiiGetPackageString (&gEfiCallerIdGuid, SerialNumber, NULL);
+  SerialNumberStrLen = StrLen (SerialNumberStr);
+
+  // Asset Tag
+  AssetTagStr = HiiGetPackageString (&gEfiCallerIdGuid, AssetTag, NULL);
+  AssetTagStrLen = StrLen (AssetTagStr);
+
+  // Part Number
+  PartNumberStr = HiiGetPackageString (&gEfiCallerIdGuid, PartNumber, NULL);
+  PartNumberStrLen = StrLen (PartNumberStr);
+
+  TotalSize = sizeof (SMBIOS_TABLE_TYPE4) +
+              ProcessorSocketStrLen  + 1 +
+              ProcessorManuStrLen    + 1 +
+              ProcessorVersionStrLen + 1 +
+              SerialNumberStrLen     + 1 +
+              AssetTagStrLen         + 1 +
+              PartNumberStrLen       + 1 + 1;
+
+  *Type4Record = AllocateZeroPool (TotalSize);
+  if (*Type4Record == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Exit;
+  }
+
+  CopyMem (*Type4Record, &mSmbiosProcessorTableTemplate, sizeof (SMBIOS_TABLE_TYPE4));
+
+  OptionalStrStart = (CHAR8 *)(*Type4Record + 1);
+  UnicodeStrToAsciiStrS (
+    ProcessorSocketStr,
+    OptionalStrStart,
+    ProcessorSocketStrLen + 1
+    );
+
+  StrStart = OptionalStrStart + ProcessorSocketStrLen + 1;
+  UnicodeStrToAsciiStrS (
+    ProcessorManuStr,
+    StrStart,
+    ProcessorManuStrLen + 1
+    );
+
+  StrStart += ProcessorManuStrLen + 1;
+  UnicodeStrToAsciiStrS (
+    ProcessorVersionStr,
+    StrStart,
+    ProcessorVersionStrLen + 1
+    );
+
+  StrStart += ProcessorVersionStrLen + 1;
+  UnicodeStrToAsciiStrS (
+    SerialNumberStr,
+    StrStart,
+    SerialNumberStrLen + 1
+    );
+
+  StrStart += SerialNumberStrLen + 1;
+  UnicodeStrToAsciiStrS (
+    AssetTagStr,
+    StrStart,
+    AssetTagStrLen + 1
+    );
+
+  StrStart += AssetTagStrLen + 1;
+  UnicodeStrToAsciiStrS (
+    PartNumberStr,
+    StrStart,
+    PartNumberStrLen + 1
+    );
+
+Exit:
+  FreePool (ProcessorSocketStr);
+  FreePool (ProcessorManuStr);
+  FreePool (ProcessorVersionStr);
+  FreePool (SerialNumberStr);
+  FreePool (AssetTagStr);
+  FreePool (PartNumberStr);
+
+  return Status;
+}
+
+/**
+ * Add Type 4 SMBIOS Record for Processor Information.
+ *
+ * @param[in]    ProcessorNumber     Processor number of specified processor.
+ *
+**/
+EFI_STATUS
+AddSmbiosProcessorTypeTable (
+  IN UINTN                  ProcessorIndex
+  )
+{
+  EFI_STATUS                  Status;
+  SMBIOS_TABLE_TYPE4          *Type4Record;
+  EFI_SMBIOS_HANDLE           SmbiosHandle;
+  EFI_SMBIOS_HANDLE           L1CacheHandle;
+  EFI_SMBIOS_HANDLE           L2CacheHandle;
+  EFI_SMBIOS_HANDLE           L3CacheHandle;
+  UINT8                       *LegacyVoltage;
+  PROCESSOR_STATUS_DATA       ProcessorStatus = {{0}};
+  MISC_PROCESSOR_DATA         MiscProcessorData;
+  BOOLEAN                     SocketPopulated;
+
+  Type4Record         = NULL;
+
+  MiscProcessorData.Voltage             = 0;
+  MiscProcessorData.CurrentSpeed        = 0;
+  MiscProcessorData.CoreCount           = 0;
+  MiscProcessorData.CoresEnabled        = 0;
+  MiscProcessorData.ThreadCount         = 0;
[SAMI] Should MaxSpeed fields should be initialised to zero.
[/SAMI]
+  L1CacheHandle       = 0xFFFF;
+  L2CacheHandle       = 0xFFFF;
+  L3CacheHandle       = 0xFFFF;
+
+  SocketPopulated = OemIsSocketPresent(ProcessorIndex);
+
+  Status = AllocateType4AndSetProcessorInformationStrings (
+             &Type4Record,
+             ProcessorIndex,
+             SocketPopulated
+             );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  OemGetProcessorInformation (ProcessorIndex,
+                              &ProcessorStatus,
+                              (PROCESSOR_CHARACTERISTIC_FLAGS*)
+                                &Type4Record->ProcessorCharacteristics,
+                              &MiscProcessorData);
+
+  if (SocketPopulated) {
+    AddSmbiosCacheTypeTable (ProcessorIndex, &L1CacheHandle,
+                             &L2CacheHandle, &L3CacheHandle);
+  }
+
+  LegacyVoltage = (UINT8*)&Type4Record->Voltage;
+
+  *LegacyVoltage                    = MiscProcessorData.Voltage;
+  Type4Record->CurrentSpeed         = MiscProcessorData.CurrentSpeed;
+  Type4Record->MaxSpeed             = MiscProcessorData.MaxSpeed;
+  Type4Record->Status               = ProcessorStatus.Data;
+  Type4Record->L1CacheHandle        = L1CacheHandle;
+  Type4Record->L2CacheHandle        = L2CacheHandle;
+  Type4Record->L3CacheHandle        = L3CacheHandle;
+  Type4Record->CoreCount            = MiscProcessorData.CoreCount;
+  Type4Record->CoreCount2           = MiscProcessorData.CoreCount;
+  Type4Record->EnabledCoreCount     = MiscProcessorData.CoresEnabled;
+  Type4Record->EnabledCoreCount2    = MiscProcessorData.CoresEnabled;
+  Type4Record->ThreadCount          = MiscProcessorData.ThreadCount;
+  Type4Record->ThreadCount2         = MiscProcessorData.ThreadCount;
+
+  Type4Record->CurrentSpeed         = GetCpuFrequency (ProcessorIndex);
+  Type4Record->ExternalClock        = (UINT16)(ArmReadCntFrq () / 1000 / 1000);
+
+  SetProcessorIdField (Type4Record);
+
+  UINTN MainIdRegister = ArmReadMidr ();
+  if (((MainIdRegister >> 16) & 0xF) < 8) {
+    Type4Record->ProcessorFamily2 = ProcessorFamilyARM;
+  } else {
+    if (sizeof (VOID*) == 4) {
+      Type4Record->ProcessorFamily2 = ProcessorFamilyARMv7;
+    } else {
+      Type4Record->ProcessorFamily2 = ProcessorFamilyARMv8;
+    }
+  }
+
+  SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
+  Status = mSmbios->Add (mSmbios, NULL, &SmbiosHandle, (EFI_SMBIOS_TABLE_HEADER *)Type4Record);
+
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Smbios Type04 Table Log Failed! %r \n",
+            __FUNCTION__, __LINE__, Status));
+  }
+  FreePool (Type4Record);
+
+  return Status;
+}
+
+/**
+ * Standard EFI driver point.  This driver locates the ProcessorConfigurationData Variable,
+ * if it exists, add the related SMBIOS tables by PI SMBIOS protocol.
+ *
+ * @param  ImageHandle     Handle for the image of this driver
+ * @param  SystemTable     Pointer to the EFI System Table
+ *
+ * @retval  EFI_SUCCESS    The data was successfully stored.
+ *
+**/
+EFI_STATUS
+EFIAPI
+ProcessorSubClassEntryPoint(
+  IN EFI_HANDLE         ImageHandle,
+  IN EFI_SYSTEM_TABLE   *SystemTable
+  )
+{
+  EFI_STATUS                      Status;
+  UINT32                          SocketIndex;
+
+  //
+  // Locate dependent protocols
+  //
+  Status = gBS->LocateProtocol (&gEfiSmbiosProtocolGuid, NULL, (VOID**)&mSmbios);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "Could not locate SMBIOS protocol.  %r\n", Status));
+    return Status;
+  }
+
+  //
+  // Add our default strings to the HII database. They will be modified later.
+  //
+  mHiiHandle = HiiAddPackages (&gEfiCallerIdGuid,
+                               NULL,
+                               ProcessorSubClassStrings,
+                               NULL,
+                               NULL
+                              );
+  if (mHiiHandle == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  //
+  // Add SMBIOS tables for populated sockets.
+  //
+  for (SocketIndex = 0; SocketIndex < OemGetProcessorMaxSockets(); SocketIndex++) {
+    Status = AddSmbiosProcessorTypeTable (SocketIndex);
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_ERROR, "Add Processor Type Table Failed!  %r.\n", Status));
+      return Status;
+    }
+  }
+
+  return Status;
+}
diff --git a/ArmPkg/Universal/Smbios/SmbiosMiscDxe/SmbiosMiscDataTable.c b/ArmPkg/Universal/Smbios/SmbiosMiscDxe/SmbiosMiscDataTable.c
new file mode 100644
index 000000000000..c9f460f1d5a8
--- /dev/null
+++ b/ArmPkg/Universal/Smbios/SmbiosMiscDxe/SmbiosMiscDataTable.c
@@ -0,0 +1,61 @@
+/** @file
+  This file provides SMBIOS Misc Type.
+
+  Based on files under Nt32Pkg/MiscSubClassPlatformDxe/
+
+  Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2015, Hisilicon Limited. All rights reserved.<BR>
+  Copyright (c) 2015, Linaro Limited. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent\
+
+**/
+
+#include "SmbiosMisc.h"
+
+MISC_SMBIOS_TABLE_EXTERNS (SMBIOS_TABLE_TYPE0,
+                           MiscBiosVendor,
+                           MiscBiosVendor)
+MISC_SMBIOS_TABLE_EXTERNS (SMBIOS_TABLE_TYPE1,
+                           MiscSystemManufacturer,
+                           MiscSystemManufacturer)
+MISC_SMBIOS_TABLE_EXTERNS (SMBIOS_TABLE_TYPE3,
+                          MiscChassisManufacturer,
+                          MiscChassisManufacturer)
+MISC_SMBIOS_TABLE_EXTERNS (SMBIOS_TABLE_TYPE2,
+                           MiscBaseBoardManufacturer,
+                           MiscBaseBoardManufacturer)
+MISC_SMBIOS_TABLE_EXTERNS (SMBIOS_TABLE_TYPE13,
+                           MiscNumberOfInstallableLanguages,
+                           MiscNumberOfInstallableLanguages)
+MISC_SMBIOS_TABLE_EXTERNS (SMBIOS_TABLE_TYPE32,
+                           MiscBootInformation,
+                           MiscBootInformation)
+
+
+EFI_MISC_SMBIOS_DATA_TABLE mSmbiosMiscDataTable[] = {
+  // Type0
+  MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION (MiscBiosVendor,
+                                             MiscBiosVendor),
+  // Type1
+  MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION (MiscSystemManufacturer,
+                                             MiscSystemManufacturer),
+  // Type3
+  MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION (MiscChassisManufacturer,
+                                             MiscChassisManufacturer),
+  // Type2
+  MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION (MiscBaseBoardManufacturer,
+                                             MiscBaseBoardManufacturer),
+  // Type13
+  MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION (MiscNumberOfInstallableLanguages,
+                                             MiscNumberOfInstallableLanguages),
+  // Type32
+  MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION (MiscBootInformation,
+                                             MiscBootInformation),
+};
+
+
+//
+// Number of Data Table entries.
+//
+UINTN mSmbiosMiscDataTableEntries =
+  (sizeof (mSmbiosMiscDataTable)) / sizeof (EFI_MISC_SMBIOS_DATA_TABLE);
diff --git a/ArmPkg/Universal/Smbios/SmbiosMiscDxe/SmbiosMiscEntryPoint.c b/ArmPkg/Universal/Smbios/SmbiosMiscDxe/SmbiosMiscEntryPoint.c
new file mode 100644
index 000000000000..d61744fcd8e8
--- /dev/null
+++ b/ArmPkg/Universal/Smbios/SmbiosMiscDxe/SmbiosMiscEntryPoint.c
@@ -0,0 +1,178 @@
+/** @file
+  This driver parses the mSmbiosMiscDataTable structure and reports
+  any generated data using SMBIOS protocol.
+
+  Based on files under Nt32Pkg/MiscSubClassPlatformDxe/
+
+  Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2015, Hisilicon Limited. All rights reserved.<BR>
+  Copyright (c) 2015, Linaro Limited. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "SmbiosMisc.h"
+
+
+EFI_HANDLE              mImageHandle;
+EFI_HII_HANDLE          mHiiHandle;
+EFI_SMBIOS_PROTOCOL     *mSmbios = NULL;
+
+/**
+  Standard EFI driver point.  This driver parses the mSmbiosMiscDataTable
+  structure and reports any generated data using SMBIOS protocol.
+
+  @param  ImageHandle     Handle for the image of this driver
+  @param  SystemTable     Pointer to the EFI System Table
+
+  @retval  EFI_SUCCESS    The data was successfully stored.
+
+**/
+EFI_STATUS
+EFIAPI
+SmbiosMiscEntryPoint(
+  IN EFI_HANDLE         ImageHandle,
+  IN EFI_SYSTEM_TABLE   *SystemTable
+  )
+{
+  UINTN                Index;
+  EFI_STATUS           EfiStatus;
+  EFI_SMBIOS_PROTOCOL  *Smbios;
+
+  mImageHandle = ImageHandle;
+
+  EfiStatus = gBS->LocateProtocol (&gEfiSmbiosProtocolGuid, NULL, (VOID**)&Smbios);
+  if (EFI_ERROR (EfiStatus)) {
+    DEBUG ((DEBUG_ERROR, "Could not locate SMBIOS protocol.  %r\n", EfiStatus));
+    return EfiStatus;
+  }
+
+  mSmbios = Smbios;
+
+  mHiiHandle = HiiAddPackages (
+                 &gEfiCallerIdGuid,
+                  mImageHandle,
+                  SmbiosMiscDxeStrings,
+                  NULL
+                  );
+  if (mHiiHandle == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  for (Index = 0; Index < mSmbiosMiscDataTableEntries; ++Index) {
+    //
+    // If the entry have a function pointer, just log the data.
+    //
+    if (mSmbiosMiscDataTable[Index].Function != NULL) {
+      EfiStatus = (*mSmbiosMiscDataTable[Index].Function)(
+          mSmbiosMiscDataTable[Index].RecordData,
+          Smbios
+          );
+
+      if (EFI_ERROR(EfiStatus)) {
+        DEBUG ((DEBUG_ERROR, "Misc smbios store error.  Index=%d, ReturnStatus=%r\n", Index, EfiStatus));
+        return EfiStatus;
+      }
+    }
+  }
+
+  return EfiStatus;
+}
+
+
+/**
+  Logs SMBIOS record.
+
+  @param  Buffer                The data for the fixed portion of the SMBIOS record. The format of the record is
+                                determined by EFI_SMBIOS_TABLE_HEADER.Type. The size of the formatted area is defined
+                                by EFI_SMBIOS_TABLE_HEADER.Length and either followed by a double-null (0x0000) or
+                                a set of null terminated strings and a null.
+  @param  SmbiosHandle          A unique handle will be assigned to the SMBIOS record.
+
+  @retval EFI_SUCCESS           Record was added.
+  @retval EFI_OUT_OF_RESOURCES  Record was not added due to lack of system resources.
+
+**/
+EFI_STATUS
+LogSmbiosData (
+  IN       UINT8                      *Buffer,
+  IN  OUT  EFI_SMBIOS_HANDLE          *SmbiosHandle
+  )
+{
+  EFI_STATUS         Status;
+
+  *SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
+
+  Status = mSmbios->Add (
+                   mSmbios,
+                   NULL,
+                   SmbiosHandle,
+                   (EFI_SMBIOS_TABLE_HEADER *)Buffer
+                   );
+
+  return Status;
+}
+
+
+VOID
+GetLinkTypeHandle(
+  IN  UINT8                 SmbiosType,
+  OUT SMBIOS_HANDLE         **HandleArray,
+  OUT UINTN                 *HandleCount
+  )
+{
+  UINTN                    Index;
+  EFI_STATUS               Status;
+  EFI_SMBIOS_HANDLE        SmbiosHandle;
+  EFI_SMBIOS_TABLE_HEADER  *Record;
+
+  if (mSmbios == NULL) {
+    return;
+  }
+
+  SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
+  *HandleCount = 0;
+
+  // Iterate through entries to get the number
+  while (TRUE) {
+    Status = mSmbios->GetNext (
+                        mSmbios,
+                        &SmbiosHandle,
+                        &SmbiosType,
+                        &Record,
+                        NULL
+                        );
+
+    if (!EFI_ERROR (Status)) {
+      (*HandleCount)++;
+    } else {
+      break;
+    }
+  }
+
+  *HandleArray = AllocateZeroPool (sizeof (SMBIOS_HANDLE) * (*HandleCount));
+  if (*HandleArray == NULL) {
+    DEBUG ((DEBUG_ERROR, "HandleArray allocate memory resource failed.\n"));
+    *HandleCount = 0;
+    return;
+  }
+
+  SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
+
+  for (Index = 0; Index < (*HandleCount); Index++) {
+    Status = mSmbios->GetNext (
+                        mSmbios,
+                        &SmbiosHandle,
+                        &SmbiosType,
+                        &Record,
+                        NULL
+                        );
+
+    if (!EFI_ERROR (Status)) {
+      (*HandleArray)[Index] = Record->Handle;
+    } else {
+      break;
+    }
+  }
+}
+
diff --git a/ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type00/MiscBiosVendorData.c b/ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type00/MiscBiosVendorData.c
new file mode 100644
index 000000000000..3b0d907c3996
--- /dev/null
+++ b/ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type00/MiscBiosVendorData.c
@@ -0,0 +1,92 @@
+/** @file
+  This file provides Smbios Type0 Data
+
+  Based on the files under Nt32Pkg/MiscSubClassPlatformDxe/
+
+  Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2015, Hisilicon Limited. All rights reserved.<BR>
+  Copyright (c) 2015, Linaro Limited. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+
+#include "SmbiosMisc.h"
+
+
+//
+// Static (possibly build generated) Bios Vendor data.
+//
+MISC_SMBIOS_TABLE_DATA(SMBIOS_TABLE_TYPE0, MiscBiosVendor) = {
+  {                                          // Hdr
+    EFI_SMBIOS_TYPE_BIOS_INFORMATION,          // Type,
+    0,                                         // Length,
+    0                                          // Handle
+  },
+  1,                                         // Vendor
+  2,                                         // BiosVersion
+  0xE000,                                    // BiosSegment
+  3,                                         // BiosReleaseDate
+  0,                                         // BiosSize
+  {                                          // BiosCharacteristics
+    0,                                         // Reserved                          :2
+    0,                                         // Unknown                           :1
+    0,                                         // BiosCharacteristicsNotSupported   :1
+    0,                                         // IsaIsSupported                    :1
+    0,                                         // McaIsSupported                    :1
+    0,                                         // EisaIsSupported                   :1
+    1,                                         // PciIsSupported                    :1
+    0,                                         // PcmciaIsSupported                 :1
+    1,                                         // PlugAndPlayIsSupported            :1
+    0,                                         // ApmIsSupported                    :1
+    1,                                         // BiosIsUpgradable                  :1
+    1,                                         // BiosShadowingAllowed              :1
+    0,                                         // VlVesaIsSupported                 :1
+    0,                                         // EscdSupportIsAvailable            :1
+    1,                                         // BootFromCdIsSupported             :1
+    1,                                         // SelectableBootIsSupported         :1
+    0,                                         // RomBiosIsSocketed                 :1
+    0,                                         // BootFromPcmciaIsSupported         :1
+    1,                                         // EDDSpecificationIsSupported       :1
+    0,                                         // JapaneseNecFloppyIsSupported      :1
+    0,                                         // JapaneseToshibaFloppyIsSupported  :1
+    0,                                         // Floppy525_360IsSupported          :1
+    0,                                         // Floppy525_12IsSupported           :1
+    0,                                         // Floppy35_720IsSupported           :1
+    0,                                         // Floppy35_288IsSupported           :1
+    0,                                         // PrintScreenIsSupported            :1
+    0,                                         // Keyboard8042IsSupported           :1
+    0,                                         // SerialIsSupported                 :1
+    0,                                         // PrinterIsSupported                :1
+    0,                                         // CgaMonoIsSupported                :1
+    0,                                         // NecPc98                           :1
+    0                                          // ReservedForVendor                 :32
+  },
+
+  {
+    0x03,                                        // BIOSCharacteristicsExtensionBytes[0]
+    //  {                                          // BiosReserved
+    //    1,                                         // AcpiIsSupported                   :1
+    //    1,                                         // UsbLegacyIsSupported              :1
+    //    0,                                         // AgpIsSupported                    :1
+    //    0,                                         // I20BootIsSupported                :1
+    //    0,                                         // Ls120BootIsSupported              :1
+    //    0,                                         // AtapiZipDriveBootIsSupported      :1
+    //    0,                                         // Boot1394IsSupported               :1
+    //    0                                          // SmartBatteryIsSupported           :1
+    //  },
+    0x0D                                         //BIOSCharacteristicsExtensionBytes[1]
+    //  {                                          //SystemReserved
+    //    1,                                         //BiosBootSpecIsSupported            :1
+    //    0,                                         //FunctionKeyNetworkBootIsSupported  :1
+    //    1,                                         //TargetContentDistributionEnabled   :1
+    //    1,                                         //UefiSpecificationSupported         :1
+    //    0,                                         //VirtualMachineSupported            :1
+    //    0                                          //ExtensionByte2Reserved             :3
+    //  },
+  },
+  0xFF,                                        // SystemBiosMajorRelease;
+  0xFF,                                        // SystemBiosMinorRelease;
+  0xFF,                                     // EmbeddedControllerFirmwareMajorRelease;
+  0xFF                                      // EmbeddedControllerFirmwareMinorRelease;
+};
diff --git a/ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type00/MiscBiosVendorFunction.c b/ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type00/MiscBiosVendorFunction.c
new file mode 100644
index 000000000000..a502c06e4b46
--- /dev/null
+++ b/ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type00/MiscBiosVendorFunction.c
@@ -0,0 +1,263 @@
+/** @file
+  This driver parses the mMiscSubclassDataTable structure and reports
+  any generated data to the DataHub.
+
+  Copyright (c) 2009, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2015, Hisilicon Limited. All rights reserved.<BR>
+  Copyright (c) 2015, Linaro Limited. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "SmbiosMisc.h"
+typedef struct {
+  CONST CHAR8* MonthStr;
+  UINT32       MonthInt;
+} MONTH_DESCRIPTION;
+
+MONTH_DESCRIPTION mMonthDescription[] = {
[SAMI] Can we add the STATIC CONST storage class specifier here?
[/SAMI]
+  { "Jan", 1 },
+  { "Feb", 2 },
+  { "Mar", 3 },
+  { "Apr", 4 },
+  { "May", 5 },
+  { "Jun", 6 },
+  { "Jul", 7 },
+  { "Aug", 8 },
+  { "Sep", 9 },
+  { "Oct", 10 },
+  { "Nov", 11 },
+  { "Dec", 12 },
+  { "???", 1 },  // Use 1 as default month
+};
+
+/**
+ * Field Filling Function. Transform an EFI_EXP_BASE2_DATA to a byte, with '64k'
+ * as the unit.
+ *
+ * @param  Value              Pointer to Base2_Data
+ *
+ * @retval
+ *
+**/
+UINT8
+Base2ToByteWith64KUnit (
+  IN  UINTN  Value
+  )
+{
+  UINT8 Size;
+
+  Size = Value / SIZE_64KB + (Value % SIZE_64KB + SIZE_64KB - 1) / SIZE_64KB;
[SAMI] I think this could be optimised to 
   Size = (Value + (SIZE_64KB - 1)) >> 16;
[/SAMI]
+
+  return Size;
+}
+
+
+VOID
+GetReleaseTime (
+  OUT EFI_TIME *Time
+  )
+{
+  CONST CHAR8      *ReleaseDate = __DATE__;
+  CONST CHAR8      *ReleaseTime = __TIME__;
+  UINTN            i;
+
+  for (i = 0; i < 12; i++) {
+    if (AsciiStrnCmp (ReleaseDate, mMonthDescription[i].MonthStr, 3) == 0) {
+      break;
+    }
+  }
+
+  Time->Month = mMonthDescription[i].MonthInt;
+  Time->Day = AsciiStrDecimalToUintn (ReleaseDate + 4);
+  Time->Year = AsciiStrDecimalToUintn (ReleaseDate + 7);
+  Time->Hour = AsciiStrDecimalToUintn (ReleaseTime);
+  Time->Minute = AsciiStrDecimalToUintn (ReleaseTime + 3);
+  Time->Second = AsciiStrDecimalToUintn (ReleaseTime + 6);
+}
+
+/**
+ * Fetches the firmware ('BIOS') release date from the
+ * FirmwareVersionInfo HOB.
+ *
+ * @return The release date as a UTF-16 string
+**/
+CHAR16 *
+GetBiosReleaseDate (
+  VOID
+  )
+{
+  CHAR16      *ReleaseDate = NULL;
+  EFI_TIME    BuildTime;
+
+  ReleaseDate = AllocateZeroPool ((sizeof (CHAR16)) * SMBIOS_STRING_MAX_LENGTH);
+  if (ReleaseDate == NULL) {
+      return NULL;
+  }
+
+  GetReleaseTime (&BuildTime);
+
+  (VOID)UnicodeSPrintAsciiFormat (ReleaseDate,
+                        (sizeof (CHAR16)) * SMBIOS_STRING_MAX_LENGTH,
+                        "%02d/%02d/%4d",
+                        BuildTime.Month,
+                        BuildTime.Day,
+                        BuildTime.Year
+                        );
+
+  return ReleaseDate;
+}
+
+/**
+ * Fetches the firmware ('BIOS') version from the
+ * FirmwareVersionInfo HOB.
+ *
+ * @return The version as a UTF-16 string
+**/
+CHAR16 *
+GetBiosVersion (
+  VOID
+  )
+{
+  CHAR16 *ReleaseString =
+    (CHAR16 *)FixedPcdGetPtr (PcdFirmwareVersionString);
+
+  return ReleaseString;
+}
+
+
+/**
+ * This function makes boot time changes to the contents of the
+ * MiscBiosVendor (Type 0).
+ *
+ * @param  RecordData                 Pointer to copy of RecordData from the Data Table.
+ *
+ * @retval EFI_SUCCESS                All parameters were valid.
+ * @retval EFI_UNSUPPORTED            Unexpected RecordType value.
+ * @retval EFI_INVALID_PARAMETER      Invalid parameter was found.
+ *
+**/
+MISC_SMBIOS_TABLE_FUNCTION (MiscBiosVendor)
+{
+  CHAR8                 *OptionalStrStart;
+  CHAR8                 *StrStart;
+  UINTN                 VendorStrLen;
+  UINTN                 VerStrLen;
+  UINTN                 DateStrLen;
+  UINTN                 BiosPhysicalSizeHexValue;
+  CHAR16                *Vendor;
+  CHAR16                *Version;
+  CHAR16                *ReleaseDate;
+  CHAR16                *Char16String;
+  EFI_STATUS            Status;
+  EFI_STRING_ID         TokenToUpdate;
+  EFI_STRING_ID         TokenToGet;
+  SMBIOS_TABLE_TYPE0    *SmbiosRecord;
+  EFI_SMBIOS_HANDLE     SmbiosHandle;
+  SMBIOS_TABLE_TYPE0    *InputData;
+
+  //
+  // First check for invalid parameters.
+  //
+  if (RecordData == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  InputData = (SMBIOS_TABLE_TYPE0 *)RecordData;
+
+  Vendor = (CHAR16 *) PcdGetPtr (PcdFirmwareVendor);
+
+  if (StrLen (Vendor) > 0) {
+    TokenToUpdate = STRING_TOKEN (STR_MISC_BIOS_VENDOR);
+    HiiSetString (mHiiHandle, TokenToUpdate, Vendor, NULL);
+  }
+
+  Version = GetBiosVersion();
+
+  if (StrLen (Version) > 0) {
+    TokenToUpdate = STRING_TOKEN (STR_MISC_BIOS_VERSION);
+    HiiSetString (mHiiHandle, TokenToUpdate, Version, NULL);
+  } else {
+    Version = (CHAR16 *) PcdGetPtr (PcdFirmwareVersionString);
+    if (StrLen (Version) > 0) {
+      TokenToUpdate = STRING_TOKEN (STR_MISC_BIOS_VERSION);
+      HiiSetString (mHiiHandle, TokenToUpdate, Version, NULL);
+    }
+  }
+
+  Char16String = GetBiosReleaseDate ();
+  if (StrLen(Char16String) > 0) {
+    TokenToUpdate = STRING_TOKEN (STR_MISC_BIOS_RELEASE_DATE);
+    HiiSetString (mHiiHandle, TokenToUpdate, Char16String, NULL);
+  }
+
+  TokenToGet = STRING_TOKEN (STR_MISC_BIOS_VENDOR);
+  Vendor = HiiGetPackageString (&gEfiCallerIdGuid, TokenToGet, NULL);
+  VendorStrLen = StrLen (Vendor);
+
+  TokenToGet = STRING_TOKEN (STR_MISC_BIOS_VERSION);
+  Version = HiiGetPackageString (&gEfiCallerIdGuid, TokenToGet, NULL);
+  VerStrLen = StrLen (Version);
+
+  TokenToGet = STRING_TOKEN (STR_MISC_BIOS_RELEASE_DATE);
+  ReleaseDate = HiiGetPackageString (&gEfiCallerIdGuid, TokenToGet, NULL);
+  DateStrLen = StrLen (ReleaseDate);
+
+  //
+  // Now update the BiosPhysicalSize
+  //
+  BiosPhysicalSizeHexValue = FixedPcdGet32 (PcdFdSize);
+
+  //
+  // Two zeros following the last string.
+  //
+  SmbiosRecord = AllocateZeroPool (sizeof (SMBIOS_TABLE_TYPE0) + VendorStrLen + 1 +
+                                   VerStrLen + 1 +
+                                   DateStrLen + 1 + 1);
+  if (SmbiosRecord == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Exit;
+  }
+
+  (VOID)CopyMem (SmbiosRecord, InputData, sizeof (SMBIOS_TABLE_TYPE0));
+
+  SmbiosRecord->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE0);
+  SmbiosRecord->BiosSegment = (UINT16)(FixedPcdGet32 (PcdFdBaseAddress) / SIZE_64KB);
+  SmbiosRecord->BiosSize = Base2ToByteWith64KUnit (BiosPhysicalSizeHexValue) - 1;
[SAMI] The spec says "Size (n) where 64K * (n+1) is the size of the physical device containing the BIOS, in bytes.
FFh - size is 16MB or greater, see Extended BIOS ROM Size for actual size"
If the Value is greater than 16MB then this field would not be set correctly, right? 
SMBIOS 3.1 introduces the Extended BIOS ROM size which should be populated if size is > 16MB.
Also, SBBR requires compliance with SMBIOS 3.4.0.
[/SAMI]
+
+  OptionalStrStart = (CHAR8 *)(SmbiosRecord + 1);
+  UnicodeStrToAsciiStrS (Vendor, OptionalStrStart, VendorStrLen + 1);
+  StrStart = OptionalStrStart + VendorStrLen + 1;
+  UnicodeStrToAsciiStrS (Version, StrStart, VerStrLen + 1);
+  StrStart += VerStrLen + 1;
+  UnicodeStrToAsciiStrS (ReleaseDate, StrStart, DateStrLen + 1);
+  //
+  // Now we have got the full smbios record, call smbios protocol to add this record.
+  //
+  Status = LogSmbiosData ((UINT8*)SmbiosRecord, &SmbiosHandle);
+  if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Smbios Type00 Table Log Failed! %r \n",
+              __FUNCTION__, __LINE__, Status));
+  }
+
+  FreePool (SmbiosRecord);
+
+Exit:
+  if (Vendor != NULL) {
+    FreePool (Vendor);
+  }
+
+  if (Version != NULL) {
+    FreePool (Version);
+  }
+
+  if (ReleaseDate != NULL) {
+    FreePool (ReleaseDate);
+  }
+
+  if (Char16String != NULL) {
+    FreePool (Char16String);
+  }
+
+  return Status;
+}
diff --git a/ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type01/MiscSystemManufacturerData.c b/ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type01/MiscSystemManufacturerData.c
new file mode 100644
index 000000000000..908ab9164b63
--- /dev/null
+++ b/ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type01/MiscSystemManufacturerData.c
@@ -0,0 +1,35 @@
+/** @file
+  This file provides Smbios Type1 Data
+
+  Based on files under Nt32Pkg/MiscSubClassPlatformDxe/
+
+  Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2015, Hisilicon Limited. All rights reserved.<BR>
+  Copyright (c) 2015, Linaro Limited. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "SmbiosMisc.h"
+
+
+//
+// Static (possibly build generated) System Manufacturer data.
+//
+MISC_SMBIOS_TABLE_DATA(SMBIOS_TABLE_TYPE1, MiscSystemManufacturer) = {
+  {                                               // Hdr
+    EFI_SMBIOS_TYPE_SYSTEM_INFORMATION,             // Type,
+    0,                                              // Length,
+    0                                               // Handle
+  },
+  1,                                              // Manufacturer
+  2,                                              // ProductName
+  3,                                              // Version
+  4,                                              // SerialNumber
+  {                                               // Uuid
+    0x00000000, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
+  },
+  SystemWakeupTypePowerSwitch,                    // SystemWakeupType
+  5,                                              // SKUNumber,
+  6                                               // Family
+};
diff --git a/ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type01/MiscSystemManufacturerFunction.c b/ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type01/MiscSystemManufacturerFunction.c
new file mode 100644
index 000000000000..ee2d5929555f
--- /dev/null
+++ b/ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type01/MiscSystemManufacturerFunction.c
@@ -0,0 +1,173 @@
+/** @file
+  This driver parses the mMiscSubclassDataTable structure and reports
+  any generated data to smbios.
+
+  Based on files under Nt32Pkg/MiscSubClassPlatformDxe/
+
+  Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2015, Hisilicon Limited. All rights reserved.<BR>
+  Copyright (c) 2015, Linaro Limited. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "SmbiosMisc.h"
+
+/**
+  This function makes boot time changes to the contents of the
+  MiscSystemManufacturer (Type 1).
+
+  @param  RecordData                 Pointer to copy of RecordData from the Data Table.
+
+  @retval EFI_SUCCESS                All parameters were valid.
+  @retval EFI_UNSUPPORTED            Unexpected RecordType value.
+  @retval EFI_INVALID_PARAMETER      Invalid parameter was found.
+
+**/
+MISC_SMBIOS_TABLE_FUNCTION(MiscSystemManufacturer)
+{
+  CHAR8                           *OptionalStrStart;
+  CHAR8                           *StrStart;
+  UINTN                           ManuStrLen;
+  UINTN                           VerStrLen;
+  UINTN                           PdNameStrLen;
+  UINTN                           SerialNumStrLen;
+  UINTN                           SKUNumStrLen;
+  UINTN                           FamilyStrLen;
+  UINTN                           RecordLength;
+  EFI_STRING                      Manufacturer;
+  EFI_STRING                      ProductName;
+  EFI_STRING                      Version;
+  EFI_STRING                      SerialNumber;
+  EFI_STRING                      SKUNumber;
+  EFI_STRING                      Family;
+  EFI_STRING_ID                   TokenToGet;
+  EFI_SMBIOS_HANDLE               SmbiosHandle;
+  SMBIOS_TABLE_TYPE1              *SmbiosRecord;
+  SMBIOS_TABLE_TYPE1              *InputData;
+  EFI_STATUS                      Status;
+  EFI_STRING_ID                   TokenToUpdate;
+  CHAR16                          *Product;
+  CHAR16                          *pVersion;
+
+  //
+  // First check for invalid parameters.
+  //
+  if (RecordData == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  InputData = (SMBIOS_TABLE_TYPE1 *)RecordData;
+
+  Product = (CHAR16 *) PcdGetPtr (PcdSystemProductName);
+  if (StrLen (Product) > 0) {
+    TokenToUpdate = STRING_TOKEN (STR_MISC_SYSTEM_PRODUCT_NAME);
+    HiiSetString (mHiiHandle, TokenToUpdate, Product, NULL);
+  }
+
+  pVersion = (CHAR16 *) PcdGetPtr (PcdSystemVersion);
+  if (StrLen (pVersion) > 0) {
+    TokenToUpdate = STRING_TOKEN (STR_MISC_SYSTEM_VERSION);
+    HiiSetString (mHiiHandle, TokenToUpdate, pVersion, NULL);
+  }
+  UpdateSmbiosInfo (mHiiHandle, STRING_TOKEN (STR_MISC_SYSTEM_SERIAL_NUMBER), SerialNumType01);
+  UpdateSmbiosInfo (mHiiHandle, STRING_TOKEN (STR_MISC_SYSTEM_MANUFACTURER), SystemManufacturerType01);
+
+  TokenToGet   = STRING_TOKEN (STR_MISC_SYSTEM_MANUFACTURER);
+  Manufacturer = HiiGetPackageString (&gEfiCallerIdGuid, TokenToGet, NULL);
+  ManuStrLen   = StrLen (Manufacturer);
+
+  TokenToGet   = STRING_TOKEN (STR_MISC_SYSTEM_PRODUCT_NAME);
+  ProductName  = HiiGetPackageString (&gEfiCallerIdGuid, TokenToGet, NULL);
+  PdNameStrLen = StrLen (ProductName);
+
+  TokenToGet = STRING_TOKEN (STR_MISC_SYSTEM_VERSION);
+  Version    = HiiGetPackageString (&gEfiCallerIdGuid, TokenToGet, NULL);
+  VerStrLen  = StrLen (Version);
+
+  TokenToGet      = STRING_TOKEN (STR_MISC_SYSTEM_SERIAL_NUMBER);
+  SerialNumber    = HiiGetPackageString (&gEfiCallerIdGuid, TokenToGet, NULL);
+  SerialNumStrLen = StrLen (SerialNumber);
+
+  TokenToGet   = STRING_TOKEN (STR_MISC_SYSTEM_SKU_NUMBER);
+  SKUNumber    = HiiGetPackageString (&gEfiCallerIdGuid, TokenToGet, NULL);
+  SKUNumStrLen = StrLen (SKUNumber);
+
+  TokenToGet   = STRING_TOKEN (STR_MISC_SYSTEM_FAMILY);
+  Family       = HiiGetPackageString (&gEfiCallerIdGuid, TokenToGet, NULL);
+  FamilyStrLen = StrLen (Family);
+
+  //
+  // Two zeros following the last string.
+  //
+  RecordLength = sizeof (SMBIOS_TABLE_TYPE1) +
+                 ManuStrLen      + 1 +
+                 PdNameStrLen    + 1 +
+                 VerStrLen       + 1 +
+                 SerialNumStrLen + 1 +
+                 SKUNumStrLen    + 1 +
+                 FamilyStrLen    + 1 + 1;
+  SmbiosRecord = AllocateZeroPool (RecordLength);
+
+  if (SmbiosRecord == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Exit;
+  }
+
+  (VOID)CopyMem (SmbiosRecord, InputData, sizeof (SMBIOS_TABLE_TYPE1));
+
+  SmbiosRecord->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE1);
+
+  SmbiosRecord->Uuid = InputData->Uuid;
[SAMI] I think the CopyGuid() should be used here.
[/SAMI]
+
+  OptionalStrStart = (CHAR8 *)(SmbiosRecord + 1);
+  UnicodeStrToAsciiStrS (Manufacturer, OptionalStrStart, ManuStrLen + 1);
+  StrStart = OptionalStrStart + ManuStrLen + 1;
+  UnicodeStrToAsciiStrS (ProductName,  StrStart, PdNameStrLen + 1);
+  StrStart += PdNameStrLen + 1;
+  UnicodeStrToAsciiStrS (Version, StrStart, VerStrLen + 1);
+  StrStart += VerStrLen + 1;
+  UnicodeStrToAsciiStrS (SerialNumber, StrStart, SerialNumStrLen + 1);
+  StrStart += SerialNumStrLen + 1;
+  UnicodeStrToAsciiStrS (SKUNumber, StrStart, SKUNumStrLen + 1);
+  StrStart += SKUNumStrLen + 1;
+  UnicodeStrToAsciiStrS (Family, StrStart, FamilyStrLen + 1);
+
+  //
+  // Now we have got the full smbios record, call smbios protocol to add this record.
+  //
+  Status = LogSmbiosData ((UINT8*)SmbiosRecord, &SmbiosHandle);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Smbios Type01 Table Log Failed! %r \n",
+            __FUNCTION__, __LINE__, Status));
+  }
+
+  FreePool (SmbiosRecord);
+
+Exit:
+  if (Manufacturer != NULL) {
+    FreePool (Manufacturer);
+  }
+
+  if (ProductName != NULL) {
+    FreePool (ProductName);
+  }
+
+  if (Version != NULL) {
+    FreePool (Version);
+  }
+
+  if (SerialNumber != NULL) {
+    FreePool (SerialNumber);
+  }
+
+  if (SKUNumber != NULL) {
+    FreePool (SKUNumber);
+  }
+
+  if (Family != NULL) {
+    FreePool (Family);
+  }
+
+  return 0;
+}
diff --git a/ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type02/MiscBaseBoardManufacturerData.c b/ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type02/MiscBaseBoardManufacturerData.c
new file mode 100644
index 000000000000..f9122d5d8963
--- /dev/null
+++ b/ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type02/MiscBaseBoardManufacturerData.c
@@ -0,0 +1,45 @@
+/** @file
+
+  This file provide OEM to define Smbios Type2 Data
+
+  Based on files under Nt32Pkg/MiscSubClassPlatformDxe/
+
+  Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2015, Hisilicon Limited. All rights reserved.<BR>
+  Copyright (c) 2015, Linaro Limited. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "SmbiosMisc.h"
+
+//
+// Static (possibly build generated) Chassis Manufacturer data.
+//
+MISC_SMBIOS_TABLE_DATA(SMBIOS_TABLE_TYPE2, MiscBaseBoardManufacturer) = {
+  {                                                       // Hdr
+    EFI_SMBIOS_TYPE_BASEBOARD_INFORMATION,                // Type,
+    0,                                                    // Length,
+    0                                                     // Handle
+  },
+  1,                                                      // BaseBoardManufacturer
+  2,                                                      // BaseBoardProductName
+  3,                                                      // BaseBoardVersion
+  4,                                                      // BaseBoardSerialNumber
+  5,                                                      // BaseBoardAssetTag
+  {                                                       // FeatureFlag
+    1,                                                    // Motherboard           :1
+    0,                                                    // RequiresDaughterCard  :1
+    0,                                                    // Removable             :1
+    1,                                                    // Replaceable           :1
+    0,                                                    // HotSwappable          :1
+    0                                                     // Reserved              :3
+  },
+  6,                                                      // BaseBoardChassisLocation
+  0,                                                      // ChassisHandle;
+  BaseBoardTypeMotherBoard,                               // BoardType;
+  0,                                                      // NumberOfContainedObjectHandles;
+  {
+    0
+  }                                                       // ContainedObjectHandles[1];
+};
diff --git a/ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type02/MiscBaseBoardManufacturerFunction.c b/ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type02/MiscBaseBoardManufacturerFunction.c
new file mode 100644
index 000000000000..ce56017281aa
--- /dev/null
+++ b/ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type02/MiscBaseBoardManufacturerFunction.c
@@ -0,0 +1,201 @@
+/** @file
+  This driver parses the mSmbiosMiscDataTable structure and reports
+  any generated data using SMBIOS protocol.
+
+  Based on files under Nt32Pkg/MiscSubClassPlatformDxe/
+
+  Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2015, Hisilicon Limited. All rights reserved.<BR>
+  Copyright (c) 2015, Linaro Limited. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "SmbiosMisc.h"
+
+
+/**
+  This function makes basic board manufacturer to the contents of the
+  Misc Base Board Manufacturer (Type 2).
+
+  @param  RecordData                 Pointer to copy of RecordData from the Data Table.
+
+  @retval EFI_SUCCESS                All parameters were valid.
+  @retval EFI_UNSUPPORTED            Unexpected RecordType value.
+  @retval EFI_INVALID_PARAMETER      Invalid parameter was found.
+
+**/
+MISC_SMBIOS_TABLE_FUNCTION(MiscBaseBoardManufacturer)
+{
+  CHAR8                             *OptionalStrStart;
+  CHAR8                             *StrStart;
+  UINTN                             RecordLength;
+  UINTN                             ManuStrLen;
+  UINTN                             ProductNameStrLen;
+  UINTN                             VerStrLen;
+  UINTN                             SerialNumStrLen;
+  UINTN                             AssetTagStrLen;
+  UINTN                             ChassisLocaStrLen;
+  UINTN                             HandleCount = 0;
+  UINT16                            *HandleArray = NULL;
+  CHAR16                            *BaseBoardManufacturer;
+  CHAR16                            *BaseBoardProductName;
+  CHAR16                            *Version;
+  EFI_STRING                        SerialNumber;
+  EFI_STRING                        AssetTag;
+  EFI_STRING                        ChassisLocation;
+  EFI_STRING_ID                     TokenToGet;
+  EFI_SMBIOS_HANDLE                 SmbiosHandle;
+  SMBIOS_TABLE_TYPE2                *SmbiosRecord;
+  SMBIOS_TABLE_TYPE2                *InputData = NULL;
+  EFI_STATUS                        Status;
+
+  EFI_STRING_ID                     TokenToUpdate;
+
+  //
+  // First check for invalid parameters.
+  //
+  if (RecordData == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  InputData = (SMBIOS_TABLE_TYPE2*)RecordData;
+
+  BaseBoardManufacturer = (CHAR16 *) PcdGetPtr (PcdBaseBoardManufacturer);
+  if (StrLen (BaseBoardManufacturer) > 0) {
+    TokenToUpdate = STRING_TOKEN (STR_MISC_BASE_BOARD_MANUFACTURER);
+    HiiSetString (mHiiHandle, TokenToUpdate, BaseBoardManufacturer, NULL);
+  }
+
+  BaseBoardProductName = (CHAR16 *) PcdGetPtr (PcdBaseBoardProductName);
+  if (StrLen (BaseBoardProductName) > 0) {
+    TokenToUpdate = STRING_TOKEN (STR_MISC_BASE_BOARD_PRODUCT_NAME);
+    HiiSetString (mHiiHandle, TokenToUpdate, BaseBoardProductName, NULL);
+  }
+
+  Version = (CHAR16 *) PcdGetPtr (PcdBaseBoardVersion);
+  if (StrLen (Version) > 0) {
+    TokenToUpdate = STRING_TOKEN (STR_MISC_BASE_BOARD_VERSION);
+    HiiSetString (mHiiHandle, TokenToUpdate, Version, NULL);
+  }
+
+  UpdateSmbiosInfo (mHiiHandle,
+    STRING_TOKEN (STR_MISC_BASE_BOARD_ASSET_TAG),
+    AssertTagType02
+    );
+  UpdateSmbiosInfo (mHiiHandle,
+    STRING_TOKEN (STR_MISC_BASE_BOARD_SERIAL_NUMBER),
+    SerialNumberType02
+    );
+  UpdateSmbiosInfo (mHiiHandle,
+    STRING_TOKEN (STR_MISC_BASE_BOARD_MANUFACTURER),
+    BoardManufacturerType02
+    );
+
+  TokenToGet = STRING_TOKEN (STR_MISC_BASE_BOARD_MANUFACTURER);
+  BaseBoardManufacturer = HiiGetPackageString (&gEfiCallerIdGuid, TokenToGet, NULL);
+  ManuStrLen = StrLen (BaseBoardManufacturer);
+
+  TokenToGet = STRING_TOKEN (STR_MISC_BASE_BOARD_PRODUCT_NAME);
+  BaseBoardProductName = HiiGetPackageString (&gEfiCallerIdGuid, TokenToGet, NULL);
+  ProductNameStrLen = StrLen (BaseBoardProductName);
+
+  TokenToGet = STRING_TOKEN (STR_MISC_BASE_BOARD_VERSION);
+  Version = HiiGetPackageString (&gEfiCallerIdGuid, TokenToGet, NULL);
+  VerStrLen = StrLen (Version);
+
+  TokenToGet = STRING_TOKEN (STR_MISC_BASE_BOARD_SERIAL_NUMBER);
+  SerialNumber = HiiGetPackageString (&gEfiCallerIdGuid, TokenToGet, NULL);
+  SerialNumStrLen = StrLen (SerialNumber);
+
+  TokenToGet = STRING_TOKEN (STR_MISC_BASE_BOARD_ASSET_TAG);
+  AssetTag = HiiGetPackageString (&gEfiCallerIdGuid, TokenToGet, NULL);
+  AssetTagStrLen = StrLen (AssetTag);
+
+  TokenToGet = STRING_TOKEN (STR_MISC_BASE_BOARD_CHASSIS_LOCATION);
+  ChassisLocation = HiiGetPackageString (&gEfiCallerIdGuid, TokenToGet, NULL);
+  ChassisLocaStrLen = StrLen (ChassisLocation);
+
+  //
+  // Two zeros following the last string.
+  //
+  RecordLength = sizeof (SMBIOS_TABLE_TYPE2) +
+                 ManuStrLen        + 1 +
+                 ProductNameStrLen + 1 +
+                 VerStrLen         + 1 +
+                 SerialNumStrLen   + 1 +
+                 AssetTagStrLen    + 1 +
+                 ChassisLocaStrLen + 1 + 1;
+  SmbiosRecord = AllocateZeroPool (RecordLength);
+  if (SmbiosRecord == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Exit;
+  }
+
+  (VOID)CopyMem (SmbiosRecord, InputData, sizeof (SMBIOS_TABLE_TYPE2));
+  SmbiosRecord->Hdr.Length        = sizeof (SMBIOS_TABLE_TYPE2);
+
+  //
+  //  Update Contained objects Handle
+  //
+  SmbiosRecord->NumberOfContainedObjectHandles = 0;
+  GetLinkTypeHandle (EFI_SMBIOS_TYPE_SYSTEM_ENCLOSURE, &HandleArray, &HandleCount);
+  if (HandleCount > 0) {
+    SmbiosRecord->ChassisHandle = HandleArray[0];
+  }
+
+  FreePool (HandleArray);
[SAMI] Please correct me if I am wrong, from the spec it appears that there can be n handles appended at the end of the table. However, the code above appears to only assign the first handle.
I think GetLinkTypeHandle() should be called before allocating the memory for the SmbiosRecord. That way additional space for the n handles can be allocated. The handle list can then be appended to the end of the TYPE2 table.
So, the table data should look something like: SMBIOS_TABLE_TYPE2 + (n * HANDLES) + StringData.
Does this also mean that the TYPE2 table should be the last table to be populated? Should SmbiosMiscEntryPoint() be modified to schedule the population of TYPE2 table at the end?
[/SAMI]
+
+  OptionalStrStart = (CHAR8 *)(SmbiosRecord + 1);
+  UnicodeStrToAsciiStrS (BaseBoardManufacturer, OptionalStrStart, ManuStrLen + 1);
+
+  StrStart = OptionalStrStart + ManuStrLen + 1;
+  UnicodeStrToAsciiStrS (BaseBoardProductName, StrStart, ProductNameStrLen + 1);
+
+  StrStart += ProductNameStrLen + 1;
+  UnicodeStrToAsciiStrS (Version, StrStart, VerStrLen + 1);
+
+  StrStart += VerStrLen + 1;
+  UnicodeStrToAsciiStrS (SerialNumber, StrStart, SerialNumStrLen + 1);
+
+  StrStart += SerialNumStrLen + 1;
+  UnicodeStrToAsciiStrS (AssetTag, StrStart, AssetTagStrLen + 1);
+
+  StrStart += AssetTagStrLen + 1;
+  UnicodeStrToAsciiStrS (ChassisLocation, StrStart, ChassisLocaStrLen + 1);
+
+  Status = LogSmbiosData ((UINT8 *)SmbiosRecord, &SmbiosHandle);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Smbios Type02 Table Log Failed! %r \n",
+            __FUNCTION__, __LINE__, Status));
+  }
+
+  FreePool (SmbiosRecord);
+
+Exit:
+  if (BaseBoardManufacturer != NULL) {
+    FreePool (BaseBoardManufacturer);
+  }
+
+  if (BaseBoardProductName != NULL) {
+    FreePool (BaseBoardProductName);
+  }
+
+  if (Version != NULL) {
+    FreePool (Version);
+  }
+
+  if (SerialNumber != NULL) {
+    FreePool (SerialNumber);
+  }
+
+  if (AssetTag != NULL) {
+    FreePool (AssetTag);
+  }
+
+  if (ChassisLocation != NULL) {
+    FreePool (ChassisLocation);
+  }
+
+  return 0;
+}
diff --git a/ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type03/MiscChassisManufacturerData.c b/ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type03/MiscChassisManufacturerData.c
new file mode 100644
index 000000000000..2e9e0a391ce5
--- /dev/null
+++ b/ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type03/MiscChassisManufacturerData.c
@@ -0,0 +1,51 @@
+/** @file
+  This file provides Smbios Type3 Data
+
+  Based on files under Nt32Pkg/MiscSubClassPlatformDxe/
+
+  Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2015, Hisilicon Limited. All rights reserved.<BR>
+  Copyright (c) 2015, Linaro Limited. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "SmbiosMisc.h"
+
+
+//
+// Static (possibly build generated) Chassis Manufacturer data.
+//
+MISC_SMBIOS_TABLE_DATA(SMBIOS_TABLE_TYPE3, MiscChassisManufacturer) = {
+  {                                                       // Hdr
+    EFI_SMBIOS_TYPE_SYSTEM_ENCLOSURE  ,                   // Type,
+    0,                                                    // Length,
+    0                                                     // Handle
+  },
+  1,                                                      // Manufactrurer
+  MiscChassisTypeMainServerChassis,                       // Type
+  2,                                                      // Version
+  3,                                                      // SerialNumber
+  4,                                                      // AssetTag
+  ChassisStateSafe,                                       // BootupState
+  ChassisStateSafe,                                       // PowerSupplyState
+  ChassisStateSafe,                                       // ThermalState
+  ChassisSecurityStatusNone,                              // SecurityState
+  {
+    0,                                                    // OemDefined[0]
+    0,                                                    // OemDefined[1]
+    0,                                                    // OemDefined[2]
+    0                                                     // OemDefined[3]
+  },
+  2,                                                      // Height
+  1,                                                      // NumberofPowerCords
+  0,                                                      // ContainedElementCount
+  0,                                                      // ContainedElementRecordLength
+  {                                                       // ContainedElements[0]
+    {
+      0,                                                    // ContainedElementType
+      0,                                                    // ContainedElementMinimum
+      0                                                     // ContainedElementMaximum
+    }
+  }
+};
diff --git a/ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type03/MiscChassisManufacturerFunction.c b/ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type03/MiscChassisManufacturerFunction.c
new file mode 100644
index 000000000000..69029c8532f6
--- /dev/null
+++ b/ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type03/MiscChassisManufacturerFunction.c
@@ -0,0 +1,200 @@
+/** @file
+  This driver parses the mMiscSubclassDataTable structure and reports
+  any generated data to smbios.
+
+  Based on files under Nt32Pkg/MiscSubClassPlatformDxe/
+
+  Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2015, Hisilicon Limited. All rights reserved.<BR>
+  Copyright (c) 2015, Linaro Limited. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "SmbiosMisc.h"
+
+UINT8
+GetChassisType (
+  VOID
+  )
+{
+  EFI_STATUS                      Status;
+  UINT8                           ChassisType;
+
+  Status = OemGetChassisType (&ChassisType);
+  if (EFI_ERROR (Status)) {
+    return 0;
+  }
+
+  return ChassisType;
+}
+
+/**
+  This function makes boot time changes to the contents of the
+  MiscChassisManufacturer (Type 3).
+
+  @param  RecordData                 Pointer to copy of RecordData from the Data Table.
+
+  @retval EFI_SUCCESS                All parameters were valid.
+  @retval EFI_UNSUPPORTED            Unexpected RecordType value.
+  @retval EFI_INVALID_PARAMETER      Invalid parameter was found.
+
+**/
+MISC_SMBIOS_TABLE_FUNCTION(MiscChassisManufacturer)
+{
+  CHAR8                           *OptionalStrStart;
+  CHAR8                           *StrStart;
+  UINTN                           RecordLength;
+  UINTN                           ManuStrLen;
+  UINTN                           VerStrLen;
+  UINTN                           AssertTagStrLen;
+  UINTN                           SerialNumStrLen;
+  UINTN                           ChaNumStrLen;
+  EFI_STRING                      Manufacturer;
+  EFI_STRING                      Version;
+  EFI_STRING                      SerialNumber;
+  EFI_STRING                      AssertTag;
+  EFI_STRING                      ChassisSkuNumber;
+  EFI_STRING_ID                   TokenToGet;
+  EFI_SMBIOS_HANDLE               SmbiosHandle;
+  SMBIOS_TABLE_TYPE3              *SmbiosRecord;
+  SMBIOS_TABLE_TYPE3              *InputData;
+  EFI_STATUS                      Status;
+
+  UINT8                           ContainedElementCount;
+  CONTAINED_ELEMENT               ContainedElements = {0};
+  UINT8                           ExtendLength = 0;
+
+  UINT8                           ChassisType;
+
+  //
+  // First check for invalid parameters.
+  //
+  if (RecordData == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  InputData = (SMBIOS_TABLE_TYPE3 *)RecordData;
+
+  UpdateSmbiosInfo (
+    mHiiHandle,
+    STRING_TOKEN (STR_MISC_CHASSIS_ASSET_TAG),
+    AssetTagType03
+    );
+  UpdateSmbiosInfo (
+    mHiiHandle,
+    STRING_TOKEN (STR_MISC_CHASSIS_SERIAL_NUMBER),
+    SerialNumberType03
+    );
+  UpdateSmbiosInfo (
+    mHiiHandle,
+    STRING_TOKEN (STR_MISC_CHASSIS_VERSION),
+    VersionType03
+    );
+  UpdateSmbiosInfo (
+    mHiiHandle,
+    STRING_TOKEN (STR_MISC_CHASSIS_MANUFACTURER),
+    ManufacturerType03
+    );
+
+  TokenToGet = STRING_TOKEN (STR_MISC_CHASSIS_MANUFACTURER);
+  Manufacturer = HiiGetPackageString (&gEfiCallerIdGuid, TokenToGet, NULL);
+  ManuStrLen = StrLen (Manufacturer);
+
+  TokenToGet = STRING_TOKEN (STR_MISC_CHASSIS_VERSION);
+  Version = HiiGetPackageString (&gEfiCallerIdGuid, TokenToGet, NULL);
+  VerStrLen = StrLen (Version);
+
+  TokenToGet = STRING_TOKEN (STR_MISC_CHASSIS_SERIAL_NUMBER);
+  SerialNumber = HiiGetPackageString (&gEfiCallerIdGuid, TokenToGet, NULL);
+  SerialNumStrLen = StrLen (SerialNumber);
+
+  TokenToGet = STRING_TOKEN (STR_MISC_CHASSIS_ASSET_TAG);
+  AssertTag = HiiGetPackageString (&gEfiCallerIdGuid, TokenToGet, NULL);
+  AssertTagStrLen = StrLen (AssertTag);
+
+  TokenToGet = STRING_TOKEN (STR_MISC_CHASSIS_SKU_NUMBER);
+  ChassisSkuNumber = HiiGetPackageString (&gEfiCallerIdGuid, TokenToGet, NULL);
+  ChaNumStrLen = StrLen (ChassisSkuNumber);
+
+  ContainedElementCount = InputData->ContainedElementCount;
+
+  if (ContainedElementCount > 1) {
+    ExtendLength = (ContainedElementCount - 1) * sizeof (CONTAINED_ELEMENT);
+  }
+
+  //
+  // Two zeros following the last string.
+  //
+  RecordLength = sizeof (SMBIOS_TABLE_TYPE3) +
+                 ExtendLength    + 1 +
+                 ManuStrLen      + 1 +
+                 VerStrLen       + 1 +
+                 SerialNumStrLen + 1 +
+                 AssertTagStrLen + 1 +
+                 ChaNumStrLen    + 1 + 1;
+  SmbiosRecord = AllocateZeroPool (RecordLength);
+  if (SmbiosRecord == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Exit;
+  }
+
+  (VOID)CopyMem (SmbiosRecord, InputData, sizeof (SMBIOS_TABLE_TYPE3));
+
+  SmbiosRecord->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE3) + ExtendLength + 1;
+
+  ChassisType = GetChassisType ();
+  if (ChassisType != 0) {
+    SmbiosRecord->Type  = ChassisType;
+  }
+
+  //ContainedElements
+  (VOID)CopyMem (SmbiosRecord + 1, &ContainedElements, ExtendLength);
[SAMI] If I understand correctly, the Contained Element data is never really copied, right?
[/SAMI]
+
+  //ChassisSkuNumber
+  *((UINT8 *)SmbiosRecord + sizeof (SMBIOS_TABLE_TYPE3) + ExtendLength) = 5;
+
+  OptionalStrStart = (CHAR8 *)((UINT8 *)SmbiosRecord + sizeof (SMBIOS_TABLE_TYPE3) + ExtendLength + 1);
+  UnicodeStrToAsciiStrS (Manufacturer, OptionalStrStart, ManuStrLen + 1);
+  StrStart = OptionalStrStart + ManuStrLen + 1;
+  UnicodeStrToAsciiStrS (Version, StrStart, VerStrLen + 1);
+  StrStart += VerStrLen + 1;
+  UnicodeStrToAsciiStrS (SerialNumber, StrStart, SerialNumStrLen + 1);
+  StrStart += SerialNumStrLen + 1;
+  UnicodeStrToAsciiStrS (AssertTag, StrStart, AssertTagStrLen + 1);
+  StrStart += AssertTagStrLen + 1;
+  UnicodeStrToAsciiStrS (ChassisSkuNumber, StrStart, ChaNumStrLen + 1);
+  //
+  // Now we have got the full smbios record, call smbios protocol to add this record.
+  //
+  Status = LogSmbiosData ((UINT8*)SmbiosRecord, &SmbiosHandle);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Smbios Type03 Table Log Failed! %r \n",
+            __FUNCTION__, __LINE__, Status));
+  }
+
+  FreePool (SmbiosRecord);
+
+Exit:
+  if (Manufacturer != NULL) {
+    FreePool (Manufacturer);
+  }
+
+  if (Version != NULL) {
+    FreePool (Version);
+  }
+
+  if (SerialNumber != NULL) {
+    FreePool (SerialNumber);
+  }
+
+  if (AssertTag != NULL) {
+    FreePool (AssertTag);
+  }
+
+  if (ChassisSkuNumber != NULL) {
+    FreePool (ChassisSkuNumber);
+  }
+
+  return 0;
+}
diff --git a/ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type13/MiscNumberOfInstallableLanguagesData.c b/ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type13/MiscNumberOfInstallableLanguagesData.c
new file mode 100644
index 000000000000..67a35408b700
--- /dev/null
+++ b/ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type13/MiscNumberOfInstallableLanguagesData.c
@@ -0,0 +1,32 @@
+/** @file
+  This file provides Smbios Type13 Data
+
+  Based on files under Nt32Pkg/MiscSubClassPlatformDxe/
+
+  Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2015, Hisilicon Limited. All rights reserved.<BR>
+  Copyright (c) 2015, Linaro Limited. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "SmbiosMisc.h"
+
+//
+// Static (possibly build generated) Bios Vendor data.
+//
+
+MISC_SMBIOS_TABLE_DATA(SMBIOS_TABLE_TYPE13, MiscNumberOfInstallableLanguages) =
+{
+  {                                                     // Hdr
+    EFI_SMBIOS_TYPE_BIOS_LANGUAGE_INFORMATION,            // Type,
+    0,                                                    // Length,
+    0                                                     // Handle
+  },
+  0,                                                    // InstallableLanguages
+  0,                                                    // Flags
+  {
+    0                                                   // Reserved[15]
+  },
+  1                                                     // CurrentLanguage
+};
diff --git a/ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type13/MiscNumberOfInstallableLanguagesFunction.c b/ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type13/MiscNumberOfInstallableLanguagesFunction.c
new file mode 100644
index 000000000000..297203427150
--- /dev/null
+++ b/ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type13/MiscNumberOfInstallableLanguagesFunction.c
@@ -0,0 +1,154 @@
+/** @file
+  Based on files under Nt32Pkg/MiscSubClassPlatformDxe/
+
+  Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2015, Hisilicon Limited. All rights reserved.<BR>
+  Copyright (c) 2015, Linaro Limited. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "SmbiosMisc.h"
+
+/**
+  Get next language from language code list (with separator ';').
+
+  @param  LangCode       Input: point to first language in the list. On
+                         Otput: point to next language in the list, or
+                                NULL if no more language in the list.
+  @param  Lang           The first language in the list.
+
+**/
+VOID
+EFIAPI
+GetNextLanguage (
+  IN OUT CHAR8      **LangCode,
+  OUT CHAR8         *Lang
+  )
+{
+  UINTN  Index;
+  CHAR8  *StringPtr;
+
+  if (LangCode == NULL || *LangCode == NULL || Lang == NULL) {
+    return;
+  }
+
+  Index     = 0;
+  StringPtr = *LangCode;
+  while (StringPtr[Index] != 0 && StringPtr[Index] != ';') {
+    Index++;
+  }
+
+  (VOID)CopyMem (Lang, StringPtr, Index);
+  Lang[Index] = 0;
+
+  if (StringPtr[Index] == ';') {
+    Index++;
+  }
+  *LangCode = StringPtr + Index;
+}
+
+/**
+  This function returns the number of supported languages on HiiHandle.
+
+  @param   HiiHandle    The HII package list handle.
+
+  @retval  The number of supported languages.
+
+**/
+UINT16
+EFIAPI
+GetSupportedLanguageNumber (
+  IN EFI_HII_HANDLE    HiiHandle
+  )
+{
+  CHAR8   *Lang;
+  CHAR8   *Languages;
+  CHAR8   *LanguageString;
+  UINT16  LangNumber;
+
+  Languages = HiiGetSupportedLanguages (HiiHandle);
+  if (Languages == NULL) {
+    return 0;
+  }
+
+  LangNumber = 0;
+  Lang = AllocatePool (AsciiStrSize (Languages));
+  if (Lang != NULL) {
+    LanguageString = Languages;
+    while (*LanguageString != 0) {
+      GetNextLanguage (&LanguageString, Lang);
+      LangNumber++;
+    }
+    FreePool (Lang);
+  }
+  FreePool (Languages);
+  return LangNumber;
+}
+
+
+/**
+  This function makes boot time changes to the contents of the
+  MiscNumberOfInstallableLanguages (Type 13).
+
+  @param  RecordData                 Pointer to copy of RecordData from the Data Table.
+
+  @retval EFI_SUCCESS                All parameters were valid.
+  @retval EFI_UNSUPPORTED            Unexpected RecordType value.
+  @retval EFI_INVALID_PARAMETER      Invalid parameter was found.
+
+**/
+MISC_SMBIOS_TABLE_FUNCTION(MiscNumberOfInstallableLanguages)
+{
+  UINTN                                     LangStrLen;
+  CHAR8                                     CurrentLang[SMBIOS_STRING_MAX_LENGTH + 1];
+  CHAR8                                     *OptionalStrStart;
+  EFI_STATUS                                Status;
+  EFI_SMBIOS_HANDLE                         SmbiosHandle;
+  SMBIOS_TABLE_TYPE13                       *SmbiosRecord;
+  SMBIOS_TABLE_TYPE13                       *InputData = NULL;;
+
+  //
+  // First check for invalid parameters.
+  //
+  if (RecordData == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  InputData = (SMBIOS_TABLE_TYPE13 *)RecordData;
+
+  InputData->InstallableLanguages = GetSupportedLanguageNumber (mHiiHandle);
+
+  //
+  // Try to check if current langcode matches with the langcodes in installed languages
+  //
+  ZeroMem (CurrentLang, SMBIOS_STRING_MAX_LENGTH - 1);
+  (VOID)AsciiStrCpyS (CurrentLang, SMBIOS_STRING_MAX_LENGTH - 1, "en|US|iso8859-1");
+  LangStrLen = AsciiStrLen (CurrentLang);
+
+  //
+  // Two zeros following the last string.
+  //
+  SmbiosRecord = AllocateZeroPool (sizeof (SMBIOS_TABLE_TYPE13) + LangStrLen + 1 + 1);
+  if (SmbiosRecord == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  (VOID)CopyMem (SmbiosRecord, InputData, sizeof (SMBIOS_TABLE_TYPE13));
+
+  SmbiosRecord->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE13);
+
+  OptionalStrStart = (CHAR8 *)(SmbiosRecord + 1);
+  (VOID)AsciiStrCpyS (OptionalStrStart, SMBIOS_STRING_MAX_LENGTH - 1, CurrentLang);
+  //
+  // Now we have got the full smbios record, call smbios protocol to add this record.
+  //
+  Status = LogSmbiosData ((UINT8*)SmbiosRecord, &SmbiosHandle);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Smbios Type13 Table Log Failed! %r \n",
+            __FUNCTION__, __LINE__, Status));
+  }
+
+  FreePool (SmbiosRecord);
+  return Status;
+}
diff --git a/ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type32/MiscBootInformationData.c b/ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type32/MiscBootInformationData.c
new file mode 100644
index 000000000000..e72656d3b002
--- /dev/null
+++ b/ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type32/MiscBootInformationData.c
@@ -0,0 +1,34 @@
+/** @file
+  This driver parses the mMiscSubclassDataTable structure and reports
+  any generated data to the DataHub.
+
+  Based on files under Nt32Pkg/MiscSubClassPlatformDxe/
+
+  Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2015, Hisilicon Limited. All rights reserved.<BR>
+  Copyright (c) 2015, Linaro Limited. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "SmbiosMisc.h"
+
+//
+// Static (possibly build generated) Bios Vendor data.
+//
+MISC_SMBIOS_TABLE_DATA(SMBIOS_TABLE_TYPE32, MiscBootInformation) = {
+  {                                                     // Hdr
+    EFI_SMBIOS_TYPE_SYSTEM_BOOT_INFORMATION,              // Type,
+    0,                                                    // Length,
+    0                                                     // Handle
+  },
+  {                                                     // Reserved[6]
+    0,
+    0,
+    0,
+    0,
+    0,
+    0
+  },
+  BootInformationStatusNoError                          // BootInformationStatus
+};
diff --git a/ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type32/MiscBootInformationFunction.c b/ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type32/MiscBootInformationFunction.c
new file mode 100644
index 000000000000..db91385f6e5d
--- /dev/null
+++ b/ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type32/MiscBootInformationFunction.c
@@ -0,0 +1,67 @@
+/** @file
+  boot information boot time changes.
+  SMBIOS type 32.
+
+  Based on files under Nt32Pkg/MiscSubClassPlatformDxe/
+
+  Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2015, Hisilicon Limited. All rights reserved.<BR>
+  Copyright (c) 2015, Linaro Limited. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "SmbiosMisc.h"
+
+/**
+  This function makes boot time changes to the contents of the
+  MiscBootInformation (Type 32).
+
+  @param  RecordData                 Pointer to copy of RecordData from the Data Table.
+
+  @retval EFI_SUCCESS                All parameters were valid.
+  @retval EFI_UNSUPPORTED            Unexpected RecordType value.
+  @retval EFI_INVALID_PARAMETER      Invalid parameter was found.
+
+**/
+
+MISC_SMBIOS_TABLE_FUNCTION(MiscBootInformation)
+{
+  EFI_STATUS                         Status;
+  EFI_SMBIOS_HANDLE                  SmbiosHandle;
+  SMBIOS_TABLE_TYPE32                *SmbiosRecord;
+  SMBIOS_TABLE_TYPE32                *InputData;
+
+  //
+  // First check for invalid parameters.
+  //
+  if (RecordData == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  InputData = (SMBIOS_TABLE_TYPE32 *)RecordData;
+
+  //
+  // Two zeros following the last string.
+  //
+  SmbiosRecord = AllocateZeroPool (sizeof (SMBIOS_TABLE_TYPE32) + 1 + 1);
+  if (SmbiosRecord == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  (VOID)CopyMem (SmbiosRecord, InputData, sizeof (SMBIOS_TABLE_TYPE32));
+
+  SmbiosRecord->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE32);
+
+  //
+  // Now we have got the full smbios record, call smbios protocol to add this record.
+  //
+  Status = LogSmbiosData ((UINT8*)SmbiosRecord, &SmbiosHandle);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Smbios Type32 Table Log Failed! %r \n",
+            __FUNCTION__, __LINE__, Status));
+  }
+
+  FreePool (SmbiosRecord);
+  return Status;
+}
diff --git a/ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClassStrings.uni b/ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClassStrings.uni
new file mode 100644
index 000000000000..17da6178e88f
--- /dev/null
+++ b/ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClassStrings.uni
@@ -0,0 +1,23 @@
+/** @file
+  SMBIOS Type 4 strings
+
+  Copyright (c) 2015, Hisilicon Limited. All rights reserved.
+  Copyright (c) 2015, Linaro Limited. All rights reserved.
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+/=#
+
+#langdef en-US "English"
+
+//
+// Processor Information
+//
+#string STR_PROCESSOR_SOCKET_DESIGNATION    #language en-US  "Not Specified"
+#string STR_PROCESSOR_MANUFACTURE           #language en-US  "Not Specified"
+#string STR_PROCESSOR_VERSION               #language en-US  "Not Specified"
+#string STR_PROCESSOR_SERIAL_NUMBER         #language en-US  "Not Specified"
+#string STR_PROCESSOR_ASSET_TAG             #language en-US  "Not Specified"
+#string STR_PROCESSOR_PART_NUMBER           #language en-US  "Not Specified"
+#string STR_PROCESSOR_UNKNOWN               #language en-US  "Unknown"
diff --git a/ArmPkg/Universal/Smbios/SmbiosMiscDxe/SmbiosMiscLibStrings.uni b/ArmPkg/Universal/Smbios/SmbiosMiscDxe/SmbiosMiscLibStrings.uni
new file mode 100644
index 000000000000..32f30b41566d
--- /dev/null
+++ b/ArmPkg/Universal/Smbios/SmbiosMiscDxe/SmbiosMiscLibStrings.uni
@@ -0,0 +1,21 @@
+/** @file
+ *  Based on files under Nt32Pkg/MiscSubClassPlatformDxe/
+ *
+ *  Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+ *  Copyright (c) 2015, Hisilicon Limited. All rights reserved.<BR>
+ *  Copyright (c) 2015, Linaro Limited. All rights reserved.<BR>
+ *  SPDX-License-Identifier: BSD-2-Clause-Patent
+ *
+ *
+**/
+
+
+/=#
+
+#langdef en-US "English"
+
+#include "Type00/MiscBiosVendor.uni"
+#include "Type01/MiscSystemManufacturer.uni"
+#include "Type02/MiscBaseBoardManufacturer.uni"
+#include "Type03/MiscChassisManufacturer.uni"
+#include "Type13/MiscNumberOfInstallableLanguages.uni"
diff --git a/ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type00/MiscBiosVendor.uni b/ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type00/MiscBiosVendor.uni
new file mode 100644
index 000000000000..ba981e3db391
--- /dev/null
+++ b/ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type00/MiscBiosVendor.uni
@@ -0,0 +1,17 @@
+/** @file
+  Based on files under Nt32Pkg/MiscSubClassPlatformDxe/
+
+  Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2015, Hisilicon Limited. All rights reserved.<BR>
+  Copyright (c) 2015, Linaro Limited. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+/=#
+
+#string STR_MISC_BIOS_VENDOR           #language en-US  "Not Specified"
+#string STR_MISC_BIOS_VERSION          #language en-US  "Not Specified"
+#string STR_MISC_BIOS_RELEASE_DATE     #language en-US  "Not Specified"
+#string STR_MISC_BIOS_VENDOR           #language en-US  "Not Specified"
+#string STR_MISC_BIOS_RELEASE_DATE     #language en-US  "12/02/2020"
diff --git a/ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type01/MiscSystemManufacturer.uni b/ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type01/MiscSystemManufacturer.uni
new file mode 100644
index 000000000000..9d723ba684b8
--- /dev/null
+++ b/ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type01/MiscSystemManufacturer.uni
@@ -0,0 +1,20 @@
+/** @file
+  Based on files under Nt32Pkg/MiscSubClassPlatformDxe/
+
+  Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2015, Hisilicon Limited. All rights reserved.<BR>
+  Copyright (c) 2015, Linaro Limited. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+/=#
+
+#string STR_MISC_SYSTEM_MANUFACTURER   #language en-US  "Not Specified"
+#string STR_MISC_SYSTEM_PRODUCT_NAME   #language en-US  "Not Specified"
+#string STR_MISC_SYSTEM_PRODUCT_NAME   #language en-US  "Not Specified"
+#string STR_MISC_SYSTEM_VERSION        #language en-US  "Not Specified"
+#string STR_MISC_SYSTEM_VERSION        #language en-US  "Not Specified"
+#string STR_MISC_SYSTEM_SERIAL_NUMBER  #language en-US  "Not Specified"
+#string STR_MISC_SYSTEM_SKU_NUMBER     #language en-US  "Not Specified"
+#string STR_MISC_SYSTEM_FAMILY         #language en-US  "Not Specified"
diff --git a/ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type02/MiscBaseBoardManufacturer.uni b/ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type02/MiscBaseBoardManufacturer.uni
new file mode 100644
index 000000000000..47b6c71230fe
--- /dev/null
+++ b/ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type02/MiscBaseBoardManufacturer.uni
@@ -0,0 +1,20 @@
+/** @file
+  Based on files under Nt32Pkg/MiscSubClassPlatformDxe/
+
+  Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2015, Hisilicon Limited. All rights reserved.<BR>
+  Copyright (c) 2015, Linaro Limited. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+/=#
+
+#string STR_MISC_BASE_BOARD_MANUFACTURER     #language en-US  "Not Specified"
+#string STR_MISC_BASE_BOARD_PRODUCT_NAME     #language en-US  "Not Specified"
+#string STR_MISC_BASE_BOARD_PRODUCT_NAME     #language en-US  "Not Specified"
+#string STR_MISC_BASE_BOARD_VERSION          #language en-US  "Not Specified"
+#string STR_MISC_BASE_BOARD_VERSION          #language en-US  "Not Specified"
+#string STR_MISC_BASE_BOARD_SERIAL_NUMBER    #language en-US  "Not Specified"
+#string STR_MISC_BASE_BOARD_ASSET_TAG        #language en-US  "Not Specified"
+#string STR_MISC_BASE_BOARD_CHASSIS_LOCATION #language en-US  "Not Specified"
diff --git a/ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type03/MiscChassisManufacturer.uni b/ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type03/MiscChassisManufacturer.uni
new file mode 100644
index 000000000000..dacb195bff28
--- /dev/null
+++ b/ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type03/MiscChassisManufacturer.uni
@@ -0,0 +1,17 @@
+/** @file
+  Based on files under Nt32Pkg/MiscSubClassPlatformDxe/
+
+  Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2015, Hisilicon Limited. All rights reserved.<BR>
+  Copyright (c) 2015, Linaro Limited. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+/=#
+
+#string STR_MISC_CHASSIS_MANUFACTURER  #language en-US  "Not Specified"
+#string STR_MISC_CHASSIS_VERSION       #language en-US  "Not Specified"
+#string STR_MISC_CHASSIS_SERIAL_NUMBER #language en-US  "Not Specified"
+#string STR_MISC_CHASSIS_ASSET_TAG     #language en-US  "Not Specified"
+#string STR_MISC_CHASSIS_SKU_NUMBER    #language en-US  "Not Specified"
diff --git a/ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type13/MiscNumberOfInstallableLanguages.uni b/ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type13/MiscNumberOfInstallableLanguages.uni
new file mode 100644
index 000000000000..0b61b0cd179f
--- /dev/null
+++ b/ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type13/MiscNumberOfInstallableLanguages.uni
@@ -0,0 +1,42 @@
+/** @file
+  Based on files under Nt32Pkg/MiscSubClassPlatformDxe/
+
+  Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2015, Hisilicon Limited. All rights reserved.<BR>
+  Copyright (c) 2015, Linaro Limited. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+/=#
+
+/=#
+//
+// Language String (Long Format)
+//
+#string STR_MISC_BIOS_LANGUAGES_ENG_LONG        #language en-US  "en|US|iso8859-1"
+#string STR_MISC_BIOS_LANGUAGES_FRA_LONG        #language en-US  "fr|CA|iso8859-1"
+#string STR_MISC_BIOS_LANGUAGES_CHN_LONG        #language en-US  "zh|TW|unicode"
+#string STR_MISC_BIOS_LANGUAGES_JPN_LONG        #language en-US  "ja|JP|unicode"
+#string STR_MISC_BIOS_LANGUAGES_ITA_LONG        #language en-US  "it|IT|iso8859-1"
+#string STR_MISC_BIOS_LANGUAGES_SPA_LONG        #language en-US  "es|ES|iso8859-1"
+#string STR_MISC_BIOS_LANGUAGES_GER_LONG        #language en-US  "de|DE|iso8859-1"
+#string STR_MISC_BIOS_LANGUAGES_POR_LONG        #language en-US  "pt|PT|iso8859-1"
+
+
+//
+// Language String (Abbreviated Format)
+//
+#string STR_MISC_BIOS_LANGUAGES_ENG_ABBREVIATE  #language en-US  "enUS"
+#string STR_MISC_BIOS_LANGUAGES_FRA_ABBREVIATE  #language en-US  "frCA"
+#string STR_MISC_BIOS_LANGUAGES_CHN_ABBREVIATE  #language en-US  "zhTW"
+#string STR_MISC_BIOS_LANGUAGES_JPN_ABBREVIATE  #language en-US  "jaJP"
+#string STR_MISC_BIOS_LANGUAGES_ITA_ABBREVIATE  #language en-US  "itIT"
+#string STR_MISC_BIOS_LANGUAGES_SPA_ABBREVIATE  #language en-US  "esES"
+#string STR_MISC_BIOS_LANGUAGES_GER_ABBREVIATE  #language en-US  "deDE"
+#string STR_MISC_BIOS_LANGUAGES_POR_ABBREVIATE  #language en-US  "ptPT"
+
+#string STR_MISC_BIOS_LANGUAGES_SIMPLECH_ABBREVIATE  #language en-US  "zhCN"
+#string STR_MISC_BIOS_LANGUAGES_SIMPLECH_LONG        #language en-US  "zh|CN|unicode"
+
+
-- 
2.26.2













-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#69505): https://edk2.groups.io/g/devel/message/69505
Mute This Topic: https://groups.io/mt/78784077/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