public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Leif Lindholm" <leif@nuviainc.com>
To: Nhi Pham <nhi@os.amperecomputing.com>
Cc: devel@edk2.groups.io, patches@amperecomputing.com,
	vunguyen@os.amperecomputing.com,
	Thang Nguyen <thang@os.amperecomputing.com>,
	Chuong Tran <chuong@os.amperecomputing.com>,
	Phong Vo <phong@os.amperecomputing.com>,
	Michael D Kinney <michael.d.kinney@intel.com>,
	Ard Biesheuvel <ardb+tianocore@kernel.org>,
	Nate DeSimone <nathaniel.l.desimone@intel.com>
Subject: Re: [edk2-platforms][PATCH v4 27/31] AmpereAltraPkg: Add configuration screen for Memory
Date: Tue, 26 Oct 2021 13:58:48 +0100	[thread overview]
Message-ID: <20211026125848.plku2zdywmtyd3lm@leviathan> (raw)
In-Reply-To: <20211022061809.31087-28-nhi@os.amperecomputing.com>

On Fri, Oct 22, 2021 at 13:18:05 +0700, Nhi Pham wrote:
> From: Vu Nguyen <vunguyen@os.amperecomputing.com>
> 
> Provide memory screen with below info:
> * Memory total capacity
> * Memory RAS and Performance Configuration
> * Per DIMM Information
> 
> Cc: Thang Nguyen <thang@os.amperecomputing.com>
> Cc: Chuong Tran <chuong@os.amperecomputing.com>
> Cc: Phong Vo <phong@os.amperecomputing.com>
> Cc: Leif Lindholm <leif@nuviainc.com>
> Cc: Michael D Kinney <michael.d.kinney@intel.com>
> Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
> Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
> 
> Signed-off-by: Nhi Pham <nhi@os.amperecomputing.com>

