[edk2-devel] [edk2-platforms][PATCH v2 23/32] AmpereAltraPkg: Add configuration screen for memory

Nhi Pham via groups.io nhi=os.amperecomputing.com at groups.io
Wed May 26 10:07:15 UTC 2021


From: Vu Nguyen <vunguyen at os.amperecomputing.com>

Provide memory screen with below info:
* Memory total capacity
* Memory RAS and Performance Configuration
* Per DIMM Information

Cc: Thang Nguyen <thang at os.amperecomputing.com>
Cc: Chuong Tran <chuong at os.amperecomputing.com>
Cc: Phong Vo <phong at os.amperecomputing.com>
Cc: Leif Lindholm <leif at nuviainc.com>
Cc: Michael D Kinney <michael.d.kinney at intel.com>
Cc: Ard Biesheuvel <ardb+tianocore at kernel.org>
Cc: Nate DeSimone <nathaniel.l.desimone at intel.com>

Signed-off-by: Vu Nguyen <vunguyen at os.amperecomputing.com>
---
 Platform/Ampere/JadePkg/Jade.dsc                                          |    1 +
 Platform/Ampere/JadePkg/Jade.fdf                                          |    1 +
 Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoDxe.inf           |   59 +
 Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoScreen.h          |  168 +++
 Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/NVDataStruc.h            |   47 +
 Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/Vfr.vfr                  |   62 +
 Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoNvramLib.c        |  394 ++++++
 Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoScreen.c          | 1325 ++++++++++++++++++++
 Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoDxe.uni           |    9 +
 Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoDxeExtra.uni      |    9 +
 Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoScreenStrings.uni |   64 +
 11 files changed, 2139 insertions(+)

diff --git a/Platform/Ampere/JadePkg/Jade.dsc b/Platform/Ampere/JadePkg/Jade.dsc
index b5edb673abba..75b3ece3817e 100755
--- a/Platform/Ampere/JadePkg/Jade.dsc
+++ b/Platform/Ampere/JadePkg/Jade.dsc
@@ -179,3 +179,4 @@ [Components.common]
   # HII
   #
   Silicon/Ampere/AmpereAltraPkg/Drivers/PlatformInfoDxe/PlatformInfoDxe.inf
+  Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoDxe.inf
diff --git a/Platform/Ampere/JadePkg/Jade.fdf b/Platform/Ampere/JadePkg/Jade.fdf
index 6dd759322d9d..e71f3e79e6b3 100755
--- a/Platform/Ampere/JadePkg/Jade.fdf
+++ b/Platform/Ampere/JadePkg/Jade.fdf
@@ -354,5 +354,6 @@ [FV.FvMain]
   # HII
   #
   INF Silicon/Ampere/AmpereAltraPkg/Drivers/PlatformInfoDxe/PlatformInfoDxe.inf
+  INF Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoDxe.inf
 
 !include Platform/Ampere/AmperePlatformPkg/FvRules.fdf.inc
diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoDxe.inf b/Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoDxe.inf
new file mode 100644
index 000000000000..2328051c6e1a
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoDxe.inf
@@ -0,0 +1,59 @@
+## @file
+#
+# Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x0001001B
+  BASE_NAME                      = MemInfoDxe
+  MODULE_UNI_FILE                = MemInfoDxe.uni
+  FILE_GUID                      = D9EFCEFE-189B-4599-BB07-04F0A8DF5C2F
+  MODULE_TYPE                    = DXE_DRIVER
+  ENTRY_POINT                    = MemInfoScreenInitialize
+
+[Sources]
+  MemInfoNvramLib.c
+  MemInfoScreen.c
+  MemInfoScreen.h
+  MemInfoScreenStrings.uni
+  NVDataStruc.h
+  Vfr.vfr
+
+[Packages]
+  ArmPkg/ArmPkg.dec
+  ArmPlatformPkg/ArmPlatformPkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  MdePkg/MdePkg.dec
+  Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec
+  Silicon/Ampere/AmpereSiliconPkg/AmpereSiliconPkg.dec
+
+[LibraryClasses]
+  AmpereCpuLib
+  BaseLib
+  DevicePathLib
+  HiiLib
+  HobLib
+  MemoryAllocationLib
+  NVParamLib
+  UefiBootServicesTableLib
+  UefiDriverEntryPoint
+  UefiLib
+
+[Guids]
+  gEfiIfrTianoGuid                              ## PRODUCES ## UNDEFINED
+  gPlatformManagerFormsetGuid
+  gPlatformHobGuid
+
+[Protocols]
+  gEfiDevicePathProtocolGuid                    ## CONSUMES
+  gEfiHiiConfigRoutingProtocolGuid              ## CONSUMES
+  gEfiHiiConfigAccessProtocolGuid               ## PRODUCES
+
+[Depex]
+  TRUE
+
+[UserExtensions.TianoCore."ExtraFiles"]
+  MemInfoDxeExtra.uni
diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoScreen.h b/Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoScreen.h
new file mode 100644
index 000000000000..546f554f8fb2
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoScreen.h
@@ -0,0 +1,168 @@
+/** @file
+
+  Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef MEM_INFO_SCREEN_H_
+#define MEM_INFO_SCREEN_H_
+
+#include <Uefi.h>
+
+#include <Guid/MdeModuleHii.h>
+#include <Guid/PlatformInfoHobGuid.h>
+#include <Library/AmpereCpuLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/HiiLib.h>
+#include <Library/HobLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PrintLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiLib.h>
+#include <PlatformInfoHob.h>
+#include <Protocol/HiiConfigAccess.h>
+#include <Protocol/HiiConfigKeyword.h>
+#include <Protocol/HiiConfigRouting.h>
+#include <Protocol/HiiDatabase.h>
+#include <Protocol/HiiString.h>
+
+#include "NVDataStruc.h"
+
+//
+// This is the generated IFR binary data for each formset defined in VFR.
+// This data array is ready to be used as input of HiiAddPackages() to
+// create a packagelist (which contains Form packages, String packages, etc).
+//
+extern UINT8 VfrBin[];
+
+//
+// This is the generated String package data for all .UNI files.
+// This data array is ready to be used as input of HiiAddPackages() to
+// create a packagelist (which contains Form packages, String packages, etc).
+//
+extern UINT8 MemInfoDxeStrings[];
+
+enum DDR_ECC_MODE {
+  ECC_DISABLE = 0,
+  ECC_SECDED,
+  SYMBOL_ECC
+};
+
+enum DDR_ERROR_CTRL_MODE_DE {
+  ERRCTLR_DE_DISABLE = 0,
+  ERRCTLR_DE_ENABLE,
+};
+
+enum DDR_ERROR_CTRL_MODE_FI {
+  ERRCTLR_FI_DISABLE = 0,
+  ERRCTLR_FI_ENABLE,
+};
+
+#define MEM_INFO_DDR_SPEED_SEL_OFFSET                     OFFSET_OF (MEM_INFO_VARSTORE_DATA, DDRSpeedSel)
+#define MEM_INFO_ECC_MODE_SEL_OFFSET                      OFFSET_OF (MEM_INFO_VARSTORE_DATA, EccMode)
+#define MEM_INFO_ERR_CTRL_DE_MODE_SEL_OFFSET              OFFSET_OF (MEM_INFO_VARSTORE_DATA, ErrCtrl_DE)
+#define MEM_INFO_ERR_CTRL_FI_MODE_SEL_OFFSET              OFFSET_OF (MEM_INFO_VARSTORE_DATA, ErrCtrl_FI)
+#define MEM_INFO_ERR_SLAVE_32BIT_OFFSET                   OFFSET_OF (MEM_INFO_VARSTORE_DATA, Slave32bit)
+#define MEM_INFO_DDR_SCRUB_OFFSET                         OFFSET_OF (MEM_INFO_VARSTORE_DATA, ScrubPatrol)
+#define MEM_INFO_DDR_DEMAND_SCRUB_OFFSET                  OFFSET_OF (MEM_INFO_VARSTORE_DATA, DemandScrub)
+#define MEM_INFO_DDR_WRITE_CRC_OFFSET                     OFFSET_OF (MEM_INFO_VARSTORE_DATA, WriteCrc)
+#define MEM_INFO_FGR_MODE_OFFSET                          OFFSET_OF (MEM_INFO_VARSTORE_DATA, FGRMode)
+#define MEM_INFO_REFRESH2X_MODE_OFFSET                    OFFSET_OF (MEM_INFO_VARSTORE_DATA, Refresh2x)
+#define MEM_INFO_NVDIMM_MODE_SEL_OFFSET                   OFFSET_OF (MEM_INFO_VARSTORE_DATA, NvdimmModeSel)
+
+#define MEM_INFO_SCREEN_PRIVATE_DATA_SIGNATURE            SIGNATURE_32 ('M', 'E', 'M', 'i')
+
+#define MEM_INFO_DDR_SPEED_SEL_QUESTION_ID                       0x8001
+#define MEM_INFO_FORM_PERFORMANCE_QUESTION_ID                    0x8002
+#define MEM_INFO_FORM_PERFORMANCE_ECC_QUESTION_ID                0x8003
+#define MEM_INFO_FORM_PERFORMANCE_ERR_CTRL_DE_QUESTION_ID        0x8004
+#define MEM_INFO_FORM_PERFORMANCE_ERR_CTRL_FI_QUESTION_ID        0x8005
+#define MEM_INFO_DDR_SLAVE_32BIT_QUESTION_ID                     0x8006
+#define MEM_INFO_DDR_SCRUB_PATROL_QUESTION_ID                    0x8007
+#define MEM_INFO_DDR_DEMAND_SCRUB_QUESTION_ID                    0x8008
+#define MEM_INFO_DDR_WRITE_CRC_QUESTION_ID                       0x8009
+#define MEM_INFO_FGR_MODE_QUESTION_ID                            0x800A
+#define MEM_INFO_REFRESH2X_MODE_QUESTION_ID                      0x800B
+#define MEM_INFO_FORM_NVDIMM_QUESTION_ID                         0x800C
+#define MEM_INFO_FORM_NVDIMM_MODE_SEL_QUESTION_ID                0x800D
+
+#define DDR_DEFAULT_SCRUB_PATROL_DURATION 24
+#define DDR_DEFAULT_DEMAND_SCRUB          1
+#define DDR_DEFAULT_WRITE_CRC             0
+#define DDR_DEFAULT_FGR_MODE              0
+#define DDR_DEFAULT_REFRESH2X_MODE        0
+#define DDR_DEFAULT_NVDIMM_MODE_SEL       3
+
+#define DDR_FGR_MODE_GET(Value)           ((Value) & 0x3) /* Bit 0, 1 */
+#define DDR_FGR_MODE_SET(Dst, Src)        do { Dst = (((Dst) & ~0x3) | ((Src) & 0x3)); } while (0)
+
+#define DDR_REFRESH_2X_GET(Value)         ((Value) & 0x10000) >> 16 /* Bit 16 only */
+#define DDR_REFRESH_2X_SET(Dst, Src)      do { Dst = (((Dst) & ~0x10000) | ((Src) & 0x1) << 16); } while (0)
+
+#define DDR_NVDIMM_MODE_SEL_MASK         0x7FFFFFFF
+#define DDR_NVDIMM_MODE_SEL_VALID_BIT    BIT31
+
+typedef struct {
+  UINTN Signature;
+
+  EFI_HANDLE             DriverHandle;
+  EFI_HII_HANDLE         HiiHandle;
+  MEM_INFO_VARSTORE_DATA VarStoreConfig;
+
+  //
+  // Consumed protocol
+  //
+  EFI_HII_DATABASE_PROTOCOL           *HiiDatabase;
+  EFI_HII_STRING_PROTOCOL             *HiiString;
+  EFI_HII_CONFIG_ROUTING_PROTOCOL     *HiiConfigRouting;
+  EFI_CONFIG_KEYWORD_HANDLER_PROTOCOL *HiiKeywordHandler;
+  EFI_FORM_BROWSER2_PROTOCOL          *FormBrowser2;
+
+  //
+  // Produced protocol
+  //
+  EFI_HII_CONFIG_ACCESS_PROTOCOL ConfigAccess;
+} MEM_INFO_SCREEN_PRIVATE_DATA;
+
+#define MEM_INFO_SCREEN_PRIVATE_FROM_THIS(a)  CR (a, MEM_INFO_SCREEN_PRIVATE_DATA, ConfigAccess, MEM_INFO_SCREEN_PRIVATE_DATA_SIGNATURE)
+
+#pragma pack(1)
+
+///
+/// HII specific Vendor Device Path definition.
+///
+typedef struct {
+  VENDOR_DEVICE_PATH       VendorDevicePath;
+  EFI_DEVICE_PATH_PROTOCOL End;
+} HII_VENDOR_DEVICE_PATH;
+
+#pragma pack()
+
+EFI_STATUS
+MemInfoScreenInitialize (
+  IN EFI_HANDLE       ImageHandle,
+  IN EFI_SYSTEM_TABLE *SystemTable
+  );
+
+EFI_STATUS
+MemInfoScreenUnload (
+  IN EFI_HANDLE ImageHandle
+  );
+
+EFI_STATUS
+MemInfoNvparamGet (
+  OUT MEM_INFO_VARSTORE_DATA *VarStoreConfig
+  );
+
+EFI_STATUS
+MemInfoNvparamSet (
+  IN MEM_INFO_VARSTORE_DATA *VarStoreConfig
+  );
+
+#endif /* MEM_INFO_SCREEN_H_ */
diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/NVDataStruc.h b/Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/NVDataStruc.h
new file mode 100644
index 000000000000..7a6e776e7f4e
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/NVDataStruc.h
@@ -0,0 +1,47 @@
+/** @file
+
+  Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef NVDATASTRUC_H_
+#define NVDATASTRUC_H_
+
+#define MEM_INFO_VARSTORE_NAME        L"MemInfoIfrNVData"
+#define MEM_INFO_VARSTORE_ID          0x1234
+#define MEM_INFO_FORM_ID              0x1235
+#define MEM_INFO_FORM_PERFORMANCE_ID  0x1236
+#define MEM_INFO_FORM_NVDIMM_ID       0x1237
+#define MEM_INFO_FORM_SET_GUID                    { 0xd58338ee, 0xe9f7, 0x4d8d, { 0xa7, 0x08, 0xdf, 0xb2, 0xc6, 0x66, 0x1d, 0x61 } }
+#define MEM_INFO_FORM_SET_PERFORMANCE_GUID        { 0x4a072c78, 0x42f9, 0x11ea, { 0xb7, 0x7f, 0x2e, 0x28, 0xce, 0x88, 0x12, 0x62 } }
+
+#pragma pack(1)
+
+//
+// NV data structure definition
+//
+typedef struct {
+  UINT32 DDRSpeedSel;
+  UINT32 EccMode;
+  UINT32 ErrCtrl_DE;
+  UINT32 ErrCtrl_FI;
+  UINT32 Slave32bit;
+  UINT32 ScrubPatrol;
+  UINT32 DemandScrub;
+  UINT32 WriteCrc;
+  UINT32 FGRMode;
+  UINT32 Refresh2x;
+  UINT32 NvdimmModeSel;
+} MEM_INFO_VARSTORE_DATA;
+
+//
+// Labels definition
+//
+#define LABEL_UPDATE             0x2223
+#define LABEL_END                0x2224
+
+#pragma pack()
+
+#endif
diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/Vfr.vfr b/Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/Vfr.vfr
new file mode 100644
index 000000000000..6c7ccb7375d0
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/Vfr.vfr
@@ -0,0 +1,62 @@
+/** @file
+
+  Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Guid/PlatformManagerHii.h>
+#include "NVDataStruc.h"
+
+formset
+  guid    = MEM_INFO_FORM_SET_GUID,
+  title   = STRING_TOKEN(STR_MEM_INFO_FORM),
+  help    = STRING_TOKEN(STR_MEM_INFO_FORM_HELP),
+  classguid = gPlatformManagerFormsetGuid,
+
+  //
+  // Define a variable Storage
+  //
+  varstore MEM_INFO_VARSTORE_DATA,
+    varid = MEM_INFO_VARSTORE_ID,
+    name  = MemInfoIfrNVData,
+    guid  = MEM_INFO_FORM_SET_GUID;
+
+  form
+    formid = MEM_INFO_FORM_ID,
+    title = STRING_TOKEN(STR_MEM_INFO_FORM);
+
+    subtitle text = STRING_TOKEN(STR_MEM_INFO_FORM);
+
+    label LABEL_UPDATE;
+    // dynamic content here
+    label LABEL_END;
+
+  endform;
+
+  form
+    formid = MEM_INFO_FORM_PERFORMANCE_ID,
+    title = STRING_TOKEN(STR_MEM_INFO_PERFORMANCE_FORM);
+
+    subtitle text = STRING_TOKEN(STR_MEM_INFO_PERFORMANCE_FORM);
+
+    label LABEL_UPDATE;
+    // dynamic content here
+    label LABEL_END;
+
+  endform;
+
+  form
+    formid = MEM_INFO_FORM_NVDIMM_ID,
+    title = STRING_TOKEN(STR_MEM_INFO_NVDIMM_FORM);
+
+    subtitle text = STRING_TOKEN(STR_MEM_INFO_NVDIMM_FORM);
+
+    label LABEL_UPDATE;
+    // dynamic content here
+    label LABEL_END;
+
+  endform;
+
+endformset;
diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoNvramLib.c b/Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoNvramLib.c
new file mode 100644
index 000000000000..c83f489f4078
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoNvramLib.c
@@ -0,0 +1,394 @@
+/** @file
+
+  Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+
+#include <Library/NVParamLib.h>
+
+#include "MemInfoScreen.h"
+#include "NVParamDef.h"
+
+#define DDR_NVPARAM_ERRCTRL_DE_FIELD_SHIFT    0
+#define DDR_NVPARAM_ERRCTRL_DE_FIELD_MASK     0x1
+
+#define DDR_NVPARAM_ERRCTRL_FI_FIELD_SHIFT    1
+#define DDR_NVPARAM_ERRCTRL_FI_FIELD_MASK     0x2
+
+/**
+  This is function collects meminfo from NVParam
+
+  @param  Data                  The buffer to return the contents.
+
+  @retval EFI_SUCCESS           Get response data successfully.
+  @retval Other value           Failed to get meminfo from NVParam
+**/
+EFI_STATUS
+MemInfoNvparamGet (
+  OUT MEM_INFO_VARSTORE_DATA *VarStoreConfig
+  )
+{
+  UINT32     Value;
+  EFI_STATUS Status;
+
+  ASSERT (VarStoreConfig != NULL);
+
+  Status = NVParamGet (
+             NV_SI_DDR_SPEED,
+             NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+             &Value
+             );
+  if (EFI_ERROR (Status)) {
+    VarStoreConfig->DDRSpeedSel = 0; /* Default auto mode */
+  } else {
+    VarStoreConfig->DDRSpeedSel = Value;
+  }
+
+  Status = NVParamGet (
+             NV_SI_DDR_ECC_MODE,
+             NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+             &Value
+             );
+  if (EFI_ERROR (Status)) {
+    VarStoreConfig->EccMode = ECC_SECDED; /* Default enable */
+  } else {
+    VarStoreConfig->EccMode = Value;
+  }
+
+  Status = NVParamGet (
+             NV_SI_DDR_ERRCTRL,
+             NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+             &Value
+             );
+  if (EFI_ERROR (Status)) {
+    VarStoreConfig->ErrCtrl_DE = ERRCTLR_DE_ENABLE;
+    VarStoreConfig->ErrCtrl_FI = ERRCTLR_FI_ENABLE;
+  } else {
+    VarStoreConfig->ErrCtrl_DE = (Value & DDR_NVPARAM_ERRCTRL_DE_FIELD_MASK) >> DDR_NVPARAM_ERRCTRL_DE_FIELD_SHIFT;
+    VarStoreConfig->ErrCtrl_FI = (Value & DDR_NVPARAM_ERRCTRL_FI_FIELD_MASK) >> DDR_NVPARAM_ERRCTRL_FI_FIELD_SHIFT;
+  }
+
+  Status = NVParamGet (
+             NV_SI_DDR_SLAVE_32BIT_MEM_EN,
+             NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+             &Value
+             );
+  if (EFI_ERROR (Status)) {
+    VarStoreConfig->Slave32bit = 0; /* Default disabled */
+  } else {
+    VarStoreConfig->Slave32bit = Value;
+  }
+
+  Status = NVParamGet (
+             NV_SI_DDR_SCRUB_EN,
+             NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+             &Value
+             );
+  if (EFI_ERROR (Status)) {
+    VarStoreConfig->ScrubPatrol = DDR_DEFAULT_SCRUB_PATROL_DURATION;
+  } else {
+    VarStoreConfig->ScrubPatrol = Value;
+  }
+
+  Status = NVParamGet (
+             NV_SI_DDR_WR_BACK_EN,
+             NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+             &Value
+             );
+  if (EFI_ERROR (Status)) {
+    VarStoreConfig->DemandScrub = DDR_DEFAULT_DEMAND_SCRUB;
+  } else {
+    VarStoreConfig->DemandScrub = Value;
+  }
+
+  Status = NVParamGet (
+             NV_SI_DDR_CRC_MODE,
+             NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+             &Value
+             );
+  if (EFI_ERROR (Status)) {
+    VarStoreConfig->WriteCrc = DDR_DEFAULT_WRITE_CRC;
+  } else {
+    VarStoreConfig->WriteCrc = Value;
+  }
+
+  Status = NVParamGet (
+             NV_SI_DDR_REFRESH_GRANULARITY,
+             NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+             &Value
+             );
+  if (EFI_ERROR (Status)) {
+    VarStoreConfig->FGRMode = DDR_DEFAULT_FGR_MODE;
+    VarStoreConfig->Refresh2x = DDR_DEFAULT_REFRESH2X_MODE;
+  } else {
+    VarStoreConfig->FGRMode = DDR_FGR_MODE_GET (Value);
+    VarStoreConfig->Refresh2x = DDR_REFRESH_2X_GET (Value);
+  }
+
+  Status = NVParamGet (
+             NV_SI_NVDIMM_MODE,
+             NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+             &Value
+             );
+  if (EFI_ERROR (Status)) {
+    VarStoreConfig->NvdimmModeSel = DDR_DEFAULT_NVDIMM_MODE_SEL;
+  } else {
+    VarStoreConfig->NvdimmModeSel = Value & DDR_NVDIMM_MODE_SEL_MASK; /* Mask out valid bit */
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  This is function stores meminfo to corresponding NVParam
+
+  @param  VarStoreConfig         The contents for the variable.
+
+  @retval EFI_SUCCESS            Set data successfully.
+  @retval Other value            Failed to set meminfo to NVParam
+
+**/
+EFI_STATUS
+MemInfoNvparamSet (
+  IN MEM_INFO_VARSTORE_DATA *VarStoreConfig
+  )
+{
+  EFI_STATUS Status;
+  UINT32     Value, TmpValue, Value2, Update;
+
+  ASSERT (VarStoreConfig != NULL);
+
+  /* Set DDR speed */
+  Status = NVParamGet (
+             NV_SI_DDR_SPEED,
+             NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU |NV_PERM_BMC,
+             &Value
+             );
+  if (EFI_ERROR (Status) || Value != VarStoreConfig->DDRSpeedSel) {
+    Status = NVParamSet (
+               NV_SI_DDR_SPEED,
+               NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU |NV_PERM_BMC,
+               NV_PERM_BIOS | NV_PERM_MANU,
+               VarStoreConfig->DDRSpeedSel
+               );
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+  }
+
+  /* Set ECC mode */
+  Status = NVParamGet (
+             NV_SI_DDR_ECC_MODE,
+             NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU |NV_PERM_BMC,
+             &Value
+             );
+  if (EFI_ERROR (Status) || Value != VarStoreConfig->EccMode) {
+    Status = NVParamSet (
+               NV_SI_DDR_ECC_MODE,
+               NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU |NV_PERM_BMC,
+               NV_PERM_BIOS | NV_PERM_MANU,
+               VarStoreConfig->EccMode
+               );
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+  }
+
+  /* Set ErrCtrl */
+  TmpValue = (VarStoreConfig->ErrCtrl_DE << DDR_NVPARAM_ERRCTRL_DE_FIELD_SHIFT) |
+             (VarStoreConfig->ErrCtrl_FI << DDR_NVPARAM_ERRCTRL_FI_FIELD_SHIFT);
+  Status = NVParamGet (
+             NV_SI_DDR_ERRCTRL,
+             NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU |NV_PERM_BMC,
+             &Value
+             );
+  if (EFI_ERROR (Status) || Value != TmpValue ) {
+    Status = NVParamSet (
+               NV_SI_DDR_ERRCTRL,
+               NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU |NV_PERM_BMC,
+               NV_PERM_BIOS | NV_PERM_MANU,
+               TmpValue
+               );
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+  }
+
+  /* Set slave's 32bit region */
+  TmpValue = VarStoreConfig->Slave32bit;
+  Status = NVParamGet (
+             NV_SI_DDR_SLAVE_32BIT_MEM_EN,
+             NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU |NV_PERM_BMC,
+             &Value
+             );
+  if (EFI_ERROR (Status) || Value != TmpValue ) {
+    if (TmpValue == 0) {
+      /* Default is disabled so just clear nvparam */
+      Status = NVParamClr (
+                 NV_SI_DDR_SLAVE_32BIT_MEM_EN,
+                 NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU |NV_PERM_BMC
+                 );
+    } else {
+      Status = NVParamSet (
+                 NV_SI_DDR_SLAVE_32BIT_MEM_EN,
+                 NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU |NV_PERM_BMC,
+                 NV_PERM_BIOS | NV_PERM_MANU,
+                 TmpValue
+                 );
+    }
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+  }
+
+  /* Set Scrub patrol */
+  TmpValue = VarStoreConfig->ScrubPatrol;
+  Status = NVParamGet (
+             NV_SI_DDR_SCRUB_EN,
+             NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU |NV_PERM_BMC,
+             &Value
+             );
+  if (EFI_ERROR (Status) || Value != TmpValue ) {
+    if (TmpValue == DDR_DEFAULT_SCRUB_PATROL_DURATION) {
+      Status = NVParamClr (
+                 NV_SI_DDR_SCRUB_EN,
+                 NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU |NV_PERM_BMC
+                 );
+    } else {
+      Status = NVParamSet (
+                 NV_SI_DDR_SCRUB_EN,
+                 NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU |NV_PERM_BMC,
+                 NV_PERM_BIOS | NV_PERM_MANU,
+                 TmpValue
+                 );
+    }
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+  }
+
+  /* Demand Scrub */
+  TmpValue = VarStoreConfig->DemandScrub;
+  Status = NVParamGet (
+             NV_SI_DDR_WR_BACK_EN,
+             NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU |NV_PERM_BMC,
+             &Value
+             );
+  if (EFI_ERROR (Status) || Value != TmpValue ) {
+    if (TmpValue == DDR_DEFAULT_DEMAND_SCRUB) {
+      Status = NVParamClr (
+                 NV_SI_DDR_WR_BACK_EN,
+                 NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU |NV_PERM_BMC
+                 );
+    } else {
+      Status = NVParamSet (
+                 NV_SI_DDR_WR_BACK_EN,
+                 NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU |NV_PERM_BMC,
+                 NV_PERM_BIOS | NV_PERM_MANU,
+                 TmpValue
+                 );
+    }
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+  }
+
+  /* Write CRC */
+  TmpValue = VarStoreConfig->WriteCrc;
+  Status = NVParamGet (
+             NV_SI_DDR_CRC_MODE,
+             NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+             &Value
+             );
+  if (EFI_ERROR (Status) || Value != TmpValue ) {
+    if (TmpValue == DDR_DEFAULT_WRITE_CRC) {
+      Status = NVParamClr (
+                 NV_SI_DDR_CRC_MODE,
+                 NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC
+                 );
+    } else {
+      Status = NVParamSet (
+                 NV_SI_DDR_CRC_MODE,
+                 NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+                 NV_PERM_BIOS | NV_PERM_MANU,
+                 TmpValue
+                 );
+    }
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+  }
+
+  /* Write FGR/Refresh2X */
+  Value = 0;
+  Update = 0;
+  TmpValue = VarStoreConfig->FGRMode;
+  Status = NVParamGet (
+             NV_SI_DDR_REFRESH_GRANULARITY,
+             NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+             &Value
+             );
+  Value2 = DDR_FGR_MODE_GET (Value);
+  if ((EFI_ERROR (Status) && TmpValue != DDR_DEFAULT_FGR_MODE)
+      || Value2 != TmpValue)
+  {
+    DDR_FGR_MODE_SET (Value, TmpValue);
+    Update = 1;
+  }
+
+  Value2 = DDR_REFRESH_2X_GET (Value);
+  TmpValue = VarStoreConfig->Refresh2x;
+  if ((EFI_ERROR (Status) && TmpValue != DDR_DEFAULT_REFRESH2X_MODE)
+      || Value2 != TmpValue)
+  {
+    DDR_REFRESH_2X_SET (Value, TmpValue);
+    Update = 1;
+  }
+
+  if (Update == 1) {
+    Status = NVParamSet (
+               NV_SI_DDR_REFRESH_GRANULARITY,
+               NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+               NV_PERM_BIOS | NV_PERM_MANU,
+               Value
+               );
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+  }
+
+  /* Write NVDIMM-N Mode selection */
+  Value = 0;
+  TmpValue = VarStoreConfig->NvdimmModeSel;
+  Status = NVParamGet (
+             NV_SI_NVDIMM_MODE,
+             NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+             &Value
+             );
+  Value2 = Value & DDR_NVDIMM_MODE_SEL_MASK; /* Mask out valid bit */
+  if (EFI_ERROR (Status) || Value2 != TmpValue ) {
+    if (TmpValue == DDR_DEFAULT_NVDIMM_MODE_SEL) {
+      Status = NVParamClr (
+                 NV_SI_NVDIMM_MODE,
+                 NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC
+                 );
+    } else {
+      Value = TmpValue | DDR_NVDIMM_MODE_SEL_VALID_BIT; /* Add valid bit */
+      Status = NVParamSet (
+                 NV_SI_NVDIMM_MODE,
+                 NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+                 NV_PERM_BIOS | NV_PERM_MANU,
+                 Value
+                 );
+    }
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+  }
+
+  return EFI_SUCCESS;
+}
diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoScreen.c b/Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoScreen.c
new file mode 100644
index 000000000000..75f743b824e0
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoScreen.c
@@ -0,0 +1,1325 @@
+/** @file
+
+  Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "MemInfoScreen.h"
+
+#define MAX_STRING_SIZE     64
+#define GB_SCALE_FACTOR     (1024*1024*1024)
+#define MB_SCALE_FACTOR     (1024*1024)
+
+EFI_GUID gMemInfoFormSetGuid = MEM_INFO_FORM_SET_GUID;
+
+HII_VENDOR_DEVICE_PATH mHiiVendorDevicePath = {
+  {
+    {
+      HARDWARE_DEVICE_PATH,
+      HW_VENDOR_DP,
+      {
+        (UINT8)(sizeof (VENDOR_DEVICE_PATH)),
+        (UINT8)((sizeof (VENDOR_DEVICE_PATH)) >> 8)
+      }
+    },
+    MEM_INFO_FORM_SET_GUID
+  },
+  {
+    END_DEVICE_PATH_TYPE,
+    END_ENTIRE_DEVICE_PATH_SUBTYPE,
+    {
+      (UINT8)(END_DEVICE_PATH_LENGTH),
+      (UINT8)((END_DEVICE_PATH_LENGTH) >> 8)
+    }
+  }
+};
+
+EFI_HANDLE                   DriverHandle = NULL;
+MEM_INFO_SCREEN_PRIVATE_DATA *mPrivateData = NULL;
+
+/**
+  This function allows a caller to extract the current configuration for one
+  or more named elements from the target driver.
+  @param  This                   Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+  @param  Request                A null-terminated Unicode string in
+                                 <ConfigRequest> format.
+  @param  Progress               On return, points to a character in the Request
+                                 string. Points to the string's null terminator if
+                                 request was successful. Points to the most recent
+                                 '&' before the first failing name/value pair (or
+                                 the beginning of the string if the failure is in
+                                 the first name/value pair) if the request was not
+                                 successful.
+  @param  Results                A null-terminated Unicode string in
+                                 <ConfigAltResp> format which has all values filled
+                                 in for the names in the Request string. String to
+                                 be allocated by the called function.
+  @retval EFI_SUCCESS            The Results is filled with the requested values.
+  @retval EFI_INVALID_PARAMETER  Request is illegal syntax, or unknown name.
+  @retval EFI_NOT_FOUND          Routing data doesn't match any storage in this
+                                 driver.
+**/
+EFI_STATUS
+EFIAPI
+ExtractConfig (
+  IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+  IN CONST EFI_STRING                     Request,
+  OUT      EFI_STRING                     *Progress,
+  OUT      EFI_STRING                     *Results
+  )
+{
+  EFI_STATUS                      Status;
+  UINTN                           BufferSize;
+  MEM_INFO_SCREEN_PRIVATE_DATA    *PrivateData;
+  EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
+  EFI_STRING                      ConfigRequest;
+  EFI_STRING                      ConfigRequestHdr;
+  UINTN                           Size;
+  CHAR16                          *StrPointer;
+  BOOLEAN                         AllocatedRequest;
+
+  if (Progress == NULL || Results == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Initialize the local variables.
+  //
+  ConfigRequestHdr  = NULL;
+  ConfigRequest     = NULL;
+  Size              = 0;
+  *Progress         = Request;
+  AllocatedRequest  = FALSE;
+
+  PrivateData = MEM_INFO_SCREEN_PRIVATE_FROM_THIS (This);
+  HiiConfigRouting = PrivateData->HiiConfigRouting;
+
+  //
+  // Get Buffer Storage data from EFI variable.
+  // Try to get the current setting from variable.
+  //
+  BufferSize = sizeof (MEM_INFO_VARSTORE_DATA);
+  Status = MemInfoNvparamGet (&PrivateData->VarStoreConfig);
+  if (EFI_ERROR (Status)) {
+    return EFI_NOT_FOUND;
+  }
+
+  if (Request == NULL) {
+    //
+    // Request is set to NULL, construct full request string.
+    //
+
+    //
+    // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
+    // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
+    //
+    ConfigRequestHdr = HiiConstructConfigHdr (&gMemInfoFormSetGuid, MEM_INFO_VARSTORE_NAME, PrivateData->DriverHandle);
+    Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);
+    ConfigRequest = AllocateZeroPool (Size);
+    ASSERT (ConfigRequest != NULL);
+    AllocatedRequest = TRUE;
+    UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);
+    FreePool (ConfigRequestHdr);
+    ConfigRequestHdr = NULL;
+  } else {
+    //
+    // Check routing data in <ConfigHdr>.
+    // Note: if only one Storage is used, then this checking could be skipped.
+    //
+    if (!HiiIsConfigHdrMatch (Request, &gMemInfoFormSetGuid, NULL)) {
+      return EFI_NOT_FOUND;
+    }
+
+    //
+    // Set Request to the unified request string.
+    //
+    ConfigRequest = Request;
+
+    //
+    // Check whether Request includes Request Element.
+    //
+    if (StrStr (Request, L"OFFSET") == NULL) {
+      //
+      // Check Request Element does exist in Request String
+      //
+      StrPointer = StrStr (Request, L"PATH");
+      if (StrPointer == NULL) {
+        return EFI_INVALID_PARAMETER;
+      }
+      if (StrStr (StrPointer, L"&") == NULL) {
+        Size = (StrLen (Request) + 32 + 1) * sizeof (CHAR16);
+        ConfigRequest    = AllocateZeroPool (Size);
+        ASSERT (ConfigRequest != NULL);
+        AllocatedRequest = TRUE;
+        UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", Request, (UINT64)BufferSize);
+      }
+    }
+  }
+
+  //
+  // Check if requesting Name/Value storage
+  //
+  if (StrStr (ConfigRequest, L"OFFSET") == NULL) {
+    //
+    // Don't have any Name/Value storage names
+    //
+    Status = EFI_SUCCESS;
+  } else {
+    //
+    // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
+    //
+    Status = HiiConfigRouting->BlockToConfig (
+                                 HiiConfigRouting,
+                                 ConfigRequest,
+                                 (UINT8 *)&PrivateData->VarStoreConfig,
+                                 BufferSize,
+                                 Results,
+                                 Progress
+                                 );
+  }
+
+  //
+  // Free the allocated config request string.
+  //
+  if (AllocatedRequest) {
+    FreePool (ConfigRequest);
+  }
+
+  if (ConfigRequestHdr != NULL) {
+    FreePool (ConfigRequestHdr);
+  }
+  //
+  // Set Progress string to the original request string.
+  //
+  if (Request == NULL) {
+    *Progress = NULL;
+  } else if (StrStr (Request, L"OFFSET") == NULL) {
+    *Progress = Request + StrLen (Request);
+  }
+
+  return Status;
+}
+
+/**
+  This function processes the results of changes in configuration.
+  @param  This                   Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+  @param  Configuration          A null-terminated Unicode string in <ConfigResp>
+                                 format.
+  @param  Progress               A pointer to a string filled in with the offset of
+                                 the most recent '&' before the first failing
+                                 name/value pair (or the beginning of the string if
+                                 the failure is in the first name/value pair) or
+                                 the terminating NULL if all was successful.
+  @retval EFI_SUCCESS            The Results is processed successfully.
+  @retval EFI_INVALID_PARAMETER  Configuration is NULL.
+  @retval EFI_NOT_FOUND          Routing data doesn't match any storage in this
+                                 driver.
+**/
+EFI_STATUS
+EFIAPI
+RouteConfig (
+  IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+  IN CONST EFI_STRING                     Configuration,
+  OUT      EFI_STRING                     *Progress
+  )
+{
+  EFI_STATUS                      Status;
+  UINTN                           BufferSize;
+  MEM_INFO_SCREEN_PRIVATE_DATA    *PrivateData;
+  EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
+
+  if (Configuration == NULL || Progress == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  PrivateData = MEM_INFO_SCREEN_PRIVATE_FROM_THIS (This);
+  HiiConfigRouting = PrivateData->HiiConfigRouting;
+  *Progress = Configuration;
+
+  //
+  // Check routing data in <ConfigHdr>.
+  // Note: if only one Storage is used, then this checking could be skipped.
+  //
+  if (!HiiIsConfigHdrMatch (Configuration, &gMemInfoFormSetGuid, NULL)) {
+    return EFI_NOT_FOUND;
+  }
+
+  //
+  // Get Buffer Storage data from NVParam
+  //
+  Status = MemInfoNvparamGet (&PrivateData->VarStoreConfig);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Check if configuring Name/Value storage
+  //
+  if (StrStr (Configuration, L"OFFSET") == NULL) {
+    //
+    // Don't have any Name/Value storage names
+    //
+    return EFI_SUCCESS;
+  }
+
+  //
+  // Convert <ConfigResp> to buffer data by helper function ConfigToBlock()
+  //
+  BufferSize = sizeof (MEM_INFO_VARSTORE_DATA);
+  Status = HiiConfigRouting->ConfigToBlock (
+                               HiiConfigRouting,
+                               Configuration,
+                               (UINT8 *)&PrivateData->VarStoreConfig,
+                               &BufferSize,
+                               Progress
+                               );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Store Buffer Storage back to NVParam
+  //
+  Status = MemInfoNvparamSet (&PrivateData->VarStoreConfig);
+
+  return Status;
+}
+
+/**
+  This function processes the results of changes in configuration.
+  @param  This                   Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+  @param  Action                 Specifies the type of action taken by the browser.
+  @param  QuestionId             A unique value which is sent to the original
+                                 exporting driver so that it can identify the type
+                                 of data to expect.
+  @param  Type                   The type of value for the question.
+  @param  Value                  A pointer to the data being sent to the original
+                                 exporting driver.
+  @param  ActionRequest          On return, points to the action requested by the
+                                 callback function.
+  @retval EFI_SUCCESS            The callback successfully handled the action.
+  @retval EFI_INVALID_PARAMETER  Configuration is NULL.
+  @retval EFI_UNSUPPORTED        The specified Action is not supported by the
+                                 callback.
+**/
+EFI_STATUS
+EFIAPI
+DriverCallback (
+  IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+  IN       EFI_BROWSER_ACTION             Action,
+  IN       EFI_QUESTION_ID                QuestionId,
+  IN       UINT8                          Type,
+  IN       EFI_IFR_TYPE_VALUE             *Value,
+  OUT      EFI_BROWSER_ACTION_REQUEST     *ActionRequest
+  )
+{
+  if (((Value == NULL) && (Action != EFI_BROWSER_ACTION_FORM_OPEN)
+       && (Action != EFI_BROWSER_ACTION_FORM_CLOSE))
+      || (ActionRequest == NULL))
+  {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  switch (Action) {
+  case EFI_BROWSER_ACTION_FORM_OPEN:
+  case EFI_BROWSER_ACTION_FORM_CLOSE:
+    break;
+
+  case EFI_BROWSER_ACTION_DEFAULT_STANDARD:
+  case EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING:
+  {
+    switch (QuestionId) {
+    case MEM_INFO_DDR_SPEED_SEL_QUESTION_ID:
+      //
+      // DDR speed selection default to auto
+      //
+      Value->u32 = 0;
+      break;
+
+    case MEM_INFO_FORM_PERFORMANCE_ECC_QUESTION_ID:
+      //
+      // ECC mode default to be enabled
+      //
+      Value->u32 = ECC_SECDED;
+      break;
+
+    case MEM_INFO_FORM_PERFORMANCE_ERR_CTRL_DE_QUESTION_ID:
+      //
+      // ErrCtrl_DE default to be enabled
+      //
+      Value->u32 = ERRCTLR_DE_ENABLE;
+      break;
+
+    case MEM_INFO_FORM_PERFORMANCE_ERR_CTRL_FI_QUESTION_ID:
+      //
+      // ErrCtrl_FI default to be enabled
+      //
+      Value->u32 = ERRCTLR_FI_ENABLE;
+      break;
+
+    case MEM_INFO_DDR_SLAVE_32BIT_QUESTION_ID:
+      //
+      // Slave's 32bit region to be disabled
+      //
+      Value->u32 = 0;
+      break;
+
+    case MEM_INFO_DDR_SCRUB_PATROL_QUESTION_ID:
+      Value->u32 = DDR_DEFAULT_SCRUB_PATROL_DURATION;
+      break;
+
+    case MEM_INFO_DDR_DEMAND_SCRUB_QUESTION_ID:
+      Value->u32 = DDR_DEFAULT_DEMAND_SCRUB;
+      break;
+
+    case MEM_INFO_DDR_WRITE_CRC_QUESTION_ID:
+      Value->u32 = DDR_DEFAULT_WRITE_CRC;
+      break;
+
+    case MEM_INFO_FGR_MODE_QUESTION_ID:
+      Value->u32 = DDR_DEFAULT_FGR_MODE;
+      break;
+
+    case MEM_INFO_REFRESH2X_MODE_QUESTION_ID:
+      Value->u32 = DDR_DEFAULT_REFRESH2X_MODE;
+      break;
+
+    case MEM_INFO_FORM_NVDIMM_MODE_SEL_QUESTION_ID:
+      Value->u32 = DDR_DEFAULT_NVDIMM_MODE_SEL;
+      break;
+    }
+  }
+  break;
+
+  case EFI_BROWSER_ACTION_RETRIEVE:
+  case EFI_BROWSER_ACTION_CHANGING:
+  case EFI_BROWSER_ACTION_SUBMITTED:
+    break;
+
+  default:
+    return EFI_UNSUPPORTED;
+  }
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+MemInfoMainScreen (
+  PLATFORM_INFO_HOB  *PlatformHob
+  )
+{
+  MEM_INFO_SCREEN_PRIVATE_DATA *PrivateData = mPrivateData;
+  EFI_STATUS                   Status;
+  VOID                         *StartOpCodeHandle;
+  VOID                         *OptionsOpCodeHandle;
+  VOID                         *OptionsOpCodeHandle1;
+  EFI_IFR_GUID_LABEL           *StartLabel;
+  EFI_STRING_ID                StringId;
+  VOID                         *EndOpCodeHandle;
+  EFI_IFR_GUID_LABEL           *EndLabel;
+  CHAR16                       Str[MAX_STRING_SIZE], Str1[MAX_STRING_SIZE];
+  EFI_HOB_RESOURCE_DESCRIPTOR  *ResHob;
+  PLATFORM_DIMM_INFO           *DimmInfo;
+  UINT64                       Size;
+  UINTN                        Count;
+
+  //
+  // Get Buffer Storage data from EFI variable
+  //
+  Status = MemInfoNvparamGet (&PrivateData->VarStoreConfig);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = EFI_SUCCESS;
+
+  /* Update Total memory */
+  UnicodeSPrint (Str, sizeof (Str), L"%d GB", PlatformHob->DramInfo.TotalSize / GB_SCALE_FACTOR);
+  HiiSetString (
+    PrivateData->HiiHandle,
+    STRING_TOKEN (STR_MEM_INFO_TOTAL_MEM_VALUE),
+    Str,
+    NULL
+    );
+
+  /* Update effective memory */
+  Size = 0;
+  ResHob = (EFI_HOB_RESOURCE_DESCRIPTOR *)GetFirstHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR);
+  while (ResHob != NULL) {
+    if ((ResHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY)) {
+      Size += ResHob->ResourceLength;
+    }
+    ResHob = (EFI_HOB_RESOURCE_DESCRIPTOR *)GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR,(VOID *)((UINTN)ResHob + ResHob->Header.HobLength));
+  }
+  UnicodeSPrint (Str, sizeof (Str), L"%d GB", Size / GB_SCALE_FACTOR);
+  HiiSetString (
+    PrivateData->HiiHandle,
+    STRING_TOKEN (STR_MEM_INFO_EFFECT_MEM_VALUE),
+    Str,
+    NULL
+    );
+
+  /* Update current DDR speed */
+  UnicodeSPrint (Str, sizeof (Str), L"%d MHz", PlatformHob->DramInfo.MaxSpeed);
+  HiiSetString (
+    PrivateData->HiiHandle,
+    STRING_TOKEN (STR_MEM_INFO_CURRENT_SPEED_VALUE),
+    Str,
+    NULL
+    );
+
+  //
+  // Initialize the container for dynamic opcodes
+  //
+  StartOpCodeHandle = HiiAllocateOpCodeHandle ();
+  ASSERT (StartOpCodeHandle != NULL);
+
+  EndOpCodeHandle = HiiAllocateOpCodeHandle ();
+  ASSERT (EndOpCodeHandle != NULL);
+
+  //
+  // Create Option OpCode to display speed configuration
+  //
+  OptionsOpCodeHandle = HiiAllocateOpCodeHandle ();
+  ASSERT (OptionsOpCodeHandle != NULL);
+
+  //
+  // Create Option OpCode to display FGR mode configuration
+  //
+  OptionsOpCodeHandle1 = HiiAllocateOpCodeHandle ();
+  ASSERT (OptionsOpCodeHandle1 != NULL);
+
+  //
+  // Create Hii Extend Label OpCode as the start opcode
+  //
+  StartLabel = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
+  StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
+  StartLabel->Number       = LABEL_UPDATE;
+
+  //
+  // Create Hii Extend Label OpCode as the end opcode
+  //
+  EndLabel = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
+  EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
+  EndLabel->Number       = LABEL_END;
+
+  //
+  // Create a total mem title
+  //
+  HiiCreateTextOpCode (
+    StartOpCodeHandle,
+    STRING_TOKEN (STR_MEM_INFO_TOTAL_MEM),
+    STRING_TOKEN (STR_MEM_INFO_TOTAL_MEM),
+    STRING_TOKEN (STR_MEM_INFO_TOTAL_MEM_VALUE)
+    );
+
+  //
+  // Create a effective mem title
+  //
+  HiiCreateTextOpCode (
+    StartOpCodeHandle,
+    STRING_TOKEN (STR_MEM_INFO_EFFECT_MEM),
+    STRING_TOKEN (STR_MEM_INFO_EFFECT_MEM),
+    STRING_TOKEN (STR_MEM_INFO_EFFECT_MEM_VALUE)
+    );
+
+  //
+  // Create a current speed title
+  //
+  HiiCreateTextOpCode (
+    StartOpCodeHandle,
+    STRING_TOKEN (STR_MEM_INFO_CURRENT_SPEED),
+    STRING_TOKEN (STR_MEM_INFO_CURRENT_SPEED),
+    STRING_TOKEN (STR_MEM_INFO_CURRENT_SPEED_VALUE)
+    );
+
+  HiiCreateOneOfOptionOpCode (
+    OptionsOpCodeHandle,
+    STRING_TOKEN (STR_MEM_INFO_SPEED_SELECT_VALUE0),
+    0,
+    EFI_IFR_NUMERIC_SIZE_4,
+    0
+    );
+
+  HiiCreateOneOfOptionOpCode (
+    OptionsOpCodeHandle,
+    STRING_TOKEN (STR_MEM_INFO_SPEED_SELECT_VALUE1),
+    0,
+    EFI_IFR_NUMERIC_SIZE_4,
+    2133
+    );
+
+  HiiCreateOneOfOptionOpCode (
+    OptionsOpCodeHandle,
+    STRING_TOKEN (STR_MEM_INFO_SPEED_SELECT_VALUE2),
+    0,
+    EFI_IFR_NUMERIC_SIZE_4,
+    2400
+    );
+
+  HiiCreateOneOfOptionOpCode (
+    OptionsOpCodeHandle,
+    STRING_TOKEN (STR_MEM_INFO_SPEED_SELECT_VALUE3),
+    0,
+    EFI_IFR_NUMERIC_SIZE_4,
+    2666
+    );
+
+  HiiCreateOneOfOptionOpCode (
+    OptionsOpCodeHandle,
+    STRING_TOKEN (STR_MEM_INFO_SPEED_SELECT_VALUE4),
+    0,
+    EFI_IFR_NUMERIC_SIZE_4,
+    2933
+    );
+
+  HiiCreateOneOfOptionOpCode (
+    OptionsOpCodeHandle,
+    STRING_TOKEN (STR_MEM_INFO_SPEED_SELECT_VALUE5),
+    0,
+    EFI_IFR_NUMERIC_SIZE_4,
+    3200
+    );
+
+  HiiCreateOneOfOpCode (
+    StartOpCodeHandle,                                   // Container for dynamic created opcodes
+    MEM_INFO_DDR_SPEED_SEL_QUESTION_ID,                  // Question ID (or call it "key")
+    MEM_INFO_VARSTORE_ID,                                // VarStore ID
+    (UINT16)MEM_INFO_DDR_SPEED_SEL_OFFSET,               // Offset in Buffer Storage
+    STRING_TOKEN (STR_MEM_INFO_SPEED_SELECT_PROMPT),     // Question prompt text
+    STRING_TOKEN (STR_MEM_INFO_SPEED_SELECT_HELP),       // Question help text
+    EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED, // Question flag
+    EFI_IFR_NUMERIC_SIZE_4,                              // Data type of Question Value
+    OptionsOpCodeHandle,                                 // Option Opcode list
+    NULL                                                 // Default Opcode is NULl
+    );
+
+  if (IsSlaveSocketActive ()) {
+    /* Display enable slave's 32bit region */
+    HiiCreateCheckBoxOpCode (
+      StartOpCodeHandle,                                    // Container for dynamic created opcodes
+      MEM_INFO_DDR_SLAVE_32BIT_QUESTION_ID,                 // Question ID
+      MEM_INFO_VARSTORE_ID,                                 // VarStore ID
+      (UINT16)MEM_INFO_ERR_SLAVE_32BIT_OFFSET,              // Offset in Buffer Storage
+      STRING_TOKEN (STR_MEM_INFO_ENABLE_32GB_SLAVE_PROMPT), // Question prompt text
+      STRING_TOKEN (STR_MEM_INFO_ENABLE_32GB_SLAVE_HELP),   // Question help text
+      EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED,
+      0,
+      NULL
+      );
+  }
+
+  HiiCreateOneOfOptionOpCode (
+    OptionsOpCodeHandle1,
+    STRING_TOKEN (STR_MEM_INFO_FGR_MODE_VALUE0),
+    0,
+    EFI_IFR_NUMERIC_SIZE_4,
+    0
+    );
+
+  HiiCreateOneOfOptionOpCode (
+    OptionsOpCodeHandle1,
+    STRING_TOKEN (STR_MEM_INFO_FGR_MODE_VALUE1),
+    0,
+    EFI_IFR_NUMERIC_SIZE_4,
+    1
+    );
+
+  HiiCreateOneOfOptionOpCode (
+    OptionsOpCodeHandle1,
+    STRING_TOKEN (STR_MEM_INFO_FGR_MODE_VALUE2),
+    0,
+    EFI_IFR_NUMERIC_SIZE_4,
+    2
+    );
+
+  HiiCreateOneOfOpCode (
+    StartOpCodeHandle,                                   // Container for dynamic created opcodes
+    MEM_INFO_FGR_MODE_QUESTION_ID,                       // Question ID (or call it "key")
+    MEM_INFO_VARSTORE_ID,                                // VarStore ID
+    (UINT16)MEM_INFO_FGR_MODE_OFFSET,                    // Offset in Buffer Storage
+    STRING_TOKEN (STR_MEM_INFO_FGR_MODE_PROMPT),         // Question prompt text
+    STRING_TOKEN (STR_MEM_INFO_FGR_MODE_HELP),           // Question help text
+    EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED, // Question flag
+    EFI_IFR_NUMERIC_SIZE_4,                              // Data type of Question Value
+    OptionsOpCodeHandle1,                                // Option Opcode list
+    NULL                                                 // Default Opcode is NULl
+    );
+
+  //
+  // Create a Goto OpCode to ras memory configuration
+  //
+  HiiCreateGotoOpCode (
+    StartOpCodeHandle,                                 // Container for dynamic created opcodes
+    MEM_INFO_FORM_PERFORMANCE_ID,                      // Target Form ID
+    STRING_TOKEN (STR_MEM_INFO_PERFORMANCE_FORM),      // Prompt text
+    STRING_TOKEN (STR_MEM_INFO_PERFORMANCE_FORM_HELP), // Help text
+    0,                                                 // Question flag
+    MEM_INFO_FORM_PERFORMANCE_QUESTION_ID              // Question ID
+    );
+
+  //
+  // Create a Goto OpCode to nvdimm-n configuration
+  //
+  HiiCreateGotoOpCode (
+    StartOpCodeHandle,                            // Container for dynamic created opcodes
+    MEM_INFO_FORM_NVDIMM_ID,                      // Target Form ID
+    STRING_TOKEN (STR_MEM_INFO_NVDIMM_FORM),      // Prompt text
+    STRING_TOKEN (STR_MEM_INFO_NVDIMM_FORM_HELP), // Help text
+    0,                                            // Question flag
+    MEM_INFO_FORM_NVDIMM_QUESTION_ID              // Question ID
+    );
+
+  //
+  // Display DIMM list info
+  //
+  HiiCreateSubTitleOpCode (
+    StartOpCodeHandle,
+    STRING_TOKEN (STR_MEM_INFO_DIMM_INFO),
+    0,
+    0,
+    0
+    );
+
+  for (Count = 0; Count < PlatformHob->DimmList.BoardDimmSlots; Count++) {
+    DimmInfo = &PlatformHob->DimmList.Dimm[Count].Info;
+    switch (DimmInfo->DimmType) {
+    case UDIMM:
+      UnicodeSPrint (Str, sizeof (Str), L"%s", L"UDIMM");
+      break;
+
+    case RDIMM:
+      UnicodeSPrint (Str, sizeof (Str), L"%s", L"RDIMM");
+      break;
+
+    case SODIMM:
+      UnicodeSPrint (Str, sizeof (Str), L"%s", L"SODIMM");
+      break;
+
+    case LRDIMM:
+      UnicodeSPrint (Str, sizeof (Str), L"%s", L"LRDIMM");
+      break;
+
+    case RSODIMM:
+      UnicodeSPrint (Str, sizeof (Str), L"%s", L"RSODIMM");
+      break;
+
+    case NVRDIMM:
+      UnicodeSPrint (Str, sizeof (Str), L"%s", L"NV-RDIMM");
+      break;
+
+    default:
+      UnicodeSPrint (Str, sizeof (Str), L"Unknown Type");
+    }
+    if (DimmInfo->DimmStatus == DIMM_INSTALLED_OPERATIONAL) {
+      UnicodeSPrint (Str1, sizeof (Str1), L"Slot %2d: %d GB %s Installed&Operational", Count + 1, DimmInfo->DimmSize, Str);
+    } else if (DimmInfo->DimmStatus == DIMM_NOT_INSTALLED) {
+      UnicodeSPrint (Str1, sizeof (Str1), L"Slot %2d: Not Installed", Count + 1, PlatformHob->DimmList.Dimm[Count].NodeId);
+    } else if (DimmInfo->DimmStatus == DIMM_INSTALLED_NONOPERATIONAL) {
+      UnicodeSPrint (Str1, sizeof (Str1), L"Slot %2d: Installed&Non-Operational", Count + 1, PlatformHob->DimmList.Dimm[Count].NodeId);
+    } else {
+      UnicodeSPrint (Str1, sizeof (Str1), L"Slot %2d: Installed&Failed", Count + 1, PlatformHob->DimmList.Dimm[Count].NodeId);
+    }
+
+    StringId = HiiSetString (PrivateData->HiiHandle, 0, Str1, NULL);
+
+    HiiCreateSubTitleOpCode (
+      StartOpCodeHandle,
+      StringId,
+      0,
+      0,
+      0
+      );
+  }
+
+  HiiUpdateForm (
+    PrivateData->HiiHandle,  // HII handle
+    &gMemInfoFormSetGuid,    // Formset GUID
+    MEM_INFO_FORM_ID,        // Form ID
+    StartOpCodeHandle,       // Label for where to insert opcodes
+    EndOpCodeHandle          // Insert data
+    );
+
+  HiiFreeOpCodeHandle (StartOpCodeHandle);
+  HiiFreeOpCodeHandle (EndOpCodeHandle);
+  HiiFreeOpCodeHandle (OptionsOpCodeHandle);
+
+  return Status;
+}
+
+EFI_STATUS
+MemInfoMainPerformanceScreen (
+  PLATFORM_INFO_HOB  *PlatformHob
+  )
+{
+  EFI_STATUS                   Status;
+  MEM_INFO_SCREEN_PRIVATE_DATA *PrivateData = mPrivateData;
+  VOID                         *StartOpCodeHandle;
+  VOID                         *OptionsEccOpCodeHandle, *OptionsScrubOpCodeHandle;
+  EFI_IFR_GUID_LABEL           *StartLabel;
+  VOID                         *EndOpCodeHandle;
+  EFI_IFR_GUID_LABEL           *EndLabel;
+  EFI_STRING_ID                StringId;
+  CHAR16                       Str[MAX_STRING_SIZE];
+  UINTN                        Idx;
+
+  Status = EFI_SUCCESS;
+
+  //
+  // Initialize the container for dynamic opcodes
+  //
+  StartOpCodeHandle = HiiAllocateOpCodeHandle ();
+  ASSERT (StartOpCodeHandle != NULL);
+
+  EndOpCodeHandle = HiiAllocateOpCodeHandle ();
+  ASSERT (EndOpCodeHandle != NULL);
+
+  //
+  // Create Hii Extend Label OpCode as the start opcode
+  //
+  StartLabel = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
+  StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
+  StartLabel->Number       = LABEL_UPDATE;
+
+  //
+  // Create Hii Extend Label OpCode as the end opcode
+  //
+  EndLabel = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
+  EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
+  EndLabel->Number       = LABEL_END;
+
+  /* Display ECC mode selection */
+  OptionsEccOpCodeHandle = HiiAllocateOpCodeHandle ();
+  ASSERT (OptionsEccOpCodeHandle != NULL);
+
+  UnicodeSPrint (Str, sizeof (Str), L"Disabled");
+  StringId = HiiSetString (PrivateData->HiiHandle, 0, Str, NULL);
+
+  HiiCreateOneOfOptionOpCode (
+    OptionsEccOpCodeHandle,
+    StringId,
+    0,
+    EFI_IFR_NUMERIC_SIZE_4,
+    0
+    );
+
+  UnicodeSPrint (Str, sizeof (Str), L"SECDED");
+  StringId = HiiSetString (PrivateData->HiiHandle, 0, Str, NULL);
+
+  HiiCreateOneOfOptionOpCode (
+    OptionsEccOpCodeHandle,
+    StringId,
+    0,
+    EFI_IFR_NUMERIC_SIZE_4,
+    1
+    );
+
+  UnicodeSPrint (Str, sizeof (Str), L"Symbol");
+  StringId = HiiSetString (PrivateData->HiiHandle, 0, Str, NULL);
+
+  HiiCreateOneOfOptionOpCode (
+    OptionsEccOpCodeHandle,
+    StringId,
+    0,
+    EFI_IFR_NUMERIC_SIZE_4,
+    2
+    );
+
+  HiiCreateOneOfOpCode (
+    StartOpCodeHandle,                                   // Container for dynamic created opcodes
+    MEM_INFO_FORM_PERFORMANCE_ECC_QUESTION_ID,           // Question ID (or call it "key")
+    MEM_INFO_VARSTORE_ID,                                // VarStore ID
+    (UINT16)MEM_INFO_ECC_MODE_SEL_OFFSET,                // Offset in Buffer Storage
+    STRING_TOKEN (STR_MEM_INFO_ENABLE_ECC_PROMPT),       // Question prompt text
+    STRING_TOKEN (STR_MEM_INFO_ENABLE_ECC_HELP),         // Question help text
+    EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED, // Question flag
+    EFI_IFR_NUMERIC_SIZE_4,                              // Data type of Question Value
+    OptionsEccOpCodeHandle,                              // Option Opcode list
+    NULL                                                 // Default Opcode is NULl
+    );
+
+  /*
+   * Display ErrCtrl options
+   */
+  HiiCreateCheckBoxOpCode (
+    StartOpCodeHandle,                                    // Container for dynamic created opcodes
+    MEM_INFO_FORM_PERFORMANCE_ERR_CTRL_DE_QUESTION_ID,    // Question ID
+    MEM_INFO_VARSTORE_ID,                                 // VarStore ID
+    (UINT16)MEM_INFO_ERR_CTRL_DE_MODE_SEL_OFFSET,         // Offset in Buffer Storage
+    STRING_TOKEN (STR_MEM_INFO_ENABLE_ERRCTRL_DE_PROMPT), // Question prompt text
+    STRING_TOKEN (STR_MEM_INFO_ENABLE_ERRCTRL_DE_HELP),   // Question help text
+    EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED,
+    0,
+    NULL
+    );
+
+  HiiCreateCheckBoxOpCode (
+    StartOpCodeHandle,                                    // Container for dynamic created opcodes
+    MEM_INFO_FORM_PERFORMANCE_ERR_CTRL_FI_QUESTION_ID,    // Question ID
+    MEM_INFO_VARSTORE_ID,                                 // VarStore ID
+    (UINT16)MEM_INFO_ERR_CTRL_FI_MODE_SEL_OFFSET,         // Offset in Buffer Storage
+    STRING_TOKEN (STR_MEM_INFO_ENABLE_ERRCTRL_FI_PROMPT), // Question prompt text
+    STRING_TOKEN (STR_MEM_INFO_ENABLE_ERRCTRL_FI_HELP),   // Question help text
+    EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED,
+    0,
+    NULL
+    );
+
+  /* Display Scrub Patrol selection */
+  OptionsScrubOpCodeHandle = HiiAllocateOpCodeHandle ();
+  ASSERT (OptionsScrubOpCodeHandle != NULL);
+
+  UnicodeSPrint (Str, sizeof (Str), L"Disabled");
+  StringId = HiiSetString (PrivateData->HiiHandle, 0, Str, NULL);
+
+  HiiCreateOneOfOptionOpCode (
+    OptionsScrubOpCodeHandle,
+    StringId,
+    0,
+    EFI_IFR_NUMERIC_SIZE_4,
+    0
+    );
+
+  for (Idx = 1; Idx <= 24; Idx++) {
+    UnicodeSPrint (Str, sizeof (Str), L"%d", Idx);
+    StringId = HiiSetString (
+                 PrivateData->HiiHandle,
+                 0,
+                 Str,
+                 NULL
+                 );
+    HiiCreateOneOfOptionOpCode (
+      OptionsScrubOpCodeHandle,
+      StringId,
+      0,
+      EFI_IFR_NUMERIC_SIZE_4,
+      Idx
+      );
+  }
+
+  HiiCreateOneOfOpCode (
+    StartOpCodeHandle,                                   // Container for dynamic created opcodes
+    MEM_INFO_DDR_SCRUB_PATROL_QUESTION_ID,               // Question ID (or call it "key")
+    MEM_INFO_VARSTORE_ID,                                // VarStore ID
+    (UINT16)MEM_INFO_DDR_SCRUB_OFFSET,                   // Offset in Buffer Storage
+    STRING_TOKEN (STR_MEM_INFO_ENABLE_SCRUB),            // Question prompt text
+    STRING_TOKEN (STR_MEM_INFO_ENABLE_SCRUB_HELP),       // Question help text
+    EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED, // Question flag
+    EFI_IFR_NUMERIC_SIZE_4,                              // Data type of Question Value
+    OptionsScrubOpCodeHandle,                            // Option Opcode list
+    NULL                                                 // Default Opcode is NULl
+    );
+
+  /*
+   * Display Demand Scrub options
+   */
+  HiiCreateCheckBoxOpCode (
+    StartOpCodeHandle,                                      // Container for dynamic created opcodes
+    MEM_INFO_DDR_DEMAND_SCRUB_QUESTION_ID,                  // Question ID
+    MEM_INFO_VARSTORE_ID,                                   // VarStore ID
+    (UINT16)MEM_INFO_DDR_DEMAND_SCRUB_OFFSET,               // Offset in Buffer Storage
+    STRING_TOKEN (STR_MEM_INFO_ENABLE_DEMAND_SCRUB_PROMPT), // Question prompt text
+    STRING_TOKEN (STR_MEM_INFO_ENABLE_DEMAND_SCRUB_HELP),   // Question help text
+    EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED,
+    0,
+    NULL
+    );
+
+  /*
+   * Display Write CRC options
+   */
+  HiiCreateCheckBoxOpCode (
+    StartOpCodeHandle,                                   // Container for dynamic created opcodes
+    MEM_INFO_DDR_WRITE_CRC_QUESTION_ID,                  // Question ID
+    MEM_INFO_VARSTORE_ID,                                // VarStore ID
+    (UINT16)MEM_INFO_DDR_WRITE_CRC_OFFSET,               // Offset in Buffer Storage
+    STRING_TOKEN (STR_MEM_INFO_ENABLE_WRITE_CRC_PROMPT), // Question prompt text
+    STRING_TOKEN (STR_MEM_INFO_ENABLE_WRITE_CRC_HELP),   // Question help text
+    EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED,
+    0,
+    NULL
+    );
+
+  /*
+   * Display CVE-2020-10255 options
+   */
+  HiiCreateCheckBoxOpCode (
+    StartOpCodeHandle,                                 // Container for dynamic created opcodes
+    MEM_INFO_REFRESH2X_MODE_QUESTION_ID,               // Question ID
+    MEM_INFO_VARSTORE_ID,                              // VarStore ID
+    (UINT16)MEM_INFO_REFRESH2X_MODE_OFFSET,            // Offset in Buffer Storage
+    STRING_TOKEN (STR_MEM_INFO_REFRESH2X_MODE_PROMPT), // Question prompt text
+    STRING_TOKEN (STR_MEM_INFO_REFRESH2X_MODE_HELP),   // Question help text
+    EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED,
+    0,
+    NULL
+    );
+
+  HiiUpdateForm (
+    PrivateData->HiiHandle,              // HII handle
+    &gMemInfoFormSetGuid,                // Formset GUID
+    MEM_INFO_FORM_PERFORMANCE_ID,        // Form ID
+    StartOpCodeHandle,                   // Label for where to insert opcodes
+    EndOpCodeHandle                      // Insert data
+    );
+
+  HiiFreeOpCodeHandle (StartOpCodeHandle);
+  HiiFreeOpCodeHandle (EndOpCodeHandle);
+  HiiFreeOpCodeHandle (OptionsEccOpCodeHandle);
+  HiiFreeOpCodeHandle (OptionsScrubOpCodeHandle);
+
+  return Status;
+}
+
+EFI_STATUS
+MemInfoMainNvdimmScreen (
+  PLATFORM_INFO_HOB  *PlatformHob
+  )
+{
+  EFI_STATUS                   Status;
+  MEM_INFO_SCREEN_PRIVATE_DATA *PrivateData;
+  VOID                         *StartOpCodeHandle;
+  VOID                         *OptionsOpCodeHandle;
+  EFI_IFR_GUID_LABEL           *StartLabel;
+  VOID                         *EndOpCodeHandle;
+  EFI_IFR_GUID_LABEL           *EndLabel;
+  CHAR16                       Str[MAX_STRING_SIZE];
+
+  Status = EFI_SUCCESS;
+  PrivateData = mPrivateData;
+
+  if (PlatformHob == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Initialize the container for dynamic opcodes
+  //
+  StartOpCodeHandle = HiiAllocateOpCodeHandle ();
+  ASSERT (StartOpCodeHandle != NULL);
+
+  EndOpCodeHandle = HiiAllocateOpCodeHandle ();
+  ASSERT (EndOpCodeHandle != NULL);
+
+  //
+  // Create Hii Extend Label OpCode as the start opcode
+  //
+  StartLabel = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode (
+                                       StartOpCodeHandle,
+                                       &gEfiIfrTianoGuid,
+                                       NULL,
+                                       sizeof (EFI_IFR_GUID_LABEL)
+                                       );
+  StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
+  StartLabel->Number       = LABEL_UPDATE;
+
+  //
+  // Create Hii Extend Label OpCode as the end opcode
+  //
+  EndLabel = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode (
+                                     EndOpCodeHandle,
+                                     &gEfiIfrTianoGuid,
+                                     NULL,
+                                     sizeof (EFI_IFR_GUID_LABEL)
+                                     );
+  EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
+  EndLabel->Number       = LABEL_END;
+
+  //
+  // Update Current NVDIMM-N Mode title Socket0
+  //
+  switch (PlatformHob->DramInfo.NvdimmMode[0]) {
+  case 0:
+    UnicodeSPrint (Str, sizeof (Str), L"%s", L"Non-NVDIMM");
+    break;
+
+  case 1:
+    UnicodeSPrint (Str, sizeof (Str), L"%s", L"Non-Hashed");
+    break;
+
+  case 2:
+    UnicodeSPrint (Str, sizeof (Str), L"%s", L"Hashed");
+    break;
+
+  default:
+    UnicodeSPrint (Str, sizeof (Str), L"%s", L"Unknown");
+    break;
+  }
+
+  HiiSetString (
+    PrivateData->HiiHandle,
+    STRING_TOKEN (STR_MEM_INFO_NVDIMM_CUR_MODE_SK0_VALUE),
+    Str,
+    NULL
+    );
+
+  HiiCreateTextOpCode (
+    StartOpCodeHandle,
+    STRING_TOKEN (STR_MEM_INFO_NVDIMM_CUR_MODE_SK0),
+    STRING_TOKEN (STR_MEM_INFO_NVDIMM_CUR_MODE_SK0),
+    STRING_TOKEN (STR_MEM_INFO_NVDIMM_CUR_MODE_SK0_VALUE)
+    );
+
+  //
+  // Update Current NVDIMM-N Mode title Socket1
+  //
+  if (IsSlaveSocketActive ()) {
+    switch (PlatformHob->DramInfo.NvdimmMode[1]) {
+    case 0:
+      UnicodeSPrint (Str, sizeof (Str), L"%s", L"Non-NVDIMM");
+      break;
+
+    case 1:
+      UnicodeSPrint (Str, sizeof (Str), L"%s", L"Non-Hashed");
+      break;
+
+    case 2:
+      UnicodeSPrint (Str, sizeof (Str), L"%s", L"Hashed");
+      break;
+
+    default:
+      UnicodeSPrint (Str, sizeof (Str), L"%s", L"Unknown");
+      break;
+    }
+
+    HiiSetString (
+      PrivateData->HiiHandle,
+      STRING_TOKEN (STR_MEM_INFO_NVDIMM_CUR_MODE_SK1_VALUE),
+      Str,
+      NULL
+      );
+
+    HiiCreateTextOpCode (
+      StartOpCodeHandle,
+      STRING_TOKEN (STR_MEM_INFO_NVDIMM_CUR_MODE_SK1),
+      STRING_TOKEN (STR_MEM_INFO_NVDIMM_CUR_MODE_SK1),
+      STRING_TOKEN (STR_MEM_INFO_NVDIMM_CUR_MODE_SK1_VALUE)
+      );
+  }
+  //
+  // Create Option OpCode to NVDIMM-N Mode Selection
+  //
+  OptionsOpCodeHandle = HiiAllocateOpCodeHandle ();
+  ASSERT (OptionsOpCodeHandle != NULL);
+
+  //
+  // Create OpCode to NVDIMM-N Mode Selection
+  //
+  HiiCreateOneOfOptionOpCode (
+    OptionsOpCodeHandle,
+    STRING_TOKEN (STR_MEM_INFO_NVDIMM_MODE_SEL_VALUE0),
+    0,
+    EFI_IFR_NUMERIC_SIZE_4,
+    0
+    );
+
+  HiiCreateOneOfOptionOpCode (
+    OptionsOpCodeHandle,
+    STRING_TOKEN (STR_MEM_INFO_NVDIMM_MODE_SEL_VALUE1),
+    0,
+    EFI_IFR_NUMERIC_SIZE_4,
+    1
+    );
+
+  HiiCreateOneOfOptionOpCode (
+    OptionsOpCodeHandle,
+    STRING_TOKEN (STR_MEM_INFO_NVDIMM_MODE_SEL_VALUE2),
+    0,
+    EFI_IFR_NUMERIC_SIZE_4,
+    2
+    );
+
+  HiiCreateOneOfOptionOpCode (
+    OptionsOpCodeHandle,
+    STRING_TOKEN (STR_MEM_INFO_NVDIMM_MODE_SEL_VALUE3),
+    0,
+    EFI_IFR_NUMERIC_SIZE_4,
+    3
+    );
+
+  HiiCreateOneOfOpCode (
+    StartOpCodeHandle,                                   // Container for dynamic created opcodes
+    MEM_INFO_FORM_NVDIMM_MODE_SEL_QUESTION_ID,           // Question ID (or call it "key")
+    MEM_INFO_VARSTORE_ID,                                // VarStore ID
+    (UINT16)MEM_INFO_NVDIMM_MODE_SEL_OFFSET,             // Offset in Buffer Storage
+    STRING_TOKEN (STR_MEM_INFO_NVDIMM_MODE_SEL_PROMPT),  // Question prompt text
+    STRING_TOKEN (STR_MEM_INFO_NVDIMM_MODE_SEL_HELP),    // Question help text
+    EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED, // Question flag
+    EFI_IFR_NUMERIC_SIZE_4,                              // Data type of Question Value
+    OptionsOpCodeHandle,                                 // Option Opcode list
+    NULL                                                 // Default Opcode is NULl
+    );
+
+  HiiUpdateForm (
+    PrivateData->HiiHandle,              // HII handle
+    &gMemInfoFormSetGuid,                // Formset GUID
+    MEM_INFO_FORM_NVDIMM_ID,             // Form ID
+    StartOpCodeHandle,                   // Label for where to insert opcodes
+    EndOpCodeHandle                      // Insert data
+    );
+
+  HiiFreeOpCodeHandle (StartOpCodeHandle);
+  HiiFreeOpCodeHandle (EndOpCodeHandle);
+  HiiFreeOpCodeHandle (OptionsOpCodeHandle);
+
+  return Status;
+}
+
+/**
+  This function sets up the first elements of the form.
+  @param  PrivateData            Private data.
+  @retval EFI_SUCCESS            The form is set up successfully.
+**/
+EFI_STATUS
+MemInfoScreenSetup (
+  VOID
+  )
+{
+  EFI_STATUS         Status;
+  VOID               *Hob;
+  PLATFORM_INFO_HOB  *PlatformHob;
+
+  /* Get the Platform HOB */
+  Hob = GetFirstGuidHob (&gPlatformHobGuid);
+  if (Hob == NULL) {
+    return EFI_DEVICE_ERROR;
+  }
+  PlatformHob = (PLATFORM_INFO_HOB *)GET_GUID_HOB_DATA (Hob);
+
+  Status = MemInfoMainScreen (PlatformHob);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = MemInfoMainPerformanceScreen (PlatformHob);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = MemInfoMainNvdimmScreen (PlatformHob);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+MemInfoScreenInitialize (
+  IN EFI_HANDLE       ImageHandle,
+  IN EFI_SYSTEM_TABLE *SystemTable
+  )
+{
+  EFI_STATUS                      Status;
+  EFI_HII_HANDLE                  HiiHandle;
+  EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
+  BOOLEAN                         ActionFlag;
+  EFI_STRING                      ConfigRequestHdr;
+
+  //
+  // Initialize driver private data
+  //
+  mPrivateData = AllocateZeroPool (sizeof (MEM_INFO_SCREEN_PRIVATE_DATA));
+  if (mPrivateData == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  mPrivateData->Signature = MEM_INFO_SCREEN_PRIVATE_DATA_SIGNATURE;
+
+  mPrivateData->ConfigAccess.ExtractConfig = ExtractConfig;
+  mPrivateData->ConfigAccess.RouteConfig = RouteConfig;
+  mPrivateData->ConfigAccess.Callback = DriverCallback;
+
+  //
+  // Locate ConfigRouting protocol
+  //
+  Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **)&HiiConfigRouting);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+  mPrivateData->HiiConfigRouting = HiiConfigRouting;
+
+  Status = gBS->InstallMultipleProtocolInterfaces (
+                  &DriverHandle,
+                  &gEfiDevicePathProtocolGuid,
+                  &mHiiVendorDevicePath,
+                  &gEfiHiiConfigAccessProtocolGuid,
+                  &mPrivateData->ConfigAccess,
+                  NULL
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  mPrivateData->DriverHandle = DriverHandle;
+
+  //
+  // Publish our HII data
+  //
+  HiiHandle = HiiAddPackages (
+                &gMemInfoFormSetGuid,
+                DriverHandle,
+                MemInfoDxeStrings,
+                VfrBin,
+                NULL
+                );
+  if (HiiHandle == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  mPrivateData->HiiHandle = HiiHandle;
+
+  //
+  // Try to read NV config EFI variable first
+  //
+  ConfigRequestHdr = HiiConstructConfigHdr (
+                       &gMemInfoFormSetGuid,
+                       MEM_INFO_VARSTORE_NAME,
+                       DriverHandle
+                       );
+  ASSERT (ConfigRequestHdr != NULL);
+
+  //
+  // Validate Current Setting
+  //
+  ActionFlag = HiiValidateSettings (ConfigRequestHdr);
+  if (!ActionFlag) {
+    MemInfoScreenUnload (ImageHandle);
+    return EFI_INVALID_PARAMETER;
+  }
+  FreePool (ConfigRequestHdr);
+
+  Status = MemInfoScreenSetup ();
+  ASSERT_EFI_ERROR (Status);
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+MemInfoScreenUnload (
+  IN EFI_HANDLE ImageHandle
+  )
+{
+  ASSERT (mPrivateData != NULL);
+
+  if (DriverHandle != NULL) {
+    gBS->UninstallMultipleProtocolInterfaces (
+           DriverHandle,
+           &gEfiDevicePathProtocolGuid,
+           &mHiiVendorDevicePath,
+           &gEfiHiiConfigAccessProtocolGuid,
+           &mPrivateData->ConfigAccess,
+           NULL
+           );
+    DriverHandle = NULL;
+  }
+
+  if (mPrivateData->HiiHandle != NULL) {
+    HiiRemovePackages (mPrivateData->HiiHandle);
+  }
+
+  FreePool (mPrivateData);
+  mPrivateData = NULL;
+
+  return EFI_SUCCESS;
+}
diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoDxe.uni b/Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoDxe.uni
new file mode 100644
index 000000000000..a8c7cb99d6a7
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoDxe.uni
@@ -0,0 +1,9 @@
+//
+// Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+
+#string STR_MODULE_ABSTRACT             #language en-US "An Altra DDR screen setup driver"
+
+#string STR_MODULE_DESCRIPTION          #language en-US "This driver exposes a screen setup for DDR information and configuration."
diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoDxeExtra.uni b/Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoDxeExtra.uni
new file mode 100644
index 000000000000..f44f210594be
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoDxeExtra.uni
@@ -0,0 +1,9 @@
+//
+// Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+
+#string STR_PROPERTIES_MODULE_NAME
+#language en-US
+"Ampere Altra MemInfo DXE Driver"
diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoScreenStrings.uni b/Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoScreenStrings.uni
new file mode 100644
index 000000000000..d170f9ee7313
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoScreenStrings.uni
@@ -0,0 +1,64 @@
+//
+// Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+
+#langdef   en-US "English"    // English
+
+#string STR_MEM_INFO_FORM                   #language en-US "Memory Configuration"
+#string STR_MEM_INFO_FORM_HELP              #language en-US "Memory Configuration"
+#string STR_MEM_INFO_TOTAL_MEM              #language en-US "Total Memory"
+#string STR_MEM_INFO_TOTAL_MEM_VALUE        #language en-US "0 GB"
+#string STR_MEM_INFO_EFFECT_MEM             #language en-US "Effective Memory"
+#string STR_MEM_INFO_EFFECT_MEM_VALUE       #language en-US "0 MB"
+#string STR_MEM_INFO_CURRENT_SPEED          #language en-US "Memory Speed"
+#string STR_MEM_INFO_CURRENT_SPEED_VALUE    #language en-US "0 MHz"
+#string STR_MEM_INFO_SPEED_SELECT_PROMPT    #language en-US "Memory Operating Speed Selection"
+#string STR_MEM_INFO_SPEED_SELECT_HELP      #language en-US "Force specific Memory Operating Speed or use Auto setting."
+#string STR_MEM_INFO_SPEED_SELECT_VALUE0    #language en-US "Auto"
+#string STR_MEM_INFO_SPEED_SELECT_VALUE1    #language en-US "2133"
+#string STR_MEM_INFO_SPEED_SELECT_VALUE2    #language en-US "2400"
+#string STR_MEM_INFO_SPEED_SELECT_VALUE3    #language en-US "2666"
+#string STR_MEM_INFO_SPEED_SELECT_VALUE4    #language en-US "2933"
+#string STR_MEM_INFO_SPEED_SELECT_VALUE5    #language en-US "3200"
+#string STR_MEM_INFO_DIMM_INFO              #language en-US "DIMM Information"
+
+#string STR_MEM_INFO_PERFORMANCE_FORM              #language en-US "Memory RAS and Performance Configuration"
+#string STR_MEM_INFO_PERFORMANCE_FORM_HELP         #language en-US "Displays and provides options to change the memory RAS and performance Settings"
+#string STR_MEM_INFO_ENABLE_ECC_PROMPT             #language en-US "ECC mode"
+#string STR_MEM_INFO_ENABLE_ECC_HELP               #language en-US "ECC mode: Disabled, SECDED or Symbol"
+#string STR_MEM_INFO_ENABLE_ERRCTRL_DE_PROMPT      #language en-US "Defer uncorrectable read errors"
+#string STR_MEM_INFO_ENABLE_ERRCTRL_DE_HELP        #language en-US "When enabled the DMC defers uncorrectable read errors to the consumer by sending an OK response and setting the TXDAT poison flag on the CHI-B interconnect. If this bit is clear the DMC defaults to non-deferred behavior when encountering an unrecoverable error"
+#string STR_MEM_INFO_ENABLE_ERRCTRL_FI_PROMPT      #language en-US "Fault handling interrupt"
+#string STR_MEM_INFO_ENABLE_ERRCTRL_FI_HELP        #language en-US "Enables fault handling interrupt. The fault handling interrupt is raised to give notice that ECC fault has been recorded"
+#string STR_MEM_INFO_ENABLE_SCRUB                  #language en-US "Scrub Patrol duration (hour)"
+#string STR_MEM_INFO_ENABLE_SCRUB_HELP             #language en-US "Select duration (hour) for Scrub Patrol"
+#string STR_MEM_INFO_ENABLE_DEMAND_SCRUB_PROMPT    #language en-US "Demand scrub"
+#string STR_MEM_INFO_ENABLE_DEMAND_SCRUB_HELP      #language en-US "Enable/Disable the ability to write corrected data back to the memory once a correctable error is detected"
+#string STR_MEM_INFO_ENABLE_WRITE_CRC_PROMPT       #language en-US "Write CRC"
+#string STR_MEM_INFO_ENABLE_WRITE_CRC_HELP         #language en-US "Enable/Disable Cyclic Redundancy Check (CRC) functionality on write data. Be noted that enabling CRC will degrade Write bandwidth"
+
+
+#string STR_MEM_INFO_ENABLE_32GB_SLAVE_PROMPT      #language en-US "Enable Slave 32bit memory region"
+#string STR_MEM_INFO_ENABLE_32GB_SLAVE_HELP        #language en-US "Enables 32bit memory region (2GB) for slave socket"
+#string STR_MEM_INFO_FGR_MODE_PROMPT               #language en-US "Fine Granularity Refresh (FGR)"
+#string STR_MEM_INFO_FGR_MODE_VALUE0               #language en-US "1x"
+#string STR_MEM_INFO_FGR_MODE_VALUE1               #language en-US "2x"
+#string STR_MEM_INFO_FGR_MODE_VALUE2               #language en-US "4x"
+#string STR_MEM_INFO_FGR_MODE_HELP                 #language en-US "Select DDR Fine Granularity Refresh (FGR) mode 1x/2x/4x"
+#string STR_MEM_INFO_REFRESH2X_MODE_PROMPT         #language en-US "CVE-2020-10255 mitigation"
+#string STR_MEM_INFO_REFRESH2X_MODE_HELP           #language en-US "Enable mitigation for CVE-2020-10255, TRRespass"
+
+#string STR_MEM_INFO_NVDIMM_FORM                   #language en-US "NVDIMM-N Configuration"
+#string STR_MEM_INFO_NVDIMM_FORM_HELP              #language en-US "Displays and provides options to change the NVDIMM-N Settings"
+#string STR_MEM_INFO_NVDIMM_CUR_MODE_SK0           #language en-US "Socket0 Configured Mode"
+#string STR_MEM_INFO_NVDIMM_CUR_MODE_SK1           #language en-US "Socket1 Configured Mode"
+#string STR_MEM_INFO_NVDIMM_CUR_MODE_SK0_VALUE     #language en-US "Non-NVDIMM"
+#string STR_MEM_INFO_NVDIMM_CUR_MODE_SK1_VALUE     #language en-US "Non-NVDIMM"
+#string STR_MEM_INFO_NVDIMM_MODE_SEL_PROMPT        #language en-US "Mode Selection"
+#string STR_MEM_INFO_NVDIMM_MODE_SEL_VALUE0        #language en-US "Non-NVDIMM"
+#string STR_MEM_INFO_NVDIMM_MODE_SEL_VALUE1        #language en-US "Non-Hashed"
+#string STR_MEM_INFO_NVDIMM_MODE_SEL_VALUE2        #language en-US "Hashed"
+#string STR_MEM_INFO_NVDIMM_MODE_SEL_VALUE3        #language en-US "Auto"
+#string STR_MEM_INFO_NVDIMM_MODE_SEL_HELP          #language en-US "Select NVDIMM-N Mode (Non-NVDIMM/Non-Hashed/Hashed/Auto)"
-- 
2.17.1



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






More information about the edk2-devel-archive mailing list