public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH v4 00/10] ArmPkg,MdePkg: Add Universal/Smbios, and related changes
@ 2020-12-07 17:54 Rebecca Cran
  2020-12-07 17:54 ` [PATCH v4 01/10] ArmPkg: Add ARM SMC Architecture functions to ArmStdSmc.h Rebecca Cran
                   ` (11 more replies)
  0 siblings, 12 replies; 40+ messages in thread
From: Rebecca Cran @ 2020-12-07 17:54 UTC (permalink / raw)
  To: devel
  Cc: Rebecca Cran, Michael D Kinney, Liming Gao, Zhiguang Liu,
	Leif Lindholm, Ard Biesheuvel

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.

I plan to submit a patch against SbsaQemu to update it to use this new
functionality.

Note: this series is based on top of the pending SmBios.h typo fixes
      series.

Changes from v3 to v4:

- Incorporated changes based on v3 feedback.
- Improved code style to more closely match the coding standard.
- Added Doxygen comments.
- Removed the VersionInfo driver, instead integrating code into 
  Universal/Smbios

Rebecca Cran (10):
  ArmPkg: Add ARM SMC Architecture functions to ArmStdSmc.h
  MdePkg: Update IndustryStandard/SmBios.h with processor status data
  ArmPkg: Add register encoding definition for MMFR2
  ArmPkg: Add helper to read the Memory Model Features Register 2
  ArmPkg: Add helper function to read the Memory Model Feature Register
    4
  ArmPkg: Add helper to read CCIDX status
  ArmPkg: Fix the return type of the ReadCCSIDR function
  ArmPkg: Update ArmLibPrivate.h with cache register definitions
  ArmPkg: Add definition of the maximum cache level in ARMv8-A
  ArmPkg: Add Universal/Smbios, a generic SMBIOS library for ARM

 ArmPkg/ArmPkg.dec                                                                       |  14 +
 ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClassDxe.inf                   |  56 ++
 ArmPkg/Universal/Smbios/SmbiosMiscDxe/SmbiosMiscDxe.inf                                 |  86 ++
 ArmPkg/Include/Chipset/AArch64.h                                                        |   4 +
 ArmPkg/Include/IndustryStandard/ArmStdSmc.h                                             |  13 +
 ArmPkg/Include/Library/ArmLib.h                                                         |  10 +
 ArmPkg/Include/Library/OemMiscLib.h                                                     |  95 +++
 ArmPkg/Library/ArmLib/AArch64/AArch64Lib.h                                              |   6 +
 ArmPkg/Library/ArmLib/Arm/ArmV7Lib.h                                                    |   6 +
 ArmPkg/Library/ArmLib/ArmLibPrivate.h                                                   |  93 ++-
 ArmPkg/Universal/Smbios/SmbiosMiscDxe/SmbiosMisc.h                                      | 136 ++++
 MdePkg/Include/IndustryStandard/SmBios.h                                                |  13 +
 ArmPkg/Library/ArmLib/AArch64/AArch64Lib.c                                              |  12 +
 ArmPkg/Library/ArmLib/Arm/ArmV7Lib.c                                                    |  12 +
 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/Library/ArmLib/AArch64/AArch64Support.S                                          |   3 +
 ArmPkg/Library/ArmLib/AArch64/ArmLibSupportV8.S                                         |   2 +-
 ArmPkg/Library/ArmLib/Arm/ArmLibSupportV7.S                                             |   4 +
 ArmPkg/Library/ArmLib/Arm/ArmLibSupportV7.asm                                           |   6 +-
 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 +
 40 files changed, 3149 insertions(+), 3 deletions(-)
 create mode 100644 ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClassDxe.inf
 create mode 100644 ArmPkg/Universal/Smbios/SmbiosMiscDxe/SmbiosMiscDxe.inf
 create mode 100644 ArmPkg/Include/Library/OemMiscLib.h
 create mode 100644 ArmPkg/Universal/Smbios/SmbiosMiscDxe/SmbiosMisc.h
 create mode 100644 ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClass.c
 create mode 100644 ArmPkg/Universal/Smbios/SmbiosMiscDxe/SmbiosMiscDataTable.c
 create mode 100644 ArmPkg/Universal/Smbios/SmbiosMiscDxe/SmbiosMiscEntryPoint.c
 create mode 100644 ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type00/MiscBiosVendorData.c
 create mode 100644 ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type00/MiscBiosVendorFunction.c
 create mode 100644 ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type01/MiscSystemManufacturerData.c
 create mode 100644 ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type01/MiscSystemManufacturerFunction.c
 create mode 100644 ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type02/MiscBaseBoardManufacturerData.c
 create mode 100644 ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type02/MiscBaseBoardManufacturerFunction.c
 create mode 100644 ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type03/MiscChassisManufacturerData.c
 create mode 100644 ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type03/MiscChassisManufacturerFunction.c
 create mode 100644 ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type13/MiscNumberOfInstallableLanguagesData.c
 create mode 100644 ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type13/MiscNumberOfInstallableLanguagesFunction.c
 create mode 100644 ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type32/MiscBootInformationData.c
 create mode 100644 ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type32/MiscBootInformationFunction.c
 create mode 100644 ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClassStrings.uni
 create mode 100644 ArmPkg/Universal/Smbios/SmbiosMiscDxe/SmbiosMiscLibStrings.uni
 create mode 100644 ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type00/MiscBiosVendor.uni
 create mode 100644 ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type01/MiscSystemManufacturer.uni
 create mode 100644 ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type02/MiscBaseBoardManufacturer.uni
 create mode 100644 ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type03/MiscChassisManufacturer.uni
 create mode 100644 ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type13/MiscNumberOfInstallableLanguages.uni

-- 
2.26.2


^ permalink raw reply	[flat|nested] 40+ messages in thread

* [PATCH v4 01/10] ArmPkg: Add ARM SMC Architecture functions to ArmStdSmc.h
  2020-12-07 17:54 [PATCH v4 00/10] ArmPkg,MdePkg: Add Universal/Smbios, and related changes Rebecca Cran
@ 2020-12-07 17:54 ` Rebecca Cran
  2020-12-15 18:06   ` Leif Lindholm
  2020-12-16 11:23   ` [edk2-devel] " Sami Mujawar
  2020-12-07 17:54 ` [PATCH v4 02/10] MdePkg: Update IndustryStandard/SmBios.h with processor status data Rebecca Cran
                   ` (10 subsequent siblings)
  11 siblings, 2 replies; 40+ messages in thread
From: Rebecca Cran @ 2020-12-07 17:54 UTC (permalink / raw)
  To: devel
  Cc: Rebecca Cran, Michael D Kinney, Liming Gao, Zhiguang Liu,
	Leif Lindholm, Ard Biesheuvel

The ARM SMC Architecture functions were missing from ArmStdSmc.h.
Add them, based on the SMC Calling Convention version 1.2 specification.

Signed-off-by: Rebecca Cran <rebecca@nuviainc.com>
---
 ArmPkg/Include/IndustryStandard/ArmStdSmc.h | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/ArmPkg/Include/IndustryStandard/ArmStdSmc.h b/ArmPkg/Include/IndustryStandard/ArmStdSmc.h
index 3509eb680f18..13f2245f37f5 100644
--- a/ArmPkg/Include/IndustryStandard/ArmStdSmc.h
+++ b/ArmPkg/Include/IndustryStandard/ArmStdSmc.h
@@ -1,5 +1,6 @@
 /** @file
 *
+*  Copyright (c) 2020, NUVIA Inc. All rights reserved.<BR>
 *  Copyright (c) 2012-2017, ARM Limited. All rights reserved.
 *
 *  SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -52,6 +53,18 @@
 #define ARM_SMC_MM_RET_DENIED              -3
 #define ARM_SMC_MM_RET_NO_MEMORY           -4
 
+// ARM Architecture Calls
+#define SMCCC_VERSION           0x80000000
+#define SMCCC_ARCH_FEATURES     0x80000001
+#define SMCCC_ARCH_SOC_ID       0x80000002
+#define SMCCC_ARCH_WORKAROUND_1 0x80008000
+#define SMCCC_ARCH_WORKAROUND_2 0x80007FFF
+
+#define SMC_ARCH_CALL_SUCCESS            0
+#define SMC_ARCH_CALL_NOT_SUPPORTED     -1
+#define SMC_ARCH_CALL_NOT_REQUIRED      -2
+#define SMC_ARCH_CALL_INVALID_PARAMETER -3
+
 /*
  * Power State Coordination Interface (PSCI) calls cover a subset of the
  * Standard Service Call range.
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v4 02/10] MdePkg: Update IndustryStandard/SmBios.h with processor status data
  2020-12-07 17:54 [PATCH v4 00/10] ArmPkg,MdePkg: Add Universal/Smbios, and related changes Rebecca Cran
  2020-12-07 17:54 ` [PATCH v4 01/10] ArmPkg: Add ARM SMC Architecture functions to ArmStdSmc.h Rebecca Cran
@ 2020-12-07 17:54 ` Rebecca Cran
  2020-12-08  4:50   ` 回复: " gaoliming
  2020-12-07 17:54 ` [PATCH v4 03/10] ArmPkg: Add register encoding definition for MMFR2 Rebecca Cran
                   ` (9 subsequent siblings)
  11 siblings, 1 reply; 40+ messages in thread
From: Rebecca Cran @ 2020-12-07 17:54 UTC (permalink / raw)
  To: devel
  Cc: Rebecca Cran, Michael D Kinney, Liming Gao, Zhiguang Liu,
	Leif Lindholm, Ard Biesheuvel, Sami Mujawar

Add a bitfield that describes the structure of the byte in the Status
field of the SMBIOS Type 4 Processor Information table.

Signed-off-by: Rebecca Cran <rebecca@nuviainc.com>
Reviewed-by: Leif Lindholm <leif@nuviainc.com>
Acked-by: Sami Mujawar <sami.mujawar@arm.com>
---
 MdePkg/Include/IndustryStandard/SmBios.h | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/MdePkg/Include/IndustryStandard/SmBios.h b/MdePkg/Include/IndustryStandard/SmBios.h
index 3bc8732eef99..cc023b73692a 100644
--- a/MdePkg/Include/IndustryStandard/SmBios.h
+++ b/MdePkg/Include/IndustryStandard/SmBios.h
@@ -875,6 +875,19 @@ typedef struct {
   UINT16  ProcessorReserved2              :6;
 } PROCESSOR_CHARACTERISTIC_FLAGS;
 
+///
+/// Processor Information - Status
+///
+typedef union {
+  struct {
+    UINT8 CpuStatus       :3; ///< Indicates the status of the processor.
+    UINT8 Reserved1       :3; ///< Reserved for future use. Must be set to zero.
+    UINT8 SocketPopulated :1; ///< Indicates if the processor socket is populated or not.
+    UINT8 Reserved2       :1; ///< Reserved for future use. Must be set to zero.
+  } Bits;
+  UINT8 Data;
+} PROCESSOR_STATUS_DATA;
+
 typedef struct {
   PROCESSOR_SIGNATURE     Signature;
   PROCESSOR_FEATURE_FLAGS FeatureFlags;
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v4 03/10] ArmPkg: Add register encoding definition for MMFR2
  2020-12-07 17:54 [PATCH v4 00/10] ArmPkg,MdePkg: Add Universal/Smbios, and related changes Rebecca Cran
  2020-12-07 17:54 ` [PATCH v4 01/10] ArmPkg: Add ARM SMC Architecture functions to ArmStdSmc.h Rebecca Cran
  2020-12-07 17:54 ` [PATCH v4 02/10] MdePkg: Update IndustryStandard/SmBios.h with processor status data Rebecca Cran
