public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* SMM PciExpressLib Instance
@ 2016-09-14 19:21 Felix Poludov
  2016-09-14 19:28 ` Felix Poludov
  0 siblings, 1 reply; 5+ messages in thread
From: Felix Poludov @ 2016-09-14 19:21 UTC (permalink / raw)
  To: edk2-devel@lists.01.org

Dear MdePkg maintainer,

MdePkg does not provide a specialized instance of PciExpressLib for SMM Drivers.
It provides Base instance that is typically used by SMM Drivers.
However, BasePciExpressLib calls PcdGet64 (PcdPciExpressBaseAddress) on every PCI-E access
and PcdPciExpressBaseAddress is declared in MdePkg.dec as a potentially dynamic token.
SMM Drivers cannot use BasePciExpressLib when PcdPciExpressBaseAddress is dynamic.
This patch adds SMM instance of PciExpressLib based on BasePciExpressLib.
The only difference from BasePciExpressLib is a constructor that caches PCD value into a local variable.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Felix Polyudov <felixp@ami.com<mailto:felixp@ami.com>>

Thanks
Felix

Please consider the environment before printing this email.

The information contained in this message may be confidential and proprietary to American Megatrends, Inc.  This communication is intended to be read only by the individual or entity to whom it is addressed or by their designee. If the reader of this message is not the intended recipient, you are on notice that any distribution of this message, in any form, is strictly prohibited.  Please promptly notify the sender by reply e-mail or by telephone at 770-246-8600, and then delete or destroy all copies of the transmission.


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

* Re: SMM PciExpressLib Instance
  2016-09-14 19:21 SMM PciExpressLib Instance Felix Poludov
@ 2016-09-14 19:28 ` Felix Poludov
  2016-09-15  2:33   ` Kinney, Michael D
  0 siblings, 1 reply; 5+ messages in thread
From: Felix Poludov @ 2016-09-14 19:28 UTC (permalink / raw)
  To: edk2-devel@lists.01.org

Resending with the patch (the patch was missing in the original e-mail).

-----Original Message-----
From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Felix Poludov
Sent: Wednesday, September 14, 2016 3:22 PM
To: edk2-devel@lists.01.org
Subject: [edk2] SMM PciExpressLib Instance

Dear MdePkg maintainer,

MdePkg does not provide a specialized instance of PciExpressLib for SMM Drivers.
It provides Base instance that is typically used by SMM Drivers.
However, BasePciExpressLib calls PcdGet64 (PcdPciExpressBaseAddress) on every PCI-E access
and PcdPciExpressBaseAddress is declared in MdePkg.dec as a potentially dynamic token.
SMM Drivers cannot use BasePciExpressLib when PcdPciExpressBaseAddress is dynamic.
This patch adds SMM instance of PciExpressLib based on BasePciExpressLib.
The only difference from BasePciExpressLib is a constructor that caches PCD value into a local variable.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Felix Polyudov <felixp@ami.com<mailto:felixp@ami.com>>

Thanks
Felix

==
diff --git a/MdePkg/Library/SmmPciExpressLib/PciExpressLib.c b/MdePkg/Library/SmmPciExpressLib/PciExpressLib.c
new file mode 100644
index 0000000..5857b85
--- /dev/null
+++ b/MdePkg/Library/SmmPciExpressLib/PciExpressLib.c
@@ -0,0 +1,1447 @@
+/** @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 - 2012, Intel Corporation. All rights reserved.<BR>
+  Portions copyright (c) 2016, American Megatrends, Inc. All rights reserved.<BR>
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php.
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+#include <PiDxe.h>
+
+#include <Library/BaseLib.h>
+#include <Library/PciExpressLib.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+
+///
+/// Module global that contains the base physical address of the PCI Express MMIO range.
+///
+VOID *mSmmPciExpressLibPciExpressBaseAddress = 0;
+
+/**
+  The constructor function caches the PCI Express Base Address
+
+  @param  ImageHandle   The firmware allocated handle for the EFI image.
+  @param  SystemTable   A pointer to the EFI System Table.
+
+  @retval EFI_SUCCESS   The constructor completed successfully.
+**/
+EFI_STATUS
+EFIAPI
+SmmPciExpressLibConstructor (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  //
+  // Cache the physical address of the PCI Express MMIO range into a module global variable
+  //
+  mSmmPciExpressLibPciExpressBaseAddress = (VOID*)(UINTN) PcdGet64 (PcdPciExpressBaseAddress);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Assert the validity of a PCI address. A valid PCI address should contain 1's
+  only in the low 28 bits.
+
+  @param  A The address to validate.
+
+**/
+#define ASSERT_INVALID_PCI_ADDRESS(A) \
+  ASSERT (((A) & ~0xfffffff) == 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;
+}
+
+/**
+  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 mSmmPciExpressLibPciExpressBaseAddress;
+}
+
+/**
+  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/MdePkg/Library/SmmPciExpressLib/SmmPciExpressLib.inf b/MdePkg/Library/SmmPciExpressLib/SmmPciExpressLib.inf
new file mode 100644
index 0000000..e4cfebc
--- /dev/null
+++ b/MdePkg/Library/SmmPciExpressLib/SmmPciExpressLib.inf
@@ -0,0 +1,42 @@
+## @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>
+#  Portions copyright (c) 2016, American Megatrends, Inc. All rights reserved.<BR>
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution. The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php.
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = SmmPciExpressLib
+  FILE_GUID                      = 00D24382-8231-4B18-A4F0-2D94D8FE2E81
+  MODULE_TYPE                    = DXE_SMM_DRIVER
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = PciExpressLib|DXE_SMM_DRIVER SMM_CORE
+  CONSTRUCTOR                    = SmmPciExpressLibConstructor
+
+[Sources]
+  PciExpressLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+
+[LibraryClasses]
+  BaseLib
+  PcdLib
+  DebugLib
+  IoLib
+
+[Pcd]
+  gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress  ## CONSUMES


Please consider the environment before printing this email.

The information contained in this message may be confidential and proprietary to American Megatrends, Inc.  This communication is intended to be read only by the individual or entity to whom it is addressed or by their designee. If the reader of this message is not the intended recipient, you are on notice that any distribution of this message, in any form, is strictly prohibited.  Please promptly notify the sender by reply e-mail or by telephone at 770-246-8600, and then delete or destroy all copies of the transmission.


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

* Re: SMM PciExpressLib Instance
  2016-09-14 19:28 ` Felix Poludov
