From: Patrick Rudolph <patrick.rudo...@9elements.com>

* Don't hardcode PCIE_BASE at build time
* Support arbitrary platforms with different or even no MMCONF space
* Fix buffer overflow accessing MMCONF where less than 256 buses are
  exposed
* Use PciCfg8 for PCI access in PEI, which is only used for debugging

Signed-off-by: Patrick Rudolph <patrick.rudo...@9elements.com>
Signed-off-by: Marcello Sylvester Bauer <marcello.ba...@9elements.com>
Cc: Patrick Rudolph <patrick.rudo...@9elements.com>
Cc: Christian Walter <christian.wal...@9elements.com>
Cc: Maurice Ma <maurice...@intel.com>
Cc: Nate DeSimone <nathaniel.l.desim...@intel.com>
Cc: Star Zeng <star.z...@intel.com>
---
 UefiPayloadPkg/UefiPayloadPkgIa32.dsc                                |   16 +-
 UefiPayloadPkg/UefiPayloadPkgIa32X64.dsc                             |   16 +-
 UefiPayloadPkg/Library/BasePciExpressLib/BasePciExpressLib.inf       |   46 +
 UefiPayloadPkg/Library/BasePciLibPciExpress/BasePciLibPciExpress.inf |   42 +
 UefiPayloadPkg/Library/BasePciExpressLib/PciExpressLib.c             | 1455 
++++++++++++++++++++
 UefiPayloadPkg/Library/BasePciLibPciExpress/PciLib.c                 | 1302 
++++++++++++++++++
 UefiPayloadPkg/Library/BasePciExpressLib/BasePciExpressLib.uni       |   17 +
 UefiPayloadPkg/Library/BasePciLibPciExpress/BasePciLibPciExpress.uni |   17 +
 8 files changed, 2885 insertions(+), 26 deletions(-)

diff --git a/UefiPayloadPkg/UefiPayloadPkgIa32.dsc 
b/UefiPayloadPkg/UefiPayloadPkgIa32.dsc
index c6c47833871b..48b03af6f223 100644
--- a/UefiPayloadPkg/UefiPayloadPkgIa32.dsc
+++ b/UefiPayloadPkg/UefiPayloadPkgIa32.dsc
@@ -37,11 +37,6 @@ [Defines]
   #
   DEFINE MAX_LOGICAL_PROCESSORS       = 64
 
-  #
-  # PCI options
-  #
-  DEFINE PCIE_BASE                    = 0xE0000000
-
   #
   # Serial port set up
   #
@@ -121,13 +116,9 @@ [LibraryClasses]
   PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
   CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf
   IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf
-!if $(PCIE_BASE) == 0
-  PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf
   PciCf8Lib|MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf
-!else
-  PciLib|MdePkg/Library/BasePciLibPciExpress/BasePciLibPciExpress.inf
-  PciExpressLib|MdePkg/Library/BasePciExpressLib/BasePciExpressLib.inf
-!endif
+  PciLib|UefiPayloadPkg/Library/BasePciLibPciExpress/BasePciLibPciExpress.inf
+  PciExpressLib|UefiPayloadPkg/Library/BasePciExpressLib/BasePciExpressLib.inf
   PciSegmentLib|MdePkg/Library/BasePciSegmentLibPci/BasePciSegmentLibPci.inf
   PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
   
PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
@@ -216,6 +207,7 @@ [LibraryClasses.IA32.SEC]
 [LibraryClasses.IA32.PEI_CORE, LibraryClasses.IA32.PEIM]
   PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
   HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf
+  PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf
   
MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf
   
ReportStatusCodeLib|MdeModulePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.inf
   
ExtractGuidedSectionLib|MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.inf
@@ -286,8 +278,6 @@ [PcdsFixedAtBuild]
   gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseMemory|FALSE
   gEfiMdeModulePkgTokenSpaceGuid.PcdBootManagerMenuFile|{ 0x21, 0xaa, 0x2c, 
0x46, 0x14, 0x76, 0x03, 0x45, 0x83, 0x6e, 0x8a, 0xb6, 0xf4, 0x66, 0x23, 0x31 }
 
-  gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress|$(PCIE_BASE)
-
 !if $(SOURCE_DEBUG_ENABLE)
   gEfiSourceLevelDebugPkgTokenSpaceGuid.PcdDebugLoadImageMethod|0x2
 !endif
diff --git a/UefiPayloadPkg/UefiPayloadPkgIa32X64.dsc 
b/UefiPayloadPkg/UefiPayloadPkgIa32X64.dsc
index 5559b1258521..af951ee5aec0 100644
--- a/UefiPayloadPkg/UefiPayloadPkgIa32X64.dsc
+++ b/UefiPayloadPkg/UefiPayloadPkgIa32X64.dsc
@@ -38,11 +38,6 @@ [Defines]
   #
   DEFINE MAX_LOGICAL_PROCESSORS       = 64
 
-  #
-  # PCI options
-  #
-  DEFINE PCIE_BASE                    = 0xE0000000
-
   #
   # Serial port set up
   #
@@ -122,13 +117,9 @@ [LibraryClasses]
   PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
   CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf
   IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf
-!if $(PCIE_BASE) == 0
-  PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf
   PciCf8Lib|MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf
-!else
-  PciLib|MdePkg/Library/BasePciLibPciExpress/BasePciLibPciExpress.inf
-  PciExpressLib|MdePkg/Library/BasePciExpressLib/BasePciExpressLib.inf
-!endif
+  PciLib|UefiPayloadPkg/Library/BasePciLibPciExpress/BasePciLibPciExpress.inf
+  PciExpressLib|UefiPayloadPkg/Library/BasePciExpressLib/BasePciExpressLib.inf
   PciSegmentLib|MdePkg/Library/BasePciSegmentLibPci/BasePciSegmentLibPci.inf
   PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
   
PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
@@ -217,6 +208,7 @@ [LibraryClasses.IA32.SEC]
 [LibraryClasses.IA32.PEI_CORE, LibraryClasses.IA32.PEIM]
   PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
   HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf
+  PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf
   
MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf
   
ReportStatusCodeLib|MdeModulePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.inf
   
ExtractGuidedSectionLib|MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.inf
@@ -288,8 +280,6 @@ [PcdsFixedAtBuild]
   gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable|TRUE
   gEfiMdeModulePkgTokenSpaceGuid.PcdBootManagerMenuFile|{ 0x21, 0xaa, 0x2c, 
0x46, 0x14, 0x76, 0x03, 0x45, 0x83, 0x6e, 0x8a, 0xb6, 0xf4, 0x66, 0x23, 0x31 }
 
-  gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress|$(PCIE_BASE)
-
 !if $(SOURCE_DEBUG_ENABLE)
   gEfiSourceLevelDebugPkgTokenSpaceGuid.PcdDebugLoadImageMethod|0x2
 !endif
diff --git a/UefiPayloadPkg/Library/BasePciExpressLib/BasePciExpressLib.inf 
b/UefiPayloadPkg/Library/BasePciExpressLib/BasePciExpressLib.inf
new file mode 100644
index 000000000000..9f052c0a2e65
--- /dev/null
+++ b/UefiPayloadPkg/Library/BasePciExpressLib/BasePciExpressLib.inf
@@ -0,0 +1,46 @@
+## @file
+#  Instance of PCI Express Library using the 256 MB PCI Express MMIO window.
+#
+#  PCI Express Library that uses the 256 MB PCI Express MMIO window to perform
+#  PCI Configuration cycles. Layers on top of an I/O Library instance.
+#
+#  Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = BasePciExpressLib
+  MODULE_UNI_FILE                = BasePciExpressLib.uni
+  FILE_GUID                      = 287e50f4-a188-4699-b907-3e4080ca5688
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = PciExpressLib
+  CONSTRUCTOR                    = PciExpressLibInitialize
+
+#
+#  VALID_ARCHITECTURES           = IA32 X64 EBC
+#
+
+[Sources]
+  PciExpressLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  UefiPayloadPkg/UefiPayloadPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  DebugLib
+  HobLib
+  IoLib
+
+[Guids]
+  gUefiAcpiBoardInfoGuid
+
+[Pcd]
+  gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress  ## CONSUMES
+
diff --git 
a/UefiPayloadPkg/Library/BasePciLibPciExpress/BasePciLibPciExpress.inf 
b/UefiPayloadPkg/Library/BasePciLibPciExpress/BasePciLibPciExpress.inf
new file mode 100644
index 000000000000..0858e49a47ae
--- /dev/null
+++ b/UefiPayloadPkg/Library/BasePciLibPciExpress/BasePciLibPciExpress.inf
@@ -0,0 +1,42 @@
+## @file
+#  Instance of PCI Library based on PCI Express Library.
+#
+#  PCI Library that uses the 256 MB PCI Express MMIO window to perform PCI
+#  Configuration cycles. Layers on one PCI Express Library instance.
+#
+#  Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = BasePciLibPciExpress
+  MODULE_UNI_FILE                = BasePciLibPciExpress.uni
+  FILE_GUID                      = 8987081e-daeb-44a9-8bef-a195b22d9417
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = PciLib
+  CONSTRUCTOR                    = PciLibInitialize
+
+#
+#  VALID_ARCHITECTURES           = IA32 X64
+#
+
+[Sources]
+  PciLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  UefiPayloadPkg/UefiPayloadPkg.dec
+
+[Guids]
+  gUefiAcpiBoardInfoGuid
+
+[LibraryClasses]
+  PciExpressLib
+  PciCf8Lib
+  BaseLib
+  HobLib
diff --git a/UefiPayloadPkg/Library/BasePciExpressLib/PciExpressLib.c 
b/UefiPayloadPkg/Library/BasePciExpressLib/PciExpressLib.c
new file mode 100644
index 000000000000..f3b4582d3c47
--- /dev/null
+++ b/UefiPayloadPkg/Library/BasePciExpressLib/PciExpressLib.c
@@ -0,0 +1,1455 @@
+/** @file
+  Functions in this library instance make use of MMIO functions in IoLib to
+  access memory mapped PCI configuration space.
+
+  All assertions for I/O operations are handled in MMIO functions in the IoLib
+  Library.
+
+  Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+
+#include <Base.h>
+
+#include <Library/BaseLib.h>
+#include <Library/PciExpressLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/BaseMemoryLib.h>
+
+#include <Pi/PiBootMode.h>
+#include <Uefi/UefiBaseType.h>
+#include <Uefi/UefiMultiPhase.h>
+#include <Pi/PiHob.h>
+
+#include <Library/HobLib.h>
+#include <Guid/AcpiBoardInfoGuid.h>
+
+STATIC ACPI_BOARD_INFO mBoardInfo;
+/**
+  Assert the validity of a PCI address.
+  If Address > 0x0FFFFFFF, then ASSERT().
+
+  Return 0xff on transaction outside of the MMCONF space.
+
+  @param  A The address to validate.
+
+**/
+#define ASSERT_INVALID_PCI_ADDRESS(A) \
+  ASSERT (((A) & ~0xfffffff) == 0); \
+  if ((A) >= mBoardInfo.PcieBaseSize) { \
+    return ~0; \
+  }
+
+/**
+  Registers a PCI device so PCI configuration registers may be accessed after
+  SetVirtualAddressMap().
+
+  Registers the PCI device specified by Address so all the PCI configuration
+  registers associated with that PCI device may be accessed after 
SetVirtualAddressMap()
+  is called.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+
+  @param  Address The address that encodes the PCI Bus, Device, Function and
+                  Register.
+
+  @retval RETURN_SUCCESS           The PCI device was registered for runtime 
access.
+  @retval RETURN_UNSUPPORTED       An attempt was made to call this function
+                                   after ExitBootServices().
+  @retval RETURN_UNSUPPORTED       The resources required to access the PCI 
device
+                                   at runtime could not be mapped.
+  @retval RETURN_OUT_OF_RESOURCES  There are not enough resources available to
+                                   complete the registration.
+
+**/
+RETURN_STATUS
+EFIAPI
+PciExpressRegisterForRuntimeAccess (
+  IN UINTN  Address
+  )
+{
+  ASSERT_INVALID_PCI_ADDRESS (Address);
+  return RETURN_UNSUPPORTED;
+}
+
+/**
+  Performs platform specific initialization required for the CPU to access
+  the MMCONF space.  This function does not initialize the MMCONF itself.
+
+  @retval RETURN_SUCCESS       The platform specific initialization succeeded.
+  @retval RETURN_DEVICE_ERROR  The platform specific initialization could not 
be completed.
+
+**/
+RETURN_STATUS
+EFIAPI
+PciExpressLibInitialize (
+  VOID
+  )
+{
+  EFI_HOB_GUID_TYPE         *GuidHob;
+
+  //
+  // Find the acpi board information guid hob
+  //
+  GuidHob = GetFirstGuidHob (&gUefiAcpiBoardInfoGuid);
+  ASSERT (GuidHob != NULL);
+  if (GuidHob == NULL) {
+    return EFI_UNSUPPORTED;
+  }
+
+  CopyMem (&mBoardInfo, GET_GUID_HOB_DATA (GuidHob), sizeof(mBoardInfo));
+  return EFI_SUCCESS;
+}
+
+/**
+  Gets the base address of PCI Express.
+
+  This internal functions retrieves PCI Express Base Address via a PCD entry
+  PcdPciExpressBaseAddress.
+
+  @return The base address of PCI Express.
+
+**/
+VOID*
+GetPciExpressBaseAddress (
+  VOID
+  )
+{
+  return (VOID*)(UINTN) mBoardInfo.PcieBaseAddress;
+}
+
+/**
+  Reads an 8-bit PCI configuration register.
+
+  Reads and returns the 8-bit PCI configuration register specified by Address.
+  This function must guarantee that all PCI read and write operations are
+  serialized.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+
+  @param  Address The address that encodes the PCI Bus, Device, Function and
+                  Register.
+
+  @return The read value from the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciExpressRead8 (
+  IN      UINTN                     Address
+  )
+{
+  ASSERT_INVALID_PCI_ADDRESS (Address);
+  return MmioRead8 ((UINTN) GetPciExpressBaseAddress () + Address);
+}
+
+/**
+  Writes an 8-bit PCI configuration register.
+
+  Writes the 8-bit PCI configuration register specified by Address with the
+  value specified by Value. Value is returned. This function must guarantee
+  that all PCI read and write operations are serialized.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+
+  @param  Address The address that encodes the PCI Bus, Device, Function and
+                  Register.
+  @param  Value   The value to write.
+
+  @return The value written to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciExpressWrite8 (
+  IN      UINTN                     Address,
+  IN      UINT8                     Value
+  )
+{
+  ASSERT_INVALID_PCI_ADDRESS (Address);
+  return MmioWrite8 ((UINTN) GetPciExpressBaseAddress () + Address, Value);
+}
+
+/**
+  Performs a bitwise OR of an 8-bit PCI configuration register with
+  an 8-bit value.
+
+  Reads the 8-bit PCI configuration register specified by Address, performs a
+  bitwise OR between the read result and the value specified by
+  OrData, and writes the result to the 8-bit PCI configuration register
+  specified by Address. The value written to the PCI configuration register is
+  returned. This function must guarantee that all PCI read and write operations
+  are serialized.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+
+  @param  Address The address that encodes the PCI Bus, Device, Function and
+                  Register.
+  @param  OrData  The value to OR with the PCI configuration register.
+
+  @return The value written back to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciExpressOr8 (
+  IN      UINTN                     Address,
+  IN      UINT8                     OrData
+  )
+{
+  ASSERT_INVALID_PCI_ADDRESS (Address);
+  return MmioOr8 ((UINTN) GetPciExpressBaseAddress () + Address, OrData);
+}
+
+/**
+  Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit
+  value.
+
+  Reads the 8-bit PCI configuration register specified by Address, performs a
+  bitwise AND between the read result and the value specified by AndData, and
+  writes the result to the 8-bit PCI configuration register specified by
+  Address. The value written to the PCI configuration register is returned.
+  This function must guarantee that all PCI read and write operations are
+  serialized.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+
+  @param  Address The address that encodes the PCI Bus, Device, Function and
+                  Register.
+  @param  AndData The value to AND with the PCI configuration register.
+
+  @return The value written back to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciExpressAnd8 (
+  IN      UINTN                     Address,
+  IN      UINT8                     AndData
+  )
+{
+  ASSERT_INVALID_PCI_ADDRESS (Address);
+  return MmioAnd8 ((UINTN) GetPciExpressBaseAddress () + Address, AndData);
+}
+
+/**
+  Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit
+  value, followed a  bitwise OR with another 8-bit value.
+
+  Reads the 8-bit PCI configuration register specified by Address, performs a
+  bitwise AND between the read result and the value specified by AndData,
+  performs a bitwise OR between the result of the AND operation and
+  the value specified by OrData, and writes the result to the 8-bit PCI
+  configuration register specified by Address. The value written to the PCI
+  configuration register is returned. This function must guarantee that all PCI
+  read and write operations are serialized.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+
+  @param  Address The address that encodes the PCI Bus, Device, Function and
+                  Register.
+  @param  AndData The value to AND with the PCI configuration register.
+  @param  OrData  The value to OR with the result of the AND operation.
+
+  @return The value written back to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciExpressAndThenOr8 (
+  IN      UINTN                     Address,
+  IN      UINT8                     AndData,
+  IN      UINT8                     OrData
+  )
+{
+  ASSERT_INVALID_PCI_ADDRESS (Address);
+  return MmioAndThenOr8 (
+           (UINTN) GetPciExpressBaseAddress () + Address,
+           AndData,
+           OrData
+           );
+}
+
+/**
+  Reads a bit field of a PCI configuration register.
+
+  Reads the bit field in an 8-bit PCI configuration register. The bit field is
+  specified by the StartBit and the EndBit. The value of the bit field is
+  returned.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If StartBit is greater than 7, then ASSERT().
+  If EndBit is greater than 7, then ASSERT().
+  If EndBit is less than StartBit, then ASSERT().
+
+  @param  Address   The PCI configuration register to read.
+  @param  StartBit  The ordinal of the least significant bit in the bit field.
+                    Range 0..7.
+  @param  EndBit    The ordinal of the most significant bit in the bit field.
+                    Range 0..7.
+
+  @return The value of the bit field read from the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciExpressBitFieldRead8 (
+  IN      UINTN                     Address,
+  IN      UINTN                     StartBit,
+  IN      UINTN                     EndBit
+  )
+{
+  ASSERT_INVALID_PCI_ADDRESS (Address);
+  return MmioBitFieldRead8 (
+           (UINTN) GetPciExpressBaseAddress () + Address,
+           StartBit,
+           EndBit
+           );
+}
+
+/**
+  Writes a bit field to a PCI configuration register.
+
+  Writes Value to the bit field of the PCI configuration register. The bit
+  field is specified by the StartBit and the EndBit. All other bits in the
+  destination PCI configuration register are preserved. The new value of the
+  8-bit register is returned.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If StartBit is greater than 7, then ASSERT().
+  If EndBit is greater than 7, then ASSERT().
+  If EndBit is less than StartBit, then ASSERT().
+  If Value is larger than the bitmask value range specified by StartBit and 
EndBit, then ASSERT().
+
+  @param  Address   The PCI configuration register to write.
+  @param  StartBit  The ordinal of the least significant bit in the bit field.
+                    Range 0..7.
+  @param  EndBit    The ordinal of the most significant bit in the bit field.
+                    Range 0..7.
+  @param  Value     The new value of the bit field.
+
+  @return The value written back to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciExpressBitFieldWrite8 (
+  IN      UINTN                     Address,
+  IN      UINTN                     StartBit,
+  IN      UINTN                     EndBit,
+  IN      UINT8                     Value
+  )
+{
+  ASSERT_INVALID_PCI_ADDRESS (Address);
+  return MmioBitFieldWrite8 (
+           (UINTN) GetPciExpressBaseAddress () + Address,
+           StartBit,
+           EndBit,
+           Value
+           );
+}
+
+/**
+  Reads a bit field in an 8-bit PCI configuration, performs a bitwise OR, and
+  writes the result back to the bit field in the 8-bit port.
+
+  Reads the 8-bit PCI configuration register specified by Address, performs a
+  bitwise OR between the read result and the value specified by
+  OrData, and writes the result to the 8-bit PCI configuration register
+  specified by Address. The value written to the PCI configuration register is
+  returned. This function must guarantee that all PCI read and write operations
+  are serialized. Extra left bits in OrData are stripped.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If StartBit is greater than 7, then ASSERT().
+  If EndBit is greater than 7, then ASSERT().
+  If EndBit is less than StartBit, then ASSERT().
+  If OrData is larger than the bitmask value range specified by StartBit and 
EndBit, then ASSERT().
+
+  @param  Address   The PCI configuration register to write.
+  @param  StartBit  The ordinal of the least significant bit in the bit field.
+                    Range 0..7.
+  @param  EndBit    The ordinal of the most significant bit in the bit field.
+                    Range 0..7.
+  @param  OrData    The value to OR with the PCI configuration register.
+
+  @return The value written back to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciExpressBitFieldOr8 (
+  IN      UINTN                     Address,
+  IN      UINTN                     StartBit,
+  IN      UINTN                     EndBit,
+  IN      UINT8                     OrData
+  )
+{
+  ASSERT_INVALID_PCI_ADDRESS (Address);
+  return MmioBitFieldOr8 (
+           (UINTN) GetPciExpressBaseAddress () + Address,
+           StartBit,
+           EndBit,
+           OrData
+           );
+}
+
+/**
+  Reads a bit field in an 8-bit PCI configuration register, performs a bitwise
+  AND, and writes the result back to the bit field in the 8-bit register.
+
+  Reads the 8-bit PCI configuration register specified by Address, performs a
+  bitwise AND between the read result and the value specified by AndData, and
+  writes the result to the 8-bit PCI configuration register specified by
+  Address. The value written to the PCI configuration register is returned.
+  This function must guarantee that all PCI read and write operations are
+  serialized. Extra left bits in AndData are stripped.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If StartBit is greater than 7, then ASSERT().
+  If EndBit is greater than 7, then ASSERT().
+  If EndBit is less than StartBit, then ASSERT().
+  If AndData is larger than the bitmask value range specified by StartBit and 
EndBit, then ASSERT().
+
+  @param  Address   The PCI configuration register to write.
+  @param  StartBit  The ordinal of the least significant bit in the bit field.
+                    Range 0..7.
+  @param  EndBit    The ordinal of the most significant bit in the bit field.
+                    Range 0..7.
+  @param  AndData   The value to AND with the PCI configuration register.
+
+  @return The value written back to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciExpressBitFieldAnd8 (
+  IN      UINTN                     Address,
+  IN      UINTN                     StartBit,
+  IN      UINTN                     EndBit,
+  IN      UINT8                     AndData
+  )
+{
+  ASSERT_INVALID_PCI_ADDRESS (Address);
+  return MmioBitFieldAnd8 (
+           (UINTN) GetPciExpressBaseAddress () + Address,
+           StartBit,
+           EndBit,
+           AndData
+           );
+}
+
+/**
+  Reads a bit field in an 8-bit port, performs a bitwise AND followed by a
+  bitwise OR, and writes the result back to the bit field in the
+  8-bit port.
+
+  Reads the 8-bit PCI configuration register specified by Address, performs a
+  bitwise AND followed by a bitwise OR between the read result and
+  the value specified by AndData, and writes the result to the 8-bit PCI
+  configuration register specified by Address. The value written to the PCI
+  configuration register is returned. This function must guarantee that all PCI
+  read and write operations are serialized. Extra left bits in both AndData and
+  OrData are stripped.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If StartBit is greater than 7, then ASSERT().
+  If EndBit is greater than 7, then ASSERT().
+  If EndBit is less than StartBit, then ASSERT().
+  If AndData is larger than the bitmask value range specified by StartBit and 
EndBit, then ASSERT().
+  If OrData is larger than the bitmask value range specified by StartBit and 
EndBit, then ASSERT().
+
+  @param  Address   The PCI configuration register to write.
+  @param  StartBit  The ordinal of the least significant bit in the bit field.
+                    Range 0..7.
+  @param  EndBit    The ordinal of the most significant bit in the bit field.
+                    Range 0..7.
+  @param  AndData   The value to AND with the PCI configuration register.
+  @param  OrData    The value to OR with the result of the AND operation.
+
+  @return The value written back to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciExpressBitFieldAndThenOr8 (
+  IN      UINTN                     Address,
+  IN      UINTN                     StartBit,
+  IN      UINTN                     EndBit,
+  IN      UINT8                     AndData,
+  IN      UINT8                     OrData
+  )
+{
+  ASSERT_INVALID_PCI_ADDRESS (Address);
+  return MmioBitFieldAndThenOr8 (
+           (UINTN) GetPciExpressBaseAddress () + Address,
+           StartBit,
+           EndBit,
+           AndData,
+           OrData
+           );
+}
+
+/**
+  Reads a 16-bit PCI configuration register.
+
+  Reads and returns the 16-bit PCI configuration register specified by Address.
+  This function must guarantee that all PCI read and write operations are
+  serialized.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If Address is not aligned on a 16-bit boundary, then ASSERT().
+
+  @param  Address The address that encodes the PCI Bus, Device, Function and
+                  Register.
+
+  @return The read value from the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciExpressRead16 (
+  IN      UINTN                     Address
+  )
+{
+  ASSERT_INVALID_PCI_ADDRESS (Address);
+  return MmioRead16 ((UINTN) GetPciExpressBaseAddress () + Address);
+}
+
+/**
+  Writes a 16-bit PCI configuration register.
+
+  Writes the 16-bit PCI configuration register specified by Address with the
+  value specified by Value. Value is returned. This function must guarantee
+  that all PCI read and write operations are serialized.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If Address is not aligned on a 16-bit boundary, then ASSERT().
+
+  @param  Address The address that encodes the PCI Bus, Device, Function and
+                  Register.
+  @param  Value   The value to write.
+
+  @return The value written to the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciExpressWrite16 (
+  IN      UINTN                     Address,
+  IN      UINT16                    Value
+  )
+{
+  ASSERT_INVALID_PCI_ADDRESS (Address);
+  return MmioWrite16 ((UINTN) GetPciExpressBaseAddress () + Address, Value);
+}
+
+/**
+  Performs a bitwise OR of a 16-bit PCI configuration register with
+  a 16-bit value.
+
+  Reads the 16-bit PCI configuration register specified by Address, performs a
+  bitwise OR between the read result and the value specified by
+  OrData, and writes the result to the 16-bit PCI configuration register
+  specified by Address. The value written to the PCI configuration register is
+  returned. This function must guarantee that all PCI read and write operations
+  are serialized.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If Address is not aligned on a 16-bit boundary, then ASSERT().
+
+  @param  Address The address that encodes the PCI Bus, Device, Function and
+                  Register.
+  @param  OrData  The value to OR with the PCI configuration register.
+
+  @return The value written back to the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciExpressOr16 (
+  IN      UINTN                     Address,
+  IN      UINT16                    OrData
+  )
+{
+  ASSERT_INVALID_PCI_ADDRESS (Address);
+  return MmioOr16 ((UINTN) GetPciExpressBaseAddress () + Address, OrData);
+}
+
+/**
+  Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit
+  value.
+
+  Reads the 16-bit PCI configuration register specified by Address, performs a
+  bitwise AND between the read result and the value specified by AndData, and
+  writes the result to the 16-bit PCI configuration register specified by
+  Address. The value written to the PCI configuration register is returned.
+  This function must guarantee that all PCI read and write operations are
+  serialized.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If Address is not aligned on a 16-bit boundary, then ASSERT().
+
+  @param  Address The address that encodes the PCI Bus, Device, Function and
+                  Register.
+  @param  AndData The value to AND with the PCI configuration register.
+
+  @return The value written back to the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciExpressAnd16 (
+  IN      UINTN                     Address,
+  IN      UINT16                    AndData
+  )
+{
+  ASSERT_INVALID_PCI_ADDRESS (Address);
+  return MmioAnd16 ((UINTN) GetPciExpressBaseAddress () + Address, AndData);
+}
+
+/**
+  Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit
+  value, followed a  bitwise OR with another 16-bit value.
+
+  Reads the 16-bit PCI configuration register specified by Address, performs a
+  bitwise AND between the read result and the value specified by AndData,
+  performs a bitwise OR between the result of the AND operation and
+  the value specified by OrData, and writes the result to the 16-bit PCI
+  configuration register specified by Address. The value written to the PCI
+  configuration register is returned. This function must guarantee that all PCI
+  read and write operations are serialized.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If Address is not aligned on a 16-bit boundary, then ASSERT().
+
+  @param  Address The address that encodes the PCI Bus, Device, Function and
+                  Register.
+  @param  AndData The value to AND with the PCI configuration register.
+  @param  OrData  The value to OR with the result of the AND operation.
+
+  @return The value written back to the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciExpressAndThenOr16 (
+  IN      UINTN                     Address,
+  IN      UINT16                    AndData,
+  IN      UINT16                    OrData
+  )
+{
+  ASSERT_INVALID_PCI_ADDRESS (Address);
+  return MmioAndThenOr16 (
+           (UINTN) GetPciExpressBaseAddress () + Address,
+           AndData,
+           OrData
+           );
+}
+
+/**
+  Reads a bit field of a PCI configuration register.
+
+  Reads the bit field in a 16-bit PCI configuration register. The bit field is
+  specified by the StartBit and the EndBit. The value of the bit field is
+  returned.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If Address is not aligned on a 16-bit boundary, then ASSERT().
+  If StartBit is greater than 15, then ASSERT().
+  If EndBit is greater than 15, then ASSERT().
+  If EndBit is less than StartBit, then ASSERT().
+
+  @param  Address   The PCI configuration register to read.
+  @param  StartBit  The ordinal of the least significant bit in the bit field.
+                    Range 0..15.
+  @param  EndBit    The ordinal of the most significant bit in the bit field.
+                    Range 0..15.
+
+  @return The value of the bit field read from the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciExpressBitFieldRead16 (
+  IN      UINTN                     Address,
+  IN      UINTN                     StartBit,
+  IN      UINTN                     EndBit
+  )
+{
+  ASSERT_INVALID_PCI_ADDRESS (Address);
+  return MmioBitFieldRead16 (
+           (UINTN) GetPciExpressBaseAddress () + Address,
+           StartBit,
+           EndBit
+           );
+}
+
+/**
+  Writes a bit field to a PCI configuration register.
+
+  Writes Value to the bit field of the PCI configuration register. The bit
+  field is specified by the StartBit and the EndBit. All other bits in the
+  destination PCI configuration register are preserved. The new value of the
+  16-bit register is returned.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If Address is not aligned on a 16-bit boundary, then ASSERT().
+  If StartBit is greater than 15, then ASSERT().
+  If EndBit is greater than 15, then ASSERT().
+  If EndBit is less than StartBit, then ASSERT().
+  If Value is larger than the bitmask value range specified by StartBit and 
EndBit, then ASSERT().
+
+  @param  Address   The PCI configuration register to write.
+  @param  StartBit  The ordinal of the least significant bit in the bit field.
+                    Range 0..15.
+  @param  EndBit    The ordinal of the most significant bit in the bit field.
+                    Range 0..15.
+  @param  Value     The new value of the bit field.
+
+  @return The value written back to the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciExpressBitFieldWrite16 (
+  IN      UINTN                     Address,
+  IN      UINTN                     StartBit,
+  IN      UINTN                     EndBit,
+  IN      UINT16                    Value
+  )
+{
+  ASSERT_INVALID_PCI_ADDRESS (Address);
+  return MmioBitFieldWrite16 (
+           (UINTN) GetPciExpressBaseAddress () + Address,
+           StartBit,
+           EndBit,
+           Value
+           );
+}
+
+/**
+  Reads a bit field in a 16-bit PCI configuration, performs a bitwise OR, and
+  writes the result back to the bit field in the 16-bit port.
+
+  Reads the 16-bit PCI configuration register specified by Address, performs a
+  bitwise OR between the read result and the value specified by
+  OrData, and writes the result to the 16-bit PCI configuration register
+  specified by Address. The value written to the PCI configuration register is
+  returned. This function must guarantee that all PCI read and write operations
+  are serialized. Extra left bits in OrData are stripped.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If Address is not aligned on a 16-bit boundary, then ASSERT().
+  If StartBit is greater than 15, then ASSERT().
+  If EndBit is greater than 15, then ASSERT().
+  If EndBit is less than StartBit, then ASSERT().
+  If OrData is larger than the bitmask value range specified by StartBit and 
EndBit, then ASSERT().
+
+  @param  Address   The PCI configuration register to write.
+  @param  StartBit  The ordinal of the least significant bit in the bit field.
+                    Range 0..15.
+  @param  EndBit    The ordinal of the most significant bit in the bit field.
+                    Range 0..15.
+  @param  OrData    The value to OR with the PCI configuration register.
+
+  @return The value written back to the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciExpressBitFieldOr16 (
+  IN      UINTN                     Address,
+  IN      UINTN                     StartBit,
+  IN      UINTN                     EndBit,
+  IN      UINT16                    OrData
+  )
+{
+  ASSERT_INVALID_PCI_ADDRESS (Address);
+  return MmioBitFieldOr16 (
+           (UINTN) GetPciExpressBaseAddress () + Address,
+           StartBit,
+           EndBit,
+           OrData
+           );
+}
+
+/**
+  Reads a bit field in a 16-bit PCI configuration register, performs a bitwise
+  AND, and writes the result back to the bit field in the 16-bit register.
+
+  Reads the 16-bit PCI configuration register specified by Address, performs a
+  bitwise AND between the read result and the value specified by AndData, and
+  writes the result to the 16-bit PCI configuration register specified by
+  Address. The value written to the PCI configuration register is returned.
+  This function must guarantee that all PCI read and write operations are
+  serialized. Extra left bits in AndData are stripped.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If Address is not aligned on a 16-bit boundary, then ASSERT().
+  If StartBit is greater than 15, then ASSERT().
+  If EndBit is greater than 15, then ASSERT().
+  If EndBit is less than StartBit, then ASSERT().
+  If AndData is larger than the bitmask value range specified by StartBit and 
EndBit, then ASSERT().
+
+  @param  Address   The PCI configuration register to write.
+  @param  StartBit  The ordinal of the least significant bit in the bit field.
+                    Range 0..15.
+  @param  EndBit    The ordinal of the most significant bit in the bit field.
+                    Range 0..15.
+  @param  AndData   The value to AND with the PCI configuration register.
+
+  @return The value written back to the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciExpressBitFieldAnd16 (
+  IN      UINTN                     Address,
+  IN      UINTN                     StartBit,
+  IN      UINTN                     EndBit,
+  IN      UINT16                    AndData
+  )
+{
+  ASSERT_INVALID_PCI_ADDRESS (Address);
+  return MmioBitFieldAnd16 (
+           (UINTN) GetPciExpressBaseAddress () + Address,
+           StartBit,
+           EndBit,
+           AndData
+           );
+}
+
+/**
+  Reads a bit field in a 16-bit port, performs a bitwise AND followed by a
+  bitwise OR, and writes the result back to the bit field in the
+  16-bit port.
+
+  Reads the 16-bit PCI configuration register specified by Address, performs a
+  bitwise AND followed by a bitwise OR between the read result and
+  the value specified by AndData, and writes the result to the 16-bit PCI
+  configuration register specified by Address. The value written to the PCI
+  configuration register is returned. This function must guarantee that all PCI
+  read and write operations are serialized. Extra left bits in both AndData and
+  OrData are stripped.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If Address is not aligned on a 16-bit boundary, then ASSERT().
+  If StartBit is greater than 15, then ASSERT().
+  If EndBit is greater than 15, then ASSERT().
+  If EndBit is less than StartBit, then ASSERT().
+  If AndData is larger than the bitmask value range specified by StartBit and 
EndBit, then ASSERT().
+  If OrData is larger than the bitmask value range specified by StartBit and 
EndBit, then ASSERT().
+
+  @param  Address   The PCI configuration register to write.
+  @param  StartBit  The ordinal of the least significant bit in the bit field.
+                    Range 0..15.
+  @param  EndBit    The ordinal of the most significant bit in the bit field.
+                    Range 0..15.
+  @param  AndData   The value to AND with the PCI configuration register.
+  @param  OrData    The value to OR with the result of the AND operation.
+
+  @return The value written back to the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciExpressBitFieldAndThenOr16 (
+  IN      UINTN                     Address,
+  IN      UINTN                     StartBit,
+  IN      UINTN                     EndBit,
+  IN      UINT16                    AndData,
+  IN      UINT16                    OrData
+  )
+{
+  ASSERT_INVALID_PCI_ADDRESS (Address);
+  return MmioBitFieldAndThenOr16 (
+           (UINTN) GetPciExpressBaseAddress () + Address,
+           StartBit,
+           EndBit,
+           AndData,
+           OrData
+           );
+}
+
+/**
+  Reads a 32-bit PCI configuration register.
+
+  Reads and returns the 32-bit PCI configuration register specified by Address.
+  This function must guarantee that all PCI read and write operations are
+  serialized.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If Address is not aligned on a 32-bit boundary, then ASSERT().
+
+  @param  Address The address that encodes the PCI Bus, Device, Function and
+                  Register.
+
+  @return The read value from the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciExpressRead32 (
+  IN      UINTN                     Address
+  )
+{
+  ASSERT_INVALID_PCI_ADDRESS (Address);
+  return MmioRead32 ((UINTN) GetPciExpressBaseAddress () + Address);
+}
+
+/**
+  Writes a 32-bit PCI configuration register.
+
+  Writes the 32-bit PCI configuration register specified by Address with the
+  value specified by Value. Value is returned. This function must guarantee
+  that all PCI read and write operations are serialized.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If Address is not aligned on a 32-bit boundary, then ASSERT().
+
+  @param  Address The address that encodes the PCI Bus, Device, Function and
+                  Register.
+  @param  Value   The value to write.
+
+  @return The value written to the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciExpressWrite32 (
+  IN      UINTN                     Address,
+  IN      UINT32                    Value
+  )
+{
+  ASSERT_INVALID_PCI_ADDRESS (Address);
+  return MmioWrite32 ((UINTN) GetPciExpressBaseAddress () + Address, Value);
+}
+
+/**
+  Performs a bitwise OR of a 32-bit PCI configuration register with
+  a 32-bit value.
+
+  Reads the 32-bit PCI configuration register specified by Address, performs a
+  bitwise OR between the read result and the value specified by
+  OrData, and writes the result to the 32-bit PCI configuration register
+  specified by Address. The value written to the PCI configuration register is
+  returned. This function must guarantee that all PCI read and write operations
+  are serialized.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If Address is not aligned on a 32-bit boundary, then ASSERT().
+
+  @param  Address The address that encodes the PCI Bus, Device, Function and
+                  Register.
+  @param  OrData  The value to OR with the PCI configuration register.
+
+  @return The value written back to the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciExpressOr32 (
+  IN      UINTN                     Address,
+  IN      UINT32                    OrData
+  )
+{
+  ASSERT_INVALID_PCI_ADDRESS (Address);
+  return MmioOr32 ((UINTN) GetPciExpressBaseAddress () + Address, OrData);
+}
+
+/**
+  Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit
+  value.
+
+  Reads the 32-bit PCI configuration register specified by Address, performs a
+  bitwise AND between the read result and the value specified by AndData, and
+  writes the result to the 32-bit PCI configuration register specified by
+  Address. The value written to the PCI configuration register is returned.
+  This function must guarantee that all PCI read and write operations are
+  serialized.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If Address is not aligned on a 32-bit boundary, then ASSERT().
+
+  @param  Address The address that encodes the PCI Bus, Device, Function and
+                  Register.
+  @param  AndData The value to AND with the PCI configuration register.
+
+  @return The value written back to the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciExpressAnd32 (
+  IN      UINTN                     Address,
+  IN      UINT32                    AndData
+  )
+{
+  ASSERT_INVALID_PCI_ADDRESS (Address);
+  return MmioAnd32 ((UINTN) GetPciExpressBaseAddress () + Address, AndData);
+}
+
+/**
+  Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit
+  value, followed a  bitwise OR with another 32-bit value.
+
+  Reads the 32-bit PCI configuration register specified by Address, performs a
+  bitwise AND between the read result and the value specified by AndData,
+  performs a bitwise OR between the result of the AND operation and
+  the value specified by OrData, and writes the result to the 32-bit PCI
+  configuration register specified by Address. The value written to the PCI
+  configuration register is returned. This function must guarantee that all PCI
+  read and write operations are serialized.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If Address is not aligned on a 32-bit boundary, then ASSERT().
+
+  @param  Address The address that encodes the PCI Bus, Device, Function and
+                  Register.
+  @param  AndData The value to AND with the PCI configuration register.
+  @param  OrData  The value to OR with the result of the AND operation.
+
+  @return The value written back to the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciExpressAndThenOr32 (
+  IN      UINTN                     Address,
+  IN      UINT32                    AndData,
+  IN      UINT32                    OrData
+  )
+{
+  ASSERT_INVALID_PCI_ADDRESS (Address);
+  return MmioAndThenOr32 (
+           (UINTN) GetPciExpressBaseAddress () + Address,
+           AndData,
+           OrData
+           );
+}
+
+/**
+  Reads a bit field of a PCI configuration register.
+
+  Reads the bit field in a 32-bit PCI configuration register. The bit field is
+  specified by the StartBit and the EndBit. The value of the bit field is
+  returned.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If Address is not aligned on a 32-bit boundary, then ASSERT().
+  If StartBit is greater than 31, then ASSERT().
+  If EndBit is greater than 31, then ASSERT().
+  If EndBit is less than StartBit, then ASSERT().
+
+  @param  Address   The PCI configuration register to read.
+  @param  StartBit  The ordinal of the least significant bit in the bit field.
+                    Range 0..31.
+  @param  EndBit    The ordinal of the most significant bit in the bit field.
+                    Range 0..31.
+
+  @return The value of the bit field read from the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciExpressBitFieldRead32 (
+  IN      UINTN                     Address,
+  IN      UINTN                     StartBit,
+  IN      UINTN                     EndBit
+  )
+{
+  ASSERT_INVALID_PCI_ADDRESS (Address);
+  return MmioBitFieldRead32 (
+           (UINTN) GetPciExpressBaseAddress () + Address,
+           StartBit,
+           EndBit
+           );
+}
+
+/**
+  Writes a bit field to a PCI configuration register.
+
+  Writes Value to the bit field of the PCI configuration register. The bit
+  field is specified by the StartBit and the EndBit. All other bits in the
+  destination PCI configuration register are preserved. The new value of the
+  32-bit register is returned.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If Address is not aligned on a 32-bit boundary, then ASSERT().
+  If StartBit is greater than 31, then ASSERT().
+  If EndBit is greater than 31, then ASSERT().
+  If EndBit is less than StartBit, then ASSERT().
+  If Value is larger than the bitmask value range specified by StartBit and 
EndBit, then ASSERT().
+
+  @param  Address   The PCI configuration register to write.
+  @param  StartBit  The ordinal of the least significant bit in the bit field.
+                    Range 0..31.
+  @param  EndBit    The ordinal of the most significant bit in the bit field.
+                    Range 0..31.
+  @param  Value     The new value of the bit field.
+
+  @return The value written back to the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciExpressBitFieldWrite32 (
+  IN      UINTN                     Address,
+  IN      UINTN                     StartBit,
+  IN      UINTN                     EndBit,
+  IN      UINT32                    Value
+  )
+{
+  ASSERT_INVALID_PCI_ADDRESS (Address);
+  return MmioBitFieldWrite32 (
+           (UINTN) GetPciExpressBaseAddress () + Address,
+           StartBit,
+           EndBit,
+           Value
+           );
+}
+
+/**
+  Reads a bit field in a 32-bit PCI configuration, performs a bitwise OR, and
+  writes the result back to the bit field in the 32-bit port.
+
+  Reads the 32-bit PCI configuration register specified by Address, performs a
+  bitwise OR between the read result and the value specified by
+  OrData, and writes the result to the 32-bit PCI configuration register
+  specified by Address. The value written to the PCI configuration register is
+  returned. This function must guarantee that all PCI read and write operations
+  are serialized. Extra left bits in OrData are stripped.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If Address is not aligned on a 32-bit boundary, then ASSERT().
+  If StartBit is greater than 31, then ASSERT().
+  If EndBit is greater than 31, then ASSERT().
+  If EndBit is less than StartBit, then ASSERT().
+  If OrData is larger than the bitmask value range specified by StartBit and 
EndBit, then ASSERT().
+
+  @param  Address   The PCI configuration register to write.
+  @param  StartBit  The ordinal of the least significant bit in the bit field.
+                    Range 0..31.
+  @param  EndBit    The ordinal of the most significant bit in the bit field.
+                    Range 0..31.
+  @param  OrData    The value to OR with the PCI configuration register.
+
+  @return The value written back to the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciExpressBitFieldOr32 (
+  IN      UINTN                     Address,
+  IN      UINTN                     StartBit,
+  IN      UINTN                     EndBit,
+  IN      UINT32                    OrData
+  )
+{
+  ASSERT_INVALID_PCI_ADDRESS (Address);
+  return MmioBitFieldOr32 (
+           (UINTN) GetPciExpressBaseAddress () + Address,
+           StartBit,
+           EndBit,
+           OrData
+           );
+}
+
+/**
+  Reads a bit field in a 32-bit PCI configuration register, performs a bitwise
+  AND, and writes the result back to the bit field in the 32-bit register.
+
+  Reads the 32-bit PCI configuration register specified by Address, performs a
+  bitwise AND between the read result and the value specified by AndData, and
+  writes the result to the 32-bit PCI configuration register specified by
+  Address. The value written to the PCI configuration register is returned.
+  This function must guarantee that all PCI read and write operations are
+  serialized. Extra left bits in AndData are stripped.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If Address is not aligned on a 32-bit boundary, then ASSERT().
+  If StartBit is greater than 31, then ASSERT().
+  If EndBit is greater than 31, then ASSERT().
+  If EndBit is less than StartBit, then ASSERT().
+  If AndData is larger than the bitmask value range specified by StartBit and 
EndBit, then ASSERT().
+
+  @param  Address   The PCI configuration register to write.
+  @param  StartBit  The ordinal of the least significant bit in the bit field.
+                    Range 0..31.
+  @param  EndBit    The ordinal of the most significant bit in the bit field.
+                    Range 0..31.
+  @param  AndData   The value to AND with the PCI configuration register.
+
+  @return The value written back to the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciExpressBitFieldAnd32 (
+  IN      UINTN                     Address,
+  IN      UINTN                     StartBit,
+  IN      UINTN                     EndBit,
+  IN      UINT32                    AndData
+  )
+{
+  ASSERT_INVALID_PCI_ADDRESS (Address);
+  return MmioBitFieldAnd32 (
+           (UINTN) GetPciExpressBaseAddress () + Address,
+           StartBit,
+           EndBit,
+           AndData
+           );
+}
+
+/**
+  Reads a bit field in a 32-bit port, performs a bitwise AND followed by a
+  bitwise OR, and writes the result back to the bit field in the
+  32-bit port.
+
+  Reads the 32-bit PCI configuration register specified by Address, performs a
+  bitwise AND followed by a bitwise OR between the read result and
+  the value specified by AndData, and writes the result to the 32-bit PCI
+  configuration register specified by Address. The value written to the PCI
+  configuration register is returned. This function must guarantee that all PCI
+  read and write operations are serialized. Extra left bits in both AndData and
+  OrData are stripped.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If Address is not aligned on a 32-bit boundary, then ASSERT().
+  If StartBit is greater than 31, then ASSERT().
+  If EndBit is greater than 31, then ASSERT().
+  If EndBit is less than StartBit, then ASSERT().
+  If AndData is larger than the bitmask value range specified by StartBit and 
EndBit, then ASSERT().
+  If OrData is larger than the bitmask value range specified by StartBit and 
EndBit, then ASSERT().
+
+  @param  Address   The PCI configuration register to write.
+  @param  StartBit  The ordinal of the least significant bit in the bit field.
+                    Range 0..31.
+  @param  EndBit    The ordinal of the most significant bit in the bit field.
+                    Range 0..31.
+  @param  AndData   The value to AND with the PCI configuration register.
+  @param  OrData    The value to OR with the result of the AND operation.
+
+  @return The value written back to the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciExpressBitFieldAndThenOr32 (
+  IN      UINTN                     Address,
+  IN      UINTN                     StartBit,
+  IN      UINTN                     EndBit,
+  IN      UINT32                    AndData,
+  IN      UINT32                    OrData
+  )
+{
+  ASSERT_INVALID_PCI_ADDRESS (Address);
+  return MmioBitFieldAndThenOr32 (
+           (UINTN) GetPciExpressBaseAddress () + Address,
+           StartBit,
+           EndBit,
+           AndData,
+           OrData
+           );
+}
+
+/**
+  Reads a range of PCI configuration registers into a caller supplied buffer.
+
+  Reads the range of PCI configuration registers specified by StartAddress and
+  Size into the buffer specified by Buffer. This function only allows the PCI
+  configuration registers from a single PCI function to be read. Size is
+  returned. When possible 32-bit PCI configuration read cycles are used to read
+  from StartAdress to StartAddress + Size. Due to alignment restrictions, 8-bit
+  and 16-bit PCI configuration read cycles may be used at the beginning and the
+  end of the range.
+
+  If StartAddress > 0x0FFFFFFF, then ASSERT().
+  If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT().
+  If Size > 0 and Buffer is NULL, then ASSERT().
+
+  @param  StartAddress  The starting address that encodes the PCI Bus, Device,
+                        Function and Register.
+  @param  Size          The size in bytes of the transfer.
+  @param  Buffer        The pointer to a buffer receiving the data read.
+
+  @return Size read data from StartAddress.
+
+**/
+UINTN
+EFIAPI
+PciExpressReadBuffer (
+  IN      UINTN                     StartAddress,
+  IN      UINTN                     Size,
+  OUT     VOID                      *Buffer
+  )
+{
+  UINTN   ReturnValue;
+
+  ASSERT_INVALID_PCI_ADDRESS (StartAddress);
+  ASSERT (((StartAddress & 0xFFF) + Size) <= 0x1000);
+
+  if (Size == 0) {
+    return Size;
+  }
+
+  ASSERT (Buffer != NULL);
+
+  //
+  // Save Size for return
+  //
+  ReturnValue = Size;
+
+  if ((StartAddress & 1) != 0) {
+    //
+    // Read a byte if StartAddress is byte aligned
+    //
+    *(volatile UINT8 *)Buffer = PciExpressRead8 (StartAddress);
+    StartAddress += sizeof (UINT8);
+    Size -= sizeof (UINT8);
+    Buffer = (UINT8*)Buffer + 1;
+  }
+
+  if (Size >= sizeof (UINT16) && (StartAddress & 2) != 0) {
+    //
+    // Read a word if StartAddress is word aligned
+    //
+    WriteUnaligned16 ((UINT16 *) Buffer, (UINT16) PciExpressRead16 
(StartAddress));
+
+    StartAddress += sizeof (UINT16);
+    Size -= sizeof (UINT16);
+    Buffer = (UINT16*)Buffer + 1;
+  }
+
+  while (Size >= sizeof (UINT32)) {
+    //
+    // Read as many double words as possible
+    //
+    WriteUnaligned32 ((UINT32 *) Buffer, (UINT32) PciExpressRead32 
(StartAddress));
+
+    StartAddress += sizeof (UINT32);
+    Size -= sizeof (UINT32);
+    Buffer = (UINT32*)Buffer + 1;
+  }
+
+  if (Size >= sizeof (UINT16)) {
+    //
+    // Read the last remaining word if exist
+    //
+    WriteUnaligned16 ((UINT16 *) Buffer, (UINT16) PciExpressRead16 
(StartAddress));
+    StartAddress += sizeof (UINT16);
+    Size -= sizeof (UINT16);
+    Buffer = (UINT16*)Buffer + 1;
+  }
+
+  if (Size >= sizeof (UINT8)) {
+    //
+    // Read the last remaining byte if exist
+    //
+    *(volatile UINT8 *)Buffer = PciExpressRead8 (StartAddress);
+  }
+
+  return ReturnValue;
+}
+
+/**
+  Copies the data in a caller supplied buffer to a specified range of PCI
+  configuration space.
+
+  Writes the range of PCI configuration registers specified by StartAddress and
+  Size from the buffer specified by Buffer. This function only allows the PCI
+  configuration registers from a single PCI function to be written. Size is
+  returned. When possible 32-bit PCI configuration write cycles are used to
+  write from StartAdress to StartAddress + Size. Due to alignment restrictions,
+  8-bit and 16-bit PCI configuration write cycles may be used at the beginning
+  and the end of the range.
+
+  If StartAddress > 0x0FFFFFFF, then ASSERT().
+  If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT().
+  If Size > 0 and Buffer is NULL, then ASSERT().
+
+  @param  StartAddress  The starting address that encodes the PCI Bus, Device,
+                        Function and Register.
+  @param  Size          The size in bytes of the transfer.
+  @param  Buffer        The pointer to a buffer containing the data to write.
+
+  @return Size written to StartAddress.
+
+**/
+UINTN
+EFIAPI
+PciExpressWriteBuffer (
+  IN      UINTN                     StartAddress,
+  IN      UINTN                     Size,
+  IN      VOID                      *Buffer
+  )
+{
+  UINTN                             ReturnValue;
+
+  ASSERT_INVALID_PCI_ADDRESS (StartAddress);
+  ASSERT (((StartAddress & 0xFFF) + Size) <= 0x1000);
+
+  if (Size == 0) {
+    return 0;
+  }
+
+  ASSERT (Buffer != NULL);
+
+  //
+  // Save Size for return
+  //
+  ReturnValue = Size;
+
+  if ((StartAddress & 1) != 0) {
+    //
+    // Write a byte if StartAddress is byte aligned
+    //
+    PciExpressWrite8 (StartAddress, *(UINT8*)Buffer);
+    StartAddress += sizeof (UINT8);
+    Size -= sizeof (UINT8);
+    Buffer = (UINT8*)Buffer + 1;
+  }
+
+  if (Size >= sizeof (UINT16) && (StartAddress & 2) != 0) {
+    //
+    // Write a word if StartAddress is word aligned
+    //
+    PciExpressWrite16 (StartAddress, ReadUnaligned16 ((UINT16*)Buffer));
+    StartAddress += sizeof (UINT16);
+    Size -= sizeof (UINT16);
+    Buffer = (UINT16*)Buffer + 1;
+  }
+
+  while (Size >= sizeof (UINT32)) {
+    //
+    // Write as many double words as possible
+    //
+    PciExpressWrite32 (StartAddress, ReadUnaligned32 ((UINT32*)Buffer));
+    StartAddress += sizeof (UINT32);
+    Size -= sizeof (UINT32);
+    Buffer = (UINT32*)Buffer + 1;
+  }
+
+  if (Size >= sizeof (UINT16)) {
+    //
+    // Write the last remaining word if exist
+    //
+    PciExpressWrite16 (StartAddress, ReadUnaligned16 ((UINT16*)Buffer));
+    StartAddress += sizeof (UINT16);
+    Size -= sizeof (UINT16);
+    Buffer = (UINT16*)Buffer + 1;
+  }
+
+  if (Size >= sizeof (UINT8)) {
+    //
+    // Write the last remaining byte if exist
+    //
+    PciExpressWrite8 (StartAddress, *(UINT8*)Buffer);
+  }
+
+  return ReturnValue;
+}
diff --git a/UefiPayloadPkg/Library/BasePciLibPciExpress/PciLib.c 
b/UefiPayloadPkg/Library/BasePciLibPciExpress/PciLib.c
new file mode 100644
index 000000000000..fba5914462c8
--- /dev/null
+++ b/UefiPayloadPkg/Library/BasePciLibPciExpress/PciLib.c
@@ -0,0 +1,1302 @@
+/** @file
+  PCI Library functions that use the 256 MB PCI Express MMIO window to perform 
PCI
+  Configuration cycles. Layers on PCI Express Library.
+
+  Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+
+#include <Base.h>
+
+#include <Library/PciLib.h>
+#include <Library/PciExpressLib.h>
+#include <Library/PciCf8Lib.h>
+
+#include <Pi/PiBootMode.h>
+#include <Uefi/UefiBaseType.h>
+#include <Uefi/UefiMultiPhase.h>
+#include <Pi/PiHob.h>
+
+#include <Library/HobLib.h>
+#include <Guid/AcpiBoardInfoGuid.h>
+
+STATIC BOOLEAN mMMCONFEnabled;
+
+/**
+  Registers a PCI device so PCI configuration registers may be accessed after
+  SetVirtualAddressMap().
+
+  Registers the PCI device specified by Address so all the PCI configuration 
registers
+  associated with that PCI device may be accessed after SetVirtualAddressMap() 
is called.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+
+  @param  Address The address that encodes the PCI Bus, Device, Function and
+                  Register.
+
+  @retval RETURN_SUCCESS           The PCI device was registered for runtime 
access.
+  @retval RETURN_UNSUPPORTED       An attempt was made to call this function
+                                   after ExitBootServices().
+  @retval RETURN_UNSUPPORTED       The resources required to access the PCI 
device
+                                   at runtime could not be mapped.
+  @retval RETURN_OUT_OF_RESOURCES  There are not enough resources available to
+                                   complete the registration.
+
+**/
+RETURN_STATUS
+EFIAPI
+PciRegisterForRuntimeAccess (
+  IN UINTN  Address
+  )
+{
+  return PciExpressRegisterForRuntimeAccess (Address);
+}
+
+/**
+  Performs platform specific initialization required for the CPU to access
+  the MMCONF space.  This function does not initialize the MMCONF itself.
+
+  @retval RETURN_SUCCESS       The platform specific initialization succeeded.
+  @retval RETURN_DEVICE_ERROR  The platform specific initialization could not 
be completed.
+
+**/
+RETURN_STATUS
+EFIAPI
+PciLibInitialize (
+  VOID
+  )
+{
+  EFI_HOB_GUID_TYPE         *GuidHob;
+  ACPI_BOARD_INFO           *AcpiBoardInfoPtr;
+
+  //
+  // Find the acpi board information guid hob
+  //
+  GuidHob = GetFirstGuidHob (&gUefiAcpiBoardInfoGuid);
+  if (GuidHob == NULL) {
+    return EFI_SUCCESS;
+  }
+  AcpiBoardInfoPtr = (ACPI_BOARD_INFO *)GET_GUID_HOB_DATA (GuidHob);
+
+  mMMCONFEnabled = AcpiBoardInfoPtr->PcieBaseAddress != 0 &&
+      AcpiBoardInfoPtr->PcieBaseSize != 0;
+  return EFI_SUCCESS;
+}
+
+/**
+  Reads an 8-bit PCI configuration register.
+
+  Reads and returns the 8-bit PCI configuration register specified by Address.
+  This function must guarantee that all PCI read and write operations are
+  serialized.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+
+  @param  Address The address that encodes the PCI Bus, Device, Function and
+                  Register.
+
+  @return The read value from the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciRead8 (
+  IN      UINTN                     Address
+  )
+{
+  if (mMMCONFEnabled) {
+    return PciExpressRead8 (Address);
+  } else {
+    return PciCf8Read8 (Address);
+  }
+}
+
+/**
+  Writes an 8-bit PCI configuration register.
+
+  Writes the 8-bit PCI configuration register specified by Address with the
+  value specified by Value. Value is returned. This function must guarantee
+  that all PCI read and write operations are serialized.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+
+  @param  Address The address that encodes the PCI Bus, Device, Function and
+                  Register.
+  @param  Value   The value to write.
+
+  @return The value written to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciWrite8 (
+  IN      UINTN                     Address,
+  IN      UINT8                     Value
+  )
+{
+  if (mMMCONFEnabled) {
+    return PciExpressWrite8 (Address, Value);
+  } else {
+    return PciCf8Write8 (Address, Value);
+  }
+}
+
+/**
+  Performs a bitwise OR of an 8-bit PCI configuration register with
+  an 8-bit value.
+
+  Reads the 8-bit PCI configuration register specified by Address, performs a
+  bitwise OR between the read result and the value specified by
+  OrData, and writes the result to the 8-bit PCI configuration register
+  specified by Address. The value written to the PCI configuration register is
+  returned. This function must guarantee that all PCI read and write operations
+  are serialized.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+
+  @param  Address The address that encodes the PCI Bus, Device, Function and
+                  Register.
+  @param  OrData  The value to OR with the PCI configuration register.
+
+  @return The value written back to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciOr8 (
+  IN      UINTN                     Address,
+  IN      UINT8                     OrData
+  )
+{
+  if (mMMCONFEnabled) {
+    return PciExpressOr8 (Address, OrData);
+  } else {
+    return PciCf8Or8 (Address, OrData);
+  }
+}
+
+/**
+  Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit
+  value.
+
+  Reads the 8-bit PCI configuration register specified by Address, performs a
+  bitwise AND between the read result and the value specified by AndData, and
+  writes the result to the 8-bit PCI configuration register specified by
+  Address. The value written to the PCI configuration register is returned.
+  This function must guarantee that all PCI read and write operations are
+  serialized.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+
+  @param  Address The address that encodes the PCI Bus, Device, Function and
+                  Register.
+  @param  AndData The value to AND with the PCI configuration register.
+
+  @return The value written back to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciAnd8 (
+  IN      UINTN                     Address,
+  IN      UINT8                     AndData
+  )
+{
+  if (mMMCONFEnabled) {
+    return PciExpressAnd8 (Address, AndData);
+  } else {
+    return PciCf8And8 (Address, AndData);
+  }
+}
+
+/**
+  Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit
+  value, followed a  bitwise OR with another 8-bit value.
+
+  Reads the 8-bit PCI configuration register specified by Address, performs a
+  bitwise AND between the read result and the value specified by AndData,
+  performs a bitwise OR between the result of the AND operation and
+  the value specified by OrData, and writes the result to the 8-bit PCI
+  configuration register specified by Address. The value written to the PCI
+  configuration register is returned. This function must guarantee that all PCI
+  read and write operations are serialized.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+
+  @param  Address The address that encodes the PCI Bus, Device, Function and
+                  Register.
+  @param  AndData The value to AND with the PCI configuration register.
+  @param  OrData  The value to OR with the result of the AND operation.
+
+  @return The value written back to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciAndThenOr8 (
+  IN      UINTN                     Address,
+  IN      UINT8                     AndData,
+  IN      UINT8                     OrData
+  )
+{
+  if (mMMCONFEnabled) {
+    return PciExpressAndThenOr8 (Address, AndData, OrData);
+  } else {
+    return PciCf8AndThenOr8 (Address, AndData, OrData);
+  }
+}
+
+/**
+  Reads a bit field of a PCI configuration register.
+
+  Reads the bit field in an 8-bit PCI configuration register. The bit field is
+  specified by the StartBit and the EndBit. The value of the bit field is
+  returned.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If StartBit is greater than 7, then ASSERT().
+  If EndBit is greater than 7, then ASSERT().
+  If EndBit is less than StartBit, then ASSERT().
+
+  @param  Address   The PCI configuration register to read.
+  @param  StartBit  The ordinal of the least significant bit in the bit field.
+                    Range 0..7.
+  @param  EndBit    The ordinal of the most significant bit in the bit field.
+                    Range 0..7.
+
+  @return The value of the bit field read from the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciBitFieldRead8 (
+  IN      UINTN                     Address,
+  IN      UINTN                     StartBit,
+  IN      UINTN                     EndBit
+  )
+{
+  if (mMMCONFEnabled) {
+    return PciExpressBitFieldRead8 (Address, StartBit, EndBit);
+  } else {
+    return PciCf8BitFieldRead8 (Address, StartBit, EndBit);
+  }
+}
+
+/**
+  Writes a bit field to a PCI configuration register.
+
+  Writes Value to the bit field of the PCI configuration register. The bit
+  field is specified by the StartBit and the EndBit. All other bits in the
+  destination PCI configuration register are preserved. The new value of the
+  8-bit register is returned.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If StartBit is greater than 7, then ASSERT().
+  If EndBit is greater than 7, then ASSERT().
+  If EndBit is less than StartBit, then ASSERT().
+  If Value is larger than the bitmask value range specified by StartBit and 
EndBit, then ASSERT().
+
+  @param  Address   The PCI configuration register to write.
+  @param  StartBit  The ordinal of the least significant bit in the bit field.
+                    Range 0..7.
+  @param  EndBit    The ordinal of the most significant bit in the bit field.
+                    Range 0..7.
+  @param  Value     The new value of the bit field.
+
+  @return The value written back to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciBitFieldWrite8 (
+  IN      UINTN                     Address,
+  IN      UINTN                     StartBit,
+  IN      UINTN                     EndBit,
+  IN      UINT8                     Value
+  )
+{
+  if (mMMCONFEnabled) {
+    return PciExpressBitFieldWrite8 (Address, StartBit, EndBit, Value);
+  } else {
+    return PciCf8BitFieldWrite8 (Address, StartBit, EndBit, Value);
+  }
+}
+
+/**
+  Reads a bit field in an 8-bit PCI configuration, performs a bitwise OR, and
+  writes the result back to the bit field in the 8-bit port.
+
+  Reads the 8-bit PCI configuration register specified by Address, performs a
+  bitwise OR between the read result and the value specified by
+  OrData, and writes the result to the 8-bit PCI configuration register
+  specified by Address. The value written to the PCI configuration register is
+  returned. This function must guarantee that all PCI read and write operations
+  are serialized. Extra left bits in OrData are stripped.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If StartBit is greater than 7, then ASSERT().
+  If EndBit is greater than 7, then ASSERT().
+  If EndBit is less than StartBit, then ASSERT().
+  If OrData is larger than the bitmask value range specified by StartBit and 
EndBit, then ASSERT().
+
+  @param  Address   The PCI configuration register to write.
+  @param  StartBit  The ordinal of the least significant bit in the bit field.
+                    Range 0..7.
+  @param  EndBit    The ordinal of the most significant bit in the bit field.
+                    Range 0..7.
+  @param  OrData    The value to OR with the PCI configuration register.
+
+  @return The value written back to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciBitFieldOr8 (
+  IN      UINTN                     Address,
+  IN      UINTN                     StartBit,
+  IN      UINTN                     EndBit,
+  IN      UINT8                     OrData
+  )
+{
+  if (mMMCONFEnabled) {
+    return PciExpressBitFieldOr8 (Address, StartBit, EndBit, OrData);
+  } else {
+    return PciCf8BitFieldOr8 (Address, StartBit, EndBit, OrData);
+  }
+}
+
+/**
+  Reads a bit field in an 8-bit PCI configuration register, performs a bitwise
+  AND, and writes the result back to the bit field in the 8-bit register.
+
+  Reads the 8-bit PCI configuration register specified by Address, performs a
+  bitwise AND between the read result and the value specified by AndData, and
+  writes the result to the 8-bit PCI configuration register specified by
+  Address. The value written to the PCI configuration register is returned.
+  This function must guarantee that all PCI read and write operations are
+  serialized. Extra left bits in AndData are stripped.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If StartBit is greater than 7, then ASSERT().
+  If EndBit is greater than 7, then ASSERT().
+  If EndBit is less than StartBit, then ASSERT().
+  If AndData is larger than the bitmask value range specified by StartBit and 
EndBit, then ASSERT().
+
+  @param  Address   The PCI configuration register to write.
+  @param  StartBit  The ordinal of the least significant bit in the bit field.
+                    Range 0..7.
+  @param  EndBit    The ordinal of the most significant bit in the bit field.
+                    Range 0..7.
+  @param  AndData   The value to AND with the PCI configuration register.
+
+  @return The value written back to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciBitFieldAnd8 (
+  IN      UINTN                     Address,
+  IN      UINTN                     StartBit,
+  IN      UINTN                     EndBit,
+  IN      UINT8                     AndData
+  )
+{
+  if (mMMCONFEnabled) {
+    return PciExpressBitFieldAnd8 (Address, StartBit, EndBit, AndData);
+  } else {
+    return PciCf8BitFieldAnd8 (Address, StartBit, EndBit, AndData);
+  }
+}
+
+/**
+  Reads a bit field in an 8-bit port, performs a bitwise AND followed by a
+  bitwise OR, and writes the result back to the bit field in the
+  8-bit port.
+
+  Reads the 8-bit PCI configuration register specified by Address, performs a
+  bitwise AND followed by a bitwise OR between the read result and
+  the value specified by AndData, and writes the result to the 8-bit PCI
+  configuration register specified by Address. The value written to the PCI
+  configuration register is returned. This function must guarantee that all PCI
+  read and write operations are serialized. Extra left bits in both AndData and
+  OrData are stripped.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If StartBit is greater than 7, then ASSERT().
+  If EndBit is greater than 7, then ASSERT().
+  If EndBit is less than StartBit, then ASSERT().
+  If AndData is larger than the bitmask value range specified by StartBit and 
EndBit, then ASSERT().
+  If OrData is larger than the bitmask value range specified by StartBit and 
EndBit, then ASSERT().
+
+  @param  Address   The PCI configuration register to write.
+  @param  StartBit  The ordinal of the least significant bit in the bit field.
+                    Range 0..7.
+  @param  EndBit    The ordinal of the most significant bit in the bit field.
+                    Range 0..7.
+  @param  AndData   The value to AND with the PCI configuration register.
+  @param  OrData    The value to OR with the result of the AND operation.
+
+  @return The value written back to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciBitFieldAndThenOr8 (
+  IN      UINTN                     Address,
+  IN      UINTN                     StartBit,
+  IN      UINTN                     EndBit,
+  IN      UINT8                     AndData,
+  IN      UINT8                     OrData
+  )
+{
+  if (mMMCONFEnabled) {
+    return PciExpressBitFieldAndThenOr8 (Address, StartBit, EndBit, AndData, 
OrData);
+  } else {
+    return PciCf8BitFieldAndThenOr8 (Address, StartBit, EndBit, AndData, 
OrData);
+  }
+}
+
+/**
+  Reads a 16-bit PCI configuration register.
+
+  Reads and returns the 16-bit PCI configuration register specified by Address.
+  This function must guarantee that all PCI read and write operations are
+  serialized.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If Address is not aligned on a 16-bit boundary, then ASSERT().
+
+  @param  Address The address that encodes the PCI Bus, Device, Function and
+                  Register.
+
+  @return The read value from the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciRead16 (
+  IN      UINTN                     Address
+  )
+{
+  if (mMMCONFEnabled) {
+    return PciExpressRead16 (Address);
+  } else {
+    return PciCf8Read16 (Address);
+  }
+}
+
+/**
+  Writes a 16-bit PCI configuration register.
+
+  Writes the 16-bit PCI configuration register specified by Address with the
+  value specified by Value. Value is returned. This function must guarantee
+  that all PCI read and write operations are serialized.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If Address is not aligned on a 16-bit boundary, then ASSERT().
+
+  @param  Address The address that encodes the PCI Bus, Device, Function and
+                  Register.
+  @param  Value   The value to write.
+
+  @return The value written to the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciWrite16 (
+  IN      UINTN                     Address,
+  IN      UINT16                    Value
+  )
+{
+  if (mMMCONFEnabled) {
+    return PciExpressWrite16 (Address, Value);
+  } else {
+    return PciCf8Write16 (Address, Value);
+  }
+}
+
+/**
+  Performs a bitwise OR of a 16-bit PCI configuration register with
+  a 16-bit value.
+
+  Reads the 16-bit PCI configuration register specified by Address, performs a
+  bitwise OR between the read result and the value specified by
+  OrData, and writes the result to the 16-bit PCI configuration register
+  specified by Address. The value written to the PCI configuration register is
+  returned. This function must guarantee that all PCI read and write operations
+  are serialized.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If Address is not aligned on a 16-bit boundary, then ASSERT().
+
+  @param  Address The address that encodes the PCI Bus, Device, Function and
+                  Register.
+  @param  OrData  The value to OR with the PCI configuration register.
+
+  @return The value written back to the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciOr16 (
+  IN      UINTN                     Address,
+  IN      UINT16                    OrData
+  )
+{
+  if (mMMCONFEnabled) {
+    return PciExpressOr16 (Address, OrData);
+  } else {
+    return PciCf8Or16 (Address, OrData);
+  }
+}
+
+/**
+  Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit
+  value.
+
+  Reads the 16-bit PCI configuration register specified by Address, performs a
+  bitwise AND between the read result and the value specified by AndData, and
+  writes the result to the 16-bit PCI configuration register specified by
+  Address. The value written to the PCI configuration register is returned.
+  This function must guarantee that all PCI read and write operations are
+  serialized.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If Address is not aligned on a 16-bit boundary, then ASSERT().
+
+  @param  Address The address that encodes the PCI Bus, Device, Function and
+                  Register.
+  @param  AndData The value to AND with the PCI configuration register.
+
+  @return The value written back to the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciAnd16 (
+  IN      UINTN                     Address,
+  IN      UINT16                    AndData
+  )
+{
+  if (mMMCONFEnabled) {
+    return PciExpressAnd16 (Address, AndData);
+  } else {
+    return PciCf8And16 (Address, AndData);
+  }
+}
+
+/**
+  Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit
+  value, followed a  bitwise OR with another 16-bit value.
+
+  Reads the 16-bit PCI configuration register specified by Address, performs a
+  bitwise AND between the read result and the value specified by AndData,
+  performs a bitwise OR between the result of the AND operation and
+  the value specified by OrData, and writes the result to the 16-bit PCI
+  configuration register specified by Address. The value written to the PCI
+  configuration register is returned. This function must guarantee that all PCI
+  read and write operations are serialized.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If Address is not aligned on a 16-bit boundary, then ASSERT().
+
+  @param  Address The address that encodes the PCI Bus, Device, Function and
+                  Register.
+  @param  AndData The value to AND with the PCI configuration register.
+  @param  OrData  The value to OR with the result of the AND operation.
+
+  @return The value written back to the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciAndThenOr16 (
+  IN      UINTN                     Address,
+  IN      UINT16                    AndData,
+  IN      UINT16                    OrData
+  )
+{
+  if (mMMCONFEnabled) {
+    return PciExpressAndThenOr16 (Address, AndData, OrData);
+  } else {
+    return PciCf8AndThenOr16 (Address, AndData, OrData);
+  }
+}
+
+/**
+  Reads a bit field of a PCI configuration register.
+
+  Reads the bit field in a 16-bit PCI configuration register. The bit field is
+  specified by the StartBit and the EndBit. The value of the bit field is
+  returned.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If Address is not aligned on a 16-bit boundary, then ASSERT().
+  If StartBit is greater than 15, then ASSERT().
+  If EndBit is greater than 15, then ASSERT().
+  If EndBit is less than StartBit, then ASSERT().
+
+  @param  Address   The PCI configuration register to read.
+  @param  StartBit  The ordinal of the least significant bit in the bit field.
+                    Range 0..15.
+  @param  EndBit    The ordinal of the most significant bit in the bit field.
+                    Range 0..15.
+
+  @return The value of the bit field read from the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciBitFieldRead16 (
+  IN      UINTN                     Address,
+  IN      UINTN                     StartBit,
+  IN      UINTN                     EndBit
+  )
+{
+  if (mMMCONFEnabled) {
+    return PciExpressBitFieldRead16 (Address, StartBit, EndBit);
+  } else {
+    return PciCf8BitFieldRead16 (Address, StartBit, EndBit);
+  }
+}
+
+/**
+  Writes a bit field to a PCI configuration register.
+
+  Writes Value to the bit field of the PCI configuration register. The bit
+  field is specified by the StartBit and the EndBit. All other bits in the
+  destination PCI configuration register are preserved. The new value of the
+  16-bit register is returned.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If Address is not aligned on a 16-bit boundary, then ASSERT().
+  If StartBit is greater than 15, then ASSERT().
+  If EndBit is greater than 15, then ASSERT().
+  If EndBit is less than StartBit, then ASSERT().
+  If Value is larger than the bitmask value range specified by StartBit and 
EndBit, then ASSERT().
+
+  @param  Address   The PCI configuration register to write.
+  @param  StartBit  The ordinal of the least significant bit in the bit field.
+                    Range 0..15.
+  @param  EndBit    The ordinal of the most significant bit in the bit field.
+                    Range 0..15.
+  @param  Value     The new value of the bit field.
+
+  @return The value written back to the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciBitFieldWrite16 (
+  IN      UINTN                     Address,
+  IN      UINTN                     StartBit,
+  IN      UINTN                     EndBit,
+  IN      UINT16                    Value
+  )
+{
+  if (mMMCONFEnabled) {
+    return PciExpressBitFieldWrite16 (Address, StartBit, EndBit, Value);
+  } else {
+    return PciCf8BitFieldWrite16 (Address, StartBit, EndBit, Value);
+  }
+}
+
+/**
+  Reads a bit field in a 16-bit PCI configuration, performs a bitwise OR, and
+  writes the result back to the bit field in the 16-bit port.
+
+  Reads the 16-bit PCI configuration register specified by Address, performs a
+  bitwise OR between the read result and the value specified by
+  OrData, and writes the result to the 16-bit PCI configuration register
+  specified by Address. The value written to the PCI configuration register is
+  returned. This function must guarantee that all PCI read and write operations
+  are serialized. Extra left bits in OrData are stripped.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If Address is not aligned on a 16-bit boundary, then ASSERT().
+  If StartBit is greater than 15, then ASSERT().
+  If EndBit is greater than 15, then ASSERT().
+  If EndBit is less than StartBit, then ASSERT().
+  If OrData is larger than the bitmask value range specified by StartBit and 
EndBit, then ASSERT().
+
+  @param  Address   The PCI configuration register to write.
+  @param  StartBit  The ordinal of the least significant bit in the bit field.
+                    Range 0..15.
+  @param  EndBit    The ordinal of the most significant bit in the bit field.
+                    Range 0..15.
+  @param  OrData    The value to OR with the PCI configuration register.
+
+  @return The value written back to the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciBitFieldOr16 (
+  IN      UINTN                     Address,
+  IN      UINTN                     StartBit,
+  IN      UINTN                     EndBit,
+  IN      UINT16                    OrData
+  )
+{
+  if (mMMCONFEnabled) {
+    return PciExpressBitFieldOr16 (Address, StartBit, EndBit, OrData);
+  } else {
+    return PciCf8BitFieldOr16 (Address, StartBit, EndBit, OrData);
+  }
+}
+
+/**
+  Reads a bit field in a 16-bit PCI configuration register, performs a bitwise
+  AND, and writes the result back to the bit field in the 16-bit register.
+
+  Reads the 16-bit PCI configuration register specified by Address, performs a
+  bitwise AND between the read result and the value specified by AndData, and
+  writes the result to the 16-bit PCI configuration register specified by
+  Address. The value written to the PCI configuration register is returned.
+  This function must guarantee that all PCI read and write operations are
+  serialized. Extra left bits in AndData are stripped.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If Address is not aligned on a 16-bit boundary, then ASSERT().
+  If StartBit is greater than 15, then ASSERT().
+  If EndBit is greater than 15, then ASSERT().
+  If EndBit is less than StartBit, then ASSERT().
+  If AndData is larger than the bitmask value range specified by StartBit and 
EndBit, then ASSERT().
+
+  @param  Address   The PCI configuration register to write.
+  @param  StartBit  The ordinal of the least significant bit in the bit field.
+                    Range 0..15.
+  @param  EndBit    The ordinal of the most significant bit in the bit field.
+                    Range 0..15.
+  @param  AndData   The value to AND with the PCI configuration register.
+
+  @return The value written back to the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciBitFieldAnd16 (
+  IN      UINTN                     Address,
+  IN      UINTN                     StartBit,
+  IN      UINTN                     EndBit,
+  IN      UINT16                    AndData
+  )
+{
+  if (mMMCONFEnabled) {
+    return PciExpressBitFieldAnd16 (Address, StartBit, EndBit, AndData);
+  } else {
+    return PciCf8BitFieldAnd16 (Address, StartBit, EndBit, AndData);
+  }
+}
+
+/**
+  Reads a bit field in a 16-bit port, performs a bitwise AND followed by a
+  bitwise OR, and writes the result back to the bit field in the
+  16-bit port.
+
+  Reads the 16-bit PCI configuration register specified by Address, performs a
+  bitwise AND followed by a bitwise OR between the read result and
+  the value specified by AndData, and writes the result to the 16-bit PCI
+  configuration register specified by Address. The value written to the PCI
+  configuration register is returned. This function must guarantee that all PCI
+  read and write operations are serialized. Extra left bits in both AndData and
+  OrData are stripped.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If Address is not aligned on a 16-bit boundary, then ASSERT().
+  If StartBit is greater than 15, then ASSERT().
+  If EndBit is greater than 15, then ASSERT().
+  If EndBit is less than StartBit, then ASSERT().
+  If AndData is larger than the bitmask value range specified by StartBit and 
EndBit, then ASSERT().
+  If OrData is larger than the bitmask value range specified by StartBit and 
EndBit, then ASSERT().
+
+  @param  Address   The PCI configuration register to write.
+  @param  StartBit  The ordinal of the least significant bit in the bit field.
+                    Range 0..15.
+  @param  EndBit    The ordinal of the most significant bit in the bit field.
+                    Range 0..15.
+  @param  AndData   The value to AND with the PCI configuration register.
+  @param  OrData    The value to OR with the result of the AND operation.
+
+  @return The value written back to the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciBitFieldAndThenOr16 (
+  IN      UINTN                     Address,
+  IN      UINTN                     StartBit,
+  IN      UINTN                     EndBit,
+  IN      UINT16                    AndData,
+  IN      UINT16                    OrData
+  )
+{
+  if (mMMCONFEnabled) {
+    return PciExpressBitFieldAndThenOr16 (Address, StartBit, EndBit, AndData, 
OrData);
+  } else {
+    return PciCf8BitFieldAndThenOr16 (Address, StartBit, EndBit, AndData, 
OrData);
+  }
+}
+
+/**
+  Reads a 32-bit PCI configuration register.
+
+  Reads and returns the 32-bit PCI configuration register specified by Address.
+  This function must guarantee that all PCI read and write operations are
+  serialized.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If Address is not aligned on a 32-bit boundary, then ASSERT().
+
+  @param  Address The address that encodes the PCI Bus, Device, Function and
+                  Register.
+
+  @return The read value from the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciRead32 (
+  IN      UINTN                     Address
+  )
+{
+  if (mMMCONFEnabled) {
+    return PciExpressRead32 (Address);
+  } else {
+    return PciCf8Read32 (Address);
+  }
+}
+
+/**
+  Writes a 32-bit PCI configuration register.
+
+  Writes the 32-bit PCI configuration register specified by Address with the
+  value specified by Value. Value is returned. This function must guarantee
+  that all PCI read and write operations are serialized.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If Address is not aligned on a 32-bit boundary, then ASSERT().
+
+  @param  Address The address that encodes the PCI Bus, Device, Function and
+                  Register.
+  @param  Value   The value to write.
+
+  @return The value written to the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciWrite32 (
+  IN      UINTN                     Address,
+  IN      UINT32                    Value
+  )
+{
+  if (mMMCONFEnabled) {
+    return PciExpressWrite32 (Address, Value);
+  } else {
+    return PciCf8Write32 (Address, Value);
+  }
+}
+
+/**
+  Performs a bitwise OR of a 32-bit PCI configuration register with
+  a 32-bit value.
+
+  Reads the 32-bit PCI configuration register specified by Address, performs a
+  bitwise OR between the read result and the value specified by
+  OrData, and writes the result to the 32-bit PCI configuration register
+  specified by Address. The value written to the PCI configuration register is
+  returned. This function must guarantee that all PCI read and write operations
+  are serialized.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If Address is not aligned on a 32-bit boundary, then ASSERT().
+
+  @param  Address The address that encodes the PCI Bus, Device, Function and
+                  Register.
+  @param  OrData  The value to OR with the PCI configuration register.
+
+  @return The value written back to the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciOr32 (
+  IN      UINTN                     Address,
+  IN      UINT32                    OrData
+  )
+{
+  if (mMMCONFEnabled) {
+    return PciExpressOr32 (Address, OrData);
+  } else {
+    return PciCf8Or32 (Address, OrData);
+  }
+}
+
+/**
+  Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit
+  value.
+
+  Reads the 32-bit PCI configuration register specified by Address, performs a
+  bitwise AND between the read result and the value specified by AndData, and
+  writes the result to the 32-bit PCI configuration register specified by
+  Address. The value written to the PCI configuration register is returned.
+  This function must guarantee that all PCI read and write operations are
+  serialized.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If Address is not aligned on a 32-bit boundary, then ASSERT().
+
+  @param  Address The address that encodes the PCI Bus, Device, Function and
+                  Register.
+  @param  AndData The value to AND with the PCI configuration register.
+
+  @return The value written back to the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciAnd32 (
+  IN      UINTN                     Address,
+  IN      UINT32                    AndData
+  )
+{
+  if (mMMCONFEnabled) {
+    return PciExpressAnd32 (Address, AndData);
+  } else {
+    return PciCf8And32 (Address, AndData);
+  }
+}
+
+/**
+  Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit
+  value, followed a  bitwise OR with another 32-bit value.
+
+  Reads the 32-bit PCI configuration register specified by Address, performs a
+  bitwise AND between the read result and the value specified by AndData,
+  performs a bitwise OR between the result of the AND operation and
+  the value specified by OrData, and writes the result to the 32-bit PCI
+  configuration register specified by Address. The value written to the PCI
+  configuration register is returned. This function must guarantee that all PCI
+  read and write operations are serialized.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If Address is not aligned on a 32-bit boundary, then ASSERT().
+
+  @param  Address The address that encodes the PCI Bus, Device, Function and
+                  Register.
+  @param  AndData The value to AND with the PCI configuration register.
+  @param  OrData  The value to OR with the result of the AND operation.
+
+  @return The value written back to the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciAndThenOr32 (
+  IN      UINTN                     Address,
+  IN      UINT32                    AndData,
+  IN      UINT32                    OrData
+  )
+{
+  if (mMMCONFEnabled) {
+    return PciExpressAndThenOr32 (Address, AndData, OrData);
+  } else {
+    return PciCf8AndThenOr32 (Address, AndData, OrData);
+  }
+}
+
+/**
+  Reads a bit field of a PCI configuration register.
+
+  Reads the bit field in a 32-bit PCI configuration register. The bit field is
+  specified by the StartBit and the EndBit. The value of the bit field is
+  returned.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If Address is not aligned on a 32-bit boundary, then ASSERT().
+  If StartBit is greater than 31, then ASSERT().
+  If EndBit is greater than 31, then ASSERT().
+  If EndBit is less than StartBit, then ASSERT().
+
+  @param  Address   The PCI configuration register to read.
+  @param  StartBit  The ordinal of the least significant bit in the bit field.
+                    Range 0..31.
+  @param  EndBit    The ordinal of the most significant bit in the bit field.
+                    Range 0..31.
+
+  @return The value of the bit field read from the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciBitFieldRead32 (
+  IN      UINTN                     Address,
+  IN      UINTN                     StartBit,
+  IN      UINTN                     EndBit
+  )
+{
+  if (mMMCONFEnabled) {
+    return PciExpressBitFieldRead32 (Address, StartBit, EndBit);
+  } else {
+    return PciCf8BitFieldRead32 (Address, StartBit, EndBit);
+  }
+}
+
+/**
+  Writes a bit field to a PCI configuration register.
+
+  Writes Value to the bit field of the PCI configuration register. The bit
+  field is specified by the StartBit and the EndBit. All other bits in the
+  destination PCI configuration register are preserved. The new value of the
+  32-bit register is returned.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If Address is not aligned on a 32-bit boundary, then ASSERT().
+  If StartBit is greater than 31, then ASSERT().
+  If EndBit is greater than 31, then ASSERT().
+  If EndBit is less than StartBit, then ASSERT().
+  If Value is larger than the bitmask value range specified by StartBit and 
EndBit, then ASSERT().
+
+  @param  Address   The PCI configuration register to write.
+  @param  StartBit  The ordinal of the least significant bit in the bit field.
+                    Range 0..31.
+  @param  EndBit    The ordinal of the most significant bit in the bit field.
+                    Range 0..31.
+  @param  Value     The new value of the bit field.
+
+  @return The value written back to the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciBitFieldWrite32 (
+  IN      UINTN                     Address,
+  IN      UINTN                     StartBit,
+  IN      UINTN                     EndBit,
+  IN      UINT32                    Value
+  )
+{
+  if (mMMCONFEnabled) {
+    return PciExpressBitFieldWrite32 (Address, StartBit, EndBit, Value);
+  } else {
+    return PciCf8BitFieldWrite32 (Address, StartBit, EndBit, Value);
+  }
+}
+
+/**
+  Reads a bit field in a 32-bit PCI configuration, performs a bitwise OR, and
+  writes the result back to the bit field in the 32-bit port.
+
+  Reads the 32-bit PCI configuration register specified by Address, performs a
+  bitwise OR between the read result and the value specified by
+  OrData, and writes the result to the 32-bit PCI configuration register
+  specified by Address. The value written to the PCI configuration register is
+  returned. This function must guarantee that all PCI read and write operations
+  are serialized. Extra left bits in OrData are stripped.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If Address is not aligned on a 32-bit boundary, then ASSERT().
+  If StartBit is greater than 31, then ASSERT().
+  If EndBit is greater than 31, then ASSERT().
+  If EndBit is less than StartBit, then ASSERT().
+  If OrData is larger than the bitmask value range specified by StartBit and 
EndBit, then ASSERT().
+
+  @param  Address   The PCI configuration register to write.
+  @param  StartBit  The ordinal of the least significant bit in the bit field.
+                    Range 0..31.
+  @param  EndBit    The ordinal of the most significant bit in the bit field.
+                    Range 0..31.
+  @param  OrData    The value to OR with the PCI configuration register.
+
+  @return The value written back to the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciBitFieldOr32 (
+  IN      UINTN                     Address,
+  IN      UINTN                     StartBit,
+  IN      UINTN                     EndBit,
+  IN      UINT32                    OrData
+  )
+{
+  if (mMMCONFEnabled) {
+    return PciExpressBitFieldOr32 (Address, StartBit, EndBit, OrData);
+  } else {
+    return PciCf8BitFieldOr32 (Address, StartBit, EndBit, OrData);
+  }
+}
+
+/**
+  Reads a bit field in a 32-bit PCI configuration register, performs a bitwise
+  AND, and writes the result back to the bit field in the 32-bit register.
+
+  Reads the 32-bit PCI configuration register specified by Address, performs a
+  bitwise AND between the read result and the value specified by AndData, and
+  writes the result to the 32-bit PCI configuration register specified by
+  Address. The value written to the PCI configuration register is returned.
+  This function must guarantee that all PCI read and write operations are
+  serialized. Extra left bits in AndData are stripped.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If Address is not aligned on a 32-bit boundary, then ASSERT().
+  If StartBit is greater than 31, then ASSERT().
+  If EndBit is greater than 31, then ASSERT().
+  If EndBit is less than StartBit, then ASSERT().
+  If AndData is larger than the bitmask value range specified by StartBit and 
EndBit, then ASSERT().
+
+  @param  Address   The PCI configuration register to write.
+  @param  StartBit  The ordinal of the least significant bit in the bit field.
+                    Range 0..31.
+  @param  EndBit    The ordinal of the most significant bit in the bit field.
+                    Range 0..31.
+  @param  AndData   The value to AND with the PCI configuration register.
+
+  @return The value written back to the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciBitFieldAnd32 (
+  IN      UINTN                     Address,
+  IN      UINTN                     StartBit,
+  IN      UINTN                     EndBit,
+  IN      UINT32                    AndData
+  )
+{
+  if (mMMCONFEnabled) {
+    return PciExpressBitFieldAnd32 (Address, StartBit, EndBit, AndData);
+  } else {
+    return PciCf8BitFieldAnd32 (Address, StartBit, EndBit, AndData);
+  }
+}
+
+/**
+  Reads a bit field in a 32-bit port, performs a bitwise AND followed by a
+  bitwise OR, and writes the result back to the bit field in the
+  32-bit port.
+
+  Reads the 32-bit PCI configuration register specified by Address, performs a
+  bitwise AND followed by a bitwise OR between the read result and
+  the value specified by AndData, and writes the result to the 32-bit PCI
+  configuration register specified by Address. The value written to the PCI
+  configuration register is returned. This function must guarantee that all PCI
+  read and write operations are serialized. Extra left bits in both AndData and
+  OrData are stripped.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If Address is not aligned on a 32-bit boundary, then ASSERT().
+  If StartBit is greater than 31, then ASSERT().
+  If EndBit is greater than 31, then ASSERT().
+  If EndBit is less than StartBit, then ASSERT().
+  If AndData is larger than the bitmask value range specified by StartBit and 
EndBit, then ASSERT().
+  If OrData is larger than the bitmask value range specified by StartBit and 
EndBit, then ASSERT().
+
+  @param  Address   The PCI configuration register to write.
+  @param  StartBit  The ordinal of the least significant bit in the bit field.
+                    Range 0..31.
+  @param  EndBit    The ordinal of the most significant bit in the bit field.
+                    Range 0..31.
+  @param  AndData   The value to AND with the PCI configuration register.
+  @param  OrData    The value to OR with the result of the AND operation.
+
+  @return The value written back to the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciBitFieldAndThenOr32 (
+  IN      UINTN                     Address,
+  IN      UINTN                     StartBit,
+  IN      UINTN                     EndBit,
+  IN      UINT32                    AndData,
+  IN      UINT32                    OrData
+  )
+{
+  if (mMMCONFEnabled) {
+    return PciExpressBitFieldAndThenOr32 (Address, StartBit, EndBit, AndData, 
OrData);
+  } else {
+    return PciCf8BitFieldAndThenOr32 (Address, StartBit, EndBit, AndData, 
OrData);
+  }
+}
+
+/**
+  Reads a range of PCI configuration registers into a caller supplied buffer.
+
+  Reads the range of PCI configuration registers specified by StartAddress and
+  Size into the buffer specified by Buffer. This function only allows the PCI
+  configuration registers from a single PCI function to be read. Size is
+  returned. When possible 32-bit PCI configuration read cycles are used to read
+  from StartAdress to StartAddress + Size. Due to alignment restrictions, 8-bit
+  and 16-bit PCI configuration read cycles may be used at the beginning and the
+  end of the range.
+
+  If StartAddress > 0x0FFFFFFF, then ASSERT().
+  If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT().
+  If Size > 0 and Buffer is NULL, then ASSERT().
+
+  @param  StartAddress  The starting address that encodes the PCI Bus, Device,
+                        Function and Register.
+  @param  Size          The size in bytes of the transfer.
+  @param  Buffer        The pointer to a buffer receiving the data read.
+
+  @return Size
+
+**/
+UINTN
+EFIAPI
+PciReadBuffer (
+  IN      UINTN                     StartAddress,
+  IN      UINTN                     Size,
+  OUT     VOID                      *Buffer
+  )
+{
+  if (mMMCONFEnabled) {
+    return PciExpressReadBuffer (StartAddress, Size, Buffer);
+  } else {
+    return PciCf8ReadBuffer (StartAddress, Size, Buffer);
+  }
+}
+
+/**
+  Copies the data in a caller supplied buffer to a specified range of PCI
+  configuration space.
+
+  Writes the range of PCI configuration registers specified by StartAddress and
+  Size from the buffer specified by Buffer. This function only allows the PCI
+  configuration registers from a single PCI function to be written. Size is
+  returned. When possible 32-bit PCI configuration write cycles are used to
+  write from StartAdress to StartAddress + Size. Due to alignment restrictions,
+  8-bit and 16-bit PCI configuration write cycles may be used at the beginning
+  and the end of the range.
+
+  If StartAddress > 0x0FFFFFFF, then ASSERT().
+  If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT().
+  If Size > 0 and Buffer is NULL, then ASSERT().
+
+  @param  StartAddress  The starting address that encodes the PCI Bus, Device,
+                        Function and Register.
+  @param  Size          The size in bytes of the transfer.
+  @param  Buffer        The pointer to a buffer containing the data to write.
+
+  @return Size written to StartAddress.
+
+**/
+UINTN
+EFIAPI
+PciWriteBuffer (
+  IN      UINTN                     StartAddress,
+  IN      UINTN                     Size,
+  IN      VOID                      *Buffer
+  )
+{
+  if (mMMCONFEnabled) {
+    return PciExpressWriteBuffer (StartAddress, Size, Buffer);
+  } else {
+    return PciCf8WriteBuffer (StartAddress, Size, Buffer);
+  }
+}
diff --git a/UefiPayloadPkg/Library/BasePciExpressLib/BasePciExpressLib.uni 
b/UefiPayloadPkg/Library/BasePciExpressLib/BasePciExpressLib.uni
new file mode 100644
index 000000000000..98010ef2f929
--- /dev/null
+++ b/UefiPayloadPkg/Library/BasePciExpressLib/BasePciExpressLib.uni
@@ -0,0 +1,17 @@
+// /** @file
+// Instance of PCI Express Library using the 256 MB PCI Express MMIO window.
+//
+// PCI Express Library that uses the 256 MB PCI Express MMIO window to perform
+// PCI Configuration cycles. Layers on top of an I/O Library instance.
+//
+// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT             #language en-US "Instance of PCI 
Express Library using the 256 MB PCI Express MMIO window"
+
+#string STR_MODULE_DESCRIPTION          #language en-US "PCI Express Library 
that uses the 256 MB PCI Express MMIO window to perform PCI Configuration 
cycles. Layers on top of an I/O Library instance."
+
diff --git 
a/UefiPayloadPkg/Library/BasePciLibPciExpress/BasePciLibPciExpress.uni 
b/UefiPayloadPkg/Library/BasePciLibPciExpress/BasePciLibPciExpress.uni
new file mode 100644
index 000000000000..ccc456356cf2
--- /dev/null
+++ b/UefiPayloadPkg/Library/BasePciLibPciExpress/BasePciLibPciExpress.uni
@@ -0,0 +1,17 @@
+// /** @file
+// Instance of PCI Library based on PCI Express Library.
+//
+// PCI Library that uses the 256 MB PCI Express MMIO window to perform PCI
+// Configuration cycles. Layers on one PCI Express Library instance.
+//
+// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT             #language en-US "Instance of PCI 
Library based on PCI Express Library"
+
+#string STR_MODULE_DESCRIPTION          #language en-US "PCI Library that uses 
the 256 MB PCI Express MMIO window to perform PCI Configuration cycles. Layers 
on an PCI Express Library instance."
+
-- 
2.25.4


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.

View/Reply Online (#61655): https://edk2.groups.io/g/devel/message/61655
Mute This Topic: https://groups.io/mt/75080104/21656
Group Owner: devel+ow...@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub  [arch...@mail-archive.com]
-=-=-=-=-=-=-=-=-=-=-=-

Reply via email to