@ 2020-12-07 17:54 ` Rebecca Cran
  2020-12-15 18:42   ` Leif Lindholm
  2020-12-16 11:31   ` [edk2-devel] " Sami Mujawar
  2020-12-07 17:54 ` [PATCH v4 04/10] ArmPkg: Add helper to read the Memory Model Features Register 2 Rebecca Cran
                   ` (8 subsequent siblings)
  11 siblings, 2 replies; 40+ messages in thread
From: Rebecca Cran @ 2020-12-07 17:54 UTC (permalink / raw)
  To: devel
  Cc: Rebecca Cran, Michael D Kinney, Liming Gao, Zhiguang Liu,
	Leif Lindholm, Ard Biesheuvel

Add register encoding definition for Memory Model Feature Register 2.
We need to define it here because we build for ARMv8.0, which doesn't
have it.

Signed-off-by: Rebecca Cran <rebecca@nuviainc.com>
---
 ArmPkg/Include/Chipset/AArch64.h | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/ArmPkg/Include/Chipset/AArch64.h b/ArmPkg/Include/Chipset/AArch64.h
index 0ade5cce91c3..7c2b592f92ee 100644
--- a/ArmPkg/Include/Chipset/AArch64.h
+++ b/ArmPkg/Include/Chipset/AArch64.h
@@ -112,6 +112,10 @@
 #define ARM_VECTOR_LOW_A32_FIQ  0x700
 #define ARM_VECTOR_LOW_A32_SERR 0x780
 
+// The ID_AA64MMFR2_EL1 register was added in ARMv8.2. Since we
+// build for ARMv8.0, we need to define the register here.
+#define ID_AA64MMFR2_EL1 S3_0_C0_C7_2
+
 #define VECTOR_BASE(tbl)          \
   .section .text.##tbl##,"ax";    \
   .align 11;                      \
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v4 04/10] ArmPkg: Add helper to read the Memory Model Features Register 2
  2020-12-07 17:54 [PATCH v4 00/10] ArmPkg,MdePkg: Add Universal/Smbios, and related changes Rebecca Cran
                   ` (2 preceding siblings ...)
  2020-12-07 17:54 ` [PATCH v4 03/10] ArmPkg: Add register encoding definition for MMFR2 Rebecca Cran
@ 2020-12-07 17:54 ` Rebecca Cran
  2020-12-15 19:11   ` Leif Lindholm
  2020-12-07 17:54 ` [PATCH v4 05/10] ArmPkg: Add helper function to read the Memory Model Feature Register 4 Rebecca Cran
                   ` (7 subsequent siblings)
  11 siblings, 1 reply; 40+ messages in thread
From: Rebecca Cran @ 2020-12-07 17:54 UTC (permalink / raw)
  To: devel
  Cc: Rebecca Cran, Michael D Kinney, Liming Gao, Zhiguang Liu,
	Leif Lindholm, Ard Biesheuvel

Add helper function to read the MMFR2 register. We will need this to
determine CCIDX support.

Signed-off-by: Rebecca Cran <rebecca@nuviainc.com>
---
 ArmPkg/Library/ArmLib/AArch64/AArch64Lib.h     | 6 ++++++
 ArmPkg/Library/ArmLib/AArch64/AArch64Support.S | 3 +++
 2 files changed, 9 insertions(+)

diff --git a/ArmPkg/Library/ArmLib/AArch64/AArch64Lib.h b/ArmPkg/Library/ArmLib/AArch64/AArch64Lib.h
index b2c8a8ea0b84..d6bcfc3b82ae 100644
--- a/ArmPkg/Library/ArmLib/AArch64/AArch64Lib.h
+++ b/ArmPkg/Library/ArmLib/AArch64/AArch64Lib.h
@@ -35,5 +35,11 @@ ArmCleanInvalidateDataCacheEntryBySetWay (
   IN  UINTN   SetWayFormat
   );
 
+UINTN
+EFIAPI
+ArmReadIdMmfr2 (
+  VOID
+  );
+
 #endif // __AARCH64_LIB_H__
 
diff --git a/ArmPkg/Library/ArmLib/AArch64/AArch64Support.S b/ArmPkg/Library/ArmLib/AArch64/AArch64Support.S
index 199374ff59e3..874bc2866ac3 100644
--- a/ArmPkg/Library/ArmLib/AArch64/AArch64Support.S
+++ b/ArmPkg/Library/ArmLib/AArch64/AArch64Support.S
@@ -424,6 +424,9 @@ ASM_FUNC(ArmCallWFI)
   wfi
   ret
 
+ASM_FUNC(ArmReadIdMmfr2)
+  mrs   x0, ID_AA64MMFR2_EL1           // read EL1 MMFR2
+  ret
 
 ASM_FUNC(ArmReadMpidr)
   mrs   x0, mpidr_el1           // read EL1 MPIDR
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v4 05/10] ArmPkg: Add helper function to read the Memory Model Feature Register 4
  2020-12-07 17:54 [PATCH v4 00/10] ArmPkg,MdePkg: Add Universal/Smbios, and related changes Rebecca Cran
                   ` (3 preceding siblings ...)
  2020-12-07 17:54 ` [PATCH v4 04/10] ArmPkg: Add helper to read the Memory Model Features Register 2 Rebecca Cran
@ 2020-12-07 17:54 ` Rebecca Cran
  2020-12-16 11:23   ` [edk2-devel] " Sami Mujawar
  2020-12-07 17:54 ` [PATCH v4 06/10] ArmPkg: Add helper to read CCIDX status Rebecca Cran
                   ` (6 subsequent siblings)
  11 siblings, 1 reply; 40+ messages in thread
From: Rebecca Cran @ 2020-12-07 17:54 UTC (permalink / raw)
  To: devel
  Cc: Rebecca Cran, Michael D Kinney, Liming Gao, Zhiguang Liu,
	Leif Lindholm, Ard Biesheuvel

In AARCH32, CCIDX support is indicated in the MMFR4 register - unlike
under AARCH64 where it's in MMFR2. Add a helper function to read it.

Signed-off-by: Rebecca Cran <rebecca@nuviainc.com>
---
 ArmPkg/Library/ArmLib/Arm/ArmV7Lib.h          | 6 ++++++
 ArmPkg/Library/ArmLib/Arm/ArmLibSupportV7.S   | 4 ++++
 ArmPkg/Library/ArmLib/Arm/ArmLibSupportV7.asm | 4 ++++
 3 files changed, 14 insertions(+)

diff --git a/ArmPkg/Library/ArmLib/Arm/ArmV7Lib.h b/ArmPkg/Library/ArmLib/Arm/ArmV7Lib.h
index 93183e67230e..3b331a3b2088 100644
--- a/ArmPkg/Library/ArmLib/Arm/ArmV7Lib.h
+++ b/ArmPkg/Library/ArmLib/Arm/ArmV7Lib.h
@@ -48,5 +48,11 @@ ArmCleanInvalidateDataCacheEntryBySetWay (
   IN  UINTN   SetWayFormat
   );
 
+UINT32
+EFIAPI
+ArmReadIdMmfr4 (
+  VOID
+  );
+
 #endif // __ARM_V7_LIB_H__
 
diff --git a/ArmPkg/Library/ArmLib/Arm/ArmLibSupportV7.S b/ArmPkg/Library/ArmLib/Arm/ArmLibSupportV7.S
index 01c91b10fcb7..a60a2f634132 100644
--- a/ArmPkg/Library/ArmLib/Arm/ArmLibSupportV7.S
+++ b/ArmPkg/Library/ArmLib/Arm/ArmLibSupportV7.S
@@ -60,6 +60,10 @@ ASM_FUNC(ArmDisableInterrupts)
   isb
   bx      LR
 
+ASM_FUNC(ArmReadIdMmfr4)
+  mrc    p15,0,r0,c0,c2,6     @ Read ID_MMFR4 Register
+  bx     lr
+
 // UINT32
 // ReadCCSIDR (
 //   IN UINT32 CSSELR
diff --git a/ArmPkg/Library/ArmLib/Arm/ArmLibSupportV7.asm b/ArmPkg/Library/ArmLib/Arm/ArmLibSupportV7.asm
index 26ffa331b929..1679b09b797a 100644
--- a/ArmPkg/Library/ArmLib/Arm/ArmLibSupportV7.asm
+++ b/ArmPkg/Library/ArmLib/Arm/ArmLibSupportV7.asm
@@ -64,6 +64,10 @@
   isb
   bx      LR
 
+ RVCT_ASM_EXPORT ArmReadIdMmfr4
+  mrc    p15,0,r0,c0,c2,6     ; Read ID_MMFR4 Register
+  bx     LR
+
 // UINT32
 // ReadCCSIDR (
 //   IN UINT32 CSSELR
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v4 06/10] ArmPkg: Add helper to read CCIDX status
  2020-12-07 17:54 [PATCH v4 00/10] ArmPkg,MdePkg: Add Universal/Smbios, and related changes Rebecca Cran
                   ` (4 preceding siblings ...)
  2020-12-07 17:54 ` [PATCH v4 05/10] ArmPkg: Add helper function to read the Memory Model Feature Register 4 Rebecca Cran
@ 2020-12-07 17:54 ` Rebecca Cran
  2020-12-16 11:23   ` [edk2-devel] " Sami Mujawar
  2020-12-07 17:54 ` [PATCH v4 07/10] ArmPkg: Fix the return type of the ReadCCSIDR function Rebecca Cran
                   ` (5 subsequent siblings)
  11 siblings, 1 reply; 40+ messages in thread
From: Rebecca Cran @ 2020-12-07 17:54 UTC (permalink / raw)
  To: devel
  Cc: Rebecca Cran, Michael D Kinney, Liming Gao, Zhiguang Liu,
	Leif Lindholm, Ard Biesheuvel

Add a helper function to determine CCIDX support.

Signed-off-by: Rebecca Cran <rebecca@nuviainc.com>
---
 ArmPkg/Include/Library/ArmLib.h            |  6 ++++++
 ArmPkg/Library/ArmLib/AArch64/AArch64Lib.c | 12 ++++++++++++
 ArmPkg/Library/ArmLib/Arm/ArmV7Lib.c       | 12 ++++++++++++
 3 files changed, 30 insertions(+)

diff --git a/ArmPkg/Include/Library/ArmLib.h b/ArmPkg/Include/Library/ArmLib.h
index 5a27b7c2fc27..87c3a6f1ecac 100644
--- a/ArmPkg/Include/Library/ArmLib.h
+++ b/ArmPkg/Include/Library/ArmLib.h
@@ -132,6 +132,12 @@ ArmIsArchTimerImplemented (
   VOID
   );
 
+BOOLEAN
+EFIAPI
+ArmIsCcidxImplemented (
+  VOID
+  );
+
 UINTN
 EFIAPI
 ArmReadIdPfr0 (
diff --git a/ArmPkg/Library/ArmLib/AArch64/AArch64Lib.c b/ArmPkg/Library/ArmLib/AArch64/AArch64Lib.c
index 3fbd591192e2..915c2cacdd99 100644
--- a/ArmPkg/Library/ArmLib/AArch64/AArch64Lib.c
+++ b/ArmPkg/Library/ArmLib/AArch64/AArch64Lib.c
@@ -71,3 +71,15 @@ ArmCleanDataCache (
   ArmDataSynchronizationBarrier ();
   AArch64DataCacheOperation (ArmCleanDataCacheEntryBySetWay);
 }
+
+BOOLEAN
+EFIAPI
+ArmIsCcidxImplemented (
+  VOID
+  )
+{
+  UINTN Mmfr2;
+
+  Mmfr2 = ArmReadIdMmfr2 ();
+  return (((Mmfr2 >> 20) & 0xF) == 1) ? TRUE : FALSE;
+}
diff --git a/ArmPkg/Library/ArmLib/Arm/ArmV7Lib.c b/ArmPkg/Library/ArmLib/Arm/ArmV7Lib.c
index 2c4a23e1a1b2..7331b1c678f3 100644
--- a/ArmPkg/Library/ArmLib/Arm/ArmV7Lib.c
+++ b/ArmPkg/Library/ArmLib/Arm/ArmV7Lib.c
@@ -71,3 +71,15 @@ ArmCleanDataCache (
   ArmDataSynchronizationBarrier ();
   ArmV7DataCacheOperation (ArmCleanDataCacheEntryBySetWay);
 }
+
+BOOLEAN
+EFIAPI
+ArmIsCcidxImplemented (
+  VOID
+  )
+{
+  UINTN Mmfr4;
+
+  Mmfr4 = ArmReadIdMmfr4 ();
+  return (((Mmfr4 >> 24) & 0xF) == 1) ? TRUE : FALSE;
+}
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v4 07/10] ArmPkg: Fix the return type of the ReadCCSIDR function
  2020-12-07 17:54 [PATCH v4 00/10] ArmPkg,MdePkg: Add Universal/Smbios, and related changes Rebecca Cran
                   ` (5 preceding siblings ...)
  2020-12-07 17:54 ` [PATCH v4 06/10] ArmPkg: Add helper to read CCIDX status Rebecca Cran
@ 2020-12-07 17:54 ` Rebecca Cran
  2020-12-15 19:24   ` Leif Lindholm
  2020-12-16 11:31   ` [edk2-devel] " Sami Mujawar
  2020-12-07 17:54 ` [PATCH v4 08/10] ArmPkg: Update ArmLibPrivate.h with cache register definitions Rebecca Cran
                   ` (4 subsequent siblings)
  11 siblings, 2 replies; 40+ messages in thread
From: Rebecca Cran @ 2020-12-07 17:54 UTC (permalink / raw)
  To: devel
  Cc: Rebecca Cran, Michael D Kinney, Liming Gao, Zhiguang Liu,
	Leif Lindholm, Ard Biesheuvel

When CCIDX is supported, the Current Cache Size ID Register contains
data above 32 bits: namely the number of sets. Avoid truncating this
by returning a UINTN instead of UINT32. On AARCH32, the expanded
number of sets data can be read via the CCSIDR2 register.

Signed-off-by: Rebecca Cran <rebecca@nuviainc.com>
---
 ArmPkg/Library/ArmLib/ArmLibPrivate.h           | 2 +-
 ArmPkg/Library/ArmLib/AArch64/ArmLibSupportV8.S | 2 +-
 ArmPkg/Library/ArmLib/Arm/ArmLibSupportV7.asm   | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/ArmPkg/Library/ArmLib/ArmLibPrivate.h b/ArmPkg/Library/ArmLib/ArmLibPrivate.h
index 2e90739eb858..5eecbc0e1c43 100644
--- a/ArmPkg/Library/ArmLib/ArmLibPrivate.h
+++ b/ArmPkg/Library/ArmLib/ArmLibPrivate.h
@@ -61,7 +61,7 @@ CPSRRead (
   VOID
   );
 
-UINT32
+UINTN
 ReadCCSIDR (
   IN UINT32 CSSELR
   );
diff --git a/ArmPkg/Library/ArmLib/AArch64/ArmLibSupportV8.S b/ArmPkg/Library/ArmLib/AArch64/ArmLibSupportV8.S
index 0e8d21e2264f..0ae75e4cb9f9 100644
--- a/ArmPkg/Library/ArmLib/AArch64/ArmLibSupportV8.S
+++ b/ArmPkg/Library/ArmLib/AArch64/ArmLibSupportV8.S
@@ -84,7 +84,7 @@ ASM_FUNC(ArmDisableAllExceptions)
   ret
 
 
-// UINT32
+// UINTN
 // ReadCCSIDR (
 //   IN UINT32 CSSELR
 //   )
diff --git a/ArmPkg/Library/ArmLib/Arm/ArmLibSupportV7.asm b/ArmPkg/Library/ArmLib/Arm/ArmLibSupportV7.asm
index 1679b09b797a..81f3cb79994c 100644
--- a/ArmPkg/Library/ArmLib/Arm/ArmLibSupportV7.asm
+++ b/ArmPkg/Library/ArmLib/Arm/ArmLibSupportV7.asm
@@ -68,7 +68,7 @@
   mrc    p15,0,r0,c0,c2,6     ; Read ID_MMFR4 Register
   bx     LR
 
-// UINT32
+// UINTN
 // ReadCCSIDR (
 //   IN UINT32 CSSELR
 //   )
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v4 08/10] ArmPkg: Update ArmLibPrivate.h with cache register definitions
  2020-12-07 17:54 [PATCH v4 00/10] ArmPkg,MdePkg: Add Universal/Smbios, and related changes Rebecca Cran
                   ` (6 preceding siblings ...)
  2020-12-07 17:54 ` [PATCH v4 07/10] ArmPkg: Fix the return type of the ReadCCSIDR function Rebecca Cran
@ 2020-12-07 17:54 ` Rebecca Cran
  2020-12-15 19:27   ` Leif Lindholm
  2020-12-07 17:54 ` [PATCH v4 09/10] ArmPkg: Add definition of the maximum cache level in ARMv8-A Rebecca Cran
                   ` (3 subsequent siblings)
  11 siblings, 1 reply; 40+ messages in thread
From: Rebecca Cran @ 2020-12-07 17:54 UTC (permalink / raw)
  To: devel
  Cc: Rebecca Cran, Michael D Kinney, Liming Gao, Zhiguang Liu,
	Leif Lindholm, Ard Biesheuvel

Update the cache definitions in ArmLibPrivate.h based on current
ARMv8 documentation.

Signed-off-by: Rebecca Cran <rebecca@nuviainc.com>
---
 ArmPkg/Library/ArmLib/ArmLibPrivate.h | 91 ++++++++++++++++++++
 1 file changed, 91 insertions(+)

diff --git a/ArmPkg/Library/ArmLib/ArmLibPrivate.h b/ArmPkg/Library/ArmLib/ArmLibPrivate.h
index 5eecbc0e1c43..fb1e2cc6b2ac 100644
--- a/ArmPkg/Library/ArmLib/ArmLibPrivate.h
+++ b/ArmPkg/Library/ArmLib/ArmLibPrivate.h
@@ -1,5 +1,7 @@
 /** @file
+  ArmLibPrivate.h
 
+  Copyright (c) 2020, NUVIA Inc. All rights reserved.<BR>
   Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
 
   SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -50,6 +52,95 @@
 #define CACHE_ARCHITECTURE_UNIFIED            (0UL)
 #define CACHE_ARCHITECTURE_SEPARATE           (1UL)
 
+
+/// Defines the structure of the CSSELR (Cache Size Selection) register
+typedef union {
+  struct {
+    UINT32    InD       :1;  ///< Instruction not Data bit
+    UINT32    Level     :3;  ///< Cache level (zero based)
+    UINT32    TnD       :1;  ///< Allocation not Data bit
+    UINT32    Reserved  :27; ///< Reserved, RES0
+  } Bits; ///< Bitfield definition of the register
+  UINT32 Data; ///< The entire 32-bit value
+} CSSELR_DATA;
+
+/// The cache type values for the InD field of the CSSELR register
+typedef enum
+{
+  /// Select the data or unified cache
+  CsselrCacheTypeDataOrUnified = 0,
+  /// Select the instruction cache
+  CsselrCacheTypeInstruction,
+  CsselrCacheTypeMax
+} CSSELR_CACHE_TYPE;
+
+/// Defines the structure of the CCSIDR (Current Cache Size ID) register
+typedef union {
+  struct {
+    UINT64    LineSize           :3;  ///< Line size (Log2(Num bytes in cache) - 4)
+    UINT64    Associativity      :10; ///< Associativity - 1
+    UINT64    NumSets            :15; ///< Number of sets in the cache -1
+    UINT64    Unknown            :4;  ///< Reserved, UNKNOWN
+    UINT64    Reserved           :32; ///< Reserved, RES0
+  } BitsNonCcidx; ///< Bitfield definition of the register when FEAT_CCIDX is not supported.
+  struct {
+    UINT64    LineSize           :3;  ///< Line size (Log2(Num bytes in cache) - 4)
+    UINT64    Associativity      :21; ///< Associativity - 1
+    UINT64    Reserved1          :8;  ///< Reserved, RES0
+    UINT64    NumSets            :24; ///< Number of sets in the cache -1
+    UINT64    Reserved2          :8;  ///< Reserved, RES0
+  } BitsCcidx; ///< Bitfield definition of the register when FEAT_IDX is supported.
+  UINT64 Data; ///< The entire 64-bit value
+} CCSIDR_DATA;
+
+/// Defines the structure of the AARCH32 CCSIDR2 register.
+typedef union {
+  struct {
+    UINT32 NumSets               :24; ///< Number of sets in the cache - 1
+    UINT32 Reserved              :8;  ///< Reserved, RES0
+  } Bits; ///< Bitfield definition of the register
+  UINT32 Data; ///< The entire 32-bit value
+} CSSIDR2_DATA;
+
+/** Defines the structure of the CLIDR (Cache Level ID) register.
+ *
+ * The lower 32 bits are the same for both AARCH32 and AARCH64
+ * so we can use the same structure for both.
+**/
+typedef union {
+  struct {
+    UINT32    Ctype1   : 3; ///< Level 1 cache type
+    UINT32    Ctype2   : 3; ///< Level 2 cache type
+    UINT32    Ctype3   : 3; ///< Level 3 cache type
+    UINT32    Ctype4   : 3; ///< Level 4 cache type
+    UINT32    Ctype5   : 3; ///< Level 5 cache type
+    UINT32    Ctype6   : 3; ///< Level 6 cache type
+    UINT32    Ctype7   : 3; ///< Level 7 cache type
+    UINT32    LoUIS    : 3; ///< Level of Unification Inner Shareable
+    UINT32    LoC      : 3; ///< Level of Coherency
+    UINT32    LoUU     : 3; ///< Level of Unification Uniprocessor
+    UINT32    Icb      : 3; ///< Inner Cache Boundary
+  } Bits; ///< Bitfield definition of the register
+  UINT32 Data; ///< The entire 32-bit value
+} CLIDR_DATA;
+
+/// The cache types reported in the CLIDR register.
+typedef enum {
+  /// No cache is present
+  ClidrCacheTypeNone = 0,
+  /// There is only an instruction cache
+  ClidrCacheTypeInstructionOnly,
+  /// There is only a data cache
+  ClidrCacheTypeDataOnly,
+  /// There are separate data and instruction caches
+  ClidrCacheTypeSeparate,
+  /// There is a unified cache
+  ClidrCacheTypeUnified,
+  ClidrCacheTypeMax
+} CLIDR_CACHE_TYPE;
+
+#define CLIDR_GET_CACHE_TYPE(x, level) ((x >> (3 * level)) & 0b111)
+
 VOID
 CPSRMaskInsert (
   IN  UINT32  Mask,
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v4 09/10] ArmPkg: Add definition of the maximum cache level in ARMv8-A
  2020-12-07 17:54 [PATCH v4 00/10] ArmPkg,MdePkg: Add Universal/Smbios, and related changes Rebecca Cran
                   ` (7 preceding siblings ...)
  2020-12-07 17:54 ` [PATCH v4 08/10] ArmPkg: Update ArmLibPrivate.h with cache register definitions Rebecca Cran