Acked-by: Leif Lindholm <leif@nuviainc.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             |  159 +++
>  Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoScreenNVDataStruct.h |   47 +
>  Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoScreenVfr.vfr        |   62 +
>  Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoNvramLib.c           |  394 ++++++
>  Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoScreen.c             | 1395 ++++++++++++++++++++
>  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, 2200 insertions(+)
> 
> diff --git a/Platform/Ampere/JadePkg/Jade.dsc b/Platform/Ampere/JadePkg/Jade.dsc
> index deddd3b5fdde..5cebd1e9d0c3 100644
> --- a/Platform/Ampere/JadePkg/Jade.dsc
> +++ b/Platform/Ampere/JadePkg/Jade.dsc
> @@ -187,3 +187,4 @@ [Components.common]
>    #
>    Silicon/Ampere/AmpereAltraPkg/Drivers/RootComplexConfigDxe/RootComplexConfigDxe.inf
>    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 672b594cca0c..798f499c98ab 100644
> --- a/Platform/Ampere/JadePkg/Jade.fdf
> +++ b/Platform/Ampere/JadePkg/Jade.fdf
> @@ -357,5 +357,6 @@ [FV.FvMain]
>    #
>    INF Silicon/Ampere/AmpereAltraPkg/Drivers/RootComplexConfigDxe/RootComplexConfigDxe.inf
>    INF Silicon/Ampere/AmpereAltraPkg/Drivers/PlatformInfoDxe/PlatformInfoDxe.inf
> +  INF Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoDxe.inf
>  
>  !include Silicon/Ampere/AmpereSiliconPkg/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..a608133deb5b
> --- /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
> +  MemInfoScreenNVDataStruct.h
> +  MemInfoScreenVfr.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
> +  gPlatformInfoHobGuid
> +
> +[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..9dce952c9932
> --- /dev/null
> +++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoScreen.h
> @@ -0,0 +1,159 @@
> +/** @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 <Library/DebugLib.h>
> +#include <Protocol/HiiConfigAccess.h>
> +#include <Protocol/HiiConfigKeyword.h>
> +#include <Protocol/HiiConfigRouting.h>
> +#include <Protocol/HiiDatabase.h>
> +#include <Protocol/HiiString.h>
> +
> +#include "MemInfoScreenNVDataStruct.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 MemInfoScreenVfrBin[];
> +
> +//
> +// 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[];
> +
> +typedef enum {
> +  EccDisabled = 0,
> +  EccSecded,
> +  EccSymbol,
> +  EccMax
> +} DDR_ECC_MODE;
> +
> +typedef enum {
> +  ErrCtlrDeDisable = 0,
> +  ErrCtlrDeEnable,
> +  ErrCtlrDeMax
> +} DDR_ERROR_CTRL_MODE_DE;
> +
> +typedef enum {
> +  ErrCtlrFiDisable = 0,
> +  ErrCtlrFiEnable,
> +  ErrCtlrFiMax
> +} DDR_ERROR_CTRL_MODE_FI;
> +
> +#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 MAX_NUMBER_OF_HOURS_IN_A_DAY      24
> +
> +#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/MemInfoScreenNVDataStruct.h b/Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoScreenNVDataStruct.h
> new file mode 100644
> index 000000000000..75960c367880
> --- /dev/null
> +++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoScreenNVDataStruct.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 MEM_INFO_SCREEN_NV_DATA_STRUCT_H_
> +#define MEM_INFO_SCREEN_NV_DATA_STRUCT_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/MemInfoScreenVfr.vfr b/Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoScreenVfr.vfr
> new file mode 100644
> index 000000000000..e3d7aa0c44bd
> --- /dev/null
> +++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoScreenVfr.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 "MemInfoScreenNVDataStruct.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..32b8c9f416b8
> --- /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 = EccSecded; /* 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 = ErrCtlrDeEnable;
> +    VarStoreConfig->ErrCtrl_FI = ErrCtlrFiEnable;
> +  } 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..4f75e1625de9
> --- /dev/null
> +++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoScreen.c
> @@ -0,0 +1,1395 @@
> +/** @file
> +
> +  Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include <Guid/MdeModuleHii.h>
> +#include <Guid/PlatformInfoHob.h>
> +#include <Library/AmpereCpuLib.h>
> +#include <Library/BaseLib.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 "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 = EccSecded;
> +      break;
> +
> +    case MEM_INFO_FORM_PERFORMANCE_ERR_CTRL_DE_QUESTION_ID:
> +      //
> +      // ErrCtrl_DE default to be enabled
> +      //
> +      Value->u32 = ErrCtlrDeEnable;
> +      break;
> +
> +    case MEM_INFO_FORM_PERFORMANCE_ERR_CTRL_FI_QUESTION_ID:
> +      //
> +      // ErrCtrl_FI default to be enabled
> +      //
> +      Value->u32 = ErrCtlrDeEnable;
> +      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
> +UpdateMemInfo (
> +  PLATFORM_INFO_HOB  *PlatformHob
> +  )
> +{
> +  MEM_INFO_SCREEN_PRIVATE_DATA *PrivateData = mPrivateData;
> +  CHAR16                       Str[MAX_STRING_SIZE];
> +  EFI_HOB_RESOURCE_DESCRIPTOR  *ResHob;
> +  UINT64                       Size;
> +
> +  /* 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
> +    );
> +
> +  return EFI_SUCCESS;
> +}
> +
> +EFI_STATUS
> +AddMemorySpeedSelection (
> +  PLATFORM_INFO_HOB  *PlatformHob,
> +  VOID               *StartOpCodeHandle
> +  )
> +{
> +  VOID  *OptionsOpCodeHandle;
> +
> +  //
> +  // Create Option OpCode to display speed configuration
> +  //
> +  OptionsOpCodeHandle = HiiAllocateOpCodeHandle ();
> +  ASSERT (OptionsOpCodeHandle != NULL);
> +
> +  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
> +    );
> +
> +  HiiFreeOpCodeHandle (OptionsOpCodeHandle);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +EFI_STATUS
> +AddFgrModeSelection (
> +  PLATFORM_INFO_HOB  *PlatformHob,
> +  VOID               *StartOpCodeHandle
> +  )
> +{
> +  VOID  *OptionsOpCodeHandle;
> +
> +  //
> +  // Create Option OpCode to display FGR mode configuration
> +  //
> +  OptionsOpCodeHandle = HiiAllocateOpCodeHandle ();
> +  ASSERT (OptionsOpCodeHandle != NULL);
> +
> +  HiiCreateOneOfOptionOpCode (
> +    OptionsOpCodeHandle,
> +    STRING_TOKEN (STR_MEM_INFO_FGR_MODE_VALUE0),
> +    0,
> +    EFI_IFR_NUMERIC_SIZE_4,
> +    0
> +    );
> +
> +  HiiCreateOneOfOptionOpCode (
> +    OptionsOpCodeHandle,
> +    STRING_TOKEN (STR_MEM_INFO_FGR_MODE_VALUE1),
> +    0,
> +    EFI_IFR_NUMERIC_SIZE_4,
> +    1
> +    );
> +
> +  HiiCreateOneOfOptionOpCode (
> +    OptionsOpCodeHandle,
> +    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
> +    OptionsOpCodeHandle,                                // Option Opcode list
> +    NULL                                                 // Default Opcode is NULl
> +    );
> +
> +  HiiFreeOpCodeHandle (OptionsOpCodeHandle);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +EFI_STATUS
> +AddDimmListInfo (
> +  PLATFORM_INFO_HOB  *PlatformHob,
> +  VOID               *StartOpCodeHandle
> +  )
> +{
> +  MEM_INFO_SCREEN_PRIVATE_DATA *PrivateData = mPrivateData;
> +  CHAR16                       Str[MAX_STRING_SIZE], Str1[MAX_STRING_SIZE];
> +  UINTN                        Count;
> +  PLATFORM_DIMM_INFO           *DimmInfo;
> +  EFI_STRING_ID                StringId;
> +
> +  //
> +  // 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
> +      );
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +EFI_STATUS
> +MemInfoMainScreen (
> +  PLATFORM_INFO_HOB  *PlatformHob
> +  )
> +{
> +  MEM_INFO_SCREEN_PRIVATE_DATA  *PrivateData = mPrivateData;
> +  EFI_IFR_GUID_LABEL            *StartLabel;
> +  EFI_IFR_GUID_LABEL            *EndLabel;
> +  VOID                          *StartOpCodeHandle;
> +  VOID                          *EndOpCodeHandle;
> +  EFI_STATUS                    Status;
> +
> +  Status = UpdateMemInfo (PlatformHob);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // Get Buffer Storage data from EFI variable
> +  //
> +  Status = MemInfoNvparamGet (&PrivateData->VarStoreConfig);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // 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;
> +
> +  //
> +  // 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)
> +    );
> +
> +  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
> +      );
> +  }
> +
> +  Status = AddMemorySpeedSelection (PlatformHob, StartOpCodeHandle);
> +  ASSERT_EFI_ERROR (Status);
> +
> +  Status = AddFgrModeSelection (PlatformHob, StartOpCodeHandle);
> +  ASSERT_EFI_ERROR (Status);
> +
> +  //
> +  // 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
> +    );
> +
> +  Status = AddDimmListInfo (PlatformHob, StartOpCodeHandle);
> +  ASSERT_EFI_ERROR (Status);
> +
> +  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);
> +
> +  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 <= MAX_NUMBER_OF_HOURS_IN_A_DAY; 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 (&gPlatformInfoHobGuid);
> +  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,
> +                MemInfoScreenVfrBin,
> +                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
> 

  reply	other threads:[~2021-10-26 12:58 UTC|newest]

Thread overview: 56+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-10-22  6:17 [edk2-platforms][PATCH v4 00/31] Add new Ampere Mt. Jade platform Nhi Pham
2021-10-22  6:17 ` [edk2-platforms][PATCH v4 01/31] Ampere: Initial support for Ampere Altra processor and " Nhi Pham
2021-10-26 11:14   ` Leif Lindholm
2021-11-03  9:31     ` Nhi Pham
2021-10-22  6:17 ` [edk2-platforms][PATCH v4 02/31] AmpereAltraPkg: Add FlashLib library instance Nhi Pham
2021-10-26 11:25   ` Leif Lindholm
2021-11-03  9:32     ` Nhi Pham
2021-10-22  6:17 ` [edk2-platforms][PATCH v4 03/31] AmpereAltraPkg: Add FailSafe and WDT support Nhi Pham
2021-10-26 12:15   ` Leif Lindholm
2021-11-03  9:35     ` Nhi Pham
2021-10-22  6:17 ` [edk2-platforms][PATCH v4 04/31] AmpereAltraPkg: Add DwI2cLib library instance Nhi Pham
2021-10-22  6:17 ` [edk2-platforms][PATCH v4 05/31] AmpereAltraPkg: Add DwGpioLib " Nhi Pham
2021-10-22  6:17 ` [edk2-platforms][PATCH v4 06/31] JadePkg: Implement RealTimeClockLib for PCF85063 Nhi Pham
2021-10-22  6:17 ` [edk2-platforms][PATCH v4 07/31] AmpereAltraPkg: Add BootProgress support Nhi Pham
2021-10-22  6:17 ` [edk2-platforms][PATCH v4 08/31] AmpereAltraPkg: Support UEFI non-volatile variable Nhi Pham
2021-10-26 12:21   ` Leif Lindholm
2021-10-22  6:17 ` [edk2-platforms][PATCH v4 09/31] AmpereSiliconPkg: Add PlatformManagerUiLib library instance Nhi Pham
2021-10-22  6:17 ` [edk2-platforms][PATCH v4 10/31] AmpereAltraPkg, JadePkg: Add ACPI support Nhi Pham
2021-10-22  6:17 ` [edk2-platforms][PATCH v4 11/31] AmpereAltraPkg: Add Root Complex HOB data structures Nhi Pham
2021-10-26 12:23   ` Leif Lindholm
2021-10-22  6:17 ` [edk2-platforms][PATCH v4 12/31] AmpereAltraPkg: Add Ac01PcieLib library instance Nhi Pham
2021-10-26 12:45   ` Leif Lindholm
2021-11-03  9:33     ` Nhi Pham
2021-10-22  6:17 ` [edk2-platforms][PATCH v4 13/31] JadePkg: Add BoardPcieLib " Nhi Pham
2021-10-26 12:46   ` Leif Lindholm
2021-11-03  9:33     ` Nhi Pham
2021-10-22  6:17 ` [edk2-platforms][PATCH v4 14/31] AmpereAltraPkg: Add driver to initialize PCIe Root Complex Nhi Pham
2021-10-26 12:49   ` Leif Lindholm
2021-10-22  6:17 ` [edk2-platforms][PATCH v4 15/31] AmpereAltraPkg: Add PciHostBridgeLib library instance Nhi Pham
2021-10-26 12:49   ` Leif Lindholm
2021-10-22  6:17 ` [edk2-platforms][PATCH v4 16/31] AmpereAltraPkg: Add PciSegmentLib " Nhi Pham
2021-10-26 12:53   ` Leif Lindholm
2021-11-03  9:35     ` Nhi Pham
2021-10-22  6:17 ` [edk2-platforms][PATCH v4 17/31] JadePkg: Enable PciHostBridgeDxe driver Nhi Pham
2021-10-22  6:17 ` [edk2-platforms][PATCH v4 18/31] JadePkg: Add PciPlatformDxe driver Nhi Pham
2021-10-22  6:17 ` [edk2-platforms][PATCH v4 19/31] JadePkg: Add ACPI tables to support PCIe Nhi Pham
2021-10-26 12:54   ` Leif Lindholm
2021-10-22  6:17 ` [edk2-platforms][PATCH v4 20/31] JadePkg: Add ASpeed GOP driver Nhi Pham
2021-10-22  6:17 ` [edk2-platforms][PATCH v4 21/31] AmpereAltraPkg: Add Random Number Generator Support Nhi Pham
2021-10-22  6:18 ` [edk2-platforms][PATCH v4 22/31] JadePkg: Add SMBIOS tables support Nhi Pham
2021-10-22  6:18 ` [edk2-platforms][PATCH v4 23/31] AmpereAltraPkg: Add DebugInfoPei module Nhi Pham
2021-10-22  6:18 ` [edk2-platforms][PATCH v4 24/31] AmpereAltraPkg: Add configuration screen for PCIe Nhi Pham
2021-10-26 12:56   ` Leif Lindholm
2021-10-22  6:18 ` [edk2-platforms][PATCH v4 25/31] Ampere: Utilize the PCIe User setting Nhi Pham
2021-10-26 12:57   ` Leif Lindholm
2021-10-22  6:18 ` [edk2-platforms][PATCH v4 26/31] AmpereAltraPkg: Add platform info screen Nhi Pham
2021-10-22  6:18 ` [edk2-platforms][PATCH v4 27/31] AmpereAltraPkg: Add configuration screen for Memory Nhi Pham
2021-10-26 12:58   ` Leif Lindholm [this message]
2021-10-22  6:18 ` [edk2-platforms][PATCH v4 28/31] AmpereAltraPkg: Add configuration screen for CPU Nhi Pham
2021-10-22  6:18 ` [edk2-platforms][PATCH v4 29/31] AmpereAltraPkg: Add configuration screen for ACPI Nhi Pham
2021-10-22  6:18 ` [edk2-platforms][PATCH v4 30/31] AmpereAltraPkg: Add configuration screen for RAS Nhi Pham
2021-10-22  6:18 ` [edk2-platforms][PATCH v4 31/31] AmpereAltraPkg: Add configuration screen for Watchdog timer Nhi Pham
2021-10-26 13:03   ` Leif Lindholm
2021-11-03  9:36     ` Nhi Pham
2021-10-26 13:08 ` [edk2-platforms][PATCH v4 00/31] Add new Ampere Mt. Jade platform Leif Lindholm
2021-11-03  9:37   ` Nhi Pham

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20211026125848.plku2zdywmtyd3lm@leviathan \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox