[edk2-devel] [edk2-platforms][PATCH v2 15/32] JadePkg: Add PcieBoardLib library instance

Leif Lindholm leif at nuviainc.com
Mon Jun 7 22:45:59 UTC 2021


On Wed, May 26, 2021 at 17:07:07 +0700, Nhi Pham wrote:
> From: Vu Nguyen <vunguyen at os.amperecomputing.com>
> 
> Provides basic features like:
> * Screen menu to change bifurcation setting of each Root Complex. Note
>   that we can only change the option for Root Complex which doesn't have
>   default value in the BoardSetting.
> * Parsing the BoardSetting and coordinate with saved setting to enable
>   corresponding PCIe controller of each Root Complex.
> * Config speed and lane of enabled controller.
> 
> 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>
> ---
>  Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec                 |    3 +
>  Platform/Ampere/JadePkg/Library/PcieBoardLib/PcieBoardLib.inf    |   60 ++
>  Platform/Ampere/JadePkg/Library/PcieBoardLib/NVDataStruc.h       |   89 ++
>  Platform/Ampere/JadePkg/Library/PcieBoardLib/PcieBoardScreen.h   |  138 +++
>  Silicon/Ampere/AmpereAltraPkg/Include/Library/PcieBoardLib.h     |  102 ++
>  Platform/Ampere/JadePkg/Library/PcieBoardLib/Vfr.vfr             |  212 ++++
>  Platform/Ampere/JadePkg/Library/PcieBoardLib/PcieBoard.c         |  438 ++++++++
>  Platform/Ampere/JadePkg/Library/PcieBoardLib/PcieBoardCommon.c   |  327 ++++++
>  Platform/Ampere/JadePkg/Library/PcieBoardLib/PcieBoardScreen.c   | 1120 ++++++++++++++++++++
>  Platform/Ampere/JadePkg/Library/PcieBoardLib/PcieBoardScreen.uni |   99 ++
>  10 files changed, 2588 insertions(+)
> 
> diff --git a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec b/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec
> index 0d79673ce50a..a372a4e0078b 100644
> --- a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec
> +++ b/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec
> @@ -40,6 +40,9 @@ [LibraryClasses]
>    ##  @libraryclass  Defines a set of methods to initialize Pcie
>    PcieCoreLib|Silicon/Ampere/AmpereAltraP/Include/Library/PcieCoreLib.h
>  
> +  ##  @libraryclass  Defines a set of miscellaneous PCIe functions
> +  PcieBoardLib|Silicon/Ampere/AmpereAltraPkg/Include/Library/PcieBoardLib.h
> +
>    ##  @libraryclass  Defines a set of methods to access flash memory.
>    FlashLib|Silicon/Ampere/AmpereAltraPkg/Include/Library/FlashLib.h
>  
> diff --git a/Platform/Ampere/JadePkg/Library/PcieBoardLib/PcieBoardLib.inf b/Platform/Ampere/JadePkg/Library/PcieBoardLib/PcieBoardLib.inf
> new file mode 100644
> index 000000000000..6be78f8936d7
> --- /dev/null
> +++ b/Platform/Ampere/JadePkg/Library/PcieBoardLib/PcieBoardLib.inf
> @@ -0,0 +1,60 @@
> +## @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                      = PcieBoardLib
> +  FILE_GUID                      = 062191A6-E113-4FD6-84C7-E400B4B34759
> +  MODULE_TYPE                    = DXE_DRIVER
> +  VERSION_STRING                 = 1.0
> +  LIBRARY_CLASS                  = PcieBoardLib
> +
> +[Sources]
> +  PcieBoard.c
> +  PcieBoardCommon.c
> +  PcieBoardScreen.c
> +  PcieBoardScreen.h
> +  PcieBoardScreen.uni
> +  NVDataStruc.h
> +  Vfr.vfr
> +
> +[Packages]
> +  ArmPlatformPkg/ArmPlatformPkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  MdePkg/MdePkg.dec
> +  Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec
> +  Silicon/Ampere/AmpereSiliconPkg/AmpereSiliconPkg.dec
> +
> +[LibraryClasses]
> +  AmpereCpuLib
> +  BaseLib
> +  DevicePathLib
> +  GpioLib
> +  HiiLib
> +  HobLib
> +  MemoryAllocationLib
> +  SystemFirmwareInterfaceLib
> +  UefiBootServicesTableLib
> +  UefiLib
> +  UefiRuntimeServicesTableLib
> +
> +[Protocols]
> +  gEfiDevicePathProtocolGuid
> +  gEfiHiiStringProtocolGuid                     ## CONSUMES
> +  gEfiHiiConfigRoutingProtocolGuid              ## CONSUMES
> +  gEfiHiiConfigAccessProtocolGuid               ## PRODUCES
> +  gEfiHiiDatabaseProtocolGuid                   ## CONSUMES
> +  gEfiConfigKeywordHandlerProtocolGuid          ## CONSUMES
> +
> +[Guids]
> +  gEfiIfrTianoGuid                              ## CONSUMES
> +  gPlatformManagerFormsetGuid                   ## CONSUMES
> +  gPlatformHobGuid                              ## CONSUMES
> +
> +[Depex]
> +  TRUE
> diff --git a/Platform/Ampere/JadePkg/Library/PcieBoardLib/NVDataStruc.h b/Platform/Ampere/JadePkg/Library/PcieBoardLib/NVDataStruc.h
> new file mode 100644
> index 000000000000..f94f12d968fd
> --- /dev/null
> +++ b/Platform/Ampere/JadePkg/Library/PcieBoardLib/NVDataStruc.h

(Should this not be NVDataStruct.h?

> @@ -0,0 +1,89 @@
> +/** @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 MAX_AC01_PCIE_SCREEN_ROOT_COMPLEX 16
> +
> +#define PCIE_VARSTORE_NAME        L"PcieIfrNVData"
> +#define PCIE_VARSTORE_ID          0x1234
> +#define PCIE_FORM_ID              0x1235
> +#define PCIE_RC0_FORM_ID          0x1236
> +#define PCIE_RC1_FORM_ID          0x1237
> +#define PCIE_RC2_FORM_ID          0x1238
> +#define PCIE_RC3_FORM_ID          0x1239
> +#define PCIE_RC4_FORM_ID          0x123A
> +#define PCIE_RC5_FORM_ID          0x123B
> +#define PCIE_RC6_FORM_ID          0x123C
> +#define PCIE_RC7_FORM_ID          0x123D
> +#define PCIE_RC8_FORM_ID          0x123E
> +#define PCIE_RC9_FORM_ID          0x123F
> +#define PCIE_RC10_FORM_ID         0x1240
> +#define PCIE_RC11_FORM_ID         0x1241
> +#define PCIE_RC12_FORM_ID         0x1242
> +#define PCIE_RC13_FORM_ID         0x1243
> +#define PCIE_RC14_FORM_ID         0x1244
> +#define PCIE_RC15_FORM_ID         0x1245
> +#define PCIE_FORM_SET_GUID        { 0xe84e70d6, 0xe4b2, 0x4c6e, { 0x98,  0x51, 0xcb, 0x2b, 0xac, 0x77, 0x7d, 0xbb } }
> +
> +#define PCIE_GOTO_ID_BASE         0x8040

Would recommend prefix before PCIE.
Or, given this is a fully local include - dropping the PCIE prefix.

> +
> +#pragma pack(1)
> +
> +//
> +// NV data structure definition
> +//
> +typedef struct {
> +  BOOLEAN RCStatus[MAX_AC01_PCIE_SCREEN_ROOT_COMPLEX];
> +  UINT8   RCBifurLo[MAX_AC01_PCIE_SCREEN_ROOT_COMPLEX];
> +  UINT8   RCBifurHi[MAX_AC01_PCIE_SCREEN_ROOT_COMPLEX];
> +  UINT32  SmmuPmu;
> +} PCIE_VARSTORE_DATA;

Same.

> +
> +//
> +// Labels definition
> +//
> +#define LABEL_UPDATE             0x2223
> +#define LABEL_END                0x2224
> +#define LABEL_RC0_UPDATE         0x2225
> +#define LABEL_RC0_END            0x2226
> +#define LABEL_RC1_UPDATE         0x2227
> +#define LABEL_RC1_END            0x2228
> +#define LABEL_RC2_UPDATE         0x2229
> +#define LABEL_RC2_END            0x222A
> +#define LABEL_RC3_UPDATE         0x222B
> +#define LABEL_RC3_END            0x222C
> +#define LABEL_RC4_UPDATE         0x222D
> +#define LABEL_RC4_END            0x222E
> +#define LABEL_RC5_UPDATE         0x222F
> +#define LABEL_RC5_END            0x2230
> +#define LABEL_RC6_UPDATE         0x2231
> +#define LABEL_RC6_END            0x2232
> +#define LABEL_RC7_UPDATE         0x2233
> +#define LABEL_RC7_END            0x2234
> +#define LABEL_RC8_UPDATE         0x2235
> +#define LABEL_RC8_END            0x2236
> +#define LABEL_RC9_UPDATE         0x2237
> +#define LABEL_RC9_END            0x2238
> +#define LABEL_RC10_UPDATE        0x2239
> +#define LABEL_RC10_END           0x223A
> +#define LABEL_RC11_UPDATE        0x223B
> +#define LABEL_RC11_END           0x223C
> +#define LABEL_RC12_UPDATE        0x223D
> +#define LABEL_RC12_END           0x223E
> +#define LABEL_RC13_UPDATE        0x223F
> +#define LABEL_RC13_END           0x2240
> +#define LABEL_RC14_UPDATE        0x2241
> +#define LABEL_RC14_END           0x2242
> +#define LABEL_RC15_UPDATE        0x2243
> +#define LABEL_RC15_END           0x2244
> +
> +#pragma pack()

Move this to just after the struct? Nothing to pack beyond that.

> +
> +#endif
> diff --git a/Platform/Ampere/JadePkg/Library/PcieBoardLib/PcieBoardScreen.h b/Platform/Ampere/JadePkg/Library/PcieBoardLib/PcieBoardScreen.h
> new file mode 100644
> index 000000000000..c5c50060870c
> --- /dev/null
> +++ b/Platform/Ampere/JadePkg/Library/PcieBoardLib/PcieBoardScreen.h
> @@ -0,0 +1,138 @@
> +/** @file
> +
> +  Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#ifndef PCIE_SCREEN_H_
> +#define PCIE_SCREEN_H_

Needs to not start with PCIE - additional prefix is fine.

> +
> +#include <Guid/MdeModuleHii.h>
> +#include <Library/BaseLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/DevicePathLib.h>
> +#include <Library/HiiLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/PrintLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiDriverEntryPoint.h>
> +#include <Library/UefiLib.h>
> +#include <Library/UefiRuntimeServicesTableLib.h>
> +#include <Protocol/FormBrowser2.h>
> +#include <Protocol/HiiConfigAccess.h>
> +#include <Protocol/HiiConfigKeyword.h>
> +#include <Protocol/HiiConfigRouting.h>
> +#include <Protocol/HiiDatabase.h>
> +#include <Protocol/HiiString.h>

Move all include statements not needed by this header file to the .c
file that actually uses them.

> +
> +#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[];

Add some descriptive prefix.
PcieBoardVfrBin?

> +
> +//
> +// 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 PcieDxeStrings[];

Not part of PCIE or PI spec - add "Platform" or something prefix.

> +
> +#define MAX_EDITABLE_ELEMENTS 3
> +#define PCIE_RC0_STATUS_OFFSET  \
> +  OFFSET_OF (PCIE_VARSTORE_DATA, RCStatus[0])
> +#define PCIE_RC0_BIFUR_LO_OFFSET  \
> +  OFFSET_OF (PCIE_VARSTORE_DATA, RCBifurLo[0])
> +#define PCIE_RC0_BIFUR_HI_OFFSET  \
> +  OFFSET_OF (PCIE_VARSTORE_DATA, RCBifurHi[0])
> +#define PCIE_SMMU_PMU_OFFSET  \
> +  OFFSET_OF (PCIE_VARSTORE_DATA, SmmuPmu)
> +
> +#define PCIE_SCREEN_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('P', 'C', 'I', 'E')

This signature is supposed to be at least potentially unique.

> +
> +typedef struct {
> +  UINTN Signature;
> +
> +  EFI_HANDLE         DriverHandle;
> +  EFI_HII_HANDLE     HiiHandle;
> +  PCIE_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;
> +
> +  //
> +  // Produced protocol
> +  //
> +  EFI_HII_CONFIG_ACCESS_PROTOCOL ConfigAccess;
> +} PCIE_SCREEN_PRIVATE_DATA;

Structs need more unique prefixes.

> +
> +typedef union {
> +  UINT16 VAR_ID;
> +  struct _PCIE_VAR_ID {
> +    UINT16 PciDevIndex     : 12;
> +    UINT16 DataType        : 3;
> +    UINT16 Always1         : 1;
> +  } IdField;
> +} PCIE_VAR_ID;
> +
> +typedef struct {
> +  UINTN         PciDevIdx;
> +  EFI_STRING_ID GotoStringId;
> +  EFI_STRING_ID GotoHelpStringId;
> +  UINT16        GotoKey;
> +  BOOLEAN       ShowItem;
> +} PCIE_SETUP_GOTO_DATA;
> +
> +typedef struct {
> +  VOID               *StartOpCodeHandle;
> +  VOID               *EndOpCodeHandle;
> +  EFI_IFR_GUID_LABEL *StartLabel;
> +  EFI_IFR_GUID_LABEL *EndLabel;
> +
> +} PCIE_IFR_INFO;
> +
> +#define PCIE_SCREEN_PRIVATE_FROM_THIS(a)  \
> +  CR (a, PCIE_SCREEN_PRIVATE_DATA, ConfigAccess, PCIE_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()
> +
> +UINT8
> +PcieRCDevMapLoDefaultSetting (
> +  IN UINTN                    RCIndex,
> +  IN PCIE_SCREEN_PRIVATE_DATA *PrivateData
> +  );
> +
> +UINT8
> +PcieRCDevMapHiDefaultSetting (
> +  IN UINTN                    RCIndex,
> +  IN PCIE_SCREEN_PRIVATE_DATA *PrivateData
> +  );
> +
> +BOOLEAN
> +PcieRCActiveDefaultSetting (
> +  IN UINTN                    RCIndex,
> +  IN PCIE_SCREEN_PRIVATE_DATA *PrivateData
> +  );
> +
> +#endif /* PCIE_SCREEN_H_ */
> diff --git a/Silicon/Ampere/AmpereAltraPkg/Include/Library/PcieBoardLib.h b/Silicon/Ampere/AmpereAltraPkg/Include/Library/PcieBoardLib.h
> new file mode 100644
> index 000000000000..bff5b62ba13b
> --- /dev/null
> +++ b/Silicon/Ampere/AmpereAltraPkg/Include/Library/PcieBoardLib.h
> @@ -0,0 +1,102 @@
> +/** @file
> +
> +  Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#ifndef PCIE_BOARD_LIB_H_
> +#define PCIE_BOARD_LIB_H_
> +
> +#include "Pcie.h"

OK, I'm going to stop pointing this out from this point on, but
anything that is not referencing a direct aspect of the PCIe
specification should not be named PCIE*/Pcie*, ...
These names are reserved.

Since most of these symbols are internal anyway, and reference only
settings inside the PCIE configuration screen, I think the cleanest
thing would be to drop the PCIE/Pcie prefixes altogether.

> +
> +/**
> +
> +  Check if a PCIE port enabled in the board configuration.
> +
> +  @param  Index                     The port index.
> +
> +  @retval                           TRUE if the port enabled, otherwise FALSE.
> +
> +**/
> +BOOLEAN
> +PcieBoardCheckSysSlotEnabled (
> +  IN UINTN Index
> +  );
> +
> +VOID
> +PcieBoardGetRCSegmentNumber (
> +  IN  AC01_RC *RC,
> +  OUT UINTN   *SegmentNumber
> +  );
> +
> +/**
> +
> +  Check if SMM PMU enabled in board screen
> +
> +  @retval                           TRUE if the SMMU PMU enabled, otherwise FALSE.
> +
> +**/
> +BOOLEAN
> +PcieBoardCheckSmmuPmuEnabled (
> +  VOID
> +  );
> +
> +/**
> +
> +  Build UEFI menu.
> +
> +  @param  ImageHandle               Handle.
> +  @param  SystemTable               Pointer to System Table.
> +  @param  RCList                    List of Root Complex with properties.
> +
> +  @retval                           EFI_SUCCESS if successful, otherwise EFI_ERROR.
> +
> +**/
> +EFI_STATUS
> +PcieBoardScreenInitialize (
> +  IN EFI_HANDLE       ImageHandle,
> +  IN EFI_SYSTEM_TABLE *SystemTable,
> +  IN AC01_RC          *RCList
> +  );
> +
> +BOOLEAN
> +IsEmptyRC (
> +  IN AC01_RC *RC
> +  );
> +
> +VOID
> +PcieBoardSetupDevmap (
> +  IN AC01_RC *RC
> +  );
> +
> +VOID
> +PcieBoardGetLaneAllocation (
> +  IN AC01_RC *RC
> +  );
> +
> +VOID
> +PcieBoardGetSpeed (
> +  IN AC01_RC *RC
> +  );
> +
> +VOID
> +PcieBoardParseRCParams (
> +  IN AC01_RC *RC
> +  );
> +
> +VOID
> +PcieBoardAssertPerst (
> +  AC01_RC *RC,
> +  UINT32  PcieIndex,
> +  UINT8   Bifurcation,
> +  BOOLEAN isPullToHigh
> +  );
> +
> +BOOLEAN
> +PcieBoardCheckSmmuPmuEnabled (
> +  VOID
> +  );
> +
> +#endif /* PCIE_BOARD_LIB_H_ */
> diff --git a/Platform/Ampere/JadePkg/Library/PcieBoardLib/Vfr.vfr b/Platform/Ampere/JadePkg/Library/PcieBoardLib/Vfr.vfr
> new file mode 100644
> index 000000000000..a596d5ac9a92
> --- /dev/null
> +++ b/Platform/Ampere/JadePkg/Library/PcieBoardLib/Vfr.vfr
> @@ -0,0 +1,212 @@
> +/** @file
> +
> +  Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include "NVDataStruc.h"
> +
> +formset
> +  guid    = PCIE_FORM_SET_GUID,
> +  title   = STRING_TOKEN(STR_PCIE_FORM),
> +  help    = STRING_TOKEN(STR_PCIE_FORM_HELP),
> +  classguid = gPlatformManagerFormsetGuid,
> +
> +  //
> +  // Define a variable Storage
> +  //
> +  varstore PCIE_VARSTORE_DATA,
> +    varid = PCIE_VARSTORE_ID,
> +    name  = PcieIfrNVData,
> +    guid  = PCIE_FORM_SET_GUID;
> +
> +  form
> +    formid = PCIE_FORM_ID,
> +    title = STRING_TOKEN(STR_PCIE_FORM);
> +
> +    subtitle text = STRING_TOKEN(STR_PCIE_FORM);
> +
> +    label LABEL_UPDATE;
> +    // dynamic content here
> +    label LABEL_END;
> +  endform;
> +
> +  form
> +    formid = PCIE_RC0_FORM_ID,
> +    title = STRING_TOKEN(STR_PCIE_RC0_FORM);
> +
> +    subtitle text = STRING_TOKEN(STR_PCIE_RC0_FORM);
> +
> +    label LABEL_RC0_UPDATE;
> +    // dynamic content here
> +    label LABEL_RC0_END;
> +  endform;
> +
> +  form
> +    formid = PCIE_RC1_FORM_ID,
> +    title = STRING_TOKEN(STR_PCIE_RC1_FORM);
> +
> +    subtitle text = STRING_TOKEN(STR_PCIE_RC1_FORM);
> +
> +    label LABEL_RC1_UPDATE;
> +    // dynamic content here
> +    label LABEL_RC1_END;
> +  endform;
> +
> +  form
> +    formid = PCIE_RC2_FORM_ID,
> +    title = STRING_TOKEN(STR_PCIE_RC2_FORM);
> +
> +    subtitle text = STRING_TOKEN(STR_PCIE_RC2_FORM);
> +
> +    label LABEL_RC2_UPDATE;
> +    // dynamic content here
> +    label LABEL_RC2_END;
> +  endform;
> +
> +  form
> +    formid = PCIE_RC3_FORM_ID,
> +    title = STRING_TOKEN(STR_PCIE_RC3_FORM);
> +
> +    subtitle text = STRING_TOKEN(STR_PCIE_RC3_FORM);
> +
> +    label LABEL_RC3_UPDATE;
> +    // dynamic content here
> +    label LABEL_RC3_END;
> +  endform;
> +
> +  form
> +    formid = PCIE_RC4_FORM_ID,
> +    title = STRING_TOKEN(STR_PCIE_RC4_FORM);
> +
> +    subtitle text = STRING_TOKEN(STR_PCIE_RC4_FORM);
> +
> +    label LABEL_RC4_UPDATE;
> +    // dynamic content here
> +    label LABEL_RC4_END;
> +  endform;
> +
> +  form
> +    formid = PCIE_RC5_FORM_ID,
> +    title = STRING_TOKEN(STR_PCIE_RC5_FORM);
> +
> +    subtitle text = STRING_TOKEN(STR_PCIE_RC5_FORM);
> +
> +    label LABEL_RC5_UPDATE;
> +    // dynamic content here
> +    label LABEL_RC5_END;
> +  endform;
> +
> +  form
> +    formid = PCIE_RC6_FORM_ID,
> +    title = STRING_TOKEN(STR_PCIE_RC6_FORM);
> +
> +    subtitle text = STRING_TOKEN(STR_PCIE_RC6_FORM);
> +
> +    label LABEL_RC6_UPDATE;
> +    // dynamic content here
> +    label LABEL_RC6_END;
> +  endform;
> +
> +  form
> +    formid = PCIE_RC7_FORM_ID,
> +    title = STRING_TOKEN(STR_PCIE_RC7_FORM);
> +
> +    subtitle text = STRING_TOKEN(STR_PCIE_RC7_FORM);
> +
> +    label LABEL_RC7_UPDATE;
> +    // dynamic content here
> +    label LABEL_RC7_END;
> +  endform;
> +
> +  form
> +    formid = PCIE_RC8_FORM_ID,
> +    title = STRING_TOKEN(STR_PCIE_RC8_FORM);
> +
> +    subtitle text = STRING_TOKEN(STR_PCIE_RC8_FORM);
> +
> +    label LABEL_RC8_UPDATE;
> +    // dynamic content here
> +    label LABEL_RC8_END;
> +  endform;
> +
> +  form
> +    formid = PCIE_RC9_FORM_ID,
> +    title = STRING_TOKEN(STR_PCIE_RC9_FORM);
> +
> +    subtitle text = STRING_TOKEN(STR_PCIE_RC9_FORM);
> +
> +    label LABEL_RC9_UPDATE;
> +    // dynamic content here
> +    label LABEL_RC9_END;
> +  endform;
> +
> +  form
> +    formid = PCIE_RC10_FORM_ID,
> +    title = STRING_TOKEN(STR_PCIE_RC10_FORM);
> +
> +    subtitle text = STRING_TOKEN(STR_PCIE_RC10_FORM);
> +
> +    label LABEL_RC10_UPDATE;
> +    // dynamic content here
> +    label LABEL_RC10_END;
> +  endform;
> +
> +  form
> +    formid = PCIE_RC11_FORM_ID,
> +    title = STRING_TOKEN(STR_PCIE_RC11_FORM);
> +
> +    subtitle text = STRING_TOKEN(STR_PCIE_RC11_FORM);
> +
> +    label LABEL_RC11_UPDATE;
> +    // dynamic content here
> +    label LABEL_RC11_END;
> +  endform;
> +
> +  form
> +    formid = PCIE_RC12_FORM_ID,
> +    title = STRING_TOKEN(STR_PCIE_RC12_FORM);
> +
> +    subtitle text = STRING_TOKEN(STR_PCIE_RC12_FORM);
> +
> +    label LABEL_RC12_UPDATE;
> +    // dynamic content here
> +    label LABEL_RC12_END;
> +  endform;
> +
> +  form
> +    formid = PCIE_RC13_FORM_ID,
> +    title = STRING_TOKEN(STR_PCIE_RC13_FORM);
> +
> +    subtitle text = STRING_TOKEN(STR_PCIE_RC13_FORM);
> +
> +    label LABEL_RC13_UPDATE;
> +    // dynamic content here
> +    label LABEL_RC13_END;
> +  endform;
> +
> +  form
> +    formid = PCIE_RC14_FORM_ID,
> +    title = STRING_TOKEN(STR_PCIE_RC14_FORM);
> +
> +    subtitle text = STRING_TOKEN(STR_PCIE_RC14_FORM);
> +
> +    label LABEL_RC14_UPDATE;
> +    // dynamic content here
> +    label LABEL_RC14_END;
> +  endform;
> +
> +  form
> +    formid = PCIE_RC15_FORM_ID,
> +    title = STRING_TOKEN(STR_PCIE_RC15_FORM);
> +
> +    subtitle text = STRING_TOKEN(STR_PCIE_RC15_FORM);
> +
> +    label LABEL_RC15_UPDATE;
> +    // dynamic content here
> +    label LABEL_RC15_END;
> +  endform;
> +
> +endformset;
> diff --git a/Platform/Ampere/JadePkg/Library/PcieBoardLib/PcieBoard.c b/Platform/Ampere/JadePkg/Library/PcieBoardLib/PcieBoard.c
> new file mode 100644
> index 000000000000..c0c94d349b5b
> --- /dev/null
> +++ b/Platform/Ampere/JadePkg/Library/PcieBoardLib/PcieBoard.c
> @@ -0,0 +1,438 @@
> +/** @file
> +
> +  Pcie board specific driver to handle asserting PERST signal to Endpoint
> +  card and parsing NVPARAM board settings for bifurcation programming.
> +
> +  PERST asserting is via group of GPIO pins to CPLD as Platform Specification.
> +
> +  NVPARAM board settings is spec-ed within Firmware Interface Requirement.
> +  Bifuration devmap is programmed before at SCP following the rule
> +
> +  Root Complex Type-A devmap settings (RP == Root Port)
> +  -----------------------------------------
> +  | RP0   | RP1  | RP2  | RP3  | Devmap   |
> +  | (x16) | (x4) | (x8) | (x4) | (output) |
> +  -------------------------------------------
> +  |  Y    |  N   |  N   |  N   | 0        |
> +  |  Y    |  N   |  Y   |  N   | 1        |
> +  |  Y    |  N   |  Y   |  Y   | 2        |
> +  |  Y    |  Y   |  Y   |  Y   | 3        |
> +  -----------------------------------------
> +
> +  Root Complex Type-B LO (aka RCBxA) devmap settings (RP == Root Port)
> +  ----------------------------------------
> +  | RP0  | RP1  | RP2  | RP3  | Devmap   |
> +  | (x8) | (x2) | (x4) | (x3) | (output) |
> +  ----------------------------------------
> +  |  Y   |  N   |  N   |  N   | 0        |
> +  |  Y   |  N   |  Y   |  N   | 1        |
> +  |  Y   |  N   |  Y   |  Y   | 2        |
> +  |  Y   |  Y   |  Y   |  Y   | 3        |
> +  ----------------------------------------
> +
> +  Root Complex Type-B LO (aka RCBxB) devmap settings (RP == Root Port)
> +  ----------------------------------------
> +  | RP4  | RP5  | RP6  | RP7  | Devmap   |
> +  | (x8) | (x2) | (x4) | (x3) | (output) |
> +  ----------------------------------------
> +  |  Y   |  N   |  N   |  N   | 0        |
> +  |  Y   |  N   |  Y   |  N   | 1        |
> +  |  Y   |  N   |  Y   |  Y   | 2        |
> +  |  Y   |  Y   |  Y   |  Y   | 3        |
> +  ----------------------------------------
> +
> +  Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include <Guid/PlatformInfoHobGuid.h>
> +#include <Library/AmpereCpuLib.h>
> +#include <Library/BaseLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/GpioLib.h>
> +#include <Library/HobLib.h>
> +#include <Library/IoLib.h>
> +#include <Library/NVParamLib.h>
> +#include <Library/PcieBoardLib.h>
> +#include <Library/TimerLib.h>
> +#include <Library/UefiLib.h>
> +#include <Library/UefiRuntimeServicesTableLib.h>
> +#include <NVDataStruc.h>
> +#include <NVParamDef.h>
> +#include <Pcie.h>
> +#include <PlatformInfoHob.h>
> +
> +#ifndef BIT
> +#define BIT(nr)                         (1 << (nr))
> +#endif
> +
> +extern CHAR16   VariableName[];
> +extern EFI_GUID gPcieFormSetGuid;
> +
> +VOID
> +EFIAPI
> +PcieBoardLoadPreset (
> +  IN AC01_RC *RC
> +  )
> +{
> +  UINT32 Nv;
> +  INTN   NvParam;
> +  INTN   Ret;
> +  INTN   i;
> +
> +  // Load default value
> +  for (i = 0; i < MAX_PCIE_B; i++) {
> +    RC->PresetGen3[i] = PRESET_INVALID;
> +    RC->PresetGen4[i] = PRESET_INVALID;
> +  }
> +
> +  // Load override value
> +  if (RC->Socket == 0) {
> +    if (RC->Type == RCA) {
> +      if (RC->ID < 4) {

There are various live-coded values of 4 and 2 in this function.
Please replace them with #defines with descriptive names to improve readability.

> +        NvParam = NV_SI_RO_BOARD_S0_RCA0_TXRX_G3PRESET + RC->ID * NVPARAM_SIZE;
> +      } else {
> +        NvParam = NV_SI_RO_BOARD_S0_RCA4_TXRX_G3PRESET + (RC->ID - 4) * NVPARAM_SIZE;
> +      }
> +    } else {
> +      NvParam = NV_SI_RO_BOARD_S0_RCB0A_TXRX_G3PRESET + (RC->ID - 4) * (2 * NVPARAM_SIZE);
> +    }
> +  } else if (RC->Type == RCA) {
> +    if (RC->ID < 4) {
> +      NvParam = NV_SI_RO_BOARD_S1_RCA2_TXRX_G3PRESET + (RC->ID - 2) * NVPARAM_SIZE;
> +    } else {
> +      NvParam = NV_SI_RO_BOARD_S1_RCA4_TXRX_G3PRESET + (RC->ID - 4) * NVPARAM_SIZE;
> +    }
> +  } else {
> +    NvParam = NV_SI_RO_BOARD_S1_RCB0A_TXRX_G3PRESET + (RC->ID - 4) * (2 * NVPARAM_SIZE);
> +  }
> +
> +  Ret = NVParamGet ((NVPARAM)NvParam, NV_PERM_ALL, &Nv);
> +  if (Ret == EFI_SUCCESS) {
> +    for (i = 0; i < 4; i++) {
> +      RC->PresetGen3[i] = (Nv >> (NVPARAM_SIZE * i)) & 0xFF;
> +    }
> +  }
> +
> +  if (RC->Type == RCB) {
> +    NvParam += NVPARAM_SIZE;
> +    Ret = NVParamGet ((NVPARAM)NvParam, NV_PERM_ALL, &Nv);
> +    if (Ret == EFI_SUCCESS) {
> +      for (i = 0; i < 4; i++) {
> +        RC->PresetGen3[i] = (Nv >> (NVPARAM_SIZE * i)) & 0xFF;
> +      }
> +    }
> +  }
> +
> +  if (RC->Socket == 0) {
> +    if (RC->Type == RCA) {
> +      if (RC->ID < 4) {
> +        NvParam = NV_SI_RO_BOARD_S0_RCA0_TXRX_G4PRESET + RC->ID * NVPARAM_SIZE;
> +      } else {
> +        NvParam = NV_SI_RO_BOARD_S0_RCA4_TXRX_G4PRESET + (RC->ID - 4) * NVPARAM_SIZE;
> +      }
> +    } else {
> +      NvParam = NV_SI_RO_BOARD_S0_RCB0A_TXRX_G4PRESET + (RC->ID - 4) * (2 * NVPARAM_SIZE);
> +    }
> +  } else if (RC->Type == RCA) {
> +    if (RC->ID < 4) {
> +      NvParam = NV_SI_RO_BOARD_S1_RCA2_TXRX_G4PRESET + (RC->ID - 2) * NVPARAM_SIZE;
> +    } else {
> +      NvParam = NV_SI_RO_BOARD_S1_RCA4_TXRX_G4PRESET + (RC->ID - 4) * NVPARAM_SIZE;
> +    }
> +  } else {
> +    NvParam = NV_SI_RO_BOARD_S1_RCB0A_TXRX_G4PRESET + (RC->ID - 4) * (2 * NVPARAM_SIZE);
> +  }
> +
> +  Ret = NVParamGet ((NVPARAM)NvParam, NV_PERM_ALL, &Nv);
> +  if (Ret == EFI_SUCCESS) {
> +    for (i = 0; i < 4; i++) {
> +      RC->PresetGen4[i] = (Nv >> (8 * i)) & 0xFF;
> +    }
> +  }
> +
> +  if (RC->Type == RCB) {
> +    NvParam += NVPARAM_SIZE;
> +    Ret = NVParamGet ((NVPARAM)NvParam, NV_PERM_ALL, &Nv);
> +    if (Ret == EFI_SUCCESS) {
> +      for (i = 0; i < 4; i++) {
> +        RC->PresetGen4[i + 4] = (Nv >> (8 * i)) & 0xFF;
> +      }
> +    }
> +  }
> +}
> +
> +VOID
> +EFIAPI
> +PcieBoardParseRCParams (
> +  IN AC01_RC *RC
> +  )
> +{
> +  UINT32             Efuse;
> +  PLATFORM_INFO_HOB  *PlatformHob;
> +  UINT8              PlatRCId;
> +  EFI_STATUS         Status;
> +  VOID               *Hob;
> +  UINTN              BufferSize;
> +  PCIE_VARSTORE_DATA VarStoreConfig = {
> +    .RCStatus = {TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE,
> +                 TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE},
> +    .RCBifurLo = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
> +    .RCBifurHi = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
> +    .SmmuPmu = 0
> +  };
> +
> +  PCIE_DEBUG ("%a - Socket%d RC%d\n", __FUNCTION__, RC->Socket, RC->ID);
> +
> +  PlatRCId = RC->Socket * RCS_PER_SOCKET + RC->ID;
> +  // Get RC activation status
> +  BufferSize = sizeof (PCIE_VARSTORE_DATA);
> +  Status = gRT->GetVariable (
> +                  VariableName,
> +                  &gPcieFormSetGuid,
> +                  NULL,
> +                  &BufferSize,
> +                  &VarStoreConfig
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    PCIE_DEBUG ("%a - Failed to read PCIE variable data from config store.\n", __FUNCTION__);
> +  }
> +
> +  RC->Active = VarStoreConfig.RCStatus[PlatRCId];
> +  RC->DevMapLo = VarStoreConfig.RCBifurLo[PlatRCId];
> +  RC->DevMapHi = VarStoreConfig.RCBifurHi[PlatRCId];
> +
> +  PCIE_DEBUG (
> +    "%a - Socket%d RC%d is %s\n",
> +    __FUNCTION__,
> +    RC->Socket,
> +    RC->ID,
> +    (RC->Active) ? "ACTIVE" : "INACTIVE"
> +    );
> +
> +  if (!IsSlaveSocketActive () && RC->Socket == 1) {
> +    RC->Active = FALSE;
> +  }
> +
> +  if (RC->Active) {
> +    //
> +    // Consolidate with E-fuse
> +    //
> +    Efuse = 0;
> +    Hob = GetFirstGuidHob (&gPlatformHobGuid);
> +    if (Hob != NULL) {
> +      PlatformHob = (PLATFORM_INFO_HOB *)GET_GUID_HOB_DATA (Hob);
> +      Efuse = PlatformHob->RcDisableMask[0] | (PlatformHob->RcDisableMask[1] << RCS_PER_SOCKET);
> +      PCIE_DEBUG (
> +        "RcDisableMask[0]: 0x%x [1]: 0x%x\n",
> +        PlatformHob->RcDisableMask[0],
> +        PlatformHob->RcDisableMask[1]
> +        );
> +
> +      // Update errata flags for Ampere Altra
> +      if ((PlatformHob->ScuProductId[0] & 0xff) == 0x01) {
> +        if (PlatformHob->AHBCId[0] == 0x20100
> +            || PlatformHob->AHBCId[0] == 0x21100
> +            || (IsSlaveSocketActive ()
> +                && (PlatformHob->AHBCId[1] == 0x20100
> +                    || PlatformHob->AHBCId[1] == 0x21100)))
> +        {
> +          RC->Flags |= PCIE_ERRATA_SPEED1;
> +          PCIE_DEBUG ("RC[%d]: Flags 0x%x\n", RC->ID, RC->Flags);
> +        }
> +      }
> +    }
> +
> +    RC->Active = (RC->Active && !(Efuse & BIT (PlatRCId))) ? TRUE : FALSE;
> +  }
> +
> +  /* Load Gen3/Gen4 preset */
> +  PcieBoardLoadPreset (RC);
> +  PcieBoardGetLaneAllocation (RC);
> +  PcieBoardSetupDevmap (RC);
> +  PcieBoardGetSpeed (RC);
> +}
> +
> +VOID
> +EFIAPI
> +PcieBoardReleaseAllPerst (
> +  IN UINT8 SocketId
> +  )
> +{
> +  UINT32 GpioIndex, GpioPin;
> +
> +  // Write 1 to all GPIO[16..21] to release all PERST
> +  GpioPin = GPIO_DWAPB_PINS_PER_SOCKET * SocketId + 16;
> +  for (GpioIndex = 0; GpioIndex < 6; GpioIndex++) {
> +    GpioModeConfig (GpioPin + GpioIndex, GPIO_CONFIG_OUT_HI);
> +  }
> +}
> +
> +VOID
> +EFIAPI
> +PcieBoardAssertPerst (
> +  AC01_RC *RC,
> +  UINT32  PcieIndex,
> +  UINT8   Bifurcation,
> +  BOOLEAN isPullToHigh

CamelCase uses leading capital letter.

> +  )
> +{
> +  UINT32 GpioGroupVal, Val, GpioIndex, GpioPin;
> +
> +  /*
> +   * For Post-silicon, Fansipan board is using GPIO combination (GPIO[16..21])
> +   * to control CPLD.
> +   * It should be follow PCIE RESET TABLE in Fansipan schematic.
> +   *
> +   * Depend on Bifurcation settings, will active corresponding PERST pin or not
> +   */
> +
> +  if (RC->Type == RCA) {
> +    switch (Bifurcation) {
> +    case 0:                 // RCA_BIFURCATION_ONE_X16:
> +      if (PcieIndex != 0) { // 1,2,3
> +      }
> +      break;
> +
> +    case 1:                                       // RCA_BIFURCATION_TWO_X8:

Wouldn't this look an awful lot better as
  case RCA_BIFURCATION_TWO_X8:
than with a live-coded integer, followed by a comment explaining what
that integer means?
This appplies throughout this function.

> +      if ((PcieIndex == 1) || (PcieIndex == 3)) { // 1,3
> +      }
> +      break;
> +
> +    case 2:                 // RCA_BIFURCATION_ONE_X8_TWO_X4:
> +      if (PcieIndex == 1) { // 1
> +      }
> +      break;
> +
> +    case 3: // RCA_BIFURCATION_FOUR_X4:
> +      break;
> +
> +    default:
> +      PCIE_DEBUG ("Invalid Bifurcation setting\n");
> +      break;
> +    }
> +  } else { // RCB
> +    switch (Bifurcation) {
> +    case 0:                                       // RCB_BIFURCATION_ONE_X8:
> +      if ((PcieIndex != 0) && (PcieIndex != 4)) { // 1,2,3,5,6,7
> +      }
> +      break;
> +
> +    case 1:                       // RCB_BIFURCATION_TWO_X4:
> +      if ((PcieIndex % 2) != 0) { // 1,3,5,7
> +      }
> +      break;
> +
> +    case 2: // RCB_BIFURCATION_ONE_X4_TWO_X2:
> +      if ((PcieIndex == 1) || (PcieIndex == 5)) {
> +      }
> +      break;
> +
> +    case 3: // RCB_BIFURCATION_FOUR_X2:
> +      break;
> +
> +    default:
> +      PCIE_DEBUG ("Invalid Bifurcation setting\n");
> +      break;
> +    }
> +  }
> +
> +  if (!isPullToHigh) { // Pull PERST to Low
> +    if (RC->Type == RCA) { // RCA: RC->ID: 0->3 ; PcieIndex: 0->3
> +      GpioGroupVal = 62 - RC->ID*4 - PcieIndex;

That 62 needs to be a #define.

> +    }
> +    else { // RCB: RC->ID: 4->7 ; PcieIndex: 0->7

else on same line as } 

> +      GpioGroupVal = 46 - (RC->ID - 4)*8 - PcieIndex;
> +    }
> +
> +    GpioPin = GPIO_DWAPB_PINS_PER_SOCKET * RC->Socket + 16;
> +    for (GpioIndex = 0; GpioIndex < 6; GpioIndex++) {
> +      // 6: Number of GPIO pins to control via CPLD
> +      Val = (GpioGroupVal & 0x3F) & (1 << GpioIndex);
> +      if (Val == 0) {
> +        GpioModeConfig (GpioPin + GpioIndex, GPIO_CONFIG_OUT_LOW);
> +      } else {
> +        GpioModeConfig (GpioPin + GpioIndex, GPIO_CONFIG_OUT_HI);
> +      }
> +    }
> +
> +    // Keep reset as low as 100 ms as specification
> +    MicroSecondDelay (100 * 1000);
> +  } else { // Pull PERST to High
> +    PcieBoardReleaseAllPerst (RC->Socket);
> +  }
> +}
> +
> +/**
> + * Overrride the segment number for a root complex with
> + * a board specific number.
> + **/
> +VOID
> +EFIAPI
> +PcieBoardGetRCSegmentNumber (
> +  IN  AC01_RC *RC,
> +  OUT UINTN   *SegmentNumber
> +  )
> +{
> +  if (RC->Socket == 0) {
> +    if (RC->Type == RCA) {
> +      switch (RC->ID) {
> +      case 0:
> +        *SegmentNumber = 12;
> +        break;
> +
> +      case 1:
> +        *SegmentNumber = 13;
> +        break;
> +
> +      case 2:
> +        *SegmentNumber = 1;
> +        break;
> +
> +      case 3:
> +        *SegmentNumber = 0;
> +        break;
> +
> +        default:
> +          *SegmentNumber = 16;
> +      }
> +    } else { /* Socket0, CCIX: RCA0 and RCA1 */
> +      *SegmentNumber = RC->ID - 2;
> +    }
> +  } else { /* Socket1, CCIX: RCA0 and RCA1 */
> +    if (RC->ID == 0 || RC->ID == 1) {
> +      *SegmentNumber = 16;
> +    } else {
> +      *SegmentNumber = 4 + RC->ID;
> +    }
> +  }
> +}
> +
> +BOOLEAN
> +EFIAPI
> +PcieBoardCheckSmmuPmuEnabled (
> +  VOID
> +  )
> +{
> +  EFI_GUID           PcieFormSetGuid = PCIE_FORM_SET_GUID;
> +  PCIE_VARSTORE_DATA VarStoreConfig;
> +  UINTN              BufferSize;
> +  EFI_STATUS         Status;
> +
> +  // Get Buffer Storage data from EFI variable
> +  BufferSize = sizeof (PCIE_VARSTORE_DATA);
> +  Status = gRT->GetVariable (
> +                  PCIE_VARSTORE_NAME,
> +                  &PcieFormSetGuid,
> +                  NULL,
> +                  &BufferSize,
> +                  &VarStoreConfig
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    return FALSE;
> +  }
> +
> +  return VarStoreConfig.SmmuPmu;
> +}
> diff --git a/Platform/Ampere/JadePkg/Library/PcieBoardLib/PcieBoardCommon.c b/Platform/Ampere/JadePkg/Library/PcieBoardLib/PcieBoardCommon.c
> new file mode 100644
> index 000000000000..a8accbf53047
> --- /dev/null
> +++ b/Platform/Ampere/JadePkg/Library/PcieBoardLib/PcieBoardCommon.c
> @@ -0,0 +1,327 @@
> +/** @file
> +
> +  Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include <Library/DebugLib.h>
> +#include <Library/NVParamLib.h>
> +#include <Library/SystemFirmwareInterfaceLib.h>
> +#include <NVParamDef.h>
> +
> +#include "Pcie.h"
> +
> +/* Host bridge registers */
> +#define HBRCAPDMR    0x0
> +#define HBRCBPDMR    0x4

Inappropriate names for this codebase.
Are these the actual register names as described in hardware manuals
for this device? If so, they can be permitted. But every file where
these names are used need to contain a glossary section at the start
of it, explaining what these actually are.
Applies also below.

> +
> +/* HBRCAPDMR */
> +#define RCAPCIDEVMAP_SET(dst, src) \
> +  (((dst) & ~0x7) | (((UINT32)(src)) & 0x7))
> +
> +/* HBRCBPDMR */
> +#define RCBPCIDEVMAPLO_SET(dst, src) \
> +  (((dst) & ~0x7) | (((UINT32)(src)) & 0x7))
> +#define RCBPCIDEVMAPHI_SET(dst, src) \
> +  (((dst) & ~0x70) | (((UINT32)(src) << 4) & 0x70))
> +
> +#define PCIE_GET_MAX_WIDTH(Pcie, Max) \
> +  !((Pcie).MaxWidth) ? (Max) : MIN((Pcie).MaxWidth, (Max))
> +
> +BOOLEAN
> +IsEmptyRC (
> +  IN AC01_RC *RC
> +  )
> +{
> +  INTN Idx;
> +
> +  for (Idx = PCIE_0; Idx < MAX_PCIE; Idx++) {
> +    if (RC->Pcie[Idx].Active) {
> +      return FALSE;
> +    }
> +  }
> +
> +  return TRUE;
> +}
> +
> +VOID
> +PcieBoardSetRCBifur (
> +  IN AC01_RC *RC,
> +  IN UINT8   RPStart,
> +  IN UINT8   DevMap
> +  )
> +{
> +  UINT8 MaxWidth;
> +
> +  if (RPStart != PCIE_0 && RPStart != PCIE_4) {
> +    return;
> +  }
> +
> +  if (RC->Type != RCB && RPStart == PCIE_4) {
> +    return;
> +  }
> +
> +  if (RC->Type == RCA && RC->Pcie[RPStart].MaxWidth == LNKW_X16) {
> +    RC->Pcie[RPStart + 1].MaxWidth = LNKW_X4;
> +    RC->Pcie[RPStart + 2].MaxWidth = LNKW_X8;
> +    RC->Pcie[RPStart + 3].MaxWidth = LNKW_X4;
> +  }
> +
> +  if (RC->Type == RCB && RC->Pcie[RPStart].MaxWidth == LNKW_X8) {
> +    RC->Pcie[RPStart + 1].MaxWidth = LNKW_X2;
> +    RC->Pcie[RPStart + 2].MaxWidth = LNKW_X4;
> +    RC->Pcie[RPStart + 3].MaxWidth = LNKW_X2;
> +  }
> +
> +  switch (DevMap) {
> +  case 1:

Would benefit from #defines with descriptive names rather than just
live-coded integers. (All cases in switch.)

> +    MaxWidth = (RC->Type == RCA) ? LNKW_X8 : LNKW_X4;
> +    RC->Pcie[RPStart].MaxWidth = PCIE_GET_MAX_WIDTH (RC->Pcie[RPStart], MaxWidth);
> +    RC->Pcie[RPStart + 1].Active = 0;
> +    RC->Pcie[RPStart + 2].MaxWidth = PCIE_GET_MAX_WIDTH (RC->Pcie[RPStart + 2], MaxWidth);
> +    RC->Pcie[RPStart + 2].Active = 1;
> +    RC->Pcie[RPStart + 3].Active = 0;
> +    break;
> +
> +  case 2:
> +    MaxWidth = (RC->Type == RCA) ? LNKW_X8 : LNKW_X4;
> +    RC->Pcie[RPStart].MaxWidth = PCIE_GET_MAX_WIDTH (RC->Pcie[RPStart], MaxWidth);
> +    RC->Pcie[RPStart + 1].Active = 0;
> +    MaxWidth = (RC->Type == RCA) ? LNKW_X4 : LNKW_X2;
> +    RC->Pcie[RPStart + 2].MaxWidth = PCIE_GET_MAX_WIDTH (RC->Pcie[RPStart + 2], MaxWidth);
> +    RC->Pcie[RPStart + 2].Active = 1;
> +    RC->Pcie[RPStart + 3].MaxWidth = PCIE_GET_MAX_WIDTH (RC->Pcie[RPStart + 3], MaxWidth);
> +    RC->Pcie[RPStart + 3].Active = 1;
> +    break;
> +
> +  case 3:
> +    MaxWidth = (RC->Type == RCA) ? LNKW_X4 : LNKW_X2;
> +    RC->Pcie[RPStart].MaxWidth = PCIE_GET_MAX_WIDTH (RC->Pcie[RPStart], MaxWidth);
> +    RC->Pcie[RPStart + 1].MaxWidth = PCIE_GET_MAX_WIDTH (RC->Pcie[RPStart + 1], MaxWidth);
> +    RC->Pcie[RPStart + 1].Active = 1;
> +    RC->Pcie[RPStart + 2].MaxWidth = PCIE_GET_MAX_WIDTH (RC->Pcie[RPStart + 2], MaxWidth);
> +    RC->Pcie[RPStart + 2].Active = 1;
> +    RC->Pcie[RPStart + 3].MaxWidth = PCIE_GET_MAX_WIDTH (RC->Pcie[RPStart + 3], MaxWidth);
> +    RC->Pcie[RPStart + 3].Active = 1;
> +    break;
> +
> +  case 0:
> +  default:
> +    MaxWidth = (RC->Type == RCA) ? LNKW_X16 : LNKW_X8;
> +    RC->Pcie[RPStart].MaxWidth = PCIE_GET_MAX_WIDTH (RC->Pcie[RPStart], MaxWidth);
> +    RC->Pcie[RPStart + 1].Active = 0;
> +    RC->Pcie[RPStart + 2].Active = 0;
> +    RC->Pcie[RPStart + 3].Active = 0;
> +    break;
> +  }
> +}
> +
> +VOID
> +PcieBoardGetLaneAllocation (
> +  IN AC01_RC *RC
> +  )
> +{
> +  INTN    RPIndex, Ret;
> +  UINT32  Nv, Width;
> +  NVPARAM NvParam;
> +
> +  // Retrieve lane allocation and capabilities for each controller
> +  if (RC->Type == RCA) {
> +    NvParam = NV_SI_RO_BOARD_S0_RCA0_CFG + RC->Socket * 96 +
> +                RC->ID * 8;
> +  } else {
> +    NvParam = NV_SI_RO_BOARD_S0_RCB0_LO_CFG + RC->Socket * 96 +
> +              (RC->ID - MAX_RCA) * 16;
> +  }

Please create descriptively named #defines for that 96, 16, and 8.

> +
> +  Ret = NVParamGet (NvParam, NV_PERM_ALL, &Nv);
> +  Nv = (Ret != EFI_SUCCESS) ? 0 : Nv;
> +
> +  for (RPIndex = 0; RPIndex < MAX_PCIE_A; RPIndex++) {
> +    Width = (Nv >> (RPIndex * 8)) & 0xF;
> +    switch (Width) {
> +    case 1:
> +    case 2:
> +    case 3:
> +    case 4:
> +      RC->Pcie[RPIndex].MaxWidth = 1 << Width;
> +      RC->Pcie[RPIndex].MaxGen = SPEED_GEN3;
> +      RC->Pcie[RPIndex].Active = TRUE;
> +      break;
> +
> +    case 0:
> +    default:
> +      RC->Pcie[RPIndex].MaxWidth = LNKW_NONE;
> +      RC->Pcie[RPIndex].MaxGen = 0;
> +      RC->Pcie[RPIndex].Active = FALSE;
> +      break;
> +    }
> +  }
> +
> +  if (RC->Type == RCB) {
> +    // Processing Hi
> +    NvParam += 8;
> +    Ret = NVParamGet (NvParam, NV_PERM_ALL, &Nv);
> +    Nv = (Ret != EFI_SUCCESS) ? 0 : Nv;
> +
> +    for (RPIndex = MAX_PCIE_A; RPIndex < MAX_PCIE; RPIndex++) {
> +      Width = (Nv >> ((RPIndex - MAX_PCIE_A) * 8)) & 0xF;

Same 8?

> +      switch (Width) {
> +      case 1:
> +      case 2:
> +      case 3:
> +      case 4:
> +        RC->Pcie[RPIndex].MaxWidth = 1 << Width;
> +        RC->Pcie[RPIndex].MaxGen = SPEED_GEN3;
> +        RC->Pcie[RPIndex].Active = TRUE;
> +        break;
> +
> +      case 0:
> +      default:
> +        RC->Pcie[RPIndex].MaxWidth = LNKW_NONE;
> +        RC->Pcie[RPIndex].MaxGen = 0;
> +        RC->Pcie[RPIndex].Active = FALSE;
> +        break;
> +      }
> +    }
> +  }
> +
> +  // Do not proceed if no Root Port enabled
> +  if (IsEmptyRC (RC)) {
> +    RC->Active = FALSE;
> +  }
> +}
> +
> +VOID
> +PcieBoardSetupDevmap (
> +  IN AC01_RC *RC
> +  )
> +{
> +  UINT32 Val;
> +
> +  if (RC->Pcie[PCIE_0].Active
> +      && RC->Pcie[PCIE_1].Active
> +      && RC->Pcie[PCIE_2].Active
> +      && RC->Pcie[PCIE_3].Active)
> +  {
> +    RC->DefaultDevMapLo = 3;

What's a DefaultDevMapLo?
The *only* benefit of SuperLongCamelCaseNames is that they actually
completely spell out what things are. This makes abbreviating them
extremely unfortunate, except where the abbreviation is completely
obvious regardless of context.

I also have a feeling these 0, 1, 2, 3 could benefit from being
replaced by descriptively named #defines.

> +  } else if (RC->Pcie[PCIE_0].Active
> +             && RC->Pcie[PCIE_2].Active
> +             && RC->Pcie[PCIE_3].Active)
> +  {
> +    RC->DefaultDevMapLo = 2;
> +  } else if (RC->Pcie[PCIE_0].Active
> +             && RC->Pcie[PCIE_2].Active)
> +  {
> +    RC->DefaultDevMapLo = 1;
> +  } else {
> +    RC->DefaultDevMapLo = 0;
> +  }
> +
> +  if (RC->Pcie[PCIE_4].Active
> +      && RC->Pcie[PCIE_5].Active
> +      && RC->Pcie[PCIE_6].Active
> +      && RC->Pcie[PCIE_7].Active)
> +  {
> +    RC->DefaultDevMapHi = 3;
> +  } else if (RC->Pcie[PCIE_4].Active
> +             && RC->Pcie[PCIE_6].Active
> +             && RC->Pcie[PCIE_7].Active)
> +  {
> +    RC->DefaultDevMapHi = 2;
> +  } else if (RC->Pcie[PCIE_4].Active
> +             && RC->Pcie[PCIE_6].Active)
> +  {
> +    RC->DefaultDevMapHi = 1;
> +  } else {
> +    RC->DefaultDevMapHi = 0;
> +  }
> +
> +  if (RC->DevMapLo == 0) {
> +    RC->DevMapLo = RC->DefaultDevMapLo;
> +  }
> +
> +  if (RC->Type == RCB && RC->DevMapHi == 0) {
> +    RC->DevMapHi = RC->DefaultDevMapHi;
> +  }
> +
> +  PcieBoardSetRCBifur (RC, PCIE_0, RC->DevMapLo);
> +  if (RC->Type == RCB) {
> +    PcieBoardSetRCBifur (RC, PCIE_4, RC->DevMapHi);
> +  }
> +
> +  if (RC->Active) {
> +    if (RC->Type == RCA) {
> +      if (!EFI_ERROR (MailboxMsgRegisterRead (RC->Socket, RC->HBAddr + HBRCAPDMR, &Val))) {
> +        Val = RCAPCIDEVMAP_SET (Val, RC->DevMapLo & 0x7);

Is this actively trying to obscure away runtime errors, or
are there valid situations where RC->DevMapLo may be higher than 7
and only the bottom 3 bits should be respected?
If so, a comment should explain.

> +        MailboxMsgRegisterWrite (RC->Socket, RC->HBAddr + HBRCAPDMR, Val);
> +      }
> +    } else {
> +      if (!EFI_ERROR (MailboxMsgRegisterRead (RC->Socket, RC->HBAddr + HBRCBPDMR, &Val))) {
> +        Val = RCBPCIDEVMAPLO_SET (Val, RC->DevMapLo & 0x7);
> +        Val = RCBPCIDEVMAPHI_SET (Val, RC->DevMapHi & 0x7);

Is this actively trying to obscure away runtime errors, or
are there valid situations where RC->DevMapLo or RC->DevMapHi may be
higher than 7 and only the bottom 3 bits should be respected?
If so, a comment should explain.

> +        MailboxMsgRegisterWrite (RC->Socket, RC->HBAddr + HBRCBPDMR, Val);
> +      }
> +    }
> +  }
> +}
> +
> +VOID
> +PcieBoardGetSpeed (
> +  IN AC01_RC *RC
> +  )
> +{
> +  UINT8 MaxGenTbl[MAX_PCIE_A] = { SPEED_GEN4, SPEED_GEN4, SPEED_GEN4, SPEED_GEN4 };         // Bifurcation 0: RCA x16 / RCB x8
> +  UINT8 MaxGenTblX8X4X4[MAX_PCIE_A] = { SPEED_GEN4, SPEED_GEN4, SPEED_GEN1, SPEED_GEN1 };   // Bifurcation 2: x8 x4 x4 (PCIE_ERRATA_SPEED1)
> +  UINT8 MaxGenTblX4X4X4X4[MAX_PCIE_A] = { SPEED_GEN1, SPEED_GEN1, SPEED_GEN1, SPEED_GEN1 }; // Bifurcation 3: x4 x4 x4 x4 (PCIE_ERRATA_SPEED1)
> +  UINT8 MaxGenTblRCB[MAX_PCIE_A] = { SPEED_GEN1, SPEED_GEN1, SPEED_GEN1, SPEED_GEN1 };      // RCB PCIE_ERRATA_SPEED1
> +  INTN  RPIdx;
> +  UINT8 *MaxGen;
> +
> +  ASSERT (MAX_PCIE_A == 4);
> +  ASSERT (MAX_PCIE == 8);
> +
> +  //
> +  // Due to hardware errata, for A0/A1*
> +  //  RCB is limited to Gen1 speed.
> +  //  RCA x16, x8 port supports up to Gen4,
> +  //  RCA x4 port only supports Gen1.
> +  //
> +  MaxGen = MaxGenTbl;
> +  if (RC->Type == RCB) {
> +    if (RC->Flags & PCIE_ERRATA_SPEED1) {
> +      MaxGen = MaxGenTblRCB;
> +    }
> +  } else {
> +    switch (RC->DevMapLo) {
> +    case 2: /* x8 x4 x4 */

#define for these 2, 3, and 1.

> +      if (RC->Flags & PCIE_ERRATA_SPEED1) {
> +        MaxGen = MaxGenTblX8X4X4;
> +      }
> +      break;
> +
> +    case 3: /* X4 x4 x4 x4 */
> +      if (RC->Flags & PCIE_ERRATA_SPEED1) {
> +        MaxGen = MaxGenTblX4X4X4X4;
> +      }
> +      break;
> +
> +    case 1: /* x8 x8 */
> +    default:
> +      break;
> +    }
> +  }
> +
> +  for (RPIdx = 0; RPIdx < MAX_PCIE_A; RPIdx++) {
> +    RC->Pcie[RPIdx].MaxGen = RC->Pcie[RPIdx].Active ? MaxGen[RPIdx] : 0;
> +  }
> +
> +  if (RC->Type == RCB) {
> +    for (RPIdx = MAX_PCIE_A; RPIdx < MAX_PCIE; RPIdx++) {
> +      RC->Pcie[RPIdx].MaxGen = RC->Pcie[RPIdx].Active ?
> +                               MaxGen[RPIdx - MAX_PCIE_A] : 0;
> +    }
> +  }
> +}
> diff --git a/Platform/Ampere/JadePkg/Library/PcieBoardLib/PcieBoardScreen.c b/Platform/Ampere/JadePkg/Library/PcieBoardLib/PcieBoardScreen.c
> new file mode 100644
> index 000000000000..309cc8857b8c
> --- /dev/null
> +++ b/Platform/Ampere/JadePkg/Library/PcieBoardLib/PcieBoardScreen.c
> @@ -0,0 +1,1120 @@
> +/** @file
> +
> +  Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include <Guid/PlatformInfoHobGuid.h>
> +#include <Library/AmpereCpuLib.h>
> +#include <Library/HobLib.h>
> +#include <Library/NVParamLib.h>
> +#include <Library/PcieBoardLib.h>
> +#include <Library/UefiRuntimeServicesTableLib.h>
> +#include <NVParamDef.h>
> +#include <Pcie.h>
> +#include <PlatformInfoHob.h>
> +
> +#include "PcieBoardScreen.h"
> +
> +#ifndef BIT
> +#define BIT(nr) (1 << (nr))
> +#endif
> +
> +#define MAX_STRING_SIZE     32
> +
> +CHAR16   VariableName[]     = PCIE_VARSTORE_NAME;
> +EFI_GUID gPcieFormSetGuid   = PCIE_FORM_SET_GUID;
> +
> +EFI_HANDLE               DriverHandle = NULL;
> +PCIE_SCREEN_PRIVATE_DATA *mPrivateData = NULL;
> +
> +AC01_RC RCList[MAX_AC01_PCIE_ROOT_COMPLEX];
> +
> +HII_VENDOR_DEVICE_PATH mHiiVendorDevicePath = {
> +  {
> +    {
> +      HARDWARE_DEVICE_PATH,
> +      HW_VENDOR_DP,
> +      {
> +        (UINT8)(sizeof (VENDOR_DEVICE_PATH)),
> +        (UINT8)((sizeof (VENDOR_DEVICE_PATH)) >> 8)
> +      }
> +    },
> +    PCIE_FORM_SET_GUID
> +  },
> +  {
> +    END_DEVICE_PATH_TYPE,
> +    END_ENTIRE_DEVICE_PATH_SUBTYPE,
> +    {
> +      (UINT8)(END_DEVICE_PATH_LENGTH),
> +      (UINT8)((END_DEVICE_PATH_LENGTH) >> 8)
> +    }
> +  }
> +};
> +
> +/**
> +  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_OUT_OF_RESOURCES   Not enough memory to store the results.
> +  @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;
> +  PCIE_SCREEN_PRIVATE_DATA        *PrivateData;
> +  EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
> +  EFI_STRING                      ConfigRequest;
> +  EFI_STRING                      ConfigRequestHdr;
> +  UINTN                           Size;
> +  CHAR16                          *StrPointer;
> +  BOOLEAN                         AllocatedRequest;
> +  PCIE_VARSTORE_DATA              *VarStoreConfig;
> +
> +  if (Progress == NULL || Results == NULL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  //
> +  // Initialize the local variables.
> +  //
> +  ConfigRequestHdr  = NULL;
> +  ConfigRequest     = NULL;
> +  Size              = 0;
> +  *Progress         = Request;
> +  AllocatedRequest  = FALSE;
> +
> +  PrivateData = PCIE_SCREEN_PRIVATE_FROM_THIS (This);
> +  HiiConfigRouting = PrivateData->HiiConfigRouting;
> +  VarStoreConfig = &PrivateData->VarStoreConfig;
> +  ASSERT (VarStoreConfig != NULL);
> +
> +  //
> +  // Get Buffer Storage data from EFI variable.
> +  // Try to get the current setting from variable.
> +  //
> +  BufferSize = sizeof (PCIE_VARSTORE_DATA);
> +  Status = gRT->GetVariable (
> +                  VariableName,
> +                  &gPcieFormSetGuid,
> +                  NULL,
> +                  &BufferSize,
> +                  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 (
> +                         &gPcieFormSetGuid,
> +                         VariableName,
> +                         PrivateData->DriverHandle
> +                         );
> +    if (ConfigRequestHdr == NULL) {
> +      return EFI_OUT_OF_RESOURCES;
> +    }
> +    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, &gPcieFormSetGuid, 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);

What is 32?

> +        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 *)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;
> +  PCIE_SCREEN_PRIVATE_DATA        *PrivateData;
> +  EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
> +  PCIE_VARSTORE_DATA              *VarStoreConfig;
> +
> +  if (Configuration == NULL || Progress == NULL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  PrivateData = PCIE_SCREEN_PRIVATE_FROM_THIS (This);
> +  HiiConfigRouting = PrivateData->HiiConfigRouting;
> +  *Progress = Configuration;
> +  VarStoreConfig = &PrivateData->VarStoreConfig;
> +  ASSERT (VarStoreConfig != NULL);
> +
> +  //
> +  // Check routing data in <ConfigHdr>.
> +  // Note: if only one Storage is used, then this checking could be skipped.
> +  //
> +  if (!HiiIsConfigHdrMatch (Configuration, &gPcieFormSetGuid, NULL)) {
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  //
> +  // Get Buffer Storage data from EFI variable
> +  //
> +  BufferSize = sizeof (PCIE_VARSTORE_DATA);
> +  Status = gRT->GetVariable (
> +                  VariableName,
> +                  &gPcieFormSetGuid,
> +                  NULL,
> +                  &BufferSize,
> +                  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 (PCIE_VARSTORE_DATA);
> +  Status = HiiConfigRouting->ConfigToBlock (
> +                               HiiConfigRouting,
> +                               Configuration,
> +                               (UINT8 *)VarStoreConfig,
> +                               &BufferSize,
> +                               Progress
> +                               );
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // Store Buffer Storage back to variable
> +  //
> +  Status = gRT->SetVariable (
> +                  VariableName,
> +                  &gPcieFormSetGuid,
> +                  EFI_VARIABLE_NON_VOLATILE |
> +                  EFI_VARIABLE_BOOTSERVICE_ACCESS |
> +                  EFI_VARIABLE_RUNTIME_ACCESS,
> +                  sizeof (PCIE_VARSTORE_DATA),
> +                  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_OUT_OF_RESOURCES   Not enough storage is available to hold the
> +                                 variable and its data.
> +  @retval EFI_DEVICE_ERROR       The variable could not be saved.
> +  @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
> +  )
> +{
> +  PCIE_VARSTORE_DATA       *VarStoreConfig;
> +  PCIE_SCREEN_PRIVATE_DATA *PrivateData;
> +  EFI_STATUS               Status;
> +
> +  if (((Value == NULL) &&
> +       (Action != EFI_BROWSER_ACTION_FORM_OPEN) &&
> +       (Action != EFI_BROWSER_ACTION_FORM_CLOSE)) ||
> +      (ActionRequest == NULL))
> +  {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  PrivateData = PCIE_SCREEN_PRIVATE_FROM_THIS (This);
> +  VarStoreConfig = &PrivateData->VarStoreConfig;
> +  ASSERT (VarStoreConfig != NULL);
> +
> +  Status = EFI_SUCCESS;
> +
> +  switch (Action) {
> +  case EFI_BROWSER_ACTION_FORM_OPEN:
> +    break;
> +
> +  case EFI_BROWSER_ACTION_FORM_CLOSE:
> +    break;
> +
> +  case EFI_BROWSER_ACTION_DEFAULT_STANDARD:
> +  case EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING:
> +    if (QuestionId == 0x9000) {
> +      /* SMMU PMU */
> +      Value->u32 = 0; /* default disable */
> +      break;
> +    }
> +
> +    switch ((QuestionId - 0x8002) % MAX_EDITABLE_ELEMENTS) {
> +    case 0:
> +      Value->u8 = PcieRCActiveDefaultSetting ((QuestionId - 0x8002) / MAX_EDITABLE_ELEMENTS, PrivateData);
> +      break;
> +
> +    case 1:
> +      Value->u8 = PcieRCDevMapLoDefaultSetting ((QuestionId - 0x8002) / MAX_EDITABLE_ELEMENTS, PrivateData);
> +      break;
> +
> +    case 2:
> +      Value->u8 = PcieRCDevMapHiDefaultSetting ((QuestionId - 0x8002) / MAX_EDITABLE_ELEMENTS, PrivateData);
> +      break;
> +    }
> +    break;
> +
> +  case EFI_BROWSER_ACTION_RETRIEVE:
> +  case EFI_BROWSER_ACTION_CHANGING:
> +  case EFI_BROWSER_ACTION_SUBMITTED:
> +    break;
> +
> +  default:
> +    Status = EFI_UNSUPPORTED;
> +    break;
> +  }
> +
> +  return Status;
> +}
> +
> +EFI_STATUS
> +PcieScreenUnload (
> +  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;
> +}
> +
> +/**
> +  This function return default settings for Dev Map LO.
> +  @param  RC                     Root Complex ID.
> +  @param  PrivateData            Private data.
> +
> +  @retval Default dev settings.
> +**/
> +UINT8
> +PcieRCDevMapLoDefaultSetting (
> +  IN UINTN                    RCIndex,
> +  IN PCIE_SCREEN_PRIVATE_DATA *PrivateData
> +  )
> +{
> +  AC01_RC *RC = &RCList[RCIndex];
> +
> +  return RC->DefaultDevMapLo;
> +}
> +
> +/**
> +  This function return default settings for Dev Map HI.
> +  @param  RC                     Root Complex ID.
> +  @param  PrivateData            Private data.
> +
> +  @retval Default dev settings.
> +**/
> +UINT8
> +PcieRCDevMapHiDefaultSetting (
> +  IN UINTN                    RCIndex,
> +  IN PCIE_SCREEN_PRIVATE_DATA *PrivateData
> +  )
> +{
> +  AC01_RC *RC = &RCList[RCIndex];
> +
> +  return RC->DefaultDevMapHi;
> +}
> +
> +BOOLEAN
> +PcieRCActiveDefaultSetting (
> +  IN UINTN                    RCIndex,
> +  IN PCIE_SCREEN_PRIVATE_DATA *PrivateData
> +  )
> +{
> +  PLATFORM_INFO_HOB  *PlatformHob;
> +  VOID               *Hob;
> +  UINT32             Efuse;
> +
> +  // FIXME: Disable Root Complex 6 (USB and VGA) as default

Please get rid of the FIXME

> +  if (RCIndex == 6) {
> +    return FALSE;
> +  }
> +
> +  Hob = GetFirstGuidHob (&gPlatformHobGuid);
> +  if (Hob != NULL) {
> +    PlatformHob = (PLATFORM_INFO_HOB *)GET_GUID_HOB_DATA (Hob);
> +    Efuse = PlatformHob->RcDisableMask[0] | (PlatformHob->RcDisableMask[1] << RCS_PER_SOCKET);
> +    return (!(Efuse & BIT (RCIndex))) ? TRUE : FALSE;
> +  }
> +
> +  return FALSE;
> +}
> +
> +/**
> +  This function sets up the first elements of the form.
> +  @param  RC                     Root Complex ID.
> +  @param  PrivateData            Private data.
> +  @retval EFI_SUCCESS            The form is set up successfully.
> +**/
> +EFI_STATUS
> +PcieRCScreenSetup (
> +  IN UINTN                    RCIndex,
> +  IN PCIE_SCREEN_PRIVATE_DATA *PrivateData
> +  )
> +{
> +  VOID               *StartOpCodeHandle;
> +  EFI_IFR_GUID_LABEL *StartLabel;
> +  VOID               *EndOpCodeHandle;
> +  EFI_IFR_GUID_LABEL *EndLabel;
> +  VOID               *OptionsOpCodeHandle;
> +  VOID               *OptionsHiOpCodeHandle;
> +  CHAR16             Str[MAX_STRING_SIZE];
> +  UINT16             DisabledStatusVarOffset;
> +  UINT16             BifurLoVarOffset;
> +  UINT16             BifurHiVarOffset;
> +  UINT8              QuestionFlags, QuestionFlagsSubItem;
> +  AC01_RC            *RC;
> +
> +  RC = &RCList[RCIndex];
> +
> +  // 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_RC0_UPDATE + 2 * RCIndex;
> +
> +  // 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_RC0_END + 2 * RCIndex;
> +
> +  // Create textbox to tell socket
> +  HiiCreateTextOpCode (
> +    StartOpCodeHandle,
> +    STRING_TOKEN (STR_PCIE_SOCKET),
> +    STRING_TOKEN (STR_PCIE_SOCKET_HELP),
> +    HiiSetString (
> +      PrivateData->HiiHandle,
> +      0,
> +      (RC->Socket) ? L"1" : L"0",
> +      NULL
> +      )
> +    );
> +
> +  // Create textbox to tell Root Complex type
> +  HiiCreateTextOpCode (
> +    StartOpCodeHandle,
> +    STRING_TOKEN (STR_PCIE_RC_TYPE),
> +    STRING_TOKEN (STR_PCIE_RC_TYPE_HELP),
> +    HiiSetString (
> +      PrivateData->HiiHandle,
> +      0,
> +      (RC->Type == RCA) ? L"Root Complex Type-A" : L"Root Complex Type-B",
> +      NULL
> +      )
> +    );
> +
> +  UnicodeSPrint (Str, sizeof (Str), L"Root Complex #%2d", RCIndex);
> +
> +  DisabledStatusVarOffset = (UINT16)PCIE_RC0_STATUS_OFFSET +
> +                            sizeof (BOOLEAN) * RCIndex;
> +  BifurLoVarOffset = (UINT16)PCIE_RC0_BIFUR_LO_OFFSET +
> +                     sizeof (UINT8) * RCIndex;
> +  BifurHiVarOffset = (UINT16)PCIE_RC0_BIFUR_HI_OFFSET +
> +                     sizeof (UINT8) * RCIndex;
> +
> +  QuestionFlags = EFI_IFR_FLAG_RESET_REQUIRED | EFI_IFR_FLAG_CALLBACK;
> +  if (IsEmptyRC (RC)
> +      || (GetNumberOfActiveSockets () == 1 && RC->Socket == 1))
> +  {
> +    //
> +    // Do not allow changing if none of Root Port underneath enabled
> +    // or slave Root Complex on 1P system.
> +    //
> +    QuestionFlags |= EFI_IFR_FLAG_READ_ONLY;
> +  }
> +  // Create the RC disabled checkbox
> +  HiiCreateCheckBoxOpCode (
> +    StartOpCodeHandle,                        // Container for dynamic created opcodes
> +    0x8002 + MAX_EDITABLE_ELEMENTS * RCIndex, // QuestionId (or "key")
> +    PCIE_VARSTORE_ID,                         // VarStoreId
> +    DisabledStatusVarOffset,                  // VarOffset in Buffer Storage
> +    HiiSetString (
> +      PrivateData->HiiHandle,
> +      0,
> +      Str,
> +      NULL
> +      ),                                       // Prompt
> +    STRING_TOKEN (STR_PCIE_RC_STATUS_HELP),    // Help
> +    QuestionFlags,                             // QuestionFlags
> +    0,                                         // CheckBoxFlags
> +    NULL                                       // DefaultsOpCodeHandle
> +    );
> +
> +  if (RC->Type == RCA) {
> +    // Create Option OpCode to display bifurcation for RCA
> +    OptionsOpCodeHandle = HiiAllocateOpCodeHandle ();
> +    ASSERT (OptionsOpCodeHandle != NULL);
> +
> +    HiiCreateOneOfOptionOpCode (
> +      OptionsOpCodeHandle,
> +      STRING_TOKEN (STR_PCIE_BIFUR_SELECT_VALUE0),
> +      0,
> +      EFI_IFR_NUMERIC_SIZE_1,
> +      0 // Devmap=0
> +      );
> +
> +
> +    if (RC->DefaultDevMapLo != 0) {
> +      QuestionFlags |= EFI_IFR_FLAG_READ_ONLY;
> +    }
> +
> +    HiiCreateOneOfOptionOpCode (
> +      OptionsOpCodeHandle,
> +      STRING_TOKEN (STR_PCIE_BIFUR_SELECT_VALUE1),
> +      0,
> +      EFI_IFR_NUMERIC_SIZE_1,
> +      1 // Devmap=1
> +      );
> +
> +    HiiCreateOneOfOptionOpCode (
> +      OptionsOpCodeHandle,
> +      STRING_TOKEN (STR_PCIE_BIFUR_SELECT_VALUE2),
> +      0,
> +      EFI_IFR_NUMERIC_SIZE_1,
> +      2 // Devmap=2
> +      );
> +
> +    HiiCreateOneOfOptionOpCode (
> +      OptionsOpCodeHandle,
> +      STRING_TOKEN (STR_PCIE_BIFUR_SELECT_VALUE3),
> +      0,
> +      EFI_IFR_NUMERIC_SIZE_1,
> +      3 // Devmap=3
> +      );
> +
> +    HiiCreateOneOfOpCode (
> +      StartOpCodeHandle,                        // Container for dynamic created opcodes
> +      0x8003 + MAX_EDITABLE_ELEMENTS * RCIndex, // Question ID (or call it "key")
> +      PCIE_VARSTORE_ID,                         // VarStore ID
> +      BifurLoVarOffset,                         // Offset in Buffer Storage
> +      STRING_TOKEN (STR_PCIE_RCA_BIFUR),        // Question prompt text
> +      STRING_TOKEN (STR_PCIE_RCA_BIFUR_HELP),   // Question help text
> +      QuestionFlags,                            // Question flag
> +      EFI_IFR_NUMERIC_SIZE_1,                   // Data type of Question Value
> +      OptionsOpCodeHandle,                      // Option Opcode list
> +      NULL                                      // Default Opcode is NULl
> +      );
> +  } else {
> +    // Create Option OpCode to display bifurcation for RCB-Lo
> +    OptionsOpCodeHandle = HiiAllocateOpCodeHandle ();
> +    ASSERT (OptionsOpCodeHandle != NULL);
> +
> +    HiiCreateOneOfOptionOpCode (
> +      OptionsOpCodeHandle,
> +      STRING_TOKEN (STR_PCIE_BIFUR_SELECT_VALUE4),
> +      0,
> +      EFI_IFR_NUMERIC_SIZE_1,
> +      0 // Devmap=0
> +      );
> +
> +    QuestionFlagsSubItem = QuestionFlags;
> +    if (RC->DefaultDevMapLo != 0) {
> +      QuestionFlagsSubItem |= EFI_IFR_FLAG_READ_ONLY;
> +    }
> +
> +    HiiCreateOneOfOptionOpCode (
> +      OptionsOpCodeHandle,
> +      STRING_TOKEN (STR_PCIE_BIFUR_SELECT_VALUE5),
> +      0,
> +      EFI_IFR_NUMERIC_SIZE_1,
> +      1 // Devmap=1
> +      );
> +
> +    HiiCreateOneOfOptionOpCode (
> +      OptionsOpCodeHandle,
> +      STRING_TOKEN (STR_PCIE_BIFUR_SELECT_VALUE6),
> +      0,
> +      EFI_IFR_NUMERIC_SIZE_1,
> +      2 // Devmap=2
> +      );
> +
> +    HiiCreateOneOfOptionOpCode (
> +      OptionsOpCodeHandle,
> +      STRING_TOKEN (STR_PCIE_BIFUR_SELECT_VALUE7),
> +      0,
> +      EFI_IFR_NUMERIC_SIZE_1,
> +      3 // Devmap=3
> +      );
> +
> +    HiiCreateOneOfOpCode (
> +      StartOpCodeHandle,                         // Container for dynamic created opcodes
> +      0x8003 + MAX_EDITABLE_ELEMENTS * RCIndex,  // Question ID (or call it "key")
> +      PCIE_VARSTORE_ID,                          // VarStore ID
> +      BifurLoVarOffset,                          // Offset in Buffer Storage
> +      STRING_TOKEN (STR_PCIE_RCB_LO_BIFUR),      // Question prompt text
> +      STRING_TOKEN (STR_PCIE_RCB_LO_BIFUR_HELP), // Question help text
> +      QuestionFlagsSubItem,                      // Question flag
> +      EFI_IFR_NUMERIC_SIZE_1,                    // Data type of Question Value
> +      OptionsOpCodeHandle,                       // Option Opcode list
> +      NULL                                       // Default Opcode is NULl
> +      );
> +
> +    // Create Option OpCode to display bifurcation for RCB-Hi
> +    OptionsHiOpCodeHandle = HiiAllocateOpCodeHandle ();
> +    ASSERT (OptionsHiOpCodeHandle != NULL);
> +
> +    QuestionFlagsSubItem = QuestionFlags;
> +    if (RC->DefaultDevMapHi != 0) {
> +      QuestionFlagsSubItem |= EFI_IFR_FLAG_READ_ONLY;
> +    }
> +
> +    HiiCreateOneOfOptionOpCode (
> +      OptionsHiOpCodeHandle,
> +      STRING_TOKEN (STR_PCIE_BIFUR_SELECT_VALUE4),
> +      0,
> +      EFI_IFR_NUMERIC_SIZE_1,
> +      0 // Devmap=0
> +      );
> +
> +    HiiCreateOneOfOptionOpCode (
> +      OptionsHiOpCodeHandle,
> +      STRING_TOKEN (STR_PCIE_BIFUR_SELECT_VALUE5),
> +      0,
> +      EFI_IFR_NUMERIC_SIZE_1,
> +      1 // Devmap=1
> +      );
> +
> +    HiiCreateOneOfOptionOpCode (
> +      OptionsHiOpCodeHandle,
> +      STRING_TOKEN (STR_PCIE_BIFUR_SELECT_VALUE6),
> +      0,
> +      EFI_IFR_NUMERIC_SIZE_1,
> +      2 // Devmap=2
> +      );
> +
> +    HiiCreateOneOfOptionOpCode (
> +      OptionsHiOpCodeHandle,
> +      STRING_TOKEN (STR_PCIE_BIFUR_SELECT_VALUE7),
> +      0,
> +      EFI_IFR_NUMERIC_SIZE_1,
> +      3 // Devmap=3
> +      );
> +
> +    HiiCreateOneOfOpCode (
> +      StartOpCodeHandle,                         // Container for dynamic created opcodes
> +      0x8004 + MAX_EDITABLE_ELEMENTS * RCIndex,  // Question ID (or call it "key")
> +      PCIE_VARSTORE_ID,                          // VarStore ID
> +      BifurHiVarOffset,                          // Offset in Buffer Storage
> +      STRING_TOKEN (STR_PCIE_RCB_HI_BIFUR),      // Question prompt text
> +      STRING_TOKEN (STR_PCIE_RCB_HI_BIFUR_HELP), // Question help text
> +      QuestionFlagsSubItem,                      // Question flag
> +      EFI_IFR_NUMERIC_SIZE_1,                    // Data type of Question Value
> +      OptionsHiOpCodeHandle,                     // Option Opcode list
> +      NULL                                       // Default Opcode is NULl
> +      );
> +  }
> +
> +  HiiUpdateForm (
> +    PrivateData->HiiHandle,     // HII handle
> +    &gPcieFormSetGuid,          // Formset GUID
> +    PCIE_RC0_FORM_ID + RCIndex, // Form ID
> +    StartOpCodeHandle,          // Label for where to insert opcodes
> +    EndOpCodeHandle             // Insert data
> +    );
> +
> +  HiiFreeOpCodeHandle (StartOpCodeHandle);
> +  HiiFreeOpCodeHandle (EndOpCodeHandle);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  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
> +PcieMainScreenSetup (
> +  IN PCIE_SCREEN_PRIVATE_DATA *PrivateData
> +  )
> +{
> +  VOID                 *StartOpCodeHandle;
> +  EFI_IFR_GUID_LABEL   *StartLabel;
> +  VOID                 *EndOpCodeHandle;
> +  EFI_IFR_GUID_LABEL   *EndLabel;
> +  CHAR16               Str[MAX_STRING_SIZE];
> +  UINTN                RC;
> +  PCIE_SETUP_GOTO_DATA *GotoItem = NULL;
> +  EFI_QUESTION_ID      GotoId;
> +
> +  // 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;
> +
> +  HiiCreateCheckBoxOpCode (
> +    StartOpCodeHandle,                       // Container for dynamic created opcodes
> +    0x9000,                                  // Question ID
> +    PCIE_VARSTORE_ID,                        // VarStore ID
> +    (UINT16)PCIE_SMMU_PMU_OFFSET,            // Offset in Buffer Storage
> +    STRING_TOKEN (STR_PCIE_SMMU_PMU_PROMPT), // Question prompt text
> +    STRING_TOKEN (STR_PCIE_SMMU_PMU_HELP),   // Question help text
> +    EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED,
> +    0,
> +    NULL
> +    );
> +
> +  //
> +  // Create the a seperated line
> +  //
> +  HiiCreateTextOpCode (
> +    StartOpCodeHandle,
> +    STRING_TOKEN (STR_PCIE_FORM_SEPERATE_LINE),
> +    STRING_TOKEN (STR_PCIE_FORM_SEPERATE_LINE),
> +    STRING_TOKEN (STR_PCIE_FORM_SEPERATE_LINE)
> +    );
> +
> +  // Create Goto form for each RC
> +  for (RC = 0; RC < MAX_AC01_PCIE_ROOT_COMPLEX; RC++) {
> +
> +    GotoItem = AllocateZeroPool (sizeof (PCIE_SETUP_GOTO_DATA));
> +    if (GotoItem == NULL) {
> +      return EFI_OUT_OF_RESOURCES;
> +    }
> +    GotoItem->PciDevIdx = RC;
> +
> +    GotoId = PCIE_GOTO_ID_BASE + (UINT16)RC;
> +
> +    // Update HII string
> +    UnicodeSPrint (Str, sizeof (Str), L"Root Complex #%2d", RC);
> +    GotoItem->GotoStringId = HiiSetString (
> +                               PrivateData->HiiHandle,
> +                               0,
> +                               Str,
> +                               NULL
> +                               );
> +    GotoItem->GotoHelpStringId = STRING_TOKEN (STR_PCIE_GOTO_HELP);
> +    GotoItem->ShowItem = TRUE;
> +
> +    // Add goto control
> +    HiiCreateGotoOpCode (
> +      StartOpCodeHandle,
> +      PCIE_RC0_FORM_ID + RC,
> +      GotoItem->GotoStringId,
> +      GotoItem->GotoHelpStringId,
> +      EFI_IFR_FLAG_CALLBACK,
> +      GotoId
> +      );
> +  }
> +
> +  HiiUpdateForm (
> +    PrivateData->HiiHandle,  // HII handle
> +    &gPcieFormSetGuid,       // Formset GUID
> +    PCIE_FORM_ID,            // Form ID
> +    StartOpCodeHandle,       // Label for where to insert opcodes
> +    EndOpCodeHandle          // Insert data
> +    );
> +
> +  HiiFreeOpCodeHandle (StartOpCodeHandle);
> +  HiiFreeOpCodeHandle (EndOpCodeHandle);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +EFI_STATUS
> +PcieBoardScreenInitialize (
> +  IN EFI_HANDLE       ImageHandle,
> +  IN EFI_SYSTEM_TABLE *SystemTable,
> +  IN AC01_RC          *NewRCList
> +  )
> +{
> +  EFI_STATUS                          Status;
> +  EFI_HII_HANDLE                      HiiHandle;
> +  EFI_HII_DATABASE_PROTOCOL           *HiiDatabase;
> +  EFI_HII_STRING_PROTOCOL             *HiiString;
> +  EFI_HII_CONFIG_ROUTING_PROTOCOL     *HiiConfigRouting;
> +  EFI_CONFIG_KEYWORD_HANDLER_PROTOCOL *HiiKeywordHandler;
> +  UINTN                               BufferSize;
> +  BOOLEAN                             IsUpdated;
> +  PCIE_VARSTORE_DATA                  *VarStoreConfig;
> +  UINT8                               RCIndex;
> +  AC01_RC                             *RC;
> +
> +  //
> +  // Initialize driver private data
> +  //
> +  mPrivateData = AllocateZeroPool (sizeof (PCIE_SCREEN_PRIVATE_DATA));
> +  if (mPrivateData == NULL) {
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  mPrivateData->Signature = PCIE_SCREEN_PRIVATE_DATA_SIGNATURE;
> +
> +  mPrivateData->ConfigAccess.ExtractConfig = ExtractConfig;
> +  mPrivateData->ConfigAccess.RouteConfig = RouteConfig;
> +  mPrivateData->ConfigAccess.Callback = DriverCallback;
> +
> +  //
> +  // Locate Hii Database protocol
> +  //
> +  Status = gBS->LocateProtocol (
> +                  &gEfiHiiDatabaseProtocolGuid,
> +                  NULL,
> +                  (VOID **)&HiiDatabase
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +  mPrivateData->HiiDatabase = HiiDatabase;
> +
> +  //
> +  // Locate HiiString protocol
> +  //
> +  Status = gBS->LocateProtocol (
> +                  &gEfiHiiStringProtocolGuid,
> +                  NULL,
> +                  (VOID **)&HiiString
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +  mPrivateData->HiiString = HiiString;
> +
> +  //
> +  // Locate ConfigRouting protocol
> +  //
> +  Status = gBS->LocateProtocol (
> +                  &gEfiHiiConfigRoutingProtocolGuid,
> +                  NULL,
> +                  (VOID **)&HiiConfigRouting
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +  mPrivateData->HiiConfigRouting = HiiConfigRouting;
> +
> +  //
> +  // Locate keyword handler protocol
> +  //
> +  Status = gBS->LocateProtocol (
> +                  &gEfiConfigKeywordHandlerProtocolGuid,
> +                  NULL,
> +                  (VOID **)&HiiKeywordHandler
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +  mPrivateData->HiiKeywordHandler = HiiKeywordHandler;
> +
> +  Status = gBS->InstallMultipleProtocolInterfaces (
> +                  &DriverHandle,
> +                  &gEfiDevicePathProtocolGuid,
> +                  &mHiiVendorDevicePath,
> +                  &gEfiHiiConfigAccessProtocolGuid,
> +                  &mPrivateData->ConfigAccess,
> +                  NULL
> +                  );
> +  ASSERT_EFI_ERROR (Status);
> +
> +  mPrivateData->DriverHandle = DriverHandle;
> +
> +  //
> +  // Publish our HII data
> +  //
> +  HiiHandle = HiiAddPackages (
> +                &gPcieFormSetGuid,
> +                DriverHandle,
> +                PcieBoardLibStrings,
> +                VfrBin,
> +                NULL
> +                );
> +  if (HiiHandle == NULL) {
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  mPrivateData->HiiHandle = HiiHandle;
> +
> +  // Make a shadow copy all Root Complexes' properties
> +  CopyMem ((VOID *)RCList, (VOID *)NewRCList, sizeof (RCList));
> +
> +  //
> +  // Initialize efi varstore configuration data
> +  //
> +  VarStoreConfig = &mPrivateData->VarStoreConfig;
> +  ZeroMem (VarStoreConfig, sizeof (PCIE_VARSTORE_DATA));
> +
> +  // Get Buffer Storage data from EFI variable
> +  BufferSize = sizeof (PCIE_VARSTORE_DATA);
> +  Status = gRT->GetVariable (
> +                  VariableName,
> +                  &gPcieFormSetGuid,
> +                  NULL,
> +                  &BufferSize,
> +                  VarStoreConfig
> +                  );
> +
> +  IsUpdated = FALSE;
> +
> +  if (EFI_ERROR (Status)) {
> +    VarStoreConfig->SmmuPmu = 0; /* Disable by default */
> +    IsUpdated = TRUE;
> +  }
> +  // Update board settings to menu
> +  for (RCIndex = 0; RCIndex < MAX_AC01_PCIE_ROOT_COMPLEX; RCIndex++) {
> +    RC = &RCList[RCIndex];
> +
> +    if (EFI_ERROR (Status)) {
> +      VarStoreConfig->RCBifurLo[RCIndex] = RC->DevMapLo;
> +      VarStoreConfig->RCBifurHi[RCIndex] = RC->DevMapHi;
> +      VarStoreConfig->RCStatus[RCIndex] = RC->Active;
> +      IsUpdated = TRUE;
> +    }
> +    // FIXME: Disable Root Complex 6 (USB and VGA) as default

Please get rid of the FIXME.

/
    Leif

> +    if (EFI_ERROR (Status) && RCIndex == 6) {
> +      VarStoreConfig->RCStatus[RCIndex] = 0;
> +    }
> +  }
> +
> +  if (IsUpdated) {
> +    // Update Buffer Storage
> +    Status = gRT->SetVariable (
> +                    VariableName,
> +                    &gPcieFormSetGuid,
> +                    EFI_VARIABLE_NON_VOLATILE |
> +                    EFI_VARIABLE_BOOTSERVICE_ACCESS |
> +                    EFI_VARIABLE_RUNTIME_ACCESS,
> +                    sizeof (PCIE_VARSTORE_DATA),
> +                    VarStoreConfig
> +                    );
> +    if (EFI_ERROR (Status)) {
> +      return Status;
> +    }
> +  }
> +  Status = PcieMainScreenSetup (mPrivateData);
> +  ASSERT_EFI_ERROR (Status);
> +
> +  for (RCIndex = 0; RCIndex < MAX_AC01_PCIE_ROOT_COMPLEX; RCIndex++) {
> +    Status = PcieRCScreenSetup (RCIndex, mPrivateData);
> +    ASSERT_EFI_ERROR (Status);
> +  }
> +
> +  return Status;
> +}
> diff --git a/Platform/Ampere/JadePkg/Library/PcieBoardLib/PcieBoardScreen.uni b/Platform/Ampere/JadePkg/Library/PcieBoardLib/PcieBoardScreen.uni
> new file mode 100644
> index 000000000000..776eaa476787
> --- /dev/null
> +++ b/Platform/Ampere/JadePkg/Library/PcieBoardLib/PcieBoardScreen.uni
> @@ -0,0 +1,99 @@
> +//
> +// Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
> +//
> +// SPDX-License-Identifier: BSD-2-Clause-Patent
> +//
> +
> +#langdef en-US "English"
> +
> +#string STR_PCIE_FORM                   #language en-US "PCIE Root Complex Configuration"
> +#string STR_PCIE_FORM_HELP              #language en-US "Configure Root Complex"
> +
> +#string STR_PCIE_FORM_SEPERATE_LINE     #language en-US ""
> +
> +/////
> +
> +#string STR_PCIE_GOTO                   #language en-US ""
> +#string STR_PCIE_GOTO_HELP              #language en-US "Change On Board Root Complex Settings."
> +
> +#string STR_PCIE_RC_STATUS              #language en-US ""
> +#string STR_PCIE_RC_STATUS_HELP         #language en-US "Enable / Disable Root Complex"
> +
> +#string STR_PCIE_RCA_BIFUR              #language en-US "Bifurcation x16"
> +#string STR_PCIE_RCA_BIFUR_HELP         #language en-US "Set bifurcation mode for x16 Root Complex Type-A"
> +
> +#string STR_PCIE_RCB_LO_BIFUR           #language en-US "Bifurcation 1st x8"
> +#string STR_PCIE_RCB_LO_BIFUR_HELP      #language en-US "Set bifurcation mode for 1st x8 Root Complex Type-B"
> +
> +#string STR_PCIE_RCB_HI_BIFUR           #language en-US "Bifurcation 2nd x8"
> +#string STR_PCIE_RCB_HI_BIFUR_HELP      #language en-US "Set bifurcation mode for 2nd x8 Root Complex Type-B"
> +
> +/////
> +
> +#string STR_PCIE_RC0_FORM               #language en-US "Root Complex 0 Configuration"
> +#string STR_PCIE_RC0_FORM_HELP          #language en-US "Root Complex 0 Configuration"
> +
> +#string STR_PCIE_RC1_FORM               #language en-US "Root Complex 1 Configuration"
> +#string STR_PCIE_RC1_FORM_HELP          #language en-US "Root Complex 1 Configuration"
> +
> +#string STR_PCIE_RC2_FORM               #language en-US "Root Complex 2 Configuration"
> +#string STR_PCIE_RC2_FORM_HELP          #language en-US "Root Complex 2 Configuration"
> +
> +#string STR_PCIE_RC3_FORM               #language en-US "Root Complex 3 Configuration"
> +#string STR_PCIE_RC3_FORM_HELP          #language en-US "Root Complex 3 Configuration"
> +
> +#string STR_PCIE_RC4_FORM               #language en-US "Root Complex 4 Configuration"
> +#string STR_PCIE_RC4_FORM_HELP          #language en-US "Root Complex 4 Configuration"
> +
> +#string STR_PCIE_RC5_FORM               #language en-US "Root Complex 5 Configuration"
> +#string STR_PCIE_RC5_FORM_HELP          #language en-US "Root Complex 5 Configuration"
> +
> +#string STR_PCIE_RC6_FORM               #language en-US "Root Complex 6 Configuration"
> +#string STR_PCIE_RC6_FORM_HELP          #language en-US "Root Complex 6 Configuration"
> +
> +#string STR_PCIE_RC7_FORM               #language en-US "Root Complex 7 Configuration"
> +#string STR_PCIE_RC7_FORM_HELP          #language en-US "Root Complex 7 Configuration"
> +
> +#string STR_PCIE_RC8_FORM               #language en-US "Root Complex 8 Configuration"
> +#string STR_PCIE_RC8_FORM_HELP          #language en-US "Root Complex 8 Configuration"
> +
> +#string STR_PCIE_RC9_FORM               #language en-US "Root Complex 9 Configuration"
> +#string STR_PCIE_RC9_FORM_HELP          #language en-US "Root Complex 9 Configuration"
> +
> +#string STR_PCIE_RC10_FORM              #language en-US "Root Complex 10 Configuration"
> +#string STR_PCIE_RC10_FORM_HELP         #language en-US "Root Complex 10 Configuration"
> +
> +#string STR_PCIE_RC11_FORM              #language en-US "Root Complex 11 Configuration"
> +#string STR_PCIE_RC11_FORM_HELP         #language en-US "Root Complex 11 Configuration"
> +
> +#string STR_PCIE_RC12_FORM              #language en-US "Root Complex 12 Configuration"
> +#string STR_PCIE_RC12_FORM_HELP         #language en-US "Root Complex 12 Configuration"
> +
> +#string STR_PCIE_RC13_FORM              #language en-US "Root Complex 13 Configuration"
> +#string STR_PCIE_RC13_FORM_HELP         #language en-US "Root Complex 13 Configuration"
> +
> +#string STR_PCIE_RC14_FORM              #language en-US "Root Complex 14 Configuration"
> +#string STR_PCIE_RC14_FORM_HELP         #language en-US "Root Complex 14 Configuration"
> +
> +#string STR_PCIE_RC15_FORM              #language en-US "Root Complex 15 Configuration"
> +#string STR_PCIE_RC15_FORM_HELP         #language en-US "Root Complex 15 Configuration"
> +
> +#string STR_PCIE_BIFUR_SELECT_VALUE0    #language en-US "x16"
> +#string STR_PCIE_BIFUR_SELECT_VALUE1    #language en-US "x8+x8"
> +#string STR_PCIE_BIFUR_SELECT_VALUE2    #language en-US "x8+x4+x4"
> +#string STR_PCIE_BIFUR_SELECT_VALUE3    #language en-US "x4+x4+x4+x4"
> +#string STR_PCIE_BIFUR_SELECT_VALUE4    #language en-US "x8"
> +#string STR_PCIE_BIFUR_SELECT_VALUE5    #language en-US "x4+x4"
> +#string STR_PCIE_BIFUR_SELECT_VALUE6    #language en-US "x4+x2+x2"
> +#string STR_PCIE_BIFUR_SELECT_VALUE7    #language en-US "x2+x2+x2+x2"
> +
> +#string STR_PCIE_SOCKET                 #language en-US "Socket"
> +#string STR_PCIE_SOCKET_HELP            #language en-US "Socket 0 - Master; Socket 1 - Slave"
> +#string STR_PCIE_SOCKET_VALUE           #language en-US ""
> +
> +#string STR_PCIE_RC_TYPE                #language en-US "Type"
> +#string STR_PCIE_RC_TYPE_HELP           #language en-US "Type-A: x16 lanes bifurcated down to x4; Type-B: 2 of x8 lanes, each bifurcated down to x2"
> +#string STR_PCIE_RC_TYPE_VALUE          #language en-US ""
> +
> +#string STR_PCIE_SMMU_PMU_PROMPT        #language en-US "SMMU Pmu"
> +#string STR_PCIE_SMMU_PMU_HELP          #language en-US "Enable/Disable PMU feature for SMMU"
> -- 
> 2.17.1
> 


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