@ 2020-12-07 17:54 ` Rebecca Cran
  2020-12-15 19:27   ` Leif Lindholm
  2020-12-16 11:31   ` [edk2-devel] " Sami Mujawar
  2020-12-07 17:54 ` [PATCH v4 10/10] ArmPkg: Add Universal/Smbios, a generic SMBIOS library for ARM Rebecca Cran
                   ` (2 subsequent siblings)
  11 siblings, 2 replies; 40+ messages in thread
From: Rebecca Cran @ 2020-12-07 17:54 UTC (permalink / raw)
  To: devel
  Cc: Rebecca Cran, Michael D Kinney, Liming Gao, Zhiguang Liu,
	Leif Lindholm, Ard Biesheuvel

The ARM Architecture Reference Manual for ARMv8-A defines up to
seven levels of cache, L1 through L7.
Define MAX_ARM_CACHE_LEVEL to be 7.

Signed-off-by: Rebecca Cran <rebecca@nuviainc.com>
---
 ArmPkg/Include/Library/ArmLib.h | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/ArmPkg/Include/Library/ArmLib.h b/ArmPkg/Include/Library/ArmLib.h
index 87c3a6f1ecac..4e26991727cb 100644
--- a/ArmPkg/Include/Library/ArmLib.h
+++ b/ArmPkg/Include/Library/ArmLib.h
@@ -108,6 +108,10 @@ typedef enum {
 #define GET_MPID(ClusterId, CoreId)   (((ClusterId) << 8) | (CoreId))
 #define PRIMARY_CORE_ID       (PcdGet32(PcdArmPrimaryCore) & ARM_CORE_MASK)
 
+// The ARM Architecture Reference Manual for ARMv8-A defines up
+// to 7 levels of cache, L1 through L7.
+#define MAX_ARM_CACHE_LEVEL   7
+
 UINTN
 EFIAPI
 ArmDataCacheLineLength (
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v4 10/10] ArmPkg: Add Universal/Smbios, a generic SMBIOS library for ARM
  2020-12-07 17:54 [PATCH v4 00/10] ArmPkg,MdePkg: Add Universal/Smbios, and related changes Rebecca Cran
                   ` (8 preceding siblings ...)
  2020-12-07 17:54 ` [PATCH v4 09/10] ArmPkg: Add definition of the maximum cache level in ARMv8-A Rebecca Cran
@ 2020-12-07 17:54 ` Rebecca Cran
  2020-12-15 19:29   ` Leif Lindholm
                     ` (2 more replies)
  2020-12-14 15:45 ` [PATCH v4 00/10] ArmPkg,MdePkg: Add Universal/Smbios, and related changes Rebecca Cran
  2020-12-15 18:36 ` Leif Lindholm
  11 siblings, 3 replies; 40+ messages in thread
From: Rebecca Cran @ 2020-12-07 17:54 UTC (permalink / raw)
  To: devel
  Cc: Rebecca Cran, Michael D Kinney, Liming Gao, Zhiguang Liu,
	Leif Lindholm, Ard Biesheuvel

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@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
+    {                         // 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;
+  } 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 ();
+
+  // 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.
+**/
+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);
+
+  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;
+  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[] = {
+  { "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;
+
+  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;
+
+  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;
+
+  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);
+
+  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);
+
+  //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


^ permalink raw reply related	[flat|nested] 40+ messages in thread

* 回复: [PATCH v4 02/10] MdePkg: Update IndustryStandard/SmBios.h with processor status data
  2020-12-07 17:54 ` [PATCH v4 02/10] MdePkg: Update IndustryStandard/SmBios.h with processor status data Rebecca Cran
@ 2020-12-08  4:50   ` gaoliming
  0 siblings, 0 replies; 40+ messages in thread
From: gaoliming @ 2020-12-08  4:50 UTC (permalink / raw)
  To: 'Rebecca Cran', devel
  Cc: 'Michael D Kinney', 'Zhiguang Liu',
	'Leif Lindholm', 'Ard Biesheuvel',
	'Sami Mujawar'

Reviewed-by: Liming Gao <gaoliming@byosoft.com.cn>

> -----邮件原件-----
> 发件人: Rebecca Cran <rebecca@nuviainc.com>
> 发送时间: 2020年12月8日 1:54
> 收件人: devel@edk2.groups.io
> 抄送: Rebecca Cran <rebecca@nuviainc.com>; Michael D Kinney
> <michael.d.kinney@intel.com>; Liming Gao <gaoliming@byosoft.com.cn>;
> Zhiguang Liu <zhiguang.liu@intel.com>; Leif Lindholm <leif@nuviainc.com>;
> Ard Biesheuvel <ard.biesheuvel@arm.com>; Sami Mujawar
> <sami.mujawar@arm.com>
> 主题: [PATCH v4 02/10] MdePkg: Update IndustryStandard/SmBios.h with
> processor status data
> 
> Add a bitfield that describes the structure of the byte in the Status
> field of the SMBIOS Type 4 Processor Information table.
> 
> Signed-off-by: Rebecca Cran <rebecca@nuviainc.com>
> Reviewed-by: Leif Lindholm <leif@nuviainc.com>
> Acked-by: Sami Mujawar <sami.mujawar@arm.com>
> ---
>  MdePkg/Include/IndustryStandard/SmBios.h | 13 +++++++++++++
>  1 file changed, 13 insertions(+)
> 
> diff --git a/MdePkg/Include/IndustryStandard/SmBios.h
> b/MdePkg/Include/IndustryStandard/SmBios.h
> index 3bc8732eef99..cc023b73692a 100644
> --- a/MdePkg/Include/IndustryStandard/SmBios.h
> +++ b/MdePkg/Include/IndustryStandard/SmBios.h
> @@ -875,6 +875,19 @@ typedef struct {
>    UINT16  ProcessorReserved2              :6;
>  } PROCESSOR_CHARACTERISTIC_FLAGS;
> 
> +///
> +/// Processor Information - Status
> +///
> +typedef union {
> +  struct {
> +    UINT8 CpuStatus       :3; ///< Indicates the status of the processor.
> +    UINT8 Reserved1       :3; ///< Reserved for future use. Must be set
> to zero.
> +    UINT8 SocketPopulated :1; ///< Indicates if the processor socket is
> populated or not.
> +    UINT8 Reserved2       :1; ///< Reserved for future use. Must be set
> to zero.
> +  } Bits;
> +  UINT8 Data;
> +} PROCESSOR_STATUS_DATA;
> +
>  typedef struct {
>    PROCESSOR_SIGNATURE     Signature;
>    PROCESSOR_FEATURE_FLAGS FeatureFlags;
> --
> 2.26.2




^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v4 00/10] ArmPkg,MdePkg: Add Universal/Smbios, and related changes
  2020-12-07 17:54 [PATCH v4 00/10] ArmPkg,MdePkg: Add Universal/Smbios, and related changes Rebecca Cran
                   ` (9 preceding siblings ...)
  2020-12-07 17:54 ` [PATCH v4 10/10] ArmPkg: Add Universal/Smbios, a generic SMBIOS library for ARM Rebecca Cran
@ 2020-12-14 15:45 ` Rebecca Cran
  2020-12-15 18:36 ` Leif Lindholm
  11 siblings, 0 replies; 40+ messages in thread
From: Rebecca Cran @ 2020-12-14 15:45 UTC (permalink / raw)
  To: devel
  Cc: Michael D Kinney, Liming Gao, Zhiguang Liu, Leif Lindholm,
	Ard Biesheuvel

Could I have some reviews on this series, please?

Thanks.
Rebecca Cran

On 12/7/20 10:54 AM, Rebecca Cran wrote:
> 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.
> 
> I plan to submit a patch against SbsaQemu to update it to use this new
> functionality.
> 
> Note: this series is based on top of the pending SmBios.h typo fixes
>        series.
> 
> Changes from v3 to v4:
> 
> - Incorporated changes based on v3 feedback.
> - Improved code style to more closely match the coding standard.
> - Added Doxygen comments.
> - Removed the VersionInfo driver, instead integrating code into
>    Universal/Smbios
> 
> Rebecca Cran (10):
>    ArmPkg: Add ARM SMC Architecture functions to ArmStdSmc.h
>    MdePkg: Update IndustryStandard/SmBios.h with processor status data
>    ArmPkg: Add register encoding definition for MMFR2
>    ArmPkg: Add helper to read the Memory Model Features Register 2
>    ArmPkg: Add helper function to read the Memory Model Feature Register
>      4
>    ArmPkg: Add helper to read CCIDX status
>    ArmPkg: Fix the return type of the ReadCCSIDR function
>    ArmPkg: Update ArmLibPrivate.h with cache register definitions
>    ArmPkg: Add definition of the maximum cache level in ARMv8-A
>    ArmPkg: Add Universal/Smbios, a generic SMBIOS library for ARM
> 
>   ArmPkg/ArmPkg.dec                                                                       |  14 +
>   ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClassDxe.inf                   |  56 ++
>   ArmPkg/Universal/Smbios/SmbiosMiscDxe/SmbiosMiscDxe.inf                                 |  86 ++
>   ArmPkg/Include/Chipset/AArch64.h                                                        |   4 +
>   ArmPkg/Include/IndustryStandard/ArmStdSmc.h                                             |  13 +
>   ArmPkg/Include/Library/ArmLib.h                                                         |  10 +
>   ArmPkg/Include/Library/OemMiscLib.h                                                     |  95 +++
>   ArmPkg/Library/ArmLib/AArch64/AArch64Lib.h                                              |   6 +
>   ArmPkg/Library/ArmLib/Arm/ArmV7Lib.h                                                    |   6 +
>   ArmPkg/Library/ArmLib/ArmLibPrivate.h                                                   |  93 ++-
>   ArmPkg/Universal/Smbios/SmbiosMiscDxe/SmbiosMisc.h                                      | 136 ++++
>   MdePkg/Include/IndustryStandard/SmBios.h                                                |  13 +
>   ArmPkg/Library/ArmLib/AArch64/AArch64Lib.c                                              |  12 +
>   ArmPkg/Library/ArmLib/Arm/ArmV7Lib.c                                                    |  12 +
>   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/Library/ArmLib/AArch64/AArch64Support.S                                          |   3 +
>   ArmPkg/Library/ArmLib/AArch64/ArmLibSupportV8.S                                         |   2 +-
>   ArmPkg/Library/ArmLib/Arm/ArmLibSupportV7.S                                             |   4 +
>   ArmPkg/Library/ArmLib/Arm/ArmLibSupportV7.asm                                           |   6 +-
>   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 +
>   40 files changed, 3149 insertions(+), 3 deletions(-)
>   create mode 100644 ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClassDxe.inf
>   create mode 100644 ArmPkg/Universal/Smbios/SmbiosMiscDxe/SmbiosMiscDxe.inf
>   create mode 100644 ArmPkg/Include/Library/OemMiscLib.h
>   create mode 100644 ArmPkg/Universal/Smbios/SmbiosMiscDxe/SmbiosMisc.h
>   create mode 100644 ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClass.c
>   create mode 100644 ArmPkg/Universal/Smbios/SmbiosMiscDxe/SmbiosMiscDataTable.c
>   create mode 100644 ArmPkg/Universal/Smbios/SmbiosMiscDxe/SmbiosMiscEntryPoint.c
>   create mode 100644 ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type00/MiscBiosVendorData.c
>   create mode 100644 ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type00/MiscBiosVendorFunction.c
>   create mode 100644 ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type01/MiscSystemManufacturerData.c
>   create mode 100644 ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type01/MiscSystemManufacturerFunction.c
>   create mode 100644 ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type02/MiscBaseBoardManufacturerData.c
>   create mode 100644 ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type02/MiscBaseBoardManufacturerFunction.c
>   create mode 100644 ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type03/MiscChassisManufacturerData.c
>   create mode 100644 ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type03/MiscChassisManufacturerFunction.c
>   create mode 100644 ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type13/MiscNumberOfInstallableLanguagesData.c
>   create mode 100644 ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type13/MiscNumberOfInstallableLanguagesFunction.c
>   create mode 100644 ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type32/MiscBootInformationData.c
>   create mode 100644 ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type32/MiscBootInformationFunction.c
>   create mode 100644 ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClassStrings.uni
>   create mode 100644 ArmPkg/Universal/Smbios/SmbiosMiscDxe/SmbiosMiscLibStrings.uni
>   create mode 100644 ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type00/MiscBiosVendor.uni
>   create mode 100644 ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type01/MiscSystemManufacturer.uni
>   create mode 100644 ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type02/MiscBaseBoardManufacturer.uni
>   create mode 100644 ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type03/MiscChassisManufacturer.uni
>   create mode 100644 ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type13/MiscNumberOfInstallableLanguages.uni
> 


^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v4 01/10] ArmPkg: Add ARM SMC Architecture functions to ArmStdSmc.h
  2020-12-07 17:54 ` [PATCH v4 01/10] ArmPkg: Add ARM SMC Architecture functions to ArmStdSmc.h Rebecca Cran
@ 2020-12-15 18:06   ` Leif Lindholm
  2020-12-16 11:23   ` [edk2-devel] " Sami Mujawar
  1 sibling, 0 replies; 40+ messages in thread
From: Leif Lindholm @ 2020-12-15 18:06 UTC (permalink / raw)
  To: Rebecca Cran
  Cc: devel, Michael D Kinney, Liming Gao, Zhiguang Liu, Ard Biesheuvel

On Mon, Dec 07, 2020 at 10:54:18 -0700, Rebecca Cran wrote:
> The ARM SMC Architecture functions were missing from ArmStdSmc.h.
> Add them, based on the SMC Calling Convention version 1.2 specification.
> 
> Signed-off-by: Rebecca Cran <rebecca@nuviainc.com>

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

> ---
>  ArmPkg/Include/IndustryStandard/ArmStdSmc.h | 13 +++++++++++++
>  1 file changed, 13 insertions(+)
> 
> diff --git a/ArmPkg/Include/IndustryStandard/ArmStdSmc.h b/ArmPkg/Include/IndustryStandard/ArmStdSmc.h
> index 3509eb680f18..13f2245f37f5 100644
> --- a/ArmPkg/Include/IndustryStandard/ArmStdSmc.h
> +++ b/ArmPkg/Include/IndustryStandard/ArmStdSmc.h
> @@ -1,5 +1,6 @@
>  /** @file
>  *
> +*  Copyright (c) 2020, NUVIA Inc. All rights reserved.<BR>
>  *  Copyright (c) 2012-2017, ARM Limited. All rights reserved.
>  *
>  *  SPDX-License-Identifier: BSD-2-Clause-Patent
> @@ -52,6 +53,18 @@
>  #define ARM_SMC_MM_RET_DENIED              -3
>  #define ARM_SMC_MM_RET_NO_MEMORY           -4
>  
> +// ARM Architecture Calls
> +#define SMCCC_VERSION           0x80000000
> +#define SMCCC_ARCH_FEATURES     0x80000001
> +#define SMCCC_ARCH_SOC_ID       0x80000002
> +#define SMCCC_ARCH_WORKAROUND_1 0x80008000
> +#define SMCCC_ARCH_WORKAROUND_2 0x80007FFF
> +
> +#define SMC_ARCH_CALL_SUCCESS            0
> +#define SMC_ARCH_CALL_NOT_SUPPORTED     -1
> +#define SMC_ARCH_CALL_NOT_REQUIRED      -2
> +#define SMC_ARCH_CALL_INVALID_PARAMETER -3
> +
>  /*
>   * Power State Coordination Interface (PSCI) calls cover a subset of the
>   * Standard Service Call range.
> -- 
> 2.26.2
> 

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v4 00/10] ArmPkg,MdePkg: Add Universal/Smbios, and related changes
  2020-12-07 17:54 [PATCH v4 00/10] ArmPkg,MdePkg: Add Universal/Smbios, and related changes Rebecca Cran
                   ` (10 preceding siblings ...)
  2020-12-14 15:45 ` [PATCH v4 00/10] ArmPkg,MdePkg: Add Universal/Smbios, and related changes Rebecca Cran
@ 2020-12-15 18:36 ` Leif Lindholm
  11 siblings, 0 replies; 40+ messages in thread
From: Leif Lindholm @ 2020-12-15 18:36 UTC (permalink / raw)
  To: Rebecca Cran
  Cc: devel, Michael D Kinney, Liming Gao, Zhiguang Liu, Ard Biesheuvel

High-level comment:

Could you please add the two new drivers to the Components section of
ArmPkg/ArmPkg.dsc, to make it possible to build them standalone?

This will also require implementing an OemMiscLibNull.
It would make sense to break out ArmPkg/Include/Library/OemMiscLib.h
and add it together with the Null library implementation.

/
    Leif

On Mon, Dec 07, 2020 at 10:54:17 -0700, Rebecca Cran wrote:
> 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.
> 
> I plan to submit a patch against SbsaQemu to update it to use this new
> functionality.
> 
> Note: this series is based on top of the pending SmBios.h typo fixes
>       series.
> 
> Changes from v3 to v4:
> 
> - Incorporated changes based on v3 feedback.
> - Improved code style to more closely match the coding standard.
> - Added Doxygen comments.
> - Removed the VersionInfo driver, instead integrating code into 
>   Universal/Smbios
> 
> Rebecca Cran (10):
>   ArmPkg: Add ARM SMC Architecture functions to ArmStdSmc.h
>   MdePkg: Update IndustryStandard/SmBios.h with processor status data
>   ArmPkg: Add register encoding definition for MMFR2
>   ArmPkg: Add helper to read the Memory Model Features Register 2
>   ArmPkg: Add helper function to read the Memory Model Feature Register
>     4
>   ArmPkg: Add helper to read CCIDX status
>   ArmPkg: Fix the return type of the ReadCCSIDR function
>   ArmPkg: Update ArmLibPrivate.h with cache register definitions
>   ArmPkg: Add definition of the maximum cache level in ARMv8-A
>   ArmPkg: Add Universal/Smbios, a generic SMBIOS library for ARM
> 
>  ArmPkg/ArmPkg.dec                                                                       |  14 +
>  ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClassDxe.inf                   |  56 ++
>  ArmPkg/Universal/Smbios/SmbiosMiscDxe/SmbiosMiscDxe.inf                                 |  86 ++
>  ArmPkg/Include/Chipset/AArch64.h                                                        |   4 +
>  ArmPkg/Include/IndustryStandard/ArmStdSmc.h                                             |  13 +
>  ArmPkg/Include/Library/ArmLib.h                                                         |  10 +
>  ArmPkg/Include/Library/OemMiscLib.h                                                     |  95 +++
>  ArmPkg/Library/ArmLib/AArch64/AArch64Lib.h                                              |   6 +
>  ArmPkg/Library/ArmLib/Arm/ArmV7Lib.h                                                    |   6 +
>  ArmPkg/Library/ArmLib/ArmLibPrivate.h                                                   |  93 ++-
>  ArmPkg/Universal/Smbios/SmbiosMiscDxe/SmbiosMisc.h                                      | 136 ++++
>  MdePkg/Include/IndustryStandard/SmBios.h                                                |  13 +
>  ArmPkg/Library/ArmLib/AArch64/AArch64Lib.c                                              |  12 +
>  ArmPkg/Library/ArmLib/Arm/ArmV7Lib.c                                                    |  12 +
>  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/Library/ArmLib/AArch64/AArch64Support.S                                          |   3 +
>  ArmPkg/Library/ArmLib/AArch64/ArmLibSupportV8.S                                         |   2 +-
>  ArmPkg/Library/ArmLib/Arm/ArmLibSupportV7.S                                             |   4 +
>  ArmPkg/Library/ArmLib/Arm/ArmLibSupportV7.asm                                           |   6 +-
>  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 +
>  40 files changed, 3149 insertions(+), 3 deletions(-)
>  create mode 100644 ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClassDxe.inf
>  create mode 100644 ArmPkg/Universal/Smbios/SmbiosMiscDxe/SmbiosMiscDxe.inf
>  create mode 100644 ArmPkg/Include/Library/OemMiscLib.h
>  create mode 100644 ArmPkg/Universal/Smbios/SmbiosMiscDxe/SmbiosMisc.h
>  create mode 100644 ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClass.c
>  create mode 100644 ArmPkg/Universal/Smbios/SmbiosMiscDxe/SmbiosMiscDataTable.c
>  create mode 100644 ArmPkg/Universal/Smbios/SmbiosMiscDxe/SmbiosMiscEntryPoint.c
>  create mode 100644 ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type00/MiscBiosVendorData.c
>  create mode 100644 ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type00/MiscBiosVendorFunction.c
>  create mode 100644 ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type01/MiscSystemManufacturerData.c
>  create mode 100644 ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type01/MiscSystemManufacturerFunction.c
>  create mode 100644 ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type02/MiscBaseBoardManufacturerData.c
>  create mode 100644 ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type02/MiscBaseBoardManufacturerFunction.c
>  create mode 100644 ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type03/MiscChassisManufacturerData.c
>  create mode 100644 ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type03/MiscChassisManufacturerFunction.c
>  create mode 100644 ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type13/MiscNumberOfInstallableLanguagesData.c
>  create mode 100644 ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type13/MiscNumberOfInstallableLanguagesFunction.c
>  create mode 100644 ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type32/MiscBootInformationData.c
>  create mode 100644 ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type32/MiscBootInformationFunction.c
>  create mode 100644 ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClassStrings.uni
>  create mode 100644 ArmPkg/Universal/Smbios/SmbiosMiscDxe/SmbiosMiscLibStrings.uni
>  create mode 100644 ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type00/MiscBiosVendor.uni
>  create mode 100644 ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type01/MiscSystemManufacturer.uni
>  create mode 100644 ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type02/MiscBaseBoardManufacturer.uni
>  create mode 100644 ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type03/MiscChassisManufacturer.uni
>  create mode 100644 ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type13/MiscNumberOfInstallableLanguages.uni
> 
> -- 
> 2.26.2
> 

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v4 03/10] ArmPkg: Add register encoding definition for MMFR2
  2020-12-07 17:54 ` [PATCH v4 03/10] ArmPkg: Add register encoding definition for MMFR2 Rebecca Cran
@ 2020-12-15 18:42   ` Leif Lindholm
  2020-12-16 11:31   ` [edk2-devel] " Sami Mujawar
  1 sibling, 0 replies; 40+ messages in thread
From: Leif Lindholm @ 2020-12-15 18:42 UTC (permalink / raw)
  To: Rebecca Cran; +Cc: devel, Ard Biesheuvel

On Mon, Dec 07, 2020 at 10:54:20 -0700, Rebecca Cran wrote:
> Add register encoding definition for Memory Model Feature Register 2.
> We need to define it here because we build for ARMv8.0, which doesn't
> have it.
> 
> Signed-off-by: Rebecca Cran <rebecca@nuviainc.com>

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

> ---
>  ArmPkg/Include/Chipset/AArch64.h | 4 ++++
>  1 file changed, 4 insertions(+)
> 
> diff --git a/ArmPkg/Include/Chipset/AArch64.h b/ArmPkg/Include/Chipset/AArch64.h
> index 0ade5cce91c3..7c2b592f92ee 100644
> --- a/ArmPkg/Include/Chipset/AArch64.h
> +++ b/ArmPkg/Include/Chipset/AArch64.h
> @@ -112,6 +112,10 @@
>  #define ARM_VECTOR_LOW_A32_FIQ  0x700
>  #define ARM_VECTOR_LOW_A32_SERR 0x780
>  
> +// The ID_AA64MMFR2_EL1 register was added in ARMv8.2. Since we
> +// build for ARMv8.0, we need to define the register here.
> +#define ID_AA64MMFR2_EL1 S3_0_C0_C7_2
> +
>  #define VECTOR_BASE(tbl)          \
>    .section .text.##tbl##,"ax";    \
>    .align 11;                      \
> -- 
> 2.26.2
> 

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v4 04/10] ArmPkg: Add helper to read the Memory Model Features Register 2
  2020-12-07 17:54 ` [PATCH v4 04/10] ArmPkg: Add helper to read the Memory Model Features Register 2 Rebecca Cran
@ 2020-12-15 19:11   ` Leif Lindholm
  2020-12-16 11:06     ` [edk2-devel] " Sami Mujawar
  2020-12-17 13:38     ` Laszlo Ersek
  0 siblings, 2 replies; 40+ messages in thread
From: Leif Lindholm @ 2020-12-15 19:11 UTC (permalink / raw)
  To: Rebecca Cran; +Cc: devel, Ard Biesheuvel, Laszlo Ersek

+Laszlo

Ard, I could use your input on the below, and Laszlo might also have
an opinion:

On Mon, Dec 07, 2020 at 10:54:21 -0700, Rebecca Cran wrote:
> Add helper function to read the MMFR2 register. We will need this to
> determine CCIDX support.
> 
> Signed-off-by: Rebecca Cran <rebecca@nuviainc.com>
> ---
>  ArmPkg/Library/ArmLib/AArch64/AArch64Lib.h     | 6 ++++++
>  ArmPkg/Library/ArmLib/AArch64/AArch64Support.S | 3 +++
>  2 files changed, 9 insertions(+)
> 
> diff --git a/ArmPkg/Library/ArmLib/AArch64/AArch64Lib.h b/ArmPkg/Library/ArmLib/AArch64/AArch64Lib.h
> index b2c8a8ea0b84..d6bcfc3b82ae 100644
> --- a/ArmPkg/Library/ArmLib/AArch64/AArch64Lib.h
> +++ b/ArmPkg/Library/ArmLib/AArch64/AArch64Lib.h
> @@ -35,5 +35,11 @@ ArmCleanInvalidateDataCacheEntryBySetWay (
>    IN  UINTN   SetWayFormat
>    );
>  
> +UINTN
> +EFIAPI
> +ArmReadIdMmfr2 (
> +  VOID
> +  );
> +

First of all, I think this prototype belongs in
Include/Library/ArmLib.h ... but!

So, there are a lot of system registers, many of which share at least
the view of the bottom 32 bits between aarch64/aarch32 versions.

This isn't true for the ID registers - which are always 64-bit for
aarch64 state, and always 32-bit for aarch32, where aarch64 have
access to both.

So this helper function isn't generic - in this particular case, we're
adding this accessor because we want to determine CCIDX support.
For aarch64 this means ID_AA64MMFR2_EL1, but for aarch32 this means
ID_MMFR4 (also accessible from aarch64 as ID_MMFR4_EL1).

We already have ArmReadIdPfr0 and ArmReadIdPfr1 in ArmLib.h, already
being made use of, helping to demonstrate the problem:

ArmPkg/Library/ArmGicArchLib/AArch64/ArmGicArchLib.c:  if (ArmReadIdPfr0 () & AARCH64_PFR0_GIC) {
ArmPkg/Library/ArmGicArchLib/Arm/ArmGicArchLib.c:  if (ArmReadIdPfr1 () & ARM_PFR1_GIC) {

I would propose that since the high-level abstraction serve only to
confuse things, we change existing (and new) accessors to ID registers
to be explicit:

- ArmReadIdAArch64Mmfr0
- ArmReadIdAArch64Pfr0
- ArmReadIdAArch64Pfr1

The question is whether we should make the AArch32 aspect explicit or
implicit? My instinctive reaction is the latter. This matches the
native naming scheme used in the ARM ARM, and we don't support mixing
instruction set widths in UEFI.

The AArch64 prototypes should then only be made available to AARCH64
code, and the AArch32 ones only to ARM.

Does the above makes sense to everyone?

Best Regards,

Leif

>  #endif // __AARCH64_LIB_H__
>  
> diff --git a/ArmPkg/Library/ArmLib/AArch64/AArch64Support.S b/ArmPkg/Library/ArmLib/AArch64/AArch64Support.S
> index 199374ff59e3..874bc2866ac3 100644
> --- a/ArmPkg/Library/ArmLib/AArch64/AArch64Support.S
> +++ b/ArmPkg/Library/ArmLib/AArch64/AArch64Support.S
> @@ -424,6 +424,9 @@ ASM_FUNC(ArmCallWFI)
>    wfi
>    ret
>  
> +ASM_FUNC(ArmReadIdMmfr2)
> +  mrs   x0, ID_AA64MMFR2_EL1           // read EL1 MMFR2
> +  ret
>  
>  ASM_FUNC(ArmReadMpidr)
>    mrs   x0, mpidr_el1           // read EL1 MPIDR
> -- 
> 2.26.2
> 

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v4 07/10] ArmPkg: Fix the return type of the ReadCCSIDR function
  2020-12-07 17:54 ` [PATCH v4 07/10] ArmPkg: Fix the return type of the ReadCCSIDR function Rebecca Cran
@ 2020-12-15 19:24   ` Leif Lindholm
  2020-12-16 11:31   ` [edk2-devel] " Sami Mujawar
  1 sibling, 0 replies; 40+ messages in thread
From: Leif Lindholm @ 2020-12-15 19:24 UTC (permalink / raw)
  To: Rebecca Cran
  Cc: devel, Michael D Kinney, Liming Gao, Zhiguang Liu, Ard Biesheuvel

On Mon, Dec 07, 2020 at 10:54:24 -0700, Rebecca Cran wrote:
> When CCIDX is supported, the Current Cache Size ID Register contains
> data above 32 bits: namely the number of sets. Avoid truncating this
> by returning a UINTN instead of UINT32. On AARCH32, the expanded
> number of sets data can be read via the CCSIDR2 register.
>
> Signed-off-by: Rebecca Cran <rebecca@nuviainc.com>

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

> ---
>  ArmPkg/Library/ArmLib/ArmLibPrivate.h           | 2 +-
>  ArmPkg/Library/ArmLib/AArch64/ArmLibSupportV8.S | 2 +-
>  ArmPkg/Library/ArmLib/Arm/ArmLibSupportV7.asm   | 2 +-
>  3 files changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/ArmPkg/Library/ArmLib/ArmLibPrivate.h b/ArmPkg/Library/ArmLib/ArmLibPrivate.h
> index 2e90739eb858..5eecbc0e1c43 100644
> --- a/ArmPkg/Library/ArmLib/ArmLibPrivate.h
> +++ b/ArmPkg/Library/ArmLib/ArmLibPrivate.h
> @@ -61,7 +61,7 @@ CPSRRead (
>    VOID
>    );
>  
> -UINT32
> +UINTN
>  ReadCCSIDR (
>    IN UINT32 CSSELR
>    );
> diff --git a/ArmPkg/Library/ArmLib/AArch64/ArmLibSupportV8.S b/ArmPkg/Library/ArmLib/AArch64/ArmLibSupportV8.S
> index 0e8d21e2264f..0ae75e4cb9f9 100644
> --- a/ArmPkg/Library/ArmLib/AArch64/ArmLibSupportV8.S
> +++ b/ArmPkg/Library/ArmLib/AArch64/ArmLibSupportV8.S
> @@ -84,7 +84,7 @@ ASM_FUNC(ArmDisableAllExceptions)
>    ret
>  
>  
> -// UINT32
> +// UINTN
>  // ReadCCSIDR (
>  //   IN UINT32 CSSELR
>  //   )
> diff --git a/ArmPkg/Library/ArmLib/Arm/ArmLibSupportV7.asm b/ArmPkg/Library/ArmLib/Arm/ArmLibSupportV7.asm
> index 1679b09b797a..81f3cb79994c 100644
> --- a/ArmPkg/Library/ArmLib/Arm/ArmLibSupportV7.asm
> +++ b/ArmPkg/Library/ArmLib/Arm/ArmLibSupportV7.asm
> @@ -68,7 +68,7 @@
>    mrc    p15,0,r0,c0,c2,6     ; Read ID_MMFR4 Register
>    bx     LR
>  
> -// UINT32
> +// UINTN
>  // ReadCCSIDR (
>  //   IN UINT32 CSSELR
>  //   )
> -- 
> 2.26.2
> 

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v4 08/10] ArmPkg: Update ArmLibPrivate.h with cache register definitions
  2020-12-07 17:54 ` [PATCH v4 08/10] ArmPkg: Update ArmLibPrivate.h with cache register definitions Rebecca Cran
@ 2020-12-15 19:27   ` Leif Lindholm
  0 siblings, 0 replies; 40+ messages in thread
From: Leif Lindholm @ 2020-12-15 19:27 UTC (permalink / raw)
  To: Rebecca Cran
  Cc: devel, Michael D Kinney, Liming Gao, Zhiguang Liu, Ard Biesheuvel

On Mon, Dec 07, 2020 at 10:54:25 -0700, Rebecca Cran wrote:
> Update the cache definitions in ArmLibPrivate.h based on current
> ARMv8 documentation.
> 
> Signed-off-by: Rebecca Cran <rebecca@nuviainc.com>

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