@ 2016-09-15  2:33   ` Kinney, Michael D
  2016-09-15 12:54     ` Felix Poludov
  0 siblings, 1 reply; 5+ messages in thread
From: Kinney, Michael D @ 2016-09-15  2:33 UTC (permalink / raw)
  To: Felix Poludov, edk2-devel@lists.01.org, Kinney, Michael D

Felix,

Since you are doing math with the base address, shouldn't the type be UINTN
Instead of VOID *?

Please see MdePkg/Library/DxeRuntimePciExpressLib for an instance of this 
library class that caches the PCD into a global in a CONSTRUCTOR and uses
type UINTN.  Maybe this SMM lib instance should be based on DxeRuntimePciExpressLib
with the only difference being the removal of the register for runtime feature.

Thanks,

Mike

> -----Original Message-----
> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Felix Poludov
> Sent: Wednesday, September 14, 2016 12:29 PM
> To: edk2-devel@lists.01.org
> Subject: Re: [edk2] SMM PciExpressLib Instance
> 
> Resending with the patch (the patch was missing in the original e-mail).
> 
> -----Original Message-----
> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Felix Poludov
> Sent: Wednesday, September 14, 2016 3:22 PM
> To: edk2-devel@lists.01.org
> Subject: [edk2] SMM PciExpressLib Instance
> 
> Dear MdePkg maintainer,
> 
> MdePkg does not provide a specialized instance of PciExpressLib for SMM Drivers.
> It provides Base instance that is typically used by SMM Drivers.
> However, BasePciExpressLib calls PcdGet64 (PcdPciExpressBaseAddress) on every PCI-E
> access
> and PcdPciExpressBaseAddress is declared in MdePkg.dec as a potentially dynamic
> token.
> SMM Drivers cannot use BasePciExpressLib when PcdPciExpressBaseAddress is dynamic.
> This patch adds SMM instance of PciExpressLib based on BasePciExpressLib.
> The only difference from BasePciExpressLib is a constructor that caches PCD value
> into a local variable.
> 
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Felix Polyudov <felixp@ami.com<mailto:felixp@ami.com>>
> 
> Thanks
> Felix
> 
> ==
> diff --git a/MdePkg/Library/SmmPciExpressLib/PciExpressLib.c
> b/MdePkg/Library/SmmPciExpressLib/PciExpressLib.c
> new file mode 100644
> index 0000000..5857b85
> --- /dev/null
> +++ b/MdePkg/Library/SmmPciExpressLib/PciExpressLib.c
> @@ -0,0 +1,1447 @@
> +/** @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 - 2012, Intel Corporation. All rights reserved.<BR>
> +  Portions copyright (c) 2016, American Megatrends, Inc. All rights reserved.<BR>
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  http://opensource.org/licenses/bsd-license.php.
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +**/
> +
> +
> +#include <PiDxe.h>
> +
> +#include <Library/BaseLib.h>
> +#include <Library/PciExpressLib.h>
> +#include <Library/IoLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/PcdLib.h>
> +
> +///
> +/// Module global that contains the base physical address of the PCI Express MMIO
> range.
> +///
> +VOID *mSmmPciExpressLibPciExpressBaseAddress = 0;
> +
> +/**
> +  The constructor function caches the PCI Express Base Address
> +
> +  @param  ImageHandle   The firmware allocated handle for the EFI image.
> +  @param  SystemTable   A pointer to the EFI System Table.
> +
> +  @retval EFI_SUCCESS   The constructor completed successfully.
> +**/
> +EFI_STATUS
> +EFIAPI
> +SmmPciExpressLibConstructor (
> +  IN EFI_HANDLE        ImageHandle,
> +  IN EFI_SYSTEM_TABLE  *SystemTable
> +  )
> +{
> +  //
> +  // Cache the physical address of the PCI Express MMIO range into a module global
> variable
> +  //
> +  mSmmPciExpressLibPciExpressBaseAddress = (VOID*)(UINTN) PcdGet64
> (PcdPciExpressBaseAddress);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Assert the validity of a PCI address. A valid PCI address should contain 1's
> +  only in the low 28 bits.
> +
> +  @param  A The address to validate.
> +
> +**/
> +#define ASSERT_INVALID_PCI_ADDRESS(A) \
> +  ASSERT (((A) & ~0xfffffff) == 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;
> +}
> +
> +/**
> +  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 mSmmPciExpressLibPciExpressBaseAddress;
> +}
> +
> +/**
> +  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/MdePkg/Library/SmmPciExpressLib/SmmPciExpressLib.inf
> b/MdePkg/Library/SmmPciExpressLib/SmmPciExpressLib.inf
> new file mode 100644
> index 0000000..e4cfebc
> --- /dev/null
> +++ b/MdePkg/Library/SmmPciExpressLib/SmmPciExpressLib.inf
> @@ -0,0 +1,42 @@
> +## @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>
> +#  Portions copyright (c) 2016, American Megatrends, Inc. All rights reserved.<BR>
> +#
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the BSD License
> +#  which accompanies this distribution. The full text of the license may be found at
> +#  http://opensource.org/licenses/bsd-license.php.
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +#
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x00010005
> +  BASE_NAME                      = SmmPciExpressLib
> +  FILE_GUID                      = 00D24382-8231-4B18-A4F0-2D94D8FE2E81
> +  MODULE_TYPE                    = DXE_SMM_DRIVER
> +  VERSION_STRING                 = 1.0
> +  LIBRARY_CLASS                  = PciExpressLib|DXE_SMM_DRIVER SMM_CORE
> +  CONSTRUCTOR                    = SmmPciExpressLibConstructor
> +
> +[Sources]
> +  PciExpressLib.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +
> +[LibraryClasses]
> +  BaseLib
> +  PcdLib
> +  DebugLib
> +  IoLib
> +
> +[Pcd]
> +  gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress  ## CONSUMES
> 
> 
> Please consider the environment before printing this email.
> 
> The information contained in this message may be confidential and proprietary to
> American Megatrends, Inc.  This communication is intended to be read only by the
> individual or entity to whom it is addressed or by their designee. If the reader of
> this message is not the intended recipient, you are on notice that any distribution
> of this message, in any form, is strictly prohibited.  Please promptly notify the
> sender by reply e-mail or by telephone at 770-246-8600, and then delete or destroy
> all copies of the transmission.
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel


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

* Re: SMM PciExpressLib Instance
  2016-09-15  2:33   ` Kinney, Michael D
@ 2016-09-15 12:54     ` Felix Poludov
  2016-09-20 14:02       ` Gao, Liming
  0 siblings, 1 reply; 5+ messages in thread
From: Felix Poludov @ 2016-09-15 12:54 UTC (permalink / raw)
  To: Kinney, Michael D, edk2-devel@lists.01.org

Mike,

I updated the library to be based on DxeRuntimePciExpressLib.
Here is the new patch.

Thanks,
Felix

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Felix Polyudov <felixp@ami.com<mailto:felixp@ami.com>>
==
diff --git a/MdePkg/Library/SmmPciExpressLib/PciExpressLib.c b/MdePkg/Library/SmmPciExpressLib/PciExpressLib.c
new file mode 100644
index 0000000..1b88770
--- /dev/null
+++ b/MdePkg/Library/SmmPciExpressLib/PciExpressLib.c
@@ -0,0 +1,1431 @@
+/** @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 - 2012, Intel Corporation. All rights reserved.<BR>
+  Portions copyright (c) 2016, American Megatrends, Inc. All rights reserved.<BR>
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php.
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+#include <PiDxe.h>
+
+#include <Library/BaseLib.h>
+#include <Library/PciExpressLib.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+
+///
+/// Module global that contains the base physical address of the PCI Express MMIO range.
+///
+UINTN mSmmPciExpressLibPciExpressBaseAddress = 0;
+
+/**
+  The constructor function caches the PCI Express Base Address
+
+  @param  ImageHandle   The firmware allocated handle for the EFI image.
+  @param  SystemTable   A pointer to the EFI System Table.
+
+  @retval EFI_SUCCESS   The constructor completed successfully.
+**/
+EFI_STATUS
+EFIAPI
+SmmPciExpressLibConstructor (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  //
+  // Cache the physical address of the PCI Express MMIO range into a module global variable
+  //
+  mSmmPciExpressLibPciExpressBaseAddress = (UINTN) PcdGet64 (PcdPciExpressBaseAddress);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Assert the validity of a PCI address. A valid PCI address should contain 1's
+  only in the low 28 bits.
+
+  @param  A The address to validate.
+
+**/
+#define ASSERT_INVALID_PCI_ADDRESS(A) \
+  ASSERT (((A) & ~0xfffffff) == 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;
+}
+
+/**
+  Gets MMIO address that can be used to access PCI Express location defined by Address.
+
+  This internal functions converts PCI Express address to a CPU MMIO address by adding
+  PCI Express Base Address stored in a global variable mSmmPciExpressLibPciExpressBaseAddress.
+  mSmmPciExpressLibPciExpressBaseAddress is initialized in the library constructor from PCD entry
+  PcdPciExpressBaseAddress.
+
+  @param  Address  The address that encodes the PCI Bus, Device, Function and Register.
+  @return          MMIO address corresponding to Address.
+
+**/
+UINTN
+GetPciExpressAddress (
+  IN UINTN  Address
+  )
+{
+  //
+  // Make sure Address is valid
+  //
+  ASSERT_INVALID_PCI_ADDRESS (Address);
+  return mSmmPciExpressLibPciExpressBaseAddress + Address;
+}
+
+/**
+  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
+  )
+{
+  return MmioRead8 (GetPciExpressAddress (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
+  )
+{
+  return MmioWrite8 (GetPciExpressAddress (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
+  )
+{
+  return MmioOr8 (GetPciExpressAddress (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
+  )
+{
+  return MmioAnd8 (GetPciExpressAddress (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
+  )
+{
+  return MmioAndThenOr8 (
+           GetPciExpressAddress (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
+  )
+{
+  return MmioBitFieldRead8 (
+           GetPciExpressAddress (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
+  )
+{
+  return MmioBitFieldWrite8 (
+           GetPciExpressAddress (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
+  )
+{
+  return MmioBitFieldOr8 (
+           GetPciExpressAddress (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
+  )
+{
+  return MmioBitFieldAnd8 (
+           GetPciExpressAddress (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
+  )
+{
+  return MmioBitFieldAndThenOr8 (
+           GetPciExpressAddress (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
+  )
+{
+  return MmioRead16 (GetPciExpressAddress (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
+  )
+{
+  return MmioWrite16 (GetPciExpressAddress (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
+  )
+{
+  return MmioOr16 (GetPciExpressAddress (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
+  )
+{
+  return MmioAnd16 (GetPciExpressAddress (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
+  )
+{
+  return MmioAndThenOr16 (
+           GetPciExpressAddress (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
+  )
+{
+  return MmioBitFieldRead16 (
+           GetPciExpressAddress (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
+  )
+{
+  return MmioBitFieldWrite16 (
+           GetPciExpressAddress (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
+  )
+{
+  return MmioBitFieldOr16 (
+           GetPciExpressAddress (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
+  )
+{
+  return MmioBitFieldAnd16 (
+           GetPciExpressAddress (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
+  )
+{
+  return MmioBitFieldAndThenOr16 (
+           GetPciExpressAddress (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
+  )
+{
+  return MmioRead32 (GetPciExpressAddress (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
+  )
+{
+  return MmioWrite32 (GetPciExpressAddress (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
+  )
+{
+  return MmioOr32 (GetPciExpressAddress (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
+  )
+{
+  return MmioAnd32 (GetPciExpressAddress (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
+  )
+{
+  return MmioAndThenOr32 (
+           GetPciExpressAddress (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
+  )
+{
+  return MmioBitFieldRead32 (
+           GetPciExpressAddress (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
+  )
+{
+  return MmioBitFieldWrite32 (
+           GetPciExpressAddress (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
+  )
+{
+  return MmioBitFieldOr32 (
+           GetPciExpressAddress (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
+  )
+{
+  return MmioBitFieldAnd32 (
+           GetPciExpressAddress (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
+  )
+{
+  return MmioBitFieldAndThenOr32 (
+           GetPciExpressAddress (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;
+
+  //
+  // Make sure Address is valid
+  //
+  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;
+
+  //
+  // Make sure Address is valid
+  //
+  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/MdePkg/Library/SmmPciExpressLib/SmmPciExpressLib.inf b/MdePkg/Library/SmmPciExpressLib/SmmPciExpressLib.inf
new file mode 100644
index 0000000..e4cfebc
--- /dev/null
+++ b/MdePkg/Library/SmmPciExpressLib/SmmPciExpressLib.inf
@@ -0,0 +1,42 @@
+## @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>
+#  Portions copyright (c) 2016, American Megatrends, Inc. All rights reserved.<BR>
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution. The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php.
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = SmmPciExpressLib
+  FILE_GUID                      = 00D24382-8231-4B18-A4F0-2D94D8FE2E81
+  MODULE_TYPE                    = DXE_SMM_DRIVER
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = PciExpressLib|DXE_SMM_DRIVER SMM_CORE
+  CONSTRUCTOR                    = SmmPciExpressLibConstructor
+
+[Sources]
+  PciExpressLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+
+[LibraryClasses]
+  BaseLib
+  PcdLib
+  DebugLib
+  IoLib
+
+[Pcd]
+  gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress  ## CONSUMES
==

-----Original Message-----
From: Kinney, Michael D [mailto:michael.d.kinney@intel.com]
Sent: Wednesday, September 14, 2016 10:34 PM
To: Felix Poludov; edk2-devel@lists.01.org; Kinney, Michael D
Subject: RE: SMM PciExpressLib Instance

Felix,

Since you are doing math with the base address, shouldn't the type be UINTN
Instead of VOID *?

Please see MdePkg/Library/DxeRuntimePciExpressLib for an instance of this
library class that caches the PCD into a global in a CONSTRUCTOR and uses
type UINTN.  Maybe this SMM lib instance should be based on DxeRuntimePciExpressLib
with the only difference being the removal of the register for runtime feature.

Thanks,

Mike

> -----Original Message-----
> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Felix Poludov
> Sent: Wednesday, September 14, 2016 12:29 PM
> To: edk2-devel@lists.01.org
> Subject: Re: [edk2] SMM PciExpressLib Instance
>
> Resending with the patch (the patch was missing in the original e-mail).
>
> -----Original Message-----
> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Felix Poludov
> Sent: Wednesday, September 14, 2016 3:22 PM
> To: edk2-devel@lists.01.org
> Subject: [edk2] SMM PciExpressLib Instance
>
> Dear MdePkg maintainer,
>
> MdePkg does not provide a specialized instance of PciExpressLib for SMM Drivers.
> It provides Base instance that is typically used by SMM Drivers.
> However, BasePciExpressLib calls PcdGet64 (PcdPciExpressBaseAddress) on every PCI-E
> access
> and PcdPciExpressBaseAddress is declared in MdePkg.dec as a potentially dynamic
> token.
> SMM Drivers cannot use BasePciExpressLib when PcdPciExpressBaseAddress is dynamic.
> This patch adds SMM instance of PciExpressLib based on BasePciExpressLib.
> The only difference from BasePciExpressLib is a constructor that caches PCD value
> into a local variable.
>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Felix Polyudov <felixp@ami.com<mailto:felixp@ami.com>>
>
> Thanks
> Felix

Please consider the environment before printing this email.

The information contained in this message may be confidential and proprietary to American Megatrends, Inc.  This communication is intended to be read only by the individual or entity to whom it is addressed or by their designee. If the reader of this message is not the intended recipient, you are on notice that any distribution of this message, in any form, is strictly prohibited.  Please promptly notify the sender by reply e-mail or by telephone at 770-246-8600, and then delete or destroy all copies of the transmission.


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

* Re: SMM PciExpressLib Instance
  2016-09-15 12:54     ` Felix Poludov
@ 2016-09-20 14:02       ` Gao, Liming
  0 siblings, 0 replies; 5+ messages in thread
From: Gao, Liming @ 2016-09-20 14:02 UTC (permalink / raw)
  To: Felix Poludov, Kinney, Michael D, edk2-devel@lists.01.org

Felix:
  This patch is good to me. Reviewed-by: Liming Gao <liming.gao@intel.com>

Thanks
Liming
From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Felix Poludov
Sent: Thursday, September 15, 2016 8:55 PM
To: Kinney, Michael D <michael.d.kinney@intel.com>; edk2-devel@lists.01.org
Subject: Re: [edk2] SMM PciExpressLib Instance

Mike,

I updated the library to be based on DxeRuntimePciExpressLib.
Here is the new patch.

Thanks,
Felix

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Felix Polyudov <felixp@ami.com<mailto:felixp@ami.com>>
==
diff --git a/MdePkg/Library/SmmPciExpressLib/PciExpressLib.c b/MdePkg/Library/SmmPciExpressLib/PciExpressLib.c
new file mode 100644
index 0000000..1b88770
--- /dev/null
+++ b/MdePkg/Library/SmmPciExpressLib/PciExpressLib.c
@@ -0,0 +1,1431 @@
+/** @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 - 2012, Intel Corporation. All rights reserved.

+ Portions copyright (c) 2016, American Megatrends, Inc. All rights reserved.

+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+///
+/// Module global that contains the base physical address of the PCI Express MMIO range.
+///
+UINTN mSmmPciExpressLibPciExpressBaseAddress = 0;
+
+/**
+ The constructor function caches the PCI Express Base Address
+
+ @param ImageHandle The firmware allocated handle for the EFI image.
+ @param SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The constructor completed successfully.
+**/
+EFI_STATUS
+EFIAPI
+SmmPciExpressLibConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ //
+ // Cache the physical address of the PCI Express MMIO range into a module global variable
+ //
+ mSmmPciExpressLibPciExpressBaseAddress = (UINTN) PcdGet64 (PcdPciExpressBaseAddress);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Assert the validity of a PCI address. A valid PCI address should contain 1's
+ only in the low 28 bits.
+
+ @param A The address to validate.
+
+**/
+#define ASSERT_INVALID_PCI_ADDRESS(A) \
+ ASSERT (((A) & ~0xfffffff) == 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;
+}
+
+/**
+ Gets MMIO address that can be used to access PCI Express location defined by Address.
+
+ This internal functions converts PCI Express address to a CPU MMIO address by adding
+ PCI Express Base Address stored in a global variable mSmmPciExpressLibPciExpressBaseAddress.
+ mSmmPciExpressLibPciExpressBaseAddress is initialized in the library constructor from PCD entry
+ PcdPciExpressBaseAddress.
+
+ @param Address The address that encodes the PCI Bus, Device, Function and Register.
+ @return MMIO address corresponding to Address.
+
+**/
+UINTN
+GetPciExpressAddress (
+ IN UINTN Address
+ )
+{
+ //
+ // Make sure Address is valid
+ //
+ ASSERT_INVALID_PCI_ADDRESS (Address);
+ return mSmmPciExpressLibPciExpressBaseAddress + Address;
+}
+
+/**
+ 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
+ )
+{
+ return MmioRead8 (GetPciExpressAddress (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
+ )
+{
+ return MmioWrite8 (GetPciExpressAddress (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
+ )
+{
+ return MmioOr8 (GetPciExpressAddress (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
+ )
+{
+ return MmioAnd8 (GetPciExpressAddress (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
+ )
+{
+ return MmioAndThenOr8 (
+ GetPciExpressAddress (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
+ )
+{
+ return MmioBitFieldRead8 (
+ GetPciExpressAddress (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
+ )
+{
+ return MmioBitFieldWrite8 (
+ GetPciExpressAddress (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
+ )
+{
+ return MmioBitFieldOr8 (
+ GetPciExpressAddress (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
+ )
+{
+ return MmioBitFieldAnd8 (
+ GetPciExpressAddress (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
+ )
+{
+ return MmioBitFieldAndThenOr8 (
+ GetPciExpressAddress (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
+ )
+{
+ return MmioRead16 (GetPciExpressAddress (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
+ )
+{
+ return MmioWrite16 (GetPciExpressAddress (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
+ )
+{
+ return MmioOr16 (GetPciExpressAddress (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
+ )
+{
+ return MmioAnd16 (GetPciExpressAddress (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
+ )
+{
+ return MmioAndThenOr16 (
+ GetPciExpressAddress (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
+ )
+{
+ return MmioBitFieldRead16 (
+ GetPciExpressAddress (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
+ )
+{
+ return MmioBitFieldWrite16 (
+ GetPciExpressAddress (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
+ )
+{
+ return MmioBitFieldOr16 (
+ GetPciExpressAddress (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
+ )
+{
+ return MmioBitFieldAnd16 (
+ GetPciExpressAddress (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
+ )
+{
+ return MmioBitFieldAndThenOr16 (
+ GetPciExpressAddress (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
+ )
+{
+ return MmioRead32 (GetPciExpressAddress (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
+ )
+{
+ return MmioWrite32 (GetPciExpressAddress (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
+ )
+{
+ return MmioOr32 (GetPciExpressAddress (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
+ )
+{
+ return MmioAnd32 (GetPciExpressAddress (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
+ )
+{
+ return MmioAndThenOr32 (
+ GetPciExpressAddress (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
+ )
+{
+ return MmioBitFieldRead32 (
+ GetPciExpressAddress (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
+ )
+{
+ return MmioBitFieldWrite32 (
+ GetPciExpressAddress (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
+ )
+{
+ return MmioBitFieldOr32 (
+ GetPciExpressAddress (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
+ )
+{
+ return MmioBitFieldAnd32 (
+ GetPciExpressAddress (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
+ )
+{
+ return MmioBitFieldAndThenOr32 (
+ GetPciExpressAddress (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;
+
+ //
+ // Make sure Address is valid
+ //
+ 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;
+
+ //
+ // Make sure Address is valid
+ //
+ 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/MdePkg/Library/SmmPciExpressLib/SmmPciExpressLib.inf b/MdePkg/Library/SmmPciExpressLib/SmmPciExpressLib.inf
new file mode 100644
index 0000000..e4cfebc
--- /dev/null
+++ b/MdePkg/Library/SmmPciExpressLib/SmmPciExpressLib.inf
@@ -0,0 +1,42 @@
+## @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.

+# Portions copyright (c) 2016, American Megatrends, Inc. All rights reserved.

+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php.
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SmmPciExpressLib
+ FILE_GUID = 00D24382-8231-4B18-A4F0-2D94D8FE2E81
+ MODULE_TYPE = DXE_SMM_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PciExpressLib|DXE_SMM_DRIVER SMM_CORE
+ CONSTRUCTOR = SmmPciExpressLibConstructor
+
+[Sources]
+ PciExpressLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ BaseLib
+ PcdLib
+ DebugLib
+ IoLib
+
+[Pcd]
+ gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress ## CONSUMES
==

-----Original Message-----
From: Kinney, Michael D [mailto:michael.d.kinney@intel.com]
Sent: Wednesday, September 14, 2016 10:34 PM
To: Felix Poludov; edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>; Kinney, Michael D
Subject: RE: SMM PciExpressLib Instance

Felix,

Since you are doing math with the base address, shouldn't the type be UINTN
Instead of VOID *?

Please see MdePkg/Library/DxeRuntimePciExpressLib for an instance of this
library class that caches the PCD into a global in a CONSTRUCTOR and uses
type UINTN. Maybe this SMM lib instance should be based on DxeRuntimePciExpressLib
with the only difference being the removal of the register for runtime feature.

Thanks,

Mike

> -----Original Message-----
> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Felix Poludov
> Sent: Wednesday, September 14, 2016 12:29 PM
> To: edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
> Subject: Re: [edk2] SMM PciExpressLib Instance
>
> Resending with the patch (the patch was missing in the original e-mail).
>
> -----Original Message-----
> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Felix Poludov
> Sent: Wednesday, September 14, 2016 3:22 PM
> To: edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
> Subject: [edk2] SMM PciExpressLib Instance
>
> Dear MdePkg maintainer,
>
> MdePkg does not provide a specialized instance of PciExpressLib for SMM Drivers.
> It provides Base instance that is typically used by SMM Drivers.
> However, BasePciExpressLib calls PcdGet64 (PcdPciExpressBaseAddress) on every PCI-E
> access
> and PcdPciExpressBaseAddress is declared in MdePkg.dec as a potentially dynamic
> token.
> SMM Drivers cannot use BasePciExpressLib when PcdPciExpressBaseAddress is dynamic.
> This patch adds SMM instance of PciExpressLib based on BasePciExpressLib.
> The only difference from BasePciExpressLib is a constructor that caches PCD value
> into a local variable.
>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Felix Polyudov <felixp@ami.com<mailto:felixp@ami.com>>
>
> Thanks
> Felix

Please consider the environment before printing this email.

The information contained in this message may be confidential and proprietary to American Megatrends, Inc. This communication is intended to be read only by the individual or entity to whom it is addressed or by their designee. If the reader of this message is not the intended recipient, you are on notice that any distribution of this message, in any form, is strictly prohibited. Please promptly notify the sender by reply e-mail or by telephone at 770-246-8600, and then delete or destroy all copies of the transmission.
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
https://lists.01.org/mailman/listinfo/edk2-devel


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

end of thread, other threads:[~2016-09-20 14:02 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-09-14 19:21 SMM PciExpressLib Instance Felix Poludov
2016-09-14 19:28 ` Felix Poludov
2016-09-15  2:33   ` Kinney, Michael D
2016-09-15 12:54     ` Felix Poludov
2016-09-20 14:02       ` Gao, Liming

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