> ---
>  ArmPkg/Library/ArmLib/ArmLibPrivate.h | 91 ++++++++++++++++++++
>  1 file changed, 91 insertions(+)
> 
> diff --git a/ArmPkg/Library/ArmLib/ArmLibPrivate.h b/ArmPkg/Library/ArmLib/ArmLibPrivate.h
> index 5eecbc0e1c43..fb1e2cc6b2ac 100644
> --- a/ArmPkg/Library/ArmLib/ArmLibPrivate.h
> +++ b/ArmPkg/Library/ArmLib/ArmLibPrivate.h
> @@ -1,5 +1,7 @@
>  /** @file
> +  ArmLibPrivate.h
>  
> +  Copyright (c) 2020, NUVIA Inc. All rights reserved.<BR>
>    Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
>  
>    SPDX-License-Identifier: BSD-2-Clause-Patent
> @@ -50,6 +52,95 @@
>  #define CACHE_ARCHITECTURE_UNIFIED            (0UL)
>  #define CACHE_ARCHITECTURE_SEPARATE           (1UL)
>  
> +
> +/// Defines the structure of the CSSELR (Cache Size Selection) register
> +typedef union {
> +  struct {
> +    UINT32    InD       :1;  ///< Instruction not Data bit
> +    UINT32    Level     :3;  ///< Cache level (zero based)
> +    UINT32    TnD       :1;  ///< Allocation not Data bit
> +    UINT32    Reserved  :27; ///< Reserved, RES0
> +  } Bits; ///< Bitfield definition of the register
> +  UINT32 Data; ///< The entire 32-bit value
> +} CSSELR_DATA;
> +
> +/// The cache type values for the InD field of the CSSELR register
> +typedef enum
> +{
> +  /// Select the data or unified cache
> +  CsselrCacheTypeDataOrUnified = 0,
> +  /// Select the instruction cache
> +  CsselrCacheTypeInstruction,
> +  CsselrCacheTypeMax
> +} CSSELR_CACHE_TYPE;
> +
> +/// Defines the structure of the CCSIDR (Current Cache Size ID) register
> +typedef union {
> +  struct {
> +    UINT64    LineSize           :3;  ///< Line size (Log2(Num bytes in cache) - 4)
> +    UINT64    Associativity      :10; ///< Associativity - 1
> +    UINT64    NumSets            :15; ///< Number of sets in the cache -1
> +    UINT64    Unknown            :4;  ///< Reserved, UNKNOWN
> +    UINT64    Reserved           :32; ///< Reserved, RES0
> +  } BitsNonCcidx; ///< Bitfield definition of the register when FEAT_CCIDX is not supported.
> +  struct {
> +    UINT64    LineSize           :3;  ///< Line size (Log2(Num bytes in cache) - 4)
> +    UINT64    Associativity      :21; ///< Associativity - 1
> +    UINT64    Reserved1          :8;  ///< Reserved, RES0
> +    UINT64    NumSets            :24; ///< Number of sets in the cache -1
> +    UINT64    Reserved2          :8;  ///< Reserved, RES0
> +  } BitsCcidx; ///< Bitfield definition of the register when FEAT_IDX is supported.
> +  UINT64 Data; ///< The entire 64-bit value
> +} CCSIDR_DATA;
> +
> +/// Defines the structure of the AARCH32 CCSIDR2 register.
> +typedef union {
> +  struct {
> +    UINT32 NumSets               :24; ///< Number of sets in the cache - 1
> +    UINT32 Reserved              :8;  ///< Reserved, RES0
> +  } Bits; ///< Bitfield definition of the register
> +  UINT32 Data; ///< The entire 32-bit value
> +} CSSIDR2_DATA;
> +
> +/** Defines the structure of the CLIDR (Cache Level ID) register.
> + *
> + * The lower 32 bits are the same for both AARCH32 and AARCH64
> + * so we can use the same structure for both.
> +**/
> +typedef union {
> +  struct {
> +    UINT32    Ctype1   : 3; ///< Level 1 cache type
> +    UINT32    Ctype2   : 3; ///< Level 2 cache type
> +    UINT32    Ctype3   : 3; ///< Level 3 cache type
> +    UINT32    Ctype4   : 3; ///< Level 4 cache type
> +    UINT32    Ctype5   : 3; ///< Level 5 cache type
> +    UINT32    Ctype6   : 3; ///< Level 6 cache type
> +    UINT32    Ctype7   : 3; ///< Level 7 cache type
> +    UINT32    LoUIS    : 3; ///< Level of Unification Inner Shareable
> +    UINT32    LoC      : 3; ///< Level of Coherency
> +    UINT32    LoUU     : 3; ///< Level of Unification Uniprocessor
> +    UINT32    Icb      : 3; ///< Inner Cache Boundary
> +  } Bits; ///< Bitfield definition of the register
> +  UINT32 Data; ///< The entire 32-bit value
> +} CLIDR_DATA;
> +
> +/// The cache types reported in the CLIDR register.
> +typedef enum {
> +  /// No cache is present
> +  ClidrCacheTypeNone = 0,
> +  /// There is only an instruction cache
> +  ClidrCacheTypeInstructionOnly,
> +  /// There is only a data cache
> +  ClidrCacheTypeDataOnly,
> +  /// There are separate data and instruction caches
> +  ClidrCacheTypeSeparate,
> +  /// There is a unified cache
> +  ClidrCacheTypeUnified,
> +  ClidrCacheTypeMax
> +} CLIDR_CACHE_TYPE;
> +
> +#define CLIDR_GET_CACHE_TYPE(x, level) ((x >> (3 * level)) & 0b111)
> +
>  VOID
>  CPSRMaskInsert (
>    IN  UINT32  Mask,
> -- 
> 2.26.2
> 

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v4 09/10] ArmPkg: Add definition of the maximum cache level in ARMv8-A
  2020-12-07 17:54 ` [PATCH v4 09/10] ArmPkg: Add definition of the maximum cache level in ARMv8-A Rebecca Cran
@ 2020-12-15 19:27   ` Leif Lindholm
  2020-12-16 11:31   ` [edk2-devel] " Sami Mujawar
  1 sibling, 0 replies; 40+ messages in thread
From: Leif Lindholm @ 2020-12-15 19:27 UTC (permalink / raw)
  To: Rebecca Cran
  Cc: devel, Michael D Kinney, Liming Gao, Zhiguang Liu, Ard Biesheuvel

On Mon, Dec 07, 2020 at 10:54:26 -0700, Rebecca Cran wrote:
> The ARM Architecture Reference Manual for ARMv8-A defines up to
> seven levels of cache, L1 through L7.
> Define MAX_ARM_CACHE_LEVEL to be 7.
> 
> Signed-off-by: Rebecca Cran <rebecca@nuviainc.com>

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

> ---
>  ArmPkg/Include/Library/ArmLib.h | 4 ++++
>  1 file changed, 4 insertions(+)
> 
> diff --git a/ArmPkg/Include/Library/ArmLib.h b/ArmPkg/Include/Library/ArmLib.h
> index 87c3a6f1ecac..4e26991727cb 100644
> --- a/ArmPkg/Include/Library/ArmLib.h
> +++ b/ArmPkg/Include/Library/ArmLib.h
> @@ -108,6 +108,10 @@ typedef enum {
>  #define GET_MPID(ClusterId, CoreId)   (((ClusterId) << 8) | (CoreId))
>  #define PRIMARY_CORE_ID       (PcdGet32(PcdArmPrimaryCore) & ARM_CORE_MASK)
>  
> +// The ARM Architecture Reference Manual for ARMv8-A defines up
> +// to 7 levels of cache, L1 through L7.
> +#define MAX_ARM_CACHE_LEVEL   7
> +
>  UINTN
>  EFIAPI
>  ArmDataCacheLineLength (
> -- 
> 2.26.2
> 

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v4 10/10] ArmPkg: Add Universal/Smbios, a generic SMBIOS library for ARM
  2020-12-07 17:54 ` [PATCH v4 10/10] ArmPkg: Add Universal/Smbios, a generic SMBIOS library for ARM Rebecca Cran
@ 2020-12-15 19:29   ` Leif Lindholm
  2020-12-15 21:14     ` Rebecca Cran
  2020-12-16 15:13   ` [edk2-devel] " Sami Mujawar
       [not found]   ` <16513B32D4BA613C.12945@groups.io>
  2 siblings, 1 reply; 40+ messages in thread
From: Leif Lindholm @ 2020-12-15 19:29 UTC (permalink / raw)
  To: Rebecca Cran
  Cc: devel, Michael D Kinney, Liming Gao, Zhiguang Liu, Ard Biesheuvel

On Mon, Dec 07, 2020 at 10:54:27 -0700, Rebecca Cran wrote:
> 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.

This is still a pretty massive patch to review.
Could you break it up into separate commits for each driver, and the
aforementioned OemMiscLibNull?

/
    Leif

> Signed-off-by: Rebecca Cran <rebecca@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
> +    {                         // 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;
> +  } 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 ();
> +
> +  // 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.
> +**/
> +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);
> +
> +  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;
> +  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[] = {
> +  { "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;
> +
> +  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;
> +
> +  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;
> +
> +  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);
> +
> +  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);
> +
> +  //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
> 

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v4 10/10] ArmPkg: Add Universal/Smbios, a generic SMBIOS library for ARM
  2020-12-15 19:29   ` Leif Lindholm
@ 2020-12-15 21:14     ` Rebecca Cran
  0 siblings, 0 replies; 40+ messages in thread
From: Rebecca Cran @ 2020-12-15 21:14 UTC (permalink / raw)
  To: Leif Lindholm
  Cc: devel, Michael D Kinney, Liming Gao, Zhiguang Liu, Ard Biesheuvel

On 12/15/20 12:29 PM, Leif Lindholm wrote:
> On Mon, Dec 07, 2020 at 10:54:27 -0700, Rebecca Cran wrote:
>> 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.
> 
> This is still a pretty massive patch to review.
> Could you break it up into separate commits for each driver, and the
> aforementioned OemMiscLibNull?

Yes, I'll do that.

-- 
Rebecca Cran

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [edk2-devel] [PATCH v4 04/10] ArmPkg: Add helper to read the Memory Model Features Register 2
  2020-12-15 19:11   ` Leif Lindholm
@ 2020-12-16 11:06     ` Sami Mujawar
  2020-12-17 13:38     ` Laszlo Ersek
  1 sibling, 0 replies; 40+ messages in thread
From: Sami Mujawar @ 2020-12-16 11:06 UTC (permalink / raw)
  To: devel@edk2.groups.io, leif@nuviainc.com, Rebecca Cran
  Cc: Ard Biesheuvel, Laszlo Ersek, nd

Hi Leif,

I had a similar observation while reviewing the code. Please see my response inline below marked [SAMI].

Regards,

Sami Mujawar

-----Original Message-----
From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Leif Lindholm via groups.io
Sent: 15 December 2020 07:11 PM
To: Rebecca Cran <rebecca@nuviainc.com>
Cc: devel@edk2.groups.io; Ard Biesheuvel <Ard.Biesheuvel@arm.com>; Laszlo Ersek <lersek@redhat.com>
Subject: Re: [edk2-devel] [PATCH v4 04/10] ArmPkg: Add helper to read the Memory Model Features Register 2

+Laszlo

Ard, I could use your input on the below, and Laszlo might also have
an opinion:

On Mon, Dec 07, 2020 at 10:54:21 -0700, Rebecca Cran wrote:
> Add helper function to read the MMFR2 register. We will need this to
> determine CCIDX support.
> 
> Signed-off-by: Rebecca Cran <rebecca@nuviainc.com>
> ---
>  ArmPkg/Library/ArmLib/AArch64/AArch64Lib.h     | 6 ++++++
>  ArmPkg/Library/ArmLib/AArch64/AArch64Support.S | 3 +++
>  2 files changed, 9 insertions(+)
> 
> diff --git a/ArmPkg/Library/ArmLib/AArch64/AArch64Lib.h b/ArmPkg/Library/ArmLib/AArch64/AArch64Lib.h
> index b2c8a8ea0b84..d6bcfc3b82ae 100644
> --- a/ArmPkg/Library/ArmLib/AArch64/AArch64Lib.h
> +++ b/ArmPkg/Library/ArmLib/AArch64/AArch64Lib.h
> @@ -35,5 +35,11 @@ ArmCleanInvalidateDataCacheEntryBySetWay (
>    IN  UINTN   SetWayFormat
>    );
>
> +UINTN
> +EFIAPI
> +ArmReadIdMmfr2 (
> +  VOID
> +  );
> +

First of all, I think this prototype belongs in
Include/Library/ArmLib.h ... but!

So, there are a lot of system registers, many of which share at least
the view of the bottom 32 bits between aarch64/aarch32 versions.

This isn't true for the ID registers - which are always 64-bit for
aarch64 state, and always 32-bit for aarch32, where aarch64 have
access to both.

So this helper function isn't generic - in this particular case, we're
adding this accessor because we want to determine CCIDX support.
For aarch64 this means ID_AA64MMFR2_EL1, but for aarch32 this means
ID_MMFR4 (also accessible from aarch64 as ID_MMFR4_EL1).

We already have ArmReadIdPfr0 and ArmReadIdPfr1 in ArmLib.h, already
being made use of, helping to demonstrate the problem:

ArmPkg/Library/ArmGicArchLib/AArch64/ArmGicArchLib.c:  if (ArmReadIdPfr0 () & AARCH64_PFR0_GIC) {
ArmPkg/Library/ArmGicArchLib/Arm/ArmGicArchLib.c:  if (ArmReadIdPfr1 () & ARM_PFR1_GIC) {

I would propose that since the high-level abstraction serve only to
confuse things, we change existing (and new) accessors to ID registers
to be explicit:
[SAMI] I agree, it will be good to rename the functions.
[/SAMI]

- ArmReadIdAArch64Mmfr0
- ArmReadIdAArch64Pfr0
- ArmReadIdAArch64Pfr1
[SAMI] Or we could name them as ArmReadIdAa64Mmfr2() to closely match ID_AA64MMFR2_EL1. However, I am fine with either.
Since we are renaming some functions, we would need a clear function documentation header specifying which register is being read.
[/SAMI]

The question is whether we should make the AArch32 aspect explicit or
implicit? My instinctive reaction is the latter. This matches the
native naming scheme used in the ARM ARM, and we don't support mixing
instruction set widths in UEFI.
[SAMI] I agree, we do not need an AArch32 prefix for registers like ID_MMFR4. These functions can be named as ArmReadIdMmfr4().
[/SAMI]

The AArch64 prototypes should then only be made available to AARCH64
code, and the AArch32 ones only to ARM.
[SAMI] I agree, in AArch64 execution state we do not need functions to read ID_MMFR4_EL1 (as an AArch64 specific register like ID_AA64MMFR2_EL1 would have the equivalent information).
[/SAMI]

Does the above makes sense to everyone?

Best Regards,

Leif

>  #endif // __AARCH64_LIB_H__
>
> diff --git a/ArmPkg/Library/ArmLib/AArch64/AArch64Support.S b/ArmPkg/Library/ArmLib/AArch64/AArch64Support.S
> index 199374ff59e3..874bc2866ac3 100644
> --- a/ArmPkg/Library/ArmLib/AArch64/AArch64Support.S
> +++ b/ArmPkg/Library/ArmLib/AArch64/AArch64Support.S
> @@ -424,6 +424,9 @@ ASM_FUNC(ArmCallWFI)
>    wfi
>    ret
>
> +ASM_FUNC(ArmReadIdMmfr2)
> +  mrs   x0, ID_AA64MMFR2_EL1           // read EL1 MMFR2
> +  ret
>
>  ASM_FUNC(ArmReadMpidr)
>    mrs   x0, mpidr_el1           // read EL1 MPIDR
> -- 
> 2.26.2
> 






^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [edk2-devel] [PATCH v4 05/10] ArmPkg: Add helper function to read the Memory Model Feature Register 4
  2020-12-07 17:54 ` [PATCH v4 05/10] ArmPkg: Add helper function to read the Memory Model Feature Register 4 Rebecca Cran
@ 2020-12-16 11:23   ` Sami Mujawar
  0 siblings, 0 replies; 40+ messages in thread
From: Sami Mujawar @ 2020-12-16 11:23 UTC (permalink / raw)
  To: devel@edk2.groups.io, rebecca@nuviainc.com
  Cc: Michael D Kinney, Liming Gao, Zhiguang Liu, Leif Lindholm,
	Ard Biesheuvel, nd

Hi Rebecca,

Please add doxygen style function documentation for ArmReadIdMmfr4().

With that added:
Reviewed-by: Sami Mujawar <sami.mujawar@arm.com>

Regards,

Sami Mujawar

-----Original Message-----
From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Rebecca Cran via groups.io
Sent: 07 December 2020 05:54 PM
To: devel@edk2.groups.io
Cc: Rebecca Cran <rebecca@nuviainc.com>; Michael D Kinney <michael.d.kinney@intel.com>; Liming Gao <gaoliming@byosoft.com.cn>; Zhiguang Liu <zhiguang.liu@intel.com>; Leif Lindholm <leif@nuviainc.com>; Ard Biesheuvel <Ard.Biesheuvel@arm.com>
Subject: [edk2-devel] [PATCH v4 05/10] ArmPkg: Add helper function to read the Memory Model Feature Register 4

In AARCH32, CCIDX support is indicated in the MMFR4 register - unlike
under AARCH64 where it's in MMFR2. Add a helper function to read it.

Signed-off-by: Rebecca Cran <rebecca@nuviainc.com>
---
 ArmPkg/Library/ArmLib/Arm/ArmV7Lib.h          | 6 ++++++
 ArmPkg/Library/ArmLib/Arm/ArmLibSupportV7.S   | 4 ++++
 ArmPkg/Library/ArmLib/Arm/ArmLibSupportV7.asm | 4 ++++
 3 files changed, 14 insertions(+)

diff --git a/ArmPkg/Library/ArmLib/Arm/ArmV7Lib.h b/ArmPkg/Library/ArmLib/Arm/ArmV7Lib.h
index 93183e67230e..3b331a3b2088 100644
--- a/ArmPkg/Library/ArmLib/Arm/ArmV7Lib.h
+++ b/ArmPkg/Library/ArmLib/Arm/ArmV7Lib.h
@@ -48,5 +48,11 @@ ArmCleanInvalidateDataCacheEntryBySetWay (
   IN  UINTN   SetWayFormat
   );
 
+UINT32
+EFIAPI
+ArmReadIdMmfr4 (
+  VOID
+  );
+
 #endif // __ARM_V7_LIB_H__
 
diff --git a/ArmPkg/Library/ArmLib/Arm/ArmLibSupportV7.S b/ArmPkg/Library/ArmLib/Arm/ArmLibSupportV7.S
index 01c91b10fcb7..a60a2f634132 100644
--- a/ArmPkg/Library/ArmLib/Arm/ArmLibSupportV7.S
+++ b/ArmPkg/Library/ArmLib/Arm/ArmLibSupportV7.S
@@ -60,6 +60,10 @@ ASM_FUNC(ArmDisableInterrupts)
   isb
   bx      LR
 
+ASM_FUNC(ArmReadIdMmfr4)
+  mrc    p15,0,r0,c0,c2,6     @ Read ID_MMFR4 Register
+  bx     lr
+
 // UINT32
 // ReadCCSIDR (
 //   IN UINT32 CSSELR
diff --git a/ArmPkg/Library/ArmLib/Arm/ArmLibSupportV7.asm b/ArmPkg/Library/ArmLib/Arm/ArmLibSupportV7.asm
index 26ffa331b929..1679b09b797a 100644
--- a/ArmPkg/Library/ArmLib/Arm/ArmLibSupportV7.asm
+++ b/ArmPkg/Library/ArmLib/Arm/ArmLibSupportV7.asm
@@ -64,6 +64,10 @@
   isb
   bx      LR
 
+ RVCT_ASM_EXPORT ArmReadIdMmfr4
+  mrc    p15,0,r0,c0,c2,6     ; Read ID_MMFR4 Register
+  bx     LR
+
 // UINT32
 // ReadCCSIDR (
 //   IN UINT32 CSSELR
-- 
2.26.2







^ permalink raw reply related	[flat|nested] 40+ messages in thread

* Re: [edk2-devel] [PATCH v4 06/10] ArmPkg: Add helper to read CCIDX status
  2020-12-07 17:54 ` [PATCH v4 06/10] ArmPkg: Add helper to read CCIDX status Rebecca Cran
@ 2020-12-16 11:23   ` Sami Mujawar
  0 siblings, 0 replies; 40+ messages in thread
From: Sami Mujawar @ 2020-12-16 11:23 UTC (permalink / raw)
  To: devel@edk2.groups.io, rebecca@nuviainc.com
  Cc: Michael D Kinney, Liming Gao, Zhiguang Liu, Leif Lindholm,
	Ard Biesheuvel, nd

Hi Rebecca,

Please add doxygen function header for ArmIsCcidxImplemented().

With that added:
Reviewed-by: Sami Mujawar <sami.mujawar@arm.com>

Regards,

Sami Mujawar

-----Original Message-----
From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Rebecca Cran via groups.io
Sent: 07 December 2020 05:54 PM
To: devel@edk2.groups.io
Cc: Rebecca Cran <rebecca@nuviainc.com>; Michael D Kinney <michael.d.kinney@intel.com>; Liming Gao <gaoliming@byosoft.com.cn>; Zhiguang Liu <zhiguang.liu@intel.com>; Leif Lindholm <leif@nuviainc.com>; Ard Biesheuvel <Ard.Biesheuvel@arm.com>
Subject: [edk2-devel] [PATCH v4 06/10] ArmPkg: Add helper to read CCIDX status

Add a helper function to determine CCIDX support.

Signed-off-by: Rebecca Cran <rebecca@nuviainc.com>
---
 ArmPkg/Include/Library/ArmLib.h            |  6 ++++++
 ArmPkg/Library/ArmLib/AArch64/AArch64Lib.c | 12 ++++++++++++
 ArmPkg/Library/ArmLib/Arm/ArmV7Lib.c       | 12 ++++++++++++
 3 files changed, 30 insertions(+)

diff --git a/ArmPkg/Include/Library/ArmLib.h b/ArmPkg/Include/Library/ArmLib.h
index 5a27b7c2fc27..87c3a6f1ecac 100644
--- a/ArmPkg/Include/Library/ArmLib.h
+++ b/ArmPkg/Include/Library/ArmLib.h
@@ -132,6 +132,12 @@ ArmIsArchTimerImplemented (
   VOID
   );
 
+BOOLEAN
+EFIAPI
+ArmIsCcidxImplemented (
+  VOID
+  );
+
 UINTN
 EFIAPI
 ArmReadIdPfr0 (
diff --git a/ArmPkg/Library/ArmLib/AArch64/AArch64Lib.c b/ArmPkg/Library/ArmLib/AArch64/AArch64Lib.c
index 3fbd591192e2..915c2cacdd99 100644
--- a/ArmPkg/Library/ArmLib/AArch64/AArch64Lib.c
+++ b/ArmPkg/Library/ArmLib/AArch64/AArch64Lib.c
@@ -71,3 +71,15 @@ ArmCleanDataCache (
   ArmDataSynchronizationBarrier ();
   AArch64DataCacheOperation (ArmCleanDataCacheEntryBySetWay);
 }
+
+BOOLEAN
+EFIAPI
+ArmIsCcidxImplemented (
+  VOID
+  )
+{
+  UINTN Mmfr2;
+
+  Mmfr2 = ArmReadIdMmfr2 ();
+  return (((Mmfr2 >> 20) & 0xF) == 1) ? TRUE : FALSE;
+}
diff --git a/ArmPkg/Library/ArmLib/Arm/ArmV7Lib.c b/ArmPkg/Library/ArmLib/Arm/ArmV7Lib.c
index 2c4a23e1a1b2..7331b1c678f3 100644
--- a/ArmPkg/Library/ArmLib/Arm/ArmV7Lib.c
+++ b/ArmPkg/Library/ArmLib/Arm/ArmV7Lib.c
@@ -71,3 +71,15 @@ ArmCleanDataCache (
   ArmDataSynchronizationBarrier ();
   ArmV7DataCacheOperation (ArmCleanDataCacheEntryBySetWay);
 }
+
+BOOLEAN
+EFIAPI
+ArmIsCcidxImplemented (
+  VOID
+  )
+{
+  UINTN Mmfr4;
+
+  Mmfr4 = ArmReadIdMmfr4 ();
+  return (((Mmfr4 >> 24) & 0xF) == 1) ? TRUE : FALSE;
+}
-- 
2.26.2







^ permalink raw reply related	[flat|nested] 40+ messages in thread

* Re: [edk2-devel] [PATCH v4 01/10] ArmPkg: Add ARM SMC Architecture functions to ArmStdSmc.h
  2020-12-07 17:54 ` [PATCH v4 01/10] ArmPkg: Add ARM SMC Architecture functions to ArmStdSmc.h Rebecca Cran
  2020-12-15 18:06   ` Leif Lindholm
@ 2020-12-16 11:23   ` Sami Mujawar
  1 sibling, 0 replies; 40+ messages in thread
From: Sami Mujawar @ 2020-12-16 11:23 UTC (permalink / raw)
  To: devel@edk2.groups.io, rebecca@nuviainc.com
  Cc: Michael D Kinney, Liming Gao, Zhiguang Liu, Leif Lindholm,
	Ard Biesheuvel, nd

Hi Rebecca,

Is it possible to add the specification reference as mentioned in https://edk2.groups.io/g/devel/message/67400, please?
This would be helpful for someone trying to understand the code.

With that changed
Reviewed-by: Sami Mujawar <sami.mujawar@arm.com>

Regards,

Sami Mujawar

-----Original Message-----
From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Rebecca Cran via groups.io
Sent: 07 December 2020 05:54 PM
To: devel@edk2.groups.io
Cc: Rebecca Cran <rebecca@nuviainc.com>; Michael D Kinney <michael.d.kinney@intel.com>; Liming Gao <gaoliming@byosoft.com.cn>; Zhiguang Liu <zhiguang.liu@intel.com>; Leif Lindholm <leif@nuviainc.com>; Ard Biesheuvel <Ard.Biesheuvel@arm.com>
Subject: [edk2-devel] [PATCH v4 01/10] ArmPkg: Add ARM SMC Architecture functions to ArmStdSmc.h

The ARM SMC Architecture functions were missing from ArmStdSmc.h.
Add them, based on the SMC Calling Convention version 1.2 specification.

Signed-off-by: Rebecca Cran <rebecca@nuviainc.com>
---
 ArmPkg/Include/IndustryStandard/ArmStdSmc.h | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/ArmPkg/Include/IndustryStandard/ArmStdSmc.h b/ArmPkg/Include/IndustryStandard/ArmStdSmc.h
index 3509eb680f18..13f2245f37f5 100644
--- a/ArmPkg/Include/IndustryStandard/ArmStdSmc.h
+++ b/ArmPkg/Include/IndustryStandard/ArmStdSmc.h
@@ -1,5 +1,6 @@
 /** @file
 *
+*  Copyright (c) 2020, NUVIA Inc. All rights reserved.<BR>
 *  Copyright (c) 2012-2017, ARM Limited. All rights reserved.
 *
 *  SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -52,6 +53,18 @@
 #define ARM_SMC_MM_RET_DENIED              -3
 #define ARM_SMC_MM_RET_NO_MEMORY           -4
 
+// ARM Architecture Calls
+#define SMCCC_VERSION           0x80000000
+#define SMCCC_ARCH_FEATURES     0x80000001
+#define SMCCC_ARCH_SOC_ID       0x80000002
+#define SMCCC_ARCH_WORKAROUND_1 0x80008000
+#define SMCCC_ARCH_WORKAROUND_2 0x80007FFF
+
+#define SMC_ARCH_CALL_SUCCESS            0
+#define SMC_ARCH_CALL_NOT_SUPPORTED     -1
+#define SMC_ARCH_CALL_NOT_REQUIRED      -2
+#define SMC_ARCH_CALL_INVALID_PARAMETER -3
+
 /*
  * Power State Coordination Interface (PSCI) calls cover a subset of the
  * Standard Service Call range.
-- 
2.26.2







^ permalink raw reply related	[flat|nested] 40+ messages in thread

* Re: [edk2-devel] [PATCH v4 03/10] ArmPkg: Add register encoding definition for MMFR2
  2020-12-07 17:54 ` [PATCH v4 03/10] ArmPkg: Add register encoding definition for MMFR2 Rebecca Cran
  2020-12-15 18:42   ` Leif Lindholm
@ 2020-12-16 11:31   ` Sami Mujawar
  1 sibling, 0 replies; 40+ messages in thread
From: Sami Mujawar @ 2020-12-16 11:31 UTC (permalink / raw)
  To: devel@edk2.groups.io, rebecca@nuviainc.com
  Cc: Michael D Kinney, Liming Gao, Zhiguang Liu, Leif Lindholm,
	Ard Biesheuvel, nd

Hi Rebecca,

This patch looks good to me.

Reviewed-by: Sami Mujawar <sami.mujawar@arm.com>

Regards,

Sami Mujawar

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

Add register encoding definition for Memory Model Feature Register 2.
We need to define it here because we build for ARMv8.0, which doesn't
have it.

Signed-off-by: Rebecca Cran <rebecca@nuviainc.com>
---
 ArmPkg/Include/Chipset/AArch64.h | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/ArmPkg/Include/Chipset/AArch64.h b/ArmPkg/Include/Chipset/AArch64.h
index 0ade5cce91c3..7c2b592f92ee 100644
--- a/ArmPkg/Include/Chipset/AArch64.h
+++ b/ArmPkg/Include/Chipset/AArch64.h
@@ -112,6 +112,10 @@
 #define ARM_VECTOR_LOW_A32_FIQ  0x700
 #define ARM_VECTOR_LOW_A32_SERR 0x780
 
+// The ID_AA64MMFR2_EL1 register was added in ARMv8.2. Since we
+// build for ARMv8.0, we need to define the register here.
+#define ID_AA64MMFR2_EL1 S3_0_C0_C7_2
+
 #define VECTOR_BASE(tbl)          \
   .section .text.##tbl##,"ax";    \
   .align 11;                      \
-- 
2.26.2







^ permalink raw reply related	[flat|nested] 40+ messages in thread

* Re: [edk2-devel] [PATCH v4 07/10] ArmPkg: Fix the return type of the ReadCCSIDR function
  2020-12-07 17:54 ` [PATCH v4 07/10] ArmPkg: Fix the return type of the ReadCCSIDR function Rebecca Cran
  2020-12-15 19:24   ` Leif Lindholm
@ 2020-12-16 11:31   ` Sami Mujawar
  1 sibling, 0 replies; 40+ messages in thread
From: Sami Mujawar @ 2020-12-16 11:31 UTC (permalink / raw)
  To: devel@edk2.groups.io, rebecca@nuviainc.com
  Cc: Michael D Kinney, Liming Gao, Zhiguang Liu, Leif Lindholm,
	Ard Biesheuvel, nd

Hi Rebecca,

Please add doxygen style documentation for the function ReadCCSIDR().

With that added:
Reviewed-by: Sami Mujawar <sami.mujawar@arm.com>

Regards,

Sami Mujawar

-----Original Message-----
From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Rebecca Cran via groups.io
Sent: 07 December 2020 05:54 PM
To: devel@edk2.groups.io
Cc: Rebecca Cran <rebecca@nuviainc.com>; Michael D Kinney <michael.d.kinney@intel.com>; Liming Gao <gaoliming@byosoft.com.cn>; Zhiguang Liu <zhiguang.liu@intel.com>; Leif Lindholm <leif@nuviainc.com>; Ard Biesheuvel <Ard.Biesheuvel@arm.com>
Subject: [edk2-devel] [PATCH v4 07/10] ArmPkg: Fix the return type of the ReadCCSIDR function

When CCIDX is supported, the Current Cache Size ID Register contains
data above 32 bits: namely the number of sets. Avoid truncating this
by returning a UINTN instead of UINT32. On AARCH32, the expanded
number of sets data can be read via the CCSIDR2 register.

Signed-off-by: Rebecca Cran <rebecca@nuviainc.com>
---
 ArmPkg/Library/ArmLib/ArmLibPrivate.h           | 2 +-
 ArmPkg/Library/ArmLib/AArch64/ArmLibSupportV8.S | 2 +-
 ArmPkg/Library/ArmLib/Arm/ArmLibSupportV7.asm   | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/ArmPkg/Library/ArmLib/ArmLibPrivate.h b/ArmPkg/Library/ArmLib/ArmLibPrivate.h
index 2e90739eb858..5eecbc0e1c43 100644
--- a/ArmPkg/Library/ArmLib/ArmLibPrivate.h
+++ b/ArmPkg/Library/ArmLib/ArmLibPrivate.h
@@ -61,7 +61,7 @@ CPSRRead (
   VOID
   );
 
-UINT32
+UINTN
 ReadCCSIDR (
   IN UINT32 CSSELR
   );
diff --git a/ArmPkg/Library/ArmLib/AArch64/ArmLibSupportV8.S b/ArmPkg/Library/ArmLib/AArch64/ArmLibSupportV8.S
index 0e8d21e2264f..0ae75e4cb9f9 100644
--- a/ArmPkg/Library/ArmLib/AArch64/ArmLibSupportV8.S
+++ b/ArmPkg/Library/ArmLib/AArch64/ArmLibSupportV8.S
@@ -84,7 +84,7 @@ ASM_FUNC(ArmDisableAllExceptions)
   ret
 
 
-// UINT32
+// UINTN
 // ReadCCSIDR (
 //   IN UINT32 CSSELR
 //   )
diff --git a/ArmPkg/Library/ArmLib/Arm/ArmLibSupportV7.asm b/ArmPkg/Library/ArmLib/Arm/ArmLibSupportV7.asm
index 1679b09b797a..81f3cb79994c 100644
--- a/ArmPkg/Library/ArmLib/Arm/ArmLibSupportV7.asm
+++ b/ArmPkg/Library/ArmLib/Arm/ArmLibSupportV7.asm
@@ -68,7 +68,7 @@
   mrc    p15,0,r0,c0,c2,6     ; Read ID_MMFR4 Register
   bx     LR
 
-// UINT32
+// UINTN
 // ReadCCSIDR (
 //   IN UINT32 CSSELR
 //   )
-- 
2.26.2







^ permalink raw reply related	[flat|nested] 40+ messages in thread

* Re: [edk2-devel] [PATCH v4 09/10] ArmPkg: Add definition of the maximum cache level in ARMv8-A
  2020-12-07 17:54 ` [PATCH v4 09/10] ArmPkg: Add definition of the maximum cache level in ARMv8-A Rebecca Cran
  2020-12-15 19:27   ` Leif Lindholm
@ 2020-12-16 11:31   ` Sami Mujawar
  1 sibling, 0 replies; 40+ messages in thread
From: Sami Mujawar @ 2020-12-16 11:31 UTC (permalink / raw)
  To: devel@edk2.groups.io, rebecca@nuviainc.com
  Cc: Michael D Kinney, Liming Gao, Zhiguang Liu, Leif Lindholm,
	Ard Biesheuvel, nd

Hi Rebecca,

This patch looks good to me.

Reviewed-by: Sami Mujawar <sami.mujawar@arm.com>

Regards,

Sami Mujawar

-----Original Message-----
From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Rebecca Cran via groups.io
Sent: 07 December 2020 05:54 PM
To: devel@edk2.groups.io
Cc: Rebecca Cran <rebecca@nuviainc.com>; Michael D Kinney <michael.d.kinney@intel.com>; Liming Gao <gaoliming@byosoft.com.cn>; Zhiguang Liu <zhiguang.liu@intel.com>; Leif Lindholm <leif@nuviainc.com>; Ard Biesheuvel <Ard.Biesheuvel@arm.com>
Subject: [edk2-devel] [PATCH v4 09/10] ArmPkg: Add definition of the maximum cache level in ARMv8-A

The ARM Architecture Reference Manual for ARMv8-A defines up to
seven levels of cache, L1 through L7.
Define MAX_ARM_CACHE_LEVEL to be 7.

Signed-off-by: Rebecca Cran <rebecca@nuviainc.com>
---
 ArmPkg/Include/Library/ArmLib.h | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/ArmPkg/Include/Library/ArmLib.h b/ArmPkg/Include/Library/ArmLib.h
index 87c3a6f1ecac..4e26991727cb 100644
--- a/ArmPkg/Include/Library/ArmLib.h
+++ b/ArmPkg/Include/Library/ArmLib.h
@@ -108,6 +108,10 @@ typedef enum {
 #define GET_MPID(ClusterId, CoreId)   (((ClusterId) << 8) | (CoreId))
 #define PRIMARY_CORE_ID       (PcdGet32(PcdArmPrimaryCore) & ARM_CORE_MASK)
 
+// The ARM Architecture Reference Manual for ARMv8-A defines up
+// to 7 levels of cache, L1 through L7.
+#define MAX_ARM_CACHE_LEVEL   7
+
 UINTN
 EFIAPI
 ArmDataCacheLineLength (
-- 
2.26.2







^ permalink raw reply related	[flat|nested] 40+ messages in thread

* Re: [edk2-devel] [PATCH v4 10/10] ArmPkg: Add Universal/Smbios, a generic SMBIOS library for ARM
  2020-12-07 17:54 ` [PATCH v4 10/10] ArmPkg: Add Universal/Smbios, a generic SMBIOS library for ARM Rebecca Cran
  2020-12-15 19:29   ` Leif Lindholm
@ 2020-12-16 15:13   ` Sami Mujawar
  2020-12-16 15:21     ` Rebecca Cran
  2020-12-19  3:14     ` Rebecca Cran
       [not found]   ` <16513B32D4BA613C.12945@groups.io>
  2 siblings, 2 replies; 40+ messages in thread
From: Sami Mujawar @ 2020-12-16 15:13 UTC (permalink / raw)
  To: devel@edk2.groups.io, rebecca@nuviainc.com
  Cc: Michael D Kinney, Liming Gao, Zhiguang Liu, Leif Lindholm,
	Ard Biesheuvel, nd

Hi Rebecca,

Sorry for pushing for the function documentation. We are in process of enabling EKDII Core CI support for ArmPlatformPkg and ArmPkg. 
The ECC tool (checks for coding style and general good programming practices) is run as part of the Core CI. There are numerous issues reported by ECC tool and we are working towards fixing them before the Core CI is enabled.

Can you run the ECC tool for this patch and fix the reported issues, please?
The following command can be used to run ECC on the ArmPkg\Universal\Smbios  folder.
> python BaseTools\Source\Python\Ecc\EccMain.py  -c W:\edk2-review\edk2\BaseTools\Source\Python\Ecc\config.ini -e W:\edk2-review\edk2\BaseTools\Source\Python\Ecc\exception.xml -r W:\edk2-exports\edk2\Ecc.csv -t W:\edk2-review\edk2\ArmPkg\Universal\Smbios

The ECC errors 10002, 10006 and 10022 can be ignored for now (I don't know if these errors are real problems or false positives).

Regards,

Sami Mujawar

-----Original Message-----
From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Rebecca Cran via groups.io
Sent: 07 December 2020 05:54 PM
To: devel@edk2.groups.io
Cc: Rebecca Cran <rebecca@nuviainc.com>; Michael D Kinney <michael.d.kinney@intel.com>; Liming Gao <gaoliming@byosoft.com.cn>; Zhiguang Liu <zhiguang.liu@intel.com>; Leif Lindholm <leif@nuviainc.com>; Ard Biesheuvel <Ard.Biesheuvel@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@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
+    {                         // 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;
+  } 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 ();
+
+  // 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.
+**/
+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);
+
+  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;
+  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[] = {
+  { "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;
+
+  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;
+
+  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;
+
+  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);
+
+  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);
+
+  //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







^ permalink raw reply related	[flat|nested] 40+ messages in thread

* Re: [edk2-devel] [PATCH v4 10/10] ArmPkg: Add Universal/Smbios, a generic SMBIOS library for ARM
  2020-12-16 15:13   ` [edk2-devel] " Sami Mujawar
@ 2020-12-16 15:21     ` Rebecca Cran
  2020-12-19  3:14     ` Rebecca Cran
  1 sibling, 0 replies; 40+ messages in thread
From: Rebecca Cran @ 2020-12-16 15:21 UTC (permalink / raw)
  To: Sami Mujawar, devel@edk2.groups.io
  Cc: Michael D Kinney, Liming Gao, Zhiguang Liu, Leif Lindholm,
	Ard Biesheuvel, nd

On 12/16/20 8:13 AM, Sami Mujawar wrote:

> Sorry for pushing for the function documentation. We are in process of enabling EKDII Core CI support for ArmPlatformPkg and ArmPkg.
> The ECC tool (checks for coding style and general good programming practices) is run as part of the Core CI. There are numerous issues reported by ECC tool and we are working towards fixing them before the Core CI is enabled.
> 
> Can you run the ECC tool for this patch and fix the reported issues, please?
> The following command can be used to run ECC on the ArmPkg\Universal\Smbios  folder.
>> python BaseTools\Source\Python\Ecc\EccMain.py  -c W:\edk2-review\edk2\BaseTools\Source\Python\Ecc\config.ini -e W:\edk2-review\edk2\BaseTools\Source\Python\Ecc\exception.xml -r W:\edk2-exports\edk2\Ecc.csv -t W:\edk2-review\edk2\ArmPkg\Universal\Smbios
> 
> The ECC errors 10002, 10006 and 10022 can be ignored for now (I don't know if these errors are real problems or false positives).

Given that I maintain the site with the Doxygen pages at 
https://bsdio.com/edk2/docs/master/ I'm all for adding function 
documentation!

I'll run the ECC tool and fix the errors.

-- 
Rebecca Cran

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v4 04/10] ArmPkg: Add helper to read the Memory Model Features Register 2
  2020-12-15 19:11   ` Leif Lindholm
  2020-12-16 11:06     ` [edk2-devel] " Sami Mujawar
@ 2020-12-17 13:38     ` Laszlo Ersek
  2020-12-17 13:47       ` Ard Biesheuvel
  2020-12-17 17:57       ` Leif Lindholm
  1 sibling, 2 replies; 40+ messages in thread
From: Laszlo Ersek @ 2020-12-17 13:38 UTC (permalink / raw)
  To: Leif Lindholm, Rebecca Cran; +Cc: devel, Ard Biesheuvel

On 12/15/20 20:11, Leif Lindholm wrote:
> +Laszlo
> 
> Ard, I could use your input on the below, and Laszlo might also have
> an opinion:
> 
> On Mon, Dec 07, 2020 at 10:54:21 -0700, Rebecca Cran wrote:
>> Add helper function to read the MMFR2 register. We will need this to
>> determine CCIDX support.
>>
>> Signed-off-by: Rebecca Cran <rebecca@nuviainc.com>
>> ---
>>  ArmPkg/Library/ArmLib/AArch64/AArch64Lib.h     | 6 ++++++
>>  ArmPkg/Library/ArmLib/AArch64/AArch64Support.S | 3 +++
>>  2 files changed, 9 insertions(+)
>>
>> diff --git a/ArmPkg/Library/ArmLib/AArch64/AArch64Lib.h b/ArmPkg/Library/ArmLib/AArch64/AArch64Lib.h
>> index b2c8a8ea0b84..d6bcfc3b82ae 100644
>> --- a/ArmPkg/Library/ArmLib/AArch64/AArch64Lib.h
>> +++ b/ArmPkg/Library/ArmLib/AArch64/AArch64Lib.h
>> @@ -35,5 +35,11 @@ ArmCleanInvalidateDataCacheEntryBySetWay (
>>    IN  UINTN   SetWayFormat
>>    );
>>  
>> +UINTN
>> +EFIAPI
>> +ArmReadIdMmfr2 (
>> +  VOID
>> +  );
>> +
> 
> First of all, I think this prototype belongs in
> Include/Library/ArmLib.h ... but!
> 
> So, there are a lot of system registers, many of which share at least
> the view of the bottom 32 bits between aarch64/aarch32 versions.
> 
> This isn't true for the ID registers - which are always 64-bit for
> aarch64 state, and always 32-bit for aarch32, where aarch64 have
> access to both.
> 
> So this helper function isn't generic - in this particular case, we're
> adding this accessor because we want to determine CCIDX support.
> For aarch64 this means ID_AA64MMFR2_EL1, but for aarch32 this means
> ID_MMFR4 (also accessible from aarch64 as ID_MMFR4_EL1).
> 
> We already have ArmReadIdPfr0 and ArmReadIdPfr1 in ArmLib.h, already
> being made use of, helping to demonstrate the problem:
> 
> ArmPkg/Library/ArmGicArchLib/AArch64/ArmGicArchLib.c:  if (ArmReadIdPfr0 () & AARCH64_PFR0_GIC) {
> ArmPkg/Library/ArmGicArchLib/Arm/ArmGicArchLib.c:  if (ArmReadIdPfr1 () & ARM_PFR1_GIC) {
> 
> I would propose that since the high-level abstraction serve only to
> confuse things, we change existing (and new) accessors to ID registers
> to be explicit:
> 
> - ArmReadIdAArch64Mmfr0
> - ArmReadIdAArch64Pfr0
> - ArmReadIdAArch64Pfr1

I can follow until here... (and yes, using the concrete register names
in the function names makes sense)

> 
> The question is whether we should make the AArch32 aspect explicit or
> implicit? My instinctive reaction is the latter. This matches the
> native naming scheme used in the ARM ARM, and we don't support mixing
> instruction set widths in UEFI.

I lost you here, sorry.

> 
> The AArch64 prototypes should then only be made available to AARCH64
> code, and the AArch32 ones only to ARM.

But this again makes sense to me.

I guess what confuses me is your interpretation of "implicit" vs.
"explicit". I'm missing what the "AArch32 aspect" means, probably.

Thanks
laszlo


^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v4 04/10] ArmPkg: Add helper to read the Memory Model Features Register 2
  2020-12-17 13:38     ` Laszlo Ersek
@ 2020-12-17 13:47       ` Ard Biesheuvel
  2020-12-17 18:04         ` Leif Lindholm
  2020-12-17 17:57       ` Leif Lindholm
  1 sibling, 1 reply; 40+ messages in thread
From: Ard Biesheuvel @ 2020-12-17 13:47 UTC (permalink / raw)
  To: Laszlo Ersek, Leif Lindholm, Rebecca Cran; +Cc: devel

On 12/17/20 2:38 PM, Laszlo Ersek wrote:
> On 12/15/20 20:11, Leif Lindholm wrote:
>> +Laszlo
>>
>> Ard, I could use your input on the below, and Laszlo might also have
>> an opinion:
>>
>> On Mon, Dec 07, 2020 at 10:54:21 -0700, Rebecca Cran wrote:
>>> Add helper function to read the MMFR2 register. We will need this to
>>> determine CCIDX support.
>>>
>>> Signed-off-by: Rebecca Cran <rebecca@nuviainc.com>
>>> ---
>>>  ArmPkg/Library/ArmLib/AArch64/AArch64Lib.h     | 6 ++++++
>>>  ArmPkg/Library/ArmLib/AArch64/AArch64Support.S | 3 +++
>>>  2 files changed, 9 insertions(+)
>>>
>>> diff --git a/ArmPkg/Library/ArmLib/AArch64/AArch64Lib.h b/ArmPkg/Library/ArmLib/AArch64/AArch64Lib.h
>>> index b2c8a8ea0b84..d6bcfc3b82ae 100644
>>> --- a/ArmPkg/Library/ArmLib/AArch64/AArch64Lib.h
>>> +++ b/ArmPkg/Library/ArmLib/AArch64/AArch64Lib.h
>>> @@ -35,5 +35,11 @@ ArmCleanInvalidateDataCacheEntryBySetWay (
>>>    IN  UINTN   SetWayFormat
>>>    );
>>>  
>>> +UINTN
>>> +EFIAPI
>>> +ArmReadIdMmfr2 (
>>> +  VOID
>>> +  );
>>> +
>>
>> First of all, I think this prototype belongs in
>> Include/Library/ArmLib.h ... but!
>>
>> So, there are a lot of system registers, many of which share at least
>> the view of the bottom 32 bits between aarch64/aarch32 versions.
>>
>> This isn't true for the ID registers - which are always 64-bit for
>> aarch64 state, and always 32-bit for aarch32, where aarch64 have
>> access to both.
>>
>> So this helper function isn't generic - in this particular case, we're
>> adding this accessor because we want to determine CCIDX support.
>> For aarch64 this means ID_AA64MMFR2_EL1, but for aarch32 this means
>> ID_MMFR4 (also accessible from aarch64 as ID_MMFR4_EL1).
>>
>> We already have ArmReadIdPfr0 and ArmReadIdPfr1 in ArmLib.h, already
>> being made use of, helping to demonstrate the problem:
>>
>> ArmPkg/Library/ArmGicArchLib/AArch64/ArmGicArchLib.c:  if (ArmReadIdPfr0 () & AARCH64_PFR0_GIC) {
>> ArmPkg/Library/ArmGicArchLib/Arm/ArmGicArchLib.c:  if (ArmReadIdPfr1 () & ARM_PFR1_GIC) {
>>
>> I would propose that since the high-level abstraction serve only to
>> confuse things, we change existing (and new) accessors to ID registers
>> to be explicit:
>>
>> - ArmReadIdAArch64Mmfr0
>> - ArmReadIdAArch64Pfr0
>> - ArmReadIdAArch64Pfr1
> 
> I can follow until here... (and yes, using the concrete register names
> in the function names makes sense)
> 
>>
>> The question is whether we should make the AArch32 aspect explicit or
>> implicit? My instinctive reaction is the latter. This matches the
>> native naming scheme used in the ARM ARM, and we don't support mixing
>> instruction set widths in UEFI.
> 
> I lost you here, sorry.
> 

So did I :-)

But I think that we should raise the level of abstraction here:
something like

if (ArmReadIdPfr0 () & AARCH64_PFR0_GIC) {

should not exist in code that is shared between AArch64 and AArch32, I'd
much rather have a helper

ArmHasGicSre()

that encapsulates whatever is needed on each respective architecture,
and which may or may not end up using the same ID register or mask value.


>>
>> The AArch64 prototypes should then only be made available to AARCH64
>> code, and the AArch32 ones only to ARM.
> 
> But this again makes sense to me.
> 
> I guess what confuses me is your interpretation of "implicit" vs.
> "explicit". I'm missing what the "AArch32 aspect" means, probably.
> 
> Thanks
> laszlo
> 


^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v4 04/10] ArmPkg: Add helper to read the Memory Model Features Register 2
  2020-12-17 13:38     ` Laszlo Ersek
  2020-12-17 13:47       ` Ard Biesheuvel
@ 2020-12-17 17:57       ` Leif Lindholm
  1 sibling, 0 replies; 40+ messages in thread
From: Leif Lindholm @ 2020-12-17 17:57 UTC (permalink / raw)
  To: Laszlo Ersek; +Cc: Rebecca Cran, devel, Ard Biesheuvel

On Thu, Dec 17, 2020 at 14:38:55 +0100, Laszlo Ersek wrote:
> On 12/15/20 20:11, Leif Lindholm wrote:
> > +Laszlo
> > 
> > Ard, I could use your input on the below, and Laszlo might also have
> > an opinion:
> > 
> > On Mon, Dec 07, 2020 at 10:54:21 -0700, Rebecca Cran wrote:
> >> Add helper function to read the MMFR2 register. We will need this to
> >> determine CCIDX support.
> >>
> >> Signed-off-by: Rebecca Cran <rebecca@nuviainc.com>
> >> ---
> >>  ArmPkg/Library/ArmLib/AArch64/AArch64Lib.h     | 6 ++++++
> >>  ArmPkg/Library/ArmLib/AArch64/AArch64Support.S | 3 +++
> >>  2 files changed, 9 insertions(+)
> >>
> >> diff --git a/ArmPkg/Library/ArmLib/AArch64/AArch64Lib.h b/ArmPkg/Library/ArmLib/AArch64/AArch64Lib.h
> >> index b2c8a8ea0b84..d6bcfc3b82ae 100644
> >> --- a/ArmPkg/Library/ArmLib/AArch64/AArch64Lib.h
> >> +++ b/ArmPkg/Library/ArmLib/AArch64/AArch64Lib.h
> >> @@ -35,5 +35,11 @@ ArmCleanInvalidateDataCacheEntryBySetWay (
> >>    IN  UINTN   SetWayFormat
> >>    );
> >>  
> >> +UINTN
> >> +EFIAPI
> >> +ArmReadIdMmfr2 (
> >> +  VOID
> >> +  );
> >> +
> > 
> > First of all, I think this prototype belongs in
> > Include/Library/ArmLib.h ... but!
> > 
> > So, there are a lot of system registers, many of which share at least
> > the view of the bottom 32 bits between aarch64/aarch32 versions.
> > 
> > This isn't true for the ID registers - which are always 64-bit for
> > aarch64 state, and always 32-bit for aarch32, where aarch64 have
> > access to both.
> > 
> > So this helper function isn't generic - in this particular case, we're
> > adding this accessor because we want to determine CCIDX support.
> > For aarch64 this means ID_AA64MMFR2_EL1, but for aarch32 this means
> > ID_MMFR4 (also accessible from aarch64 as ID_MMFR4_EL1).
> > 
> > We already have ArmReadIdPfr0 and ArmReadIdPfr1 in ArmLib.h, already
> > being made use of, helping to demonstrate the problem:
> > 
> > ArmPkg/Library/ArmGicArchLib/AArch64/ArmGicArchLib.c:  if (ArmReadIdPfr0 () & AARCH64_PFR0_GIC) {
> > ArmPkg/Library/ArmGicArchLib/Arm/ArmGicArchLib.c:  if (ArmReadIdPfr1 () & ARM_PFR1_GIC) {
> > 
> > I would propose that since the high-level abstraction serve only to
> > confuse things, we change existing (and new) accessors to ID registers
> > to be explicit:
> > 
> > - ArmReadIdAArch64Mmfr0
> > - ArmReadIdAArch64Pfr0
> > - ArmReadIdAArch64Pfr1
> 
> I can follow until here... (and yes, using the concrete register names
> in the function names makes sense)
> 
> > 
> > The question is whether we should make the AArch32 aspect explicit or
> > implicit? My instinctive reaction is the latter. This matches the
> > native naming scheme used in the ARM ARM, and we don't support mixing
> > instruction set widths in UEFI.
> 
> I lost you here, sorry.

I simply meant we probably don't want to call the AArch32 accesssors
ArmReadIdAArch32Pfr0, since ID_PFR0 is the architectural name for the
AArch32 register when executing in AArch32 state.

As Sami pointed out, we could similarily just stick with the
CamelCased architectural names for AArch64 accessors rather than
spelling out AArch64.

/
    Leif

> > The AArch64 prototypes should then only be made available to AARCH64
> > code, and the AArch32 ones only to ARM.
> 
> But this again makes sense to me.
> 
> I guess what confuses me is your interpretation of "implicit" vs.
> "explicit". I'm missing what the "AArch32 aspect" means, probably.
> 
> Thanks
> laszlo
> 

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v4 04/10] ArmPkg: Add helper to read the Memory Model Features Register 2
  2020-12-17 13:47       ` Ard Biesheuvel
@ 2020-12-17 18:04         ` Leif Lindholm
  2020-12-17 18:19           ` Rebecca Cran
  0 siblings, 1 reply; 40+ messages in thread
From: Leif Lindholm @ 2020-12-17 18:04 UTC (permalink / raw)
  To: Ard Biesheuvel; +Cc: Laszlo Ersek, Rebecca Cran, devel

On Thu, Dec 17, 2020 at 14:47:48 +0100, Ard Biesheuvel wrote:
> >> ArmPkg/Library/ArmGicArchLib/AArch64/ArmGicArchLib.c:  if (ArmReadIdPfr0 () & AARCH64_PFR0_GIC) {
> >> ArmPkg/Library/ArmGicArchLib/Arm/ArmGicArchLib.c:  if (ArmReadIdPfr1 () & ARM_PFR1_GIC) {
> >>
> >> I would propose that since the high-level abstraction serve only to
> >> confuse things, we change existing (and new) accessors to ID registers
> >> to be explicit:
> >>
> >> - ArmReadIdAArch64Mmfr0
> >> - ArmReadIdAArch64Pfr0
> >> - ArmReadIdAArch64Pfr1
> > 
> > I can follow until here... (and yes, using the concrete register names
> > in the function names makes sense)
> > 
> >>
> >> The question is whether we should make the AArch32 aspect explicit or
> >> implicit? My instinctive reaction is the latter. This matches the
> >> native naming scheme used in the ARM ARM, and we don't support mixing
> >> instruction set widths in UEFI.
> > 
> > I lost you here, sorry.
> > 
> 
> So did I :-)
> 
> But I think that we should raise the level of abstraction here:
> something like
> 
> if (ArmReadIdPfr0 () & AARCH64_PFR0_GIC) {
> 
> should not exist in code that is shared between AArch64 and AArch32, I'd
> much rather have a helper
> 
> ArmHasGicSre()
> 
> that encapsulates whatever is needed on each respective architecture,
> and which may or may not end up using the same ID register or mask value.

Yeah, agreed. In the end, that's what Rebecca's set does in patch 6/10
- so I'll whip something together to replicate this for the GIC case.

I like the ArmHas* format though - Rebecca, could you use that for
your v5?

> 
> >>
> >> The AArch64 prototypes should then only be made available to AARCH64
> >> code, and the AArch32 ones only to ARM.
> > 
> > But this again makes sense to me.
> > 
> > I guess what confuses me is your interpretation of "implicit" vs.
> > "explicit". I'm missing what the "AArch32 aspect" means, probably.
> > 
> > Thanks
> > laszlo
> > 
> 

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v4 04/10] ArmPkg: Add helper to read the Memory Model Features Register 2
  2020-12-17 18:04         ` Leif Lindholm
@ 2020-12-17 18:19           ` Rebecca Cran
  0 siblings, 0 replies; 40+ messages in thread
From: Rebecca Cran @ 2020-12-17 18:19 UTC (permalink / raw)
  To: Leif Lindholm, Ard Biesheuvel; +Cc: Laszlo Ersek, devel

On 12/17/20 11:04 AM, Leif Lindholm wrote:

> I like the ArmHas* format though - Rebecca, could you use that for
> your v5?

Yes, I'll do that.

-- 
Rebecca Cran

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [edk2-devel] [PATCH v4 10/10] ArmPkg: Add Universal/Smbios, a generic SMBIOS library for ARM
  2020-12-16 15:13   ` [edk2-devel] " Sami Mujawar
  2020-12-16 15:21     ` Rebecca Cran
@ 2020-12-19  3:14     ` Rebecca Cran
  1 sibling, 0 replies; 40+ messages in thread
From: Rebecca Cran @ 2020-12-19  3:14 UTC (permalink / raw)
  To: Sami Mujawar, devel@edk2.groups.io
  Cc: Michael D Kinney, Liming Gao, Zhiguang Liu, Leif Lindholm,
	Ard Biesheuvel, nd

On 12/16/20 8:13 AM, Sami Mujawar wrote:

> The ECC errors 10002, 10006 and 10022 can be ignored for now (I don't know if these errors are real problems or false positives).

ECC error 4002 also appears to be a false positive, for comment lines 
with a leading asterisk. for example I'm getting:

1	4002	Function header doesn't exist 
ArmPkg/Universal/Smbios/SmbiosMiscDxe/SmbiosMiscEntryPoint.c	116	in 
Comment, <@param[in] SmbiosType The type of table to fetch *> does NOT 
end with new line

It looks like it's reading past the new line, up to the following asterisk.

I've created https://bugzilla.tianocore.org/show_bug.cgi?id=3131 .

-- 
Rebecca Cran

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [edk2-devel] [PATCH v4 10/10] ArmPkg: Add Universal/Smbios, a generic SMBIOS library for ARM
       [not found]   ` <16513B32D4BA613C.12945@groups.io>
@ 2020-12-29 15:10     ` Sami Mujawar
  2021-01-03 23:52       ` Rebecca Cran
  0 siblings, 1 reply; 40+ messages in thread
From: Sami Mujawar @ 2020-12-29 15:10 UTC (permalink / raw)
  To: devel@edk2.groups.io, Sami Mujawar, rebecca@nuviainc.com
  Cc: Michael D Kinney, Liming Gao, Zhiguang Liu, Leif Lindholm,
	Ard Biesheuvel, nd

Hi Rebecca,

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

Regards,

Sami Mujawar

-----Original Message-----
From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Rebecca Cran via groups.io
Sent: 07 December 2020 05:54 PM
To: devel@edk2.groups.io
Cc: Rebecca Cran <rebecca@nuviainc.com>; Michael D Kinney <michael.d.kinney@intel.com>; Liming Gao <gaoliming@byosoft.com.cn>; Zhiguang Liu <zhiguang.liu@intel.com>; Leif Lindholm <leif@nuviainc.com>; Ard Biesheuvel <Ard.Biesheuvel@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@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












^ permalink raw reply related	[flat|nested] 40+ messages in thread

* Re: [edk2-devel] [PATCH v4 10/10] ArmPkg: Add Universal/Smbios, a generic SMBIOS library for ARM
  2020-12-29 15:10     ` Sami Mujawar
@ 2021-01-03 23:52       ` Rebecca Cran
  2021-01-04 10:21         ` Sami Mujawar
  0 siblings, 1 reply; 40+ messages in thread
From: Rebecca Cran @ 2021-01-03 23:52 UTC (permalink / raw)
  To: Sami Mujawar, devel@edk2.groups.io
  Cc: Michael D Kinney, Liming Gao, Zhiguang Liu, Leif Lindholm,
	Ard Biesheuvel, nd

On 12/29/20 8:10 AM, Sami Mujawar wrote:

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

Thanks. I have a few comments: I've replied inline. Where I haven't 
replied, I've made the changes you suggested.


> +    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]

The string IDs are specific to the table, so I'm not sure we should 
define a constant to re-use?


> +  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]


Yes, that code currently assumes all CPUs are the same.
I'll add code to allow platforms to specify different cache information 
tables for CPUs that are different.


> +  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]

The code fetches the first of the _chassis_ handles, which it's presumed 
there will only be one.


> +  //ContainedElements
> +  (VOID)CopyMem (SmbiosRecord + 1, &ContainedElements, ExtendLength);
> [SAMI] If I understand correctly, the Contained Element data is never really copied, right?
> [/SAMI]


I'm not sure why it wouldn't be copied. Could you elaborate?

-- 
Rebecca Cran

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [edk2-devel] [PATCH v4 10/10] ArmPkg: Add Universal/Smbios, a generic SMBIOS library for ARM
  2021-01-03 23:52       ` Rebecca Cran
@ 2021-01-04 10:21         ` Sami Mujawar
  0 siblings, 0 replies; 40+ messages in thread
From: Sami Mujawar @ 2021-01-04 10:21 UTC (permalink / raw)
  To: Rebecca Cran, devel@edk2.groups.io
  Cc: Michael D Kinney, Liming Gao, Zhiguang Liu, Leif Lindholm,
	Ard Biesheuvel, nd

Hi Rebecca,

Please see my reply inline marked [SAMI].

Regards,

Sami Mujawar

-----Original Message-----
From: Rebecca Cran <rebecca@nuviainc.com> 
Sent: 03 January 2021 11:52 PM
To: Sami Mujawar <Sami.Mujawar@arm.com>; devel@edk2.groups.io
Cc: Michael D Kinney <michael.d.kinney@intel.com>; Liming Gao <gaoliming@byosoft.com.cn>; Zhiguang Liu <zhiguang.liu@intel.com>; Leif Lindholm <leif@nuviainc.com>; Ard Biesheuvel <Ard.Biesheuvel@arm.com>; nd <nd@arm.com>
Subject: Re: [edk2-devel] [PATCH v4 10/10] ArmPkg: Add Universal/Smbios, a generic SMBIOS library for ARM

On 12/29/20 8:10 AM, Sami Mujawar wrote:

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

Thanks. I have a few comments: I've replied inline. Where I haven't 
replied, I've made the changes you suggested.


> +    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]

The string IDs are specific to the table, so I'm not sure we should 
define a constant to re-use?
[SAMI] I see your point. It does not make sense to define macros to get rid of magic numbers, especially when these macros would not be used elsewhere.
[/SAMI]


> +  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]


Yes, that code currently assumes all CPUs are the same.
I'll add code to allow platforms to specify different cache information 
tables for CPUs that are different.


> +  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]

The code fetches the first of the _chassis_ handles, which it's presumed 
there will only be one.
[SAMI] A comment to reflect this may be helpful if this is specific to this implementation. I was confused as the code sets the 'Board Type' to motherboard and the spec says "List of handles of other structures (for example, Baseboard,
Processor, Port, System Slots, Memory Device) that are contained by this baseboard". So, was expecting that this list would include Processor, etc.
[/SAMI]


> +  //ContainedElements
> +  (VOID)CopyMem (SmbiosRecord + 1, &ContainedElements, ExtendLength);
> [SAMI] If I understand correctly, the Contained Element data is never really copied, right?
> [/SAMI]


I'm not sure why it wouldn't be copied. Could you elaborate?
[SAMI] If InputData->ContainedElementCount = 0 or 1, then 'CopyMem (SmbiosRecord, InputData, sizeof (SMBIOS_TABLE_TYPE3));' should be ok (assuming InputData->ContainedElements[0] is populated with the relevant data).
But if ContainedElementCount = 2 then the SmbiosRecord is populated with zeros, as ContainedElements is a local variable that is zero initialised. 
Also, if ContainedElementCount > 2 the copy operation would access invalid stack data which could be a problem.
[/SAMI]


-- 
Rebecca Cran

^ permalink raw reply	[flat|nested] 40+ messages in thread

end of thread, other threads:[~2021-01-04 10:21 UTC | newest]

Thread overview: 40+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2020-12-07 17:54 [PATCH v4 00/10] ArmPkg,MdePkg: Add Universal/Smbios, and related changes Rebecca Cran
2020-12-07 17:54 ` [PATCH v4 01/10] ArmPkg: Add ARM SMC Architecture functions to ArmStdSmc.h Rebecca Cran
2020-12-15 18:06   ` Leif Lindholm
2020-12-16 11:23   ` [edk2-devel] " Sami Mujawar
2020-12-07 17:54 ` [PATCH v4 02/10] MdePkg: Update IndustryStandard/SmBios.h with processor status data Rebecca Cran
2020-12-08  4:50   ` 回复: " gaoliming
2020-12-07 17:54 ` [PATCH v4 03/10] ArmPkg: Add register encoding definition for MMFR2 Rebecca Cran
2020-12-15 18:42   ` Leif Lindholm
2020-12-16 11:31   ` [edk2-devel] " Sami Mujawar
2020-12-07 17:54 ` [PATCH v4 04/10] ArmPkg: Add helper to read the Memory Model Features Register 2 Rebecca Cran
2020-12-15 19:11   ` Leif Lindholm
2020-12-16 11:06     ` [edk2-devel] " Sami Mujawar
2020-12-17 13:38     ` Laszlo Ersek
2020-12-17 13:47       ` Ard Biesheuvel
2020-12-17 18:04         ` Leif Lindholm
2020-12-17 18:19           ` Rebecca Cran
2020-12-17 17:57       ` Leif Lindholm
2020-12-07 17:54 ` [PATCH v4 05/10] ArmPkg: Add helper function to read the Memory Model Feature Register 4 Rebecca Cran
2020-12-16 11:23   ` [edk2-devel] " Sami Mujawar
2020-12-07 17:54 ` [PATCH v4 06/10] ArmPkg: Add helper to read CCIDX status Rebecca Cran
2020-12-16 11:23   ` [edk2-devel] " Sami Mujawar
2020-12-07 17:54 ` [PATCH v4 07/10] ArmPkg: Fix the return type of the ReadCCSIDR function Rebecca Cran
2020-12-15 19:24   ` Leif Lindholm
2020-12-16 11:31   ` [edk2-devel] " Sami Mujawar
2020-12-07 17:54 ` [PATCH v4 08/10] ArmPkg: Update ArmLibPrivate.h with cache register definitions Rebecca Cran
2020-12-15 19:27   ` Leif Lindholm
2020-12-07 17:54 ` [PATCH v4 09/10] ArmPkg: Add definition of the maximum cache level in ARMv8-A Rebecca Cran
2020-12-15 19:27   ` Leif Lindholm
2020-12-16 11:31   ` [edk2-devel] " Sami Mujawar
2020-12-07 17:54 ` [PATCH v4 10/10] ArmPkg: Add Universal/Smbios, a generic SMBIOS library for ARM Rebecca Cran
2020-12-15 19:29   ` Leif Lindholm
2020-12-15 21:14     ` Rebecca Cran
2020-12-16 15:13   ` [edk2-devel] " Sami Mujawar
2020-12-16 15:21     ` Rebecca Cran
2020-12-19  3:14     ` Rebecca Cran
     [not found]   ` <16513B32D4BA613C.12945@groups.io>
2020-12-29 15:10     ` Sami Mujawar
2021-01-03 23:52       ` Rebecca Cran
2021-01-04 10:21         ` Sami Mujawar
2020-12-14 15:45 ` [PATCH v4 00/10] ArmPkg,MdePkg: Add Universal/Smbios, and related changes Rebecca Cran
2020-12-15 18:36 ` Leif Lindholm

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