[edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH] PciBusDxe: New PCI features Max_Payload_Size, Max_Read_Req_Size

Javeed, Ashraf posted 1 patch 4 years, 6 months ago
Patches applied successfully (tree, apply log)
git fetch https://github.com/patchew-project/edk2 tags/patchew/20190923142051.10832-1-ashraf.javeed@intel.com
MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c               |   23 ++------------
MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h               |   14 ++++++++-
MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf          |    9 +++++-
MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c     |  229 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------------------------------
MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c        |  139 ++++++++++++++++++++--------------------------------------------------------------
MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c |   34 ++++++++++++--------
MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c    | 1601 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h    |  201 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c   |  565 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h   |  193 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c   |   15 +--------
MdeModulePkg/MdeModulePkg.dec                         |   10 ++++++
12 files changed, 2797 insertions(+), 236 deletions(-)
[edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH] PciBusDxe: New PCI features Max_Payload_Size, Max_Read_Req_Size
Posted by Javeed, Ashraf 4 years, 6 months ago
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=2194

The EDK2 Kernel PciBusDxe driver is enhanced to enable the configuration
of PCI features like Max_Payload_Size and Max_Read_Req_Size.

Max_Payload_Size:- The PCI Device Control register provides this feature
register field which controls the maximum data packet (TLP) size that a
PCI device should maintain as a requester. The PCI Bus driver is required
to maintain a highest common value supported by all the PCI devices in a
PCIe hierarchy, especially in case of isochronous applications.

Max_Read_Req_Size:- The PCI Device Control register provides this feature
register field which controls the maximum memory read request size that a
PCI device should maintain as a requester. The PCI Bus driver is required
to maintain a common value, same as Max_Payload_Size, in case of
isochronous applications only; or else, it should maintain the user
requested value uniformly in a PCIe hierarchy (PCI root port and its
downstream devices).

The PCI Base Specification 4 Revision 1 contains detailed information
about these features. The EDK2 PCI Bus driver needs to enable the
configuration of these features as per the PCI Base specification.

The EDK2 PCI Bus driver also needs to take the PCI device-specific
platform policy into the consideration while programming these features;
thus the code changes to support these, is explicitly dependent on the
new PCI Platform Protocol interface definition defined in the below
record:-
https://bugzilla.tianocore.org/show_bug.cgi?id=1954

Signed-off-by: Ashraf Javeed <ashraf.javeed@intel.com>
Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Hao A Wu <hao.a.wu@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
---
 MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c               |   23 ++------------
 MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h               |   14 ++++++++-
 MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf          |    9 +++++-
 MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c     |  229 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------------------------------
 MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c        |  139 ++++++++++++++++++++--------------------------------------------------------------
 MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c |   34 ++++++++++++--------
 MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c    | 1601 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h    |  201 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c   |  565 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h   |  193 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c   |   15 +--------
 MdeModulePkg/MdeModulePkg.dec                         |   10 ++++++
 12 files changed, 2797 insertions(+), 236 deletions(-)

diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c
index b020ce50ce..2503b298f4 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c
@@ -8,7 +8,7 @@
   PCI Root Bridges. So it means platform needs install PCI Root Bridge IO protocol for each
   PCI Root Bus and install PCI Host Bridge Resource Allocation Protocol.
 
-Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
 SPDX-License-Identifier: BSD-2-Clause-Patent
 
 **/
@@ -34,8 +34,6 @@ BOOLEAN                                       gFullEnumeration     = TRUE;
 UINT64                                        gAllOne              = 0xFFFFFFFFFFFFFFFFULL;
 UINT64                                        gAllZero             = 0;
 
-EFI_PCI_PLATFORM_PROTOCOL                     *gPciPlatformProtocol;
-EFI_PCI_OVERRIDE_PROTOCOL                     *gPciOverrideProtocol;
 EDKII_IOMMU_PROTOCOL                          *mIoMmuProtocol;
 
 
@@ -266,24 +264,7 @@ PciBusDriverBindingStart (
   // If PCI Platform protocol is available, get it now.
   // If the platform implements this, it must be installed before BDS phase
   //
-  gPciPlatformProtocol = NULL;
-  gBS->LocateProtocol (
-        &gEfiPciPlatformProtocolGuid,
-        NULL,
-        (VOID **) &gPciPlatformProtocol
-        );
-
-  //
-  // If PCI Platform protocol doesn't exist, try to Pci Override Protocol.
-  //
-  if (gPciPlatformProtocol == NULL) {
-    gPciOverrideProtocol = NULL;
-    gBS->LocateProtocol (
-          &gEfiPciOverrideProtocolGuid,
-          NULL,
-          (VOID **) &gPciOverrideProtocol
-          );
-  }
+  GetPciPlatformProtocol ();
 
   if (mIoMmuProtocol == NULL) {
     gBS->LocateProtocol (
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
index 504a1b1c12..7955bf8a26 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
@@ -27,6 +27,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 #include <Protocol/PciOverride.h>
 #include <Protocol/PciEnumerationComplete.h>
 #include <Protocol/IoMmu.h>
+#include <Protocol/PciPlatform2.h>
+#include <Protocol/PciOverride2.h>
 
 #include <Library/DebugLib.h>
 #include <Library/UefiDriverEntryPoint.h>
@@ -79,6 +81,7 @@ typedef enum {
 #include "PciPowerManagement.h"
 #include "PciHotPlugSupport.h"
 #include "PciLib.h"
+#include "PciFeatureSupport.h"
 
 #define VGABASE1  0x3B0
 #define VGALIMIT1 0x3BB
@@ -263,9 +266,13 @@ struct _PCI_IO_DEVICE {
 
   BOOLEAN                                   IsPciExp;
   //
-  // For SR-IOV
+  // For PCI Express Capability List Structure
   //
   UINT8                                     PciExpressCapabilityOffset;
+  PCI_CAPABILITY_PCIEXP                     PciExpStruct;
+  //
+  // For SR-IOV
+  //
   UINT32                                    AriCapabilityOffset;
   UINT32                                    SrIovCapabilityOffset;
   UINT32                                    MrIovCapabilityOffset;
@@ -279,6 +286,11 @@ struct _PCI_IO_DEVICE {
   // This field is used to support this case.
   //
   UINT16                                    BridgeIoAlignment;
+  //
+  // Other PCI features setup flags
+  //
+  UINT8                                     SetupMPS;
+  UINT8                                     SetupMRRS;
 };
 
 #define PCI_IO_DEVICE_FROM_PCI_IO_THIS(a) \
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
index 05c22025b8..13768d7ded 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
@@ -2,7 +2,7 @@
 #  The PCI bus driver will probe all PCI devices and allocate MMIO and IO space for these devices.
 #  Please use PCD feature flag PcdPciBusHotplugDeviceSupport to enable hot plug supporting.
 #
-#  Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+#  Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
 #
 #  SPDX-License-Identifier: BSD-2-Clause-Patent
 #
@@ -57,6 +57,10 @@
   PciCommand.h
   PciIo.h
   PciBus.h
+  PciFeatureSupport.c
+  PciFeatureSupport.h
+  PciPlatformSupport.c
+  PciPlatformSupport.h
 
 [Packages]
   MdePkg/MdePkg.dec
@@ -91,6 +95,8 @@
   gEfiLoadFile2ProtocolGuid                       ## SOMETIMES_PRODUCES
   gEdkiiIoMmuProtocolGuid                         ## SOMETIMES_CONSUMES
   gEfiLoadedImageDevicePathProtocolGuid           ## CONSUMES
+  gEfiPciPlatformProtocol2Guid                     ## SOMETIMES_CONSUMES
+  gEfiPciOverrideProtocol2Guid                     ## SOMETIMES_CONSUMES
 
 [FeaturePcd]
   gEfiMdeModulePkgTokenSpaceGuid.PcdPciBusHotplugDeviceSupport      ## CONSUMES
@@ -104,6 +110,7 @@
   gEfiMdeModulePkgTokenSpaceGuid.PcdAriSupport                  ## CONSUMES
   gEfiMdeModulePkgTokenSpaceGuid.PcdMrIovSupport                ## CONSUMES
   gEfiMdeModulePkgTokenSpaceGuid.PcdPciDisableBusEnumeration    ## SOMETIMES_CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdOtherPciFeatures                    ## CONSUMES
 
 [UserExtensions.TianoCore."ExtraFiles"]
   PciBusDxeExtra.uni
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
index b7832c6970..0f76ab1cd5 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
@@ -170,6 +170,8 @@ DestroyRootBridgeByHandle (
 
     if (Temp->Handle == Controller) {
 
+      DestroyRootBridgePciFeaturesConfigCompletionList ( Temp);
+
       RemoveEntryList (CurrentLink);
 
       DestroyPciDeviceTree (Temp);
@@ -208,8 +210,6 @@ RegisterPciDevice (
   )
 {
   EFI_STATUS          Status;
-  VOID                *PlatformOpRomBuffer;
-  UINTN               PlatformOpRomSize;
   EFI_PCI_IO_PROTOCOL *PciIo;
   UINT8               Data8;
   BOOLEAN             HasEfiImage;
@@ -244,49 +244,13 @@ RegisterPciDevice (
     //
     // Get the OpRom provided by platform
     //
-    if (gPciPlatformProtocol != NULL) {
-      Status = gPciPlatformProtocol->GetPciRom (
-                                       gPciPlatformProtocol,
-                                       PciIoDevice->Handle,
-                                       &PlatformOpRomBuffer,
-                                       &PlatformOpRomSize
-                                       );
-      if (!EFI_ERROR (Status)) {
-        PciIoDevice->EmbeddedRom    = FALSE;
-        PciIoDevice->RomSize        = (UINT32) PlatformOpRomSize;
-        PciIoDevice->PciIo.RomSize  = PlatformOpRomSize;
-        PciIoDevice->PciIo.RomImage = PlatformOpRomBuffer;
-        //
-        // For OpROM read from gPciPlatformProtocol:
-        // Add the Rom Image to internal database for later PCI light enumeration
-        //
-        PciRomAddImageMapping (
-          NULL,
-          PciIoDevice->PciRootBridgeIo->SegmentNumber,
-          PciIoDevice->BusNumber,
-          PciIoDevice->DeviceNumber,
-          PciIoDevice->FunctionNumber,
-          PciIoDevice->PciIo.RomImage,
-          PciIoDevice->PciIo.RomSize
-          );
-      }
-    } else if (gPciOverrideProtocol != NULL) {
-      Status = gPciOverrideProtocol->GetPciRom (
-                                       gPciOverrideProtocol,
-                                       PciIoDevice->Handle,
-                                       &PlatformOpRomBuffer,
-                                       &PlatformOpRomSize
-                                       );
-      if (!EFI_ERROR (Status)) {
-        PciIoDevice->EmbeddedRom    = FALSE;
-        PciIoDevice->RomSize        = (UINT32) PlatformOpRomSize;
-        PciIoDevice->PciIo.RomSize  = PlatformOpRomSize;
-        PciIoDevice->PciIo.RomImage = PlatformOpRomBuffer;
-        //
-        // For OpROM read from gPciOverrideProtocol:
-        // Add the Rom Image to internal database for later PCI light enumeration
-        //
-        PciRomAddImageMapping (
+    Status = GetPlatformPciOptionRom ( Controller, PciIoDevice);
+    if (!EFI_ERROR (Status)) {
+      //
+      // For OpROM read from the PCI Platform Protocol:
+      // Add the Rom Image to internal database for later PCI light enumeration
+      //
+      PciRomAddImageMapping (
           NULL,
           PciIoDevice->PciRootBridgeIo->SegmentNumber,
           PciIoDevice->BusNumber,
@@ -294,8 +258,7 @@ RegisterPciDevice (
           PciIoDevice->FunctionNumber,
           PciIoDevice->PciIo.RomImage,
           PciIoDevice->PciIo.RomSize
-          );
-      }
+        );
     }
   }
 
@@ -597,7 +560,7 @@ DeRegisterPciDevice (
 }
 
 /**
-  Start to manage the PCI device on the specified root bridge or PCI-PCI Bridge.
+  Start the PCI root Ports or PCI-PCI Bridge only.
 
   @param Controller          The root bridge handle.
   @param RootBridge          A pointer to the PCI_IO_DEVICE.
@@ -612,7 +575,82 @@ DeRegisterPciDevice (
 
 **/
 EFI_STATUS
-StartPciDevicesOnBridge (
+StartPciRootPortsOnBridge (
+  IN EFI_HANDLE                          Controller,
+  IN PCI_IO_DEVICE                       *RootBridge
+  )
+
+{
+  PCI_IO_DEVICE             *PciIoDevice;
+  EFI_STATUS                Status;
+  LIST_ENTRY                *CurrentLink;
+  UINT64                    Supports;
+
+  PciIoDevice = NULL;
+  CurrentLink = RootBridge->ChildList.ForwardLink;
+
+  while (CurrentLink != NULL && CurrentLink != &RootBridge->ChildList) {
+
+    PciIoDevice = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
+
+    //
+    // check if the device has been assigned with required resource
+    // and registered
+    //
+    if (!PciIoDevice->Registered && !PciIoDevice->Allocated) {
+      return EFI_NOT_READY;
+    }
+
+    if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {
+      Status = StartPciRootPortsOnBridge (
+                 Controller,
+                 PciIoDevice
+                 );
+
+      PciIoDevice->PciIo.Attributes (
+                           &(PciIoDevice->PciIo),
+                           EfiPciIoAttributeOperationSupported,
+                           0,
+                           &Supports
+                         );
+      Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;
+      PciIoDevice->PciIo.Attributes (
+                           &(PciIoDevice->PciIo),
+                           EfiPciIoAttributeOperationEnable,
+                           Supports,
+                           NULL
+                         );
+
+    }
+
+    CurrentLink = CurrentLink->ForwardLink;
+  }
+
+  if (PciIoDevice == NULL) {
+    return EFI_NOT_FOUND;
+  } else {
+    return EFI_SUCCESS;
+  }
+}
+
+
+/**
+  Register to manage the PCI device on the specified root bridge or PCI-PCI Bridge.
+
+  @param Controller          The root bridge handle.
+  @param RootBridge          A pointer to the PCI_IO_DEVICE.
+  @param RemainingDevicePath A pointer to the EFI_DEVICE_PATH_PROTOCOL.
+  @param NumberOfChildren    Children number.
+  @param ChildHandleBuffer   A pointer to the child handle buffer.
+
+  @retval EFI_NOT_READY   Device is not allocated.
+  @retval EFI_UNSUPPORTED Device only support PCI-PCI bridge.
+  @retval EFI_NOT_FOUND   Can not find the specific device.
+  @retval EFI_SUCCESS     Success to start Pci devices on bridge.
+
+**/
+EFI_STATUS
+RegisterPciDevicesOnBridge (
   IN EFI_HANDLE                          Controller,
   IN PCI_IO_DEVICE                       *RootBridge,
   IN EFI_DEVICE_PATH_PROTOCOL            *RemainingDevicePath,
@@ -626,7 +664,6 @@ StartPciDevicesOnBridge (
   EFI_DEVICE_PATH_PROTOCOL  *CurrentDevicePath;
   EFI_STATUS                Status;
   LIST_ENTRY                *CurrentLink;
-  UINT64                    Supports;
 
   PciIoDevice = NULL;
   CurrentLink = RootBridge->ChildList.ForwardLink;
@@ -681,7 +718,7 @@ StartPciDevicesOnBridge (
       // If it is a PPB
       //
       if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {
-        Status = StartPciDevicesOnBridge (
+        Status = RegisterPciDevicesOnBridge (
                    Controller,
                    PciIoDevice,
                    CurrentDevicePath,
@@ -689,20 +726,6 @@ StartPciDevicesOnBridge (
                    ChildHandleBuffer
                    );
 
-        PciIoDevice->PciIo.Attributes (
-                             &(PciIoDevice->PciIo),
-                             EfiPciIoAttributeOperationSupported,
-                             0,
-                             &Supports
-                             );
-        Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;
-        PciIoDevice->PciIo.Attributes (
-                             &(PciIoDevice->PciIo),
-                             EfiPciIoAttributeOperationEnable,
-                             Supports,
-                             NULL
-                             );
-
         return Status;
       } else {
 
@@ -733,28 +756,13 @@ StartPciDevicesOnBridge (
       }
 
       if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {
-        Status = StartPciDevicesOnBridge (
+        Status = RegisterPciDevicesOnBridge (
                    Controller,
                    PciIoDevice,
                    RemainingDevicePath,
                    NumberOfChildren,
                    ChildHandleBuffer
                    );
-
-        PciIoDevice->PciIo.Attributes (
-                             &(PciIoDevice->PciIo),
-                             EfiPciIoAttributeOperationSupported,
-                             0,
-                             &Supports
-                             );
-        Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;
-        PciIoDevice->PciIo.Attributes (
-                             &(PciIoDevice->PciIo),
-                             EfiPciIoAttributeOperationEnable,
-                             Supports,
-                             NULL
-                             );
-
       }
 
       CurrentLink = CurrentLink->ForwardLink;
@@ -768,6 +776,65 @@ StartPciDevicesOnBridge (
   }
 }
 
+/**
+  Start to manage the PCI device on the specified root bridge or PCI-PCI Bridge.
+
+  @param Controller          The root bridge handle.
+  @param RootBridge          A pointer to the PCI_IO_DEVICE.
+  @param RemainingDevicePath A pointer to the EFI_DEVICE_PATH_PROTOCOL.
+  @param NumberOfChildren    Children number.
+  @param ChildHandleBuffer   A pointer to the child handle buffer.
+
+  @retval EFI_NOT_READY   Device is not allocated.
+  @retval EFI_UNSUPPORTED Device only support PCI-PCI bridge.
+  @retval EFI_NOT_FOUND   Can not find the specific device.
+  @retval EFI_SUCCESS     Success to start Pci devices on bridge.
+
+**/
+EFI_STATUS
+StartPciDevicesOnBridge (
+  IN EFI_HANDLE                          Controller,
+  IN PCI_IO_DEVICE                       *RootBridge,
+  IN EFI_DEVICE_PATH_PROTOCOL            *RemainingDevicePath,
+  IN OUT UINT8                           *NumberOfChildren,
+  IN OUT EFI_HANDLE                      *ChildHandleBuffer
+  )
+
+{
+  EFI_STATUS                Status;
+
+  //
+  // first register all the PCI devices
+  //
+  Status = RegisterPciDevicesOnBridge (
+             Controller,
+             RootBridge,
+             RemainingDevicePath,
+             NumberOfChildren,
+             ChildHandleBuffer
+             );
+
+  if (EFI_ERROR (Status) == EFI_NOT_FOUND) {
+    return Status;
+  } else {
+    if ( CheckOtherPciFeaturesPcd ()) {
+      //
+      // the late configuration of PCI features
+      //
+      Status = EnumerateOtherPciFeatures (
+                  RootBridge
+                );
+    }
+    //
+    // finally start those PCI bridge port devices only
+    //
+    return StartPciRootPortsOnBridge (
+            Controller,
+            RootBridge
+            );
+  }
+}
+
 /**
   Start to manage all the PCI devices it found previously under
   the entire host bridge.
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c
index 8db1ebf8ec..0a56668380 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c
@@ -1003,7 +1003,7 @@ PciHostBridgeAdjustAllocation (
     Status = RejectPciDevice (PciResNode->PciDev);
     if (Status == EFI_SUCCESS) {
       DEBUG ((
-        EFI_D_ERROR,
+        DEBUG_ERROR,
         "PciBus: [%02x|%02x|%02x] was rejected due to resource confliction.\n",
         PciResNode->PciDev->BusNumber, PciResNode->PciDev->DeviceNumber, PciResNode->PciDev->FunctionNumber
         ));
@@ -1746,7 +1746,7 @@ NotifyPhase (
 
   HostBridgeHandle  = NULL;
   RootBridgeHandle  = NULL;
-  if (gPciPlatformProtocol != NULL) {
+  if ( CheckPciPlatformProtocolInstall()) {
     //
     // Get Host Bridge Handle.
     //
@@ -1770,42 +1770,11 @@ NotifyPhase (
     //
     // Call PlatformPci::PlatformNotify() if the protocol is present.
     //
-    gPciPlatformProtocol->PlatformNotify (
-                            gPciPlatformProtocol,
-                            HostBridgeHandle,
-                            Phase,
-                            ChipsetEntry
-                            );
-  } else if (gPciOverrideProtocol != NULL){
-    //
-    // Get Host Bridge Handle.
-    //
-    PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle);
-
-    //
-    // Get the rootbridge Io protocol to find the host bridge handle
-    //
-    Status = gBS->HandleProtocol (
-                    RootBridgeHandle,
-                    &gEfiPciRootBridgeIoProtocolGuid,
-                    (VOID **) &PciRootBridgeIo
-                    );
-
-    if (EFI_ERROR (Status)) {
-      return EFI_NOT_FOUND;
-    }
-
-    HostBridgeHandle = PciRootBridgeIo->ParentHandle;
-
-    //
-    // Call PlatformPci::PhaseNotify() if the protocol is present.
-    //
-    gPciOverrideProtocol->PlatformNotify (
-                            gPciOverrideProtocol,
-                            HostBridgeHandle,
-                            Phase,
-                            ChipsetEntry
-                            );
+    PciPlatformNotifyPhase (
+        HostBridgeHandle,
+        Phase,
+        ChipsetEntry
+        );
   }
 
   Status = PciResAlloc->NotifyPhase (
@@ -1813,27 +1782,15 @@ NotifyPhase (
                           Phase
                           );
 
-  if (gPciPlatformProtocol != NULL) {
+  if ( CheckPciPlatformProtocolInstall()) {
     //
     // Call PlatformPci::PlatformNotify() if the protocol is present.
     //
-    gPciPlatformProtocol->PlatformNotify (
-                            gPciPlatformProtocol,
-                            HostBridgeHandle,
-                            Phase,
-                            ChipsetExit
-                            );
-
-  } else if (gPciOverrideProtocol != NULL) {
-    //
-    // Call PlatformPci::PhaseNotify() if the protocol is present.
-    //
-    gPciOverrideProtocol->PlatformNotify (
-                            gPciOverrideProtocol,
-                            HostBridgeHandle,
-                            Phase,
-                            ChipsetExit
-                            );
+    PciPlatformNotifyPhase (
+        HostBridgeHandle,
+        Phase,
+        ChipsetExit
+        );
   }
 
   return Status;
@@ -1914,31 +1871,16 @@ PreprocessController (
   RootBridgePciAddress.Bus              = Bus;
   RootBridgePciAddress.ExtendedRegister = 0;
 
-  if (gPciPlatformProtocol != NULL) {
-    //
-    // Call PlatformPci::PrepController() if the protocol is present.
-    //
-    gPciPlatformProtocol->PlatformPrepController (
-                            gPciPlatformProtocol,
-                            HostBridgeHandle,
-                            RootBridgeHandle,
-                            RootBridgePciAddress,
-                            Phase,
-                            ChipsetEntry
-                            );
-  } else if (gPciOverrideProtocol != NULL) {
-    //
-    // Call PlatformPci::PrepController() if the protocol is present.
-    //
-    gPciOverrideProtocol->PlatformPrepController (
-                            gPciOverrideProtocol,
-                            HostBridgeHandle,
-                            RootBridgeHandle,
-                            RootBridgePciAddress,
-                            Phase,
-                            ChipsetEntry
-                            );
-  }
+  //
+  // Call PlatformPci::PrepController() if the protocol is present.
+  //
+  PciPlatformPreprocessController (
+      HostBridgeHandle,
+      RootBridgeHandle,
+      RootBridgePciAddress,
+      Phase,
+      ChipsetEntry
+    );
 
   Status = PciResAlloc->PreprocessController (
                           PciResAlloc,
@@ -1947,31 +1889,16 @@ PreprocessController (
                           Phase
                           );
 
-  if (gPciPlatformProtocol != NULL) {
-    //
-    // Call PlatformPci::PrepController() if the protocol is present.
-    //
-    gPciPlatformProtocol->PlatformPrepController (
-                            gPciPlatformProtocol,
-                            HostBridgeHandle,
-                            RootBridgeHandle,
-                            RootBridgePciAddress,
-                            Phase,
-                            ChipsetExit
-                            );
-  } else if (gPciOverrideProtocol != NULL) {
-    //
-    // Call PlatformPci::PrepController() if the protocol is present.
-    //
-    gPciOverrideProtocol->PlatformPrepController (
-                            gPciOverrideProtocol,
-                            HostBridgeHandle,
-                            RootBridgeHandle,
-                            RootBridgePciAddress,
-                            Phase,
-                            ChipsetExit
-                            );
-  }
+  //
+  // Call PlatformPci::PrepController() if the protocol is present.
+  //
+  PciPlatformPreprocessController (
+      HostBridgeHandle,
+      RootBridgeHandle,
+      RootBridgePciAddress,
+      Phase,
+      ChipsetExit
+    );
 
   return EFI_SUCCESS;
 }
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
index c7eafff593..2343702154 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
@@ -230,7 +230,7 @@ PciSearchDevice (
   PciIoDevice = NULL;
 
   DEBUG ((
-    EFI_D_INFO,
+    DEBUG_INFO,
     "PciBus: Discovered %s @ [%02x|%02x|%02x]\n",
     IS_PCI_BRIDGE (Pci) ?     L"PPB" :
     IS_CARDBUS_BRIDGE (Pci) ? L"P2C" :
@@ -397,7 +397,7 @@ DumpPpbPaddingResource (
 
     if ((Type != PciBarTypeUnknown) && ((ResourceType == PciBarTypeUnknown) || (ResourceType == Type))) {
       DEBUG ((
-        EFI_D_INFO,
+        DEBUG_INFO,
         "   Padding: Type = %s; Alignment = 0x%lx;\tLength = 0x%lx\n",
         mBarTypeStr[Type], Descriptor->AddrRangeMax, Descriptor->AddrLen
         ));
@@ -424,7 +424,7 @@ DumpPciBars (
     }
 
     DEBUG ((
-      EFI_D_INFO,
+      DEBUG_INFO,
       "   BAR[%d]: Type = %s; Alignment = 0x%lx;\tLength = 0x%lx;\tOffset = 0x%02x\n",
       Index, mBarTypeStr[MIN (PciIoDevice->PciBar[Index].BarType, PciBarTypeMaxType)],
       PciIoDevice->PciBar[Index].Alignment, PciIoDevice->PciBar[Index].Length, PciIoDevice->PciBar[Index].Offset
@@ -437,13 +437,13 @@ DumpPciBars (
     }
 
     DEBUG ((
-      EFI_D_INFO,
+      DEBUG_INFO,
       " VFBAR[%d]: Type = %s; Alignment = 0x%lx;\tLength = 0x%lx;\tOffset = 0x%02x\n",
       Index, mBarTypeStr[MIN (PciIoDevice->VfPciBar[Index].BarType, PciBarTypeMaxType)],
       PciIoDevice->VfPciBar[Index].Alignment, PciIoDevice->VfPciBar[Index].Length, PciIoDevice->VfPciBar[Index].Offset
       ));
   }
-  DEBUG ((EFI_D_INFO, "\n"));
+  DEBUG ((DEBUG_INFO, "\n"));
 }
 
 /**
@@ -1903,7 +1903,7 @@ PciParseBar (
       // Fix the length to support some special 64 bit BAR
       //
       if (Value == 0) {
-        DEBUG ((EFI_D_INFO, "[PciBus]BAR probing for upper 32bit of MEM64 BAR returns 0, change to 0xFFFFFFFF.\n"));
+        DEBUG ((DEBUG_INFO, "[PciBus]BAR probing for upper 32bit of MEM64 BAR returns 0, change to 0xFFFFFFFF.\n"));
         Value = (UINT32) -1;
       } else {
         Value |= ((UINT32)(-1) << HighBitSet32 (Value));
@@ -2153,7 +2153,17 @@ CreatePciIoDevice (
              NULL
              );
   if (!EFI_ERROR (Status)) {
-    PciIoDevice->IsPciExp = TRUE;
+  PciIoDevice->IsPciExp = TRUE;
+    //
+    // read the PCI device's entire PCI Express Capability structure
+    //
+    PciIo->Pci.Read (
+                  PciIo,
+                  EfiPciIoWidthUint8,
+                  PciIoDevice->PciExpressCapabilityOffset,
+                  sizeof (PCI_CAPABILITY_PCIEXP) / sizeof (UINT8),
+                  &PciIoDevice->PciExpStruct
+                );
   }
 
   if (PcdGetBool (PcdAriSupport)) {
@@ -2206,7 +2216,7 @@ CreatePciIoDevice (
                               &Data32
                               );
           DEBUG ((
-            EFI_D_INFO,
+            DEBUG_INFO,
             " ARI: forwarding enabled for PPB[%02x:%02x:%02x]\n",
             Bridge->BusNumber,
             Bridge->DeviceNumber,
@@ -2215,7 +2225,7 @@ CreatePciIoDevice (
         }
       }
 
-      DEBUG ((EFI_D_INFO, " ARI: CapOffset = 0x%x\n", PciIoDevice->AriCapabilityOffset));
+      DEBUG ((DEBUG_INFO, " ARI: CapOffset = 0x%x\n", PciIoDevice->AriCapabilityOffset));
     }
   }
 
@@ -2325,12 +2335,12 @@ CreatePciIoDevice (
       PciIoDevice->ReservedBusNum = (UINT16)(EFI_PCI_BUS_OF_RID (LastVF) - Bus + 1);
 
       DEBUG ((
-        EFI_D_INFO,
+        DEBUG_INFO,
         " SR-IOV: SupportedPageSize = 0x%x; SystemPageSize = 0x%x; FirstVFOffset = 0x%x;\n",
         SupportedPageSize, PciIoDevice->SystemPageSize >> 12, FirstVFOffset
         ));
       DEBUG ((
-        EFI_D_INFO,
+        DEBUG_INFO,
         "         InitialVFs = 0x%x; ReservedBusNum = 0x%x; CapOffset = 0x%x\n",
         PciIoDevice->InitialVFs, PciIoDevice->ReservedBusNum, PciIoDevice->SrIovCapabilityOffset
         ));
@@ -2345,7 +2355,7 @@ CreatePciIoDevice (
                NULL
                );
     if (!EFI_ERROR (Status)) {
-      DEBUG ((EFI_D_INFO, " MR-IOV: CapOffset = 0x%x\n", PciIoDevice->MrIovCapabilityOffset));
+      DEBUG ((DEBUG_INFO, " MR-IOV: CapOffset = 0x%x\n", PciIoDevice->MrIovCapabilityOffset));
     }
   }
 
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
new file mode 100644
index 0000000000..0819da6536
--- /dev/null
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
@@ -0,0 +1,1601 @@
+/** @file
+  PCI standard feature support functions implementation for PCI Bus module..
+
+Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "PciFeatureSupport.h"
+
+/**
+  A gobal pointer to PRIMARY_ROOT_PORT_NODE buffer to track all the primary physical
+  PCI Root Ports (PCI Controllers) for a given PCI Root Bridge instance while
+  enumerating to configure the PCI features
+**/
+PRIMARY_ROOT_PORT_NODE                      *mPrimaryRootPortList;
+
+/**
+  A gobal pointer to OTHER_PCI_FEATURES_CONFIGURATION_TABLE buffer all the PCI
+  Feature configuration Table nodes to pair against each of the PRIMARY_ROOT_PORT_NODE
+  buffer nodes. Each node of these is used to align all the PCI devices originating
+  from the PCI Root Port devices of a PCI Root Bridge instance
+**/
+OTHER_PCI_FEATURES_CONFIGURATION_TABLE      *mPciFeaturesConfigurationTableInstances;
+
+/**
+  A global pointer to PCI_FEATURE_CONFIGURATION_COMPLETION_LIST, which stores all
+  the PCI Root Bridge instances that are enumerated for the other PCI features,
+  like MaxPayloadSize & MaxReadReqSize; during the the Start() interface of the
+  driver binding protocol. The records pointed by this pointer would be destroyed
+  when the DXE core invokes the Stop() interface.
+**/
+PCI_FEATURE_CONFIGURATION_COMPLETION_LIST   *mPciFeaturesConfigurationCompletionList = NULL;
+
+/**
+  Main routine to indicate platform selection of any of the other PCI features
+  to be configured by this driver
+
+  @retval TRUE    platform has selected the other PCI features to be configured
+          FALSE   platform has not selected any of the other PCI features
+**/
+BOOLEAN
+CheckOtherPciFeaturesPcd (
+  )
+{
+  return PcdGet32 ( PcdOtherPciFeatures) ? TRUE : FALSE;
+}
+
+/**
+  Main routine to indicate whether the platform has selected the Max_Payload_Size
+  PCI feature to be configured by this driver
+
+  @retval TRUE    platform has selected the Max_Payload_Size to be configured
+          FALSE   platform has not selected this feature
+**/
+BOOLEAN
+SetupMaxPayloadSize (
+  )
+{
+  return (PcdGet32 ( PcdOtherPciFeatures) & PCI_FEATURE_SUPPORT_FLAG_MPS) ? TRUE : FALSE;
+}
+
+/**
+  Main routine to indicate whether the platform has selected the Max_Read_Req_Size
+  PCI feature to be configured by this driver
+
+  @retval TRUE    platform has selected the Max_Read_Req_Size to be configured
+          FALSE   platform has not selected this feature
+**/
+BOOLEAN
+SetupMaxReadReqSize (
+  )
+{
+  return (PcdGet32 ( PcdOtherPciFeatures) & PCI_FEATURE_SUPPORT_FLAG_MRRS) ? TRUE : FALSE;
+}
+
+/**
+  Helper routine which determines whether the given PCI Root Bridge instance
+  record already exist. This routine shall help avoid duplicate record creation
+  in case of re-enumeration of PCI configuation features.
+
+  @param  RootBridge              A pointer to the PCI_IO_DEVICE for the Root Bridge
+  @param  PciFeatureConfigRecord  A pointer to a pointer for type
+                                  PCI_FEATURE_CONFIGURATION_COMPLETION_LIST
+                                  record, Use to return the specific record.
+
+  @retval TRUE                    Record already exist
+          FALSE                   Record does not exist for the given PCI Root Bridge
+**/
+BOOLEAN
+CheckPciFeatureConfigurationRecordExist (
+  IN  PCI_IO_DEVICE                             *RootBridge,
+  OUT PCI_FEATURE_CONFIGURATION_COMPLETION_LIST **PciFeatureConfigRecord
+  )
+{
+  LIST_ENTRY                                  *Link;
+  PCI_FEATURE_CONFIGURATION_COMPLETION_LIST   *Temp;
+
+  if ( mPciFeaturesConfigurationCompletionList) {
+    Link = &mPciFeaturesConfigurationCompletionList->RootBridgeLink;
+
+    do {
+      Temp = PCI_FEATURE_CONFIGURATION_COMPLETION_LIST_FROM_LINK (Link);
+      if ( Temp->RootBridgeHandle == RootBridge->Handle) {
+        *PciFeatureConfigRecord = Temp;
+        return TRUE;
+      }
+      Link = Link->ForwardLink;
+    } while (Link != &mPciFeaturesConfigurationCompletionList->RootBridgeLink);
+  }
+  //
+  // not found on the PCI feature configuration completion list
+  //
+  *PciFeatureConfigRecord = NULL;
+  return FALSE;
+}
+
+/**
+  This routine is primarily to avoid multiple configuration of PCI features
+  to the same PCI Root Bridge due to EDK2 core's ConnectController calls on
+  all the EFI handles. This routine also provide re-enumeration of the PCI
+  features on the same PCI Root Bridge based on the policy of ReEnumeratePciFeatureConfiguration
+  of the PCI_FEATURE_CONFIGURATION_COMPLETION_LIST.
+
+  @param  RootBridge              A pointer to the PCI_IO_DEVICE for the Root Bridge
+
+  @retval TRUE                    PCI Feature configuration required for the PCI
+                                  Root Bridge
+          FALSE                   PCI Feature configuration is not required to be
+                                  re-enumerated for the PCI Root Bridge
+**/
+BOOLEAN
+CheckPciFeaturesConfigurationRequired (
+  IN PCI_IO_DEVICE          *RootBridge
+  )
+{
+  LIST_ENTRY                                  *Link;
+  PCI_FEATURE_CONFIGURATION_COMPLETION_LIST   *Temp;
+
+  if ( mPciFeaturesConfigurationCompletionList) {
+    Link = &mPciFeaturesConfigurationCompletionList->RootBridgeLink;
+
+    do {
+      Temp = PCI_FEATURE_CONFIGURATION_COMPLETION_LIST_FROM_LINK (Link);
+      if ( Temp->RootBridgeHandle == RootBridge->Handle) {
+        return Temp->ReEnumeratePciFeatureConfiguration;
+      }
+      Link = Link->ForwardLink;
+    } while (Link != &mPciFeaturesConfigurationCompletionList->RootBridgeLink);
+  }
+  //
+  // not found on the PCI feature configuration completion list, return as required
+  //
+  return TRUE;
+}
+
+/**
+  This routine finds the duplicate record if exist and assigns the re-enumeration
+  requirement flag, as passed as input. It creates new record for the PCI Root
+  Bridge and appends the list after updating its re-enumeration flag.
+
+  @param  RootBridge            A pointer to PCI_IO_DEVICE of the Root Bridge
+  @param  ReEnumerationRequired A BOOLEAN for recording the re-enumeration requirement
+
+  @retval EFI_SUCCESS           new record inserted into the list or updated the
+                                existing record
+          EFI_INVALID_PARAMETER Unexpected error as CheckPciFeatureConfigurationRecordExist
+                                reports as record exist but does not return its pointer
+          EFI_OUT_OF_RESOURCES  Not able to create PCI features configuratin complete
+                                record for the RootBridge
+**/
+EFI_STATUS
+AddRootBridgeInPciFeaturesConfigCompletionList (
+  IN PCI_IO_DEVICE          *RootBridge,
+  IN BOOLEAN                ReEnumerationRequired
+  )
+{
+  PCI_FEATURE_CONFIGURATION_COMPLETION_LIST   *Temp;
+
+  if ( CheckPciFeatureConfigurationRecordExist ( RootBridge, &Temp)) {
+    //
+    // this PCI Root Bridge record already exist; it may have been re-enumerated
+    // hence just update its enumeration required flag again to exit
+    //
+    if ( Temp) {
+      Temp->ReEnumeratePciFeatureConfiguration  = ReEnumerationRequired;
+      return EFI_SUCCESS;
+    } else {
+      //
+      // PCI feature configuration complete record reported as exist and no
+      // record pointer returned
+      //
+      return EFI_INVALID_PARAMETER;
+    }
+
+  } else {
+
+    Temp = AllocateZeroPool ( sizeof ( PCI_FEATURE_CONFIGURATION_COMPLETION_LIST));
+    if ( !Temp) {
+      return EFI_OUT_OF_RESOURCES;
+    }
+    Temp->Signature                           = PCI_FEATURE_CONFIGURATION_SIGNATURE;
+    Temp->RootBridgeHandle                    = RootBridge->Handle;
+    Temp->ReEnumeratePciFeatureConfiguration  = ReEnumerationRequired;
+    if ( mPciFeaturesConfigurationCompletionList) {
+      InsertTailList ( &mPciFeaturesConfigurationCompletionList->RootBridgeLink,
+                       &Temp->RootBridgeLink);
+    } else {
+      //
+      // init the very first node of the Root Bridge
+      //
+      mPciFeaturesConfigurationCompletionList = Temp;
+      InitializeListHead ( &mPciFeaturesConfigurationCompletionList->RootBridgeLink);
+    }
+  }
+  return EFI_SUCCESS;
+}
+
+/**
+  Free up memory alloted for the primary physical PCI Root ports of the PCI Root
+  Bridge instance. Free up all the nodes of type PRIMARY_ROOT_PORT_NODE.
+**/
+VOID
+DestroyPrimaryRootPortNodes ()
+{
+  LIST_ENTRY                *Link;
+  PRIMARY_ROOT_PORT_NODE    *Temp;
+
+  if ( mPrimaryRootPortList) {
+    Link = &mPrimaryRootPortList->NeighborRootPort;
+
+    if ( IsListEmpty ( Link)) {
+      FreePool ( mPrimaryRootPortList);
+    } else {
+      do {
+        if ( Link->ForwardLink != &mPrimaryRootPortList->NeighborRootPort) {
+          Link = Link->ForwardLink;
+        }
+        Temp = PRIMARY_ROOT_PORT_NODE_FROM_LINK ( Link);
+        Link = RemoveEntryList ( Link);
+        FreePool ( Temp);
+      } while ( !IsListEmpty ( Link));
+      FreePool ( mPrimaryRootPortList);
+    }
+    mPrimaryRootPortList = NULL;
+  }
+}
+
+/**
+  Free up the memory allocated for temporarily maintaining the PCI feature
+  configuration table for all the nodes of the primary PCI Root port.
+  Free up memory alloted for OTHER_PCI_FEATURES_CONFIGURATION_TABLE.
+**/
+VOID
+ErasePciFeaturesConfigurationTable (
+  )
+{
+  if ( mPciFeaturesConfigurationTableInstances) {
+    FreePool ( mPciFeaturesConfigurationTableInstances);
+  }
+  mPciFeaturesConfigurationTableInstances = NULL;
+}
+
+/**
+  Routine meant for initializing any global variables used. It primarily cleans
+  up the internal data structure memory allocated for the previous PCI Root Bridge
+  instance. This should be the first routine to call for any virtual PCI Root
+  Bridge instance.
+**/
+VOID
+SetupPciFeaturesConfigurationDefaults ()
+{
+  //
+  // delete the primary root port list
+  //
+  if (mPrimaryRootPortList) {
+    DestroyPrimaryRootPortNodes ();
+  }
+
+  if ( mPciFeaturesConfigurationTableInstances) {
+    ErasePciFeaturesConfigurationTable ();
+  }
+}
+
+/**
+  Helper routine to determine whether the PCI device is a physical root port
+  recorded in the list.
+
+  @param  PciDevice                       A pointer to the PCI_IO_DEVICE.
+
+  @retval TRUE                            The PCI device instance is a primary
+                                          primary physical PCI Root Port
+          FALSE                           Not a primary physical PCI Root port
+**/
+BOOLEAN
+CheckRootBridgePrimaryPort (
+  IN PCI_IO_DEVICE          *PciDevice
+  )
+{
+  LIST_ENTRY                *Link;
+  PRIMARY_ROOT_PORT_NODE    *Temp;
+
+  if ( !mPrimaryRootPortList) {
+    return FALSE;
+  }
+  Link = &mPrimaryRootPortList->NeighborRootPort;
+  do {
+    Temp = PRIMARY_ROOT_PORT_NODE_FROM_LINK ( Link);
+    if ( Temp->RootBridgeHandle == PciDevice->Parent->Handle
+        && Temp->RootPortHandle == PciDevice->Handle) {
+      //
+      // the given PCI device is the primary root port of the Root Bridge controller
+      //
+      return TRUE;
+    }
+    Link = Link->ForwardLink;
+  } while ( Link != &mPrimaryRootPortList->NeighborRootPort);
+  //
+  // the given PCI device is not the primary root port of the Bridge controller
+  //
+  return FALSE;
+}
+
+/**
+  Main routine to determine the child PCI devices of a physical PCI bridge device
+  and group them under a common internal PCI features Configuration table.
+
+  @param  PciDevice                       A pointer to the PCI_IO_DEVICE.
+  @param  PciFeaturesConfigTable          A pointer to a pointer to the
+                                          OTHER_PCI_FEATURES_CONFIGURATION_TABLE.
+                                          Returns NULL in case of RCiEP or the PCI
+                                          device does match with any of the physical
+                                          Root ports, or it does not belong to any
+                                          Root port's PCU bus range (not a child)
+
+  @retval EFI_SUCCESS                     able to determine the PCI feature
+                                          configuration table. For RCiEP since
+                                          since it is not prepared.
+          EFI_NOT_FOUND                   the PCI feature configuration table does
+                                          not exist as the PCI physical Bridge device
+                                          is not found for this device's parent
+                                          Root Bridge instance
+**/
+EFI_STATUS
+GetPciFeaturesConfigurationTable (
+  IN  PCI_IO_DEVICE                           *PciDevice,
+  OUT OTHER_PCI_FEATURES_CONFIGURATION_TABLE  **PciFeaturesConfigTable
+  )
+{
+  LIST_ENTRY                *Link;
+  PRIMARY_ROOT_PORT_NODE    *Temp;
+
+  if ( !mPrimaryRootPortList) {
+    *PciFeaturesConfigTable = NULL;
+    return EFI_NOT_FOUND;
+  }
+
+  //
+  // The PCI features configuration table is not built for RCiEP, return NULL
+  //
+  if ( PciDevice->PciExpStruct.Capability.Bits.DevicePortType == \
+        PCIE_DEVICE_PORT_TYPE_ROOT_COMPLEX_INTEGRATED_ENDPOINT) {
+    *PciFeaturesConfigTable = NULL;
+    return EFI_SUCCESS;
+  }
+
+  Link = &mPrimaryRootPortList->NeighborRootPort;
+  do {
+    Temp = PRIMARY_ROOT_PORT_NODE_FROM_LINK ( Link);
+    if ( Temp->RootBridgeHandle == PciDevice->Parent->Handle
+        && Temp->RootPortHandle == PciDevice->Handle) {
+      //
+      // the given PCI device is the primary root port of the Root Bridge controller
+      //
+      *PciFeaturesConfigTable = Temp->OtherPciFeaturesConfigurationTable;
+      return EFI_SUCCESS;
+    } else {
+      //
+      // check this PCI device belongs to the primary root port of the root bridge
+      //
+      if ( PciDevice->BusNumber >= Temp->SecondaryBusStart
+          && PciDevice->BusNumber <= Temp->SecondaryBusEnd) {
+        *PciFeaturesConfigTable = Temp->OtherPciFeaturesConfigurationTable;
+        return EFI_SUCCESS;
+      }
+    }
+    Link = Link->ForwardLink;
+  } while ( Link != &mPrimaryRootPortList->NeighborRootPort);
+  //
+  // the PCI device must be RCiEP, does not belong to any primary root port
+  //
+  *PciFeaturesConfigTable = NULL;
+  return EFI_SUCCESS;
+}
+
+/**
+  The helper routine to retrieve the PCI bus numbers from the PCI Bridge or Root
+  port device. Assumes the input PCI device has the PCI Type 1 configuration header.
+
+  @param  PciDevice                       A pointer to the PCI_IO_DEVICE.
+  @param  PrimaryBusNumber                A pointer to return the PCI Priamry
+                                          Bus number.
+  @param  SecondaryBusNumber              A pointer to return the PCI Secondary
+                                          Bus number.
+  @param  SubordinateBusNumber            A pointer to return the PCI Subordinate
+                                          Bus number.
+
+  @retval EFI_SUCCESS           The data was read from the PCI device.
+  @retval EFI_UNSUPPORTED       The address range specified by Offset, Width, and Count is not
+                                valid for the PCI configuration header of the PCI device.
+  @retval EFI_INVALID_PARAMETER input parameters provided to the read operation were invalid.
+**/
+EFI_STATUS
+GetPciRootPortBusAssigned (
+  IN  PCI_IO_DEVICE                           *PciDevice,
+  OUT UINT8                                   *PrimaryBusNumber,
+  OUT UINT8                                   *SecondaryBusNumber,
+  OUT UINT8                                   *SubordinateBusNumber
+  )
+{
+  EFI_STATUS                                  Status;
+  UINT32                                      RootPortBusAssigned;
+
+  Status = PciDevice->PciIo.Pci.Read (
+                                  &PciDevice->PciIo,
+                                  EfiPciIoWidthUint32,
+                                  PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET,
+                                  1,
+                                  &RootPortBusAssigned
+                                );
+  if ( !EFI_ERROR(Status)) {
+    if ( PrimaryBusNumber) {
+      *PrimaryBusNumber = (UINT8) (0xFF & RootPortBusAssigned);
+    }
+    if ( SecondaryBusNumber) {
+      *SecondaryBusNumber = (UINT8)(0xFF & (RootPortBusAssigned >> 8));
+    }
+    if ( SubordinateBusNumber) {
+      *SubordinateBusNumber = (UINT8)(0xFF & (RootPortBusAssigned >> 16));
+    }
+  }
+  return Status;
+}
+
+/**
+  This routine determines the existance of the child PCI device for the given
+  PCI Root / Bridge Port device. Always assumes the input PCI device is the bridge
+  or PCI-PCI Bridge device. This routine should not be used with PCI endpoint device.
+
+  @param  PciDevice                       A pointer to the PCI_IO_DEVICE.
+
+  @retval TRUE                            child device exist
+          FALSE                           no child device
+**/
+BOOLEAN
+IsPciRootPortEmpty (
+  IN  PCI_IO_DEVICE                           *PciDevice
+  )
+{
+  UINT8                                       SecBus,
+                                              SubBus;
+  EFI_STATUS                                  Status;
+  LIST_ENTRY                                  *Link;
+  PCI_IO_DEVICE                               *NextPciDevice;
+
+  //
+  // check secondary & suboridinate bus numbers for its endpoint device
+  // existance
+  //
+  Status = GetPciRootPortBusAssigned ( PciDevice, NULL, &SecBus, &SubBus);
+  if ( !EFI_ERROR( Status)) {
+    Link = PciDevice->ChildList.ForwardLink;
+    if ( IsListEmpty ( Link)) {
+      //
+      // return as PCI Root port empty
+      //
+      DEBUG (( DEBUG_INFO, "RP empty,"));
+      return TRUE;
+    }
+    do {
+      NextPciDevice = PCI_IO_DEVICE_FROM_LINK ( Link);
+      DEBUG (( DEBUG_INFO, "dev@%x", NextPciDevice->BusNumber));
+
+      if ( NextPciDevice->BusNumber >= SecBus
+          && NextPciDevice->BusNumber <= SubBus) {
+
+        return FALSE;
+      }
+
+      Link = Link->ForwardLink;
+    } while ( Link != &PciDevice->ChildList);
+  } else {
+    SecBus = SubBus = 0;
+    DEBUG (( DEBUG_ERROR, "unable to retrieve root port's bus range assigned!!!"));
+  }
+
+  //
+  // return as PCI Root port empty
+  //
+  return TRUE;
+}
+
+/**
+  The main routine which process the PCI feature Max_Payload_Size as per the
+  device-specific platform policy, as well as in complaince with the PCI Base
+  specification Revision 4, that aligns the value for the entire PCI heirarchy
+  starting from its physical PCI Root port / Bridge device.
+
+  @param PciDevice                      A pointer to the PCI_IO_DEVICE.
+  @param PciConfigPhase                 for the PCI feature configuration phases:
+                                        PciFeatureGetDevicePolicy & PciFeatureSetupPhase
+  @param PciFeaturesConfigurationTable  pointer to OTHER_PCI_FEATURES_CONFIGURATION_TABLE
+
+  @retval EFI_SUCCESS                   processing of PCI feature Max_Payload_Size
+                                        is successful.
+**/
+EFI_STATUS
+ProcessMaxPayloadSize (
+  IN  PCI_IO_DEVICE                           *PciDevice,
+  IN  PCI_FEATURE_CONFIGURATION_PHASE         PciConfigPhase,
+  IN  OTHER_PCI_FEATURES_CONFIGURATION_TABLE  *PciFeaturesConfigurationTable
+  )
+{
+  PCI_REG_PCIE_DEVICE_CAPABILITY          PciDeviceCap;
+  UINT8                                   MpsValue;
+
+
+  PciDeviceCap.Uint32 = PciDevice->PciExpStruct.DeviceCapability.Uint32;
+
+  if ( PciConfigPhase == PciFeatureGetDevicePolicy) {
+    if ( SetupMpsAsPerDeviceCapability ( PciDevice->SetupMPS))
+    {
+      MpsValue = (UINT8)PciDeviceCap.Bits.MaxPayloadSize;
+      //
+      // no change to PCI Root ports without any endpoint device
+      //
+      if ( IS_PCI_BRIDGE ( &PciDevice->Pci) && PciDeviceCap.Bits.MaxPayloadSize) {
+        if ( IsPciRootPortEmpty ( PciDevice)) {
+          MpsValue = PCIE_MAX_PAYLOAD_SIZE_128B;
+          DEBUG (( DEBUG_INFO, "(reset RP MPS to min.)"));
+        }
+      }
+    } else {
+      MpsValue = TranslateMpsSetupValueToPci ( PciDevice->SetupMPS);
+    }
+    //
+    // discard device policy override request if greater than PCI device capability
+    //
+    PciDevice->SetupMPS = MIN( (UINT8)PciDeviceCap.Bits.MaxPayloadSize, MpsValue);
+  }
+
+  //
+  // align the MPS of the tree to the HCF with this device
+  //
+  if ( PciFeaturesConfigurationTable) {
+    MpsValue = PciFeaturesConfigurationTable->Max_Payload_Size;
+
+    MpsValue = MIN ( PciDevice->SetupMPS, MpsValue);
+    PciDevice->SetupMPS = MIN ( PciDevice->SetupMPS, MpsValue);
+
+    if ( MpsValue != PciFeaturesConfigurationTable->Max_Payload_Size) {
+      DEBUG (( DEBUG_INFO, "reset MPS of the tree to %d,", MpsValue));
+      PciFeaturesConfigurationTable->Max_Payload_Size = MpsValue;
+    }
+  }
+
+  DEBUG (( DEBUG_INFO,
+      "Max_Payload_Size: %d [DevCap:%d],",
+      PciDevice->SetupMPS, PciDeviceCap.Bits.MaxPayloadSize
+  ));
+  return EFI_SUCCESS;
+}
+
+/**
+  The main routine which process the PCI feature Max_Read_Req_Size as per the
+  device-specific platform policy, as well as in complaince with the PCI Base
+  specification Revision 4, that aligns the value for the entire PCI heirarchy
+  starting from its physical PCI Root port / Bridge device.
+
+  @param PciDevice                      A pointer to the PCI_IO_DEVICE.
+  @param PciConfigPhase                 for the PCI feature configuration phases:
+                                        PciFeatureGetDevicePolicy & PciFeatureSetupPhase
+  @param PciFeaturesConfigurationTable  pointer to OTHER_PCI_FEATURES_CONFIGURATION_TABLE
+
+  @retval EFI_SUCCESS                   processing of PCI feature Max_Read_Req_Size
+                                        is successful.
+**/
+EFI_STATUS
+ProcessMaxReadReqSize (
+  IN  PCI_IO_DEVICE                           *PciDevice,
+  IN  PCI_FEATURE_CONFIGURATION_PHASE         PciConfigPhase,
+  IN  OTHER_PCI_FEATURES_CONFIGURATION_TABLE  *PciFeaturesConfigurationTable
+  )
+{
+  PCI_REG_PCIE_DEVICE_CAPABILITY  PciDeviceCap;
+  UINT8                           MrrsValue;
+
+  PciDeviceCap.Uint32 = PciDevice->PciExpStruct.DeviceCapability.Uint32;
+
+  if ( PciConfigPhase == PciFeatureGetDevicePolicy) {
+    if ( SetupMrrsAsPerDeviceCapability ( PciDevice->SetupMRRS))
+    {
+      //
+      // The maximum read request size is not the data packet size of the TLP,
+      // but the memory read request size, and set to the function as a requestor
+      // to not exceed this limit.
+      // However, for the PCI device capable of isochronous traffic; this memory read
+      // request size should not extend beyond the Max_Payload_Size. Thus, in case if
+      // device policy return by platform indicates to set as per device capability
+      // than set as per Max_Payload_Size configuration value
+      //
+      if ( SetupMaxPayloadSize()) {
+        MrrsValue = PciDevice->SetupMPS;
+      } else {
+        //
+        // in case this driver is not required to configure the Max_Payload_Size
+        // than consider programming HCF of the device capability's Max_Payload_Size
+        // in this PCI hierarchy; thus making this an implementation specific feature
+        // which the platform should avoid. For better results, the platform should
+        // make both the Max_Payload_Size & Max_Read_Request_Size to be configured
+        // by this driver
+        //
+        MrrsValue = (UINT8)PciDeviceCap.Bits.MaxPayloadSize;
+      }
+    } else {
+      //
+      // override as per platform based device policy
+      //
+      MrrsValue = TranslateMrrsSetupValueToPci ( PciDevice->SetupMRRS);
+      //
+      // align this device's Max_Read_Request_Size value to the entire PCI tree
+      //
+      if ( PciFeaturesConfigurationTable) {
+        if ( !PciFeaturesConfigurationTable->Lock_Max_Read_Request_Size) {
+          PciFeaturesConfigurationTable->Lock_Max_Read_Request_Size = TRUE;
+          PciFeaturesConfigurationTable->Max_Read_Request_Size = MrrsValue;
+        } else {
+          //
+          // in case of another user enforced value of MRRS within the same tree,
+          // pick the smallest between the locked value and this value; to set
+          // across entire PCI tree nodes
+          //
+          MrrsValue = MIN (
+                        MrrsValue,
+                        PciFeaturesConfigurationTable->Max_Read_Request_Size
+                        );
+          PciFeaturesConfigurationTable->Max_Read_Request_Size = MrrsValue;
+        }
+      }
+    }
+    //
+    // align this device's Max_Read_Request_Size to derived configuration value
+    //
+    PciDevice->SetupMRRS = MrrsValue;
+
+  }
+
+  //
+  // align the Max_Read_Request_Size of the PCI tree based on 3 conditions:
+  // first, if user defines MRRS for any one PCI device in the tree than align
+  // all the devices in the PCI tree.
+  // second, if user override is not define for this PCI tree than setup the MRRS
+  // based on MPS value of the tree to meet the criteria for the isochronous
+  // traffic.
+  // third, if no user override, or platform firmware policy has not selected
+  // this PCI bus driver to configure the MPS; than configure the MRRS to a
+  // highest common value of PCI device capability for the MPS found among all
+  // the PCI devices in this tree
+  //
+  if ( PciFeaturesConfigurationTable) {
+    if ( PciFeaturesConfigurationTable->Lock_Max_Read_Request_Size) {
+      PciDevice->SetupMRRS = PciFeaturesConfigurationTable->Max_Read_Request_Size;
+    } else {
+      if ( SetupMaxPayloadSize()) {
+        PciDevice->SetupMRRS = PciDevice->SetupMPS;
+      } else {
+        PciDevice->SetupMRRS = MIN (
+                                PciDevice->SetupMRRS,
+                                PciFeaturesConfigurationTable->Max_Read_Request_Size
+                                );
+      }
+      PciFeaturesConfigurationTable->Max_Read_Request_Size = PciDevice->SetupMRRS;
+    }
+  }
+  DEBUG (( DEBUG_INFO, "Max_Read_Request_Size: %d\n", PciDevice->SetupMRRS));
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Overrides the PCI Device Control register MaxPayloadSize register field; if
+  the hardware value is different than the intended value.
+
+  @param  PciDevice             A pointer to the PCI_IO_DEVICE instance.
+
+  @retval EFI_SUCCESS           The data was read from or written to the PCI device.
+  @retval EFI_UNSUPPORTED       The address range specified by Offset, Width, and Count is not
+                                valid for the PCI configuration header of the PCI controller.
+  @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid.
+
+**/
+EFI_STATUS
+OverrideMaxPayloadSize (
+  IN PCI_IO_DEVICE          *PciDevice
+  )
+{
+  PCI_REG_PCIE_DEVICE_CONTROL PcieDev;
+  UINT32                      Offset;
+  EFI_STATUS                  Status;
+
+  PcieDev.Uint16 = 0;
+  Offset = PciDevice->PciExpressCapabilityOffset +
+               OFFSET_OF (PCI_CAPABILITY_PCIEXP, DeviceControl);
+  Status = PciDevice->PciIo.Pci.Read (
+                                  &PciDevice->PciIo,
+                                  EfiPciIoWidthUint16,
+                                  Offset,
+                                  1,
+                                  &PcieDev.Uint16
+                                );
+  if ( EFI_ERROR(Status)){
+    DEBUG (( DEBUG_ERROR, "Unexpected DeviceControl register (0x%x) read error!",
+        Offset
+    ));
+    return Status;
+  }
+  if ( PcieDev.Bits.MaxPayloadSize != PciDevice->SetupMPS) {
+    PcieDev.Bits.MaxPayloadSize = PciDevice->SetupMPS;
+    DEBUG (( DEBUG_INFO, "Max_Payload_Size=%d,", PciDevice->SetupMPS));
+
+    Status = PciDevice->PciIo.Pci.Write (
+                                    &PciDevice->PciIo,
+                                    EfiPciIoWidthUint16,
+                                    Offset,
+                                    1,
+                                    &PcieDev.Uint16
+                                  );
+    if ( !EFI_ERROR(Status)) {
+      PciDevice->PciExpStruct.DeviceControl.Uint16 = PcieDev.Uint16;
+    } else {
+      DEBUG (( DEBUG_ERROR, "Unexpected DeviceControl register (0x%x) write error!",
+          Offset
+      ));
+    }
+  } else {
+    DEBUG (( DEBUG_INFO, "No write of Max_Payload_Size=%d,", PciDevice->SetupMPS));
+  }
+
+  return Status;
+}
+
+/**
+  Overrides the PCI Device Control register MaxPayloadSize register field; if
+  the hardware value is different than the intended value.
+
+  @param  PciDevice             A pointer to the PCI_IO_DEVICE instance.
+
+  @retval EFI_SUCCESS           The data was read from or written to the PCI controller.
+  @retval EFI_UNSUPPORTED       The address range specified by Offset, Width, and Count is not
+                                valid for the PCI configuration header of the PCI controller.
+  @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid.
+
+**/
+EFI_STATUS
+OverrideMaxReadReqSize (
+  IN PCI_IO_DEVICE          *PciDevice
+  )
+{
+  PCI_REG_PCIE_DEVICE_CONTROL PcieDev;
+  UINT32                      Offset;
+  EFI_STATUS                  Status;
+
+  PcieDev.Uint16 = 0;
+  Offset = PciDevice->PciExpressCapabilityOffset +
+               OFFSET_OF (PCI_CAPABILITY_PCIEXP, DeviceControl);
+  Status = PciDevice->PciIo.Pci.Read (
+                                  &PciDevice->PciIo,
+                                  EfiPciIoWidthUint16,
+                                  Offset,
+                                  1,
+                                  &PcieDev.Uint16
+                                );
+  if ( EFI_ERROR(Status)){
+    DEBUG (( DEBUG_ERROR, "Unexpected DeviceControl register (0x%x) read error!",
+        Offset
+    ));
+    return Status;
+  }
+  if ( PcieDev.Bits.MaxReadRequestSize != PciDevice->SetupMRRS) {
+    PcieDev.Bits.MaxReadRequestSize = PciDevice->SetupMRRS;
+    DEBUG (( DEBUG_INFO, "Max_Read_Request_Size: %d\n", PciDevice->SetupMRRS));
+
+    Status = PciDevice->PciIo.Pci.Write (
+                                    &PciDevice->PciIo,
+                                    EfiPciIoWidthUint16,
+                                    Offset,
+                                    1,
+                                    &PcieDev.Uint16
+                                  );
+    if ( !EFI_ERROR(Status)) {
+      PciDevice->PciExpStruct.DeviceControl.Uint16 = PcieDev.Uint16;
+    } else {
+      DEBUG (( DEBUG_ERROR, "Unexpected DeviceControl register (0x%x) write error!",
+          Offset
+      ));
+    }
+  } else {
+    DEBUG (( DEBUG_INFO, "No write of Max_Read_Request_Size=%d\n", PciDevice->SetupMRRS));
+  }
+
+  return Status;
+}
+
+/**
+  helper routine to dump the PCIe Device Port Type
+**/
+VOID
+DumpDevicePortType (
+  IN  UINT8   DevicePortType
+  )
+{
+  switch ( DevicePortType){
+    case PCIE_DEVICE_PORT_TYPE_PCIE_ENDPOINT:
+      DEBUG (( DEBUG_INFO, "PCIe endpoint found\n"));
+      break;
+    case PCIE_DEVICE_PORT_TYPE_LEGACY_PCIE_ENDPOINT:
+      DEBUG (( DEBUG_INFO, "legacy PCI endpoint found\n"));
+      break;
+    case PCIE_DEVICE_PORT_TYPE_ROOT_PORT:
+      DEBUG (( DEBUG_INFO, "PCIe Root Port found\n"));
+      break;
+    case PCIE_DEVICE_PORT_TYPE_UPSTREAM_PORT:
+      DEBUG (( DEBUG_INFO, "PCI switch upstream port found\n"));
+      break;
+    case PCIE_DEVICE_PORT_TYPE_DOWNSTREAM_PORT:
+      DEBUG (( DEBUG_INFO, "PCI switch downstream port found\n"));
+      break;
+    case PCIE_DEVICE_PORT_TYPE_PCIE_TO_PCI_BRIDGE:
+      DEBUG (( DEBUG_INFO, "PCIe-PCI bridge found\n"));
+      break;
+    case PCIE_DEVICE_PORT_TYPE_PCI_TO_PCIE_BRIDGE:
+      DEBUG (( DEBUG_INFO, "PCI-PCIe bridge found\n"));
+      break;
+    case PCIE_DEVICE_PORT_TYPE_ROOT_COMPLEX_INTEGRATED_ENDPOINT:
+      DEBUG (( DEBUG_INFO, "RCiEP found\n"));
+      break;
+    case PCIE_DEVICE_PORT_TYPE_ROOT_COMPLEX_EVENT_COLLECTOR:
+      DEBUG (( DEBUG_INFO, "RC Event Collector found\n"));
+      break;
+  }
+}
+
+/**
+   Process each PCI device as per the pltaform and device-specific policy.
+
+  @param RootBridge             A pointer to the PCI_IO_DEVICE.
+
+  @retval EFI_SUCCESS           processing each PCI feature as per policy defined
+                                was successful.
+ **/
+EFI_STATUS
+SetupDevicePciFeatures (
+  IN  PCI_IO_DEVICE                   *PciDevice,
+  IN  PCI_FEATURE_CONFIGURATION_PHASE PciConfigPhase
+  )
+{
+  EFI_STATUS                              Status;
+  PCI_REG_PCIE_CAPABILITY                 PcieCap;
+  OTHER_PCI_FEATURES_CONFIGURATION_TABLE  *OtherPciFeaturesConfigTable;
+
+  PcieCap.Uint16 = PciDevice->PciExpStruct.Capability.Uint16;
+  DumpDevicePortType ( (UINT8)PcieCap.Bits.DevicePortType);
+
+  OtherPciFeaturesConfigTable = NULL;
+  Status = GetPciFeaturesConfigurationTable ( PciDevice, &OtherPciFeaturesConfigTable);
+  if ( EFI_ERROR( Status)) {
+    DEBUG ((
+        EFI_D_WARN, "No primary root port found in these root bridge nodes!\n"
+    ));
+  } else if ( !OtherPciFeaturesConfigTable) {
+    DEBUG ((
+        DEBUG_INFO, "No PCI features config. table for this device!\n"
+    ));
+  } else {
+    DEBUG ((
+        DEBUG_INFO, "using PCI features config. table ID: %d\n",
+        OtherPciFeaturesConfigTable->ID
+    ));
+  }
+
+  if ( PciConfigPhase == PciFeatureGetDevicePolicy) {
+    Status = GetPciDevicePlatformPolicy ( PciDevice);
+    if ( EFI_ERROR(Status)) {
+      DEBUG ((
+          DEBUG_ERROR, "Error in obtaining PCI device policy!!!\n"
+      ));
+    }
+  }
+
+  if ( SetupMaxPayloadSize ()) {
+    Status = ProcessMaxPayloadSize (
+              PciDevice,
+              PciConfigPhase,
+              OtherPciFeaturesConfigTable
+              );
+  }
+  //
+  // implementation specific rule:- the MRRS of any PCI device should be processed
+  // only after the MPS is processed for that device
+  //
+  if ( SetupMaxReadReqSize ()) {
+    Status = ProcessMaxReadReqSize (
+              PciDevice,
+              PciConfigPhase,
+              OtherPciFeaturesConfigTable
+              );
+  }
+  return Status;
+}
+
+/**
+  Traverse all the nodes from the root bridge or PCI-PCI bridge instance, to
+  configure the PCI features as per the device-specific platform policy, and
+  as per the device capability, as applicable.
+
+  @param RootBridge             A pointer to the PCI_IO_DEVICE.
+
+  @retval EFI_SUCCESS           Traversing all the nodes of the root bridge
+                                instances were successfull.
+**/
+EFI_STATUS
+SetupPciFeatures (
+  IN  PCI_IO_DEVICE                   *RootBridge,
+  IN  PCI_FEATURE_CONFIGURATION_PHASE PciConfigPhase
+  )
+{
+  EFI_STATUS           Status;
+  LIST_ENTRY           *Link;
+  PCI_IO_DEVICE        *Device;
+
+  for ( Link = RootBridge->ChildList.ForwardLink
+      ; Link != &RootBridge->ChildList
+      ; Link = Link->ForwardLink
+  ) {
+    Device = PCI_IO_DEVICE_FROM_LINK (Link);
+    if (IS_PCI_BRIDGE (&Device->Pci)) {
+      DEBUG ((
+          DEBUG_INFO, "::Bridge [%02x|%02x|%02x] -",
+          Device->BusNumber, Device->DeviceNumber, Device->FunctionNumber
+      ));
+      if (Device->IsPciExp) {
+        Status = SetupDevicePciFeatures ( Device, PciConfigPhase);
+      } else {
+        DEBUG (( DEBUG_INFO, "Not a PCIe capable device!\n"));
+        //
+        // PCI Bridge which does not have PCI Express Capability structure
+        // cannot process this kind of PCI Bridge device
+        //
+
+      }
+
+      SetupPciFeatures ( Device, PciConfigPhase);
+    } else {
+      DEBUG ((
+          DEBUG_INFO, "::Device [%02x|%02x|%02x] -",
+          Device->BusNumber, Device->DeviceNumber, Device->FunctionNumber
+      ));
+      if (Device->IsPciExp) {
+
+        Status = SetupDevicePciFeatures ( Device, PciConfigPhase);
+      } else {
+        DEBUG (( DEBUG_INFO, "Not a PCIe capable device!\n"));
+        //
+        // PCI Device which does not have PCI Express Capability structure
+        // cannot process this kind of PCI device
+        //
+      }
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Program the PCI device, to override the PCI features as per the policy,
+  resolved from previous traverse.
+
+  @param RootBridge             A pointer to the PCI_IO_DEVICE.
+
+  @retval EFI_SUCCESS           The other PCI features configuration during enumeration
+                                of all the nodes of the PCI root bridge instance were
+                                programmed in PCI-compliance pattern along with the
+                                device-specific policy, as applicable.
+  @retval EFI_UNSUPPORTED       One of the override operation maong the nodes of
+                                the PCI hierarchy resulted in a incompatible address
+                                range.
+  @retval EFI_INVALID_PARAMETER The override operation is performed with invalid input
+                                parameters.
+**/
+EFI_STATUS
+ProgramDevicePciFeatures (
+  IN PCI_IO_DEVICE          *PciDevice
+  )
+{
+  EFI_STATUS           Status;
+
+  if ( SetupMaxPayloadSize ()) {
+    Status = OverrideMaxPayloadSize (PciDevice);
+  }
+  if ( SetupMaxReadReqSize ()) {
+    Status = OverrideMaxReadReqSize (PciDevice);
+  }
+  return Status;
+}
+
+/**
+  Program all the nodes of the specified root bridge or PCI-PCI Bridge, to
+  override the PCI features.
+
+  @param RootBridge             A pointer to the PCI_IO_DEVICE.
+
+  @retval EFI_SUCCESS           The other PCI features configuration during enumeration
+                                of all the nodes of the PCI root bridge instance were
+                                programmed in PCI-compliance pattern along with the
+                                device-specific policy, as applicable.
+  @retval EFI_UNSUPPORTED       One of the override operation maong the nodes of
+                                the PCI hierarchy resulted in a incompatible address
+                                range.
+  @retval EFI_INVALID_PARAMETER The override operation is performed with invalid input
+                                parameters.
+**/
+EFI_STATUS
+ProgramPciFeatures (
+  IN PCI_IO_DEVICE          *RootBridge
+  )
+{
+  EFI_STATUS           Status;
+  LIST_ENTRY           *Link;
+  PCI_IO_DEVICE        *Device;
+
+  for ( Link = RootBridge->ChildList.ForwardLink
+      ; Link != &RootBridge->ChildList
+      ; Link = Link->ForwardLink
+  ) {
+    Device = PCI_IO_DEVICE_FROM_LINK (Link);
+    if (IS_PCI_BRIDGE (&Device->Pci)) {
+      DEBUG ((
+          DEBUG_INFO, "::Bridge [%02x|%02x|%02x] -",
+          Device->BusNumber, Device->DeviceNumber, Device->FunctionNumber
+      ));
+      if (Device->IsPciExp) {
+        DEBUG (( DEBUG_INFO, "ready to override!\n"));
+
+        Status = ProgramDevicePciFeatures ( Device);
+      } else {
+        DEBUG (( DEBUG_INFO, "skipped!\n"));
+        //
+        // PCI Bridge which does not have PCI Express Capability structure
+        // cannot process this kind of PCI Bridge device
+        //
+
+      }
+
+      Status = ProgramPciFeatures ( Device);
+    } else {
+      DEBUG ((
+          DEBUG_INFO, "::Device [%02x|%02x|%02x] -",
+          Device->BusNumber, Device->DeviceNumber, Device->FunctionNumber
+      ));
+      if (Device->IsPciExp) {
+        DEBUG (( DEBUG_INFO, "ready to override!\n"));
+
+        Status = ProgramDevicePciFeatures ( Device);
+      } else {
+        DEBUG (( DEBUG_INFO, "skipped!\n"));
+        //
+        // PCI Device which does not have PCI Express Capability structure
+        // cannot process this kind of PCI device
+        //
+      }
+    }
+  }
+
+  return Status;
+}
+
+/**
+  Create a node of type PRIMARY_ROOT_PORT_NODE for the given PCI device, and
+  assigns EFI handles of its Root Bridge and its own, along with its PCI Bus
+  range for the secondary and subordinate bus range.
+
+  @param  RootBridge          A pointer to the PCI_IO_DEVICE for its PCI Root Bridge
+  @param  Device              A pointer to the PCI_IO_DEVICE for the PCI controller
+  @param  RootPortSecBus      PCI controller's Secondary Bus number
+  @param  RootPortSubBus      PCI controller's Subordinate Bus number
+  @param  PrimaryRootPortNode A pointer to the PRIMARY_ROOT_PORT_NODE to return
+                              the newly created node for the PCI controller. In
+                              case of error nothing is return in this.
+
+  @retval EFI_SUCCESS           new node of PRIMARY_ROOT_PORT_NODE is returned for
+                                the PCI controller
+          EFI_OUT_OF_RESOURCES  unable to create the node for the PCI controller
+          EFI_INVALID_PARAMETER unable to store the node as the input buffer is
+                                not empty (*PrimaryRootPortNode)
+**/
+EFI_STATUS
+CreatePrimaryPciRootPortNode (
+  IN  PCI_IO_DEVICE           *RootBridge,
+  IN  PCI_IO_DEVICE           *Device,
+  IN  UINT8                   RootPortSecBus,
+  IN  UINT8                   RootPortSubBus,
+  OUT PRIMARY_ROOT_PORT_NODE  **PrimaryRootPortNode
+  )
+{
+  PRIMARY_ROOT_PORT_NODE      *RootPortNode = NULL;
+
+  if ( !*PrimaryRootPortNode) {
+    RootPortNode                    = AllocateZeroPool ( sizeof (PRIMARY_ROOT_PORT_NODE));
+    if ( RootPortNode == NULL) {
+      return EFI_OUT_OF_RESOURCES;
+    }
+    RootPortNode->Signature         = PCI_ROOT_PORT_SIGNATURE;
+    RootPortNode->RootBridgeHandle  = RootBridge->Handle;
+    RootPortNode->RootPortHandle    = Device->Handle;
+    RootPortNode->SecondaryBusStart = RootPortSecBus;
+    RootPortNode->SecondaryBusEnd   = RootPortSubBus;
+    InitializeListHead ( &RootPortNode->NeighborRootPort);
+    *PrimaryRootPortNode = RootPortNode;
+    return EFI_SUCCESS;
+  } else {
+    return EFI_INVALID_PARAMETER;
+  }
+}
+
+/**
+  Checks to report whether the input PCI controller's secondary / subordinate
+  bus numbers are within the recorded list of other PCI controllers (root ports).
+
+  @param  RootPortNode      A pointer to the first node of PRIMARY_ROOT_PORT_NODE
+  @param  RootPortSecBus    PCI secondary bus number of the PCI controller found
+  @param  RootPortSubBus    PCI subordinate bus number of the PCI Root Port found
+
+  @retval TRUE              A child PCI Root port found
+          FALSE             A new PCI controller found
+**/
+BOOLEAN
+CheckChildRootPort (
+  IN      PRIMARY_ROOT_PORT_NODE  *RootPortNode,
+  IN      UINT8                   RootPortSecBus,
+  IN      UINT8                   RootPortSubBus
+)
+{
+  LIST_ENTRY              *Link;
+  PRIMARY_ROOT_PORT_NODE  *Temp;
+
+  if ( !RootPortNode) {
+    return FALSE;
+  }
+  Link = &RootPortNode->NeighborRootPort;
+  do {
+    Temp = PRIMARY_ROOT_PORT_NODE_FROM_LINK ( Link);
+    if ( RootPortSecBus >= Temp->SecondaryBusStart
+        && RootPortSubBus <= Temp->SecondaryBusEnd) {
+      //
+      // given root port's secondary & subordinate within its primary ports
+      // hence return as child port
+      //
+      return TRUE;
+    }
+    Link = Link->ForwardLink;
+  } while (Link != &RootPortNode->NeighborRootPort);
+  //
+  // the given root port's secondary / subordinate bus numbers do not belong to
+  // any existing primary root port's bus range hence consider another primary
+  // root port of the root bridge controller
+  //
+  return FALSE;
+}
+
+/**
+  Create the vector of PCI Feature configuration table as per the number of
+  the PCI Root Ports given, assigns default value to the PCI features supported
+  and assign its address to the global variable "mPciFeaturesConfigurationTableInstances".
+
+  @param  NumberOfRootPorts   An input arguement of UINTN to indicate number of
+                              primary PCI physical Root Bridge devices found
+
+  @retval EFI_OUT_OF_RESOURCES  unable to allocate buffer to store PCI feature
+                                configuration table for all the physical PCI root
+                                ports given
+          EFI_SUCCESS           PCI Feature COnfiguration table created for all
+                                the PCI Rooot ports reported
+ */
+EFI_STATUS
+CreatePciFeaturesConfigurationTableInstances (
+  IN  UINTN NumberOfRootPorts
+  )
+{
+  OTHER_PCI_FEATURES_CONFIGURATION_TABLE   *PciRootBridgePortFeatures = NULL;
+  UINTN                                     Instances;
+
+  PciRootBridgePortFeatures = AllocateZeroPool (
+                                sizeof ( OTHER_PCI_FEATURES_CONFIGURATION_TABLE) * NumberOfRootPorts
+                                );
+  if ( !PciRootBridgePortFeatures) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  for ( Instances = 0; Instances < NumberOfRootPorts; Instances++) {
+    PciRootBridgePortFeatures [Instances].ID                    = Instances + 1;
+    PciRootBridgePortFeatures [Instances].Max_Payload_Size      = PCIE_MAX_PAYLOAD_SIZE_4096B;
+    PciRootBridgePortFeatures [Instances].Max_Read_Request_Size = PCIE_MAX_READ_REQ_SIZE_4096B;
+    PciRootBridgePortFeatures [Instances].Lock_Max_Read_Request_Size = FALSE;
+  }
+  mPciFeaturesConfigurationTableInstances = PciRootBridgePortFeatures;
+  return EFI_SUCCESS;
+}
+
+/**
+  This routine pairs the each PCI Root Port node with one of the PCI Feature
+  Configuration Table node. Each physical PCI Root Port has its own PCI feature
+  configuration table which will used for aligning all its downstream components.
+
+  @param  NumberOfRootPorts     inputs the number of physical PCI root ports
+                                found on the Root bridge instance
+
+  @retval EFI_INVALID_PARAMETER if the primary PCI root ports list is vacant when
+                                there is one or more PCI Root port indicated as per
+                                input parameter
+          EFI_UNSUPPORTED       The PCI Root Port nodes not paired equally with
+                                the PCI Configuration Table nodes
+          EFI_SUCCESS           each PCI feature configuration node is paired equally
+                                with each PCI Root port in the list
+**/
+EFI_STATUS
+AssignPciFeaturesConfigurationTable (
+  IN  UINTN NumberOfRootPorts
+  )
+{
+  UINTN                       Instances;
+  LIST_ENTRY                  *Link;
+  PRIMARY_ROOT_PORT_NODE      *Temp;
+
+  if ( !mPrimaryRootPortList
+      && NumberOfRootPorts) {
+    DEBUG ((
+        DEBUG_ERROR,
+        "Critical error! no internal table setup for %d PCI Root ports \n",
+        NumberOfRootPorts
+    ));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if ( NumberOfRootPorts) {
+    Link = &mPrimaryRootPortList->NeighborRootPort;
+    for ( Instances = 0
+        ; (Instances < NumberOfRootPorts)
+        ; Instances++
+    ) {
+      Temp = PRIMARY_ROOT_PORT_NODE_FROM_LINK ( Link);
+      Temp->OtherPciFeaturesConfigurationTable = &mPciFeaturesConfigurationTableInstances [Instances];
+      DEBUG ((
+          DEBUG_INFO,
+          "Assigned to %dth primary root port\n",
+          Instances
+      ));
+
+      Link = Link->ForwardLink;
+    }
+    if ( Link != &mPrimaryRootPortList->NeighborRootPort) {
+      DEBUG ((
+          DEBUG_ERROR,
+          "Error!! PCI Root Port list is not properly matched with Config., Table list \n"
+      ));
+      return EFI_UNSUPPORTED;
+    }
+  }
+  return  EFI_SUCCESS;
+}
+
+/**
+  Prepare each PCI Controller (Root Port) with its own PCI Feature configuration
+  table node that can be used for tracking to align all PCI nodes in its hierarchy.
+
+  @param  PrimaryRootPorts      A pointer to PRIMARY_ROOT_PORT_NODE
+  @param  NumberOfRootPorts     Total number of pysical primary PCI Root ports
+
+  @retval EFI_OUT_OF_RESOURCES  unable to allocate buffer to store PCI feature
+                                configuration table for all the physical PCI root
+                                ports given
+          EFI_INVALID_PARAMETER if the primary PCI root ports list is vacant when
+                                there is one or more PCI Root port indicated as per
+                                input parameter
+          EFI_UNSUPPORTED       The PCI Root Port nodes not paired equally with
+                                the PCI Configuration Table nodes
+          EFI_SUCCESS           each PCI feature configuration node is paired equally
+                                with each PCI Root port in the list
+**/
+EFI_STATUS
+PreparePciControllerConfigurationTable (
+  IN  PRIMARY_ROOT_PORT_NODE    *PrimaryRootPorts,
+  IN  UINTN                     NumberOfRootPorts
+  )
+{
+  EFI_STATUS                    Status;
+
+  mPrimaryRootPortList = PrimaryRootPorts;
+  DEBUG ((
+      DEBUG_INFO, "Number of primary Root Ports found on this bridge = %d\n",
+      NumberOfRootPorts
+  ));
+
+  Status = CreatePciFeaturesConfigurationTableInstances ( NumberOfRootPorts);
+  if ( EFI_ERROR(Status)) {
+    DEBUG ((
+        DEBUG_ERROR, "Unexpected memory node creation error for PCI features!\n"
+    ));
+  } else {
+    //
+    // align the primary root port nodes list with the PCI Feature configuration
+    // table. Note that the PCI Feature configuration table is not maintain for
+    // the RCiEP devices
+    //
+    Status = AssignPciFeaturesConfigurationTable ( NumberOfRootPorts);
+  }
+  return Status;
+}
+
+/**
+  Scan all the nodes of the RootBridge to identify and create a separate list
+  of all primary physical PCI root ports and link each with its own instance of
+  the PCI Feature Configuration Table.
+
+  @param  RootBridge    A pointer to the PCI_IO_DEVICE of the PCI Root Bridge
+
+  @retval EFI_OUT_OF_RESOURCES  unable to allocate buffer to store PCI feature
+                                configuration table for all the physical PCI root
+                                ports given
+          EFI_NOT_FOUND         No PCI Bridge device found
+          EFI_SUCCESS           PCI Feature COnfiguration table created for all
+                                the PCI Rooot ports found
+          EFI_INVALID_PARAMETER invalid parameter passed to the routine which
+                                creates the PCI controller node for the primary
+                                Root post list
+**/
+EFI_STATUS
+RecordPciRootPortBridges (
+  IN  PCI_IO_DEVICE           *RootBridge
+  )
+{
+  EFI_STATUS              Status = EFI_NOT_FOUND;
+  LIST_ENTRY              *Link;
+  PCI_IO_DEVICE           *Device;
+  UINTN                   NumberOfRootPorts;
+  PRIMARY_ROOT_PORT_NODE  *PrimaryRootPorts,
+                          *TempNode;
+  UINT8                   RootPortSecBus,
+                          RootPortSubBus;
+
+  DEBUG ((
+      DEBUG_INFO, "<<********** RecordPciRootPortBridges -start *************>>\n"
+  ));
+  NumberOfRootPorts = 0;
+  PrimaryRootPorts = NULL;
+  for ( Link = RootBridge->ChildList.ForwardLink
+      ; Link != &RootBridge->ChildList
+      ; Link = Link->ForwardLink
+  ) {
+    Device = PCI_IO_DEVICE_FROM_LINK (Link);
+    if (IS_PCI_BRIDGE (&Device->Pci)) {
+      Status = GetPciRootPortBusAssigned (
+                  Device,
+                  NULL,
+                  &RootPortSecBus,
+                  &RootPortSubBus
+                  );
+      if ( !EFI_ERROR(Status)) {
+        DEBUG ((
+            DEBUG_INFO, "::Device [%02x|%02x|%02x] - SecBus=0x%x, SubBus=0x%x\n",
+            Device->BusNumber, Device->DeviceNumber, Device->FunctionNumber,
+            RootPortSecBus, RootPortSubBus
+        ));
+      } else {
+        DEBUG ((
+            DEBUG_ERROR, "Unexpected read error [0x%lx]::Device [%02x|%02x|%02x]\n",
+            Status, Device->BusNumber, Device->DeviceNumber, Device->FunctionNumber
+        ));
+        RootPortSecBus = RootPortSubBus = 0;
+        continue;
+      }
+
+      if ( !PrimaryRootPorts) {
+        NumberOfRootPorts++;
+        Status = CreatePrimaryPciRootPortNode (
+                    RootBridge,
+                    Device,
+                    RootPortSecBus,
+                    RootPortSubBus,
+                    &PrimaryRootPorts
+                    );
+        if ( EFI_ERROR(Status)) {
+          //
+          // abort mission to scan for all primary roots ports of a bridge
+          // controller if error encountered for very first PCI primary root port
+          //
+          DEBUG ((
+              DEBUG_ERROR, "Unexpected node creation error [0x%lx]::Device [%02x|%02x|%02x]\n",
+              Status, Device->BusNumber, Device->DeviceNumber, Device->FunctionNumber
+          ));
+          return Status;
+        }
+        DEBUG ((
+            DEBUG_INFO, "first primary root port found::Device [%02x|%02x|%02x]\n",
+            Device->BusNumber, Device->DeviceNumber, Device->FunctionNumber
+        ));
+      } else {
+        if ( !CheckChildRootPort ( PrimaryRootPorts, RootPortSecBus, RootPortSubBus)) {
+          NumberOfRootPorts++;
+          TempNode = NULL;
+          Status = CreatePrimaryPciRootPortNode (
+                      RootBridge,
+                      Device,
+                      RootPortSecBus,
+                      RootPortSubBus,
+                      &TempNode
+                      );
+          if ( !EFI_ERROR(Status)) {
+            //
+            // another primary root port found on the same bridge controller
+            // insert in the node list
+            //
+            InsertTailList ( &PrimaryRootPorts->NeighborRootPort, &TempNode->NeighborRootPort);
+            DEBUG ((
+                DEBUG_INFO, "next primary root port found::Device [%02x|%02x|%02x]\n",
+                Device->BusNumber, Device->DeviceNumber, Device->FunctionNumber
+            ));
+          } else {
+            DEBUG ((
+                DEBUG_ERROR, "Unexpected node creation error [0x%lx]::Device [%02x|%02x|%02x]\n",
+                Status, Device->BusNumber, Device->DeviceNumber, Device->FunctionNumber
+            ));
+          }
+        }
+      }
+    }
+  }
+  //
+  // prepare the PCI root port and its feature configuration table list
+  //
+  if ( NumberOfRootPorts) {
+    Status = PreparePciControllerConfigurationTable (
+                PrimaryRootPorts,
+                NumberOfRootPorts
+              );
+
+  } else {
+    DEBUG ((
+        DEBUG_INFO, "No PCI Root port found on this bridge!\n"
+    ));
+  }
+
+  DEBUG ((
+      DEBUG_INFO, "<<********** RecordPciRootPortBridges - end **********>>\n"
+  ));
+  return Status;
+}
+
+/**
+  Enumerate all the nodes of the specified root bridge or PCI-PCI Bridge, to
+  configure the other PCI features.
+
+  @param RootBridge          A pointer to the PCI_IO_DEVICE.
+
+  @retval EFI_SUCCESS           The other PCI features configuration during enumeration
+                                of all the nodes of the PCI root bridge instance were
+                                programmed in PCI-compliance pattern along with the
+                                device-specific policy, as applicable.
+  @retval EFI_UNSUPPORTED       One of the override operation maong the nodes of
+                                the PCI hierarchy resulted in a incompatible address
+                                range.
+  @retval EFI_INVALID_PARAMETER The override operation is performed with invalid input
+                                parameters.
+**/
+EFI_STATUS
+EnumerateOtherPciFeatures (
+  IN PCI_IO_DEVICE          *RootBridge
+  )
+{
+  EFI_STATUS            Status;
+  CHAR16                *Str;
+  UINTN                 OtherPciFeatureConfigPhase;
+
+  //
+  // check on PCI features configuration is complete and re-enumeration is required
+  //
+  if ( !CheckPciFeaturesConfigurationRequired ( RootBridge)) {
+    return EFI_ALREADY_STARTED;
+  }
+
+  Str = ConvertDevicePathToText (
+          DevicePathFromHandle (RootBridge->Handle),
+          FALSE,
+          FALSE
+        );
+  DEBUG ((DEBUG_INFO, "Enumerating PCI features for Root Bridge %s\n", Str != NULL ? Str : L""));
+
+  for ( OtherPciFeatureConfigPhase = PciFeatureRootBridgeScan
+      ; OtherPciFeatureConfigPhase <= PciFeatureConfigurationComplete
+      ; OtherPciFeatureConfigPhase++
+      ) {
+    switch ( OtherPciFeatureConfigPhase){
+      case  PciFeatureRootBridgeScan:
+        SetupPciFeaturesConfigurationDefaults ();
+        //
+        //first scan the entire root bridge heirarchy for the primary PCI root ports
+        //
+        RecordPciRootPortBridges ( RootBridge);
+        break;
+
+      case  PciFeatureGetDevicePolicy:
+      case  PciFeatureSetupPhase:
+        DEBUG ((
+            DEBUG_INFO, "<<********** SetupPciFeatures - start **********>>\n"
+        ));
+        //
+        // enumerate the other PCI features
+        //
+        Status = SetupPciFeatures ( RootBridge, OtherPciFeatureConfigPhase);
+
+        DEBUG ((
+            DEBUG_INFO, "<<********** SetupPciFeatures - end **********>>\n"
+        ));
+        break;
+
+      case  PciFeatureConfigurationPhase:
+        //
+        // override the PCI features as per enumeration phase
+        //
+        DEBUG ((DEBUG_INFO, "PCI features override for Root Bridge %s\n", Str != NULL ? Str : L""));
+        DEBUG ((
+            DEBUG_INFO, "<<********** ProgramPciFeatures - start **********>>\n"
+        ));
+        Status = ProgramPciFeatures ( RootBridge);
+        DEBUG ((
+            DEBUG_INFO, "<<********** ProgramPciFeatures - end **********>>\n"
+        ));
+        break;
+
+      case  PciFeatureConfigurationComplete:
+        //
+        // clean up the temporary resource nodes created for this root bridge
+        //
+        DestroyPrimaryRootPortNodes ();
+
+        ErasePciFeaturesConfigurationTable ();
+    }
+  }
+
+  if (Str != NULL) {
+    FreePool (Str);
+  }
+  //
+  // mark this root bridge as PCI features configuration complete, and no new
+  // enumeration is required
+  //
+  AddRootBridgeInPciFeaturesConfigCompletionList ( RootBridge, FALSE);
+  return Status;
+}
+
+/**
+  This routine is invoked from the Stop () interface for the EFI handle of the
+  RootBridge. Free up its node of type PCI_FEATURE_CONFIGURATION_COMPLETION_LIST.
+
+  @param  RootBridge      A pointer to the PCI_IO_DEVICE
+**/
+VOID
+DestroyRootBridgePciFeaturesConfigCompletionList (
+  IN PCI_IO_DEVICE          *RootBridge
+  )
+{
+  LIST_ENTRY                                  *Link;
+  PCI_FEATURE_CONFIGURATION_COMPLETION_LIST   *Temp;
+
+  if ( mPciFeaturesConfigurationCompletionList) {
+    Link = &mPciFeaturesConfigurationCompletionList->RootBridgeLink;
+
+    do {
+      Temp = PCI_FEATURE_CONFIGURATION_COMPLETION_LIST_FROM_LINK (Link);
+      if ( Temp->RootBridgeHandle == RootBridge->Handle) {
+        RemoveEntryList ( Link);
+        FreePool ( Temp);
+        return;
+      }
+      Link = Link->ForwardLink;
+    } while (Link != &mPciFeaturesConfigurationCompletionList->RootBridgeLink);
+  }
+  //
+  // not found on the PCI feature configuration completion list, return
+  //
+  return;
+}
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
new file mode 100644
index 0000000000..9f225fa993
--- /dev/null
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
@@ -0,0 +1,201 @@
+/** @file
+  PCI standard feature support functions implementation for PCI Bus module..
+
+Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _EFI_PCI_FEATURES_SUPPORT_H_
+#define _EFI_PCI_FEATURES_SUPPORT_H_
+
+#include "PciBus.h"
+#include "PciPlatformSupport.h"
+
+//
+// Macro definitions for the PCI Features support PCD
+//
+#define PCI_FEATURE_SUPPORT_FLAG_MPS  BIT0
+#define PCI_FEATURE_SUPPORT_FLAG_MRRS BIT1
+
+//
+// defines the data structure to hold the details of the PCI Root port devices
+//
+typedef struct _PRIMARY_ROOT_PORT_NODE  PRIMARY_ROOT_PORT_NODE;
+
+//
+// defines the data structure to hold the configuration data for the other PCI
+// features
+//
+typedef struct _OTHER_PCI_FEATURES_CONFIGURATION_TABLE  OTHER_PCI_FEATURES_CONFIGURATION_TABLE;
+
+//
+// Defines for the PCI features configuration completion and re-enumeration list
+//
+typedef struct _PCI_FEATURE_CONFIGURATION_COMPLETION_LIST  PCI_FEATURE_CONFIGURATION_COMPLETION_LIST;
+
+//
+// Signature value for the PCI Root Port node
+//
+#define PCI_ROOT_PORT_SIGNATURE               SIGNATURE_32 ('p', 'c', 'i', 'p')
+
+//
+// Definitions of the PCI Root Port data structure members
+//
+struct _PRIMARY_ROOT_PORT_NODE {
+  //
+  // Signature header
+  //
+  UINT32                                    Signature;
+  //
+  // linked list pointers to next node
+  //
+  LIST_ENTRY                                NeighborRootPort;
+  //
+  // EFI handle of the parent Root Bridge instance
+  //
+  EFI_HANDLE                                RootBridgeHandle;
+  //
+  // EFI handle of the PCI controller
+  //
+  EFI_HANDLE                                RootPortHandle;
+  //
+  // PCI Secondary bus value of the PCI controller
+  //
+  UINT8                                     SecondaryBusStart;
+  //
+  // PCI Subordinate bus value of the PCI controller
+  //
+  UINT8                                     SecondaryBusEnd;
+  //
+  // pointer to the corresponding PCI feature configuration Table node
+  //
+  OTHER_PCI_FEATURES_CONFIGURATION_TABLE    *OtherPciFeaturesConfigurationTable;
+};
+
+#define PRIMARY_ROOT_PORT_NODE_FROM_LINK(a) \
+  CR (a, PRIMARY_ROOT_PORT_NODE, NeighborRootPort, PCI_ROOT_PORT_SIGNATURE)
+
+//
+// Definition of the PCI Feature configuration Table members
+//
+struct _OTHER_PCI_FEATURES_CONFIGURATION_TABLE {
+  //
+  // Configuration Table ID
+  //
+  UINTN                                     ID;
+  //
+  // to configure the PCI feature Maximum payload size to maintain the data packet
+  // size among all the PCI devices in the PCI hierarchy
+  //
+  UINT8                                     Max_Payload_Size;
+  //
+  // to configure the PCI feature maximum read request size to maintain the memory
+  // requester size among all the PCI devices in the PCI hierarchy
+  //
+  UINT8                                     Max_Read_Request_Size;
+  //
+  // lock the Max_Read_Request_Size for the entire PCI tree of a root port
+  //
+  BOOLEAN                                   Lock_Max_Read_Request_Size;
+};
+
+
+//
+// PCI feature configuration node signature value
+//
+#define PCI_FEATURE_CONFIGURATION_SIGNATURE               SIGNATURE_32 ('p', 'c', 'i', 'f')
+
+struct _PCI_FEATURE_CONFIGURATION_COMPLETION_LIST {
+  //
+  // Signature header
+  //
+  UINT32                                    Signature;
+  //
+  // link to next Root Bridge whose PCI Feature configuration is complete
+  //
+  LIST_ENTRY                                RootBridgeLink;
+  //
+  // EFI handle of the Root Bridge whose PCI feature configuration is complete
+  //
+  EFI_HANDLE                                RootBridgeHandle;
+  //
+  // indication for complete re-enumeration of the PCI feature configuration
+  //
+  BOOLEAN                                   ReEnumeratePciFeatureConfiguration;
+};
+
+#define PCI_FEATURE_CONFIGURATION_COMPLETION_LIST_FROM_LINK(a) \
+  CR (a, PCI_FEATURE_CONFIGURATION_COMPLETION_LIST, RootBridgeLink, PCI_FEATURE_CONFIGURATION_SIGNATURE)
+
+//
+// Declaration of the internal sub-phases within the PCI Feature enumeration
+//
+typedef enum {
+  //
+  // initial phase in configuring the other PCI features to record the primary
+  // root ports
+  //
+  PciFeatureRootBridgeScan,
+  //
+  // get the PCI device-specific platform policies and align with device capabilities
+  //
+  PciFeatureGetDevicePolicy,
+  //
+  // align all PCI nodes in the PCI heirarchical tree
+  //
+  PciFeatureSetupPhase,
+  //
+  // finally override to complete configuration of the PCI feature
+  //
+  PciFeatureConfigurationPhase,
+  //
+  // PCI feature configuration complete
+  //
+  PciFeatureConfigurationComplete
+
+}PCI_FEATURE_CONFIGURATION_PHASE;
+
+/**
+  Main routine to indicate platform selection of any of the other PCI features
+  to be configured by this driver
+
+  @retval TRUE    platform has selected the other PCI features to be configured
+          FALSE   platform has not selected any of the other PCI features
+**/
+BOOLEAN
+CheckOtherPciFeaturesPcd (
+  );
+
+/**
+  Enumerate all the nodes of the specified root bridge or PCI-PCI Bridge, to
+  configure the other PCI features.
+
+  @param RootBridge          A pointer to the PCI_IO_DEVICE.
+
+  @retval EFI_SUCCESS           The other PCI features configuration during enumeration
+                                of all the nodes of the PCI root bridge instance were
+                                programmed in PCI-compliance pattern along with the
+                                device-specific policy, as applicable.
+  @retval EFI_UNSUPPORTED       One of the override operation maong the nodes of
+                                the PCI hierarchy resulted in a incompatible address
+                                range.
+  @retval EFI_INVALID_PARAMETER The override operation is performed with invalid input
+                                parameters.
+**/
+EFI_STATUS
+EnumerateOtherPciFeatures (
+  IN PCI_IO_DEVICE           *RootBridge
+  );
+
+/**
+  This routine is invoked from the Stop () interface for the EFI handle of the
+  RootBridge. Free up its node of type PCI_FEATURE_CONFIGURATION_COMPLETION_LIST.
+
+  @param  RootBridge      A pointer to the PCI_IO_DEVICE
+**/
+VOID
+DestroyRootBridgePciFeaturesConfigCompletionList (
+  IN PCI_IO_DEVICE          *RootBridge
+  );
+#endif
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
new file mode 100644
index 0000000000..d94037d69a
--- /dev/null
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
@@ -0,0 +1,565 @@
+/** @file
+  This file encapsulate the usage of PCI Platform Protocol
+
+  This file define the necessary hooks used to obtain the platform
+  level data and policies which could be used in the PCI Enumeration phases
+
+Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "PciPlatformSupport.h"
+
+EFI_PCI_PLATFORM_PROTOCOL                     *mPciPlatformProtocol;
+EFI_PCI_OVERRIDE_PROTOCOL                     *mPciOverrideProtocol;
+
+EFI_PCI_PLATFORM_PROTOCOL2                    *mPciPlatformProtocol2;
+EFI_PCI_OVERRIDE_PROTOCOL2                    *mPciOverrideProtocol2;
+
+
+/**
+  This function retrieves the PCI Platform Protocol published by platform driver
+
+**/
+VOID
+GetPciPlatformProtocol (
+  )
+{
+  mPciPlatformProtocol2 = NULL;
+  gBS->LocateProtocol (
+      &gEfiPciPlatformProtocol2Guid,
+      NULL,
+      (VOID **) &mPciPlatformProtocol2
+  );
+
+  //
+  // If PCI Platform protocol doesn't exist, try to get Pci Override Protocol.
+  //
+  if (mPciPlatformProtocol2 == NULL) {
+    mPciOverrideProtocol2 = NULL;
+    gBS->LocateProtocol (
+        &gEfiPciOverrideProtocol2Guid,
+        NULL,
+        (VOID **) &mPciOverrideProtocol2
+    );
+  }
+  //
+  // fetch the old PCI Platform Protocols if new are not installed
+  //
+  if (mPciOverrideProtocol2 == NULL) {
+
+    mPciPlatformProtocol = NULL;
+    gBS->LocateProtocol (
+        &gEfiPciPlatformProtocolGuid,
+        NULL,
+        (VOID **) &mPciPlatformProtocol
+    );
+
+    //
+    // If PCI Platform protocol doesn't exist, try to  get Pci Override Protocol.
+    //
+    if (mPciPlatformProtocol == NULL) {
+      mPciOverrideProtocol = NULL;
+      gBS->LocateProtocol (
+          &gEfiPciOverrideProtocolGuid,
+          NULL,
+          (VOID **) &mPciOverrideProtocol
+      );
+    }
+  }
+}
+
+/**
+  This function indicates the presence of PCI Platform driver
+  @retval     TRUE or FALSE
+**/
+BOOLEAN
+CheckPciPlatformProtocolInstall (
+  )
+{
+  if (mPciPlatformProtocol2 != NULL) {
+    return TRUE;
+  } else if (mPciOverrideProtocol2 != NULL) {
+    return TRUE;
+  } else {
+    if (mPciPlatformProtocol != NULL) {
+      return TRUE;
+    } else if (mPciOverrideProtocol != NULL){
+      return TRUE;
+    }
+  }
+  return FALSE;
+}
+
+/**
+  Provides the hooks from the PCI bus driver to every PCI controller (device/function) at various
+  stages of the PCI enumeration process that allow the host bridge driver to preinitialize individual
+  PCI controllers before enumeration.
+
+  This function is called during the PCI enumeration process. No specific action is expected from this
+  member function. It allows the host bridge driver to preinitialize individual PCI controllers before
+  enumeration.
+
+  @param[in] HostBridgeHandle     The associated PCI host bridge handle.
+  @param[in] RootBridgeHandle     The associated PCI root bridge handle.
+  @param[in] RootBridgePciAddress The address of the PCI device on the PCI bus.
+  @param[in] Phase          The phase of the PCI controller enumeration.
+  @param[in] ExecPhase      Defines the execution phase of the PCI chipset driver.
+
+  @retval    Status         returns the status from the PCI Platform protocol as is
+
+**/
+EFI_STATUS
+PciPlatformPreprocessController (
+  IN EFI_HANDLE                                    HostBridgeHandle,
+  IN EFI_HANDLE                                    RootBridgeHandle,
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS   RootBridgePciAddress,
+  IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE  Phase,
+  IN EFI_PCI_EXECUTION_PHASE                       ExecPhase
+  )
+{
+  EFI_STATUS  Status;
+
+  if (mPciPlatformProtocol2 != NULL) {
+    //
+    // Call PlatformPci::PrepController() if the protocol is present.
+    //
+    Status = mPciPlatformProtocol2->PlatformPrepController (
+                                      (EFI_PCI_PLATFORM_PROTOCOL*)mPciPlatformProtocol2,
+                                      HostBridgeHandle,
+                                      RootBridgeHandle,
+                                      RootBridgePciAddress,
+                                      Phase,
+                                      ExecPhase
+                                    );
+  } else if (mPciOverrideProtocol2 != NULL) {
+    //
+    // Call PlatformPci::PrepController() if the protocol is present.
+    //
+    Status = mPciOverrideProtocol2->PlatformPrepController (
+                                      (EFI_PCI_PLATFORM_PROTOCOL*)mPciOverrideProtocol2,
+                                      HostBridgeHandle,
+                                      RootBridgeHandle,
+                                      RootBridgePciAddress,
+                                      Phase,
+                                      ExecPhase
+                                    );
+  } else {
+    if (mPciPlatformProtocol != NULL) {
+      //
+      // Call PlatformPci::PrepController() if the protocol is present.
+      //
+      Status = mPciPlatformProtocol->PlatformPrepController (
+                                      mPciPlatformProtocol,
+                                      HostBridgeHandle,
+                                      RootBridgeHandle,
+                                      RootBridgePciAddress,
+                                      Phase,
+                                      ExecPhase
+                                    );
+    } else if (mPciOverrideProtocol != NULL) {
+      //
+      // Call PlatformPci::PrepController() if the protocol is present.
+      //
+      Status = mPciOverrideProtocol->PlatformPrepController (
+                                      mPciOverrideProtocol,
+                                      HostBridgeHandle,
+                                      RootBridgeHandle,
+                                      RootBridgePciAddress,
+                                      Phase,
+                                      ExecPhase
+                                    );
+    } else {
+      //
+      // return PCI Platform Protocol not found
+      //
+      return EFI_NOT_FOUND;
+    }
+  }
+  return Status;
+}
+
+/**
+  This function notifies the PCI Platform driver about the PCI host bridge resource
+  allocation phase and PCI execution phase.
+
+  @param[in]  HostBridge     The handle of the host bridge controller.
+  @param[in]  Phase          The phase of the PCI bus enumeration.
+  @param[in]  ExecPhase      Defines the execution phase of the PCI chipset driver.
+  @retval     Status          returns the status from the PCI Platform protocol as is
+
+**/
+EFI_STATUS
+PciPlatformNotifyPhase (
+  IN  EFI_HANDLE                                      HostBridgeHandle,
+  IN  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE   Phase,
+  IN  EFI_PCI_EXECUTION_PHASE                         ExecPhase
+  )
+{
+  EFI_STATUS  Status;
+
+  if ( mPciPlatformProtocol2 != NULL) {
+    Status = mPciPlatformProtocol2->PlatformNotify (
+                                      (EFI_PCI_PLATFORM_PROTOCOL*)mPciPlatformProtocol2,
+                                      HostBridgeHandle,
+                                      Phase,
+                                      ExecPhase
+                                    );
+  } else if ( mPciOverrideProtocol2 != NULL) {
+    Status = mPciOverrideProtocol2->PlatformNotify (
+                                      (EFI_PCI_PLATFORM_PROTOCOL*)mPciOverrideProtocol2,
+                                      HostBridgeHandle,
+                                      Phase,
+                                      ExecPhase
+                                    );
+  } else {
+
+    if ( mPciPlatformProtocol != NULL) {
+      Status = mPciPlatformProtocol->PlatformNotify (
+                                      mPciPlatformProtocol,
+                                      HostBridgeHandle,
+                                      Phase,
+                                      ExecPhase
+                                    );
+    } else if ( mPciOverrideProtocol != NULL){
+      Status = mPciOverrideProtocol->PlatformNotify (
+                                      mPciOverrideProtocol,
+                                      HostBridgeHandle,
+                                      Phase,
+                                      ExecPhase
+                                    );
+    } else {
+      //
+      // return PCI Platform Protocol not found
+      //
+      return EFI_NOT_FOUND;
+    }
+  }
+  return Status;
+}
+
+/**
+  This function retrieves the PCI platform policy.
+
+  @param  PciPolicy     pointer to the legacy EFI_PCI_PLATFORM_POLICY
+  @retval Status        returns the status from the PCI Platform protocol as is
+
+**/
+EFI_STATUS
+PciGetPlatformPolicy (
+  OUT EFI_PCI_PLATFORM_POLICY *PciPolicy
+  )
+{
+  EFI_STATUS  Status;
+
+  if ( mPciPlatformProtocol2 != NULL) {
+      Status = mPciPlatformProtocol2->GetPlatformPolicy (
+                                        (EFI_PCI_PLATFORM_PROTOCOL*)mPciPlatformProtocol2,
+                                        PciPolicy
+                                      );
+  } else if ( mPciOverrideProtocol2 != NULL) {
+      Status = mPciOverrideProtocol2->GetPlatformPolicy (
+                                        (EFI_PCI_PLATFORM_PROTOCOL*)mPciOverrideProtocol2,
+                                        PciPolicy
+                                      );
+  } else {
+    if ( mPciPlatformProtocol != NULL) {
+      Status = mPciPlatformProtocol->GetPlatformPolicy (
+                                      mPciPlatformProtocol,
+                                      PciPolicy
+                                    );
+    }
+
+    if ( mPciOverrideProtocol != NULL) {
+      Status = mPciOverrideProtocol->GetPlatformPolicy (
+                                      mPciOverrideProtocol,
+                                      PciPolicy
+                                    );
+    } else {
+      //
+      // return PCI Platform Protocol not found
+      //
+      return EFI_NOT_FOUND;
+    }
+  }
+  return Status;
+}
+
+/**
+  This function retrieves the Option ROM image and size from the Platform.
+
+  It uses the PCI_IO_DEVICE internal fields are used to store OpROM image/size
+
+  @param Controller     An EFI handle for the PCI bus controller.
+  @param PciIoDevice    A PCI_IO_DEVICE pointer to the PCI IO device to be registered.
+
+  @retval EFI_SUCCESS            The option ROM was available for this device and loaded into memory.
+  @retval EFI_NOT_FOUND          No option ROM was available for this device.
+  @retval EFI_OUT_OF_RESOURCES   No memory was available to load the option ROM.
+  @retval EFI_DEVICE_ERROR       An error occurred in obtaining the option ROM.
+
+**/
+EFI_STATUS
+GetPlatformPciOptionRom (
+  IN  EFI_HANDLE                    Controller,
+  IN  PCI_IO_DEVICE                 *PciIoDevice
+  )
+{
+  EFI_STATUS  Status;
+  VOID        *PlatformOpRomBuffer;
+  UINTN       PlatformOpRomSize;
+
+  if (mPciPlatformProtocol2 != NULL) {
+    Status = mPciPlatformProtocol2->GetPciRom (
+                                      (EFI_PCI_PLATFORM_PROTOCOL*)mPciPlatformProtocol2,
+                                      PciIoDevice->Handle,
+                                      &PlatformOpRomBuffer,
+                                      &PlatformOpRomSize
+                                      );
+  } else if (mPciOverrideProtocol2 != NULL) {
+    Status = mPciOverrideProtocol2->GetPciRom (
+                                      (EFI_PCI_PLATFORM_PROTOCOL*)mPciOverrideProtocol2,
+                                      PciIoDevice->Handle,
+                                      &PlatformOpRomBuffer,
+                                      &PlatformOpRomSize
+                                      );
+  } else {
+    if (mPciPlatformProtocol != NULL) {
+      Status = mPciPlatformProtocol->GetPciRom (
+                                      mPciPlatformProtocol,
+                                      PciIoDevice->Handle,
+                                      &PlatformOpRomBuffer,
+                                      &PlatformOpRomSize
+                                      );
+    } else if (mPciOverrideProtocol != NULL) {
+      Status = mPciOverrideProtocol->GetPciRom (
+                                        mPciOverrideProtocol,
+                                        PciIoDevice->Handle,
+                                        &PlatformOpRomBuffer,
+                                        &PlatformOpRomSize
+                                        );
+    } else {
+      //
+      // return PCI Platform Protocol not found
+      //
+      return EFI_NOT_FOUND;
+    }
+  }
+
+  if (!EFI_ERROR (Status)) {
+    PciIoDevice->EmbeddedRom    = FALSE;
+    PciIoDevice->RomSize        = (UINT32)PlatformOpRomSize;
+    PciIoDevice->PciIo.RomSize  = PlatformOpRomSize;
+    PciIoDevice->PciIo.RomImage = PlatformOpRomBuffer;
+  }
+  return Status;
+}
+
+/**
+  Helper routine to indicate whether the given PCI device specific policy value
+  dictates to override the Max_Payload_Size to a particular value, or set as per
+  device capability.
+
+  @param  MPS     Input device-specific policy should be in terms of type
+                  EFI_PCI_CONF_MAX_PAYLOAD_SIZE
+
+  @retval TRUE    Setup Max_Payload_Size as per device capability
+          FALSE   override as per device-specific platform policy
+**/
+BOOLEAN
+SetupMpsAsPerDeviceCapability (
+  IN  UINT8                   MPS
+)
+{
+  if ( MPS == EFI_PCI_CONF_MAX_PAYLOAD_SIZE_AUTO) {
+    return TRUE;
+  } else {
+    return FALSE;
+  }
+}
+
+/**
+  Helper routine to indicate whether the given PCI device specific policy value
+  dictates to override the Max_Read_Req_Size to a particular value, or set as per
+  device capability.
+
+  @param  MRRS    Input device-specific policy should be in terms of type
+                  EFI_PCI_CONF_MAX_READ_REQ_SIZE
+
+  @retval TRUE    Setup Max_Read_Req_Size as per device capability
+          FALSE   override as per device-specific platform policy
+**/
+BOOLEAN
+SetupMrrsAsPerDeviceCapability (
+  IN  UINT8                   MRRS
+)
+{
+  if ( MRRS == EFI_PCI_CONF_MAX_READ_REQ_SIZE_AUTO) {
+    return TRUE;
+  } else {
+    return FALSE;
+  }
+}
+
+/**
+  Routine to translate the given device-specific platform policy from type
+  EFI_PCI_CONF_MAX_PAYLOAD_SIZE to HW-specific value, as per PCI Base Specification
+  Revision 4.0; for the PCI feature Max_Payload_Size.
+
+  @param  MPS     Input device-specific policy should be in terms of type
+                  EFI_PCI_CONF_MAX_PAYLOAD_SIZE
+
+  @retval         Range values for the Max_Payload_Size as defined in the PCI
+                  Base Specification 4.0
+**/
+UINT8
+TranslateMpsSetupValueToPci (
+  IN  UINT8                   MPS
+)
+{
+  switch (MPS) {
+    case EFI_PCI_CONF_MAX_PAYLOAD_SIZE_128B:
+      return PCIE_MAX_PAYLOAD_SIZE_128B;
+    case EFI_PCI_CONF_MAX_PAYLOAD_SIZE_256B:
+      return PCIE_MAX_PAYLOAD_SIZE_256B;
+    case EFI_PCI_CONF_MAX_PAYLOAD_SIZE_512B:
+      return PCIE_MAX_PAYLOAD_SIZE_512B;
+    case EFI_PCI_CONF_MAX_PAYLOAD_SIZE_1024B:
+      return PCIE_MAX_PAYLOAD_SIZE_1024B;
+    case EFI_PCI_CONF_MAX_PAYLOAD_SIZE_2048B:
+      return PCIE_MAX_PAYLOAD_SIZE_2048B;
+    case EFI_PCI_CONF_MAX_PAYLOAD_SIZE_4096B:
+      return PCIE_MAX_PAYLOAD_SIZE_4096B;
+    default:
+      return PCIE_MAX_PAYLOAD_SIZE_128B;
+  }
+}
+
+/**
+  Routine to translate the given device-specific platform policy from type
+  EFI_PCI_CONF_MAX_READ_REQ_SIZE to HW-specific value, as per PCI Base Specification
+  Revision 4.0; for the PCI feature Max_Read_Req_Size.
+
+  @param  MRRS    Input device-specific policy should be in terms of type
+                  EFI_PCI_CONF_MAX_READ_REQ_SIZE
+
+  @retval         Range values for the Max_Read_Req_Size as defined in the PCI
+                  Base Specification 4.0
+**/
+UINT8
+TranslateMrrsSetupValueToPci (
+  IN  UINT8                   MRRS
+)
+{
+  switch (MRRS) {
+    case EFI_PCI_CONF_MAX_READ_REQ_SIZE_128B:
+      return PCIE_MAX_READ_REQ_SIZE_128B;
+    case EFI_PCI_CONF_MAX_READ_REQ_SIZE_256B:
+      return PCIE_MAX_READ_REQ_SIZE_256B;
+    case EFI_PCI_CONF_MAX_READ_REQ_SIZE_512B:
+      return PCIE_MAX_READ_REQ_SIZE_512B;
+    case EFI_PCI_CONF_MAX_READ_REQ_SIZE_1024B:
+      return PCIE_MAX_READ_REQ_SIZE_1024B;
+    case EFI_PCI_CONF_MAX_READ_REQ_SIZE_2048B:
+      return PCIE_MAX_READ_REQ_SIZE_2048B;
+    case EFI_PCI_CONF_MAX_READ_REQ_SIZE_4096B:
+      return PCIE_MAX_READ_REQ_SIZE_4096B;
+    default:
+      return PCIE_MAX_READ_REQ_SIZE_128B;
+  }
+}
+
+/**
+  Generic routine to setup the PCI features as per its predetermined defaults.
+**/
+VOID
+SetupDefaultsDevicePlatformPolicy (
+  IN  PCI_IO_DEVICE               *PciDevice
+  )
+{
+  PciDevice->SetupMPS = EFI_PCI_CONF_MAX_PAYLOAD_SIZE_AUTO;
+  PciDevice->SetupMRRS = EFI_PCI_CONF_MAX_READ_REQ_SIZE_AUTO;
+}
+
+/**
+  Intermediate routine to either get the PCI device specific platform policies
+  through the PCI Platform Protocol, or its alias the PCI Override Protocol.
+
+  @param  PciIoDevice         A pointer to PCI_IO_DEVICE
+  @param  PciPlatformProtocol A pointer to EFI_PCI_PLATFORM_PROTOCOL2
+
+  @retval EFI_STATUS          The direct status from the PCI Platform Protocol
+  @retval EFI_SUCCESS         if on returning predetermined PCI features defaults,
+                              for the case when protocol returns as EFI_UNSUPPORTED
+                              to indicate PCI device exist and it has no platform
+                              policy defined.
+**/
+EFI_STATUS
+GetPciDevicePlatformPolicyEx (
+  IN  PCI_IO_DEVICE               *PciIoDevice,
+  IN  EFI_PCI_PLATFORM_PROTOCOL2  *PciPlatformProtocol
+  )
+{
+  EFI_PCI_PLATFORM_EXTENDED_POLICY  PciPlatformExtendedPolicy;
+  EFI_STATUS                        Status;
+
+  ZeroMem ( &PciPlatformExtendedPolicy, sizeof (EFI_PCI_PLATFORM_EXTENDED_POLICY));
+  Status = PciPlatformProtocol->GetDevicePolicy (
+                                  PciPlatformProtocol,
+                                  PciIoDevice->Handle,
+                                  &PciPlatformExtendedPolicy
+                                  );
+  //
+  // platform chipset policies are returned for this PCI device
+  //
+  if (!EFI_ERROR(Status)) {
+    PciIoDevice->SetupMPS = PciPlatformExtendedPolicy.DeviceCtlMPS;
+    PciIoDevice->SetupMRRS = PciPlatformExtendedPolicy.DeviceCtlMRRS;
+  }
+  //
+  // platform chipset policies are not provided for this PCI device
+  //
+  if (EFI_ERROR(Status) == EFI_UNSUPPORTED) {
+    //
+    // let the enumeration happen as per the PCI standard way
+    //
+    SetupDefaultsDevicePlatformPolicy ( PciIoDevice);
+    return EFI_SUCCESS;
+  }
+
+  return Status;
+}
+
+/**
+  Gets the PCI device-specific platform policy from the PCI Platform Protocol.
+  If no PCI Platform protocol is published than setup the PCI feature to predetermined
+  defaults, in order to align all the PCI devices in the PCI hierarchy, as applicable.
+
+  @param  PciDevice     A pointer to PCI_IO_DEVICE
+
+  @retval EFI_STATUS    The direct status from the PCI Platform Protocol
+  @retval EFI_SUCCESS   On return of predetermined PCI features defaults, for
+                        the case when protocol returns as EFI_UNSUPPORTED to
+                        indicate PCI device exist and it has no platform policy
+                        defined. Also, on returns when no PCI Platform Protocol
+                        exist.
+**/
+EFI_STATUS
+GetPciDevicePlatformPolicy (
+  IN PCI_IO_DEVICE          *PciDevice
+  )
+{
+  if ( mPciPlatformProtocol2 != NULL) {
+    return GetPciDevicePlatformPolicyEx ( PciDevice, mPciPlatformProtocol2);
+  } else if (mPciOverrideProtocol2 != NULL) {
+    return GetPciDevicePlatformPolicyEx ( PciDevice, mPciOverrideProtocol2);
+  } else {
+    //
+    // new PCI Platform Protocol 2 is not installed; let the enumeration happen
+    // as per PCI standard way
+    //
+    SetupDefaultsDevicePlatformPolicy ( PciDevice);
+    return EFI_SUCCESS;
+  }
+}
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
new file mode 100644
index 0000000000..d54e46b950
--- /dev/null
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
@@ -0,0 +1,193 @@
+/** @file
+  This file encapsulate the usage of PCI Platform Protocol
+
+  This file define the necessary hooks used to obtain the platform
+  level data and policies which could be used in the PCI Enumeration phases
+
+Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+
+#ifndef _EFI_PCI_PLATFORM_SUPPORT_H_
+#define _EFI_PCI_PLATFORM_SUPPORT_H_
+
+#include "PciBus.h"
+
+/**
+  This function retrieves the PCI Platform Protocol published by platform driver
+
+**/
+VOID
+GetPciPlatformProtocol (
+  );
+
+/**
+  This function indicates the presence of PCI Platform driver
+  @retval     TRUE or FALSE
+**/
+BOOLEAN
+CheckPciPlatformProtocolInstall (
+  );
+
+
+/**
+  Provides the hooks from the PCI bus driver to every PCI controller (device/function) at various
+  stages of the PCI enumeration process that allow the host bridge driver to preinitialize individual
+  PCI controllers before enumeration.
+
+  This function is called during the PCI enumeration process. No specific action is expected from this
+  member function. It allows the host bridge driver to preinitialize individual PCI controllers before
+  enumeration.
+
+  @param[in] HostBridgeHandle     The associated PCI host bridge handle.
+  @param[in] RootBridgeHandle     The associated PCI root bridge handle.
+  @param[in] RootBridgePciAddress The address of the PCI device on the PCI bus.
+  @param[in] Phase          The phase of the PCI controller enumeration.
+  @param[in] ExecPhase      Defines the execution phase of the PCI chipset driver.
+
+  @retval    Status         returns the status from the PCI Platform protocol as is
+
+**/
+EFI_STATUS
+PciPlatformPreprocessController (
+  IN EFI_HANDLE                                    HostBridgeHandle,
+  IN EFI_HANDLE                                    RootBridgeHandle,
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS   RootBridgePciAddress,
+  IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE  Phase,
+  IN EFI_PCI_EXECUTION_PHASE                       ExecPhase
+  );
+
+/**
+  This function notifies the PCI Platform driver about the PCI host bridge resource
+  allocation phase and PCI execution phase.
+
+  @param[in]  HostBridge     The handle of the host bridge controller.
+  @param[in]  Phase          The phase of the PCI bus enumeration.
+  @param[in]  ExecPhase      Defines the execution phase of the PCI chipset driver.
+  @retval     Status          returns the status from the PCI Platform protocol as is
+
+**/
+EFI_STATUS
+PciPlatformNotifyPhase (
+  IN  EFI_HANDLE                                      HostBridgeHandle,
+  IN  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE   Phase,
+  IN  EFI_PCI_EXECUTION_PHASE                         ExecPhase
+  );
+
+/**
+  This function retrieves the PCI platform policy.
+
+  @param  PciPolicy     pointer to the legacy EFI_PCI_PLATFORM_POLICY
+  @retval Status        returns the status from the PCI Platform protocol as is
+
+**/
+EFI_STATUS
+PciGetPlatformPolicy (
+  OUT EFI_PCI_PLATFORM_POLICY *PciPolicy
+  );
+
+/**
+  This function retrieves the Option ROM image and size from the Platform.
+
+  It uses the PCI_IO_DEVICE internal fields are used to store OpROM image/size
+
+  @param Controller     An EFI handle for the PCI bus controller.
+  @param PciIoDevice    A PCI_IO_DEVICE pointer to the PCI IO device to be registered.
+
+  @retval EFI_SUCCESS            The option ROM was available for this device and loaded into memory.
+  @retval EFI_NOT_FOUND          No option ROM was available for this device.
+  @retval EFI_OUT_OF_RESOURCES   No memory was available to load the option ROM.
+  @retval EFI_DEVICE_ERROR       An error occurred in obtaining the option ROM.
+
+**/
+EFI_STATUS
+GetPlatformPciOptionRom (
+  IN  EFI_HANDLE                    Controller,
+  IN  PCI_IO_DEVICE                 *PciIoDevice
+  );
+
+/**
+  Gets the PCI device-specific platform policy from the PCI Platform Protocol.
+  If no PCI Platform protocol is published than setup the PCI feature to predetermined
+  defaults, in order to align all the PCI devices in the PCI hierarchy, as applicable.
+
+  @param  PciDevice     A pointer to PCI_IO_DEVICE
+
+  @retval EFI_STATUS    The direct status from the PCI Platform Protocol
+  @retval EFI_SUCCESS   On return of predetermined PCI features defaults, for
+                        the case when protocol returns as EFI_UNSUPPORTED to
+                        indicate PCI device exist and it has no platform policy
+                        defined. Also, on returns when no PCI Platform Protocol
+                        exist.
+**/
+EFI_STATUS
+GetPciDevicePlatformPolicy (
+  IN PCI_IO_DEVICE          *PciDevice
+  );
+
+/**
+  Helper routine to indicate whether the given PCI device specific policy value
+  dictates to override the Max_Payload_Size to a particular value, or set as per
+  device capability.
+
+  @param  MPS     Input device-specific policy should be in terms of type
+                  EFI_PCI_CONF_MAX_PAYLOAD_SIZE
+
+  @retval TRUE    Setup Max_Payload_Size as per device capability
+          FALSE   override as per device-specific platform policy
+**/
+BOOLEAN
+SetupMpsAsPerDeviceCapability (
+  IN  UINT8                   MPS
+);
+
+/**
+  Helper routine to indicate whether the given PCI device specific policy value
+  dictates to override the Max_Read_Req_Size to a particular value, or set as per
+  device capability.
+
+  @param  MRRS    Input device-specific policy should be in terms of type
+                  EFI_PCI_CONF_MAX_READ_REQ_SIZE
+
+  @retval TRUE    Setup Max_Read_Req_Size as per device capability
+          FALSE   override as per device-specific platform policy
+**/
+BOOLEAN
+SetupMrrsAsPerDeviceCapability (
+  IN  UINT8                   MRRS
+);
+
+/**
+  Routine to translate the given device-specific platform policy from type
+  EFI_PCI_CONF_MAX_PAYLOAD_SIZE to HW-specific value, as per PCI Base Specification
+  Revision 4.0; for the PCI feature Max_Payload_Size.
+
+  @param  MPS     Input device-specific policy should be in terms of type
+                  EFI_PCI_CONF_MAX_PAYLOAD_SIZE
+
+  @retval         Range values for the Max_Payload_Size as defined in the PCI
+                  Base Specification 4.0
+**/
+UINT8
+TranslateMpsSetupValueToPci (
+  IN  UINT8                   MPS
+);
+
+/**
+  Routine to translate the given device-specific platform policy from type
+  EFI_PCI_CONF_MAX_READ_REQ_SIZE to HW-specific value, as per PCI Base Specification
+  Revision 4.0; for the PCI feature Max_Read_Req_Size.
+
+  @param  MRRS    Input device-specific policy should be in terms of type
+                  EFI_PCI_CONF_MAX_READ_REQ_SIZE
+
+  @retval         Range values for the Max_Read_Req_Size as defined in the PCI
+                  Base Specification 4.0
+**/
+UINT8
+TranslateMrrsSetupValueToPci (
+  IN  UINT8                   MRRS
+);
+#endif
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c
index 4969ee0f64..755423f77b 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c
@@ -198,20 +198,7 @@ CalculateApertureIo16 (
     //
     Status = EFI_NOT_FOUND;
     PciPolicy = 0;
-    if (gPciPlatformProtocol != NULL) {
-      Status = gPciPlatformProtocol->GetPlatformPolicy (
-                                       gPciPlatformProtocol,
-                                       &PciPolicy
-                                       );
-    }
-
-    if (EFI_ERROR (Status) && gPciOverrideProtocol != NULL) {
-      Status = gPciOverrideProtocol->GetPlatformPolicy (
-                                       gPciOverrideProtocol,
-                                       &PciPolicy
-                                       );
-    }
-
+    Status = PciGetPlatformPolicy ( &PciPolicy);
     if (!EFI_ERROR (Status)) {
       if ((PciPolicy & EFI_RESERVE_ISA_IO_ALIAS) != 0) {
         mReserveIsaAliases = TRUE;
diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec
index 17beb45235..7bcbe5a3ea 100644
--- a/MdeModulePkg/MdeModulePkg.dec
+++ b/MdeModulePkg/MdeModulePkg.dec
@@ -1026,6 +1026,16 @@
   # @Prompt Enable UEFI Stack Guard.
   gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard|FALSE|BOOLEAN|0x30001055
 
+  ## This PCD is to indicate the PCI Bus driver to setup other new PCI features.
+  #  Each PCI feature is represented by its mask bit position and it configures
+  #  if that bit is set.
+  #
+  #   Bit 0 - if set, the PCI Bus driver programs the device's Max_Payload_Size.<BR>
+  #   Bit 1 - if set, the PCI Bus driver programs the device's Max_Read_Req_Size.<BR>
+  #   Bit 2 to 31 - Reserved for future use by the PCI Bus driver.<BR>
+  # @Prompt The UEFI PCU Bus driver enables the new set of other PCI Features.
+  gEfiMdeModulePkgTokenSpaceGuid.PcdOtherPciFeatures|0x00000003|UINT32|0x30001056
+
 [PcdsFixedAtBuild, PcdsPatchableInModule]
   ## Dynamic type PCD can be registered callback function for Pcd setting action.
   #  PcdMaxPeiPcdCallBackNumberPerPcdEntry indicates the maximum number of callback function
-- 
2.21.0.windows.1


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

View/Reply Online (#47851): https://edk2.groups.io/g/devel/message/47851
Mute This Topic: https://groups.io/mt/34264504/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub  [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-

Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH] PciBusDxe: New PCI features Max_Payload_Size, Max_Read_Req_Size
Posted by Ni, Ray 4 years, 5 months ago
Javeed,
The patch is too big.
I recommend you separate the patch to several small patches. The goal of that is to make reviewers today (like me) and future easy to understand the code changes.  Some potential changes that can be separated out:
1. "DEBUG_ERROR/DEBUG_INFO"
2. The change related to the PciPlatform/PciOverride invocation can also be separated out and it can be in a patch before any changes to implement the features.
3. The change that splits the original StartPciDevicesOnBridge() to RegisterPciDevicesOnBridge() and StartPciRootPortsOnBridge(). This change can be separated out as a patch before any changes to implement the features.


Some other comments:
1. CheckPciPlatformProtocolInstall(): better to rename to IsPciPlatformAvailable(). "Check" doesn't tell how to interpret the return result. "Is" does.
2. GetPciPlatformProtocol(): better to rename to InitializePciPlatform ().
3. Why the type cast is needed in below code? If it is because PciPlatform2 protocol reuses the prototype of GetPciRom defined for PciPlatform protocol, I suggest you define GetPciRom for PciPlatform2. Type redefinition seems a duplication. But below type-cast is more annoyed.

    Status = mPciPlatformProtocol2->GetPciRom (
                                      (EFI_PCI_PLATFORM_PROTOCOL*)mPciPlatformProtocol2,
                                      PciIoDevice->Handle,
                                      &PlatformOpRomBuffer,
                                      &PlatformOpRomSize
                                      );

4. Please run ECC tool and fix all coding style issue
5. I don't quite understand what *primary* PCI root port is. So I don't quite understand what RecordPciRootPortBridges() does.

Thanks,
Ray

> -----Original Message-----
> From: Javeed, Ashraf <ashraf.javeed@intel.com>
> Sent: Monday, September 23, 2019 10:21 PM
> To: devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>;
> Ni, Ray <ray.ni@intel.com>
> Subject: [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH] PciBusDxe: New PCI
> features Max_Payload_Size, Max_Read_Req_Size
> 
> REF: https://bugzilla.tianocore.org/show_bug.cgi?id=2194
> 
> The EDK2 Kernel PciBusDxe driver is enhanced to enable the configuration
> of PCI features like Max_Payload_Size and Max_Read_Req_Size.
> 
> Max_Payload_Size:- The PCI Device Control register provides this feature
> register field which controls the maximum data packet (TLP) size that a
> PCI device should maintain as a requester. The PCI Bus driver is required
> to maintain a highest common value supported by all the PCI devices in a
> PCIe hierarchy, especially in case of isochronous applications.
> 
> Max_Read_Req_Size:- The PCI Device Control register provides this feature
> register field which controls the maximum memory read request size that a
> PCI device should maintain as a requester. The PCI Bus driver is required
> to maintain a common value, same as Max_Payload_Size, in case of
> isochronous applications only; or else, it should maintain the user
> requested value uniformly in a PCIe hierarchy (PCI root port and its
> downstream devices).
> 
> The PCI Base Specification 4 Revision 1 contains detailed information
> about these features. The EDK2 PCI Bus driver needs to enable the
> configuration of these features as per the PCI Base specification.
> 
> The EDK2 PCI Bus driver also needs to take the PCI device-specific
> platform policy into the consideration while programming these features;
> thus the code changes to support these, is explicitly dependent on the
> new PCI Platform Protocol interface definition defined in the below
> record:-
> https://bugzilla.tianocore.org/show_bug.cgi?id=1954
> 
> Signed-off-by: Ashraf Javeed <ashraf.javeed@intel.com>
> Cc: Jian J Wang <jian.j.wang@intel.com>
> Cc: Hao A Wu <hao.a.wu@intel.com>
> Cc: Ray Ni <ray.ni@intel.com>
> ---
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c               |   23 ++------------
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h               |   14 ++++++++-
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf          |    9 +++++-
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c     |  229
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> ++++++++++++++++++++++++++++------------------------------------------------
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c        |  139
> ++++++++++++++++++++--------------------------------------------------------------
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c |   34
> ++++++++++++--------
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c    | 1601
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h    |  201
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> ++
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c   |  565
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h   |  193
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c   |   15 +--------
>  MdeModulePkg/MdeModulePkg.dec                         |   10 ++++++
>  12 files changed, 2797 insertions(+), 236 deletions(-)
> 
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c
> index b020ce50ce..2503b298f4 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c
> @@ -8,7 +8,7 @@
>    PCI Root Bridges. So it means platform needs install PCI Root Bridge IO
> protocol for each
> 
>    PCI Root Bus and install PCI Host Bridge Resource Allocation Protocol.
> 
> 
> 
> -Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
> 
> +Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
> 
>  SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> 
> 
>  **/
> 
> @@ -34,8 +34,6 @@ BOOLEAN                                       gFullEnumeration     = TRUE;
>  UINT64                                        gAllOne              = 0xFFFFFFFFFFFFFFFFULL;
> 
>  UINT64                                        gAllZero             = 0;
> 
> 
> 
> -EFI_PCI_PLATFORM_PROTOCOL                     *gPciPlatformProtocol;
> 
> -EFI_PCI_OVERRIDE_PROTOCOL                     *gPciOverrideProtocol;
> 
>  EDKII_IOMMU_PROTOCOL                          *mIoMmuProtocol;
> 
> 
> 
> 
> 
> @@ -266,24 +264,7 @@ PciBusDriverBindingStart (
>    // If PCI Platform protocol is available, get it now.
> 
>    // If the platform implements this, it must be installed before BDS phase
> 
>    //
> 
> -  gPciPlatformProtocol = NULL;
> 
> -  gBS->LocateProtocol (
> 
> -        &gEfiPciPlatformProtocolGuid,
> 
> -        NULL,
> 
> -        (VOID **) &gPciPlatformProtocol
> 
> -        );
> 
> -
> 
> -  //
> 
> -  // If PCI Platform protocol doesn't exist, try to Pci Override Protocol.
> 
> -  //
> 
> -  if (gPciPlatformProtocol == NULL) {
> 
> -    gPciOverrideProtocol = NULL;
> 
> -    gBS->LocateProtocol (
> 
> -          &gEfiPciOverrideProtocolGuid,
> 
> -          NULL,
> 
> -          (VOID **) &gPciOverrideProtocol
> 
> -          );
> 
> -  }
> 
> +  GetPciPlatformProtocol ();
> 
> 
> 
>    if (mIoMmuProtocol == NULL) {
> 
>      gBS->LocateProtocol (
> 
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> index 504a1b1c12..7955bf8a26 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> @@ -27,6 +27,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
>  #include <Protocol/PciOverride.h>
> 
>  #include <Protocol/PciEnumerationComplete.h>
> 
>  #include <Protocol/IoMmu.h>
> 
> +#include <Protocol/PciPlatform2.h>
> 
> +#include <Protocol/PciOverride2.h>
> 
> 
> 
>  #include <Library/DebugLib.h>
> 
>  #include <Library/UefiDriverEntryPoint.h>
> 
> @@ -79,6 +81,7 @@ typedef enum {
>  #include "PciPowerManagement.h"
> 
>  #include "PciHotPlugSupport.h"
> 
>  #include "PciLib.h"
> 
> +#include "PciFeatureSupport.h"
> 
> 
> 
>  #define VGABASE1  0x3B0
> 
>  #define VGALIMIT1 0x3BB
> 
> @@ -263,9 +266,13 @@ struct _PCI_IO_DEVICE {
> 
> 
>    BOOLEAN                                   IsPciExp;
> 
>    //
> 
> -  // For SR-IOV
> 
> +  // For PCI Express Capability List Structure
> 
>    //
> 
>    UINT8                                     PciExpressCapabilityOffset;
> 
> +  PCI_CAPABILITY_PCIEXP                     PciExpStruct;
> 
> +  //
> 
> +  // For SR-IOV
> 
> +  //
> 
>    UINT32                                    AriCapabilityOffset;
> 
>    UINT32                                    SrIovCapabilityOffset;
> 
>    UINT32                                    MrIovCapabilityOffset;
> 
> @@ -279,6 +286,11 @@ struct _PCI_IO_DEVICE {
>    // This field is used to support this case.
> 
>    //
> 
>    UINT16                                    BridgeIoAlignment;
> 
> +  //
> 
> +  // Other PCI features setup flags
> 
> +  //
> 
> +  UINT8                                     SetupMPS;
> 
> +  UINT8                                     SetupMRRS;
> 
>  };
> 
> 
> 
>  #define PCI_IO_DEVICE_FROM_PCI_IO_THIS(a) \
> 
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
> index 05c22025b8..13768d7ded 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
> @@ -2,7 +2,7 @@
>  #  The PCI bus driver will probe all PCI devices and allocate MMIO and IO
> space for these devices.
> 
>  #  Please use PCD feature flag PcdPciBusHotplugDeviceSupport to enable
> hot plug supporting.
> 
>  #
> 
> -#  Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
> 
> +#  Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
> 
>  #
> 
>  #  SPDX-License-Identifier: BSD-2-Clause-Patent
> 
>  #
> 
> @@ -57,6 +57,10 @@
>    PciCommand.h
> 
>    PciIo.h
> 
>    PciBus.h
> 
> +  PciFeatureSupport.c
> 
> +  PciFeatureSupport.h
> 
> +  PciPlatformSupport.c
> 
> +  PciPlatformSupport.h
> 
> 
> 
>  [Packages]
> 
>    MdePkg/MdePkg.dec
> 
> @@ -91,6 +95,8 @@
>    gEfiLoadFile2ProtocolGuid                       ## SOMETIMES_PRODUCES
> 
>    gEdkiiIoMmuProtocolGuid                         ## SOMETIMES_CONSUMES
> 
>    gEfiLoadedImageDevicePathProtocolGuid           ## CONSUMES
> 
> +  gEfiPciPlatformProtocol2Guid                     ## SOMETIMES_CONSUMES
> 
> +  gEfiPciOverrideProtocol2Guid                     ## SOMETIMES_CONSUMES
> 
> 
> 
>  [FeaturePcd]
> 
>    gEfiMdeModulePkgTokenSpaceGuid.PcdPciBusHotplugDeviceSupport      ##
> CONSUMES
> 
> @@ -104,6 +110,7 @@
>    gEfiMdeModulePkgTokenSpaceGuid.PcdAriSupport                  ## CONSUMES
> 
>    gEfiMdeModulePkgTokenSpaceGuid.PcdMrIovSupport                ##
> CONSUMES
> 
>    gEfiMdeModulePkgTokenSpaceGuid.PcdPciDisableBusEnumeration    ##
> SOMETIMES_CONSUMES
> 
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdOtherPciFeatures                    ##
> CONSUMES
> 
> 
> 
>  [UserExtensions.TianoCore."ExtraFiles"]
> 
>    PciBusDxeExtra.uni
> 
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
> index b7832c6970..0f76ab1cd5 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
> @@ -170,6 +170,8 @@ DestroyRootBridgeByHandle (
> 
> 
>      if (Temp->Handle == Controller) {
> 
> 
> 
> +      DestroyRootBridgePciFeaturesConfigCompletionList ( Temp);
> 
> +
> 
>        RemoveEntryList (CurrentLink);
> 
> 
> 
>        DestroyPciDeviceTree (Temp);
> 
> @@ -208,8 +210,6 @@ RegisterPciDevice (
>    )
> 
>  {
> 
>    EFI_STATUS          Status;
> 
> -  VOID                *PlatformOpRomBuffer;
> 
> -  UINTN               PlatformOpRomSize;
> 
>    EFI_PCI_IO_PROTOCOL *PciIo;
> 
>    UINT8               Data8;
> 
>    BOOLEAN             HasEfiImage;
> 
> @@ -244,49 +244,13 @@ RegisterPciDevice (
>      //
> 
>      // Get the OpRom provided by platform
> 
>      //
> 
> -    if (gPciPlatformProtocol != NULL) {
> 
> -      Status = gPciPlatformProtocol->GetPciRom (
> 
> -                                       gPciPlatformProtocol,
> 
> -                                       PciIoDevice->Handle,
> 
> -                                       &PlatformOpRomBuffer,
> 
> -                                       &PlatformOpRomSize
> 
> -                                       );
> 
> -      if (!EFI_ERROR (Status)) {
> 
> -        PciIoDevice->EmbeddedRom    = FALSE;
> 
> -        PciIoDevice->RomSize        = (UINT32) PlatformOpRomSize;
> 
> -        PciIoDevice->PciIo.RomSize  = PlatformOpRomSize;
> 
> -        PciIoDevice->PciIo.RomImage = PlatformOpRomBuffer;
> 
> -        //
> 
> -        // For OpROM read from gPciPlatformProtocol:
> 
> -        // Add the Rom Image to internal database for later PCI light
> enumeration
> 
> -        //
> 
> -        PciRomAddImageMapping (
> 
> -          NULL,
> 
> -          PciIoDevice->PciRootBridgeIo->SegmentNumber,
> 
> -          PciIoDevice->BusNumber,
> 
> -          PciIoDevice->DeviceNumber,
> 
> -          PciIoDevice->FunctionNumber,
> 
> -          PciIoDevice->PciIo.RomImage,
> 
> -          PciIoDevice->PciIo.RomSize
> 
> -          );
> 
> -      }
> 
> -    } else if (gPciOverrideProtocol != NULL) {
> 
> -      Status = gPciOverrideProtocol->GetPciRom (
> 
> -                                       gPciOverrideProtocol,
> 
> -                                       PciIoDevice->Handle,
> 
> -                                       &PlatformOpRomBuffer,
> 
> -                                       &PlatformOpRomSize
> 
> -                                       );
> 
> -      if (!EFI_ERROR (Status)) {
> 
> -        PciIoDevice->EmbeddedRom    = FALSE;
> 
> -        PciIoDevice->RomSize        = (UINT32) PlatformOpRomSize;
> 
> -        PciIoDevice->PciIo.RomSize  = PlatformOpRomSize;
> 
> -        PciIoDevice->PciIo.RomImage = PlatformOpRomBuffer;
> 
> -        //
> 
> -        // For OpROM read from gPciOverrideProtocol:
> 
> -        // Add the Rom Image to internal database for later PCI light
> enumeration
> 
> -        //
> 
> -        PciRomAddImageMapping (
> 
> +    Status = GetPlatformPciOptionRom ( Controller, PciIoDevice);
> 
> +    if (!EFI_ERROR (Status)) {
> 
> +      //
> 
> +      // For OpROM read from the PCI Platform Protocol:
> 
> +      // Add the Rom Image to internal database for later PCI light
> enumeration
> 
> +      //
> 
> +      PciRomAddImageMapping (
> 
>            NULL,
> 
>            PciIoDevice->PciRootBridgeIo->SegmentNumber,
> 
>            PciIoDevice->BusNumber,
> 
> @@ -294,8 +258,7 @@ RegisterPciDevice (
>            PciIoDevice->FunctionNumber,
> 
>            PciIoDevice->PciIo.RomImage,
> 
>            PciIoDevice->PciIo.RomSize
> 
> -          );
> 
> -      }
> 
> +        );
> 
>      }
> 
>    }
> 
> 
> 
> @@ -597,7 +560,7 @@ DeRegisterPciDevice (
>  }
> 
> 
> 
>  /**
> 
> -  Start to manage the PCI device on the specified root bridge or PCI-PCI
> Bridge.
> 
> +  Start the PCI root Ports or PCI-PCI Bridge only.
> 
> 
> 
>    @param Controller          The root bridge handle.
> 
>    @param RootBridge          A pointer to the PCI_IO_DEVICE.
> 
> @@ -612,7 +575,82 @@ DeRegisterPciDevice (
> 
> 
>  **/
> 
>  EFI_STATUS
> 
> -StartPciDevicesOnBridge (
> 
> +StartPciRootPortsOnBridge (
> 
> +  IN EFI_HANDLE                          Controller,
> 
> +  IN PCI_IO_DEVICE                       *RootBridge
> 
> +  )
> 
> +
> 
> +{
> 
> +  PCI_IO_DEVICE             *PciIoDevice;
> 
> +  EFI_STATUS                Status;
> 
> +  LIST_ENTRY                *CurrentLink;
> 
> +  UINT64                    Supports;
> 
> +
> 
> +  PciIoDevice = NULL;
> 
> +  CurrentLink = RootBridge->ChildList.ForwardLink;
> 
> +
> 
> +  while (CurrentLink != NULL && CurrentLink != &RootBridge->ChildList) {
> 
> +
> 
> +    PciIoDevice = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
> 
> +
> 
> +    //
> 
> +    // check if the device has been assigned with required resource
> 
> +    // and registered
> 
> +    //
> 
> +    if (!PciIoDevice->Registered && !PciIoDevice->Allocated) {
> 
> +      return EFI_NOT_READY;
> 
> +    }
> 
> +
> 
> +    if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {
> 
> +      Status = StartPciRootPortsOnBridge (
> 
> +                 Controller,
> 
> +                 PciIoDevice
> 
> +                 );
> 
> +
> 
> +      PciIoDevice->PciIo.Attributes (
> 
> +                           &(PciIoDevice->PciIo),
> 
> +                           EfiPciIoAttributeOperationSupported,
> 
> +                           0,
> 
> +                           &Supports
> 
> +                         );
> 
> +      Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;
> 
> +      PciIoDevice->PciIo.Attributes (
> 
> +                           &(PciIoDevice->PciIo),
> 
> +                           EfiPciIoAttributeOperationEnable,
> 
> +                           Supports,
> 
> +                           NULL
> 
> +                         );
> 
> +
> 
> +    }
> 
> +
> 
> +    CurrentLink = CurrentLink->ForwardLink;
> 
> +  }
> 
> +
> 
> +  if (PciIoDevice == NULL) {
> 
> +    return EFI_NOT_FOUND;
> 
> +  } else {
> 
> +    return EFI_SUCCESS;
> 
> +  }
> 
> +}
> 
> +
> 
> +
> 
> +/**
> 
> +  Register to manage the PCI device on the specified root bridge or PCI-PCI
> Bridge.
> 
> +
> 
> +  @param Controller          The root bridge handle.
> 
> +  @param RootBridge          A pointer to the PCI_IO_DEVICE.
> 
> +  @param RemainingDevicePath A pointer to the
> EFI_DEVICE_PATH_PROTOCOL.
> 
> +  @param NumberOfChildren    Children number.
> 
> +  @param ChildHandleBuffer   A pointer to the child handle buffer.
> 
> +
> 
> +  @retval EFI_NOT_READY   Device is not allocated.
> 
> +  @retval EFI_UNSUPPORTED Device only support PCI-PCI bridge.
> 
> +  @retval EFI_NOT_FOUND   Can not find the specific device.
> 
> +  @retval EFI_SUCCESS     Success to start Pci devices on bridge.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +RegisterPciDevicesOnBridge (
> 
>    IN EFI_HANDLE                          Controller,
> 
>    IN PCI_IO_DEVICE                       *RootBridge,
> 
>    IN EFI_DEVICE_PATH_PROTOCOL            *RemainingDevicePath,
> 
> @@ -626,7 +664,6 @@ StartPciDevicesOnBridge (
>    EFI_DEVICE_PATH_PROTOCOL  *CurrentDevicePath;
> 
>    EFI_STATUS                Status;
> 
>    LIST_ENTRY                *CurrentLink;
> 
> -  UINT64                    Supports;
> 
> 
> 
>    PciIoDevice = NULL;
> 
>    CurrentLink = RootBridge->ChildList.ForwardLink;
> 
> @@ -681,7 +718,7 @@ StartPciDevicesOnBridge (
>        // If it is a PPB
> 
>        //
> 
>        if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {
> 
> -        Status = StartPciDevicesOnBridge (
> 
> +        Status = RegisterPciDevicesOnBridge (
> 
>                     Controller,
> 
>                     PciIoDevice,
> 
>                     CurrentDevicePath,
> 
> @@ -689,20 +726,6 @@ StartPciDevicesOnBridge (
>                     ChildHandleBuffer
> 
>                     );
> 
> 
> 
> -        PciIoDevice->PciIo.Attributes (
> 
> -                             &(PciIoDevice->PciIo),
> 
> -                             EfiPciIoAttributeOperationSupported,
> 
> -                             0,
> 
> -                             &Supports
> 
> -                             );
> 
> -        Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;
> 
> -        PciIoDevice->PciIo.Attributes (
> 
> -                             &(PciIoDevice->PciIo),
> 
> -                             EfiPciIoAttributeOperationEnable,
> 
> -                             Supports,
> 
> -                             NULL
> 
> -                             );
> 
> -
> 
>          return Status;
> 
>        } else {
> 
> 
> 
> @@ -733,28 +756,13 @@ StartPciDevicesOnBridge (
>        }
> 
> 
> 
>        if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {
> 
> -        Status = StartPciDevicesOnBridge (
> 
> +        Status = RegisterPciDevicesOnBridge (
> 
>                     Controller,
> 
>                     PciIoDevice,
> 
>                     RemainingDevicePath,
> 
>                     NumberOfChildren,
> 
>                     ChildHandleBuffer
> 
>                     );
> 
> -
> 
> -        PciIoDevice->PciIo.Attributes (
> 
> -                             &(PciIoDevice->PciIo),
> 
> -                             EfiPciIoAttributeOperationSupported,
> 
> -                             0,
> 
> -                             &Supports
> 
> -                             );
> 
> -        Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;
> 
> -        PciIoDevice->PciIo.Attributes (
> 
> -                             &(PciIoDevice->PciIo),
> 
> -                             EfiPciIoAttributeOperationEnable,
> 
> -                             Supports,
> 
> -                             NULL
> 
> -                             );
> 
> -
> 
>        }
> 
> 
> 
>        CurrentLink = CurrentLink->ForwardLink;
> 
> @@ -768,6 +776,65 @@ StartPciDevicesOnBridge (
>    }
> 
>  }
> 
> 
> 
> +/**
> 
> +  Start to manage the PCI device on the specified root bridge or PCI-PCI
> Bridge.
> 
> +
> 
> +  @param Controller          The root bridge handle.
> 
> +  @param RootBridge          A pointer to the PCI_IO_DEVICE.
> 
> +  @param RemainingDevicePath A pointer to the
> EFI_DEVICE_PATH_PROTOCOL.
> 
> +  @param NumberOfChildren    Children number.
> 
> +  @param ChildHandleBuffer   A pointer to the child handle buffer.
> 
> +
> 
> +  @retval EFI_NOT_READY   Device is not allocated.
> 
> +  @retval EFI_UNSUPPORTED Device only support PCI-PCI bridge.
> 
> +  @retval EFI_NOT_FOUND   Can not find the specific device.
> 
> +  @retval EFI_SUCCESS     Success to start Pci devices on bridge.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +StartPciDevicesOnBridge (
> 
> +  IN EFI_HANDLE                          Controller,
> 
> +  IN PCI_IO_DEVICE                       *RootBridge,
> 
> +  IN EFI_DEVICE_PATH_PROTOCOL            *RemainingDevicePath,
> 
> +  IN OUT UINT8                           *NumberOfChildren,
> 
> +  IN OUT EFI_HANDLE                      *ChildHandleBuffer
> 
> +  )
> 
> +
> 
> +{
> 
> +  EFI_STATUS                Status;
> 
> +
> 
> +  //
> 
> +  // first register all the PCI devices
> 
> +  //
> 
> +  Status = RegisterPciDevicesOnBridge (
> 
> +             Controller,
> 
> +             RootBridge,
> 
> +             RemainingDevicePath,
> 
> +             NumberOfChildren,
> 
> +             ChildHandleBuffer
> 
> +             );
> 
> +
> 
> +  if (EFI_ERROR (Status) == EFI_NOT_FOUND) {
> 
> +    return Status;
> 
> +  } else {
> 
> +    if ( CheckOtherPciFeaturesPcd ()) {
> 
> +      //
> 
> +      // the late configuration of PCI features
> 
> +      //
> 
> +      Status = EnumerateOtherPciFeatures (
> 
> +                  RootBridge
> 
> +                );
> 
> +    }
> 
> +    //
> 
> +    // finally start those PCI bridge port devices only
> 
> +    //
> 
> +    return StartPciRootPortsOnBridge (
> 
> +            Controller,
> 
> +            RootBridge
> 
> +            );
> 
> +  }
> 
> +}
> 
> +
> 
>  /**
> 
>    Start to manage all the PCI devices it found previously under
> 
>    the entire host bridge.
> 
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c
> index 8db1ebf8ec..0a56668380 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c
> @@ -1003,7 +1003,7 @@ PciHostBridgeAdjustAllocation (
>      Status = RejectPciDevice (PciResNode->PciDev);
> 
>      if (Status == EFI_SUCCESS) {
> 
>        DEBUG ((
> 
> -        EFI_D_ERROR,
> 
> +        DEBUG_ERROR,
> 
>          "PciBus: [%02x|%02x|%02x] was rejected due to resource
> confliction.\n",
> 
>          PciResNode->PciDev->BusNumber, PciResNode->PciDev-
> >DeviceNumber, PciResNode->PciDev->FunctionNumber
> 
>          ));
> 
> @@ -1746,7 +1746,7 @@ NotifyPhase (
> 
> 
>    HostBridgeHandle  = NULL;
> 
>    RootBridgeHandle  = NULL;
> 
> -  if (gPciPlatformProtocol != NULL) {
> 
> +  if ( CheckPciPlatformProtocolInstall()) {
> 
>      //
> 
>      // Get Host Bridge Handle.
> 
>      //
> 
> @@ -1770,42 +1770,11 @@ NotifyPhase (
>      //
> 
>      // Call PlatformPci::PlatformNotify() if the protocol is present.
> 
>      //
> 
> -    gPciPlatformProtocol->PlatformNotify (
> 
> -                            gPciPlatformProtocol,
> 
> -                            HostBridgeHandle,
> 
> -                            Phase,
> 
> -                            ChipsetEntry
> 
> -                            );
> 
> -  } else if (gPciOverrideProtocol != NULL){
> 
> -    //
> 
> -    // Get Host Bridge Handle.
> 
> -    //
> 
> -    PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle);
> 
> -
> 
> -    //
> 
> -    // Get the rootbridge Io protocol to find the host bridge handle
> 
> -    //
> 
> -    Status = gBS->HandleProtocol (
> 
> -                    RootBridgeHandle,
> 
> -                    &gEfiPciRootBridgeIoProtocolGuid,
> 
> -                    (VOID **) &PciRootBridgeIo
> 
> -                    );
> 
> -
> 
> -    if (EFI_ERROR (Status)) {
> 
> -      return EFI_NOT_FOUND;
> 
> -    }
> 
> -
> 
> -    HostBridgeHandle = PciRootBridgeIo->ParentHandle;
> 
> -
> 
> -    //
> 
> -    // Call PlatformPci::PhaseNotify() if the protocol is present.
> 
> -    //
> 
> -    gPciOverrideProtocol->PlatformNotify (
> 
> -                            gPciOverrideProtocol,
> 
> -                            HostBridgeHandle,
> 
> -                            Phase,
> 
> -                            ChipsetEntry
> 
> -                            );
> 
> +    PciPlatformNotifyPhase (
> 
> +        HostBridgeHandle,
> 
> +        Phase,
> 
> +        ChipsetEntry
> 
> +        );
> 
>    }
> 
> 
> 
>    Status = PciResAlloc->NotifyPhase (
> 
> @@ -1813,27 +1782,15 @@ NotifyPhase (
>                            Phase
> 
>                            );
> 
> 
> 
> -  if (gPciPlatformProtocol != NULL) {
> 
> +  if ( CheckPciPlatformProtocolInstall()) {
> 
>      //
> 
>      // Call PlatformPci::PlatformNotify() if the protocol is present.
> 
>      //
> 
> -    gPciPlatformProtocol->PlatformNotify (
> 
> -                            gPciPlatformProtocol,
> 
> -                            HostBridgeHandle,
> 
> -                            Phase,
> 
> -                            ChipsetExit
> 
> -                            );
> 
> -
> 
> -  } else if (gPciOverrideProtocol != NULL) {
> 
> -    //
> 
> -    // Call PlatformPci::PhaseNotify() if the protocol is present.
> 
> -    //
> 
> -    gPciOverrideProtocol->PlatformNotify (
> 
> -                            gPciOverrideProtocol,
> 
> -                            HostBridgeHandle,
> 
> -                            Phase,
> 
> -                            ChipsetExit
> 
> -                            );
> 
> +    PciPlatformNotifyPhase (
> 
> +        HostBridgeHandle,
> 
> +        Phase,
> 
> +        ChipsetExit
> 
> +        );
> 
>    }
> 
> 
> 
>    return Status;
> 
> @@ -1914,31 +1871,16 @@ PreprocessController (
>    RootBridgePciAddress.Bus              = Bus;
> 
>    RootBridgePciAddress.ExtendedRegister = 0;
> 
> 
> 
> -  if (gPciPlatformProtocol != NULL) {
> 
> -    //
> 
> -    // Call PlatformPci::PrepController() if the protocol is present.
> 
> -    //
> 
> -    gPciPlatformProtocol->PlatformPrepController (
> 
> -                            gPciPlatformProtocol,
> 
> -                            HostBridgeHandle,
> 
> -                            RootBridgeHandle,
> 
> -                            RootBridgePciAddress,
> 
> -                            Phase,
> 
> -                            ChipsetEntry
> 
> -                            );
> 
> -  } else if (gPciOverrideProtocol != NULL) {
> 
> -    //
> 
> -    // Call PlatformPci::PrepController() if the protocol is present.
> 
> -    //
> 
> -    gPciOverrideProtocol->PlatformPrepController (
> 
> -                            gPciOverrideProtocol,
> 
> -                            HostBridgeHandle,
> 
> -                            RootBridgeHandle,
> 
> -                            RootBridgePciAddress,
> 
> -                            Phase,
> 
> -                            ChipsetEntry
> 
> -                            );
> 
> -  }
> 
> +  //
> 
> +  // Call PlatformPci::PrepController() if the protocol is present.
> 
> +  //
> 
> +  PciPlatformPreprocessController (
> 
> +      HostBridgeHandle,
> 
> +      RootBridgeHandle,
> 
> +      RootBridgePciAddress,
> 
> +      Phase,
> 
> +      ChipsetEntry
> 
> +    );
> 
> 
> 
>    Status = PciResAlloc->PreprocessController (
> 
>                            PciResAlloc,
> 
> @@ -1947,31 +1889,16 @@ PreprocessController (
>                            Phase
> 
>                            );
> 
> 
> 
> -  if (gPciPlatformProtocol != NULL) {
> 
> -    //
> 
> -    // Call PlatformPci::PrepController() if the protocol is present.
> 
> -    //
> 
> -    gPciPlatformProtocol->PlatformPrepController (
> 
> -                            gPciPlatformProtocol,
> 
> -                            HostBridgeHandle,
> 
> -                            RootBridgeHandle,
> 
> -                            RootBridgePciAddress,
> 
> -                            Phase,
> 
> -                            ChipsetExit
> 
> -                            );
> 
> -  } else if (gPciOverrideProtocol != NULL) {
> 
> -    //
> 
> -    // Call PlatformPci::PrepController() if the protocol is present.
> 
> -    //
> 
> -    gPciOverrideProtocol->PlatformPrepController (
> 
> -                            gPciOverrideProtocol,
> 
> -                            HostBridgeHandle,
> 
> -                            RootBridgeHandle,
> 
> -                            RootBridgePciAddress,
> 
> -                            Phase,
> 
> -                            ChipsetExit
> 
> -                            );
> 
> -  }
> 
> +  //
> 
> +  // Call PlatformPci::PrepController() if the protocol is present.
> 
> +  //
> 
> +  PciPlatformPreprocessController (
> 
> +      HostBridgeHandle,
> 
> +      RootBridgeHandle,
> 
> +      RootBridgePciAddress,
> 
> +      Phase,
> 
> +      ChipsetExit
> 
> +    );
> 
> 
> 
>    return EFI_SUCCESS;
> 
>  }
> 
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
> index c7eafff593..2343702154 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
> @@ -230,7 +230,7 @@ PciSearchDevice (
>    PciIoDevice = NULL;
> 
> 
> 
>    DEBUG ((
> 
> -    EFI_D_INFO,
> 
> +    DEBUG_INFO,
> 
>      "PciBus: Discovered %s @ [%02x|%02x|%02x]\n",
> 
>      IS_PCI_BRIDGE (Pci) ?     L"PPB" :
> 
>      IS_CARDBUS_BRIDGE (Pci) ? L"P2C" :
> 
> @@ -397,7 +397,7 @@ DumpPpbPaddingResource (
> 
> 
>      if ((Type != PciBarTypeUnknown) && ((ResourceType ==
> PciBarTypeUnknown) || (ResourceType == Type))) {
> 
>        DEBUG ((
> 
> -        EFI_D_INFO,
> 
> +        DEBUG_INFO,
> 
>          "   Padding: Type = %s; Alignment = 0x%lx;\tLength = 0x%lx\n",
> 
>          mBarTypeStr[Type], Descriptor->AddrRangeMax, Descriptor->AddrLen
> 
>          ));
> 
> @@ -424,7 +424,7 @@ DumpPciBars (
>      }
> 
> 
> 
>      DEBUG ((
> 
> -      EFI_D_INFO,
> 
> +      DEBUG_INFO,
> 
>        "   BAR[%d]: Type = %s; Alignment = 0x%lx;\tLength = 0x%lx;\tOffset =
> 0x%02x\n",
> 
>        Index, mBarTypeStr[MIN (PciIoDevice->PciBar[Index].BarType,
> PciBarTypeMaxType)],
> 
>        PciIoDevice->PciBar[Index].Alignment, PciIoDevice-
> >PciBar[Index].Length, PciIoDevice->PciBar[Index].Offset
> 
> @@ -437,13 +437,13 @@ DumpPciBars (
>      }
> 
> 
> 
>      DEBUG ((
> 
> -      EFI_D_INFO,
> 
> +      DEBUG_INFO,
> 
>        " VFBAR[%d]: Type = %s; Alignment = 0x%lx;\tLength = 0x%lx;\tOffset =
> 0x%02x\n",
> 
>        Index, mBarTypeStr[MIN (PciIoDevice->VfPciBar[Index].BarType,
> PciBarTypeMaxType)],
> 
>        PciIoDevice->VfPciBar[Index].Alignment, PciIoDevice-
> >VfPciBar[Index].Length, PciIoDevice->VfPciBar[Index].Offset
> 
>        ));
> 
>    }
> 
> -  DEBUG ((EFI_D_INFO, "\n"));
> 
> +  DEBUG ((DEBUG_INFO, "\n"));
> 
>  }
> 
> 
> 
>  /**
> 
> @@ -1903,7 +1903,7 @@ PciParseBar (
>        // Fix the length to support some special 64 bit BAR
> 
>        //
> 
>        if (Value == 0) {
> 
> -        DEBUG ((EFI_D_INFO, "[PciBus]BAR probing for upper 32bit of MEM64
> BAR returns 0, change to 0xFFFFFFFF.\n"));
> 
> +        DEBUG ((DEBUG_INFO, "[PciBus]BAR probing for upper 32bit of MEM64
> BAR returns 0, change to 0xFFFFFFFF.\n"));
> 
>          Value = (UINT32) -1;
> 
>        } else {
> 
>          Value |= ((UINT32)(-1) << HighBitSet32 (Value));
> 
> @@ -2153,7 +2153,17 @@ CreatePciIoDevice (
>               NULL
> 
>               );
> 
>    if (!EFI_ERROR (Status)) {
> 
> -    PciIoDevice->IsPciExp = TRUE;
> 
> +  PciIoDevice->IsPciExp = TRUE;
> 
> +    //
> 
> +    // read the PCI device's entire PCI Express Capability structure
> 
> +    //
> 
> +    PciIo->Pci.Read (
> 
> +                  PciIo,
> 
> +                  EfiPciIoWidthUint8,
> 
> +                  PciIoDevice->PciExpressCapabilityOffset,
> 
> +                  sizeof (PCI_CAPABILITY_PCIEXP) / sizeof (UINT8),
> 
> +                  &PciIoDevice->PciExpStruct
> 
> +                );
> 
>    }
> 
> 
> 
>    if (PcdGetBool (PcdAriSupport)) {
> 
> @@ -2206,7 +2216,7 @@ CreatePciIoDevice (
>                                &Data32
> 
>                                );
> 
>            DEBUG ((
> 
> -            EFI_D_INFO,
> 
> +            DEBUG_INFO,
> 
>              " ARI: forwarding enabled for PPB[%02x:%02x:%02x]\n",
> 
>              Bridge->BusNumber,
> 
>              Bridge->DeviceNumber,
> 
> @@ -2215,7 +2225,7 @@ CreatePciIoDevice (
>          }
> 
>        }
> 
> 
> 
> -      DEBUG ((EFI_D_INFO, " ARI: CapOffset = 0x%x\n", PciIoDevice-
> >AriCapabilityOffset));
> 
> +      DEBUG ((DEBUG_INFO, " ARI: CapOffset = 0x%x\n", PciIoDevice-
> >AriCapabilityOffset));
> 
>      }
> 
>    }
> 
> 
> 
> @@ -2325,12 +2335,12 @@ CreatePciIoDevice (
>        PciIoDevice->ReservedBusNum = (UINT16)(EFI_PCI_BUS_OF_RID (LastVF)
> - Bus + 1);
> 
> 
> 
>        DEBUG ((
> 
> -        EFI_D_INFO,
> 
> +        DEBUG_INFO,
> 
>          " SR-IOV: SupportedPageSize = 0x%x; SystemPageSize = 0x%x;
> FirstVFOffset = 0x%x;\n",
> 
>          SupportedPageSize, PciIoDevice->SystemPageSize >> 12, FirstVFOffset
> 
>          ));
> 
>        DEBUG ((
> 
> -        EFI_D_INFO,
> 
> +        DEBUG_INFO,
> 
>          "         InitialVFs = 0x%x; ReservedBusNum = 0x%x; CapOffset = 0x%x\n",
> 
>          PciIoDevice->InitialVFs, PciIoDevice->ReservedBusNum, PciIoDevice-
> >SrIovCapabilityOffset
> 
>          ));
> 
> @@ -2345,7 +2355,7 @@ CreatePciIoDevice (
>                 NULL
> 
>                 );
> 
>      if (!EFI_ERROR (Status)) {
> 
> -      DEBUG ((EFI_D_INFO, " MR-IOV: CapOffset = 0x%x\n", PciIoDevice-
> >MrIovCapabilityOffset));
> 
> +      DEBUG ((DEBUG_INFO, " MR-IOV: CapOffset = 0x%x\n", PciIoDevice-
> >MrIovCapabilityOffset));
> 
>      }
> 
>    }
> 
> 
> 
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> new file mode 100644
> index 0000000000..0819da6536
> --- /dev/null
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> @@ -0,0 +1,1601 @@
> +/** @file
> 
> +  PCI standard feature support functions implementation for PCI Bus
> module..
> 
> +
> 
> +Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> 
> +SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> +
> 
> +**/
> 
> +
> 
> +#include "PciFeatureSupport.h"
> 
> +
> 
> +/**
> 
> +  A gobal pointer to PRIMARY_ROOT_PORT_NODE buffer to track all the
> primary physical
> 
> +  PCI Root Ports (PCI Controllers) for a given PCI Root Bridge instance while
> 
> +  enumerating to configure the PCI features
> 
> +**/
> 
> +PRIMARY_ROOT_PORT_NODE                      *mPrimaryRootPortList;
> 
> +
> 
> +/**
> 
> +  A gobal pointer to OTHER_PCI_FEATURES_CONFIGURATION_TABLE buffer
> all the PCI
> 
> +  Feature configuration Table nodes to pair against each of the
> PRIMARY_ROOT_PORT_NODE
> 
> +  buffer nodes. Each node of these is used to align all the PCI devices
> originating
> 
> +  from the PCI Root Port devices of a PCI Root Bridge instance
> 
> +**/
> 
> +OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> *mPciFeaturesConfigurationTableInstances;
> 
> +
> 
> +/**
> 
> +  A global pointer to PCI_FEATURE_CONFIGURATION_COMPLETION_LIST,
> which stores all
> 
> +  the PCI Root Bridge instances that are enumerated for the other PCI
> features,
> 
> +  like MaxPayloadSize & MaxReadReqSize; during the the Start() interface of
> the
> 
> +  driver binding protocol. The records pointed by this pointer would be
> destroyed
> 
> +  when the DXE core invokes the Stop() interface.
> 
> +**/
> 
> +PCI_FEATURE_CONFIGURATION_COMPLETION_LIST
> *mPciFeaturesConfigurationCompletionList = NULL;
> 
> +
> 
> +/**
> 
> +  Main routine to indicate platform selection of any of the other PCI features
> 
> +  to be configured by this driver
> 
> +
> 
> +  @retval TRUE    platform has selected the other PCI features to be
> configured
> 
> +          FALSE   platform has not selected any of the other PCI features
> 
> +**/
> 
> +BOOLEAN
> 
> +CheckOtherPciFeaturesPcd (
> 
> +  )
> 
> +{
> 
> +  return PcdGet32 ( PcdOtherPciFeatures) ? TRUE : FALSE;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Main routine to indicate whether the platform has selected the
> Max_Payload_Size
> 
> +  PCI feature to be configured by this driver
> 
> +
> 
> +  @retval TRUE    platform has selected the Max_Payload_Size to be
> configured
> 
> +          FALSE   platform has not selected this feature
> 
> +**/
> 
> +BOOLEAN
> 
> +SetupMaxPayloadSize (
> 
> +  )
> 
> +{
> 
> +  return (PcdGet32 ( PcdOtherPciFeatures) &
> PCI_FEATURE_SUPPORT_FLAG_MPS) ? TRUE : FALSE;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Main routine to indicate whether the platform has selected the
> Max_Read_Req_Size
> 
> +  PCI feature to be configured by this driver
> 
> +
> 
> +  @retval TRUE    platform has selected the Max_Read_Req_Size to be
> configured
> 
> +          FALSE   platform has not selected this feature
> 
> +**/
> 
> +BOOLEAN
> 
> +SetupMaxReadReqSize (
> 
> +  )
> 
> +{
> 
> +  return (PcdGet32 ( PcdOtherPciFeatures) &
> PCI_FEATURE_SUPPORT_FLAG_MRRS) ? TRUE : FALSE;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Helper routine which determines whether the given PCI Root Bridge
> instance
> 
> +  record already exist. This routine shall help avoid duplicate record creation
> 
> +  in case of re-enumeration of PCI configuation features.
> 
> +
> 
> +  @param  RootBridge              A pointer to the PCI_IO_DEVICE for the Root
> Bridge
> 
> +  @param  PciFeatureConfigRecord  A pointer to a pointer for type
> 
> +                                  PCI_FEATURE_CONFIGURATION_COMPLETION_LIST
> 
> +                                  record, Use to return the specific record.
> 
> +
> 
> +  @retval TRUE                    Record already exist
> 
> +          FALSE                   Record does not exist for the given PCI Root Bridge
> 
> +**/
> 
> +BOOLEAN
> 
> +CheckPciFeatureConfigurationRecordExist (
> 
> +  IN  PCI_IO_DEVICE                             *RootBridge,
> 
> +  OUT PCI_FEATURE_CONFIGURATION_COMPLETION_LIST
> **PciFeatureConfigRecord
> 
> +  )
> 
> +{
> 
> +  LIST_ENTRY                                  *Link;
> 
> +  PCI_FEATURE_CONFIGURATION_COMPLETION_LIST   *Temp;
> 
> +
> 
> +  if ( mPciFeaturesConfigurationCompletionList) {
> 
> +    Link = &mPciFeaturesConfigurationCompletionList->RootBridgeLink;
> 
> +
> 
> +    do {
> 
> +      Temp =
> PCI_FEATURE_CONFIGURATION_COMPLETION_LIST_FROM_LINK (Link);
> 
> +      if ( Temp->RootBridgeHandle == RootBridge->Handle) {
> 
> +        *PciFeatureConfigRecord = Temp;
> 
> +        return TRUE;
> 
> +      }
> 
> +      Link = Link->ForwardLink;
> 
> +    } while (Link != &mPciFeaturesConfigurationCompletionList-
> >RootBridgeLink);
> 
> +  }
> 
> +  //
> 
> +  // not found on the PCI feature configuration completion list
> 
> +  //
> 
> +  *PciFeatureConfigRecord = NULL;
> 
> +  return FALSE;
> 
> +}
> 
> +
> 
> +/**
> 
> +  This routine is primarily to avoid multiple configuration of PCI features
> 
> +  to the same PCI Root Bridge due to EDK2 core's ConnectController calls on
> 
> +  all the EFI handles. This routine also provide re-enumeration of the PCI
> 
> +  features on the same PCI Root Bridge based on the policy of
> ReEnumeratePciFeatureConfiguration
> 
> +  of the PCI_FEATURE_CONFIGURATION_COMPLETION_LIST.
> 
> +
> 
> +  @param  RootBridge              A pointer to the PCI_IO_DEVICE for the Root
> Bridge
> 
> +
> 
> +  @retval TRUE                    PCI Feature configuration required for the PCI
> 
> +                                  Root Bridge
> 
> +          FALSE                   PCI Feature configuration is not required to be
> 
> +                                  re-enumerated for the PCI Root Bridge
> 
> +**/
> 
> +BOOLEAN
> 
> +CheckPciFeaturesConfigurationRequired (
> 
> +  IN PCI_IO_DEVICE          *RootBridge
> 
> +  )
> 
> +{
> 
> +  LIST_ENTRY                                  *Link;
> 
> +  PCI_FEATURE_CONFIGURATION_COMPLETION_LIST   *Temp;
> 
> +
> 
> +  if ( mPciFeaturesConfigurationCompletionList) {
> 
> +    Link = &mPciFeaturesConfigurationCompletionList->RootBridgeLink;
> 
> +
> 
> +    do {
> 
> +      Temp =
> PCI_FEATURE_CONFIGURATION_COMPLETION_LIST_FROM_LINK (Link);
> 
> +      if ( Temp->RootBridgeHandle == RootBridge->Handle) {
> 
> +        return Temp->ReEnumeratePciFeatureConfiguration;
> 
> +      }
> 
> +      Link = Link->ForwardLink;
> 
> +    } while (Link != &mPciFeaturesConfigurationCompletionList-
> >RootBridgeLink);
> 
> +  }
> 
> +  //
> 
> +  // not found on the PCI feature configuration completion list, return as
> required
> 
> +  //
> 
> +  return TRUE;
> 
> +}
> 
> +
> 
> +/**
> 
> +  This routine finds the duplicate record if exist and assigns the re-
> enumeration
> 
> +  requirement flag, as passed as input. It creates new record for the PCI
> Root
> 
> +  Bridge and appends the list after updating its re-enumeration flag.
> 
> +
> 
> +  @param  RootBridge            A pointer to PCI_IO_DEVICE of the Root Bridge
> 
> +  @param  ReEnumerationRequired A BOOLEAN for recording the re-
> enumeration requirement
> 
> +
> 
> +  @retval EFI_SUCCESS           new record inserted into the list or updated the
> 
> +                                existing record
> 
> +          EFI_INVALID_PARAMETER Unexpected error as
> CheckPciFeatureConfigurationRecordExist
> 
> +                                reports as record exist but does not return its pointer
> 
> +          EFI_OUT_OF_RESOURCES  Not able to create PCI features configuratin
> complete
> 
> +                                record for the RootBridge
> 
> +**/
> 
> +EFI_STATUS
> 
> +AddRootBridgeInPciFeaturesConfigCompletionList (
> 
> +  IN PCI_IO_DEVICE          *RootBridge,
> 
> +  IN BOOLEAN                ReEnumerationRequired
> 
> +  )
> 
> +{
> 
> +  PCI_FEATURE_CONFIGURATION_COMPLETION_LIST   *Temp;
> 
> +
> 
> +  if ( CheckPciFeatureConfigurationRecordExist ( RootBridge, &Temp)) {
> 
> +    //
> 
> +    // this PCI Root Bridge record already exist; it may have been re-
> enumerated
> 
> +    // hence just update its enumeration required flag again to exit
> 
> +    //
> 
> +    if ( Temp) {
> 
> +      Temp->ReEnumeratePciFeatureConfiguration  =
> ReEnumerationRequired;
> 
> +      return EFI_SUCCESS;
> 
> +    } else {
> 
> +      //
> 
> +      // PCI feature configuration complete record reported as exist and no
> 
> +      // record pointer returned
> 
> +      //
> 
> +      return EFI_INVALID_PARAMETER;
> 
> +    }
> 
> +
> 
> +  } else {
> 
> +
> 
> +    Temp = AllocateZeroPool ( sizeof
> ( PCI_FEATURE_CONFIGURATION_COMPLETION_LIST));
> 
> +    if ( !Temp) {
> 
> +      return EFI_OUT_OF_RESOURCES;
> 
> +    }
> 
> +    Temp->Signature                           =
> PCI_FEATURE_CONFIGURATION_SIGNATURE;
> 
> +    Temp->RootBridgeHandle                    = RootBridge->Handle;
> 
> +    Temp->ReEnumeratePciFeatureConfiguration  = ReEnumerationRequired;
> 
> +    if ( mPciFeaturesConfigurationCompletionList) {
> 
> +      InsertTailList ( &mPciFeaturesConfigurationCompletionList-
> >RootBridgeLink,
> 
> +                       &Temp->RootBridgeLink);
> 
> +    } else {
> 
> +      //
> 
> +      // init the very first node of the Root Bridge
> 
> +      //
> 
> +      mPciFeaturesConfigurationCompletionList = Temp;
> 
> +      InitializeListHead ( &mPciFeaturesConfigurationCompletionList-
> >RootBridgeLink);
> 
> +    }
> 
> +  }
> 
> +  return EFI_SUCCESS;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Free up memory alloted for the primary physical PCI Root ports of the PCI
> Root
> 
> +  Bridge instance. Free up all the nodes of type
> PRIMARY_ROOT_PORT_NODE.
> 
> +**/
> 
> +VOID
> 
> +DestroyPrimaryRootPortNodes ()
> 
> +{
> 
> +  LIST_ENTRY                *Link;
> 
> +  PRIMARY_ROOT_PORT_NODE    *Temp;
> 
> +
> 
> +  if ( mPrimaryRootPortList) {
> 
> +    Link = &mPrimaryRootPortList->NeighborRootPort;
> 
> +
> 
> +    if ( IsListEmpty ( Link)) {
> 
> +      FreePool ( mPrimaryRootPortList);
> 
> +    } else {
> 
> +      do {
> 
> +        if ( Link->ForwardLink != &mPrimaryRootPortList->NeighborRootPort) {
> 
> +          Link = Link->ForwardLink;
> 
> +        }
> 
> +        Temp = PRIMARY_ROOT_PORT_NODE_FROM_LINK ( Link);
> 
> +        Link = RemoveEntryList ( Link);
> 
> +        FreePool ( Temp);
> 
> +      } while ( !IsListEmpty ( Link));
> 
> +      FreePool ( mPrimaryRootPortList);
> 
> +    }
> 
> +    mPrimaryRootPortList = NULL;
> 
> +  }
> 
> +}
> 
> +
> 
> +/**
> 
> +  Free up the memory allocated for temporarily maintaining the PCI feature
> 
> +  configuration table for all the nodes of the primary PCI Root port.
> 
> +  Free up memory alloted for
> OTHER_PCI_FEATURES_CONFIGURATION_TABLE.
> 
> +**/
> 
> +VOID
> 
> +ErasePciFeaturesConfigurationTable (
> 
> +  )
> 
> +{
> 
> +  if ( mPciFeaturesConfigurationTableInstances) {
> 
> +    FreePool ( mPciFeaturesConfigurationTableInstances);
> 
> +  }
> 
> +  mPciFeaturesConfigurationTableInstances = NULL;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Routine meant for initializing any global variables used. It primarily cleans
> 
> +  up the internal data structure memory allocated for the previous PCI Root
> Bridge
> 
> +  instance. This should be the first routine to call for any virtual PCI Root
> 
> +  Bridge instance.
> 
> +**/
> 
> +VOID
> 
> +SetupPciFeaturesConfigurationDefaults ()
> 
> +{
> 
> +  //
> 
> +  // delete the primary root port list
> 
> +  //
> 
> +  if (mPrimaryRootPortList) {
> 
> +    DestroyPrimaryRootPortNodes ();
> 
> +  }
> 
> +
> 
> +  if ( mPciFeaturesConfigurationTableInstances) {
> 
> +    ErasePciFeaturesConfigurationTable ();
> 
> +  }
> 
> +}
> 
> +
> 
> +/**
> 
> +  Helper routine to determine whether the PCI device is a physical root port
> 
> +  recorded in the list.
> 
> +
> 
> +  @param  PciDevice                       A pointer to the PCI_IO_DEVICE.
> 
> +
> 
> +  @retval TRUE                            The PCI device instance is a primary
> 
> +                                          primary physical PCI Root Port
> 
> +          FALSE                           Not a primary physical PCI Root port
> 
> +**/
> 
> +BOOLEAN
> 
> +CheckRootBridgePrimaryPort (
> 
> +  IN PCI_IO_DEVICE          *PciDevice
> 
> +  )
> 
> +{
> 
> +  LIST_ENTRY                *Link;
> 
> +  PRIMARY_ROOT_PORT_NODE    *Temp;
> 
> +
> 
> +  if ( !mPrimaryRootPortList) {
> 
> +    return FALSE;
> 
> +  }
> 
> +  Link = &mPrimaryRootPortList->NeighborRootPort;
> 
> +  do {
> 
> +    Temp = PRIMARY_ROOT_PORT_NODE_FROM_LINK ( Link);
> 
> +    if ( Temp->RootBridgeHandle == PciDevice->Parent->Handle
> 
> +        && Temp->RootPortHandle == PciDevice->Handle) {
> 
> +      //
> 
> +      // the given PCI device is the primary root port of the Root Bridge
> controller
> 
> +      //
> 
> +      return TRUE;
> 
> +    }
> 
> +    Link = Link->ForwardLink;
> 
> +  } while ( Link != &mPrimaryRootPortList->NeighborRootPort);
> 
> +  //
> 
> +  // the given PCI device is not the primary root port of the Bridge controller
> 
> +  //
> 
> +  return FALSE;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Main routine to determine the child PCI devices of a physical PCI bridge
> device
> 
> +  and group them under a common internal PCI features Configuration table.
> 
> +
> 
> +  @param  PciDevice                       A pointer to the PCI_IO_DEVICE.
> 
> +  @param  PciFeaturesConfigTable          A pointer to a pointer to the
> 
> +                                          OTHER_PCI_FEATURES_CONFIGURATION_TABLE.
> 
> +                                          Returns NULL in case of RCiEP or the PCI
> 
> +                                          device does match with any of the physical
> 
> +                                          Root ports, or it does not belong to any
> 
> +                                          Root port's PCU bus range (not a child)
> 
> +
> 
> +  @retval EFI_SUCCESS                     able to determine the PCI feature
> 
> +                                          configuration table. For RCiEP since
> 
> +                                          since it is not prepared.
> 
> +          EFI_NOT_FOUND                   the PCI feature configuration table does
> 
> +                                          not exist as the PCI physical Bridge device
> 
> +                                          is not found for this device's parent
> 
> +                                          Root Bridge instance
> 
> +**/
> 
> +EFI_STATUS
> 
> +GetPciFeaturesConfigurationTable (
> 
> +  IN  PCI_IO_DEVICE                           *PciDevice,
> 
> +  OUT OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> **PciFeaturesConfigTable
> 
> +  )
> 
> +{
> 
> +  LIST_ENTRY                *Link;
> 
> +  PRIMARY_ROOT_PORT_NODE    *Temp;
> 
> +
> 
> +  if ( !mPrimaryRootPortList) {
> 
> +    *PciFeaturesConfigTable = NULL;
> 
> +    return EFI_NOT_FOUND;
> 
> +  }
> 
> +
> 
> +  //
> 
> +  // The PCI features configuration table is not built for RCiEP, return NULL
> 
> +  //
> 
> +  if ( PciDevice->PciExpStruct.Capability.Bits.DevicePortType == \
> 
> +        PCIE_DEVICE_PORT_TYPE_ROOT_COMPLEX_INTEGRATED_ENDPOINT)
> {
> 
> +    *PciFeaturesConfigTable = NULL;
> 
> +    return EFI_SUCCESS;
> 
> +  }
> 
> +
> 
> +  Link = &mPrimaryRootPortList->NeighborRootPort;
> 
> +  do {
> 
> +    Temp = PRIMARY_ROOT_PORT_NODE_FROM_LINK ( Link);
> 
> +    if ( Temp->RootBridgeHandle == PciDevice->Parent->Handle
> 
> +        && Temp->RootPortHandle == PciDevice->Handle) {
> 
> +      //
> 
> +      // the given PCI device is the primary root port of the Root Bridge
> controller
> 
> +      //
> 
> +      *PciFeaturesConfigTable = Temp->OtherPciFeaturesConfigurationTable;
> 
> +      return EFI_SUCCESS;
> 
> +    } else {
> 
> +      //
> 
> +      // check this PCI device belongs to the primary root port of the root
> bridge
> 
> +      //
> 
> +      if ( PciDevice->BusNumber >= Temp->SecondaryBusStart
> 
> +          && PciDevice->BusNumber <= Temp->SecondaryBusEnd) {
> 
> +        *PciFeaturesConfigTable = Temp->OtherPciFeaturesConfigurationTable;
> 
> +        return EFI_SUCCESS;
> 
> +      }
> 
> +    }
> 
> +    Link = Link->ForwardLink;
> 
> +  } while ( Link != &mPrimaryRootPortList->NeighborRootPort);
> 
> +  //
> 
> +  // the PCI device must be RCiEP, does not belong to any primary root port
> 
> +  //
> 
> +  *PciFeaturesConfigTable = NULL;
> 
> +  return EFI_SUCCESS;
> 
> +}
> 
> +
> 
> +/**
> 
> +  The helper routine to retrieve the PCI bus numbers from the PCI Bridge or
> Root
> 
> +  port device. Assumes the input PCI device has the PCI Type 1 configuration
> header.
> 
> +
> 
> +  @param  PciDevice                       A pointer to the PCI_IO_DEVICE.
> 
> +  @param  PrimaryBusNumber                A pointer to return the PCI Priamry
> 
> +                                          Bus number.
> 
> +  @param  SecondaryBusNumber              A pointer to return the PCI
> Secondary
> 
> +                                          Bus number.
> 
> +  @param  SubordinateBusNumber            A pointer to return the PCI
> Subordinate
> 
> +                                          Bus number.
> 
> +
> 
> +  @retval EFI_SUCCESS           The data was read from the PCI device.
> 
> +  @retval EFI_UNSUPPORTED       The address range specified by Offset,
> Width, and Count is not
> 
> +                                valid for the PCI configuration header of the PCI device.
> 
> +  @retval EFI_INVALID_PARAMETER input parameters provided to the read
> operation were invalid.
> 
> +**/
> 
> +EFI_STATUS
> 
> +GetPciRootPortBusAssigned (
> 
> +  IN  PCI_IO_DEVICE                           *PciDevice,
> 
> +  OUT UINT8                                   *PrimaryBusNumber,
> 
> +  OUT UINT8                                   *SecondaryBusNumber,
> 
> +  OUT UINT8                                   *SubordinateBusNumber
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS                                  Status;
> 
> +  UINT32                                      RootPortBusAssigned;
> 
> +
> 
> +  Status = PciDevice->PciIo.Pci.Read (
> 
> +                                  &PciDevice->PciIo,
> 
> +                                  EfiPciIoWidthUint32,
> 
> +                                  PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET,
> 
> +                                  1,
> 
> +                                  &RootPortBusAssigned
> 
> +                                );
> 
> +  if ( !EFI_ERROR(Status)) {
> 
> +    if ( PrimaryBusNumber) {
> 
> +      *PrimaryBusNumber = (UINT8) (0xFF & RootPortBusAssigned);
> 
> +    }
> 
> +    if ( SecondaryBusNumber) {
> 
> +      *SecondaryBusNumber = (UINT8)(0xFF & (RootPortBusAssigned >> 8));
> 
> +    }
> 
> +    if ( SubordinateBusNumber) {
> 
> +      *SubordinateBusNumber = (UINT8)(0xFF & (RootPortBusAssigned >>
> 16));
> 
> +    }
> 
> +  }
> 
> +  return Status;
> 
> +}
> 
> +
> 
> +/**
> 
> +  This routine determines the existance of the child PCI device for the given
> 
> +  PCI Root / Bridge Port device. Always assumes the input PCI device is the
> bridge
> 
> +  or PCI-PCI Bridge device. This routine should not be used with PCI
> endpoint device.
> 
> +
> 
> +  @param  PciDevice                       A pointer to the PCI_IO_DEVICE.
> 
> +
> 
> +  @retval TRUE                            child device exist
> 
> +          FALSE                           no child device
> 
> +**/
> 
> +BOOLEAN
> 
> +IsPciRootPortEmpty (
> 
> +  IN  PCI_IO_DEVICE                           *PciDevice
> 
> +  )
> 
> +{
> 
> +  UINT8                                       SecBus,
> 
> +                                              SubBus;
> 
> +  EFI_STATUS                                  Status;
> 
> +  LIST_ENTRY                                  *Link;
> 
> +  PCI_IO_DEVICE                               *NextPciDevice;
> 
> +
> 
> +  //
> 
> +  // check secondary & suboridinate bus numbers for its endpoint device
> 
> +  // existance
> 
> +  //
> 
> +  Status = GetPciRootPortBusAssigned ( PciDevice, NULL, &SecBus,
> &SubBus);
> 
> +  if ( !EFI_ERROR( Status)) {
> 
> +    Link = PciDevice->ChildList.ForwardLink;
> 
> +    if ( IsListEmpty ( Link)) {
> 
> +      //
> 
> +      // return as PCI Root port empty
> 
> +      //
> 
> +      DEBUG (( DEBUG_INFO, "RP empty,"));
> 
> +      return TRUE;
> 
> +    }
> 
> +    do {
> 
> +      NextPciDevice = PCI_IO_DEVICE_FROM_LINK ( Link);
> 
> +      DEBUG (( DEBUG_INFO, "dev@%x", NextPciDevice->BusNumber));
> 
> +
> 
> +      if ( NextPciDevice->BusNumber >= SecBus
> 
> +          && NextPciDevice->BusNumber <= SubBus) {
> 
> +
> 
> +        return FALSE;
> 
> +      }
> 
> +
> 
> +      Link = Link->ForwardLink;
> 
> +    } while ( Link != &PciDevice->ChildList);
> 
> +  } else {
> 
> +    SecBus = SubBus = 0;
> 
> +    DEBUG (( DEBUG_ERROR, "unable to retrieve root port's bus range
> assigned!!!"));
> 
> +  }
> 
> +
> 
> +  //
> 
> +  // return as PCI Root port empty
> 
> +  //
> 
> +  return TRUE;
> 
> +}
> 
> +
> 
> +/**
> 
> +  The main routine which process the PCI feature Max_Payload_Size as per
> the
> 
> +  device-specific platform policy, as well as in complaince with the PCI Base
> 
> +  specification Revision 4, that aligns the value for the entire PCI heirarchy
> 
> +  starting from its physical PCI Root port / Bridge device.
> 
> +
> 
> +  @param PciDevice                      A pointer to the PCI_IO_DEVICE.
> 
> +  @param PciConfigPhase                 for the PCI feature configuration phases:
> 
> +                                        PciFeatureGetDevicePolicy & PciFeatureSetupPhase
> 
> +  @param PciFeaturesConfigurationTable  pointer to
> OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> 
> +
> 
> +  @retval EFI_SUCCESS                   processing of PCI feature
> Max_Payload_Size
> 
> +                                        is successful.
> 
> +**/
> 
> +EFI_STATUS
> 
> +ProcessMaxPayloadSize (
> 
> +  IN  PCI_IO_DEVICE                           *PciDevice,
> 
> +  IN  PCI_FEATURE_CONFIGURATION_PHASE         PciConfigPhase,
> 
> +  IN  OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> *PciFeaturesConfigurationTable
> 
> +  )
> 
> +{
> 
> +  PCI_REG_PCIE_DEVICE_CAPABILITY          PciDeviceCap;
> 
> +  UINT8                                   MpsValue;
> 
> +
> 
> +
> 
> +  PciDeviceCap.Uint32 = PciDevice->PciExpStruct.DeviceCapability.Uint32;
> 
> +
> 
> +  if ( PciConfigPhase == PciFeatureGetDevicePolicy) {
> 
> +    if ( SetupMpsAsPerDeviceCapability ( PciDevice->SetupMPS))
> 
> +    {
> 
> +      MpsValue = (UINT8)PciDeviceCap.Bits.MaxPayloadSize;
> 
> +      //
> 
> +      // no change to PCI Root ports without any endpoint device
> 
> +      //
> 
> +      if ( IS_PCI_BRIDGE ( &PciDevice->Pci) &&
> PciDeviceCap.Bits.MaxPayloadSize) {
> 
> +        if ( IsPciRootPortEmpty ( PciDevice)) {
> 
> +          MpsValue = PCIE_MAX_PAYLOAD_SIZE_128B;
> 
> +          DEBUG (( DEBUG_INFO, "(reset RP MPS to min.)"));
> 
> +        }
> 
> +      }
> 
> +    } else {
> 
> +      MpsValue = TranslateMpsSetupValueToPci ( PciDevice->SetupMPS);
> 
> +    }
> 
> +    //
> 
> +    // discard device policy override request if greater than PCI device
> capability
> 
> +    //
> 
> +    PciDevice->SetupMPS = MIN( (UINT8)PciDeviceCap.Bits.MaxPayloadSize,
> MpsValue);
> 
> +  }
> 
> +
> 
> +  //
> 
> +  // align the MPS of the tree to the HCF with this device
> 
> +  //
> 
> +  if ( PciFeaturesConfigurationTable) {
> 
> +    MpsValue = PciFeaturesConfigurationTable->Max_Payload_Size;
> 
> +
> 
> +    MpsValue = MIN ( PciDevice->SetupMPS, MpsValue);
> 
> +    PciDevice->SetupMPS = MIN ( PciDevice->SetupMPS, MpsValue);
> 
> +
> 
> +    if ( MpsValue != PciFeaturesConfigurationTable->Max_Payload_Size) {
> 
> +      DEBUG (( DEBUG_INFO, "reset MPS of the tree to %d,", MpsValue));
> 
> +      PciFeaturesConfigurationTable->Max_Payload_Size = MpsValue;
> 
> +    }
> 
> +  }
> 
> +
> 
> +  DEBUG (( DEBUG_INFO,
> 
> +      "Max_Payload_Size: %d [DevCap:%d],",
> 
> +      PciDevice->SetupMPS, PciDeviceCap.Bits.MaxPayloadSize
> 
> +  ));
> 
> +  return EFI_SUCCESS;
> 
> +}
> 
> +
> 
> +/**
> 
> +  The main routine which process the PCI feature Max_Read_Req_Size as
> per the
> 
> +  device-specific platform policy, as well as in complaince with the PCI Base
> 
> +  specification Revision 4, that aligns the value for the entire PCI heirarchy
> 
> +  starting from its physical PCI Root port / Bridge device.
> 
> +
> 
> +  @param PciDevice                      A pointer to the PCI_IO_DEVICE.
> 
> +  @param PciConfigPhase                 for the PCI feature configuration phases:
> 
> +                                        PciFeatureGetDevicePolicy & PciFeatureSetupPhase
> 
> +  @param PciFeaturesConfigurationTable  pointer to
> OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> 
> +
> 
> +  @retval EFI_SUCCESS                   processing of PCI feature
> Max_Read_Req_Size
> 
> +                                        is successful.
> 
> +**/
> 
> +EFI_STATUS
> 
> +ProcessMaxReadReqSize (
> 
> +  IN  PCI_IO_DEVICE                           *PciDevice,
> 
> +  IN  PCI_FEATURE_CONFIGURATION_PHASE         PciConfigPhase,
> 
> +  IN  OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> *PciFeaturesConfigurationTable
> 
> +  )
> 
> +{
> 
> +  PCI_REG_PCIE_DEVICE_CAPABILITY  PciDeviceCap;
> 
> +  UINT8                           MrrsValue;
> 
> +
> 
> +  PciDeviceCap.Uint32 = PciDevice->PciExpStruct.DeviceCapability.Uint32;
> 
> +
> 
> +  if ( PciConfigPhase == PciFeatureGetDevicePolicy) {
> 
> +    if ( SetupMrrsAsPerDeviceCapability ( PciDevice->SetupMRRS))
> 
> +    {
> 
> +      //
> 
> +      // The maximum read request size is not the data packet size of the TLP,
> 
> +      // but the memory read request size, and set to the function as a
> requestor
> 
> +      // to not exceed this limit.
> 
> +      // However, for the PCI device capable of isochronous traffic; this
> memory read
> 
> +      // request size should not extend beyond the Max_Payload_Size. Thus,
> in case if
> 
> +      // device policy return by platform indicates to set as per device
> capability
> 
> +      // than set as per Max_Payload_Size configuration value
> 
> +      //
> 
> +      if ( SetupMaxPayloadSize()) {
> 
> +        MrrsValue = PciDevice->SetupMPS;
> 
> +      } else {
> 
> +        //
> 
> +        // in case this driver is not required to configure the Max_Payload_Size
> 
> +        // than consider programming HCF of the device capability's
> Max_Payload_Size
> 
> +        // in this PCI hierarchy; thus making this an implementation specific
> feature
> 
> +        // which the platform should avoid. For better results, the platform
> should
> 
> +        // make both the Max_Payload_Size & Max_Read_Request_Size to be
> configured
> 
> +        // by this driver
> 
> +        //
> 
> +        MrrsValue = (UINT8)PciDeviceCap.Bits.MaxPayloadSize;
> 
> +      }
> 
> +    } else {
> 
> +      //
> 
> +      // override as per platform based device policy
> 
> +      //
> 
> +      MrrsValue = TranslateMrrsSetupValueToPci ( PciDevice->SetupMRRS);
> 
> +      //
> 
> +      // align this device's Max_Read_Request_Size value to the entire PCI
> tree
> 
> +      //
> 
> +      if ( PciFeaturesConfigurationTable) {
> 
> +        if ( !PciFeaturesConfigurationTable->Lock_Max_Read_Request_Size) {
> 
> +          PciFeaturesConfigurationTable->Lock_Max_Read_Request_Size =
> TRUE;
> 
> +          PciFeaturesConfigurationTable->Max_Read_Request_Size =
> MrrsValue;
> 
> +        } else {
> 
> +          //
> 
> +          // in case of another user enforced value of MRRS within the same
> tree,
> 
> +          // pick the smallest between the locked value and this value; to set
> 
> +          // across entire PCI tree nodes
> 
> +          //
> 
> +          MrrsValue = MIN (
> 
> +                        MrrsValue,
> 
> +                        PciFeaturesConfigurationTable->Max_Read_Request_Size
> 
> +                        );
> 
> +          PciFeaturesConfigurationTable->Max_Read_Request_Size =
> MrrsValue;
> 
> +        }
> 
> +      }
> 
> +    }
> 
> +    //
> 
> +    // align this device's Max_Read_Request_Size to derived configuration
> value
> 
> +    //
> 
> +    PciDevice->SetupMRRS = MrrsValue;
> 
> +
> 
> +  }
> 
> +
> 
> +  //
> 
> +  // align the Max_Read_Request_Size of the PCI tree based on 3 conditions:
> 
> +  // first, if user defines MRRS for any one PCI device in the tree than align
> 
> +  // all the devices in the PCI tree.
> 
> +  // second, if user override is not define for this PCI tree than setup the
> MRRS
> 
> +  // based on MPS value of the tree to meet the criteria for the isochronous
> 
> +  // traffic.
> 
> +  // third, if no user override, or platform firmware policy has not selected
> 
> +  // this PCI bus driver to configure the MPS; than configure the MRRS to a
> 
> +  // highest common value of PCI device capability for the MPS found among
> all
> 
> +  // the PCI devices in this tree
> 
> +  //
> 
> +  if ( PciFeaturesConfigurationTable) {
> 
> +    if ( PciFeaturesConfigurationTable->Lock_Max_Read_Request_Size) {
> 
> +      PciDevice->SetupMRRS = PciFeaturesConfigurationTable-
> >Max_Read_Request_Size;
> 
> +    } else {
> 
> +      if ( SetupMaxPayloadSize()) {
> 
> +        PciDevice->SetupMRRS = PciDevice->SetupMPS;
> 
> +      } else {
> 
> +        PciDevice->SetupMRRS = MIN (
> 
> +                                PciDevice->SetupMRRS,
> 
> +                                PciFeaturesConfigurationTable->Max_Read_Request_Size
> 
> +                                );
> 
> +      }
> 
> +      PciFeaturesConfigurationTable->Max_Read_Request_Size = PciDevice-
> >SetupMRRS;
> 
> +    }
> 
> +  }
> 
> +  DEBUG (( DEBUG_INFO, "Max_Read_Request_Size: %d\n", PciDevice-
> >SetupMRRS));
> 
> +
> 
> +  return EFI_SUCCESS;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Overrides the PCI Device Control register MaxPayloadSize register field; if
> 
> +  the hardware value is different than the intended value.
> 
> +
> 
> +  @param  PciDevice             A pointer to the PCI_IO_DEVICE instance.
> 
> +
> 
> +  @retval EFI_SUCCESS           The data was read from or written to the PCI
> device.
> 
> +  @retval EFI_UNSUPPORTED       The address range specified by Offset,
> Width, and Count is not
> 
> +                                valid for the PCI configuration header of the PCI controller.
> 
> +  @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +OverrideMaxPayloadSize (
> 
> +  IN PCI_IO_DEVICE          *PciDevice
> 
> +  )
> 
> +{
> 
> +  PCI_REG_PCIE_DEVICE_CONTROL PcieDev;
> 
> +  UINT32                      Offset;
> 
> +  EFI_STATUS                  Status;
> 
> +
> 
> +  PcieDev.Uint16 = 0;
> 
> +  Offset = PciDevice->PciExpressCapabilityOffset +
> 
> +               OFFSET_OF (PCI_CAPABILITY_PCIEXP, DeviceControl);
> 
> +  Status = PciDevice->PciIo.Pci.Read (
> 
> +                                  &PciDevice->PciIo,
> 
> +                                  EfiPciIoWidthUint16,
> 
> +                                  Offset,
> 
> +                                  1,
> 
> +                                  &PcieDev.Uint16
> 
> +                                );
> 
> +  if ( EFI_ERROR(Status)){
> 
> +    DEBUG (( DEBUG_ERROR, "Unexpected DeviceControl register (0x%x)
> read error!",
> 
> +        Offset
> 
> +    ));
> 
> +    return Status;
> 
> +  }
> 
> +  if ( PcieDev.Bits.MaxPayloadSize != PciDevice->SetupMPS) {
> 
> +    PcieDev.Bits.MaxPayloadSize = PciDevice->SetupMPS;
> 
> +    DEBUG (( DEBUG_INFO, "Max_Payload_Size=%d,", PciDevice-
> >SetupMPS));
> 
> +
> 
> +    Status = PciDevice->PciIo.Pci.Write (
> 
> +                                    &PciDevice->PciIo,
> 
> +                                    EfiPciIoWidthUint16,
> 
> +                                    Offset,
> 
> +                                    1,
> 
> +                                    &PcieDev.Uint16
> 
> +                                  );
> 
> +    if ( !EFI_ERROR(Status)) {
> 
> +      PciDevice->PciExpStruct.DeviceControl.Uint16 = PcieDev.Uint16;
> 
> +    } else {
> 
> +      DEBUG (( DEBUG_ERROR, "Unexpected DeviceControl register (0x%x)
> write error!",
> 
> +          Offset
> 
> +      ));
> 
> +    }
> 
> +  } else {
> 
> +    DEBUG (( DEBUG_INFO, "No write of Max_Payload_Size=%d,", PciDevice-
> >SetupMPS));
> 
> +  }
> 
> +
> 
> +  return Status;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Overrides the PCI Device Control register MaxPayloadSize register field; if
> 
> +  the hardware value is different than the intended value.
> 
> +
> 
> +  @param  PciDevice             A pointer to the PCI_IO_DEVICE instance.
> 
> +
> 
> +  @retval EFI_SUCCESS           The data was read from or written to the PCI
> controller.
> 
> +  @retval EFI_UNSUPPORTED       The address range specified by Offset,
> Width, and Count is not
> 
> +                                valid for the PCI configuration header of the PCI controller.
> 
> +  @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +OverrideMaxReadReqSize (
> 
> +  IN PCI_IO_DEVICE          *PciDevice
> 
> +  )
> 
> +{
> 
> +  PCI_REG_PCIE_DEVICE_CONTROL PcieDev;
> 
> +  UINT32                      Offset;
> 
> +  EFI_STATUS                  Status;
> 
> +
> 
> +  PcieDev.Uint16 = 0;
> 
> +  Offset = PciDevice->PciExpressCapabilityOffset +
> 
> +               OFFSET_OF (PCI_CAPABILITY_PCIEXP, DeviceControl);
> 
> +  Status = PciDevice->PciIo.Pci.Read (
> 
> +                                  &PciDevice->PciIo,
> 
> +                                  EfiPciIoWidthUint16,
> 
> +                                  Offset,
> 
> +                                  1,
> 
> +                                  &PcieDev.Uint16
> 
> +                                );
> 
> +  if ( EFI_ERROR(Status)){
> 
> +    DEBUG (( DEBUG_ERROR, "Unexpected DeviceControl register (0x%x)
> read error!",
> 
> +        Offset
> 
> +    ));
> 
> +    return Status;
> 
> +  }
> 
> +  if ( PcieDev.Bits.MaxReadRequestSize != PciDevice->SetupMRRS) {
> 
> +    PcieDev.Bits.MaxReadRequestSize = PciDevice->SetupMRRS;
> 
> +    DEBUG (( DEBUG_INFO, "Max_Read_Request_Size: %d\n", PciDevice-
> >SetupMRRS));
> 
> +
> 
> +    Status = PciDevice->PciIo.Pci.Write (
> 
> +                                    &PciDevice->PciIo,
> 
> +                                    EfiPciIoWidthUint16,
> 
> +                                    Offset,
> 
> +                                    1,
> 
> +                                    &PcieDev.Uint16
> 
> +                                  );
> 
> +    if ( !EFI_ERROR(Status)) {
> 
> +      PciDevice->PciExpStruct.DeviceControl.Uint16 = PcieDev.Uint16;
> 
> +    } else {
> 
> +      DEBUG (( DEBUG_ERROR, "Unexpected DeviceControl register (0x%x)
> write error!",
> 
> +          Offset
> 
> +      ));
> 
> +    }
> 
> +  } else {
> 
> +    DEBUG (( DEBUG_INFO, "No write of Max_Read_Request_Size=%d\n",
> PciDevice->SetupMRRS));
> 
> +  }
> 
> +
> 
> +  return Status;
> 
> +}
> 
> +
> 
> +/**
> 
> +  helper routine to dump the PCIe Device Port Type
> 
> +**/
> 
> +VOID
> 
> +DumpDevicePortType (
> 
> +  IN  UINT8   DevicePortType
> 
> +  )
> 
> +{
> 
> +  switch ( DevicePortType){
> 
> +    case PCIE_DEVICE_PORT_TYPE_PCIE_ENDPOINT:
> 
> +      DEBUG (( DEBUG_INFO, "PCIe endpoint found\n"));
> 
> +      break;
> 
> +    case PCIE_DEVICE_PORT_TYPE_LEGACY_PCIE_ENDPOINT:
> 
> +      DEBUG (( DEBUG_INFO, "legacy PCI endpoint found\n"));
> 
> +      break;
> 
> +    case PCIE_DEVICE_PORT_TYPE_ROOT_PORT:
> 
> +      DEBUG (( DEBUG_INFO, "PCIe Root Port found\n"));
> 
> +      break;
> 
> +    case PCIE_DEVICE_PORT_TYPE_UPSTREAM_PORT:
> 
> +      DEBUG (( DEBUG_INFO, "PCI switch upstream port found\n"));
> 
> +      break;
> 
> +    case PCIE_DEVICE_PORT_TYPE_DOWNSTREAM_PORT:
> 
> +      DEBUG (( DEBUG_INFO, "PCI switch downstream port found\n"));
> 
> +      break;
> 
> +    case PCIE_DEVICE_PORT_TYPE_PCIE_TO_PCI_BRIDGE:
> 
> +      DEBUG (( DEBUG_INFO, "PCIe-PCI bridge found\n"));
> 
> +      break;
> 
> +    case PCIE_DEVICE_PORT_TYPE_PCI_TO_PCIE_BRIDGE:
> 
> +      DEBUG (( DEBUG_INFO, "PCI-PCIe bridge found\n"));
> 
> +      break;
> 
> +    case
> PCIE_DEVICE_PORT_TYPE_ROOT_COMPLEX_INTEGRATED_ENDPOINT:
> 
> +      DEBUG (( DEBUG_INFO, "RCiEP found\n"));
> 
> +      break;
> 
> +    case PCIE_DEVICE_PORT_TYPE_ROOT_COMPLEX_EVENT_COLLECTOR:
> 
> +      DEBUG (( DEBUG_INFO, "RC Event Collector found\n"));
> 
> +      break;
> 
> +  }
> 
> +}
> 
> +
> 
> +/**
> 
> +   Process each PCI device as per the pltaform and device-specific policy.
> 
> +
> 
> +  @param RootBridge             A pointer to the PCI_IO_DEVICE.
> 
> +
> 
> +  @retval EFI_SUCCESS           processing each PCI feature as per policy
> defined
> 
> +                                was successful.
> 
> + **/
> 
> +EFI_STATUS
> 
> +SetupDevicePciFeatures (
> 
> +  IN  PCI_IO_DEVICE                   *PciDevice,
> 
> +  IN  PCI_FEATURE_CONFIGURATION_PHASE PciConfigPhase
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS                              Status;
> 
> +  PCI_REG_PCIE_CAPABILITY                 PcieCap;
> 
> +  OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> *OtherPciFeaturesConfigTable;
> 
> +
> 
> +  PcieCap.Uint16 = PciDevice->PciExpStruct.Capability.Uint16;
> 
> +  DumpDevicePortType ( (UINT8)PcieCap.Bits.DevicePortType);
> 
> +
> 
> +  OtherPciFeaturesConfigTable = NULL;
> 
> +  Status = GetPciFeaturesConfigurationTable ( PciDevice,
> &OtherPciFeaturesConfigTable);
> 
> +  if ( EFI_ERROR( Status)) {
> 
> +    DEBUG ((
> 
> +        EFI_D_WARN, "No primary root port found in these root bridge
> nodes!\n"
> 
> +    ));
> 
> +  } else if ( !OtherPciFeaturesConfigTable) {
> 
> +    DEBUG ((
> 
> +        DEBUG_INFO, "No PCI features config. table for this device!\n"
> 
> +    ));
> 
> +  } else {
> 
> +    DEBUG ((
> 
> +        DEBUG_INFO, "using PCI features config. table ID: %d\n",
> 
> +        OtherPciFeaturesConfigTable->ID
> 
> +    ));
> 
> +  }
> 
> +
> 
> +  if ( PciConfigPhase == PciFeatureGetDevicePolicy) {
> 
> +    Status = GetPciDevicePlatformPolicy ( PciDevice);
> 
> +    if ( EFI_ERROR(Status)) {
> 
> +      DEBUG ((
> 
> +          DEBUG_ERROR, "Error in obtaining PCI device policy!!!\n"
> 
> +      ));
> 
> +    }
> 
> +  }
> 
> +
> 
> +  if ( SetupMaxPayloadSize ()) {
> 
> +    Status = ProcessMaxPayloadSize (
> 
> +              PciDevice,
> 
> +              PciConfigPhase,
> 
> +              OtherPciFeaturesConfigTable
> 
> +              );
> 
> +  }
> 
> +  //
> 
> +  // implementation specific rule:- the MRRS of any PCI device should be
> processed
> 
> +  // only after the MPS is processed for that device
> 
> +  //
> 
> +  if ( SetupMaxReadReqSize ()) {
> 
> +    Status = ProcessMaxReadReqSize (
> 
> +              PciDevice,
> 
> +              PciConfigPhase,
> 
> +              OtherPciFeaturesConfigTable
> 
> +              );
> 
> +  }
> 
> +  return Status;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Traverse all the nodes from the root bridge or PCI-PCI bridge instance, to
> 
> +  configure the PCI features as per the device-specific platform policy, and
> 
> +  as per the device capability, as applicable.
> 
> +
> 
> +  @param RootBridge             A pointer to the PCI_IO_DEVICE.
> 
> +
> 
> +  @retval EFI_SUCCESS           Traversing all the nodes of the root bridge
> 
> +                                instances were successfull.
> 
> +**/
> 
> +EFI_STATUS
> 
> +SetupPciFeatures (
> 
> +  IN  PCI_IO_DEVICE                   *RootBridge,
> 
> +  IN  PCI_FEATURE_CONFIGURATION_PHASE PciConfigPhase
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS           Status;
> 
> +  LIST_ENTRY           *Link;
> 
> +  PCI_IO_DEVICE        *Device;
> 
> +
> 
> +  for ( Link = RootBridge->ChildList.ForwardLink
> 
> +      ; Link != &RootBridge->ChildList
> 
> +      ; Link = Link->ForwardLink
> 
> +  ) {
> 
> +    Device = PCI_IO_DEVICE_FROM_LINK (Link);
> 
> +    if (IS_PCI_BRIDGE (&Device->Pci)) {
> 
> +      DEBUG ((
> 
> +          DEBUG_INFO, "::Bridge [%02x|%02x|%02x] -",
> 
> +          Device->BusNumber, Device->DeviceNumber, Device-
> >FunctionNumber
> 
> +      ));
> 
> +      if (Device->IsPciExp) {
> 
> +        Status = SetupDevicePciFeatures ( Device, PciConfigPhase);
> 
> +      } else {
> 
> +        DEBUG (( DEBUG_INFO, "Not a PCIe capable device!\n"));
> 
> +        //
> 
> +        // PCI Bridge which does not have PCI Express Capability structure
> 
> +        // cannot process this kind of PCI Bridge device
> 
> +        //
> 
> +
> 
> +      }
> 
> +
> 
> +      SetupPciFeatures ( Device, PciConfigPhase);
> 
> +    } else {
> 
> +      DEBUG ((
> 
> +          DEBUG_INFO, "::Device [%02x|%02x|%02x] -",
> 
> +          Device->BusNumber, Device->DeviceNumber, Device-
> >FunctionNumber
> 
> +      ));
> 
> +      if (Device->IsPciExp) {
> 
> +
> 
> +        Status = SetupDevicePciFeatures ( Device, PciConfigPhase);
> 
> +      } else {
> 
> +        DEBUG (( DEBUG_INFO, "Not a PCIe capable device!\n"));
> 
> +        //
> 
> +        // PCI Device which does not have PCI Express Capability structure
> 
> +        // cannot process this kind of PCI device
> 
> +        //
> 
> +      }
> 
> +    }
> 
> +  }
> 
> +
> 
> +  return EFI_SUCCESS;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Program the PCI device, to override the PCI features as per the policy,
> 
> +  resolved from previous traverse.
> 
> +
> 
> +  @param RootBridge             A pointer to the PCI_IO_DEVICE.
> 
> +
> 
> +  @retval EFI_SUCCESS           The other PCI features configuration during
> enumeration
> 
> +                                of all the nodes of the PCI root bridge instance were
> 
> +                                programmed in PCI-compliance pattern along with the
> 
> +                                device-specific policy, as applicable.
> 
> +  @retval EFI_UNSUPPORTED       One of the override operation maong the
> nodes of
> 
> +                                the PCI hierarchy resulted in a incompatible address
> 
> +                                range.
> 
> +  @retval EFI_INVALID_PARAMETER The override operation is performed
> with invalid input
> 
> +                                parameters.
> 
> +**/
> 
> +EFI_STATUS
> 
> +ProgramDevicePciFeatures (
> 
> +  IN PCI_IO_DEVICE          *PciDevice
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS           Status;
> 
> +
> 
> +  if ( SetupMaxPayloadSize ()) {
> 
> +    Status = OverrideMaxPayloadSize (PciDevice);
> 
> +  }
> 
> +  if ( SetupMaxReadReqSize ()) {
> 
> +    Status = OverrideMaxReadReqSize (PciDevice);
> 
> +  }
> 
> +  return Status;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Program all the nodes of the specified root bridge or PCI-PCI Bridge, to
> 
> +  override the PCI features.
> 
> +
> 
> +  @param RootBridge             A pointer to the PCI_IO_DEVICE.
> 
> +
> 
> +  @retval EFI_SUCCESS           The other PCI features configuration during
> enumeration
> 
> +                                of all the nodes of the PCI root bridge instance were
> 
> +                                programmed in PCI-compliance pattern along with the
> 
> +                                device-specific policy, as applicable.
> 
> +  @retval EFI_UNSUPPORTED       One of the override operation maong the
> nodes of
> 
> +                                the PCI hierarchy resulted in a incompatible address
> 
> +                                range.
> 
> +  @retval EFI_INVALID_PARAMETER The override operation is performed
> with invalid input
> 
> +                                parameters.
> 
> +**/
> 
> +EFI_STATUS
> 
> +ProgramPciFeatures (
> 
> +  IN PCI_IO_DEVICE          *RootBridge
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS           Status;
> 
> +  LIST_ENTRY           *Link;
> 
> +  PCI_IO_DEVICE        *Device;
> 
> +
> 
> +  for ( Link = RootBridge->ChildList.ForwardLink
> 
> +      ; Link != &RootBridge->ChildList
> 
> +      ; Link = Link->ForwardLink
> 
> +  ) {
> 
> +    Device = PCI_IO_DEVICE_FROM_LINK (Link);
> 
> +    if (IS_PCI_BRIDGE (&Device->Pci)) {
> 
> +      DEBUG ((
> 
> +          DEBUG_INFO, "::Bridge [%02x|%02x|%02x] -",
> 
> +          Device->BusNumber, Device->DeviceNumber, Device-
> >FunctionNumber
> 
> +      ));
> 
> +      if (Device->IsPciExp) {
> 
> +        DEBUG (( DEBUG_INFO, "ready to override!\n"));
> 
> +
> 
> +        Status = ProgramDevicePciFeatures ( Device);
> 
> +      } else {
> 
> +        DEBUG (( DEBUG_INFO, "skipped!\n"));
> 
> +        //
> 
> +        // PCI Bridge which does not have PCI Express Capability structure
> 
> +        // cannot process this kind of PCI Bridge device
> 
> +        //
> 
> +
> 
> +      }
> 
> +
> 
> +      Status = ProgramPciFeatures ( Device);
> 
> +    } else {
> 
> +      DEBUG ((
> 
> +          DEBUG_INFO, "::Device [%02x|%02x|%02x] -",
> 
> +          Device->BusNumber, Device->DeviceNumber, Device-
> >FunctionNumber
> 
> +      ));
> 
> +      if (Device->IsPciExp) {
> 
> +        DEBUG (( DEBUG_INFO, "ready to override!\n"));
> 
> +
> 
> +        Status = ProgramDevicePciFeatures ( Device);
> 
> +      } else {
> 
> +        DEBUG (( DEBUG_INFO, "skipped!\n"));
> 
> +        //
> 
> +        // PCI Device which does not have PCI Express Capability structure
> 
> +        // cannot process this kind of PCI device
> 
> +        //
> 
> +      }
> 
> +    }
> 
> +  }
> 
> +
> 
> +  return Status;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Create a node of type PRIMARY_ROOT_PORT_NODE for the given PCI
> device, and
> 
> +  assigns EFI handles of its Root Bridge and its own, along with its PCI Bus
> 
> +  range for the secondary and subordinate bus range.
> 
> +
> 
> +  @param  RootBridge          A pointer to the PCI_IO_DEVICE for its PCI Root
> Bridge
> 
> +  @param  Device              A pointer to the PCI_IO_DEVICE for the PCI
> controller
> 
> +  @param  RootPortSecBus      PCI controller's Secondary Bus number
> 
> +  @param  RootPortSubBus      PCI controller's Subordinate Bus number
> 
> +  @param  PrimaryRootPortNode A pointer to the
> PRIMARY_ROOT_PORT_NODE to return
> 
> +                              the newly created node for the PCI controller. In
> 
> +                              case of error nothing is return in this.
> 
> +
> 
> +  @retval EFI_SUCCESS           new node of PRIMARY_ROOT_PORT_NODE is
> returned for
> 
> +                                the PCI controller
> 
> +          EFI_OUT_OF_RESOURCES  unable to create the node for the PCI
> controller
> 
> +          EFI_INVALID_PARAMETER unable to store the node as the input
> buffer is
> 
> +                                not empty (*PrimaryRootPortNode)
> 
> +**/
> 
> +EFI_STATUS
> 
> +CreatePrimaryPciRootPortNode (
> 
> +  IN  PCI_IO_DEVICE           *RootBridge,
> 
> +  IN  PCI_IO_DEVICE           *Device,
> 
> +  IN  UINT8                   RootPortSecBus,
> 
> +  IN  UINT8                   RootPortSubBus,
> 
> +  OUT PRIMARY_ROOT_PORT_NODE  **PrimaryRootPortNode
> 
> +  )
> 
> +{
> 
> +  PRIMARY_ROOT_PORT_NODE      *RootPortNode = NULL;
> 
> +
> 
> +  if ( !*PrimaryRootPortNode) {
> 
> +    RootPortNode                    = AllocateZeroPool ( sizeof
> (PRIMARY_ROOT_PORT_NODE));
> 
> +    if ( RootPortNode == NULL) {
> 
> +      return EFI_OUT_OF_RESOURCES;
> 
> +    }
> 
> +    RootPortNode->Signature         = PCI_ROOT_PORT_SIGNATURE;
> 
> +    RootPortNode->RootBridgeHandle  = RootBridge->Handle;
> 
> +    RootPortNode->RootPortHandle    = Device->Handle;
> 
> +    RootPortNode->SecondaryBusStart = RootPortSecBus;
> 
> +    RootPortNode->SecondaryBusEnd   = RootPortSubBus;
> 
> +    InitializeListHead ( &RootPortNode->NeighborRootPort);
> 
> +    *PrimaryRootPortNode = RootPortNode;
> 
> +    return EFI_SUCCESS;
> 
> +  } else {
> 
> +    return EFI_INVALID_PARAMETER;
> 
> +  }
> 
> +}
> 
> +
> 
> +/**
> 
> +  Checks to report whether the input PCI controller's secondary /
> subordinate
> 
> +  bus numbers are within the recorded list of other PCI controllers (root
> ports).
> 
> +
> 
> +  @param  RootPortNode      A pointer to the first node of
> PRIMARY_ROOT_PORT_NODE
> 
> +  @param  RootPortSecBus    PCI secondary bus number of the PCI controller
> found
> 
> +  @param  RootPortSubBus    PCI subordinate bus number of the PCI Root
> Port found
> 
> +
> 
> +  @retval TRUE              A child PCI Root port found
> 
> +          FALSE             A new PCI controller found
> 
> +**/
> 
> +BOOLEAN
> 
> +CheckChildRootPort (
> 
> +  IN      PRIMARY_ROOT_PORT_NODE  *RootPortNode,
> 
> +  IN      UINT8                   RootPortSecBus,
> 
> +  IN      UINT8                   RootPortSubBus
> 
> +)
> 
> +{
> 
> +  LIST_ENTRY              *Link;
> 
> +  PRIMARY_ROOT_PORT_NODE  *Temp;
> 
> +
> 
> +  if ( !RootPortNode) {
> 
> +    return FALSE;
> 
> +  }
> 
> +  Link = &RootPortNode->NeighborRootPort;
> 
> +  do {
> 
> +    Temp = PRIMARY_ROOT_PORT_NODE_FROM_LINK ( Link);
> 
> +    if ( RootPortSecBus >= Temp->SecondaryBusStart
> 
> +        && RootPortSubBus <= Temp->SecondaryBusEnd) {
> 
> +      //
> 
> +      // given root port's secondary & subordinate within its primary ports
> 
> +      // hence return as child port
> 
> +      //
> 
> +      return TRUE;
> 
> +    }
> 
> +    Link = Link->ForwardLink;
> 
> +  } while (Link != &RootPortNode->NeighborRootPort);
> 
> +  //
> 
> +  // the given root port's secondary / subordinate bus numbers do not
> belong to
> 
> +  // any existing primary root port's bus range hence consider another
> primary
> 
> +  // root port of the root bridge controller
> 
> +  //
> 
> +  return FALSE;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Create the vector of PCI Feature configuration table as per the number of
> 
> +  the PCI Root Ports given, assigns default value to the PCI features
> supported
> 
> +  and assign its address to the global variable
> "mPciFeaturesConfigurationTableInstances".
> 
> +
> 
> +  @param  NumberOfRootPorts   An input arguement of UINTN to indicate
> number of
> 
> +                              primary PCI physical Root Bridge devices found
> 
> +
> 
> +  @retval EFI_OUT_OF_RESOURCES  unable to allocate buffer to store PCI
> feature
> 
> +                                configuration table for all the physical PCI root
> 
> +                                ports given
> 
> +          EFI_SUCCESS           PCI Feature COnfiguration table created for all
> 
> +                                the PCI Rooot ports reported
> 
> + */
> 
> +EFI_STATUS
> 
> +CreatePciFeaturesConfigurationTableInstances (
> 
> +  IN  UINTN NumberOfRootPorts
> 
> +  )
> 
> +{
> 
> +  OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> *PciRootBridgePortFeatures = NULL;
> 
> +  UINTN                                     Instances;
> 
> +
> 
> +  PciRootBridgePortFeatures = AllocateZeroPool (
> 
> +                                sizeof ( OTHER_PCI_FEATURES_CONFIGURATION_TABLE) *
> NumberOfRootPorts
> 
> +                                );
> 
> +  if ( !PciRootBridgePortFeatures) {
> 
> +    return EFI_OUT_OF_RESOURCES;
> 
> +  }
> 
> +
> 
> +  for ( Instances = 0; Instances < NumberOfRootPorts; Instances++) {
> 
> +    PciRootBridgePortFeatures [Instances].ID                    = Instances + 1;
> 
> +    PciRootBridgePortFeatures [Instances].Max_Payload_Size      =
> PCIE_MAX_PAYLOAD_SIZE_4096B;
> 
> +    PciRootBridgePortFeatures [Instances].Max_Read_Request_Size =
> PCIE_MAX_READ_REQ_SIZE_4096B;
> 
> +    PciRootBridgePortFeatures [Instances].Lock_Max_Read_Request_Size =
> FALSE;
> 
> +  }
> 
> +  mPciFeaturesConfigurationTableInstances = PciRootBridgePortFeatures;
> 
> +  return EFI_SUCCESS;
> 
> +}
> 
> +
> 
> +/**
> 
> +  This routine pairs the each PCI Root Port node with one of the PCI Feature
> 
> +  Configuration Table node. Each physical PCI Root Port has its own PCI
> feature
> 
> +  configuration table which will used for aligning all its downstream
> components.
> 
> +
> 
> +  @param  NumberOfRootPorts     inputs the number of physical PCI root
> ports
> 
> +                                found on the Root bridge instance
> 
> +
> 
> +  @retval EFI_INVALID_PARAMETER if the primary PCI root ports list is
> vacant when
> 
> +                                there is one or more PCI Root port indicated as per
> 
> +                                input parameter
> 
> +          EFI_UNSUPPORTED       The PCI Root Port nodes not paired equally with
> 
> +                                the PCI Configuration Table nodes
> 
> +          EFI_SUCCESS           each PCI feature configuration node is paired
> equally
> 
> +                                with each PCI Root port in the list
> 
> +**/
> 
> +EFI_STATUS
> 
> +AssignPciFeaturesConfigurationTable (
> 
> +  IN  UINTN NumberOfRootPorts
> 
> +  )
> 
> +{
> 
> +  UINTN                       Instances;
> 
> +  LIST_ENTRY                  *Link;
> 
> +  PRIMARY_ROOT_PORT_NODE      *Temp;
> 
> +
> 
> +  if ( !mPrimaryRootPortList
> 
> +      && NumberOfRootPorts) {
> 
> +    DEBUG ((
> 
> +        DEBUG_ERROR,
> 
> +        "Critical error! no internal table setup for %d PCI Root ports \n",
> 
> +        NumberOfRootPorts
> 
> +    ));
> 
> +    return EFI_INVALID_PARAMETER;
> 
> +  }
> 
> +
> 
> +  if ( NumberOfRootPorts) {
> 
> +    Link = &mPrimaryRootPortList->NeighborRootPort;
> 
> +    for ( Instances = 0
> 
> +        ; (Instances < NumberOfRootPorts)
> 
> +        ; Instances++
> 
> +    ) {
> 
> +      Temp = PRIMARY_ROOT_PORT_NODE_FROM_LINK ( Link);
> 
> +      Temp->OtherPciFeaturesConfigurationTable =
> &mPciFeaturesConfigurationTableInstances [Instances];
> 
> +      DEBUG ((
> 
> +          DEBUG_INFO,
> 
> +          "Assigned to %dth primary root port\n",
> 
> +          Instances
> 
> +      ));
> 
> +
> 
> +      Link = Link->ForwardLink;
> 
> +    }
> 
> +    if ( Link != &mPrimaryRootPortList->NeighborRootPort) {
> 
> +      DEBUG ((
> 
> +          DEBUG_ERROR,
> 
> +          "Error!! PCI Root Port list is not properly matched with Config., Table
> list \n"
> 
> +      ));
> 
> +      return EFI_UNSUPPORTED;
> 
> +    }
> 
> +  }
> 
> +  return  EFI_SUCCESS;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Prepare each PCI Controller (Root Port) with its own PCI Feature
> configuration
> 
> +  table node that can be used for tracking to align all PCI nodes in its
> hierarchy.
> 
> +
> 
> +  @param  PrimaryRootPorts      A pointer to PRIMARY_ROOT_PORT_NODE
> 
> +  @param  NumberOfRootPorts     Total number of pysical primary PCI Root
> ports
> 
> +
> 
> +  @retval EFI_OUT_OF_RESOURCES  unable to allocate buffer to store PCI
> feature
> 
> +                                configuration table for all the physical PCI root
> 
> +                                ports given
> 
> +          EFI_INVALID_PARAMETER if the primary PCI root ports list is vacant
> when
> 
> +                                there is one or more PCI Root port indicated as per
> 
> +                                input parameter
> 
> +          EFI_UNSUPPORTED       The PCI Root Port nodes not paired equally with
> 
> +                                the PCI Configuration Table nodes
> 
> +          EFI_SUCCESS           each PCI feature configuration node is paired
> equally
> 
> +                                with each PCI Root port in the list
> 
> +**/
> 
> +EFI_STATUS
> 
> +PreparePciControllerConfigurationTable (
> 
> +  IN  PRIMARY_ROOT_PORT_NODE    *PrimaryRootPorts,
> 
> +  IN  UINTN                     NumberOfRootPorts
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS                    Status;
> 
> +
> 
> +  mPrimaryRootPortList = PrimaryRootPorts;
> 
> +  DEBUG ((
> 
> +      DEBUG_INFO, "Number of primary Root Ports found on this bridge
> = %d\n",
> 
> +      NumberOfRootPorts
> 
> +  ));
> 
> +
> 
> +  Status = CreatePciFeaturesConfigurationTableInstances
> ( NumberOfRootPorts);
> 
> +  if ( EFI_ERROR(Status)) {
> 
> +    DEBUG ((
> 
> +        DEBUG_ERROR, "Unexpected memory node creation error for PCI
> features!\n"
> 
> +    ));
> 
> +  } else {
> 
> +    //
> 
> +    // align the primary root port nodes list with the PCI Feature configuration
> 
> +    // table. Note that the PCI Feature configuration table is not maintain for
> 
> +    // the RCiEP devices
> 
> +    //
> 
> +    Status = AssignPciFeaturesConfigurationTable ( NumberOfRootPorts);
> 
> +  }
> 
> +  return Status;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Scan all the nodes of the RootBridge to identify and create a separate list
> 
> +  of all primary physical PCI root ports and link each with its own instance of
> 
> +  the PCI Feature Configuration Table.
> 
> +
> 
> +  @param  RootBridge    A pointer to the PCI_IO_DEVICE of the PCI Root
> Bridge
> 
> +
> 
> +  @retval EFI_OUT_OF_RESOURCES  unable to allocate buffer to store PCI
> feature
> 
> +                                configuration table for all the physical PCI root
> 
> +                                ports given
> 
> +          EFI_NOT_FOUND         No PCI Bridge device found
> 
> +          EFI_SUCCESS           PCI Feature COnfiguration table created for all
> 
> +                                the PCI Rooot ports found
> 
> +          EFI_INVALID_PARAMETER invalid parameter passed to the routine
> which
> 
> +                                creates the PCI controller node for the primary
> 
> +                                Root post list
> 
> +**/
> 
> +EFI_STATUS
> 
> +RecordPciRootPortBridges (
> 
> +  IN  PCI_IO_DEVICE           *RootBridge
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS              Status = EFI_NOT_FOUND;
> 
> +  LIST_ENTRY              *Link;
> 
> +  PCI_IO_DEVICE           *Device;
> 
> +  UINTN                   NumberOfRootPorts;
> 
> +  PRIMARY_ROOT_PORT_NODE  *PrimaryRootPorts,
> 
> +                          *TempNode;
> 
> +  UINT8                   RootPortSecBus,
> 
> +                          RootPortSubBus;
> 
> +
> 
> +  DEBUG ((
> 
> +      DEBUG_INFO, "<<********** RecordPciRootPortBridges -start
> *************>>\n"
> 
> +  ));
> 
> +  NumberOfRootPorts = 0;
> 
> +  PrimaryRootPorts = NULL;
> 
> +  for ( Link = RootBridge->ChildList.ForwardLink
> 
> +      ; Link != &RootBridge->ChildList
> 
> +      ; Link = Link->ForwardLink
> 
> +  ) {
> 
> +    Device = PCI_IO_DEVICE_FROM_LINK (Link);
> 
> +    if (IS_PCI_BRIDGE (&Device->Pci)) {
> 
> +      Status = GetPciRootPortBusAssigned (
> 
> +                  Device,
> 
> +                  NULL,
> 
> +                  &RootPortSecBus,
> 
> +                  &RootPortSubBus
> 
> +                  );
> 
> +      if ( !EFI_ERROR(Status)) {
> 
> +        DEBUG ((
> 
> +            DEBUG_INFO, "::Device [%02x|%02x|%02x] - SecBus=0x%x,
> SubBus=0x%x\n",
> 
> +            Device->BusNumber, Device->DeviceNumber, Device-
> >FunctionNumber,
> 
> +            RootPortSecBus, RootPortSubBus
> 
> +        ));
> 
> +      } else {
> 
> +        DEBUG ((
> 
> +            DEBUG_ERROR, "Unexpected read error [0x%lx]::Device
> [%02x|%02x|%02x]\n",
> 
> +            Status, Device->BusNumber, Device->DeviceNumber, Device-
> >FunctionNumber
> 
> +        ));
> 
> +        RootPortSecBus = RootPortSubBus = 0;
> 
> +        continue;
> 
> +      }
> 
> +
> 
> +      if ( !PrimaryRootPorts) {
> 
> +        NumberOfRootPorts++;
> 
> +        Status = CreatePrimaryPciRootPortNode (
> 
> +                    RootBridge,
> 
> +                    Device,
> 
> +                    RootPortSecBus,
> 
> +                    RootPortSubBus,
> 
> +                    &PrimaryRootPorts
> 
> +                    );
> 
> +        if ( EFI_ERROR(Status)) {
> 
> +          //
> 
> +          // abort mission to scan for all primary roots ports of a bridge
> 
> +          // controller if error encountered for very first PCI primary root port
> 
> +          //
> 
> +          DEBUG ((
> 
> +              DEBUG_ERROR, "Unexpected node creation error [0x%lx]::Device
> [%02x|%02x|%02x]\n",
> 
> +              Status, Device->BusNumber, Device->DeviceNumber, Device-
> >FunctionNumber
> 
> +          ));
> 
> +          return Status;
> 
> +        }
> 
> +        DEBUG ((
> 
> +            DEBUG_INFO, "first primary root port found::Device
> [%02x|%02x|%02x]\n",
> 
> +            Device->BusNumber, Device->DeviceNumber, Device-
> >FunctionNumber
> 
> +        ));
> 
> +      } else {
> 
> +        if ( !CheckChildRootPort ( PrimaryRootPorts, RootPortSecBus,
> RootPortSubBus)) {
> 
> +          NumberOfRootPorts++;
> 
> +          TempNode = NULL;
> 
> +          Status = CreatePrimaryPciRootPortNode (
> 
> +                      RootBridge,
> 
> +                      Device,
> 
> +                      RootPortSecBus,
> 
> +                      RootPortSubBus,
> 
> +                      &TempNode
> 
> +                      );
> 
> +          if ( !EFI_ERROR(Status)) {
> 
> +            //
> 
> +            // another primary root port found on the same bridge controller
> 
> +            // insert in the node list
> 
> +            //
> 
> +            InsertTailList ( &PrimaryRootPorts->NeighborRootPort, &TempNode-
> >NeighborRootPort);
> 
> +            DEBUG ((
> 
> +                DEBUG_INFO, "next primary root port found::Device
> [%02x|%02x|%02x]\n",
> 
> +                Device->BusNumber, Device->DeviceNumber, Device-
> >FunctionNumber
> 
> +            ));
> 
> +          } else {
> 
> +            DEBUG ((
> 
> +                DEBUG_ERROR, "Unexpected node creation error [0x%lx]::Device
> [%02x|%02x|%02x]\n",
> 
> +                Status, Device->BusNumber, Device->DeviceNumber, Device-
> >FunctionNumber
> 
> +            ));
> 
> +          }
> 
> +        }
> 
> +      }
> 
> +    }
> 
> +  }
> 
> +  //
> 
> +  // prepare the PCI root port and its feature configuration table list
> 
> +  //
> 
> +  if ( NumberOfRootPorts) {
> 
> +    Status = PreparePciControllerConfigurationTable (
> 
> +                PrimaryRootPorts,
> 
> +                NumberOfRootPorts
> 
> +              );
> 
> +
> 
> +  } else {
> 
> +    DEBUG ((
> 
> +        DEBUG_INFO, "No PCI Root port found on this bridge!\n"
> 
> +    ));
> 
> +  }
> 
> +
> 
> +  DEBUG ((
> 
> +      DEBUG_INFO, "<<********** RecordPciRootPortBridges - end
> **********>>\n"
> 
> +  ));
> 
> +  return Status;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Enumerate all the nodes of the specified root bridge or PCI-PCI Bridge, to
> 
> +  configure the other PCI features.
> 
> +
> 
> +  @param RootBridge          A pointer to the PCI_IO_DEVICE.
> 
> +
> 
> +  @retval EFI_SUCCESS           The other PCI features configuration during
> enumeration
> 
> +                                of all the nodes of the PCI root bridge instance were
> 
> +                                programmed in PCI-compliance pattern along with the
> 
> +                                device-specific policy, as applicable.
> 
> +  @retval EFI_UNSUPPORTED       One of the override operation maong the
> nodes of
> 
> +                                the PCI hierarchy resulted in a incompatible address
> 
> +                                range.
> 
> +  @retval EFI_INVALID_PARAMETER The override operation is performed
> with invalid input
> 
> +                                parameters.
> 
> +**/
> 
> +EFI_STATUS
> 
> +EnumerateOtherPciFeatures (
> 
> +  IN PCI_IO_DEVICE          *RootBridge
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS            Status;
> 
> +  CHAR16                *Str;
> 
> +  UINTN                 OtherPciFeatureConfigPhase;
> 
> +
> 
> +  //
> 
> +  // check on PCI features configuration is complete and re-enumeration is
> required
> 
> +  //
> 
> +  if ( !CheckPciFeaturesConfigurationRequired ( RootBridge)) {
> 
> +    return EFI_ALREADY_STARTED;
> 
> +  }
> 
> +
> 
> +  Str = ConvertDevicePathToText (
> 
> +          DevicePathFromHandle (RootBridge->Handle),
> 
> +          FALSE,
> 
> +          FALSE
> 
> +        );
> 
> +  DEBUG ((DEBUG_INFO, "Enumerating PCI features for Root Bridge %s\n",
> Str != NULL ? Str : L""));
> 
> +
> 
> +  for ( OtherPciFeatureConfigPhase = PciFeatureRootBridgeScan
> 
> +      ; OtherPciFeatureConfigPhase <= PciFeatureConfigurationComplete
> 
> +      ; OtherPciFeatureConfigPhase++
> 
> +      ) {
> 
> +    switch ( OtherPciFeatureConfigPhase){
> 
> +      case  PciFeatureRootBridgeScan:
> 
> +        SetupPciFeaturesConfigurationDefaults ();
> 
> +        //
> 
> +        //first scan the entire root bridge heirarchy for the primary PCI root
> ports
> 
> +        //
> 
> +        RecordPciRootPortBridges ( RootBridge);
> 
> +        break;
> 
> +
> 
> +      case  PciFeatureGetDevicePolicy:
> 
> +      case  PciFeatureSetupPhase:
> 
> +        DEBUG ((
> 
> +            DEBUG_INFO, "<<********** SetupPciFeatures - start
> **********>>\n"
> 
> +        ));
> 
> +        //
> 
> +        // enumerate the other PCI features
> 
> +        //
> 
> +        Status = SetupPciFeatures ( RootBridge, OtherPciFeatureConfigPhase);
> 
> +
> 
> +        DEBUG ((
> 
> +            DEBUG_INFO, "<<********** SetupPciFeatures - end
> **********>>\n"
> 
> +        ));
> 
> +        break;
> 
> +
> 
> +      case  PciFeatureConfigurationPhase:
> 
> +        //
> 
> +        // override the PCI features as per enumeration phase
> 
> +        //
> 
> +        DEBUG ((DEBUG_INFO, "PCI features override for Root Bridge %s\n",
> Str != NULL ? Str : L""));
> 
> +        DEBUG ((
> 
> +            DEBUG_INFO, "<<********** ProgramPciFeatures - start
> **********>>\n"
> 
> +        ));
> 
> +        Status = ProgramPciFeatures ( RootBridge);
> 
> +        DEBUG ((
> 
> +            DEBUG_INFO, "<<********** ProgramPciFeatures - end
> **********>>\n"
> 
> +        ));
> 
> +        break;
> 
> +
> 
> +      case  PciFeatureConfigurationComplete:
> 
> +        //
> 
> +        // clean up the temporary resource nodes created for this root bridge
> 
> +        //
> 
> +        DestroyPrimaryRootPortNodes ();
> 
> +
> 
> +        ErasePciFeaturesConfigurationTable ();
> 
> +    }
> 
> +  }
> 
> +
> 
> +  if (Str != NULL) {
> 
> +    FreePool (Str);
> 
> +  }
> 
> +  //
> 
> +  // mark this root bridge as PCI features configuration complete, and no
> new
> 
> +  // enumeration is required
> 
> +  //
> 
> +  AddRootBridgeInPciFeaturesConfigCompletionList ( RootBridge, FALSE);
> 
> +  return Status;
> 
> +}
> 
> +
> 
> +/**
> 
> +  This routine is invoked from the Stop () interface for the EFI handle of the
> 
> +  RootBridge. Free up its node of type
> PCI_FEATURE_CONFIGURATION_COMPLETION_LIST.
> 
> +
> 
> +  @param  RootBridge      A pointer to the PCI_IO_DEVICE
> 
> +**/
> 
> +VOID
> 
> +DestroyRootBridgePciFeaturesConfigCompletionList (
> 
> +  IN PCI_IO_DEVICE          *RootBridge
> 
> +  )
> 
> +{
> 
> +  LIST_ENTRY                                  *Link;
> 
> +  PCI_FEATURE_CONFIGURATION_COMPLETION_LIST   *Temp;
> 
> +
> 
> +  if ( mPciFeaturesConfigurationCompletionList) {
> 
> +    Link = &mPciFeaturesConfigurationCompletionList->RootBridgeLink;
> 
> +
> 
> +    do {
> 
> +      Temp =
> PCI_FEATURE_CONFIGURATION_COMPLETION_LIST_FROM_LINK (Link);
> 
> +      if ( Temp->RootBridgeHandle == RootBridge->Handle) {
> 
> +        RemoveEntryList ( Link);
> 
> +        FreePool ( Temp);
> 
> +        return;
> 
> +      }
> 
> +      Link = Link->ForwardLink;
> 
> +    } while (Link != &mPciFeaturesConfigurationCompletionList-
> >RootBridgeLink);
> 
> +  }
> 
> +  //
> 
> +  // not found on the PCI feature configuration completion list, return
> 
> +  //
> 
> +  return;
> 
> +}
> 
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> new file mode 100644
> index 0000000000..9f225fa993
> --- /dev/null
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> @@ -0,0 +1,201 @@
> +/** @file
> 
> +  PCI standard feature support functions implementation for PCI Bus
> module..
> 
> +
> 
> +Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> 
> +SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> +
> 
> +**/
> 
> +
> 
> +#ifndef _EFI_PCI_FEATURES_SUPPORT_H_
> 
> +#define _EFI_PCI_FEATURES_SUPPORT_H_
> 
> +
> 
> +#include "PciBus.h"
> 
> +#include "PciPlatformSupport.h"
> 
> +
> 
> +//
> 
> +// Macro definitions for the PCI Features support PCD
> 
> +//
> 
> +#define PCI_FEATURE_SUPPORT_FLAG_MPS  BIT0
> 
> +#define PCI_FEATURE_SUPPORT_FLAG_MRRS BIT1
> 
> +
> 
> +//
> 
> +// defines the data structure to hold the details of the PCI Root port devices
> 
> +//
> 
> +typedef struct _PRIMARY_ROOT_PORT_NODE
> PRIMARY_ROOT_PORT_NODE;
> 
> +
> 
> +//
> 
> +// defines the data structure to hold the configuration data for the other
> PCI
> 
> +// features
> 
> +//
> 
> +typedef struct _OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> OTHER_PCI_FEATURES_CONFIGURATION_TABLE;
> 
> +
> 
> +//
> 
> +// Defines for the PCI features configuration completion and re-
> enumeration list
> 
> +//
> 
> +typedef struct _PCI_FEATURE_CONFIGURATION_COMPLETION_LIST
> PCI_FEATURE_CONFIGURATION_COMPLETION_LIST;
> 
> +
> 
> +//
> 
> +// Signature value for the PCI Root Port node
> 
> +//
> 
> +#define PCI_ROOT_PORT_SIGNATURE               SIGNATURE_32 ('p', 'c', 'i', 'p')
> 
> +
> 
> +//
> 
> +// Definitions of the PCI Root Port data structure members
> 
> +//
> 
> +struct _PRIMARY_ROOT_PORT_NODE {
> 
> +  //
> 
> +  // Signature header
> 
> +  //
> 
> +  UINT32                                    Signature;
> 
> +  //
> 
> +  // linked list pointers to next node
> 
> +  //
> 
> +  LIST_ENTRY                                NeighborRootPort;
> 
> +  //
> 
> +  // EFI handle of the parent Root Bridge instance
> 
> +  //
> 
> +  EFI_HANDLE                                RootBridgeHandle;
> 
> +  //
> 
> +  // EFI handle of the PCI controller
> 
> +  //
> 
> +  EFI_HANDLE                                RootPortHandle;
> 
> +  //
> 
> +  // PCI Secondary bus value of the PCI controller
> 
> +  //
> 
> +  UINT8                                     SecondaryBusStart;
> 
> +  //
> 
> +  // PCI Subordinate bus value of the PCI controller
> 
> +  //
> 
> +  UINT8                                     SecondaryBusEnd;
> 
> +  //
> 
> +  // pointer to the corresponding PCI feature configuration Table node
> 
> +  //
> 
> +  OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> *OtherPciFeaturesConfigurationTable;
> 
> +};
> 
> +
> 
> +#define PRIMARY_ROOT_PORT_NODE_FROM_LINK(a) \
> 
> +  CR (a, PRIMARY_ROOT_PORT_NODE, NeighborRootPort,
> PCI_ROOT_PORT_SIGNATURE)
> 
> +
> 
> +//
> 
> +// Definition of the PCI Feature configuration Table members
> 
> +//
> 
> +struct _OTHER_PCI_FEATURES_CONFIGURATION_TABLE {
> 
> +  //
> 
> +  // Configuration Table ID
> 
> +  //
> 
> +  UINTN                                     ID;
> 
> +  //
> 
> +  // to configure the PCI feature Maximum payload size to maintain the data
> packet
> 
> +  // size among all the PCI devices in the PCI hierarchy
> 
> +  //
> 
> +  UINT8                                     Max_Payload_Size;
> 
> +  //
> 
> +  // to configure the PCI feature maximum read request size to maintain the
> memory
> 
> +  // requester size among all the PCI devices in the PCI hierarchy
> 
> +  //
> 
> +  UINT8                                     Max_Read_Request_Size;
> 
> +  //
> 
> +  // lock the Max_Read_Request_Size for the entire PCI tree of a root port
> 
> +  //
> 
> +  BOOLEAN                                   Lock_Max_Read_Request_Size;
> 
> +};
> 
> +
> 
> +
> 
> +//
> 
> +// PCI feature configuration node signature value
> 
> +//
> 
> +#define PCI_FEATURE_CONFIGURATION_SIGNATURE
> SIGNATURE_32 ('p', 'c', 'i', 'f')
> 
> +
> 
> +struct _PCI_FEATURE_CONFIGURATION_COMPLETION_LIST {
> 
> +  //
> 
> +  // Signature header
> 
> +  //
> 
> +  UINT32                                    Signature;
> 
> +  //
> 
> +  // link to next Root Bridge whose PCI Feature configuration is complete
> 
> +  //
> 
> +  LIST_ENTRY                                RootBridgeLink;
> 
> +  //
> 
> +  // EFI handle of the Root Bridge whose PCI feature configuration is
> complete
> 
> +  //
> 
> +  EFI_HANDLE                                RootBridgeHandle;
> 
> +  //
> 
> +  // indication for complete re-enumeration of the PCI feature configuration
> 
> +  //
> 
> +  BOOLEAN                                   ReEnumeratePciFeatureConfiguration;
> 
> +};
> 
> +
> 
> +#define
> PCI_FEATURE_CONFIGURATION_COMPLETION_LIST_FROM_LINK(a) \
> 
> +  CR (a, PCI_FEATURE_CONFIGURATION_COMPLETION_LIST,
> RootBridgeLink, PCI_FEATURE_CONFIGURATION_SIGNATURE)
> 
> +
> 
> +//
> 
> +// Declaration of the internal sub-phases within the PCI Feature
> enumeration
> 
> +//
> 
> +typedef enum {
> 
> +  //
> 
> +  // initial phase in configuring the other PCI features to record the primary
> 
> +  // root ports
> 
> +  //
> 
> +  PciFeatureRootBridgeScan,
> 
> +  //
> 
> +  // get the PCI device-specific platform policies and align with device
> capabilities
> 
> +  //
> 
> +  PciFeatureGetDevicePolicy,
> 
> +  //
> 
> +  // align all PCI nodes in the PCI heirarchical tree
> 
> +  //
> 
> +  PciFeatureSetupPhase,
> 
> +  //
> 
> +  // finally override to complete configuration of the PCI feature
> 
> +  //
> 
> +  PciFeatureConfigurationPhase,
> 
> +  //
> 
> +  // PCI feature configuration complete
> 
> +  //
> 
> +  PciFeatureConfigurationComplete
> 
> +
> 
> +}PCI_FEATURE_CONFIGURATION_PHASE;
> 
> +
> 
> +/**
> 
> +  Main routine to indicate platform selection of any of the other PCI features
> 
> +  to be configured by this driver
> 
> +
> 
> +  @retval TRUE    platform has selected the other PCI features to be
> configured
> 
> +          FALSE   platform has not selected any of the other PCI features
> 
> +**/
> 
> +BOOLEAN
> 
> +CheckOtherPciFeaturesPcd (
> 
> +  );
> 
> +
> 
> +/**
> 
> +  Enumerate all the nodes of the specified root bridge or PCI-PCI Bridge, to
> 
> +  configure the other PCI features.
> 
> +
> 
> +  @param RootBridge          A pointer to the PCI_IO_DEVICE.
> 
> +
> 
> +  @retval EFI_SUCCESS           The other PCI features configuration during
> enumeration
> 
> +                                of all the nodes of the PCI root bridge instance were
> 
> +                                programmed in PCI-compliance pattern along with the
> 
> +                                device-specific policy, as applicable.
> 
> +  @retval EFI_UNSUPPORTED       One of the override operation maong the
> nodes of
> 
> +                                the PCI hierarchy resulted in a incompatible address
> 
> +                                range.
> 
> +  @retval EFI_INVALID_PARAMETER The override operation is performed
> with invalid input
> 
> +                                parameters.
> 
> +**/
> 
> +EFI_STATUS
> 
> +EnumerateOtherPciFeatures (
> 
> +  IN PCI_IO_DEVICE           *RootBridge
> 
> +  );
> 
> +
> 
> +/**
> 
> +  This routine is invoked from the Stop () interface for the EFI handle of the
> 
> +  RootBridge. Free up its node of type
> PCI_FEATURE_CONFIGURATION_COMPLETION_LIST.
> 
> +
> 
> +  @param  RootBridge      A pointer to the PCI_IO_DEVICE
> 
> +**/
> 
> +VOID
> 
> +DestroyRootBridgePciFeaturesConfigCompletionList (
> 
> +  IN PCI_IO_DEVICE          *RootBridge
> 
> +  );
> 
> +#endif
> 
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> new file mode 100644
> index 0000000000..d94037d69a
> --- /dev/null
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> @@ -0,0 +1,565 @@
> +/** @file
> 
> +  This file encapsulate the usage of PCI Platform Protocol
> 
> +
> 
> +  This file define the necessary hooks used to obtain the platform
> 
> +  level data and policies which could be used in the PCI Enumeration phases
> 
> +
> 
> +Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> 
> +SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> +
> 
> +**/
> 
> +
> 
> +#include "PciPlatformSupport.h"
> 
> +
> 
> +EFI_PCI_PLATFORM_PROTOCOL                     *mPciPlatformProtocol;
> 
> +EFI_PCI_OVERRIDE_PROTOCOL                     *mPciOverrideProtocol;
> 
> +
> 
> +EFI_PCI_PLATFORM_PROTOCOL2                    *mPciPlatformProtocol2;
> 
> +EFI_PCI_OVERRIDE_PROTOCOL2                    *mPciOverrideProtocol2;
> 
> +
> 
> +
> 
> +/**
> 
> +  This function retrieves the PCI Platform Protocol published by platform
> driver
> 
> +
> 
> +**/
> 
> +VOID
> 
> +GetPciPlatformProtocol (
> 
> +  )
> 
> +{
> 
> +  mPciPlatformProtocol2 = NULL;
> 
> +  gBS->LocateProtocol (
> 
> +      &gEfiPciPlatformProtocol2Guid,
> 
> +      NULL,
> 
> +      (VOID **) &mPciPlatformProtocol2
> 
> +  );
> 
> +
> 
> +  //
> 
> +  // If PCI Platform protocol doesn't exist, try to get Pci Override Protocol.
> 
> +  //
> 
> +  if (mPciPlatformProtocol2 == NULL) {
> 
> +    mPciOverrideProtocol2 = NULL;
> 
> +    gBS->LocateProtocol (
> 
> +        &gEfiPciOverrideProtocol2Guid,
> 
> +        NULL,
> 
> +        (VOID **) &mPciOverrideProtocol2
> 
> +    );
> 
> +  }
> 
> +  //
> 
> +  // fetch the old PCI Platform Protocols if new are not installed
> 
> +  //
> 
> +  if (mPciOverrideProtocol2 == NULL) {
> 
> +
> 
> +    mPciPlatformProtocol = NULL;
> 
> +    gBS->LocateProtocol (
> 
> +        &gEfiPciPlatformProtocolGuid,
> 
> +        NULL,
> 
> +        (VOID **) &mPciPlatformProtocol
> 
> +    );
> 
> +
> 
> +    //
> 
> +    // If PCI Platform protocol doesn't exist, try to  get Pci Override Protocol.
> 
> +    //
> 
> +    if (mPciPlatformProtocol == NULL) {
> 
> +      mPciOverrideProtocol = NULL;
> 
> +      gBS->LocateProtocol (
> 
> +          &gEfiPciOverrideProtocolGuid,
> 
> +          NULL,
> 
> +          (VOID **) &mPciOverrideProtocol
> 
> +      );
> 
> +    }
> 
> +  }
> 
> +}
> 
> +
> 
> +/**
> 
> +  This function indicates the presence of PCI Platform driver
> 
> +  @retval     TRUE or FALSE
> 
> +**/
> 
> +BOOLEAN
> 
> +CheckPciPlatformProtocolInstall (
> 
> +  )
> 
> +{
> 
> +  if (mPciPlatformProtocol2 != NULL) {
> 
> +    return TRUE;
> 
> +  } else if (mPciOverrideProtocol2 != NULL) {
> 
> +    return TRUE;
> 
> +  } else {
> 
> +    if (mPciPlatformProtocol != NULL) {
> 
> +      return TRUE;
> 
> +    } else if (mPciOverrideProtocol != NULL){
> 
> +      return TRUE;
> 
> +    }
> 
> +  }
> 
> +  return FALSE;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Provides the hooks from the PCI bus driver to every PCI controller
> (device/function) at various
> 
> +  stages of the PCI enumeration process that allow the host bridge driver to
> preinitialize individual
> 
> +  PCI controllers before enumeration.
> 
> +
> 
> +  This function is called during the PCI enumeration process. No specific
> action is expected from this
> 
> +  member function. It allows the host bridge driver to preinitialize individual
> PCI controllers before
> 
> +  enumeration.
> 
> +
> 
> +  @param[in] HostBridgeHandle     The associated PCI host bridge handle.
> 
> +  @param[in] RootBridgeHandle     The associated PCI root bridge handle.
> 
> +  @param[in] RootBridgePciAddress The address of the PCI device on the
> PCI bus.
> 
> +  @param[in] Phase          The phase of the PCI controller enumeration.
> 
> +  @param[in] ExecPhase      Defines the execution phase of the PCI chipset
> driver.
> 
> +
> 
> +  @retval    Status         returns the status from the PCI Platform protocol as is
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +PciPlatformPreprocessController (
> 
> +  IN EFI_HANDLE                                    HostBridgeHandle,
> 
> +  IN EFI_HANDLE                                    RootBridgeHandle,
> 
> +  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS
> RootBridgePciAddress,
> 
> +  IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE  Phase,
> 
> +  IN EFI_PCI_EXECUTION_PHASE                       ExecPhase
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS  Status;
> 
> +
> 
> +  if (mPciPlatformProtocol2 != NULL) {
> 
> +    //
> 
> +    // Call PlatformPci::PrepController() if the protocol is present.
> 
> +    //
> 
> +    Status = mPciPlatformProtocol2->PlatformPrepController (
> 
> +
> (EFI_PCI_PLATFORM_PROTOCOL*)mPciPlatformProtocol2,
> 
> +                                      HostBridgeHandle,
> 
> +                                      RootBridgeHandle,
> 
> +                                      RootBridgePciAddress,
> 
> +                                      Phase,
> 
> +                                      ExecPhase
> 
> +                                    );
> 
> +  } else if (mPciOverrideProtocol2 != NULL) {
> 
> +    //
> 
> +    // Call PlatformPci::PrepController() if the protocol is present.
> 
> +    //
> 
> +    Status = mPciOverrideProtocol2->PlatformPrepController (
> 
> +
> (EFI_PCI_PLATFORM_PROTOCOL*)mPciOverrideProtocol2,
> 
> +                                      HostBridgeHandle,
> 
> +                                      RootBridgeHandle,
> 
> +                                      RootBridgePciAddress,
> 
> +                                      Phase,
> 
> +                                      ExecPhase
> 
> +                                    );
> 
> +  } else {
> 
> +    if (mPciPlatformProtocol != NULL) {
> 
> +      //
> 
> +      // Call PlatformPci::PrepController() if the protocol is present.
> 
> +      //
> 
> +      Status = mPciPlatformProtocol->PlatformPrepController (
> 
> +                                      mPciPlatformProtocol,
> 
> +                                      HostBridgeHandle,
> 
> +                                      RootBridgeHandle,
> 
> +                                      RootBridgePciAddress,
> 
> +                                      Phase,
> 
> +                                      ExecPhase
> 
> +                                    );
> 
> +    } else if (mPciOverrideProtocol != NULL) {
> 
> +      //
> 
> +      // Call PlatformPci::PrepController() if the protocol is present.
> 
> +      //
> 
> +      Status = mPciOverrideProtocol->PlatformPrepController (
> 
> +                                      mPciOverrideProtocol,
> 
> +                                      HostBridgeHandle,
> 
> +                                      RootBridgeHandle,
> 
> +                                      RootBridgePciAddress,
> 
> +                                      Phase,
> 
> +                                      ExecPhase
> 
> +                                    );
> 
> +    } else {
> 
> +      //
> 
> +      // return PCI Platform Protocol not found
> 
> +      //
> 
> +      return EFI_NOT_FOUND;
> 
> +    }
> 
> +  }
> 
> +  return Status;
> 
> +}
> 
> +
> 
> +/**
> 
> +  This function notifies the PCI Platform driver about the PCI host bridge
> resource
> 
> +  allocation phase and PCI execution phase.
> 
> +
> 
> +  @param[in]  HostBridge     The handle of the host bridge controller.
> 
> +  @param[in]  Phase          The phase of the PCI bus enumeration.
> 
> +  @param[in]  ExecPhase      Defines the execution phase of the PCI chipset
> driver.
> 
> +  @retval     Status          returns the status from the PCI Platform protocol as
> is
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +PciPlatformNotifyPhase (
> 
> +  IN  EFI_HANDLE                                      HostBridgeHandle,
> 
> +  IN  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE   Phase,
> 
> +  IN  EFI_PCI_EXECUTION_PHASE                         ExecPhase
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS  Status;
> 
> +
> 
> +  if ( mPciPlatformProtocol2 != NULL) {
> 
> +    Status = mPciPlatformProtocol2->PlatformNotify (
> 
> +
> (EFI_PCI_PLATFORM_PROTOCOL*)mPciPlatformProtocol2,
> 
> +                                      HostBridgeHandle,
> 
> +                                      Phase,
> 
> +                                      ExecPhase
> 
> +                                    );
> 
> +  } else if ( mPciOverrideProtocol2 != NULL) {
> 
> +    Status = mPciOverrideProtocol2->PlatformNotify (
> 
> +
> (EFI_PCI_PLATFORM_PROTOCOL*)mPciOverrideProtocol2,
> 
> +                                      HostBridgeHandle,
> 
> +                                      Phase,
> 
> +                                      ExecPhase
> 
> +                                    );
> 
> +  } else {
> 
> +
> 
> +    if ( mPciPlatformProtocol != NULL) {
> 
> +      Status = mPciPlatformProtocol->PlatformNotify (
> 
> +                                      mPciPlatformProtocol,
> 
> +                                      HostBridgeHandle,
> 
> +                                      Phase,
> 
> +                                      ExecPhase
> 
> +                                    );
> 
> +    } else if ( mPciOverrideProtocol != NULL){
> 
> +      Status = mPciOverrideProtocol->PlatformNotify (
> 
> +                                      mPciOverrideProtocol,
> 
> +                                      HostBridgeHandle,
> 
> +                                      Phase,
> 
> +                                      ExecPhase
> 
> +                                    );
> 
> +    } else {
> 
> +      //
> 
> +      // return PCI Platform Protocol not found
> 
> +      //
> 
> +      return EFI_NOT_FOUND;
> 
> +    }
> 
> +  }
> 
> +  return Status;
> 
> +}
> 
> +
> 
> +/**
> 
> +  This function retrieves the PCI platform policy.
> 
> +
> 
> +  @param  PciPolicy     pointer to the legacy EFI_PCI_PLATFORM_POLICY
> 
> +  @retval Status        returns the status from the PCI Platform protocol as is
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +PciGetPlatformPolicy (
> 
> +  OUT EFI_PCI_PLATFORM_POLICY *PciPolicy
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS  Status;
> 
> +
> 
> +  if ( mPciPlatformProtocol2 != NULL) {
> 
> +      Status = mPciPlatformProtocol2->GetPlatformPolicy (
> 
> +
> (EFI_PCI_PLATFORM_PROTOCOL*)mPciPlatformProtocol2,
> 
> +                                        PciPolicy
> 
> +                                      );
> 
> +  } else if ( mPciOverrideProtocol2 != NULL) {
> 
> +      Status = mPciOverrideProtocol2->GetPlatformPolicy (
> 
> +
> (EFI_PCI_PLATFORM_PROTOCOL*)mPciOverrideProtocol2,
> 
> +                                        PciPolicy
> 
> +                                      );
> 
> +  } else {
> 
> +    if ( mPciPlatformProtocol != NULL) {
> 
> +      Status = mPciPlatformProtocol->GetPlatformPolicy (
> 
> +                                      mPciPlatformProtocol,
> 
> +                                      PciPolicy
> 
> +                                    );
> 
> +    }
> 
> +
> 
> +    if ( mPciOverrideProtocol != NULL) {
> 
> +      Status = mPciOverrideProtocol->GetPlatformPolicy (
> 
> +                                      mPciOverrideProtocol,
> 
> +                                      PciPolicy
> 
> +                                    );
> 
> +    } else {
> 
> +      //
> 
> +      // return PCI Platform Protocol not found
> 
> +      //
> 
> +      return EFI_NOT_FOUND;
> 
> +    }
> 
> +  }
> 
> +  return Status;
> 
> +}
> 
> +
> 
> +/**
> 
> +  This function retrieves the Option ROM image and size from the Platform.
> 
> +
> 
> +  It uses the PCI_IO_DEVICE internal fields are used to store OpROM
> image/size
> 
> +
> 
> +  @param Controller     An EFI handle for the PCI bus controller.
> 
> +  @param PciIoDevice    A PCI_IO_DEVICE pointer to the PCI IO device to be
> registered.
> 
> +
> 
> +  @retval EFI_SUCCESS            The option ROM was available for this device
> and loaded into memory.
> 
> +  @retval EFI_NOT_FOUND          No option ROM was available for this device.
> 
> +  @retval EFI_OUT_OF_RESOURCES   No memory was available to load the
> option ROM.
> 
> +  @retval EFI_DEVICE_ERROR       An error occurred in obtaining the option
> ROM.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +GetPlatformPciOptionRom (
> 
> +  IN  EFI_HANDLE                    Controller,
> 
> +  IN  PCI_IO_DEVICE                 *PciIoDevice
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS  Status;
> 
> +  VOID        *PlatformOpRomBuffer;
> 
> +  UINTN       PlatformOpRomSize;
> 
> +
> 
> +  if (mPciPlatformProtocol2 != NULL) {
> 
> +    Status = mPciPlatformProtocol2->GetPciRom (
> 
> +
> (EFI_PCI_PLATFORM_PROTOCOL*)mPciPlatformProtocol2,
> 
> +                                      PciIoDevice->Handle,
> 
> +                                      &PlatformOpRomBuffer,
> 
> +                                      &PlatformOpRomSize
> 
> +                                      );
> 
> +  } else if (mPciOverrideProtocol2 != NULL) {
> 
> +    Status = mPciOverrideProtocol2->GetPciRom (
> 
> +
> (EFI_PCI_PLATFORM_PROTOCOL*)mPciOverrideProtocol2,
> 
> +                                      PciIoDevice->Handle,
> 
> +                                      &PlatformOpRomBuffer,
> 
> +                                      &PlatformOpRomSize
> 
> +                                      );
> 
> +  } else {
> 
> +    if (mPciPlatformProtocol != NULL) {
> 
> +      Status = mPciPlatformProtocol->GetPciRom (
> 
> +                                      mPciPlatformProtocol,
> 
> +                                      PciIoDevice->Handle,
> 
> +                                      &PlatformOpRomBuffer,
> 
> +                                      &PlatformOpRomSize
> 
> +                                      );
> 
> +    } else if (mPciOverrideProtocol != NULL) {
> 
> +      Status = mPciOverrideProtocol->GetPciRom (
> 
> +                                        mPciOverrideProtocol,
> 
> +                                        PciIoDevice->Handle,
> 
> +                                        &PlatformOpRomBuffer,
> 
> +                                        &PlatformOpRomSize
> 
> +                                        );
> 
> +    } else {
> 
> +      //
> 
> +      // return PCI Platform Protocol not found
> 
> +      //
> 
> +      return EFI_NOT_FOUND;
> 
> +    }
> 
> +  }
> 
> +
> 
> +  if (!EFI_ERROR (Status)) {
> 
> +    PciIoDevice->EmbeddedRom    = FALSE;
> 
> +    PciIoDevice->RomSize        = (UINT32)PlatformOpRomSize;
> 
> +    PciIoDevice->PciIo.RomSize  = PlatformOpRomSize;
> 
> +    PciIoDevice->PciIo.RomImage = PlatformOpRomBuffer;
> 
> +  }
> 
> +  return Status;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Helper routine to indicate whether the given PCI device specific policy
> value
> 
> +  dictates to override the Max_Payload_Size to a particular value, or set as
> per
> 
> +  device capability.
> 
> +
> 
> +  @param  MPS     Input device-specific policy should be in terms of type
> 
> +                  EFI_PCI_CONF_MAX_PAYLOAD_SIZE
> 
> +
> 
> +  @retval TRUE    Setup Max_Payload_Size as per device capability
> 
> +          FALSE   override as per device-specific platform policy
> 
> +**/
> 
> +BOOLEAN
> 
> +SetupMpsAsPerDeviceCapability (
> 
> +  IN  UINT8                   MPS
> 
> +)
> 
> +{
> 
> +  if ( MPS == EFI_PCI_CONF_MAX_PAYLOAD_SIZE_AUTO) {
> 
> +    return TRUE;
> 
> +  } else {
> 
> +    return FALSE;
> 
> +  }
> 
> +}
> 
> +
> 
> +/**
> 
> +  Helper routine to indicate whether the given PCI device specific policy
> value
> 
> +  dictates to override the Max_Read_Req_Size to a particular value, or set as
> per
> 
> +  device capability.
> 
> +
> 
> +  @param  MRRS    Input device-specific policy should be in terms of type
> 
> +                  EFI_PCI_CONF_MAX_READ_REQ_SIZE
> 
> +
> 
> +  @retval TRUE    Setup Max_Read_Req_Size as per device capability
> 
> +          FALSE   override as per device-specific platform policy
> 
> +**/
> 
> +BOOLEAN
> 
> +SetupMrrsAsPerDeviceCapability (
> 
> +  IN  UINT8                   MRRS
> 
> +)
> 
> +{
> 
> +  if ( MRRS == EFI_PCI_CONF_MAX_READ_REQ_SIZE_AUTO) {
> 
> +    return TRUE;
> 
> +  } else {
> 
> +    return FALSE;
> 
> +  }
> 
> +}
> 
> +
> 
> +/**
> 
> +  Routine to translate the given device-specific platform policy from type
> 
> +  EFI_PCI_CONF_MAX_PAYLOAD_SIZE to HW-specific value, as per PCI Base
> Specification
> 
> +  Revision 4.0; for the PCI feature Max_Payload_Size.
> 
> +
> 
> +  @param  MPS     Input device-specific policy should be in terms of type
> 
> +                  EFI_PCI_CONF_MAX_PAYLOAD_SIZE
> 
> +
> 
> +  @retval         Range values for the Max_Payload_Size as defined in the PCI
> 
> +                  Base Specification 4.0
> 
> +**/
> 
> +UINT8
> 
> +TranslateMpsSetupValueToPci (
> 
> +  IN  UINT8                   MPS
> 
> +)
> 
> +{
> 
> +  switch (MPS) {
> 
> +    case EFI_PCI_CONF_MAX_PAYLOAD_SIZE_128B:
> 
> +      return PCIE_MAX_PAYLOAD_SIZE_128B;
> 
> +    case EFI_PCI_CONF_MAX_PAYLOAD_SIZE_256B:
> 
> +      return PCIE_MAX_PAYLOAD_SIZE_256B;
> 
> +    case EFI_PCI_CONF_MAX_PAYLOAD_SIZE_512B:
> 
> +      return PCIE_MAX_PAYLOAD_SIZE_512B;
> 
> +    case EFI_PCI_CONF_MAX_PAYLOAD_SIZE_1024B:
> 
> +      return PCIE_MAX_PAYLOAD_SIZE_1024B;
> 
> +    case EFI_PCI_CONF_MAX_PAYLOAD_SIZE_2048B:
> 
> +      return PCIE_MAX_PAYLOAD_SIZE_2048B;
> 
> +    case EFI_PCI_CONF_MAX_PAYLOAD_SIZE_4096B:
> 
> +      return PCIE_MAX_PAYLOAD_SIZE_4096B;
> 
> +    default:
> 
> +      return PCIE_MAX_PAYLOAD_SIZE_128B;
> 
> +  }
> 
> +}
> 
> +
> 
> +/**
> 
> +  Routine to translate the given device-specific platform policy from type
> 
> +  EFI_PCI_CONF_MAX_READ_REQ_SIZE to HW-specific value, as per PCI
> Base Specification
> 
> +  Revision 4.0; for the PCI feature Max_Read_Req_Size.
> 
> +
> 
> +  @param  MRRS    Input device-specific policy should be in terms of type
> 
> +                  EFI_PCI_CONF_MAX_READ_REQ_SIZE
> 
> +
> 
> +  @retval         Range values for the Max_Read_Req_Size as defined in the
> PCI
> 
> +                  Base Specification 4.0
> 
> +**/
> 
> +UINT8
> 
> +TranslateMrrsSetupValueToPci (
> 
> +  IN  UINT8                   MRRS
> 
> +)
> 
> +{
> 
> +  switch (MRRS) {
> 
> +    case EFI_PCI_CONF_MAX_READ_REQ_SIZE_128B:
> 
> +      return PCIE_MAX_READ_REQ_SIZE_128B;
> 
> +    case EFI_PCI_CONF_MAX_READ_REQ_SIZE_256B:
> 
> +      return PCIE_MAX_READ_REQ_SIZE_256B;
> 
> +    case EFI_PCI_CONF_MAX_READ_REQ_SIZE_512B:
> 
> +      return PCIE_MAX_READ_REQ_SIZE_512B;
> 
> +    case EFI_PCI_CONF_MAX_READ_REQ_SIZE_1024B:
> 
> +      return PCIE_MAX_READ_REQ_SIZE_1024B;
> 
> +    case EFI_PCI_CONF_MAX_READ_REQ_SIZE_2048B:
> 
> +      return PCIE_MAX_READ_REQ_SIZE_2048B;
> 
> +    case EFI_PCI_CONF_MAX_READ_REQ_SIZE_4096B:
> 
> +      return PCIE_MAX_READ_REQ_SIZE_4096B;
> 
> +    default:
> 
> +      return PCIE_MAX_READ_REQ_SIZE_128B;
> 
> +  }
> 
> +}
> 
> +
> 
> +/**
> 
> +  Generic routine to setup the PCI features as per its predetermined
> defaults.
> 
> +**/
> 
> +VOID
> 
> +SetupDefaultsDevicePlatformPolicy (
> 
> +  IN  PCI_IO_DEVICE               *PciDevice
> 
> +  )
> 
> +{
> 
> +  PciDevice->SetupMPS = EFI_PCI_CONF_MAX_PAYLOAD_SIZE_AUTO;
> 
> +  PciDevice->SetupMRRS = EFI_PCI_CONF_MAX_READ_REQ_SIZE_AUTO;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Intermediate routine to either get the PCI device specific platform policies
> 
> +  through the PCI Platform Protocol, or its alias the PCI Override Protocol.
> 
> +
> 
> +  @param  PciIoDevice         A pointer to PCI_IO_DEVICE
> 
> +  @param  PciPlatformProtocol A pointer to
> EFI_PCI_PLATFORM_PROTOCOL2
> 
> +
> 
> +  @retval EFI_STATUS          The direct status from the PCI Platform Protocol
> 
> +  @retval EFI_SUCCESS         if on returning predetermined PCI features
> defaults,
> 
> +                              for the case when protocol returns as EFI_UNSUPPORTED
> 
> +                              to indicate PCI device exist and it has no platform
> 
> +                              policy defined.
> 
> +**/
> 
> +EFI_STATUS
> 
> +GetPciDevicePlatformPolicyEx (
> 
> +  IN  PCI_IO_DEVICE               *PciIoDevice,
> 
> +  IN  EFI_PCI_PLATFORM_PROTOCOL2  *PciPlatformProtocol
> 
> +  )
> 
> +{
> 
> +  EFI_PCI_PLATFORM_EXTENDED_POLICY  PciPlatformExtendedPolicy;
> 
> +  EFI_STATUS                        Status;
> 
> +
> 
> +  ZeroMem ( &PciPlatformExtendedPolicy, sizeof
> (EFI_PCI_PLATFORM_EXTENDED_POLICY));
> 
> +  Status = PciPlatformProtocol->GetDevicePolicy (
> 
> +                                  PciPlatformProtocol,
> 
> +                                  PciIoDevice->Handle,
> 
> +                                  &PciPlatformExtendedPolicy
> 
> +                                  );
> 
> +  //
> 
> +  // platform chipset policies are returned for this PCI device
> 
> +  //
> 
> +  if (!EFI_ERROR(Status)) {
> 
> +    PciIoDevice->SetupMPS = PciPlatformExtendedPolicy.DeviceCtlMPS;
> 
> +    PciIoDevice->SetupMRRS = PciPlatformExtendedPolicy.DeviceCtlMRRS;
> 
> +  }
> 
> +  //
> 
> +  // platform chipset policies are not provided for this PCI device
> 
> +  //
> 
> +  if (EFI_ERROR(Status) == EFI_UNSUPPORTED) {
> 
> +    //
> 
> +    // let the enumeration happen as per the PCI standard way
> 
> +    //
> 
> +    SetupDefaultsDevicePlatformPolicy ( PciIoDevice);
> 
> +    return EFI_SUCCESS;
> 
> +  }
> 
> +
> 
> +  return Status;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Gets the PCI device-specific platform policy from the PCI Platform Protocol.
> 
> +  If no PCI Platform protocol is published than setup the PCI feature to
> predetermined
> 
> +  defaults, in order to align all the PCI devices in the PCI hierarchy, as
> applicable.
> 
> +
> 
> +  @param  PciDevice     A pointer to PCI_IO_DEVICE
> 
> +
> 
> +  @retval EFI_STATUS    The direct status from the PCI Platform Protocol
> 
> +  @retval EFI_SUCCESS   On return of predetermined PCI features defaults,
> for
> 
> +                        the case when protocol returns as EFI_UNSUPPORTED to
> 
> +                        indicate PCI device exist and it has no platform policy
> 
> +                        defined. Also, on returns when no PCI Platform Protocol
> 
> +                        exist.
> 
> +**/
> 
> +EFI_STATUS
> 
> +GetPciDevicePlatformPolicy (
> 
> +  IN PCI_IO_DEVICE          *PciDevice
> 
> +  )
> 
> +{
> 
> +  if ( mPciPlatformProtocol2 != NULL) {
> 
> +    return GetPciDevicePlatformPolicyEx ( PciDevice, mPciPlatformProtocol2);
> 
> +  } else if (mPciOverrideProtocol2 != NULL) {
> 
> +    return GetPciDevicePlatformPolicyEx ( PciDevice, mPciOverrideProtocol2);
> 
> +  } else {
> 
> +    //
> 
> +    // new PCI Platform Protocol 2 is not installed; let the enumeration
> happen
> 
> +    // as per PCI standard way
> 
> +    //
> 
> +    SetupDefaultsDevicePlatformPolicy ( PciDevice);
> 
> +    return EFI_SUCCESS;
> 
> +  }
> 
> +}
> 
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
> new file mode 100644
> index 0000000000..d54e46b950
> --- /dev/null
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
> @@ -0,0 +1,193 @@
> +/** @file
> 
> +  This file encapsulate the usage of PCI Platform Protocol
> 
> +
> 
> +  This file define the necessary hooks used to obtain the platform
> 
> +  level data and policies which could be used in the PCI Enumeration phases
> 
> +
> 
> +Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> 
> +SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> +
> 
> +**/
> 
> +
> 
> +
> 
> +#ifndef _EFI_PCI_PLATFORM_SUPPORT_H_
> 
> +#define _EFI_PCI_PLATFORM_SUPPORT_H_
> 
> +
> 
> +#include "PciBus.h"
> 
> +
> 
> +/**
> 
> +  This function retrieves the PCI Platform Protocol published by platform
> driver
> 
> +
> 
> +**/
> 
> +VOID
> 
> +GetPciPlatformProtocol (
> 
> +  );
> 
> +
> 
> +/**
> 
> +  This function indicates the presence of PCI Platform driver
> 
> +  @retval     TRUE or FALSE
> 
> +**/
> 
> +BOOLEAN
> 
> +CheckPciPlatformProtocolInstall (
> 
> +  );
> 
> +
> 
> +
> 
> +/**
> 
> +  Provides the hooks from the PCI bus driver to every PCI controller
> (device/function) at various
> 
> +  stages of the PCI enumeration process that allow the host bridge driver to
> preinitialize individual
> 
> +  PCI controllers before enumeration.
> 
> +
> 
> +  This function is called during the PCI enumeration process. No specific
> action is expected from this
> 
> +  member function. It allows the host bridge driver to preinitialize individual
> PCI controllers before
> 
> +  enumeration.
> 
> +
> 
> +  @param[in] HostBridgeHandle     The associated PCI host bridge handle.
> 
> +  @param[in] RootBridgeHandle     The associated PCI root bridge handle.
> 
> +  @param[in] RootBridgePciAddress The address of the PCI device on the
> PCI bus.
> 
> +  @param[in] Phase          The phase of the PCI controller enumeration.
> 
> +  @param[in] ExecPhase      Defines the execution phase of the PCI chipset
> driver.
> 
> +
> 
> +  @retval    Status         returns the status from the PCI Platform protocol as is
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +PciPlatformPreprocessController (
> 
> +  IN EFI_HANDLE                                    HostBridgeHandle,
> 
> +  IN EFI_HANDLE                                    RootBridgeHandle,
> 
> +  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS
> RootBridgePciAddress,
> 
> +  IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE  Phase,
> 
> +  IN EFI_PCI_EXECUTION_PHASE                       ExecPhase
> 
> +  );
> 
> +
> 
> +/**
> 
> +  This function notifies the PCI Platform driver about the PCI host bridge
> resource
> 
> +  allocation phase and PCI execution phase.
> 
> +
> 
> +  @param[in]  HostBridge     The handle of the host bridge controller.
> 
> +  @param[in]  Phase          The phase of the PCI bus enumeration.
> 
> +  @param[in]  ExecPhase      Defines the execution phase of the PCI chipset
> driver.
> 
> +  @retval     Status          returns the status from the PCI Platform protocol as
> is
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +PciPlatformNotifyPhase (
> 
> +  IN  EFI_HANDLE                                      HostBridgeHandle,
> 
> +  IN  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE   Phase,
> 
> +  IN  EFI_PCI_EXECUTION_PHASE                         ExecPhase
> 
> +  );
> 
> +
> 
> +/**
> 
> +  This function retrieves the PCI platform policy.
> 
> +
> 
> +  @param  PciPolicy     pointer to the legacy EFI_PCI_PLATFORM_POLICY
> 
> +  @retval Status        returns the status from the PCI Platform protocol as is
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +PciGetPlatformPolicy (
> 
> +  OUT EFI_PCI_PLATFORM_POLICY *PciPolicy
> 
> +  );
> 
> +
> 
> +/**
> 
> +  This function retrieves the Option ROM image and size from the Platform.
> 
> +
> 
> +  It uses the PCI_IO_DEVICE internal fields are used to store OpROM
> image/size
> 
> +
> 
> +  @param Controller     An EFI handle for the PCI bus controller.
> 
> +  @param PciIoDevice    A PCI_IO_DEVICE pointer to the PCI IO device to be
> registered.
> 
> +
> 
> +  @retval EFI_SUCCESS            The option ROM was available for this device
> and loaded into memory.
> 
> +  @retval EFI_NOT_FOUND          No option ROM was available for this device.
> 
> +  @retval EFI_OUT_OF_RESOURCES   No memory was available to load the
> option ROM.
> 
> +  @retval EFI_DEVICE_ERROR       An error occurred in obtaining the option
> ROM.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +GetPlatformPciOptionRom (
> 
> +  IN  EFI_HANDLE                    Controller,
> 
> +  IN  PCI_IO_DEVICE                 *PciIoDevice
> 
> +  );
> 
> +
> 
> +/**
> 
> +  Gets the PCI device-specific platform policy from the PCI Platform Protocol.
> 
> +  If no PCI Platform protocol is published than setup the PCI feature to
> predetermined
> 
> +  defaults, in order to align all the PCI devices in the PCI hierarchy, as
> applicable.
> 
> +
> 
> +  @param  PciDevice     A pointer to PCI_IO_DEVICE
> 
> +
> 
> +  @retval EFI_STATUS    The direct status from the PCI Platform Protocol
> 
> +  @retval EFI_SUCCESS   On return of predetermined PCI features defaults,
> for
> 
> +                        the case when protocol returns as EFI_UNSUPPORTED to
> 
> +                        indicate PCI device exist and it has no platform policy
> 
> +                        defined. Also, on returns when no PCI Platform Protocol
> 
> +                        exist.
> 
> +**/
> 
> +EFI_STATUS
> 
> +GetPciDevicePlatformPolicy (
> 
> +  IN PCI_IO_DEVICE          *PciDevice
> 
> +  );
> 
> +
> 
> +/**
> 
> +  Helper routine to indicate whether the given PCI device specific policy
> value
> 
> +  dictates to override the Max_Payload_Size to a particular value, or set as
> per
> 
> +  device capability.
> 
> +
> 
> +  @param  MPS     Input device-specific policy should be in terms of type
> 
> +                  EFI_PCI_CONF_MAX_PAYLOAD_SIZE
> 
> +
> 
> +  @retval TRUE    Setup Max_Payload_Size as per device capability
> 
> +          FALSE   override as per device-specific platform policy
> 
> +**/
> 
> +BOOLEAN
> 
> +SetupMpsAsPerDeviceCapability (
> 
> +  IN  UINT8                   MPS
> 
> +);
> 
> +
> 
> +/**
> 
> +  Helper routine to indicate whether the given PCI device specific policy
> value
> 
> +  dictates to override the Max_Read_Req_Size to a particular value, or set as
> per
> 
> +  device capability.
> 
> +
> 
> +  @param  MRRS    Input device-specific policy should be in terms of type
> 
> +                  EFI_PCI_CONF_MAX_READ_REQ_SIZE
> 
> +
> 
> +  @retval TRUE    Setup Max_Read_Req_Size as per device capability
> 
> +          FALSE   override as per device-specific platform policy
> 
> +**/
> 
> +BOOLEAN
> 
> +SetupMrrsAsPerDeviceCapability (
> 
> +  IN  UINT8                   MRRS
> 
> +);
> 
> +
> 
> +/**
> 
> +  Routine to translate the given device-specific platform policy from type
> 
> +  EFI_PCI_CONF_MAX_PAYLOAD_SIZE to HW-specific value, as per PCI Base
> Specification
> 
> +  Revision 4.0; for the PCI feature Max_Payload_Size.
> 
> +
> 
> +  @param  MPS     Input device-specific policy should be in terms of type
> 
> +                  EFI_PCI_CONF_MAX_PAYLOAD_SIZE
> 
> +
> 
> +  @retval         Range values for the Max_Payload_Size as defined in the PCI
> 
> +                  Base Specification 4.0
> 
> +**/
> 
> +UINT8
> 
> +TranslateMpsSetupValueToPci (
> 
> +  IN  UINT8                   MPS
> 
> +);
> 
> +
> 
> +/**
> 
> +  Routine to translate the given device-specific platform policy from type
> 
> +  EFI_PCI_CONF_MAX_READ_REQ_SIZE to HW-specific value, as per PCI
> Base Specification
> 
> +  Revision 4.0; for the PCI feature Max_Read_Req_Size.
> 
> +
> 
> +  @param  MRRS    Input device-specific policy should be in terms of type
> 
> +                  EFI_PCI_CONF_MAX_READ_REQ_SIZE
> 
> +
> 
> +  @retval         Range values for the Max_Read_Req_Size as defined in the
> PCI
> 
> +                  Base Specification 4.0
> 
> +**/
> 
> +UINT8
> 
> +TranslateMrrsSetupValueToPci (
> 
> +  IN  UINT8                   MRRS
> 
> +);
> 
> +#endif
> 
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c
> index 4969ee0f64..755423f77b 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c
> @@ -198,20 +198,7 @@ CalculateApertureIo16 (
>      //
> 
>      Status = EFI_NOT_FOUND;
> 
>      PciPolicy = 0;
> 
> -    if (gPciPlatformProtocol != NULL) {
> 
> -      Status = gPciPlatformProtocol->GetPlatformPolicy (
> 
> -                                       gPciPlatformProtocol,
> 
> -                                       &PciPolicy
> 
> -                                       );
> 
> -    }
> 
> -
> 
> -    if (EFI_ERROR (Status) && gPciOverrideProtocol != NULL) {
> 
> -      Status = gPciOverrideProtocol->GetPlatformPolicy (
> 
> -                                       gPciOverrideProtocol,
> 
> -                                       &PciPolicy
> 
> -                                       );
> 
> -    }
> 
> -
> 
> +    Status = PciGetPlatformPolicy ( &PciPolicy);
> 
>      if (!EFI_ERROR (Status)) {
> 
>        if ((PciPolicy & EFI_RESERVE_ISA_IO_ALIAS) != 0) {
> 
>          mReserveIsaAliases = TRUE;
> 
> diff --git a/MdeModulePkg/MdeModulePkg.dec
> b/MdeModulePkg/MdeModulePkg.dec
> index 17beb45235..7bcbe5a3ea 100644
> --- a/MdeModulePkg/MdeModulePkg.dec
> +++ b/MdeModulePkg/MdeModulePkg.dec
> @@ -1026,6 +1026,16 @@
>    # @Prompt Enable UEFI Stack Guard.
> 
> 
> gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard|FALSE|BOOLEAN|0
> x30001055
> 
> 
> 
> +  ## This PCD is to indicate the PCI Bus driver to setup other new PCI
> features.
> 
> +  #  Each PCI feature is represented by its mask bit position and it configures
> 
> +  #  if that bit is set.
> 
> +  #
> 
> +  #   Bit 0 - if set, the PCI Bus driver programs the device's
> Max_Payload_Size.<BR>
> 
> +  #   Bit 1 - if set, the PCI Bus driver programs the device's
> Max_Read_Req_Size.<BR>
> 
> +  #   Bit 2 to 31 - Reserved for future use by the PCI Bus driver.<BR>
> 
> +  # @Prompt The UEFI PCU Bus driver enables the new set of other PCI
> Features.
> 
> +
> gEfiMdeModulePkgTokenSpaceGuid.PcdOtherPciFeatures|0x00000003|UIN
> T32|0x30001056
> 
> +
> 
>  [PcdsFixedAtBuild, PcdsPatchableInModule]
> 
>    ## Dynamic type PCD can be registered callback function for Pcd setting
> action.
> 
>    #  PcdMaxPeiPcdCallBackNumberPerPcdEntry indicates the maximum
> number of callback function
> 
> --
> 2.21.0.windows.1


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

View/Reply Online (#48880): https://edk2.groups.io/g/devel/message/48880
Mute This Topic: https://groups.io/mt/34264504/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub  [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-

Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH] PciBusDxe: New PCI features Max_Payload_Size, Max_Read_Req_Size
Posted by Ni, Ray 4 years, 5 months ago
More comments:
1. IsPciRootPortEmpty(): can you just check whether PciDevice->ChildList is empty by using IsListEmpty (&PciDevice->ChildList)?
2. Can you point to me which spec requires the MPS to be 128 for empty root ports?
3. GetPciRootPortBusAssigned() is dangerous because it assumes the input PciDevice points to the bridge.
4. RecordPciRootPortBridges() could be simplified to just collect all PciDevice instances who:
    a. belongs to the linked list of the root bridge
    b. is a bridge

> -----Original Message-----
> From: Ni, Ray
> Sent: Monday, October 14, 2019 2:57 PM
> To: Javeed, Ashraf <ashraf.javeed@intel.com>; devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>
> Subject: RE: [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH] PciBusDxe: New
> PCI features Max_Payload_Size, Max_Read_Req_Size
> 
> Javeed,
> The patch is too big.
> I recommend you separate the patch to several small patches. The goal of
> that is to make reviewers today (like me) and future easy to understand the
> code changes.  Some potential changes that can be separated out:
> 1. "DEBUG_ERROR/DEBUG_INFO"
> 2. The change related to the PciPlatform/PciOverride invocation can also be
> separated out and it can be in a patch before any changes to implement the
> features.
> 3. The change that splits the original StartPciDevicesOnBridge() to
> RegisterPciDevicesOnBridge() and StartPciRootPortsOnBridge(). This change
> can be separated out as a patch before any changes to implement the
> features.
> 
> 
> Some other comments:
> 1. CheckPciPlatformProtocolInstall(): better to rename to
> IsPciPlatformAvailable(). "Check" doesn't tell how to interpret the return
> result. "Is" does.
> 2. GetPciPlatformProtocol(): better to rename to InitializePciPlatform ().
> 3. Why the type cast is needed in below code? If it is because PciPlatform2
> protocol reuses the prototype of GetPciRom defined for PciPlatform protocol,
> I suggest you define GetPciRom for PciPlatform2. Type redefinition seems a
> duplication. But below type-cast is more annoyed.
> 
>     Status = mPciPlatformProtocol2->GetPciRom (
>                                       (EFI_PCI_PLATFORM_PROTOCOL*)mPciPlatformProtocol2,
>                                       PciIoDevice->Handle,
>                                       &PlatformOpRomBuffer,
>                                       &PlatformOpRomSize
>                                       );
> 
> 4. Please run ECC tool and fix all coding style issue
> 5. I don't quite understand what *primary* PCI root port is. So I don't quite
> understand what RecordPciRootPortBridges() does.
> 
> Thanks,
> Ray
> 
> > -----Original Message-----
> > From: Javeed, Ashraf <ashraf.javeed@intel.com>
> > Sent: Monday, September 23, 2019 10:21 PM
> > To: devel@edk2.groups.io
> > Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A
> <hao.a.wu@intel.com>;
> > Ni, Ray <ray.ni@intel.com>
> > Subject: [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH] PciBusDxe: New PCI
> > features Max_Payload_Size, Max_Read_Req_Size
> >
> > REF: https://bugzilla.tianocore.org/show_bug.cgi?id=2194
> >
> > The EDK2 Kernel PciBusDxe driver is enhanced to enable the configuration
> > of PCI features like Max_Payload_Size and Max_Read_Req_Size.
> >
> > Max_Payload_Size:- The PCI Device Control register provides this feature
> > register field which controls the maximum data packet (TLP) size that a
> > PCI device should maintain as a requester. The PCI Bus driver is required
> > to maintain a highest common value supported by all the PCI devices in a
> > PCIe hierarchy, especially in case of isochronous applications.
> >
> > Max_Read_Req_Size:- The PCI Device Control register provides this
> feature
> > register field which controls the maximum memory read request size that a
> > PCI device should maintain as a requester. The PCI Bus driver is required
> > to maintain a common value, same as Max_Payload_Size, in case of
> > isochronous applications only; or else, it should maintain the user
> > requested value uniformly in a PCIe hierarchy (PCI root port and its
> > downstream devices).
> >
> > The PCI Base Specification 4 Revision 1 contains detailed information
> > about these features. The EDK2 PCI Bus driver needs to enable the
> > configuration of these features as per the PCI Base specification.
> >
> > The EDK2 PCI Bus driver also needs to take the PCI device-specific
> > platform policy into the consideration while programming these features;
> > thus the code changes to support these, is explicitly dependent on the
> > new PCI Platform Protocol interface definition defined in the below
> > record:-
> > https://bugzilla.tianocore.org/show_bug.cgi?id=1954
> >
> > Signed-off-by: Ashraf Javeed <ashraf.javeed@intel.com>
> > Cc: Jian J Wang <jian.j.wang@intel.com>
> > Cc: Hao A Wu <hao.a.wu@intel.com>
> > Cc: Ray Ni <ray.ni@intel.com>
> > ---
> >  MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c               |   23 ++------------
> >  MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h               |   14 ++++++++-
> >  MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf          |    9 +++++-
> >  MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c     |  229
> >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > ++++++++++++++++++++++++++++-----------------------------------------------
> -
> >  MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c        |  139
> > ++++++++++++++++++++-----------------------------------------------------------
> ---
> >  MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c |   34
> > ++++++++++++--------
> >  MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c    | 1601
> >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > +++++++++
> >  MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h    |  201
> >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > ++
> >  MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c   |  565
> >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > +++++++++++++++++++++++++++++++++++++++++
> >  MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h   |  193
> >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > +++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >  MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c   |   15 +--------
> >  MdeModulePkg/MdeModulePkg.dec                         |   10 ++++++
> >  12 files changed, 2797 insertions(+), 236 deletions(-)
> >
> > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c
> > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c
> > index b020ce50ce..2503b298f4 100644
> > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c
> > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c
> > @@ -8,7 +8,7 @@
> >    PCI Root Bridges. So it means platform needs install PCI Root Bridge IO
> > protocol for each
> >
> >    PCI Root Bus and install PCI Host Bridge Resource Allocation Protocol.
> >
> >
> >
> > -Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
> >
> > +Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
> >
> >  SPDX-License-Identifier: BSD-2-Clause-Patent
> >
> >
> >
> >  **/
> >
> > @@ -34,8 +34,6 @@ BOOLEAN                                       gFullEnumeration     =
> TRUE;
> >  UINT64                                        gAllOne              = 0xFFFFFFFFFFFFFFFFULL;
> >
> >  UINT64                                        gAllZero             = 0;
> >
> >
> >
> > -EFI_PCI_PLATFORM_PROTOCOL                     *gPciPlatformProtocol;
> >
> > -EFI_PCI_OVERRIDE_PROTOCOL                     *gPciOverrideProtocol;
> >
> >  EDKII_IOMMU_PROTOCOL                          *mIoMmuProtocol;
> >
> >
> >
> >
> >
> > @@ -266,24 +264,7 @@ PciBusDriverBindingStart (
> >    // If PCI Platform protocol is available, get it now.
> >
> >    // If the platform implements this, it must be installed before BDS phase
> >
> >    //
> >
> > -  gPciPlatformProtocol = NULL;
> >
> > -  gBS->LocateProtocol (
> >
> > -        &gEfiPciPlatformProtocolGuid,
> >
> > -        NULL,
> >
> > -        (VOID **) &gPciPlatformProtocol
> >
> > -        );
> >
> > -
> >
> > -  //
> >
> > -  // If PCI Platform protocol doesn't exist, try to Pci Override Protocol.
> >
> > -  //
> >
> > -  if (gPciPlatformProtocol == NULL) {
> >
> > -    gPciOverrideProtocol = NULL;
> >
> > -    gBS->LocateProtocol (
> >
> > -          &gEfiPciOverrideProtocolGuid,
> >
> > -          NULL,
> >
> > -          (VOID **) &gPciOverrideProtocol
> >
> > -          );
> >
> > -  }
> >
> > +  GetPciPlatformProtocol ();
> >
> >
> >
> >    if (mIoMmuProtocol == NULL) {
> >
> >      gBS->LocateProtocol (
> >
> > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> > index 504a1b1c12..7955bf8a26 100644
> > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> > @@ -27,6 +27,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
> >  #include <Protocol/PciOverride.h>
> >
> >  #include <Protocol/PciEnumerationComplete.h>
> >
> >  #include <Protocol/IoMmu.h>
> >
> > +#include <Protocol/PciPlatform2.h>
> >
> > +#include <Protocol/PciOverride2.h>
> >
> >
> >
> >  #include <Library/DebugLib.h>
> >
> >  #include <Library/UefiDriverEntryPoint.h>
> >
> > @@ -79,6 +81,7 @@ typedef enum {
> >  #include "PciPowerManagement.h"
> >
> >  #include "PciHotPlugSupport.h"
> >
> >  #include "PciLib.h"
> >
> > +#include "PciFeatureSupport.h"
> >
> >
> >
> >  #define VGABASE1  0x3B0
> >
> >  #define VGALIMIT1 0x3BB
> >
> > @@ -263,9 +266,13 @@ struct _PCI_IO_DEVICE {
> >
> >
> >    BOOLEAN                                   IsPciExp;
> >
> >    //
> >
> > -  // For SR-IOV
> >
> > +  // For PCI Express Capability List Structure
> >
> >    //
> >
> >    UINT8                                     PciExpressCapabilityOffset;
> >
> > +  PCI_CAPABILITY_PCIEXP                     PciExpStruct;
> >
> > +  //
> >
> > +  // For SR-IOV
> >
> > +  //
> >
> >    UINT32                                    AriCapabilityOffset;
> >
> >    UINT32                                    SrIovCapabilityOffset;
> >
> >    UINT32                                    MrIovCapabilityOffset;
> >
> > @@ -279,6 +286,11 @@ struct _PCI_IO_DEVICE {
> >    // This field is used to support this case.
> >
> >    //
> >
> >    UINT16                                    BridgeIoAlignment;
> >
> > +  //
> >
> > +  // Other PCI features setup flags
> >
> > +  //
> >
> > +  UINT8                                     SetupMPS;
> >
> > +  UINT8                                     SetupMRRS;
> >
> >  };
> >
> >
> >
> >  #define PCI_IO_DEVICE_FROM_PCI_IO_THIS(a) \
> >
> > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
> > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
> > index 05c22025b8..13768d7ded 100644
> > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
> > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
> > @@ -2,7 +2,7 @@
> >  #  The PCI bus driver will probe all PCI devices and allocate MMIO and IO
> > space for these devices.
> >
> >  #  Please use PCD feature flag PcdPciBusHotplugDeviceSupport to enable
> > hot plug supporting.
> >
> >  #
> >
> > -#  Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
> >
> > +#  Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
> >
> >  #
> >
> >  #  SPDX-License-Identifier: BSD-2-Clause-Patent
> >
> >  #
> >
> > @@ -57,6 +57,10 @@
> >    PciCommand.h
> >
> >    PciIo.h
> >
> >    PciBus.h
> >
> > +  PciFeatureSupport.c
> >
> > +  PciFeatureSupport.h
> >
> > +  PciPlatformSupport.c
> >
> > +  PciPlatformSupport.h
> >
> >
> >
> >  [Packages]
> >
> >    MdePkg/MdePkg.dec
> >
> > @@ -91,6 +95,8 @@
> >    gEfiLoadFile2ProtocolGuid                       ## SOMETIMES_PRODUCES
> >
> >    gEdkiiIoMmuProtocolGuid                         ## SOMETIMES_CONSUMES
> >
> >    gEfiLoadedImageDevicePathProtocolGuid           ## CONSUMES
> >
> > +  gEfiPciPlatformProtocol2Guid                     ## SOMETIMES_CONSUMES
> >
> > +  gEfiPciOverrideProtocol2Guid                     ## SOMETIMES_CONSUMES
> >
> >
> >
> >  [FeaturePcd]
> >
> >    gEfiMdeModulePkgTokenSpaceGuid.PcdPciBusHotplugDeviceSupport
> ##
> > CONSUMES
> >
> > @@ -104,6 +110,7 @@
> >    gEfiMdeModulePkgTokenSpaceGuid.PcdAriSupport                  ##
> CONSUMES
> >
> >    gEfiMdeModulePkgTokenSpaceGuid.PcdMrIovSupport                ##
> > CONSUMES
> >
> >    gEfiMdeModulePkgTokenSpaceGuid.PcdPciDisableBusEnumeration    ##
> > SOMETIMES_CONSUMES
> >
> > +  gEfiMdeModulePkgTokenSpaceGuid.PcdOtherPciFeatures                    ##
> > CONSUMES
> >
> >
> >
> >  [UserExtensions.TianoCore."ExtraFiles"]
> >
> >    PciBusDxeExtra.uni
> >
> > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
> > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
> > index b7832c6970..0f76ab1cd5 100644
> > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
> > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
> > @@ -170,6 +170,8 @@ DestroyRootBridgeByHandle (
> >
> >
> >      if (Temp->Handle == Controller) {
> >
> >
> >
> > +      DestroyRootBridgePciFeaturesConfigCompletionList ( Temp);
> >
> > +
> >
> >        RemoveEntryList (CurrentLink);
> >
> >
> >
> >        DestroyPciDeviceTree (Temp);
> >
> > @@ -208,8 +210,6 @@ RegisterPciDevice (
> >    )
> >
> >  {
> >
> >    EFI_STATUS          Status;
> >
> > -  VOID                *PlatformOpRomBuffer;
> >
> > -  UINTN               PlatformOpRomSize;
> >
> >    EFI_PCI_IO_PROTOCOL *PciIo;
> >
> >    UINT8               Data8;
> >
> >    BOOLEAN             HasEfiImage;
> >
> > @@ -244,49 +244,13 @@ RegisterPciDevice (
> >      //
> >
> >      // Get the OpRom provided by platform
> >
> >      //
> >
> > -    if (gPciPlatformProtocol != NULL) {
> >
> > -      Status = gPciPlatformProtocol->GetPciRom (
> >
> > -                                       gPciPlatformProtocol,
> >
> > -                                       PciIoDevice->Handle,
> >
> > -                                       &PlatformOpRomBuffer,
> >
> > -                                       &PlatformOpRomSize
> >
> > -                                       );
> >
> > -      if (!EFI_ERROR (Status)) {
> >
> > -        PciIoDevice->EmbeddedRom    = FALSE;
> >
> > -        PciIoDevice->RomSize        = (UINT32) PlatformOpRomSize;
> >
> > -        PciIoDevice->PciIo.RomSize  = PlatformOpRomSize;
> >
> > -        PciIoDevice->PciIo.RomImage = PlatformOpRomBuffer;
> >
> > -        //
> >
> > -        // For OpROM read from gPciPlatformProtocol:
> >
> > -        // Add the Rom Image to internal database for later PCI light
> > enumeration
> >
> > -        //
> >
> > -        PciRomAddImageMapping (
> >
> > -          NULL,
> >
> > -          PciIoDevice->PciRootBridgeIo->SegmentNumber,
> >
> > -          PciIoDevice->BusNumber,
> >
> > -          PciIoDevice->DeviceNumber,
> >
> > -          PciIoDevice->FunctionNumber,
> >
> > -          PciIoDevice->PciIo.RomImage,
> >
> > -          PciIoDevice->PciIo.RomSize
> >
> > -          );
> >
> > -      }
> >
> > -    } else if (gPciOverrideProtocol != NULL) {
> >
> > -      Status = gPciOverrideProtocol->GetPciRom (
> >
> > -                                       gPciOverrideProtocol,
> >
> > -                                       PciIoDevice->Handle,
> >
> > -                                       &PlatformOpRomBuffer,
> >
> > -                                       &PlatformOpRomSize
> >
> > -                                       );
> >
> > -      if (!EFI_ERROR (Status)) {
> >
> > -        PciIoDevice->EmbeddedRom    = FALSE;
> >
> > -        PciIoDevice->RomSize        = (UINT32) PlatformOpRomSize;
> >
> > -        PciIoDevice->PciIo.RomSize  = PlatformOpRomSize;
> >
> > -        PciIoDevice->PciIo.RomImage = PlatformOpRomBuffer;
> >
> > -        //
> >
> > -        // For OpROM read from gPciOverrideProtocol:
> >
> > -        // Add the Rom Image to internal database for later PCI light
> > enumeration
> >
> > -        //
> >
> > -        PciRomAddImageMapping (
> >
> > +    Status = GetPlatformPciOptionRom ( Controller, PciIoDevice);
> >
> > +    if (!EFI_ERROR (Status)) {
> >
> > +      //
> >
> > +      // For OpROM read from the PCI Platform Protocol:
> >
> > +      // Add the Rom Image to internal database for later PCI light
> > enumeration
> >
> > +      //
> >
> > +      PciRomAddImageMapping (
> >
> >            NULL,
> >
> >            PciIoDevice->PciRootBridgeIo->SegmentNumber,
> >
> >            PciIoDevice->BusNumber,
> >
> > @@ -294,8 +258,7 @@ RegisterPciDevice (
> >            PciIoDevice->FunctionNumber,
> >
> >            PciIoDevice->PciIo.RomImage,
> >
> >            PciIoDevice->PciIo.RomSize
> >
> > -          );
> >
> > -      }
> >
> > +        );
> >
> >      }
> >
> >    }
> >
> >
> >
> > @@ -597,7 +560,7 @@ DeRegisterPciDevice (
> >  }
> >
> >
> >
> >  /**
> >
> > -  Start to manage the PCI device on the specified root bridge or PCI-PCI
> > Bridge.
> >
> > +  Start the PCI root Ports or PCI-PCI Bridge only.
> >
> >
> >
> >    @param Controller          The root bridge handle.
> >
> >    @param RootBridge          A pointer to the PCI_IO_DEVICE.
> >
> > @@ -612,7 +575,82 @@ DeRegisterPciDevice (
> >
> >
> >  **/
> >
> >  EFI_STATUS
> >
> > -StartPciDevicesOnBridge (
> >
> > +StartPciRootPortsOnBridge (
> >
> > +  IN EFI_HANDLE                          Controller,
> >
> > +  IN PCI_IO_DEVICE                       *RootBridge
> >
> > +  )
> >
> > +
> >
> > +{
> >
> > +  PCI_IO_DEVICE             *PciIoDevice;
> >
> > +  EFI_STATUS                Status;
> >
> > +  LIST_ENTRY                *CurrentLink;
> >
> > +  UINT64                    Supports;
> >
> > +
> >
> > +  PciIoDevice = NULL;
> >
> > +  CurrentLink = RootBridge->ChildList.ForwardLink;
> >
> > +
> >
> > +  while (CurrentLink != NULL && CurrentLink != &RootBridge->ChildList) {
> >
> > +
> >
> > +    PciIoDevice = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
> >
> > +
> >
> > +    //
> >
> > +    // check if the device has been assigned with required resource
> >
> > +    // and registered
> >
> > +    //
> >
> > +    if (!PciIoDevice->Registered && !PciIoDevice->Allocated) {
> >
> > +      return EFI_NOT_READY;
> >
> > +    }
> >
> > +
> >
> > +    if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {
> >
> > +      Status = StartPciRootPortsOnBridge (
> >
> > +                 Controller,
> >
> > +                 PciIoDevice
> >
> > +                 );
> >
> > +
> >
> > +      PciIoDevice->PciIo.Attributes (
> >
> > +                           &(PciIoDevice->PciIo),
> >
> > +                           EfiPciIoAttributeOperationSupported,
> >
> > +                           0,
> >
> > +                           &Supports
> >
> > +                         );
> >
> > +      Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;
> >
> > +      PciIoDevice->PciIo.Attributes (
> >
> > +                           &(PciIoDevice->PciIo),
> >
> > +                           EfiPciIoAttributeOperationEnable,
> >
> > +                           Supports,
> >
> > +                           NULL
> >
> > +                         );
> >
> > +
> >
> > +    }
> >
> > +
> >
> > +    CurrentLink = CurrentLink->ForwardLink;
> >
> > +  }
> >
> > +
> >
> > +  if (PciIoDevice == NULL) {
> >
> > +    return EFI_NOT_FOUND;
> >
> > +  } else {
> >
> > +    return EFI_SUCCESS;
> >
> > +  }
> >
> > +}
> >
> > +
> >
> > +
> >
> > +/**
> >
> > +  Register to manage the PCI device on the specified root bridge or PCI-PCI
> > Bridge.
> >
> > +
> >
> > +  @param Controller          The root bridge handle.
> >
> > +  @param RootBridge          A pointer to the PCI_IO_DEVICE.
> >
> > +  @param RemainingDevicePath A pointer to the
> > EFI_DEVICE_PATH_PROTOCOL.
> >
> > +  @param NumberOfChildren    Children number.
> >
> > +  @param ChildHandleBuffer   A pointer to the child handle buffer.
> >
> > +
> >
> > +  @retval EFI_NOT_READY   Device is not allocated.
> >
> > +  @retval EFI_UNSUPPORTED Device only support PCI-PCI bridge.
> >
> > +  @retval EFI_NOT_FOUND   Can not find the specific device.
> >
> > +  @retval EFI_SUCCESS     Success to start Pci devices on bridge.
> >
> > +
> >
> > +**/
> >
> > +EFI_STATUS
> >
> > +RegisterPciDevicesOnBridge (
> >
> >    IN EFI_HANDLE                          Controller,
> >
> >    IN PCI_IO_DEVICE                       *RootBridge,
> >
> >    IN EFI_DEVICE_PATH_PROTOCOL            *RemainingDevicePath,
> >
> > @@ -626,7 +664,6 @@ StartPciDevicesOnBridge (
> >    EFI_DEVICE_PATH_PROTOCOL  *CurrentDevicePath;
> >
> >    EFI_STATUS                Status;
> >
> >    LIST_ENTRY                *CurrentLink;
> >
> > -  UINT64                    Supports;
> >
> >
> >
> >    PciIoDevice = NULL;
> >
> >    CurrentLink = RootBridge->ChildList.ForwardLink;
> >
> > @@ -681,7 +718,7 @@ StartPciDevicesOnBridge (
> >        // If it is a PPB
> >
> >        //
> >
> >        if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {
> >
> > -        Status = StartPciDevicesOnBridge (
> >
> > +        Status = RegisterPciDevicesOnBridge (
> >
> >                     Controller,
> >
> >                     PciIoDevice,
> >
> >                     CurrentDevicePath,
> >
> > @@ -689,20 +726,6 @@ StartPciDevicesOnBridge (
> >                     ChildHandleBuffer
> >
> >                     );
> >
> >
> >
> > -        PciIoDevice->PciIo.Attributes (
> >
> > -                             &(PciIoDevice->PciIo),
> >
> > -                             EfiPciIoAttributeOperationSupported,
> >
> > -                             0,
> >
> > -                             &Supports
> >
> > -                             );
> >
> > -        Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;
> >
> > -        PciIoDevice->PciIo.Attributes (
> >
> > -                             &(PciIoDevice->PciIo),
> >
> > -                             EfiPciIoAttributeOperationEnable,
> >
> > -                             Supports,
> >
> > -                             NULL
> >
> > -                             );
> >
> > -
> >
> >          return Status;
> >
> >        } else {
> >
> >
> >
> > @@ -733,28 +756,13 @@ StartPciDevicesOnBridge (
> >        }
> >
> >
> >
> >        if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {
> >
> > -        Status = StartPciDevicesOnBridge (
> >
> > +        Status = RegisterPciDevicesOnBridge (
> >
> >                     Controller,
> >
> >                     PciIoDevice,
> >
> >                     RemainingDevicePath,
> >
> >                     NumberOfChildren,
> >
> >                     ChildHandleBuffer
> >
> >                     );
> >
> > -
> >
> > -        PciIoDevice->PciIo.Attributes (
> >
> > -                             &(PciIoDevice->PciIo),
> >
> > -                             EfiPciIoAttributeOperationSupported,
> >
> > -                             0,
> >
> > -                             &Supports
> >
> > -                             );
> >
> > -        Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;
> >
> > -        PciIoDevice->PciIo.Attributes (
> >
> > -                             &(PciIoDevice->PciIo),
> >
> > -                             EfiPciIoAttributeOperationEnable,
> >
> > -                             Supports,
> >
> > -                             NULL
> >
> > -                             );
> >
> > -
> >
> >        }
> >
> >
> >
> >        CurrentLink = CurrentLink->ForwardLink;
> >
> > @@ -768,6 +776,65 @@ StartPciDevicesOnBridge (
> >    }
> >
> >  }
> >
> >
> >
> > +/**
> >
> > +  Start to manage the PCI device on the specified root bridge or PCI-PCI
> > Bridge.
> >
> > +
> >
> > +  @param Controller          The root bridge handle.
> >
> > +  @param RootBridge          A pointer to the PCI_IO_DEVICE.
> >
> > +  @param RemainingDevicePath A pointer to the
> > EFI_DEVICE_PATH_PROTOCOL.
> >
> > +  @param NumberOfChildren    Children number.
> >
> > +  @param ChildHandleBuffer   A pointer to the child handle buffer.
> >
> > +
> >
> > +  @retval EFI_NOT_READY   Device is not allocated.
> >
> > +  @retval EFI_UNSUPPORTED Device only support PCI-PCI bridge.
> >
> > +  @retval EFI_NOT_FOUND   Can not find the specific device.
> >
> > +  @retval EFI_SUCCESS     Success to start Pci devices on bridge.
> >
> > +
> >
> > +**/
> >
> > +EFI_STATUS
> >
> > +StartPciDevicesOnBridge (
> >
> > +  IN EFI_HANDLE                          Controller,
> >
> > +  IN PCI_IO_DEVICE                       *RootBridge,
> >
> > +  IN EFI_DEVICE_PATH_PROTOCOL            *RemainingDevicePath,
> >
> > +  IN OUT UINT8                           *NumberOfChildren,
> >
> > +  IN OUT EFI_HANDLE                      *ChildHandleBuffer
> >
> > +  )
> >
> > +
> >
> > +{
> >
> > +  EFI_STATUS                Status;
> >
> > +
> >
> > +  //
> >
> > +  // first register all the PCI devices
> >
> > +  //
> >
> > +  Status = RegisterPciDevicesOnBridge (
> >
> > +             Controller,
> >
> > +             RootBridge,
> >
> > +             RemainingDevicePath,
> >
> > +             NumberOfChildren,
> >
> > +             ChildHandleBuffer
> >
> > +             );
> >
> > +
> >
> > +  if (EFI_ERROR (Status) == EFI_NOT_FOUND) {
> >
> > +    return Status;
> >
> > +  } else {
> >
> > +    if ( CheckOtherPciFeaturesPcd ()) {
> >
> > +      //
> >
> > +      // the late configuration of PCI features
> >
> > +      //
> >
> > +      Status = EnumerateOtherPciFeatures (
> >
> > +                  RootBridge
> >
> > +                );
> >
> > +    }
> >
> > +    //
> >
> > +    // finally start those PCI bridge port devices only
> >
> > +    //
> >
> > +    return StartPciRootPortsOnBridge (
> >
> > +            Controller,
> >
> > +            RootBridge
> >
> > +            );
> >
> > +  }
> >
> > +}
> >
> > +
> >
> >  /**
> >
> >    Start to manage all the PCI devices it found previously under
> >
> >    the entire host bridge.
> >
> > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c
> > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c
> > index 8db1ebf8ec..0a56668380 100644
> > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c
> > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c
> > @@ -1003,7 +1003,7 @@ PciHostBridgeAdjustAllocation (
> >      Status = RejectPciDevice (PciResNode->PciDev);
> >
> >      if (Status == EFI_SUCCESS) {
> >
> >        DEBUG ((
> >
> > -        EFI_D_ERROR,
> >
> > +        DEBUG_ERROR,
> >
> >          "PciBus: [%02x|%02x|%02x] was rejected due to resource
> > confliction.\n",
> >
> >          PciResNode->PciDev->BusNumber, PciResNode->PciDev-
> > >DeviceNumber, PciResNode->PciDev->FunctionNumber
> >
> >          ));
> >
> > @@ -1746,7 +1746,7 @@ NotifyPhase (
> >
> >
> >    HostBridgeHandle  = NULL;
> >
> >    RootBridgeHandle  = NULL;
> >
> > -  if (gPciPlatformProtocol != NULL) {
> >
> > +  if ( CheckPciPlatformProtocolInstall()) {
> >
> >      //
> >
> >      // Get Host Bridge Handle.
> >
> >      //
> >
> > @@ -1770,42 +1770,11 @@ NotifyPhase (
> >      //
> >
> >      // Call PlatformPci::PlatformNotify() if the protocol is present.
> >
> >      //
> >
> > -    gPciPlatformProtocol->PlatformNotify (
> >
> > -                            gPciPlatformProtocol,
> >
> > -                            HostBridgeHandle,
> >
> > -                            Phase,
> >
> > -                            ChipsetEntry
> >
> > -                            );
> >
> > -  } else if (gPciOverrideProtocol != NULL){
> >
> > -    //
> >
> > -    // Get Host Bridge Handle.
> >
> > -    //
> >
> > -    PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle);
> >
> > -
> >
> > -    //
> >
> > -    // Get the rootbridge Io protocol to find the host bridge handle
> >
> > -    //
> >
> > -    Status = gBS->HandleProtocol (
> >
> > -                    RootBridgeHandle,
> >
> > -                    &gEfiPciRootBridgeIoProtocolGuid,
> >
> > -                    (VOID **) &PciRootBridgeIo
> >
> > -                    );
> >
> > -
> >
> > -    if (EFI_ERROR (Status)) {
> >
> > -      return EFI_NOT_FOUND;
> >
> > -    }
> >
> > -
> >
> > -    HostBridgeHandle = PciRootBridgeIo->ParentHandle;
> >
> > -
> >
> > -    //
> >
> > -    // Call PlatformPci::PhaseNotify() if the protocol is present.
> >
> > -    //
> >
> > -    gPciOverrideProtocol->PlatformNotify (
> >
> > -                            gPciOverrideProtocol,
> >
> > -                            HostBridgeHandle,
> >
> > -                            Phase,
> >
> > -                            ChipsetEntry
> >
> > -                            );
> >
> > +    PciPlatformNotifyPhase (
> >
> > +        HostBridgeHandle,
> >
> > +        Phase,
> >
> > +        ChipsetEntry
> >
> > +        );
> >
> >    }
> >
> >
> >
> >    Status = PciResAlloc->NotifyPhase (
> >
> > @@ -1813,27 +1782,15 @@ NotifyPhase (
> >                            Phase
> >
> >                            );
> >
> >
> >
> > -  if (gPciPlatformProtocol != NULL) {
> >
> > +  if ( CheckPciPlatformProtocolInstall()) {
> >
> >      //
> >
> >      // Call PlatformPci::PlatformNotify() if the protocol is present.
> >
> >      //
> >
> > -    gPciPlatformProtocol->PlatformNotify (
> >
> > -                            gPciPlatformProtocol,
> >
> > -                            HostBridgeHandle,
> >
> > -                            Phase,
> >
> > -                            ChipsetExit
> >
> > -                            );
> >
> > -
> >
> > -  } else if (gPciOverrideProtocol != NULL) {
> >
> > -    //
> >
> > -    // Call PlatformPci::PhaseNotify() if the protocol is present.
> >
> > -    //
> >
> > -    gPciOverrideProtocol->PlatformNotify (
> >
> > -                            gPciOverrideProtocol,
> >
> > -                            HostBridgeHandle,
> >
> > -                            Phase,
> >
> > -                            ChipsetExit
> >
> > -                            );
> >
> > +    PciPlatformNotifyPhase (
> >
> > +        HostBridgeHandle,
> >
> > +        Phase,
> >
> > +        ChipsetExit
> >
> > +        );
> >
> >    }
> >
> >
> >
> >    return Status;
> >
> > @@ -1914,31 +1871,16 @@ PreprocessController (
> >    RootBridgePciAddress.Bus              = Bus;
> >
> >    RootBridgePciAddress.ExtendedRegister = 0;
> >
> >
> >
> > -  if (gPciPlatformProtocol != NULL) {
> >
> > -    //
> >
> > -    // Call PlatformPci::PrepController() if the protocol is present.
> >
> > -    //
> >
> > -    gPciPlatformProtocol->PlatformPrepController (
> >
> > -                            gPciPlatformProtocol,
> >
> > -                            HostBridgeHandle,
> >
> > -                            RootBridgeHandle,
> >
> > -                            RootBridgePciAddress,
> >
> > -                            Phase,
> >
> > -                            ChipsetEntry
> >
> > -                            );
> >
> > -  } else if (gPciOverrideProtocol != NULL) {
> >
> > -    //
> >
> > -    // Call PlatformPci::PrepController() if the protocol is present.
> >
> > -    //
> >
> > -    gPciOverrideProtocol->PlatformPrepController (
> >
> > -                            gPciOverrideProtocol,
> >
> > -                            HostBridgeHandle,
> >
> > -                            RootBridgeHandle,
> >
> > -                            RootBridgePciAddress,
> >
> > -                            Phase,
> >
> > -                            ChipsetEntry
> >
> > -                            );
> >
> > -  }
> >
> > +  //
> >
> > +  // Call PlatformPci::PrepController() if the protocol is present.
> >
> > +  //
> >
> > +  PciPlatformPreprocessController (
> >
> > +      HostBridgeHandle,
> >
> > +      RootBridgeHandle,
> >
> > +      RootBridgePciAddress,
> >
> > +      Phase,
> >
> > +      ChipsetEntry
> >
> > +    );
> >
> >
> >
> >    Status = PciResAlloc->PreprocessController (
> >
> >                            PciResAlloc,
> >
> > @@ -1947,31 +1889,16 @@ PreprocessController (
> >                            Phase
> >
> >                            );
> >
> >
> >
> > -  if (gPciPlatformProtocol != NULL) {
> >
> > -    //
> >
> > -    // Call PlatformPci::PrepController() if the protocol is present.
> >
> > -    //
> >
> > -    gPciPlatformProtocol->PlatformPrepController (
> >
> > -                            gPciPlatformProtocol,
> >
> > -                            HostBridgeHandle,
> >
> > -                            RootBridgeHandle,
> >
> > -                            RootBridgePciAddress,
> >
> > -                            Phase,
> >
> > -                            ChipsetExit
> >
> > -                            );
> >
> > -  } else if (gPciOverrideProtocol != NULL) {
> >
> > -    //
> >
> > -    // Call PlatformPci::PrepController() if the protocol is present.
> >
> > -    //
> >
> > -    gPciOverrideProtocol->PlatformPrepController (
> >
> > -                            gPciOverrideProtocol,
> >
> > -                            HostBridgeHandle,
> >
> > -                            RootBridgeHandle,
> >
> > -                            RootBridgePciAddress,
> >
> > -                            Phase,
> >
> > -                            ChipsetExit
> >
> > -                            );
> >
> > -  }
> >
> > +  //
> >
> > +  // Call PlatformPci::PrepController() if the protocol is present.
> >
> > +  //
> >
> > +  PciPlatformPreprocessController (
> >
> > +      HostBridgeHandle,
> >
> > +      RootBridgeHandle,
> >
> > +      RootBridgePciAddress,
> >
> > +      Phase,
> >
> > +      ChipsetExit
> >
> > +    );
> >
> >
> >
> >    return EFI_SUCCESS;
> >
> >  }
> >
> > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
> > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
> > index c7eafff593..2343702154 100644
> > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
> > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
> > @@ -230,7 +230,7 @@ PciSearchDevice (
> >    PciIoDevice = NULL;
> >
> >
> >
> >    DEBUG ((
> >
> > -    EFI_D_INFO,
> >
> > +    DEBUG_INFO,
> >
> >      "PciBus: Discovered %s @ [%02x|%02x|%02x]\n",
> >
> >      IS_PCI_BRIDGE (Pci) ?     L"PPB" :
> >
> >      IS_CARDBUS_BRIDGE (Pci) ? L"P2C" :
> >
> > @@ -397,7 +397,7 @@ DumpPpbPaddingResource (
> >
> >
> >      if ((Type != PciBarTypeUnknown) && ((ResourceType ==
> > PciBarTypeUnknown) || (ResourceType == Type))) {
> >
> >        DEBUG ((
> >
> > -        EFI_D_INFO,
> >
> > +        DEBUG_INFO,
> >
> >          "   Padding: Type = %s; Alignment = 0x%lx;\tLength = 0x%lx\n",
> >
> >          mBarTypeStr[Type], Descriptor->AddrRangeMax, Descriptor->AddrLen
> >
> >          ));
> >
> > @@ -424,7 +424,7 @@ DumpPciBars (
> >      }
> >
> >
> >
> >      DEBUG ((
> >
> > -      EFI_D_INFO,
> >
> > +      DEBUG_INFO,
> >
> >        "   BAR[%d]: Type = %s; Alignment = 0x%lx;\tLength = 0x%lx;\tOffset =
> > 0x%02x\n",
> >
> >        Index, mBarTypeStr[MIN (PciIoDevice->PciBar[Index].BarType,
> > PciBarTypeMaxType)],
> >
> >        PciIoDevice->PciBar[Index].Alignment, PciIoDevice-
> > >PciBar[Index].Length, PciIoDevice->PciBar[Index].Offset
> >
> > @@ -437,13 +437,13 @@ DumpPciBars (
> >      }
> >
> >
> >
> >      DEBUG ((
> >
> > -      EFI_D_INFO,
> >
> > +      DEBUG_INFO,
> >
> >        " VFBAR[%d]: Type = %s; Alignment = 0x%lx;\tLength = 0x%lx;\tOffset =
> > 0x%02x\n",
> >
> >        Index, mBarTypeStr[MIN (PciIoDevice->VfPciBar[Index].BarType,
> > PciBarTypeMaxType)],
> >
> >        PciIoDevice->VfPciBar[Index].Alignment, PciIoDevice-
> > >VfPciBar[Index].Length, PciIoDevice->VfPciBar[Index].Offset
> >
> >        ));
> >
> >    }
> >
> > -  DEBUG ((EFI_D_INFO, "\n"));
> >
> > +  DEBUG ((DEBUG_INFO, "\n"));
> >
> >  }
> >
> >
> >
> >  /**
> >
> > @@ -1903,7 +1903,7 @@ PciParseBar (
> >        // Fix the length to support some special 64 bit BAR
> >
> >        //
> >
> >        if (Value == 0) {
> >
> > -        DEBUG ((EFI_D_INFO, "[PciBus]BAR probing for upper 32bit of MEM64
> > BAR returns 0, change to 0xFFFFFFFF.\n"));
> >
> > +        DEBUG ((DEBUG_INFO, "[PciBus]BAR probing for upper 32bit of
> MEM64
> > BAR returns 0, change to 0xFFFFFFFF.\n"));
> >
> >          Value = (UINT32) -1;
> >
> >        } else {
> >
> >          Value |= ((UINT32)(-1) << HighBitSet32 (Value));
> >
> > @@ -2153,7 +2153,17 @@ CreatePciIoDevice (
> >               NULL
> >
> >               );
> >
> >    if (!EFI_ERROR (Status)) {
> >
> > -    PciIoDevice->IsPciExp = TRUE;
> >
> > +  PciIoDevice->IsPciExp = TRUE;
> >
> > +    //
> >
> > +    // read the PCI device's entire PCI Express Capability structure
> >
> > +    //
> >
> > +    PciIo->Pci.Read (
> >
> > +                  PciIo,
> >
> > +                  EfiPciIoWidthUint8,
> >
> > +                  PciIoDevice->PciExpressCapabilityOffset,
> >
> > +                  sizeof (PCI_CAPABILITY_PCIEXP) / sizeof (UINT8),
> >
> > +                  &PciIoDevice->PciExpStruct
> >
> > +                );
> >
> >    }
> >
> >
> >
> >    if (PcdGetBool (PcdAriSupport)) {
> >
> > @@ -2206,7 +2216,7 @@ CreatePciIoDevice (
> >                                &Data32
> >
> >                                );
> >
> >            DEBUG ((
> >
> > -            EFI_D_INFO,
> >
> > +            DEBUG_INFO,
> >
> >              " ARI: forwarding enabled for PPB[%02x:%02x:%02x]\n",
> >
> >              Bridge->BusNumber,
> >
> >              Bridge->DeviceNumber,
> >
> > @@ -2215,7 +2225,7 @@ CreatePciIoDevice (
> >          }
> >
> >        }
> >
> >
> >
> > -      DEBUG ((EFI_D_INFO, " ARI: CapOffset = 0x%x\n", PciIoDevice-
> > >AriCapabilityOffset));
> >
> > +      DEBUG ((DEBUG_INFO, " ARI: CapOffset = 0x%x\n", PciIoDevice-
> > >AriCapabilityOffset));
> >
> >      }
> >
> >    }
> >
> >
> >
> > @@ -2325,12 +2335,12 @@ CreatePciIoDevice (
> >        PciIoDevice->ReservedBusNum = (UINT16)(EFI_PCI_BUS_OF_RID
> (LastVF)
> > - Bus + 1);
> >
> >
> >
> >        DEBUG ((
> >
> > -        EFI_D_INFO,
> >
> > +        DEBUG_INFO,
> >
> >          " SR-IOV: SupportedPageSize = 0x%x; SystemPageSize = 0x%x;
> > FirstVFOffset = 0x%x;\n",
> >
> >          SupportedPageSize, PciIoDevice->SystemPageSize >> 12, FirstVFOffset
> >
> >          ));
> >
> >        DEBUG ((
> >
> > -        EFI_D_INFO,
> >
> > +        DEBUG_INFO,
> >
> >          "         InitialVFs = 0x%x; ReservedBusNum = 0x%x; CapOffset = 0x%x\n",
> >
> >          PciIoDevice->InitialVFs, PciIoDevice->ReservedBusNum, PciIoDevice-
> > >SrIovCapabilityOffset
> >
> >          ));
> >
> > @@ -2345,7 +2355,7 @@ CreatePciIoDevice (
> >                 NULL
> >
> >                 );
> >
> >      if (!EFI_ERROR (Status)) {
> >
> > -      DEBUG ((EFI_D_INFO, " MR-IOV: CapOffset = 0x%x\n", PciIoDevice-
> > >MrIovCapabilityOffset));
> >
> > +      DEBUG ((DEBUG_INFO, " MR-IOV: CapOffset = 0x%x\n", PciIoDevice-
> > >MrIovCapabilityOffset));
> >
> >      }
> >
> >    }
> >
> >
> >
> > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> > new file mode 100644
> > index 0000000000..0819da6536
> > --- /dev/null
> > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> > @@ -0,0 +1,1601 @@
> > +/** @file
> >
> > +  PCI standard feature support functions implementation for PCI Bus
> > module..
> >
> > +
> >
> > +Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> >
> > +SPDX-License-Identifier: BSD-2-Clause-Patent
> >
> > +
> >
> > +**/
> >
> > +
> >
> > +#include "PciFeatureSupport.h"
> >
> > +
> >
> > +/**
> >
> > +  A gobal pointer to PRIMARY_ROOT_PORT_NODE buffer to track all the
> > primary physical
> >
> > +  PCI Root Ports (PCI Controllers) for a given PCI Root Bridge instance while
> >
> > +  enumerating to configure the PCI features
> >
> > +**/
> >
> > +PRIMARY_ROOT_PORT_NODE                      *mPrimaryRootPortList;
> >
> > +
> >
> > +/**
> >
> > +  A gobal pointer to OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> buffer
> > all the PCI
> >
> > +  Feature configuration Table nodes to pair against each of the
> > PRIMARY_ROOT_PORT_NODE
> >
> > +  buffer nodes. Each node of these is used to align all the PCI devices
> > originating
> >
> > +  from the PCI Root Port devices of a PCI Root Bridge instance
> >
> > +**/
> >
> > +OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > *mPciFeaturesConfigurationTableInstances;
> >
> > +
> >
> > +/**
> >
> > +  A global pointer to PCI_FEATURE_CONFIGURATION_COMPLETION_LIST,
> > which stores all
> >
> > +  the PCI Root Bridge instances that are enumerated for the other PCI
> > features,
> >
> > +  like MaxPayloadSize & MaxReadReqSize; during the the Start() interface
> of
> > the
> >
> > +  driver binding protocol. The records pointed by this pointer would be
> > destroyed
> >
> > +  when the DXE core invokes the Stop() interface.
> >
> > +**/
> >
> > +PCI_FEATURE_CONFIGURATION_COMPLETION_LIST
> > *mPciFeaturesConfigurationCompletionList = NULL;
> >
> > +
> >
> > +/**
> >
> > +  Main routine to indicate platform selection of any of the other PCI
> features
> >
> > +  to be configured by this driver
> >
> > +
> >
> > +  @retval TRUE    platform has selected the other PCI features to be
> > configured
> >
> > +          FALSE   platform has not selected any of the other PCI features
> >
> > +**/
> >
> > +BOOLEAN
> >
> > +CheckOtherPciFeaturesPcd (
> >
> > +  )
> >
> > +{
> >
> > +  return PcdGet32 ( PcdOtherPciFeatures) ? TRUE : FALSE;
> >
> > +}
> >
> > +
> >
> > +/**
> >
> > +  Main routine to indicate whether the platform has selected the
> > Max_Payload_Size
> >
> > +  PCI feature to be configured by this driver
> >
> > +
> >
> > +  @retval TRUE    platform has selected the Max_Payload_Size to be
> > configured
> >
> > +          FALSE   platform has not selected this feature
> >
> > +**/
> >
> > +BOOLEAN
> >
> > +SetupMaxPayloadSize (
> >
> > +  )
> >
> > +{
> >
> > +  return (PcdGet32 ( PcdOtherPciFeatures) &
> > PCI_FEATURE_SUPPORT_FLAG_MPS) ? TRUE : FALSE;
> >
> > +}
> >
> > +
> >
> > +/**
> >
> > +  Main routine to indicate whether the platform has selected the
> > Max_Read_Req_Size
> >
> > +  PCI feature to be configured by this driver
> >
> > +
> >
> > +  @retval TRUE    platform has selected the Max_Read_Req_Size to be
> > configured
> >
> > +          FALSE   platform has not selected this feature
> >
> > +**/
> >
> > +BOOLEAN
> >
> > +SetupMaxReadReqSize (
> >
> > +  )
> >
> > +{
> >
> > +  return (PcdGet32 ( PcdOtherPciFeatures) &
> > PCI_FEATURE_SUPPORT_FLAG_MRRS) ? TRUE : FALSE;
> >
> > +}
> >
> > +
> >
> > +/**
> >
> > +  Helper routine which determines whether the given PCI Root Bridge
> > instance
> >
> > +  record already exist. This routine shall help avoid duplicate record
> creation
> >
> > +  in case of re-enumeration of PCI configuation features.
> >
> > +
> >
> > +  @param  RootBridge              A pointer to the PCI_IO_DEVICE for the Root
> > Bridge
> >
> > +  @param  PciFeatureConfigRecord  A pointer to a pointer for type
> >
> > +                                  PCI_FEATURE_CONFIGURATION_COMPLETION_LIST
> >
> > +                                  record, Use to return the specific record.
> >
> > +
> >
> > +  @retval TRUE                    Record already exist
> >
> > +          FALSE                   Record does not exist for the given PCI Root Bridge
> >
> > +**/
> >
> > +BOOLEAN
> >
> > +CheckPciFeatureConfigurationRecordExist (
> >
> > +  IN  PCI_IO_DEVICE                             *RootBridge,
> >
> > +  OUT PCI_FEATURE_CONFIGURATION_COMPLETION_LIST
> > **PciFeatureConfigRecord
> >
> > +  )
> >
> > +{
> >
> > +  LIST_ENTRY                                  *Link;
> >
> > +  PCI_FEATURE_CONFIGURATION_COMPLETION_LIST   *Temp;
> >
> > +
> >
> > +  if ( mPciFeaturesConfigurationCompletionList) {
> >
> > +    Link = &mPciFeaturesConfigurationCompletionList->RootBridgeLink;
> >
> > +
> >
> > +    do {
> >
> > +      Temp =
> > PCI_FEATURE_CONFIGURATION_COMPLETION_LIST_FROM_LINK (Link);
> >
> > +      if ( Temp->RootBridgeHandle == RootBridge->Handle) {
> >
> > +        *PciFeatureConfigRecord = Temp;
> >
> > +        return TRUE;
> >
> > +      }
> >
> > +      Link = Link->ForwardLink;
> >
> > +    } while (Link != &mPciFeaturesConfigurationCompletionList-
> > >RootBridgeLink);
> >
> > +  }
> >
> > +  //
> >
> > +  // not found on the PCI feature configuration completion list
> >
> > +  //
> >
> > +  *PciFeatureConfigRecord = NULL;
> >
> > +  return FALSE;
> >
> > +}
> >
> > +
> >
> > +/**
> >
> > +  This routine is primarily to avoid multiple configuration of PCI features
> >
> > +  to the same PCI Root Bridge due to EDK2 core's ConnectController calls
> on
> >
> > +  all the EFI handles. This routine also provide re-enumeration of the PCI
> >
> > +  features on the same PCI Root Bridge based on the policy of
> > ReEnumeratePciFeatureConfiguration
> >
> > +  of the PCI_FEATURE_CONFIGURATION_COMPLETION_LIST.
> >
> > +
> >
> > +  @param  RootBridge              A pointer to the PCI_IO_DEVICE for the Root
> > Bridge
> >
> > +
> >
> > +  @retval TRUE                    PCI Feature configuration required for the PCI
> >
> > +                                  Root Bridge
> >
> > +          FALSE                   PCI Feature configuration is not required to be
> >
> > +                                  re-enumerated for the PCI Root Bridge
> >
> > +**/
> >
> > +BOOLEAN
> >
> > +CheckPciFeaturesConfigurationRequired (
> >
> > +  IN PCI_IO_DEVICE          *RootBridge
> >
> > +  )
> >
> > +{
> >
> > +  LIST_ENTRY                                  *Link;
> >
> > +  PCI_FEATURE_CONFIGURATION_COMPLETION_LIST   *Temp;
> >
> > +
> >
> > +  if ( mPciFeaturesConfigurationCompletionList) {
> >
> > +    Link = &mPciFeaturesConfigurationCompletionList->RootBridgeLink;
> >
> > +
> >
> > +    do {
> >
> > +      Temp =
> > PCI_FEATURE_CONFIGURATION_COMPLETION_LIST_FROM_LINK (Link);
> >
> > +      if ( Temp->RootBridgeHandle == RootBridge->Handle) {
> >
> > +        return Temp->ReEnumeratePciFeatureConfiguration;
> >
> > +      }
> >
> > +      Link = Link->ForwardLink;
> >
> > +    } while (Link != &mPciFeaturesConfigurationCompletionList-
> > >RootBridgeLink);
> >
> > +  }
> >
> > +  //
> >
> > +  // not found on the PCI feature configuration completion list, return as
> > required
> >
> > +  //
> >
> > +  return TRUE;
> >
> > +}
> >
> > +
> >
> > +/**
> >
> > +  This routine finds the duplicate record if exist and assigns the re-
> > enumeration
> >
> > +  requirement flag, as passed as input. It creates new record for the PCI
> > Root
> >
> > +  Bridge and appends the list after updating its re-enumeration flag.
> >
> > +
> >
> > +  @param  RootBridge            A pointer to PCI_IO_DEVICE of the Root
> Bridge
> >
> > +  @param  ReEnumerationRequired A BOOLEAN for recording the re-
> > enumeration requirement
> >
> > +
> >
> > +  @retval EFI_SUCCESS           new record inserted into the list or updated
> the
> >
> > +                                existing record
> >
> > +          EFI_INVALID_PARAMETER Unexpected error as
> > CheckPciFeatureConfigurationRecordExist
> >
> > +                                reports as record exist but does not return its pointer
> >
> > +          EFI_OUT_OF_RESOURCES  Not able to create PCI features
> configuratin
> > complete
> >
> > +                                record for the RootBridge
> >
> > +**/
> >
> > +EFI_STATUS
> >
> > +AddRootBridgeInPciFeaturesConfigCompletionList (
> >
> > +  IN PCI_IO_DEVICE          *RootBridge,
> >
> > +  IN BOOLEAN                ReEnumerationRequired
> >
> > +  )
> >
> > +{
> >
> > +  PCI_FEATURE_CONFIGURATION_COMPLETION_LIST   *Temp;
> >
> > +
> >
> > +  if ( CheckPciFeatureConfigurationRecordExist ( RootBridge, &Temp)) {
> >
> > +    //
> >
> > +    // this PCI Root Bridge record already exist; it may have been re-
> > enumerated
> >
> > +    // hence just update its enumeration required flag again to exit
> >
> > +    //
> >
> > +    if ( Temp) {
> >
> > +      Temp->ReEnumeratePciFeatureConfiguration  =
> > ReEnumerationRequired;
> >
> > +      return EFI_SUCCESS;
> >
> > +    } else {
> >
> > +      //
> >
> > +      // PCI feature configuration complete record reported as exist and no
> >
> > +      // record pointer returned
> >
> > +      //
> >
> > +      return EFI_INVALID_PARAMETER;
> >
> > +    }
> >
> > +
> >
> > +  } else {
> >
> > +
> >
> > +    Temp = AllocateZeroPool ( sizeof
> > ( PCI_FEATURE_CONFIGURATION_COMPLETION_LIST));
> >
> > +    if ( !Temp) {
> >
> > +      return EFI_OUT_OF_RESOURCES;
> >
> > +    }
> >
> > +    Temp->Signature                           =
> > PCI_FEATURE_CONFIGURATION_SIGNATURE;
> >
> > +    Temp->RootBridgeHandle                    = RootBridge->Handle;
> >
> > +    Temp->ReEnumeratePciFeatureConfiguration  =
> ReEnumerationRequired;
> >
> > +    if ( mPciFeaturesConfigurationCompletionList) {
> >
> > +      InsertTailList ( &mPciFeaturesConfigurationCompletionList-
> > >RootBridgeLink,
> >
> > +                       &Temp->RootBridgeLink);
> >
> > +    } else {
> >
> > +      //
> >
> > +      // init the very first node of the Root Bridge
> >
> > +      //
> >
> > +      mPciFeaturesConfigurationCompletionList = Temp;
> >
> > +      InitializeListHead ( &mPciFeaturesConfigurationCompletionList-
> > >RootBridgeLink);
> >
> > +    }
> >
> > +  }
> >
> > +  return EFI_SUCCESS;
> >
> > +}
> >
> > +
> >
> > +/**
> >
> > +  Free up memory alloted for the primary physical PCI Root ports of the
> PCI
> > Root
> >
> > +  Bridge instance. Free up all the nodes of type
> > PRIMARY_ROOT_PORT_NODE.
> >
> > +**/
> >
> > +VOID
> >
> > +DestroyPrimaryRootPortNodes ()
> >
> > +{
> >
> > +  LIST_ENTRY                *Link;
> >
> > +  PRIMARY_ROOT_PORT_NODE    *Temp;
> >
> > +
> >
> > +  if ( mPrimaryRootPortList) {
> >
> > +    Link = &mPrimaryRootPortList->NeighborRootPort;
> >
> > +
> >
> > +    if ( IsListEmpty ( Link)) {
> >
> > +      FreePool ( mPrimaryRootPortList);
> >
> > +    } else {
> >
> > +      do {
> >
> > +        if ( Link->ForwardLink != &mPrimaryRootPortList->NeighborRootPort)
> {
> >
> > +          Link = Link->ForwardLink;
> >
> > +        }
> >
> > +        Temp = PRIMARY_ROOT_PORT_NODE_FROM_LINK ( Link);
> >
> > +        Link = RemoveEntryList ( Link);
> >
> > +        FreePool ( Temp);
> >
> > +      } while ( !IsListEmpty ( Link));
> >
> > +      FreePool ( mPrimaryRootPortList);
> >
> > +    }
> >
> > +    mPrimaryRootPortList = NULL;
> >
> > +  }
> >
> > +}
> >
> > +
> >
> > +/**
> >
> > +  Free up the memory allocated for temporarily maintaining the PCI
> feature
> >
> > +  configuration table for all the nodes of the primary PCI Root port.
> >
> > +  Free up memory alloted for
> > OTHER_PCI_FEATURES_CONFIGURATION_TABLE.
> >
> > +**/
> >
> > +VOID
> >
> > +ErasePciFeaturesConfigurationTable (
> >
> > +  )
> >
> > +{
> >
> > +  if ( mPciFeaturesConfigurationTableInstances) {
> >
> > +    FreePool ( mPciFeaturesConfigurationTableInstances);
> >
> > +  }
> >
> > +  mPciFeaturesConfigurationTableInstances = NULL;
> >
> > +}
> >
> > +
> >
> > +/**
> >
> > +  Routine meant for initializing any global variables used. It primarily cleans
> >
> > +  up the internal data structure memory allocated for the previous PCI
> Root
> > Bridge
> >
> > +  instance. This should be the first routine to call for any virtual PCI Root
> >
> > +  Bridge instance.
> >
> > +**/
> >
> > +VOID
> >
> > +SetupPciFeaturesConfigurationDefaults ()
> >
> > +{
> >
> > +  //
> >
> > +  // delete the primary root port list
> >
> > +  //
> >
> > +  if (mPrimaryRootPortList) {
> >
> > +    DestroyPrimaryRootPortNodes ();
> >
> > +  }
> >
> > +
> >
> > +  if ( mPciFeaturesConfigurationTableInstances) {
> >
> > +    ErasePciFeaturesConfigurationTable ();
> >
> > +  }
> >
> > +}
> >
> > +
> >
> > +/**
> >
> > +  Helper routine to determine whether the PCI device is a physical root
> port
> >
> > +  recorded in the list.
> >
> > +
> >
> > +  @param  PciDevice                       A pointer to the PCI_IO_DEVICE.
> >
> > +
> >
> > +  @retval TRUE                            The PCI device instance is a primary
> >
> > +                                          primary physical PCI Root Port
> >
> > +          FALSE                           Not a primary physical PCI Root port
> >
> > +**/
> >
> > +BOOLEAN
> >
> > +CheckRootBridgePrimaryPort (
> >
> > +  IN PCI_IO_DEVICE          *PciDevice
> >
> > +  )
> >
> > +{
> >
> > +  LIST_ENTRY                *Link;
> >
> > +  PRIMARY_ROOT_PORT_NODE    *Temp;
> >
> > +
> >
> > +  if ( !mPrimaryRootPortList) {
> >
> > +    return FALSE;
> >
> > +  }
> >
> > +  Link = &mPrimaryRootPortList->NeighborRootPort;
> >
> > +  do {
> >
> > +    Temp = PRIMARY_ROOT_PORT_NODE_FROM_LINK ( Link);
> >
> > +    if ( Temp->RootBridgeHandle == PciDevice->Parent->Handle
> >
> > +        && Temp->RootPortHandle == PciDevice->Handle) {
> >
> > +      //
> >
> > +      // the given PCI device is the primary root port of the Root Bridge
> > controller
> >
> > +      //
> >
> > +      return TRUE;
> >
> > +    }
> >
> > +    Link = Link->ForwardLink;
> >
> > +  } while ( Link != &mPrimaryRootPortList->NeighborRootPort);
> >
> > +  //
> >
> > +  // the given PCI device is not the primary root port of the Bridge
> controller
> >
> > +  //
> >
> > +  return FALSE;
> >
> > +}
> >
> > +
> >
> > +/**
> >
> > +  Main routine to determine the child PCI devices of a physical PCI bridge
> > device
> >
> > +  and group them under a common internal PCI features Configuration
> table.
> >
> > +
> >
> > +  @param  PciDevice                       A pointer to the PCI_IO_DEVICE.
> >
> > +  @param  PciFeaturesConfigTable          A pointer to a pointer to the
> >
> > +                                          OTHER_PCI_FEATURES_CONFIGURATION_TABLE.
> >
> > +                                          Returns NULL in case of RCiEP or the PCI
> >
> > +                                          device does match with any of the physical
> >
> > +                                          Root ports, or it does not belong to any
> >
> > +                                          Root port's PCU bus range (not a child)
> >
> > +
> >
> > +  @retval EFI_SUCCESS                     able to determine the PCI feature
> >
> > +                                          configuration table. For RCiEP since
> >
> > +                                          since it is not prepared.
> >
> > +          EFI_NOT_FOUND                   the PCI feature configuration table does
> >
> > +                                          not exist as the PCI physical Bridge device
> >
> > +                                          is not found for this device's parent
> >
> > +                                          Root Bridge instance
> >
> > +**/
> >
> > +EFI_STATUS
> >
> > +GetPciFeaturesConfigurationTable (
> >
> > +  IN  PCI_IO_DEVICE                           *PciDevice,
> >
> > +  OUT OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > **PciFeaturesConfigTable
> >
> > +  )
> >
> > +{
> >
> > +  LIST_ENTRY                *Link;
> >
> > +  PRIMARY_ROOT_PORT_NODE    *Temp;
> >
> > +
> >
> > +  if ( !mPrimaryRootPortList) {
> >
> > +    *PciFeaturesConfigTable = NULL;
> >
> > +    return EFI_NOT_FOUND;
> >
> > +  }
> >
> > +
> >
> > +  //
> >
> > +  // The PCI features configuration table is not built for RCiEP, return NULL
> >
> > +  //
> >
> > +  if ( PciDevice->PciExpStruct.Capability.Bits.DevicePortType == \
> >
> > +        PCIE_DEVICE_PORT_TYPE_ROOT_COMPLEX_INTEGRATED_ENDPOINT)
> > {
> >
> > +    *PciFeaturesConfigTable = NULL;
> >
> > +    return EFI_SUCCESS;
> >
> > +  }
> >
> > +
> >
> > +  Link = &mPrimaryRootPortList->NeighborRootPort;
> >
> > +  do {
> >
> > +    Temp = PRIMARY_ROOT_PORT_NODE_FROM_LINK ( Link);
> >
> > +    if ( Temp->RootBridgeHandle == PciDevice->Parent->Handle
> >
> > +        && Temp->RootPortHandle == PciDevice->Handle) {
> >
> > +      //
> >
> > +      // the given PCI device is the primary root port of the Root Bridge
> > controller
> >
> > +      //
> >
> > +      *PciFeaturesConfigTable = Temp-
> >OtherPciFeaturesConfigurationTable;
> >
> > +      return EFI_SUCCESS;
> >
> > +    } else {
> >
> > +      //
> >
> > +      // check this PCI device belongs to the primary root port of the root
> > bridge
> >
> > +      //
> >
> > +      if ( PciDevice->BusNumber >= Temp->SecondaryBusStart
> >
> > +          && PciDevice->BusNumber <= Temp->SecondaryBusEnd) {
> >
> > +        *PciFeaturesConfigTable = Temp-
> >OtherPciFeaturesConfigurationTable;
> >
> > +        return EFI_SUCCESS;
> >
> > +      }
> >
> > +    }
> >
> > +    Link = Link->ForwardLink;
> >
> > +  } while ( Link != &mPrimaryRootPortList->NeighborRootPort);
> >
> > +  //
> >
> > +  // the PCI device must be RCiEP, does not belong to any primary root
> port
> >
> > +  //
> >
> > +  *PciFeaturesConfigTable = NULL;
> >
> > +  return EFI_SUCCESS;
> >
> > +}
> >
> > +
> >
> > +/**
> >
> > +  The helper routine to retrieve the PCI bus numbers from the PCI Bridge
> or
> > Root
> >
> > +  port device. Assumes the input PCI device has the PCI Type 1
> configuration
> > header.
> >
> > +
> >
> > +  @param  PciDevice                       A pointer to the PCI_IO_DEVICE.
> >
> > +  @param  PrimaryBusNumber                A pointer to return the PCI Priamry
> >
> > +                                          Bus number.
> >
> > +  @param  SecondaryBusNumber              A pointer to return the PCI
> > Secondary
> >
> > +                                          Bus number.
> >
> > +  @param  SubordinateBusNumber            A pointer to return the PCI
> > Subordinate
> >
> > +                                          Bus number.
> >
> > +
> >
> > +  @retval EFI_SUCCESS           The data was read from the PCI device.
> >
> > +  @retval EFI_UNSUPPORTED       The address range specified by Offset,
> > Width, and Count is not
> >
> > +                                valid for the PCI configuration header of the PCI device.
> >
> > +  @retval EFI_INVALID_PARAMETER input parameters provided to the
> read
> > operation were invalid.
> >
> > +**/
> >
> > +EFI_STATUS
> >
> > +GetPciRootPortBusAssigned (
> >
> > +  IN  PCI_IO_DEVICE                           *PciDevice,
> >
> > +  OUT UINT8                                   *PrimaryBusNumber,
> >
> > +  OUT UINT8                                   *SecondaryBusNumber,
> >
> > +  OUT UINT8                                   *SubordinateBusNumber
> >
> > +  )
> >
> > +{
> >
> > +  EFI_STATUS                                  Status;
> >
> > +  UINT32                                      RootPortBusAssigned;
> >
> > +
> >
> > +  Status = PciDevice->PciIo.Pci.Read (
> >
> > +                                  &PciDevice->PciIo,
> >
> > +                                  EfiPciIoWidthUint32,
> >
> > +                                  PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET,
> >
> > +                                  1,
> >
> > +                                  &RootPortBusAssigned
> >
> > +                                );
> >
> > +  if ( !EFI_ERROR(Status)) {
> >
> > +    if ( PrimaryBusNumber) {
> >
> > +      *PrimaryBusNumber = (UINT8) (0xFF & RootPortBusAssigned);
> >
> > +    }
> >
> > +    if ( SecondaryBusNumber) {
> >
> > +      *SecondaryBusNumber = (UINT8)(0xFF & (RootPortBusAssigned >> 8));
> >
> > +    }
> >
> > +    if ( SubordinateBusNumber) {
> >
> > +      *SubordinateBusNumber = (UINT8)(0xFF & (RootPortBusAssigned >>
> > 16));
> >
> > +    }
> >
> > +  }
> >
> > +  return Status;
> >
> > +}
> >
> > +
> >
> > +/**
> >
> > +  This routine determines the existance of the child PCI device for the
> given
> >
> > +  PCI Root / Bridge Port device. Always assumes the input PCI device is the
> > bridge
> >
> > +  or PCI-PCI Bridge device. This routine should not be used with PCI
> > endpoint device.
> >
> > +
> >
> > +  @param  PciDevice                       A pointer to the PCI_IO_DEVICE.
> >
> > +
> >
> > +  @retval TRUE                            child device exist
> >
> > +          FALSE                           no child device
> >
> > +**/
> >
> > +BOOLEAN
> >
> > +IsPciRootPortEmpty (
> >
> > +  IN  PCI_IO_DEVICE                           *PciDevice
> >
> > +  )
> >
> > +{
> >
> > +  UINT8                                       SecBus,
> >
> > +                                              SubBus;
> >
> > +  EFI_STATUS                                  Status;
> >
> > +  LIST_ENTRY                                  *Link;
> >
> > +  PCI_IO_DEVICE                               *NextPciDevice;
> >
> > +
> >
> > +  //
> >
> > +  // check secondary & suboridinate bus numbers for its endpoint device
> >
> > +  // existance
> >
> > +  //
> >
> > +  Status = GetPciRootPortBusAssigned ( PciDevice, NULL, &SecBus,
> > &SubBus);
> >
> > +  if ( !EFI_ERROR( Status)) {
> >
> > +    Link = PciDevice->ChildList.ForwardLink;
> >
> > +    if ( IsListEmpty ( Link)) {
> >
> > +      //
> >
> > +      // return as PCI Root port empty
> >
> > +      //
> >
> > +      DEBUG (( DEBUG_INFO, "RP empty,"));
> >
> > +      return TRUE;
> >
> > +    }
> >
> > +    do {
> >
> > +      NextPciDevice = PCI_IO_DEVICE_FROM_LINK ( Link);
> >
> > +      DEBUG (( DEBUG_INFO, "dev@%x", NextPciDevice->BusNumber));
> >
> > +
> >
> > +      if ( NextPciDevice->BusNumber >= SecBus
> >
> > +          && NextPciDevice->BusNumber <= SubBus) {
> >
> > +
> >
> > +        return FALSE;
> >
> > +      }
> >
> > +
> >
> > +      Link = Link->ForwardLink;
> >
> > +    } while ( Link != &PciDevice->ChildList);
> >
> > +  } else {
> >
> > +    SecBus = SubBus = 0;
> >
> > +    DEBUG (( DEBUG_ERROR, "unable to retrieve root port's bus range
> > assigned!!!"));
> >
> > +  }
> >
> > +
> >
> > +  //
> >
> > +  // return as PCI Root port empty
> >
> > +  //
> >
> > +  return TRUE;
> >
> > +}
> >
> > +
> >
> > +/**
> >
> > +  The main routine which process the PCI feature Max_Payload_Size as
> per
> > the
> >
> > +  device-specific platform policy, as well as in complaince with the PCI Base
> >
> > +  specification Revision 4, that aligns the value for the entire PCI heirarchy
> >
> > +  starting from its physical PCI Root port / Bridge device.
> >
> > +
> >
> > +  @param PciDevice                      A pointer to the PCI_IO_DEVICE.
> >
> > +  @param PciConfigPhase                 for the PCI feature configuration phases:
> >
> > +                                        PciFeatureGetDevicePolicy & PciFeatureSetupPhase
> >
> > +  @param PciFeaturesConfigurationTable  pointer to
> > OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> >
> > +
> >
> > +  @retval EFI_SUCCESS                   processing of PCI feature
> > Max_Payload_Size
> >
> > +                                        is successful.
> >
> > +**/
> >
> > +EFI_STATUS
> >
> > +ProcessMaxPayloadSize (
> >
> > +  IN  PCI_IO_DEVICE                           *PciDevice,
> >
> > +  IN  PCI_FEATURE_CONFIGURATION_PHASE         PciConfigPhase,
> >
> > +  IN  OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > *PciFeaturesConfigurationTable
> >
> > +  )
> >
> > +{
> >
> > +  PCI_REG_PCIE_DEVICE_CAPABILITY          PciDeviceCap;
> >
> > +  UINT8                                   MpsValue;
> >
> > +
> >
> > +
> >
> > +  PciDeviceCap.Uint32 = PciDevice->PciExpStruct.DeviceCapability.Uint32;
> >
> > +
> >
> > +  if ( PciConfigPhase == PciFeatureGetDevicePolicy) {
> >
> > +    if ( SetupMpsAsPerDeviceCapability ( PciDevice->SetupMPS))
> >
> > +    {
> >
> > +      MpsValue = (UINT8)PciDeviceCap.Bits.MaxPayloadSize;
> >
> > +      //
> >
> > +      // no change to PCI Root ports without any endpoint device
> >
> > +      //
> >
> > +      if ( IS_PCI_BRIDGE ( &PciDevice->Pci) &&
> > PciDeviceCap.Bits.MaxPayloadSize) {
> >
> > +        if ( IsPciRootPortEmpty ( PciDevice)) {
> >
> > +          MpsValue = PCIE_MAX_PAYLOAD_SIZE_128B;
> >
> > +          DEBUG (( DEBUG_INFO, "(reset RP MPS to min.)"));
> >
> > +        }
> >
> > +      }
> >
> > +    } else {
> >
> > +      MpsValue = TranslateMpsSetupValueToPci ( PciDevice->SetupMPS);
> >
> > +    }
> >
> > +    //
> >
> > +    // discard device policy override request if greater than PCI device
> > capability
> >
> > +    //
> >
> > +    PciDevice->SetupMPS =
> MIN( (UINT8)PciDeviceCap.Bits.MaxPayloadSize,
> > MpsValue);
> >
> > +  }
> >
> > +
> >
> > +  //
> >
> > +  // align the MPS of the tree to the HCF with this device
> >
> > +  //
> >
> > +  if ( PciFeaturesConfigurationTable) {
> >
> > +    MpsValue = PciFeaturesConfigurationTable->Max_Payload_Size;
> >
> > +
> >
> > +    MpsValue = MIN ( PciDevice->SetupMPS, MpsValue);
> >
> > +    PciDevice->SetupMPS = MIN ( PciDevice->SetupMPS, MpsValue);
> >
> > +
> >
> > +    if ( MpsValue != PciFeaturesConfigurationTable->Max_Payload_Size) {
> >
> > +      DEBUG (( DEBUG_INFO, "reset MPS of the tree to %d,", MpsValue));
> >
> > +      PciFeaturesConfigurationTable->Max_Payload_Size = MpsValue;
> >
> > +    }
> >
> > +  }
> >
> > +
> >
> > +  DEBUG (( DEBUG_INFO,
> >
> > +      "Max_Payload_Size: %d [DevCap:%d],",
> >
> > +      PciDevice->SetupMPS, PciDeviceCap.Bits.MaxPayloadSize
> >
> > +  ));
> >
> > +  return EFI_SUCCESS;
> >
> > +}
> >
> > +
> >
> > +/**
> >
> > +  The main routine which process the PCI feature Max_Read_Req_Size as
> > per the
> >
> > +  device-specific platform policy, as well as in complaince with the PCI Base
> >
> > +  specification Revision 4, that aligns the value for the entire PCI heirarchy
> >
> > +  starting from its physical PCI Root port / Bridge device.
> >
> > +
> >
> > +  @param PciDevice                      A pointer to the PCI_IO_DEVICE.
> >
> > +  @param PciConfigPhase                 for the PCI feature configuration phases:
> >
> > +                                        PciFeatureGetDevicePolicy & PciFeatureSetupPhase
> >
> > +  @param PciFeaturesConfigurationTable  pointer to
> > OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> >
> > +
> >
> > +  @retval EFI_SUCCESS                   processing of PCI feature
> > Max_Read_Req_Size
> >
> > +                                        is successful.
> >
> > +**/
> >
> > +EFI_STATUS
> >
> > +ProcessMaxReadReqSize (
> >
> > +  IN  PCI_IO_DEVICE                           *PciDevice,
> >
> > +  IN  PCI_FEATURE_CONFIGURATION_PHASE         PciConfigPhase,
> >
> > +  IN  OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > *PciFeaturesConfigurationTable
> >
> > +  )
> >
> > +{
> >
> > +  PCI_REG_PCIE_DEVICE_CAPABILITY  PciDeviceCap;
> >
> > +  UINT8                           MrrsValue;
> >
> > +
> >
> > +  PciDeviceCap.Uint32 = PciDevice->PciExpStruct.DeviceCapability.Uint32;
> >
> > +
> >
> > +  if ( PciConfigPhase == PciFeatureGetDevicePolicy) {
> >
> > +    if ( SetupMrrsAsPerDeviceCapability ( PciDevice->SetupMRRS))
> >
> > +    {
> >
> > +      //
> >
> > +      // The maximum read request size is not the data packet size of the
> TLP,
> >
> > +      // but the memory read request size, and set to the function as a
> > requestor
> >
> > +      // to not exceed this limit.
> >
> > +      // However, for the PCI device capable of isochronous traffic; this
> > memory read
> >
> > +      // request size should not extend beyond the Max_Payload_Size. Thus,
> > in case if
> >
> > +      // device policy return by platform indicates to set as per device
> > capability
> >
> > +      // than set as per Max_Payload_Size configuration value
> >
> > +      //
> >
> > +      if ( SetupMaxPayloadSize()) {
> >
> > +        MrrsValue = PciDevice->SetupMPS;
> >
> > +      } else {
> >
> > +        //
> >
> > +        // in case this driver is not required to configure the
> Max_Payload_Size
> >
> > +        // than consider programming HCF of the device capability's
> > Max_Payload_Size
> >
> > +        // in this PCI hierarchy; thus making this an implementation specific
> > feature
> >
> > +        // which the platform should avoid. For better results, the platform
> > should
> >
> > +        // make both the Max_Payload_Size & Max_Read_Request_Size to
> be
> > configured
> >
> > +        // by this driver
> >
> > +        //
> >
> > +        MrrsValue = (UINT8)PciDeviceCap.Bits.MaxPayloadSize;
> >
> > +      }
> >
> > +    } else {
> >
> > +      //
> >
> > +      // override as per platform based device policy
> >
> > +      //
> >
> > +      MrrsValue = TranslateMrrsSetupValueToPci ( PciDevice->SetupMRRS);
> >
> > +      //
> >
> > +      // align this device's Max_Read_Request_Size value to the entire PCI
> > tree
> >
> > +      //
> >
> > +      if ( PciFeaturesConfigurationTable) {
> >
> > +        if ( !PciFeaturesConfigurationTable->Lock_Max_Read_Request_Size)
> {
> >
> > +          PciFeaturesConfigurationTable->Lock_Max_Read_Request_Size =
> > TRUE;
> >
> > +          PciFeaturesConfigurationTable->Max_Read_Request_Size =
> > MrrsValue;
> >
> > +        } else {
> >
> > +          //
> >
> > +          // in case of another user enforced value of MRRS within the same
> > tree,
> >
> > +          // pick the smallest between the locked value and this value; to set
> >
> > +          // across entire PCI tree nodes
> >
> > +          //
> >
> > +          MrrsValue = MIN (
> >
> > +                        MrrsValue,
> >
> > +                        PciFeaturesConfigurationTable->Max_Read_Request_Size
> >
> > +                        );
> >
> > +          PciFeaturesConfigurationTable->Max_Read_Request_Size =
> > MrrsValue;
> >
> > +        }
> >
> > +      }
> >
> > +    }
> >
> > +    //
> >
> > +    // align this device's Max_Read_Request_Size to derived configuration
> > value
> >
> > +    //
> >
> > +    PciDevice->SetupMRRS = MrrsValue;
> >
> > +
> >
> > +  }
> >
> > +
> >
> > +  //
> >
> > +  // align the Max_Read_Request_Size of the PCI tree based on 3
> conditions:
> >
> > +  // first, if user defines MRRS for any one PCI device in the tree than align
> >
> > +  // all the devices in the PCI tree.
> >
> > +  // second, if user override is not define for this PCI tree than setup the
> > MRRS
> >
> > +  // based on MPS value of the tree to meet the criteria for the
> isochronous
> >
> > +  // traffic.
> >
> > +  // third, if no user override, or platform firmware policy has not selected
> >
> > +  // this PCI bus driver to configure the MPS; than configure the MRRS to a
> >
> > +  // highest common value of PCI device capability for the MPS found
> among
> > all
> >
> > +  // the PCI devices in this tree
> >
> > +  //
> >
> > +  if ( PciFeaturesConfigurationTable) {
> >
> > +    if ( PciFeaturesConfigurationTable->Lock_Max_Read_Request_Size) {
> >
> > +      PciDevice->SetupMRRS = PciFeaturesConfigurationTable-
> > >Max_Read_Request_Size;
> >
> > +    } else {
> >
> > +      if ( SetupMaxPayloadSize()) {
> >
> > +        PciDevice->SetupMRRS = PciDevice->SetupMPS;
> >
> > +      } else {
> >
> > +        PciDevice->SetupMRRS = MIN (
> >
> > +                                PciDevice->SetupMRRS,
> >
> > +                                PciFeaturesConfigurationTable-
> >Max_Read_Request_Size
> >
> > +                                );
> >
> > +      }
> >
> > +      PciFeaturesConfigurationTable->Max_Read_Request_Size =
> PciDevice-
> > >SetupMRRS;
> >
> > +    }
> >
> > +  }
> >
> > +  DEBUG (( DEBUG_INFO, "Max_Read_Request_Size: %d\n", PciDevice-
> > >SetupMRRS));
> >
> > +
> >
> > +  return EFI_SUCCESS;
> >
> > +}
> >
> > +
> >
> > +/**
> >
> > +  Overrides the PCI Device Control register MaxPayloadSize register field;
> if
> >
> > +  the hardware value is different than the intended value.
> >
> > +
> >
> > +  @param  PciDevice             A pointer to the PCI_IO_DEVICE instance.
> >
> > +
> >
> > +  @retval EFI_SUCCESS           The data was read from or written to the PCI
> > device.
> >
> > +  @retval EFI_UNSUPPORTED       The address range specified by Offset,
> > Width, and Count is not
> >
> > +                                valid for the PCI configuration header of the PCI controller.
> >
> > +  @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid.
> >
> > +
> >
> > +**/
> >
> > +EFI_STATUS
> >
> > +OverrideMaxPayloadSize (
> >
> > +  IN PCI_IO_DEVICE          *PciDevice
> >
> > +  )
> >
> > +{
> >
> > +  PCI_REG_PCIE_DEVICE_CONTROL PcieDev;
> >
> > +  UINT32                      Offset;
> >
> > +  EFI_STATUS                  Status;
> >
> > +
> >
> > +  PcieDev.Uint16 = 0;
> >
> > +  Offset = PciDevice->PciExpressCapabilityOffset +
> >
> > +               OFFSET_OF (PCI_CAPABILITY_PCIEXP, DeviceControl);
> >
> > +  Status = PciDevice->PciIo.Pci.Read (
> >
> > +                                  &PciDevice->PciIo,
> >
> > +                                  EfiPciIoWidthUint16,
> >
> > +                                  Offset,
> >
> > +                                  1,
> >
> > +                                  &PcieDev.Uint16
> >
> > +                                );
> >
> > +  if ( EFI_ERROR(Status)){
> >
> > +    DEBUG (( DEBUG_ERROR, "Unexpected DeviceControl register (0x%x)
> > read error!",
> >
> > +        Offset
> >
> > +    ));
> >
> > +    return Status;
> >
> > +  }
> >
> > +  if ( PcieDev.Bits.MaxPayloadSize != PciDevice->SetupMPS) {
> >
> > +    PcieDev.Bits.MaxPayloadSize = PciDevice->SetupMPS;
> >
> > +    DEBUG (( DEBUG_INFO, "Max_Payload_Size=%d,", PciDevice-
> > >SetupMPS));
> >
> > +
> >
> > +    Status = PciDevice->PciIo.Pci.Write (
> >
> > +                                    &PciDevice->PciIo,
> >
> > +                                    EfiPciIoWidthUint16,
> >
> > +                                    Offset,
> >
> > +                                    1,
> >
> > +                                    &PcieDev.Uint16
> >
> > +                                  );
> >
> > +    if ( !EFI_ERROR(Status)) {
> >
> > +      PciDevice->PciExpStruct.DeviceControl.Uint16 = PcieDev.Uint16;
> >
> > +    } else {
> >
> > +      DEBUG (( DEBUG_ERROR, "Unexpected DeviceControl register (0x%x)
> > write error!",
> >
> > +          Offset
> >
> > +      ));
> >
> > +    }
> >
> > +  } else {
> >
> > +    DEBUG (( DEBUG_INFO, "No write of Max_Payload_Size=%d,",
> PciDevice-
> > >SetupMPS));
> >
> > +  }
> >
> > +
> >
> > +  return Status;
> >
> > +}
> >
> > +
> >
> > +/**
> >
> > +  Overrides the PCI Device Control register MaxPayloadSize register field;
> if
> >
> > +  the hardware value is different than the intended value.
> >
> > +
> >
> > +  @param  PciDevice             A pointer to the PCI_IO_DEVICE instance.
> >
> > +
> >
> > +  @retval EFI_SUCCESS           The data was read from or written to the PCI
> > controller.
> >
> > +  @retval EFI_UNSUPPORTED       The address range specified by Offset,
> > Width, and Count is not
> >
> > +                                valid for the PCI configuration header of the PCI controller.
> >
> > +  @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid.
> >
> > +
> >
> > +**/
> >
> > +EFI_STATUS
> >
> > +OverrideMaxReadReqSize (
> >
> > +  IN PCI_IO_DEVICE          *PciDevice
> >
> > +  )
> >
> > +{
> >
> > +  PCI_REG_PCIE_DEVICE_CONTROL PcieDev;
> >
> > +  UINT32                      Offset;
> >
> > +  EFI_STATUS                  Status;
> >
> > +
> >
> > +  PcieDev.Uint16 = 0;
> >
> > +  Offset = PciDevice->PciExpressCapabilityOffset +
> >
> > +               OFFSET_OF (PCI_CAPABILITY_PCIEXP, DeviceControl);
> >
> > +  Status = PciDevice->PciIo.Pci.Read (
> >
> > +                                  &PciDevice->PciIo,
> >
> > +                                  EfiPciIoWidthUint16,
> >
> > +                                  Offset,
> >
> > +                                  1,
> >
> > +                                  &PcieDev.Uint16
> >
> > +                                );
> >
> > +  if ( EFI_ERROR(Status)){
> >
> > +    DEBUG (( DEBUG_ERROR, "Unexpected DeviceControl register (0x%x)
> > read error!",
> >
> > +        Offset
> >
> > +    ));
> >
> > +    return Status;
> >
> > +  }
> >
> > +  if ( PcieDev.Bits.MaxReadRequestSize != PciDevice->SetupMRRS) {
> >
> > +    PcieDev.Bits.MaxReadRequestSize = PciDevice->SetupMRRS;
> >
> > +    DEBUG (( DEBUG_INFO, "Max_Read_Request_Size: %d\n", PciDevice-
> > >SetupMRRS));
> >
> > +
> >
> > +    Status = PciDevice->PciIo.Pci.Write (
> >
> > +                                    &PciDevice->PciIo,
> >
> > +                                    EfiPciIoWidthUint16,
> >
> > +                                    Offset,
> >
> > +                                    1,
> >
> > +                                    &PcieDev.Uint16
> >
> > +                                  );
> >
> > +    if ( !EFI_ERROR(Status)) {
> >
> > +      PciDevice->PciExpStruct.DeviceControl.Uint16 = PcieDev.Uint16;
> >
> > +    } else {
> >
> > +      DEBUG (( DEBUG_ERROR, "Unexpected DeviceControl register (0x%x)
> > write error!",
> >
> > +          Offset
> >
> > +      ));
> >
> > +    }
> >
> > +  } else {
> >
> > +    DEBUG (( DEBUG_INFO, "No write of Max_Read_Request_Size=%d\n",
> > PciDevice->SetupMRRS));
> >
> > +  }
> >
> > +
> >
> > +  return Status;
> >
> > +}
> >
> > +
> >
> > +/**
> >
> > +  helper routine to dump the PCIe Device Port Type
> >
> > +**/
> >
> > +VOID
> >
> > +DumpDevicePortType (
> >
> > +  IN  UINT8   DevicePortType
> >
> > +  )
> >
> > +{
> >
> > +  switch ( DevicePortType){
> >
> > +    case PCIE_DEVICE_PORT_TYPE_PCIE_ENDPOINT:
> >
> > +      DEBUG (( DEBUG_INFO, "PCIe endpoint found\n"));
> >
> > +      break;
> >
> > +    case PCIE_DEVICE_PORT_TYPE_LEGACY_PCIE_ENDPOINT:
> >
> > +      DEBUG (( DEBUG_INFO, "legacy PCI endpoint found\n"));
> >
> > +      break;
> >
> > +    case PCIE_DEVICE_PORT_TYPE_ROOT_PORT:
> >
> > +      DEBUG (( DEBUG_INFO, "PCIe Root Port found\n"));
> >
> > +      break;
> >
> > +    case PCIE_DEVICE_PORT_TYPE_UPSTREAM_PORT:
> >
> > +      DEBUG (( DEBUG_INFO, "PCI switch upstream port found\n"));
> >
> > +      break;
> >
> > +    case PCIE_DEVICE_PORT_TYPE_DOWNSTREAM_PORT:
> >
> > +      DEBUG (( DEBUG_INFO, "PCI switch downstream port found\n"));
> >
> > +      break;
> >
> > +    case PCIE_DEVICE_PORT_TYPE_PCIE_TO_PCI_BRIDGE:
> >
> > +      DEBUG (( DEBUG_INFO, "PCIe-PCI bridge found\n"));
> >
> > +      break;
> >
> > +    case PCIE_DEVICE_PORT_TYPE_PCI_TO_PCIE_BRIDGE:
> >
> > +      DEBUG (( DEBUG_INFO, "PCI-PCIe bridge found\n"));
> >
> > +      break;
> >
> > +    case
> > PCIE_DEVICE_PORT_TYPE_ROOT_COMPLEX_INTEGRATED_ENDPOINT:
> >
> > +      DEBUG (( DEBUG_INFO, "RCiEP found\n"));
> >
> > +      break;
> >
> > +    case PCIE_DEVICE_PORT_TYPE_ROOT_COMPLEX_EVENT_COLLECTOR:
> >
> > +      DEBUG (( DEBUG_INFO, "RC Event Collector found\n"));
> >
> > +      break;
> >
> > +  }
> >
> > +}
> >
> > +
> >
> > +/**
> >
> > +   Process each PCI device as per the pltaform and device-specific policy.
> >
> > +
> >
> > +  @param RootBridge             A pointer to the PCI_IO_DEVICE.
> >
> > +
> >
> > +  @retval EFI_SUCCESS           processing each PCI feature as per policy
> > defined
> >
> > +                                was successful.
> >
> > + **/
> >
> > +EFI_STATUS
> >
> > +SetupDevicePciFeatures (
> >
> > +  IN  PCI_IO_DEVICE                   *PciDevice,
> >
> > +  IN  PCI_FEATURE_CONFIGURATION_PHASE PciConfigPhase
> >
> > +  )
> >
> > +{
> >
> > +  EFI_STATUS                              Status;
> >
> > +  PCI_REG_PCIE_CAPABILITY                 PcieCap;
> >
> > +  OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > *OtherPciFeaturesConfigTable;
> >
> > +
> >
> > +  PcieCap.Uint16 = PciDevice->PciExpStruct.Capability.Uint16;
> >
> > +  DumpDevicePortType ( (UINT8)PcieCap.Bits.DevicePortType);
> >
> > +
> >
> > +  OtherPciFeaturesConfigTable = NULL;
> >
> > +  Status = GetPciFeaturesConfigurationTable ( PciDevice,
> > &OtherPciFeaturesConfigTable);
> >
> > +  if ( EFI_ERROR( Status)) {
> >
> > +    DEBUG ((
> >
> > +        EFI_D_WARN, "No primary root port found in these root bridge
> > nodes!\n"
> >
> > +    ));
> >
> > +  } else if ( !OtherPciFeaturesConfigTable) {
> >
> > +    DEBUG ((
> >
> > +        DEBUG_INFO, "No PCI features config. table for this device!\n"
> >
> > +    ));
> >
> > +  } else {
> >
> > +    DEBUG ((
> >
> > +        DEBUG_INFO, "using PCI features config. table ID: %d\n",
> >
> > +        OtherPciFeaturesConfigTable->ID
> >
> > +    ));
> >
> > +  }
> >
> > +
> >
> > +  if ( PciConfigPhase == PciFeatureGetDevicePolicy) {
> >
> > +    Status = GetPciDevicePlatformPolicy ( PciDevice);
> >
> > +    if ( EFI_ERROR(Status)) {
> >
> > +      DEBUG ((
> >
> > +          DEBUG_ERROR, "Error in obtaining PCI device policy!!!\n"
> >
> > +      ));
> >
> > +    }
> >
> > +  }
> >
> > +
> >
> > +  if ( SetupMaxPayloadSize ()) {
> >
> > +    Status = ProcessMaxPayloadSize (
> >
> > +              PciDevice,
> >
> > +              PciConfigPhase,
> >
> > +              OtherPciFeaturesConfigTable
> >
> > +              );
> >
> > +  }
> >
> > +  //
> >
> > +  // implementation specific rule:- the MRRS of any PCI device should be
> > processed
> >
> > +  // only after the MPS is processed for that device
> >
> > +  //
> >
> > +  if ( SetupMaxReadReqSize ()) {
> >
> > +    Status = ProcessMaxReadReqSize (
> >
> > +              PciDevice,
> >
> > +              PciConfigPhase,
> >
> > +              OtherPciFeaturesConfigTable
> >
> > +              );
> >
> > +  }
> >
> > +  return Status;
> >
> > +}
> >
> > +
> >
> > +/**
> >
> > +  Traverse all the nodes from the root bridge or PCI-PCI bridge instance, to
> >
> > +  configure the PCI features as per the device-specific platform policy, and
> >
> > +  as per the device capability, as applicable.
> >
> > +
> >
> > +  @param RootBridge             A pointer to the PCI_IO_DEVICE.
> >
> > +
> >
> > +  @retval EFI_SUCCESS           Traversing all the nodes of the root bridge
> >
> > +                                instances were successfull.
> >
> > +**/
> >
> > +EFI_STATUS
> >
> > +SetupPciFeatures (
> >
> > +  IN  PCI_IO_DEVICE                   *RootBridge,
> >
> > +  IN  PCI_FEATURE_CONFIGURATION_PHASE PciConfigPhase
> >
> > +  )
> >
> > +{
> >
> > +  EFI_STATUS           Status;
> >
> > +  LIST_ENTRY           *Link;
> >
> > +  PCI_IO_DEVICE        *Device;
> >
> > +
> >
> > +  for ( Link = RootBridge->ChildList.ForwardLink
> >
> > +      ; Link != &RootBridge->ChildList
> >
> > +      ; Link = Link->ForwardLink
> >
> > +  ) {
> >
> > +    Device = PCI_IO_DEVICE_FROM_LINK (Link);
> >
> > +    if (IS_PCI_BRIDGE (&Device->Pci)) {
> >
> > +      DEBUG ((
> >
> > +          DEBUG_INFO, "::Bridge [%02x|%02x|%02x] -",
> >
> > +          Device->BusNumber, Device->DeviceNumber, Device-
> > >FunctionNumber
> >
> > +      ));
> >
> > +      if (Device->IsPciExp) {
> >
> > +        Status = SetupDevicePciFeatures ( Device, PciConfigPhase);
> >
> > +      } else {
> >
> > +        DEBUG (( DEBUG_INFO, "Not a PCIe capable device!\n"));
> >
> > +        //
> >
> > +        // PCI Bridge which does not have PCI Express Capability structure
> >
> > +        // cannot process this kind of PCI Bridge device
> >
> > +        //
> >
> > +
> >
> > +      }
> >
> > +
> >
> > +      SetupPciFeatures ( Device, PciConfigPhase);
> >
> > +    } else {
> >
> > +      DEBUG ((
> >
> > +          DEBUG_INFO, "::Device [%02x|%02x|%02x] -",
> >
> > +          Device->BusNumber, Device->DeviceNumber, Device-
> > >FunctionNumber
> >
> > +      ));
> >
> > +      if (Device->IsPciExp) {
> >
> > +
> >
> > +        Status = SetupDevicePciFeatures ( Device, PciConfigPhase);
> >
> > +      } else {
> >
> > +        DEBUG (( DEBUG_INFO, "Not a PCIe capable device!\n"));
> >
> > +        //
> >
> > +        // PCI Device which does not have PCI Express Capability structure
> >
> > +        // cannot process this kind of PCI device
> >
> > +        //
> >
> > +      }
> >
> > +    }
> >
> > +  }
> >
> > +
> >
> > +  return EFI_SUCCESS;
> >
> > +}
> >
> > +
> >
> > +/**
> >
> > +  Program the PCI device, to override the PCI features as per the policy,
> >
> > +  resolved from previous traverse.
> >
> > +
> >
> > +  @param RootBridge             A pointer to the PCI_IO_DEVICE.
> >
> > +
> >
> > +  @retval EFI_SUCCESS           The other PCI features configuration during
> > enumeration
> >
> > +                                of all the nodes of the PCI root bridge instance were
> >
> > +                                programmed in PCI-compliance pattern along with the
> >
> > +                                device-specific policy, as applicable.
> >
> > +  @retval EFI_UNSUPPORTED       One of the override operation maong the
> > nodes of
> >
> > +                                the PCI hierarchy resulted in a incompatible address
> >
> > +                                range.
> >
> > +  @retval EFI_INVALID_PARAMETER The override operation is performed
> > with invalid input
> >
> > +                                parameters.
> >
> > +**/
> >
> > +EFI_STATUS
> >
> > +ProgramDevicePciFeatures (
> >
> > +  IN PCI_IO_DEVICE          *PciDevice
> >
> > +  )
> >
> > +{
> >
> > +  EFI_STATUS           Status;
> >
> > +
> >
> > +  if ( SetupMaxPayloadSize ()) {
> >
> > +    Status = OverrideMaxPayloadSize (PciDevice);
> >
> > +  }
> >
> > +  if ( SetupMaxReadReqSize ()) {
> >
> > +    Status = OverrideMaxReadReqSize (PciDevice);
> >
> > +  }
> >
> > +  return Status;
> >
> > +}
> >
> > +
> >
> > +/**
> >
> > +  Program all the nodes of the specified root bridge or PCI-PCI Bridge, to
> >
> > +  override the PCI features.
> >
> > +
> >
> > +  @param RootBridge             A pointer to the PCI_IO_DEVICE.
> >
> > +
> >
> > +  @retval EFI_SUCCESS           The other PCI features configuration during
> > enumeration
> >
> > +                                of all the nodes of the PCI root bridge instance were
> >
> > +                                programmed in PCI-compliance pattern along with the
> >
> > +                                device-specific policy, as applicable.
> >
> > +  @retval EFI_UNSUPPORTED       One of the override operation maong the
> > nodes of
> >
> > +                                the PCI hierarchy resulted in a incompatible address
> >
> > +                                range.
> >
> > +  @retval EFI_INVALID_PARAMETER The override operation is performed
> > with invalid input
> >
> > +                                parameters.
> >
> > +**/
> >
> > +EFI_STATUS
> >
> > +ProgramPciFeatures (
> >
> > +  IN PCI_IO_DEVICE          *RootBridge
> >
> > +  )
> >
> > +{
> >
> > +  EFI_STATUS           Status;
> >
> > +  LIST_ENTRY           *Link;
> >
> > +  PCI_IO_DEVICE        *Device;
> >
> > +
> >
> > +  for ( Link = RootBridge->ChildList.ForwardLink
> >
> > +      ; Link != &RootBridge->ChildList
> >
> > +      ; Link = Link->ForwardLink
> >
> > +  ) {
> >
> > +    Device = PCI_IO_DEVICE_FROM_LINK (Link);
> >
> > +    if (IS_PCI_BRIDGE (&Device->Pci)) {
> >
> > +      DEBUG ((
> >
> > +          DEBUG_INFO, "::Bridge [%02x|%02x|%02x] -",
> >
> > +          Device->BusNumber, Device->DeviceNumber, Device-
> > >FunctionNumber
> >
> > +      ));
> >
> > +      if (Device->IsPciExp) {
> >
> > +        DEBUG (( DEBUG_INFO, "ready to override!\n"));
> >
> > +
> >
> > +        Status = ProgramDevicePciFeatures ( Device);
> >
> > +      } else {
> >
> > +        DEBUG (( DEBUG_INFO, "skipped!\n"));
> >
> > +        //
> >
> > +        // PCI Bridge which does not have PCI Express Capability structure
> >
> > +        // cannot process this kind of PCI Bridge device
> >
> > +        //
> >
> > +
> >
> > +      }
> >
> > +
> >
> > +      Status = ProgramPciFeatures ( Device);
> >
> > +    } else {
> >
> > +      DEBUG ((
> >
> > +          DEBUG_INFO, "::Device [%02x|%02x|%02x] -",
> >
> > +          Device->BusNumber, Device->DeviceNumber, Device-
> > >FunctionNumber
> >
> > +      ));
> >
> > +      if (Device->IsPciExp) {
> >
> > +        DEBUG (( DEBUG_INFO, "ready to override!\n"));
> >
> > +
> >
> > +        Status = ProgramDevicePciFeatures ( Device);
> >
> > +      } else {
> >
> > +        DEBUG (( DEBUG_INFO, "skipped!\n"));
> >
> > +        //
> >
> > +        // PCI Device which does not have PCI Express Capability structure
> >
> > +        // cannot process this kind of PCI device
> >
> > +        //
> >
> > +      }
> >
> > +    }
> >
> > +  }
> >
> > +
> >
> > +  return Status;
> >
> > +}
> >
> > +
> >
> > +/**
> >
> > +  Create a node of type PRIMARY_ROOT_PORT_NODE for the given PCI
> > device, and
> >
> > +  assigns EFI handles of its Root Bridge and its own, along with its PCI Bus
> >
> > +  range for the secondary and subordinate bus range.
> >
> > +
> >
> > +  @param  RootBridge          A pointer to the PCI_IO_DEVICE for its PCI Root
> > Bridge
> >
> > +  @param  Device              A pointer to the PCI_IO_DEVICE for the PCI
> > controller
> >
> > +  @param  RootPortSecBus      PCI controller's Secondary Bus number
> >
> > +  @param  RootPortSubBus      PCI controller's Subordinate Bus number
> >
> > +  @param  PrimaryRootPortNode A pointer to the
> > PRIMARY_ROOT_PORT_NODE to return
> >
> > +                              the newly created node for the PCI controller. In
> >
> > +                              case of error nothing is return in this.
> >
> > +
> >
> > +  @retval EFI_SUCCESS           new node of PRIMARY_ROOT_PORT_NODE is
> > returned for
> >
> > +                                the PCI controller
> >
> > +          EFI_OUT_OF_RESOURCES  unable to create the node for the PCI
> > controller
> >
> > +          EFI_INVALID_PARAMETER unable to store the node as the input
> > buffer is
> >
> > +                                not empty (*PrimaryRootPortNode)
> >
> > +**/
> >
> > +EFI_STATUS
> >
> > +CreatePrimaryPciRootPortNode (
> >
> > +  IN  PCI_IO_DEVICE           *RootBridge,
> >
> > +  IN  PCI_IO_DEVICE           *Device,
> >
> > +  IN  UINT8                   RootPortSecBus,
> >
> > +  IN  UINT8                   RootPortSubBus,
> >
> > +  OUT PRIMARY_ROOT_PORT_NODE  **PrimaryRootPortNode
> >
> > +  )
> >
> > +{
> >
> > +  PRIMARY_ROOT_PORT_NODE      *RootPortNode = NULL;
> >
> > +
> >
> > +  if ( !*PrimaryRootPortNode) {
> >
> > +    RootPortNode                    = AllocateZeroPool ( sizeof
> > (PRIMARY_ROOT_PORT_NODE));
> >
> > +    if ( RootPortNode == NULL) {
> >
> > +      return EFI_OUT_OF_RESOURCES;
> >
> > +    }
> >
> > +    RootPortNode->Signature         = PCI_ROOT_PORT_SIGNATURE;
> >
> > +    RootPortNode->RootBridgeHandle  = RootBridge->Handle;
> >
> > +    RootPortNode->RootPortHandle    = Device->Handle;
> >
> > +    RootPortNode->SecondaryBusStart = RootPortSecBus;
> >
> > +    RootPortNode->SecondaryBusEnd   = RootPortSubBus;
> >
> > +    InitializeListHead ( &RootPortNode->NeighborRootPort);
> >
> > +    *PrimaryRootPortNode = RootPortNode;
> >
> > +    return EFI_SUCCESS;
> >
> > +  } else {
> >
> > +    return EFI_INVALID_PARAMETER;
> >
> > +  }
> >
> > +}
> >
> > +
> >
> > +/**
> >
> > +  Checks to report whether the input PCI controller's secondary /
> > subordinate
> >
> > +  bus numbers are within the recorded list of other PCI controllers (root
> > ports).
> >
> > +
> >
> > +  @param  RootPortNode      A pointer to the first node of
> > PRIMARY_ROOT_PORT_NODE
> >
> > +  @param  RootPortSecBus    PCI secondary bus number of the PCI
> controller
> > found
> >
> > +  @param  RootPortSubBus    PCI subordinate bus number of the PCI Root
> > Port found
> >
> > +
> >
> > +  @retval TRUE              A child PCI Root port found
> >
> > +          FALSE             A new PCI controller found
> >
> > +**/
> >
> > +BOOLEAN
> >
> > +CheckChildRootPort (
> >
> > +  IN      PRIMARY_ROOT_PORT_NODE  *RootPortNode,
> >
> > +  IN      UINT8                   RootPortSecBus,
> >
> > +  IN      UINT8                   RootPortSubBus
> >
> > +)
> >
> > +{
> >
> > +  LIST_ENTRY              *Link;
> >
> > +  PRIMARY_ROOT_PORT_NODE  *Temp;
> >
> > +
> >
> > +  if ( !RootPortNode) {
> >
> > +    return FALSE;
> >
> > +  }
> >
> > +  Link = &RootPortNode->NeighborRootPort;
> >
> > +  do {
> >
> > +    Temp = PRIMARY_ROOT_PORT_NODE_FROM_LINK ( Link);
> >
> > +    if ( RootPortSecBus >= Temp->SecondaryBusStart
> >
> > +        && RootPortSubBus <= Temp->SecondaryBusEnd) {
> >
> > +      //
> >
> > +      // given root port's secondary & subordinate within its primary ports
> >
> > +      // hence return as child port
> >
> > +      //
> >
> > +      return TRUE;
> >
> > +    }
> >
> > +    Link = Link->ForwardLink;
> >
> > +  } while (Link != &RootPortNode->NeighborRootPort);
> >
> > +  //
> >
> > +  // the given root port's secondary / subordinate bus numbers do not
> > belong to
> >
> > +  // any existing primary root port's bus range hence consider another
> > primary
> >
> > +  // root port of the root bridge controller
> >
> > +  //
> >
> > +  return FALSE;
> >
> > +}
> >
> > +
> >
> > +/**
> >
> > +  Create the vector of PCI Feature configuration table as per the number
> of
> >
> > +  the PCI Root Ports given, assigns default value to the PCI features
> > supported
> >
> > +  and assign its address to the global variable
> > "mPciFeaturesConfigurationTableInstances".
> >
> > +
> >
> > +  @param  NumberOfRootPorts   An input arguement of UINTN to indicate
> > number of
> >
> > +                              primary PCI physical Root Bridge devices found
> >
> > +
> >
> > +  @retval EFI_OUT_OF_RESOURCES  unable to allocate buffer to store PCI
> > feature
> >
> > +                                configuration table for all the physical PCI root
> >
> > +                                ports given
> >
> > +          EFI_SUCCESS           PCI Feature COnfiguration table created for all
> >
> > +                                the PCI Rooot ports reported
> >
> > + */
> >
> > +EFI_STATUS
> >
> > +CreatePciFeaturesConfigurationTableInstances (
> >
> > +  IN  UINTN NumberOfRootPorts
> >
> > +  )
> >
> > +{
> >
> > +  OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > *PciRootBridgePortFeatures = NULL;
> >
> > +  UINTN                                     Instances;
> >
> > +
> >
> > +  PciRootBridgePortFeatures = AllocateZeroPool (
> >
> > +                                sizeof ( OTHER_PCI_FEATURES_CONFIGURATION_TABLE)
> *
> > NumberOfRootPorts
> >
> > +                                );
> >
> > +  if ( !PciRootBridgePortFeatures) {
> >
> > +    return EFI_OUT_OF_RESOURCES;
> >
> > +  }
> >
> > +
> >
> > +  for ( Instances = 0; Instances < NumberOfRootPorts; Instances++) {
> >
> > +    PciRootBridgePortFeatures [Instances].ID                    = Instances + 1;
> >
> > +    PciRootBridgePortFeatures [Instances].Max_Payload_Size      =
> > PCIE_MAX_PAYLOAD_SIZE_4096B;
> >
> > +    PciRootBridgePortFeatures [Instances].Max_Read_Request_Size =
> > PCIE_MAX_READ_REQ_SIZE_4096B;
> >
> > +    PciRootBridgePortFeatures [Instances].Lock_Max_Read_Request_Size
> =
> > FALSE;
> >
> > +  }
> >
> > +  mPciFeaturesConfigurationTableInstances = PciRootBridgePortFeatures;
> >
> > +  return EFI_SUCCESS;
> >
> > +}
> >
> > +
> >
> > +/**
> >
> > +  This routine pairs the each PCI Root Port node with one of the PCI
> Feature
> >
> > +  Configuration Table node. Each physical PCI Root Port has its own PCI
> > feature
> >
> > +  configuration table which will used for aligning all its downstream
> > components.
> >
> > +
> >
> > +  @param  NumberOfRootPorts     inputs the number of physical PCI root
> > ports
> >
> > +                                found on the Root bridge instance
> >
> > +
> >
> > +  @retval EFI_INVALID_PARAMETER if the primary PCI root ports list is
> > vacant when
> >
> > +                                there is one or more PCI Root port indicated as per
> >
> > +                                input parameter
> >
> > +          EFI_UNSUPPORTED       The PCI Root Port nodes not paired equally
> with
> >
> > +                                the PCI Configuration Table nodes
> >
> > +          EFI_SUCCESS           each PCI feature configuration node is paired
> > equally
> >
> > +                                with each PCI Root port in the list
> >
> > +**/
> >
> > +EFI_STATUS
> >
> > +AssignPciFeaturesConfigurationTable (
> >
> > +  IN  UINTN NumberOfRootPorts
> >
> > +  )
> >
> > +{
> >
> > +  UINTN                       Instances;
> >
> > +  LIST_ENTRY                  *Link;
> >
> > +  PRIMARY_ROOT_PORT_NODE      *Temp;
> >
> > +
> >
> > +  if ( !mPrimaryRootPortList
> >
> > +      && NumberOfRootPorts) {
> >
> > +    DEBUG ((
> >
> > +        DEBUG_ERROR,
> >
> > +        "Critical error! no internal table setup for %d PCI Root ports \n",
> >
> > +        NumberOfRootPorts
> >
> > +    ));
> >
> > +    return EFI_INVALID_PARAMETER;
> >
> > +  }
> >
> > +
> >
> > +  if ( NumberOfRootPorts) {
> >
> > +    Link = &mPrimaryRootPortList->NeighborRootPort;
> >
> > +    for ( Instances = 0
> >
> > +        ; (Instances < NumberOfRootPorts)
> >
> > +        ; Instances++
> >
> > +    ) {
> >
> > +      Temp = PRIMARY_ROOT_PORT_NODE_FROM_LINK ( Link);
> >
> > +      Temp->OtherPciFeaturesConfigurationTable =
> > &mPciFeaturesConfigurationTableInstances [Instances];
> >
> > +      DEBUG ((
> >
> > +          DEBUG_INFO,
> >
> > +          "Assigned to %dth primary root port\n",
> >
> > +          Instances
> >
> > +      ));
> >
> > +
> >
> > +      Link = Link->ForwardLink;
> >
> > +    }
> >
> > +    if ( Link != &mPrimaryRootPortList->NeighborRootPort) {
> >
> > +      DEBUG ((
> >
> > +          DEBUG_ERROR,
> >
> > +          "Error!! PCI Root Port list is not properly matched with Config., Table
> > list \n"
> >
> > +      ));
> >
> > +      return EFI_UNSUPPORTED;
> >
> > +    }
> >
> > +  }
> >
> > +  return  EFI_SUCCESS;
> >
> > +}
> >
> > +
> >
> > +/**
> >
> > +  Prepare each PCI Controller (Root Port) with its own PCI Feature
> > configuration
> >
> > +  table node that can be used for tracking to align all PCI nodes in its
> > hierarchy.
> >
> > +
> >
> > +  @param  PrimaryRootPorts      A pointer to PRIMARY_ROOT_PORT_NODE
> >
> > +  @param  NumberOfRootPorts     Total number of pysical primary PCI
> Root
> > ports
> >
> > +
> >
> > +  @retval EFI_OUT_OF_RESOURCES  unable to allocate buffer to store PCI
> > feature
> >
> > +                                configuration table for all the physical PCI root
> >
> > +                                ports given
> >
> > +          EFI_INVALID_PARAMETER if the primary PCI root ports list is vacant
> > when
> >
> > +                                there is one or more PCI Root port indicated as per
> >
> > +                                input parameter
> >
> > +          EFI_UNSUPPORTED       The PCI Root Port nodes not paired equally
> with
> >
> > +                                the PCI Configuration Table nodes
> >
> > +          EFI_SUCCESS           each PCI feature configuration node is paired
> > equally
> >
> > +                                with each PCI Root port in the list
> >
> > +**/
> >
> > +EFI_STATUS
> >
> > +PreparePciControllerConfigurationTable (
> >
> > +  IN  PRIMARY_ROOT_PORT_NODE    *PrimaryRootPorts,
> >
> > +  IN  UINTN                     NumberOfRootPorts
> >
> > +  )
> >
> > +{
> >
> > +  EFI_STATUS                    Status;
> >
> > +
> >
> > +  mPrimaryRootPortList = PrimaryRootPorts;
> >
> > +  DEBUG ((
> >
> > +      DEBUG_INFO, "Number of primary Root Ports found on this bridge
> > = %d\n",
> >
> > +      NumberOfRootPorts
> >
> > +  ));
> >
> > +
> >
> > +  Status = CreatePciFeaturesConfigurationTableInstances
> > ( NumberOfRootPorts);
> >
> > +  if ( EFI_ERROR(Status)) {
> >
> > +    DEBUG ((
> >
> > +        DEBUG_ERROR, "Unexpected memory node creation error for PCI
> > features!\n"
> >
> > +    ));
> >
> > +  } else {
> >
> > +    //
> >
> > +    // align the primary root port nodes list with the PCI Feature
> configuration
> >
> > +    // table. Note that the PCI Feature configuration table is not maintain
> for
> >
> > +    // the RCiEP devices
> >
> > +    //
> >
> > +    Status = AssignPciFeaturesConfigurationTable ( NumberOfRootPorts);
> >
> > +  }
> >
> > +  return Status;
> >
> > +}
> >
> > +
> >
> > +/**
> >
> > +  Scan all the nodes of the RootBridge to identify and create a separate list
> >
> > +  of all primary physical PCI root ports and link each with its own instance
> of
> >
> > +  the PCI Feature Configuration Table.
> >
> > +
> >
> > +  @param  RootBridge    A pointer to the PCI_IO_DEVICE of the PCI Root
> > Bridge
> >
> > +
> >
> > +  @retval EFI_OUT_OF_RESOURCES  unable to allocate buffer to store PCI
> > feature
> >
> > +                                configuration table for all the physical PCI root
> >
> > +                                ports given
> >
> > +          EFI_NOT_FOUND         No PCI Bridge device found
> >
> > +          EFI_SUCCESS           PCI Feature COnfiguration table created for all
> >
> > +                                the PCI Rooot ports found
> >
> > +          EFI_INVALID_PARAMETER invalid parameter passed to the routine
> > which
> >
> > +                                creates the PCI controller node for the primary
> >
> > +                                Root post list
> >
> > +**/
> >
> > +EFI_STATUS
> >
> > +RecordPciRootPortBridges (
> >
> > +  IN  PCI_IO_DEVICE           *RootBridge
> >
> > +  )
> >
> > +{
> >
> > +  EFI_STATUS              Status = EFI_NOT_FOUND;
> >
> > +  LIST_ENTRY              *Link;
> >
> > +  PCI_IO_DEVICE           *Device;
> >
> > +  UINTN                   NumberOfRootPorts;
> >
> > +  PRIMARY_ROOT_PORT_NODE  *PrimaryRootPorts,
> >
> > +                          *TempNode;
> >
> > +  UINT8                   RootPortSecBus,
> >
> > +                          RootPortSubBus;
> >
> > +
> >
> > +  DEBUG ((
> >
> > +      DEBUG_INFO, "<<********** RecordPciRootPortBridges -start
> > *************>>\n"
> >
> > +  ));
> >
> > +  NumberOfRootPorts = 0;
> >
> > +  PrimaryRootPorts = NULL;
> >
> > +  for ( Link = RootBridge->ChildList.ForwardLink
> >
> > +      ; Link != &RootBridge->ChildList
> >
> > +      ; Link = Link->ForwardLink
> >
> > +  ) {
> >
> > +    Device = PCI_IO_DEVICE_FROM_LINK (Link);
> >
> > +    if (IS_PCI_BRIDGE (&Device->Pci)) {
> >
> > +      Status = GetPciRootPortBusAssigned (
> >
> > +                  Device,
> >
> > +                  NULL,
> >
> > +                  &RootPortSecBus,
> >
> > +                  &RootPortSubBus
> >
> > +                  );
> >
> > +      if ( !EFI_ERROR(Status)) {
> >
> > +        DEBUG ((
> >
> > +            DEBUG_INFO, "::Device [%02x|%02x|%02x] - SecBus=0x%x,
> > SubBus=0x%x\n",
> >
> > +            Device->BusNumber, Device->DeviceNumber, Device-
> > >FunctionNumber,
> >
> > +            RootPortSecBus, RootPortSubBus
> >
> > +        ));
> >
> > +      } else {
> >
> > +        DEBUG ((
> >
> > +            DEBUG_ERROR, "Unexpected read error [0x%lx]::Device
> > [%02x|%02x|%02x]\n",
> >
> > +            Status, Device->BusNumber, Device->DeviceNumber, Device-
> > >FunctionNumber
> >
> > +        ));
> >
> > +        RootPortSecBus = RootPortSubBus = 0;
> >
> > +        continue;
> >
> > +      }
> >
> > +
> >
> > +      if ( !PrimaryRootPorts) {
> >
> > +        NumberOfRootPorts++;
> >
> > +        Status = CreatePrimaryPciRootPortNode (
> >
> > +                    RootBridge,
> >
> > +                    Device,
> >
> > +                    RootPortSecBus,
> >
> > +                    RootPortSubBus,
> >
> > +                    &PrimaryRootPorts
> >
> > +                    );
> >
> > +        if ( EFI_ERROR(Status)) {
> >
> > +          //
> >
> > +          // abort mission to scan for all primary roots ports of a bridge
> >
> > +          // controller if error encountered for very first PCI primary root port
> >
> > +          //
> >
> > +          DEBUG ((
> >
> > +              DEBUG_ERROR, "Unexpected node creation error [0x%lx]::Device
> > [%02x|%02x|%02x]\n",
> >
> > +              Status, Device->BusNumber, Device->DeviceNumber, Device-
> > >FunctionNumber
> >
> > +          ));
> >
> > +          return Status;
> >
> > +        }
> >
> > +        DEBUG ((
> >
> > +            DEBUG_INFO, "first primary root port found::Device
> > [%02x|%02x|%02x]\n",
> >
> > +            Device->BusNumber, Device->DeviceNumber, Device-
> > >FunctionNumber
> >
> > +        ));
> >
> > +      } else {
> >
> > +        if ( !CheckChildRootPort ( PrimaryRootPorts, RootPortSecBus,
> > RootPortSubBus)) {
> >
> > +          NumberOfRootPorts++;
> >
> > +          TempNode = NULL;
> >
> > +          Status = CreatePrimaryPciRootPortNode (
> >
> > +                      RootBridge,
> >
> > +                      Device,
> >
> > +                      RootPortSecBus,
> >
> > +                      RootPortSubBus,
> >
> > +                      &TempNode
> >
> > +                      );
> >
> > +          if ( !EFI_ERROR(Status)) {
> >
> > +            //
> >
> > +            // another primary root port found on the same bridge controller
> >
> > +            // insert in the node list
> >
> > +            //
> >
> > +            InsertTailList ( &PrimaryRootPorts->NeighborRootPort,
> &TempNode-
> > >NeighborRootPort);
> >
> > +            DEBUG ((
> >
> > +                DEBUG_INFO, "next primary root port found::Device
> > [%02x|%02x|%02x]\n",
> >
> > +                Device->BusNumber, Device->DeviceNumber, Device-
> > >FunctionNumber
> >
> > +            ));
> >
> > +          } else {
> >
> > +            DEBUG ((
> >
> > +                DEBUG_ERROR, "Unexpected node creation error [0x%lx]::Device
> > [%02x|%02x|%02x]\n",
> >
> > +                Status, Device->BusNumber, Device->DeviceNumber, Device-
> > >FunctionNumber
> >
> > +            ));
> >
> > +          }
> >
> > +        }
> >
> > +      }
> >
> > +    }
> >
> > +  }
> >
> > +  //
> >
> > +  // prepare the PCI root port and its feature configuration table list
> >
> > +  //
> >
> > +  if ( NumberOfRootPorts) {
> >
> > +    Status = PreparePciControllerConfigurationTable (
> >
> > +                PrimaryRootPorts,
> >
> > +                NumberOfRootPorts
> >
> > +              );
> >
> > +
> >
> > +  } else {
> >
> > +    DEBUG ((
> >
> > +        DEBUG_INFO, "No PCI Root port found on this bridge!\n"
> >
> > +    ));
> >
> > +  }
> >
> > +
> >
> > +  DEBUG ((
> >
> > +      DEBUG_INFO, "<<********** RecordPciRootPortBridges - end
> > **********>>\n"
> >
> > +  ));
> >
> > +  return Status;
> >
> > +}
> >
> > +
> >
> > +/**
> >
> > +  Enumerate all the nodes of the specified root bridge or PCI-PCI Bridge, to
> >
> > +  configure the other PCI features.
> >
> > +
> >
> > +  @param RootBridge          A pointer to the PCI_IO_DEVICE.
> >
> > +
> >
> > +  @retval EFI_SUCCESS           The other PCI features configuration during
> > enumeration
> >
> > +                                of all the nodes of the PCI root bridge instance were
> >
> > +                                programmed in PCI-compliance pattern along with the
> >
> > +                                device-specific policy, as applicable.
> >
> > +  @retval EFI_UNSUPPORTED       One of the override operation maong the
> > nodes of
> >
> > +                                the PCI hierarchy resulted in a incompatible address
> >
> > +                                range.
> >
> > +  @retval EFI_INVALID_PARAMETER The override operation is performed
> > with invalid input
> >
> > +                                parameters.
> >
> > +**/
> >
> > +EFI_STATUS
> >
> > +EnumerateOtherPciFeatures (
> >
> > +  IN PCI_IO_DEVICE          *RootBridge
> >
> > +  )
> >
> > +{
> >
> > +  EFI_STATUS            Status;
> >
> > +  CHAR16                *Str;
> >
> > +  UINTN                 OtherPciFeatureConfigPhase;
> >
> > +
> >
> > +  //
> >
> > +  // check on PCI features configuration is complete and re-enumeration is
> > required
> >
> > +  //
> >
> > +  if ( !CheckPciFeaturesConfigurationRequired ( RootBridge)) {
> >
> > +    return EFI_ALREADY_STARTED;
> >
> > +  }
> >
> > +
> >
> > +  Str = ConvertDevicePathToText (
> >
> > +          DevicePathFromHandle (RootBridge->Handle),
> >
> > +          FALSE,
> >
> > +          FALSE
> >
> > +        );
> >
> > +  DEBUG ((DEBUG_INFO, "Enumerating PCI features for Root Bridge %s\n",
> > Str != NULL ? Str : L""));
> >
> > +
> >
> > +  for ( OtherPciFeatureConfigPhase = PciFeatureRootBridgeScan
> >
> > +      ; OtherPciFeatureConfigPhase <= PciFeatureConfigurationComplete
> >
> > +      ; OtherPciFeatureConfigPhase++
> >
> > +      ) {
> >
> > +    switch ( OtherPciFeatureConfigPhase){
> >
> > +      case  PciFeatureRootBridgeScan:
> >
> > +        SetupPciFeaturesConfigurationDefaults ();
> >
> > +        //
> >
> > +        //first scan the entire root bridge heirarchy for the primary PCI root
> > ports
> >
> > +        //
> >
> > +        RecordPciRootPortBridges ( RootBridge);
> >
> > +        break;
> >
> > +
> >
> > +      case  PciFeatureGetDevicePolicy:
> >
> > +      case  PciFeatureSetupPhase:
> >
> > +        DEBUG ((
> >
> > +            DEBUG_INFO, "<<********** SetupPciFeatures - start
> > **********>>\n"
> >
> > +        ));
> >
> > +        //
> >
> > +        // enumerate the other PCI features
> >
> > +        //
> >
> > +        Status = SetupPciFeatures ( RootBridge, OtherPciFeatureConfigPhase);
> >
> > +
> >
> > +        DEBUG ((
> >
> > +            DEBUG_INFO, "<<********** SetupPciFeatures - end
> > **********>>\n"
> >
> > +        ));
> >
> > +        break;
> >
> > +
> >
> > +      case  PciFeatureConfigurationPhase:
> >
> > +        //
> >
> > +        // override the PCI features as per enumeration phase
> >
> > +        //
> >
> > +        DEBUG ((DEBUG_INFO, "PCI features override for Root Bridge %s\n",
> > Str != NULL ? Str : L""));
> >
> > +        DEBUG ((
> >
> > +            DEBUG_INFO, "<<********** ProgramPciFeatures - start
> > **********>>\n"
> >
> > +        ));
> >
> > +        Status = ProgramPciFeatures ( RootBridge);
> >
> > +        DEBUG ((
> >
> > +            DEBUG_INFO, "<<********** ProgramPciFeatures - end
> > **********>>\n"
> >
> > +        ));
> >
> > +        break;
> >
> > +
> >
> > +      case  PciFeatureConfigurationComplete:
> >
> > +        //
> >
> > +        // clean up the temporary resource nodes created for this root bridge
> >
> > +        //
> >
> > +        DestroyPrimaryRootPortNodes ();
> >
> > +
> >
> > +        ErasePciFeaturesConfigurationTable ();
> >
> > +    }
> >
> > +  }
> >
> > +
> >
> > +  if (Str != NULL) {
> >
> > +    FreePool (Str);
> >
> > +  }
> >
> > +  //
> >
> > +  // mark this root bridge as PCI features configuration complete, and no
> > new
> >
> > +  // enumeration is required
> >
> > +  //
> >
> > +  AddRootBridgeInPciFeaturesConfigCompletionList ( RootBridge, FALSE);
> >
> > +  return Status;
> >
> > +}
> >
> > +
> >
> > +/**
> >
> > +  This routine is invoked from the Stop () interface for the EFI handle of
> the
> >
> > +  RootBridge. Free up its node of type
> > PCI_FEATURE_CONFIGURATION_COMPLETION_LIST.
> >
> > +
> >
> > +  @param  RootBridge      A pointer to the PCI_IO_DEVICE
> >
> > +**/
> >
> > +VOID
> >
> > +DestroyRootBridgePciFeaturesConfigCompletionList (
> >
> > +  IN PCI_IO_DEVICE          *RootBridge
> >
> > +  )
> >
> > +{
> >
> > +  LIST_ENTRY                                  *Link;
> >
> > +  PCI_FEATURE_CONFIGURATION_COMPLETION_LIST   *Temp;
> >
> > +
> >
> > +  if ( mPciFeaturesConfigurationCompletionList) {
> >
> > +    Link = &mPciFeaturesConfigurationCompletionList->RootBridgeLink;
> >
> > +
> >
> > +    do {
> >
> > +      Temp =
> > PCI_FEATURE_CONFIGURATION_COMPLETION_LIST_FROM_LINK (Link);
> >
> > +      if ( Temp->RootBridgeHandle == RootBridge->Handle) {
> >
> > +        RemoveEntryList ( Link);
> >
> > +        FreePool ( Temp);
> >
> > +        return;
> >
> > +      }
> >
> > +      Link = Link->ForwardLink;
> >
> > +    } while (Link != &mPciFeaturesConfigurationCompletionList-
> > >RootBridgeLink);
> >
> > +  }
> >
> > +  //
> >
> > +  // not found on the PCI feature configuration completion list, return
> >
> > +  //
> >
> > +  return;
> >
> > +}
> >
> > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> > new file mode 100644
> > index 0000000000..9f225fa993
> > --- /dev/null
> > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> > @@ -0,0 +1,201 @@
> > +/** @file
> >
> > +  PCI standard feature support functions implementation for PCI Bus
> > module..
> >
> > +
> >
> > +Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> >
> > +SPDX-License-Identifier: BSD-2-Clause-Patent
> >
> > +
> >
> > +**/
> >
> > +
> >
> > +#ifndef _EFI_PCI_FEATURES_SUPPORT_H_
> >
> > +#define _EFI_PCI_FEATURES_SUPPORT_H_
> >
> > +
> >
> > +#include "PciBus.h"
> >
> > +#include "PciPlatformSupport.h"
> >
> > +
> >
> > +//
> >
> > +// Macro definitions for the PCI Features support PCD
> >
> > +//
> >
> > +#define PCI_FEATURE_SUPPORT_FLAG_MPS  BIT0
> >
> > +#define PCI_FEATURE_SUPPORT_FLAG_MRRS BIT1
> >
> > +
> >
> > +//
> >
> > +// defines the data structure to hold the details of the PCI Root port
> devices
> >
> > +//
> >
> > +typedef struct _PRIMARY_ROOT_PORT_NODE
> > PRIMARY_ROOT_PORT_NODE;
> >
> > +
> >
> > +//
> >
> > +// defines the data structure to hold the configuration data for the other
> > PCI
> >
> > +// features
> >
> > +//
> >
> > +typedef struct _OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > OTHER_PCI_FEATURES_CONFIGURATION_TABLE;
> >
> > +
> >
> > +//
> >
> > +// Defines for the PCI features configuration completion and re-
> > enumeration list
> >
> > +//
> >
> > +typedef struct _PCI_FEATURE_CONFIGURATION_COMPLETION_LIST
> > PCI_FEATURE_CONFIGURATION_COMPLETION_LIST;
> >
> > +
> >
> > +//
> >
> > +// Signature value for the PCI Root Port node
> >
> > +//
> >
> > +#define PCI_ROOT_PORT_SIGNATURE               SIGNATURE_32 ('p', 'c', 'i',
> 'p')
> >
> > +
> >
> > +//
> >
> > +// Definitions of the PCI Root Port data structure members
> >
> > +//
> >
> > +struct _PRIMARY_ROOT_PORT_NODE {
> >
> > +  //
> >
> > +  // Signature header
> >
> > +  //
> >
> > +  UINT32                                    Signature;
> >
> > +  //
> >
> > +  // linked list pointers to next node
> >
> > +  //
> >
> > +  LIST_ENTRY                                NeighborRootPort;
> >
> > +  //
> >
> > +  // EFI handle of the parent Root Bridge instance
> >
> > +  //
> >
> > +  EFI_HANDLE                                RootBridgeHandle;
> >
> > +  //
> >
> > +  // EFI handle of the PCI controller
> >
> > +  //
> >
> > +  EFI_HANDLE                                RootPortHandle;
> >
> > +  //
> >
> > +  // PCI Secondary bus value of the PCI controller
> >
> > +  //
> >
> > +  UINT8                                     SecondaryBusStart;
> >
> > +  //
> >
> > +  // PCI Subordinate bus value of the PCI controller
> >
> > +  //
> >
> > +  UINT8                                     SecondaryBusEnd;
> >
> > +  //
> >
> > +  // pointer to the corresponding PCI feature configuration Table node
> >
> > +  //
> >
> > +  OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > *OtherPciFeaturesConfigurationTable;
> >
> > +};
> >
> > +
> >
> > +#define PRIMARY_ROOT_PORT_NODE_FROM_LINK(a) \
> >
> > +  CR (a, PRIMARY_ROOT_PORT_NODE, NeighborRootPort,
> > PCI_ROOT_PORT_SIGNATURE)
> >
> > +
> >
> > +//
> >
> > +// Definition of the PCI Feature configuration Table members
> >
> > +//
> >
> > +struct _OTHER_PCI_FEATURES_CONFIGURATION_TABLE {
> >
> > +  //
> >
> > +  // Configuration Table ID
> >
> > +  //
> >
> > +  UINTN                                     ID;
> >
> > +  //
> >
> > +  // to configure the PCI feature Maximum payload size to maintain the
> data
> > packet
> >
> > +  // size among all the PCI devices in the PCI hierarchy
> >
> > +  //
> >
> > +  UINT8                                     Max_Payload_Size;
> >
> > +  //
> >
> > +  // to configure the PCI feature maximum read request size to maintain
> the
> > memory
> >
> > +  // requester size among all the PCI devices in the PCI hierarchy
> >
> > +  //
> >
> > +  UINT8                                     Max_Read_Request_Size;
> >
> > +  //
> >
> > +  // lock the Max_Read_Request_Size for the entire PCI tree of a root port
> >
> > +  //
> >
> > +  BOOLEAN                                   Lock_Max_Read_Request_Size;
> >
> > +};
> >
> > +
> >
> > +
> >
> > +//
> >
> > +// PCI feature configuration node signature value
> >
> > +//
> >
> > +#define PCI_FEATURE_CONFIGURATION_SIGNATURE
> > SIGNATURE_32 ('p', 'c', 'i', 'f')
> >
> > +
> >
> > +struct _PCI_FEATURE_CONFIGURATION_COMPLETION_LIST {
> >
> > +  //
> >
> > +  // Signature header
> >
> > +  //
> >
> > +  UINT32                                    Signature;
> >
> > +  //
> >
> > +  // link to next Root Bridge whose PCI Feature configuration is complete
> >
> > +  //
> >
> > +  LIST_ENTRY                                RootBridgeLink;
> >
> > +  //
> >
> > +  // EFI handle of the Root Bridge whose PCI feature configuration is
> > complete
> >
> > +  //
> >
> > +  EFI_HANDLE                                RootBridgeHandle;
> >
> > +  //
> >
> > +  // indication for complete re-enumeration of the PCI feature
> configuration
> >
> > +  //
> >
> > +  BOOLEAN                                   ReEnumeratePciFeatureConfiguration;
> >
> > +};
> >
> > +
> >
> > +#define
> > PCI_FEATURE_CONFIGURATION_COMPLETION_LIST_FROM_LINK(a) \
> >
> > +  CR (a, PCI_FEATURE_CONFIGURATION_COMPLETION_LIST,
> > RootBridgeLink, PCI_FEATURE_CONFIGURATION_SIGNATURE)
> >
> > +
> >
> > +//
> >
> > +// Declaration of the internal sub-phases within the PCI Feature
> > enumeration
> >
> > +//
> >
> > +typedef enum {
> >
> > +  //
> >
> > +  // initial phase in configuring the other PCI features to record the primary
> >
> > +  // root ports
> >
> > +  //
> >
> > +  PciFeatureRootBridgeScan,
> >
> > +  //
> >
> > +  // get the PCI device-specific platform policies and align with device
> > capabilities
> >
> > +  //
> >
> > +  PciFeatureGetDevicePolicy,
> >
> > +  //
> >
> > +  // align all PCI nodes in the PCI heirarchical tree
> >
> > +  //
> >
> > +  PciFeatureSetupPhase,
> >
> > +  //
> >
> > +  // finally override to complete configuration of the PCI feature
> >
> > +  //
> >
> > +  PciFeatureConfigurationPhase,
> >
> > +  //
> >
> > +  // PCI feature configuration complete
> >
> > +  //
> >
> > +  PciFeatureConfigurationComplete
> >
> > +
> >
> > +}PCI_FEATURE_CONFIGURATION_PHASE;
> >
> > +
> >
> > +/**
> >
> > +  Main routine to indicate platform selection of any of the other PCI
> features
> >
> > +  to be configured by this driver
> >
> > +
> >
> > +  @retval TRUE    platform has selected the other PCI features to be
> > configured
> >
> > +          FALSE   platform has not selected any of the other PCI features
> >
> > +**/
> >
> > +BOOLEAN
> >
> > +CheckOtherPciFeaturesPcd (
> >
> > +  );
> >
> > +
> >
> > +/**
> >
> > +  Enumerate all the nodes of the specified root bridge or PCI-PCI Bridge, to
> >
> > +  configure the other PCI features.
> >
> > +
> >
> > +  @param RootBridge          A pointer to the PCI_IO_DEVICE.
> >
> > +
> >
> > +  @retval EFI_SUCCESS           The other PCI features configuration during
> > enumeration
> >
> > +                                of all the nodes of the PCI root bridge instance were
> >
> > +                                programmed in PCI-compliance pattern along with the
> >
> > +                                device-specific policy, as applicable.
> >
> > +  @retval EFI_UNSUPPORTED       One of the override operation maong the
> > nodes of
> >
> > +                                the PCI hierarchy resulted in a incompatible address
> >
> > +                                range.
> >
> > +  @retval EFI_INVALID_PARAMETER The override operation is performed
> > with invalid input
> >
> > +                                parameters.
> >
> > +**/
> >
> > +EFI_STATUS
> >
> > +EnumerateOtherPciFeatures (
> >
> > +  IN PCI_IO_DEVICE           *RootBridge
> >
> > +  );
> >
> > +
> >
> > +/**
> >
> > +  This routine is invoked from the Stop () interface for the EFI handle of
> the
> >
> > +  RootBridge. Free up its node of type
> > PCI_FEATURE_CONFIGURATION_COMPLETION_LIST.
> >
> > +
> >
> > +  @param  RootBridge      A pointer to the PCI_IO_DEVICE
> >
> > +**/
> >
> > +VOID
> >
> > +DestroyRootBridgePciFeaturesConfigCompletionList (
> >
> > +  IN PCI_IO_DEVICE          *RootBridge
> >
> > +  );
> >
> > +#endif
> >
> > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> > new file mode 100644
> > index 0000000000..d94037d69a
> > --- /dev/null
> > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> > @@ -0,0 +1,565 @@
> > +/** @file
> >
> > +  This file encapsulate the usage of PCI Platform Protocol
> >
> > +
> >
> > +  This file define the necessary hooks used to obtain the platform
> >
> > +  level data and policies which could be used in the PCI Enumeration
> phases
> >
> > +
> >
> > +Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> >
> > +SPDX-License-Identifier: BSD-2-Clause-Patent
> >
> > +
> >
> > +**/
> >
> > +
> >
> > +#include "PciPlatformSupport.h"
> >
> > +
> >
> > +EFI_PCI_PLATFORM_PROTOCOL                     *mPciPlatformProtocol;
> >
> > +EFI_PCI_OVERRIDE_PROTOCOL                     *mPciOverrideProtocol;
> >
> > +
> >
> > +EFI_PCI_PLATFORM_PROTOCOL2                    *mPciPlatformProtocol2;
> >
> > +EFI_PCI_OVERRIDE_PROTOCOL2                    *mPciOverrideProtocol2;
> >
> > +
> >
> > +
> >
> > +/**
> >
> > +  This function retrieves the PCI Platform Protocol published by platform
> > driver
> >
> > +
> >
> > +**/
> >
> > +VOID
> >
> > +GetPciPlatformProtocol (
> >
> > +  )
> >
> > +{
> >
> > +  mPciPlatformProtocol2 = NULL;
> >
> > +  gBS->LocateProtocol (
> >
> > +      &gEfiPciPlatformProtocol2Guid,
> >
> > +      NULL,
> >
> > +      (VOID **) &mPciPlatformProtocol2
> >
> > +  );
> >
> > +
> >
> > +  //
> >
> > +  // If PCI Platform protocol doesn't exist, try to get Pci Override Protocol.
> >
> > +  //
> >
> > +  if (mPciPlatformProtocol2 == NULL) {
> >
> > +    mPciOverrideProtocol2 = NULL;
> >
> > +    gBS->LocateProtocol (
> >
> > +        &gEfiPciOverrideProtocol2Guid,
> >
> > +        NULL,
> >
> > +        (VOID **) &mPciOverrideProtocol2
> >
> > +    );
> >
> > +  }
> >
> > +  //
> >
> > +  // fetch the old PCI Platform Protocols if new are not installed
> >
> > +  //
> >
> > +  if (mPciOverrideProtocol2 == NULL) {
> >
> > +
> >
> > +    mPciPlatformProtocol = NULL;
> >
> > +    gBS->LocateProtocol (
> >
> > +        &gEfiPciPlatformProtocolGuid,
> >
> > +        NULL,
> >
> > +        (VOID **) &mPciPlatformProtocol
> >
> > +    );
> >
> > +
> >
> > +    //
> >
> > +    // If PCI Platform protocol doesn't exist, try to  get Pci Override Protocol.
> >
> > +    //
> >
> > +    if (mPciPlatformProtocol == NULL) {
> >
> > +      mPciOverrideProtocol = NULL;
> >
> > +      gBS->LocateProtocol (
> >
> > +          &gEfiPciOverrideProtocolGuid,
> >
> > +          NULL,
> >
> > +          (VOID **) &mPciOverrideProtocol
> >
> > +      );
> >
> > +    }
> >
> > +  }
> >
> > +}
> >
> > +
> >
> > +/**
> >
> > +  This function indicates the presence of PCI Platform driver
> >
> > +  @retval     TRUE or FALSE
> >
> > +**/
> >
> > +BOOLEAN
> >
> > +CheckPciPlatformProtocolInstall (
> >
> > +  )
> >
> > +{
> >
> > +  if (mPciPlatformProtocol2 != NULL) {
> >
> > +    return TRUE;
> >
> > +  } else if (mPciOverrideProtocol2 != NULL) {
> >
> > +    return TRUE;
> >
> > +  } else {
> >
> > +    if (mPciPlatformProtocol != NULL) {
> >
> > +      return TRUE;
> >
> > +    } else if (mPciOverrideProtocol != NULL){
> >
> > +      return TRUE;
> >
> > +    }
> >
> > +  }
> >
> > +  return FALSE;
> >
> > +}
> >
> > +
> >
> > +/**
> >
> > +  Provides the hooks from the PCI bus driver to every PCI controller
> > (device/function) at various
> >
> > +  stages of the PCI enumeration process that allow the host bridge driver
> to
> > preinitialize individual
> >
> > +  PCI controllers before enumeration.
> >
> > +
> >
> > +  This function is called during the PCI enumeration process. No specific
> > action is expected from this
> >
> > +  member function. It allows the host bridge driver to preinitialize
> individual
> > PCI controllers before
> >
> > +  enumeration.
> >
> > +
> >
> > +  @param[in] HostBridgeHandle     The associated PCI host bridge handle.
> >
> > +  @param[in] RootBridgeHandle     The associated PCI root bridge handle.
> >
> > +  @param[in] RootBridgePciAddress The address of the PCI device on the
> > PCI bus.
> >
> > +  @param[in] Phase          The phase of the PCI controller enumeration.
> >
> > +  @param[in] ExecPhase      Defines the execution phase of the PCI chipset
> > driver.
> >
> > +
> >
> > +  @retval    Status         returns the status from the PCI Platform protocol as
> is
> >
> > +
> >
> > +**/
> >
> > +EFI_STATUS
> >
> > +PciPlatformPreprocessController (
> >
> > +  IN EFI_HANDLE                                    HostBridgeHandle,
> >
> > +  IN EFI_HANDLE                                    RootBridgeHandle,
> >
> > +  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS
> > RootBridgePciAddress,
> >
> > +  IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE  Phase,
> >
> > +  IN EFI_PCI_EXECUTION_PHASE                       ExecPhase
> >
> > +  )
> >
> > +{
> >
> > +  EFI_STATUS  Status;
> >
> > +
> >
> > +  if (mPciPlatformProtocol2 != NULL) {
> >
> > +    //
> >
> > +    // Call PlatformPci::PrepController() if the protocol is present.
> >
> > +    //
> >
> > +    Status = mPciPlatformProtocol2->PlatformPrepController (
> >
> > +
> > (EFI_PCI_PLATFORM_PROTOCOL*)mPciPlatformProtocol2,
> >
> > +                                      HostBridgeHandle,
> >
> > +                                      RootBridgeHandle,
> >
> > +                                      RootBridgePciAddress,
> >
> > +                                      Phase,
> >
> > +                                      ExecPhase
> >
> > +                                    );
> >
> > +  } else if (mPciOverrideProtocol2 != NULL) {
> >
> > +    //
> >
> > +    // Call PlatformPci::PrepController() if the protocol is present.
> >
> > +    //
> >
> > +    Status = mPciOverrideProtocol2->PlatformPrepController (
> >
> > +
> > (EFI_PCI_PLATFORM_PROTOCOL*)mPciOverrideProtocol2,
> >
> > +                                      HostBridgeHandle,
> >
> > +                                      RootBridgeHandle,
> >
> > +                                      RootBridgePciAddress,
> >
> > +                                      Phase,
> >
> > +                                      ExecPhase
> >
> > +                                    );
> >
> > +  } else {
> >
> > +    if (mPciPlatformProtocol != NULL) {
> >
> > +      //
> >
> > +      // Call PlatformPci::PrepController() if the protocol is present.
> >
> > +      //
> >
> > +      Status = mPciPlatformProtocol->PlatformPrepController (
> >
> > +                                      mPciPlatformProtocol,
> >
> > +                                      HostBridgeHandle,
> >
> > +                                      RootBridgeHandle,
> >
> > +                                      RootBridgePciAddress,
> >
> > +                                      Phase,
> >
> > +                                      ExecPhase
> >
> > +                                    );
> >
> > +    } else if (mPciOverrideProtocol != NULL) {
> >
> > +      //
> >
> > +      // Call PlatformPci::PrepController() if the protocol is present.
> >
> > +      //
> >
> > +      Status = mPciOverrideProtocol->PlatformPrepController (
> >
> > +                                      mPciOverrideProtocol,
> >
> > +                                      HostBridgeHandle,
> >
> > +                                      RootBridgeHandle,
> >
> > +                                      RootBridgePciAddress,
> >
> > +                                      Phase,
> >
> > +                                      ExecPhase
> >
> > +                                    );
> >
> > +    } else {
> >
> > +      //
> >
> > +      // return PCI Platform Protocol not found
> >
> > +      //
> >
> > +      return EFI_NOT_FOUND;
> >
> > +    }
> >
> > +  }
> >
> > +  return Status;
> >
> > +}
> >
> > +
> >
> > +/**
> >
> > +  This function notifies the PCI Platform driver about the PCI host bridge
> > resource
> >
> > +  allocation phase and PCI execution phase.
> >
> > +
> >
> > +  @param[in]  HostBridge     The handle of the host bridge controller.
> >
> > +  @param[in]  Phase          The phase of the PCI bus enumeration.
> >
> > +  @param[in]  ExecPhase      Defines the execution phase of the PCI
> chipset
> > driver.
> >
> > +  @retval     Status          returns the status from the PCI Platform protocol
> as
> > is
> >
> > +
> >
> > +**/
> >
> > +EFI_STATUS
> >
> > +PciPlatformNotifyPhase (
> >
> > +  IN  EFI_HANDLE                                      HostBridgeHandle,
> >
> > +  IN  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE   Phase,
> >
> > +  IN  EFI_PCI_EXECUTION_PHASE                         ExecPhase
> >
> > +  )
> >
> > +{
> >
> > +  EFI_STATUS  Status;
> >
> > +
> >
> > +  if ( mPciPlatformProtocol2 != NULL) {
> >
> > +    Status = mPciPlatformProtocol2->PlatformNotify (
> >
> > +
> > (EFI_PCI_PLATFORM_PROTOCOL*)mPciPlatformProtocol2,
> >
> > +                                      HostBridgeHandle,
> >
> > +                                      Phase,
> >
> > +                                      ExecPhase
> >
> > +                                    );
> >
> > +  } else if ( mPciOverrideProtocol2 != NULL) {
> >
> > +    Status = mPciOverrideProtocol2->PlatformNotify (
> >
> > +
> > (EFI_PCI_PLATFORM_PROTOCOL*)mPciOverrideProtocol2,
> >
> > +                                      HostBridgeHandle,
> >
> > +                                      Phase,
> >
> > +                                      ExecPhase
> >
> > +                                    );
> >
> > +  } else {
> >
> > +
> >
> > +    if ( mPciPlatformProtocol != NULL) {
> >
> > +      Status = mPciPlatformProtocol->PlatformNotify (
> >
> > +                                      mPciPlatformProtocol,
> >
> > +                                      HostBridgeHandle,
> >
> > +                                      Phase,
> >
> > +                                      ExecPhase
> >
> > +                                    );
> >
> > +    } else if ( mPciOverrideProtocol != NULL){
> >
> > +      Status = mPciOverrideProtocol->PlatformNotify (
> >
> > +                                      mPciOverrideProtocol,
> >
> > +                                      HostBridgeHandle,
> >
> > +                                      Phase,
> >
> > +                                      ExecPhase
> >
> > +                                    );
> >
> > +    } else {
> >
> > +      //
> >
> > +      // return PCI Platform Protocol not found
> >
> > +      //
> >
> > +      return EFI_NOT_FOUND;
> >
> > +    }
> >
> > +  }
> >
> > +  return Status;
> >
> > +}
> >
> > +
> >
> > +/**
> >
> > +  This function retrieves the PCI platform policy.
> >
> > +
> >
> > +  @param  PciPolicy     pointer to the legacy EFI_PCI_PLATFORM_POLICY
> >
> > +  @retval Status        returns the status from the PCI Platform protocol as is
> >
> > +
> >
> > +**/
> >
> > +EFI_STATUS
> >
> > +PciGetPlatformPolicy (
> >
> > +  OUT EFI_PCI_PLATFORM_POLICY *PciPolicy
> >
> > +  )
> >
> > +{
> >
> > +  EFI_STATUS  Status;
> >
> > +
> >
> > +  if ( mPciPlatformProtocol2 != NULL) {
> >
> > +      Status = mPciPlatformProtocol2->GetPlatformPolicy (
> >
> > +
> > (EFI_PCI_PLATFORM_PROTOCOL*)mPciPlatformProtocol2,
> >
> > +                                        PciPolicy
> >
> > +                                      );
> >
> > +  } else if ( mPciOverrideProtocol2 != NULL) {
> >
> > +      Status = mPciOverrideProtocol2->GetPlatformPolicy (
> >
> > +
> > (EFI_PCI_PLATFORM_PROTOCOL*)mPciOverrideProtocol2,
> >
> > +                                        PciPolicy
> >
> > +                                      );
> >
> > +  } else {
> >
> > +    if ( mPciPlatformProtocol != NULL) {
> >
> > +      Status = mPciPlatformProtocol->GetPlatformPolicy (
> >
> > +                                      mPciPlatformProtocol,
> >
> > +                                      PciPolicy
> >
> > +                                    );
> >
> > +    }
> >
> > +
> >
> > +    if ( mPciOverrideProtocol != NULL) {
> >
> > +      Status = mPciOverrideProtocol->GetPlatformPolicy (
> >
> > +                                      mPciOverrideProtocol,
> >
> > +                                      PciPolicy
> >
> > +                                    );
> >
> > +    } else {
> >
> > +      //
> >
> > +      // return PCI Platform Protocol not found
> >
> > +      //
> >
> > +      return EFI_NOT_FOUND;
> >
> > +    }
> >
> > +  }
> >
> > +  return Status;
> >
> > +}
> >
> > +
> >
> > +/**
> >
> > +  This function retrieves the Option ROM image and size from the Platform.
> >
> > +
> >
> > +  It uses the PCI_IO_DEVICE internal fields are used to store OpROM
> > image/size
> >
> > +
> >
> > +  @param Controller     An EFI handle for the PCI bus controller.
> >
> > +  @param PciIoDevice    A PCI_IO_DEVICE pointer to the PCI IO device to
> be
> > registered.
> >
> > +
> >
> > +  @retval EFI_SUCCESS            The option ROM was available for this device
> > and loaded into memory.
> >
> > +  @retval EFI_NOT_FOUND          No option ROM was available for this
> device.
> >
> > +  @retval EFI_OUT_OF_RESOURCES   No memory was available to load the
> > option ROM.
> >
> > +  @retval EFI_DEVICE_ERROR       An error occurred in obtaining the option
> > ROM.
> >
> > +
> >
> > +**/
> >
> > +EFI_STATUS
> >
> > +GetPlatformPciOptionRom (
> >
> > +  IN  EFI_HANDLE                    Controller,
> >
> > +  IN  PCI_IO_DEVICE                 *PciIoDevice
> >
> > +  )
> >
> > +{
> >
> > +  EFI_STATUS  Status;
> >
> > +  VOID        *PlatformOpRomBuffer;
> >
> > +  UINTN       PlatformOpRomSize;
> >
> > +
> >
> > +  if (mPciPlatformProtocol2 != NULL) {
> >
> > +    Status = mPciPlatformProtocol2->GetPciRom (
> >
> > +
> > (EFI_PCI_PLATFORM_PROTOCOL*)mPciPlatformProtocol2,
> >
> > +                                      PciIoDevice->Handle,
> >
> > +                                      &PlatformOpRomBuffer,
> >
> > +                                      &PlatformOpRomSize
> >
> > +                                      );
> >
> > +  } else if (mPciOverrideProtocol2 != NULL) {
> >
> > +    Status = mPciOverrideProtocol2->GetPciRom (
> >
> > +
> > (EFI_PCI_PLATFORM_PROTOCOL*)mPciOverrideProtocol2,
> >
> > +                                      PciIoDevice->Handle,
> >
> > +                                      &PlatformOpRomBuffer,
> >
> > +                                      &PlatformOpRomSize
> >
> > +                                      );
> >
> > +  } else {
> >
> > +    if (mPciPlatformProtocol != NULL) {
> >
> > +      Status = mPciPlatformProtocol->GetPciRom (
> >
> > +                                      mPciPlatformProtocol,
> >
> > +                                      PciIoDevice->Handle,
> >
> > +                                      &PlatformOpRomBuffer,
> >
> > +                                      &PlatformOpRomSize
> >
> > +                                      );
> >
> > +    } else if (mPciOverrideProtocol != NULL) {
> >
> > +      Status = mPciOverrideProtocol->GetPciRom (
> >
> > +                                        mPciOverrideProtocol,
> >
> > +                                        PciIoDevice->Handle,
> >
> > +                                        &PlatformOpRomBuffer,
> >
> > +                                        &PlatformOpRomSize
> >
> > +                                        );
> >
> > +    } else {
> >
> > +      //
> >
> > +      // return PCI Platform Protocol not found
> >
> > +      //
> >
> > +      return EFI_NOT_FOUND;
> >
> > +    }
> >
> > +  }
> >
> > +
> >
> > +  if (!EFI_ERROR (Status)) {
> >
> > +    PciIoDevice->EmbeddedRom    = FALSE;
> >
> > +    PciIoDevice->RomSize        = (UINT32)PlatformOpRomSize;
> >
> > +    PciIoDevice->PciIo.RomSize  = PlatformOpRomSize;
> >
> > +    PciIoDevice->PciIo.RomImage = PlatformOpRomBuffer;
> >
> > +  }
> >
> > +  return Status;
> >
> > +}
> >
> > +
> >
> > +/**
> >
> > +  Helper routine to indicate whether the given PCI device specific policy
> > value
> >
> > +  dictates to override the Max_Payload_Size to a particular value, or set as
> > per
> >
> > +  device capability.
> >
> > +
> >
> > +  @param  MPS     Input device-specific policy should be in terms of type
> >
> > +                  EFI_PCI_CONF_MAX_PAYLOAD_SIZE
> >
> > +
> >
> > +  @retval TRUE    Setup Max_Payload_Size as per device capability
> >
> > +          FALSE   override as per device-specific platform policy
> >
> > +**/
> >
> > +BOOLEAN
> >
> > +SetupMpsAsPerDeviceCapability (
> >
> > +  IN  UINT8                   MPS
> >
> > +)
> >
> > +{
> >
> > +  if ( MPS == EFI_PCI_CONF_MAX_PAYLOAD_SIZE_AUTO) {
> >
> > +    return TRUE;
> >
> > +  } else {
> >
> > +    return FALSE;
> >
> > +  }
> >
> > +}
> >
> > +
> >
> > +/**
> >
> > +  Helper routine to indicate whether the given PCI device specific policy
> > value
> >
> > +  dictates to override the Max_Read_Req_Size to a particular value, or set
> as
> > per
> >
> > +  device capability.
> >
> > +
> >
> > +  @param  MRRS    Input device-specific policy should be in terms of type
> >
> > +                  EFI_PCI_CONF_MAX_READ_REQ_SIZE
> >
> > +
> >
> > +  @retval TRUE    Setup Max_Read_Req_Size as per device capability
> >
> > +          FALSE   override as per device-specific platform policy
> >
> > +**/
> >
> > +BOOLEAN
> >
> > +SetupMrrsAsPerDeviceCapability (
> >
> > +  IN  UINT8                   MRRS
> >
> > +)
> >
> > +{
> >
> > +  if ( MRRS == EFI_PCI_CONF_MAX_READ_REQ_SIZE_AUTO) {
> >
> > +    return TRUE;
> >
> > +  } else {
> >
> > +    return FALSE;
> >
> > +  }
> >
> > +}
> >
> > +
> >
> > +/**
> >
> > +  Routine to translate the given device-specific platform policy from type
> >
> > +  EFI_PCI_CONF_MAX_PAYLOAD_SIZE to HW-specific value, as per PCI
> Base
> > Specification
> >
> > +  Revision 4.0; for the PCI feature Max_Payload_Size.
> >
> > +
> >
> > +  @param  MPS     Input device-specific policy should be in terms of type
> >
> > +                  EFI_PCI_CONF_MAX_PAYLOAD_SIZE
> >
> > +
> >
> > +  @retval         Range values for the Max_Payload_Size as defined in the
> PCI
> >
> > +                  Base Specification 4.0
> >
> > +**/
> >
> > +UINT8
> >
> > +TranslateMpsSetupValueToPci (
> >
> > +  IN  UINT8                   MPS
> >
> > +)
> >
> > +{
> >
> > +  switch (MPS) {
> >
> > +    case EFI_PCI_CONF_MAX_PAYLOAD_SIZE_128B:
> >
> > +      return PCIE_MAX_PAYLOAD_SIZE_128B;
> >
> > +    case EFI_PCI_CONF_MAX_PAYLOAD_SIZE_256B:
> >
> > +      return PCIE_MAX_PAYLOAD_SIZE_256B;
> >
> > +    case EFI_PCI_CONF_MAX_PAYLOAD_SIZE_512B:
> >
> > +      return PCIE_MAX_PAYLOAD_SIZE_512B;
> >
> > +    case EFI_PCI_CONF_MAX_PAYLOAD_SIZE_1024B:
> >
> > +      return PCIE_MAX_PAYLOAD_SIZE_1024B;
> >
> > +    case EFI_PCI_CONF_MAX_PAYLOAD_SIZE_2048B:
> >
> > +      return PCIE_MAX_PAYLOAD_SIZE_2048B;
> >
> > +    case EFI_PCI_CONF_MAX_PAYLOAD_SIZE_4096B:
> >
> > +      return PCIE_MAX_PAYLOAD_SIZE_4096B;
> >
> > +    default:
> >
> > +      return PCIE_MAX_PAYLOAD_SIZE_128B;
> >
> > +  }
> >
> > +}
> >
> > +
> >
> > +/**
> >
> > +  Routine to translate the given device-specific platform policy from type
> >
> > +  EFI_PCI_CONF_MAX_READ_REQ_SIZE to HW-specific value, as per PCI
> > Base Specification
> >
> > +  Revision 4.0; for the PCI feature Max_Read_Req_Size.
> >
> > +
> >
> > +  @param  MRRS    Input device-specific policy should be in terms of type
> >
> > +                  EFI_PCI_CONF_MAX_READ_REQ_SIZE
> >
> > +
> >
> > +  @retval         Range values for the Max_Read_Req_Size as defined in the
> > PCI
> >
> > +                  Base Specification 4.0
> >
> > +**/
> >
> > +UINT8
> >
> > +TranslateMrrsSetupValueToPci (
> >
> > +  IN  UINT8                   MRRS
> >
> > +)
> >
> > +{
> >
> > +  switch (MRRS) {
> >
> > +    case EFI_PCI_CONF_MAX_READ_REQ_SIZE_128B:
> >
> > +      return PCIE_MAX_READ_REQ_SIZE_128B;
> >
> > +    case EFI_PCI_CONF_MAX_READ_REQ_SIZE_256B:
> >
> > +      return PCIE_MAX_READ_REQ_SIZE_256B;
> >
> > +    case EFI_PCI_CONF_MAX_READ_REQ_SIZE_512B:
> >
> > +      return PCIE_MAX_READ_REQ_SIZE_512B;
> >
> > +    case EFI_PCI_CONF_MAX_READ_REQ_SIZE_1024B:
> >
> > +      return PCIE_MAX_READ_REQ_SIZE_1024B;
> >
> > +    case EFI_PCI_CONF_MAX_READ_REQ_SIZE_2048B:
> >
> > +      return PCIE_MAX_READ_REQ_SIZE_2048B;
> >
> > +    case EFI_PCI_CONF_MAX_READ_REQ_SIZE_4096B:
> >
> > +      return PCIE_MAX_READ_REQ_SIZE_4096B;
> >
> > +    default:
> >
> > +      return PCIE_MAX_READ_REQ_SIZE_128B;
> >
> > +  }
> >
> > +}
> >
> > +
> >
> > +/**
> >
> > +  Generic routine to setup the PCI features as per its predetermined
> > defaults.
> >
> > +**/
> >
> > +VOID
> >
> > +SetupDefaultsDevicePlatformPolicy (
> >
> > +  IN  PCI_IO_DEVICE               *PciDevice
> >
> > +  )
> >
> > +{
> >
> > +  PciDevice->SetupMPS = EFI_PCI_CONF_MAX_PAYLOAD_SIZE_AUTO;
> >
> > +  PciDevice->SetupMRRS = EFI_PCI_CONF_MAX_READ_REQ_SIZE_AUTO;
> >
> > +}
> >
> > +
> >
> > +/**
> >
> > +  Intermediate routine to either get the PCI device specific platform
> policies
> >
> > +  through the PCI Platform Protocol, or its alias the PCI Override Protocol.
> >
> > +
> >
> > +  @param  PciIoDevice         A pointer to PCI_IO_DEVICE
> >
> > +  @param  PciPlatformProtocol A pointer to
> > EFI_PCI_PLATFORM_PROTOCOL2
> >
> > +
> >
> > +  @retval EFI_STATUS          The direct status from the PCI Platform Protocol
> >
> > +  @retval EFI_SUCCESS         if on returning predetermined PCI features
> > defaults,
> >
> > +                              for the case when protocol returns as EFI_UNSUPPORTED
> >
> > +                              to indicate PCI device exist and it has no platform
> >
> > +                              policy defined.
> >
> > +**/
> >
> > +EFI_STATUS
> >
> > +GetPciDevicePlatformPolicyEx (
> >
> > +  IN  PCI_IO_DEVICE               *PciIoDevice,
> >
> > +  IN  EFI_PCI_PLATFORM_PROTOCOL2  *PciPlatformProtocol
> >
> > +  )
> >
> > +{
> >
> > +  EFI_PCI_PLATFORM_EXTENDED_POLICY  PciPlatformExtendedPolicy;
> >
> > +  EFI_STATUS                        Status;
> >
> > +
> >
> > +  ZeroMem ( &PciPlatformExtendedPolicy, sizeof
> > (EFI_PCI_PLATFORM_EXTENDED_POLICY));
> >
> > +  Status = PciPlatformProtocol->GetDevicePolicy (
> >
> > +                                  PciPlatformProtocol,
> >
> > +                                  PciIoDevice->Handle,
> >
> > +                                  &PciPlatformExtendedPolicy
> >
> > +                                  );
> >
> > +  //
> >
> > +  // platform chipset policies are returned for this PCI device
> >
> > +  //
> >
> > +  if (!EFI_ERROR(Status)) {
> >
> > +    PciIoDevice->SetupMPS = PciPlatformExtendedPolicy.DeviceCtlMPS;
> >
> > +    PciIoDevice->SetupMRRS = PciPlatformExtendedPolicy.DeviceCtlMRRS;
> >
> > +  }
> >
> > +  //
> >
> > +  // platform chipset policies are not provided for this PCI device
> >
> > +  //
> >
> > +  if (EFI_ERROR(Status) == EFI_UNSUPPORTED) {
> >
> > +    //
> >
> > +    // let the enumeration happen as per the PCI standard way
> >
> > +    //
> >
> > +    SetupDefaultsDevicePlatformPolicy ( PciIoDevice);
> >
> > +    return EFI_SUCCESS;
> >
> > +  }
> >
> > +
> >
> > +  return Status;
> >
> > +}
> >
> > +
> >
> > +/**
> >
> > +  Gets the PCI device-specific platform policy from the PCI Platform
> Protocol.
> >
> > +  If no PCI Platform protocol is published than setup the PCI feature to
> > predetermined
> >
> > +  defaults, in order to align all the PCI devices in the PCI hierarchy, as
> > applicable.
> >
> > +
> >
> > +  @param  PciDevice     A pointer to PCI_IO_DEVICE
> >
> > +
> >
> > +  @retval EFI_STATUS    The direct status from the PCI Platform Protocol
> >
> > +  @retval EFI_SUCCESS   On return of predetermined PCI features defaults,
> > for
> >
> > +                        the case when protocol returns as EFI_UNSUPPORTED to
> >
> > +                        indicate PCI device exist and it has no platform policy
> >
> > +                        defined. Also, on returns when no PCI Platform Protocol
> >
> > +                        exist.
> >
> > +**/
> >
> > +EFI_STATUS
> >
> > +GetPciDevicePlatformPolicy (
> >
> > +  IN PCI_IO_DEVICE          *PciDevice
> >
> > +  )
> >
> > +{
> >
> > +  if ( mPciPlatformProtocol2 != NULL) {
> >
> > +    return GetPciDevicePlatformPolicyEx ( PciDevice,
> mPciPlatformProtocol2);
> >
> > +  } else if (mPciOverrideProtocol2 != NULL) {
> >
> > +    return GetPciDevicePlatformPolicyEx ( PciDevice,
> mPciOverrideProtocol2);
> >
> > +  } else {
> >
> > +    //
> >
> > +    // new PCI Platform Protocol 2 is not installed; let the enumeration
> > happen
> >
> > +    // as per PCI standard way
> >
> > +    //
> >
> > +    SetupDefaultsDevicePlatformPolicy ( PciDevice);
> >
> > +    return EFI_SUCCESS;
> >
> > +  }
> >
> > +}
> >
> > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
> > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
> > new file mode 100644
> > index 0000000000..d54e46b950
> > --- /dev/null
> > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
> > @@ -0,0 +1,193 @@
> > +/** @file
> >
> > +  This file encapsulate the usage of PCI Platform Protocol
> >
> > +
> >
> > +  This file define the necessary hooks used to obtain the platform
> >
> > +  level data and policies which could be used in the PCI Enumeration
> phases
> >
> > +
> >
> > +Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> >
> > +SPDX-License-Identifier: BSD-2-Clause-Patent
> >
> > +
> >
> > +**/
> >
> > +
> >
> > +
> >
> > +#ifndef _EFI_PCI_PLATFORM_SUPPORT_H_
> >
> > +#define _EFI_PCI_PLATFORM_SUPPORT_H_
> >
> > +
> >
> > +#include "PciBus.h"
> >
> > +
> >
> > +/**
> >
> > +  This function retrieves the PCI Platform Protocol published by platform
> > driver
> >
> > +
> >
> > +**/
> >
> > +VOID
> >
> > +GetPciPlatformProtocol (
> >
> > +  );
> >
> > +
> >
> > +/**
> >
> > +  This function indicates the presence of PCI Platform driver
> >
> > +  @retval     TRUE or FALSE
> >
> > +**/
> >
> > +BOOLEAN
> >
> > +CheckPciPlatformProtocolInstall (
> >
> > +  );
> >
> > +
> >
> > +
> >
> > +/**
> >
> > +  Provides the hooks from the PCI bus driver to every PCI controller
> > (device/function) at various
> >
> > +  stages of the PCI enumeration process that allow the host bridge driver
> to
> > preinitialize individual
> >
> > +  PCI controllers before enumeration.
> >
> > +
> >
> > +  This function is called during the PCI enumeration process. No specific
> > action is expected from this
> >
> > +  member function. It allows the host bridge driver to preinitialize
> individual
> > PCI controllers before
> >
> > +  enumeration.
> >
> > +
> >
> > +  @param[in] HostBridgeHandle     The associated PCI host bridge handle.
> >
> > +  @param[in] RootBridgeHandle     The associated PCI root bridge handle.
> >
> > +  @param[in] RootBridgePciAddress The address of the PCI device on the
> > PCI bus.
> >
> > +  @param[in] Phase          The phase of the PCI controller enumeration.
> >
> > +  @param[in] ExecPhase      Defines the execution phase of the PCI chipset
> > driver.
> >
> > +
> >
> > +  @retval    Status         returns the status from the PCI Platform protocol as
> is
> >
> > +
> >
> > +**/
> >
> > +EFI_STATUS
> >
> > +PciPlatformPreprocessController (
> >
> > +  IN EFI_HANDLE                                    HostBridgeHandle,
> >
> > +  IN EFI_HANDLE                                    RootBridgeHandle,
> >
> > +  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS
> > RootBridgePciAddress,
> >
> > +  IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE  Phase,
> >
> > +  IN EFI_PCI_EXECUTION_PHASE                       ExecPhase
> >
> > +  );
> >
> > +
> >
> > +/**
> >
> > +  This function notifies the PCI Platform driver about the PCI host bridge
> > resource
> >
> > +  allocation phase and PCI execution phase.
> >
> > +
> >
> > +  @param[in]  HostBridge     The handle of the host bridge controller.
> >
> > +  @param[in]  Phase          The phase of the PCI bus enumeration.
> >
> > +  @param[in]  ExecPhase      Defines the execution phase of the PCI
> chipset
> > driver.
> >
> > +  @retval     Status          returns the status from the PCI Platform protocol
> as
> > is
> >
> > +
> >
> > +**/
> >
> > +EFI_STATUS
> >
> > +PciPlatformNotifyPhase (
> >
> > +  IN  EFI_HANDLE                                      HostBridgeHandle,
> >
> > +  IN  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE   Phase,
> >
> > +  IN  EFI_PCI_EXECUTION_PHASE                         ExecPhase
> >
> > +  );
> >
> > +
> >
> > +/**
> >
> > +  This function retrieves the PCI platform policy.
> >
> > +
> >
> > +  @param  PciPolicy     pointer to the legacy EFI_PCI_PLATFORM_POLICY
> >
> > +  @retval Status        returns the status from the PCI Platform protocol as is
> >
> > +
> >
> > +**/
> >
> > +EFI_STATUS
> >
> > +PciGetPlatformPolicy (
> >
> > +  OUT EFI_PCI_PLATFORM_POLICY *PciPolicy
> >
> > +  );
> >
> > +
> >
> > +/**
> >
> > +  This function retrieves the Option ROM image and size from the Platform.
> >
> > +
> >
> > +  It uses the PCI_IO_DEVICE internal fields are used to store OpROM
> > image/size
> >
> > +
> >
> > +  @param Controller     An EFI handle for the PCI bus controller.
> >
> > +  @param PciIoDevice    A PCI_IO_DEVICE pointer to the PCI IO device to
> be
> > registered.
> >
> > +
> >
> > +  @retval EFI_SUCCESS            The option ROM was available for this device
> > and loaded into memory.
> >
> > +  @retval EFI_NOT_FOUND          No option ROM was available for this
> device.
> >
> > +  @retval EFI_OUT_OF_RESOURCES   No memory was available to load the
> > option ROM.
> >
> > +  @retval EFI_DEVICE_ERROR       An error occurred in obtaining the option
> > ROM.
> >
> > +
> >
> > +**/
> >
> > +EFI_STATUS
> >
> > +GetPlatformPciOptionRom (
> >
> > +  IN  EFI_HANDLE                    Controller,
> >
> > +  IN  PCI_IO_DEVICE                 *PciIoDevice
> >
> > +  );
> >
> > +
> >
> > +/**
> >
> > +  Gets the PCI device-specific platform policy from the PCI Platform
> Protocol.
> >
> > +  If no PCI Platform protocol is published than setup the PCI feature to
> > predetermined
> >
> > +  defaults, in order to align all the PCI devices in the PCI hierarchy, as
> > applicable.
> >
> > +
> >
> > +  @param  PciDevice     A pointer to PCI_IO_DEVICE
> >
> > +
> >
> > +  @retval EFI_STATUS    The direct status from the PCI Platform Protocol
> >
> > +  @retval EFI_SUCCESS   On return of predetermined PCI features defaults,
> > for
> >
> > +                        the case when protocol returns as EFI_UNSUPPORTED to
> >
> > +                        indicate PCI device exist and it has no platform policy
> >
> > +                        defined. Also, on returns when no PCI Platform Protocol
> >
> > +                        exist.
> >
> > +**/
> >
> > +EFI_STATUS
> >
> > +GetPciDevicePlatformPolicy (
> >
> > +  IN PCI_IO_DEVICE          *PciDevice
> >
> > +  );
> >
> > +
> >
> > +/**
> >
> > +  Helper routine to indicate whether the given PCI device specific policy
> > value
> >
> > +  dictates to override the Max_Payload_Size to a particular value, or set as
> > per
> >
> > +  device capability.
> >
> > +
> >
> > +  @param  MPS     Input device-specific policy should be in terms of type
> >
> > +                  EFI_PCI_CONF_MAX_PAYLOAD_SIZE
> >
> > +
> >
> > +  @retval TRUE    Setup Max_Payload_Size as per device capability
> >
> > +          FALSE   override as per device-specific platform policy
> >
> > +**/
> >
> > +BOOLEAN
> >
> > +SetupMpsAsPerDeviceCapability (
> >
> > +  IN  UINT8                   MPS
> >
> > +);
> >
> > +
> >
> > +/**
> >
> > +  Helper routine to indicate whether the given PCI device specific policy
> > value
> >
> > +  dictates to override the Max_Read_Req_Size to a particular value, or set
> as
> > per
> >
> > +  device capability.
> >
> > +
> >
> > +  @param  MRRS    Input device-specific policy should be in terms of type
> >
> > +                  EFI_PCI_CONF_MAX_READ_REQ_SIZE
> >
> > +
> >
> > +  @retval TRUE    Setup Max_Read_Req_Size as per device capability
> >
> > +          FALSE   override as per device-specific platform policy
> >
> > +**/
> >
> > +BOOLEAN
> >
> > +SetupMrrsAsPerDeviceCapability (
> >
> > +  IN  UINT8                   MRRS
> >
> > +);
> >
> > +
> >
> > +/**
> >
> > +  Routine to translate the given device-specific platform policy from type
> >
> > +  EFI_PCI_CONF_MAX_PAYLOAD_SIZE to HW-specific value, as per PCI
> Base
> > Specification
> >
> > +  Revision 4.0; for the PCI feature Max_Payload_Size.
> >
> > +
> >
> > +  @param  MPS     Input device-specific policy should be in terms of type
> >
> > +                  EFI_PCI_CONF_MAX_PAYLOAD_SIZE
> >
> > +
> >
> > +  @retval         Range values for the Max_Payload_Size as defined in the
> PCI
> >
> > +                  Base Specification 4.0
> >
> > +**/
> >
> > +UINT8
> >
> > +TranslateMpsSetupValueToPci (
> >
> > +  IN  UINT8                   MPS
> >
> > +);
> >
> > +
> >
> > +/**
> >
> > +  Routine to translate the given device-specific platform policy from type
> >
> > +  EFI_PCI_CONF_MAX_READ_REQ_SIZE to HW-specific value, as per PCI
> > Base Specification
> >
> > +  Revision 4.0; for the PCI feature Max_Read_Req_Size.
> >
> > +
> >
> > +  @param  MRRS    Input device-specific policy should be in terms of type
> >
> > +                  EFI_PCI_CONF_MAX_READ_REQ_SIZE
> >
> > +
> >
> > +  @retval         Range values for the Max_Read_Req_Size as defined in the
> > PCI
> >
> > +                  Base Specification 4.0
> >
> > +**/
> >
> > +UINT8
> >
> > +TranslateMrrsSetupValueToPci (
> >
> > +  IN  UINT8                   MRRS
> >
> > +);
> >
> > +#endif
> >
> > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c
> > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c
> > index 4969ee0f64..755423f77b 100644
> > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c
> > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c
> > @@ -198,20 +198,7 @@ CalculateApertureIo16 (
> >      //
> >
> >      Status = EFI_NOT_FOUND;
> >
> >      PciPolicy = 0;
> >
> > -    if (gPciPlatformProtocol != NULL) {
> >
> > -      Status = gPciPlatformProtocol->GetPlatformPolicy (
> >
> > -                                       gPciPlatformProtocol,
> >
> > -                                       &PciPolicy
> >
> > -                                       );
> >
> > -    }
> >
> > -
> >
> > -    if (EFI_ERROR (Status) && gPciOverrideProtocol != NULL) {
> >
> > -      Status = gPciOverrideProtocol->GetPlatformPolicy (
> >
> > -                                       gPciOverrideProtocol,
> >
> > -                                       &PciPolicy
> >
> > -                                       );
> >
> > -    }
> >
> > -
> >
> > +    Status = PciGetPlatformPolicy ( &PciPolicy);
> >
> >      if (!EFI_ERROR (Status)) {
> >
> >        if ((PciPolicy & EFI_RESERVE_ISA_IO_ALIAS) != 0) {
> >
> >          mReserveIsaAliases = TRUE;
> >
> > diff --git a/MdeModulePkg/MdeModulePkg.dec
> > b/MdeModulePkg/MdeModulePkg.dec
> > index 17beb45235..7bcbe5a3ea 100644
> > --- a/MdeModulePkg/MdeModulePkg.dec
> > +++ b/MdeModulePkg/MdeModulePkg.dec
> > @@ -1026,6 +1026,16 @@
> >    # @Prompt Enable UEFI Stack Guard.
> >
> >
> >
> gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard|FALSE|BOOLEAN|0
> > x30001055
> >
> >
> >
> > +  ## This PCD is to indicate the PCI Bus driver to setup other new PCI
> > features.
> >
> > +  #  Each PCI feature is represented by its mask bit position and it
> configures
> >
> > +  #  if that bit is set.
> >
> > +  #
> >
> > +  #   Bit 0 - if set, the PCI Bus driver programs the device's
> > Max_Payload_Size.<BR>
> >
> > +  #   Bit 1 - if set, the PCI Bus driver programs the device's
> > Max_Read_Req_Size.<BR>
> >
> > +  #   Bit 2 to 31 - Reserved for future use by the PCI Bus driver.<BR>
> >
> > +  # @Prompt The UEFI PCU Bus driver enables the new set of other PCI
> > Features.
> >
> > +
> >
> gEfiMdeModulePkgTokenSpaceGuid.PcdOtherPciFeatures|0x00000003|UIN
> > T32|0x30001056
> >
> > +
> >
> >  [PcdsFixedAtBuild, PcdsPatchableInModule]
> >
> >    ## Dynamic type PCD can be registered callback function for Pcd setting
> > action.
> >
> >    #  PcdMaxPeiPcdCallBackNumberPerPcdEntry indicates the maximum
> > number of callback function
> >
> > --
> > 2.21.0.windows.1


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

View/Reply Online (#48888): https://edk2.groups.io/g/devel/message/48888
Mute This Topic: https://groups.io/mt/34264504/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub  [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-

Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH] PciBusDxe: New PCI features Max_Payload_Size, Max_Read_Req_Size
Posted by Javeed, Ashraf 4 years, 5 months ago
Ray,
Thanks for the review!
Please find my response inline below.

Regards
Ashraf

> -----Original Message-----
> From: Ni, Ray <ray.ni@intel.com>
> Sent: Monday, October 14, 2019 3:23 PM
> To: Javeed, Ashraf <ashraf.javeed@intel.com>; 'devel@edk2.groups.io'
> <devel@edk2.groups.io>
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>
> Subject: RE: [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH] PciBusDxe: New PCI
> features Max_Payload_Size, Max_Read_Req_Size
> 
> More comments:
> 1. IsPciRootPortEmpty(): can you just check whether PciDevice->ChildList is
> empty by using IsListEmpty (&PciDevice->ChildList)?
OK, will do the additional check.

> 2. Can you point to me which spec requires the MPS to be 128 for empty root
> ports?
Refer the PCI Express Base Specification Revision 5, chapter 7.5.3.4 Implementation Notes section.

> 3. GetPciRootPortBusAssigned() is dangerous because it assumes the input
> PciDevice points to the bridge.
Good catch! Will make the right change.

> 4. RecordPciRootPortBridges() could be simplified to just collect all PciDevice
> instances who:
>     a. belongs to the linked list of the root bridge
>     b. is a bridge
I can see if I can optimize further, but do note that I need to align the PCI feature Max_Payload_Size and Max_Read_Request_Size among all the child PCI devices of the Root Port (RP) in the Root Complex (RC) and since a single RC is known to have multiple RP I need to maintain the list of all the primary RP in the Root Bridge handle so that each primary RP can have its PCI configuration table to track the Max_Payload_Size and Max_Read_Request_Size that needs to be assigned to all its child PCI devices in the tree.

> 
> > -----Original Message-----
> > From: Ni, Ray
> > Sent: Monday, October 14, 2019 2:57 PM
> > To: Javeed, Ashraf <ashraf.javeed@intel.com>; devel@edk2.groups.io
> > Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>
> > Subject: RE: [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH] PciBusDxe: New
> > PCI features Max_Payload_Size, Max_Read_Req_Size
> >
> > Javeed,
> > The patch is too big.
> > I recommend you separate the patch to several small patches. The goal of
> > that is to make reviewers today (like me) and future easy to understand the
> > code changes.  Some potential changes that can be separated out:
> > 1. "DEBUG_ERROR/DEBUG_INFO"
> > 2. The change related to the PciPlatform/PciOverride invocation can also be
> > separated out and it can be in a patch before any changes to implement the
> > features.
OK, I can combine the above two in a single patch as the macros I got to change because the PatchCheck.py script reports out for the entire source file.

> > 3. The change that splits the original StartPciDevicesOnBridge() to
> > RegisterPciDevicesOnBridge() and StartPciRootPortsOnBridge(). This change
> > can be separated out as a patch before any changes to implement the
> > features.
OK, will do.

> >
> >
> > Some other comments:
> > 1. CheckPciPlatformProtocolInstall(): better to rename to
> > IsPciPlatformAvailable(). "Check" doesn't tell how to interpret the return
> > result. "Is" does.
OK, will do.

> > 2. GetPciPlatformProtocol(): better to rename to InitializePciPlatform ().
To me, the word "Initialize" would mean also installing the PCI Platform Protocol which is not the case with the PCI Bus driver; since it only fetches the existing protocol already installed by the platform...

> > 3. Why the type cast is needed in below code? If it is because PciPlatform2
> > protocol reuses the prototype of GetPciRom defined for PciPlatform protocol,
> > I suggest you define GetPciRom for PciPlatform2. Type redefinition seems a
> > duplication. But below type-cast is more annoyed.
> >
> >     Status = mPciPlatformProtocol2->GetPciRom (
> >
> (EFI_PCI_PLATFORM_PROTOCOL*)mPciPlatformProtocol2,
> >                                       PciIoDevice->Handle,
> >                                       &PlatformOpRomBuffer,
> >                                       &PlatformOpRomSize
> >                                       );
> >
Yes, the PciPlatform2.h which I had submitted to the edk2-staging branch previously; includes the PciPlatform.h during compilation. Even I was thinking the same and since the new definition of the PCI Platform Protocol has to used in future; I can port the legacy definitions into the new definition source file itself to avoid further change in future.

> > 4. Please run ECC tool and fix all coding style issue
I thought the ECC tool is used once the changes are submitted into the Gerritt by the maintainer; it is good if I can use it offline; please let me know where to get this tool.

> > 5. I don't quite understand what *primary* PCI root port is. So I don't quite
> > understand what RecordPciRootPortBridges() does.
I used the word primary for the PCI Root port to indicate the first level Root port in the RC of the host; there can be multiple first level PCI RP in the Root Bridge handle and each RP can have its downstream hierarchy which in turn can be the PCIe-PCIe/PCI/PCI-X bridge devices and its endpoint devices. Since the RP and its downstream PCI bridges both have the same PCI Type 1 PCI Configuration header, I have to maintain the list of first level RP of the Root Bridge handle.

> >
> > Thanks,
> > Ray
> >
> > > -----Original Message-----
> > > From: Javeed, Ashraf <ashraf.javeed@intel.com>
> > > Sent: Monday, September 23, 2019 10:21 PM
> > > To: devel@edk2.groups.io
> > > Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A
> > <hao.a.wu@intel.com>;
> > > Ni, Ray <ray.ni@intel.com>
> > > Subject: [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH] PciBusDxe: New PCI
> > > features Max_Payload_Size, Max_Read_Req_Size
> > >
> > > REF: https://bugzilla.tianocore.org/show_bug.cgi?id=2194
> > >
> > > The EDK2 Kernel PciBusDxe driver is enhanced to enable the configuration
> > > of PCI features like Max_Payload_Size and Max_Read_Req_Size.
> > >
> > > Max_Payload_Size:- The PCI Device Control register provides this feature
> > > register field which controls the maximum data packet (TLP) size that a
> > > PCI device should maintain as a requester. The PCI Bus driver is required
> > > to maintain a highest common value supported by all the PCI devices in a
> > > PCIe hierarchy, especially in case of isochronous applications.
> > >
> > > Max_Read_Req_Size:- The PCI Device Control register provides this
> > feature
> > > register field which controls the maximum memory read request size that a
> > > PCI device should maintain as a requester. The PCI Bus driver is required
> > > to maintain a common value, same as Max_Payload_Size, in case of
> > > isochronous applications only; or else, it should maintain the user
> > > requested value uniformly in a PCIe hierarchy (PCI root port and its
> > > downstream devices).
> > >
> > > The PCI Base Specification 4 Revision 1 contains detailed information
> > > about these features. The EDK2 PCI Bus driver needs to enable the
> > > configuration of these features as per the PCI Base specification.
> > >
> > > The EDK2 PCI Bus driver also needs to take the PCI device-specific
> > > platform policy into the consideration while programming these features;
> > > thus the code changes to support these, is explicitly dependent on the
> > > new PCI Platform Protocol interface definition defined in the below
> > > record:-
> > > https://bugzilla.tianocore.org/show_bug.cgi?id=1954
> > >
> > > Signed-off-by: Ashraf Javeed <ashraf.javeed@intel.com>
> > > Cc: Jian J Wang <jian.j.wang@intel.com>
> > > Cc: Hao A Wu <hao.a.wu@intel.com>
> > > Cc: Ray Ni <ray.ni@intel.com>
> > > ---
> > >  MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c               |   23 ++------------
> > >  MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h               |   14 ++++++++-
> > >  MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf          |    9 +++++-
> > >  MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c     |  229
> > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > ++++++++++++++++++++++++++++-----------------------------------------------
> > -
> > >  MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c        |  139
> > > ++++++++++++++++++++-----------------------------------------------------------
> > ---
> > >  MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c |   34
> > > ++++++++++++--------
> > >  MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c    | 1601
> > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > +++++++++
> > >  MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h    |  201
> > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > ++
> > >  MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c   |  565
> > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > +++++++++++++++++++++++++++++++++++++++++
> > >  MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h   |  193
> > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > +++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > >  MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c   |   15 +--------
> > >  MdeModulePkg/MdeModulePkg.dec                         |   10 ++++++
> > >  12 files changed, 2797 insertions(+), 236 deletions(-)
> > >
> > > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c
> > > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c
> > > index b020ce50ce..2503b298f4 100644
> > > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c
> > > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c
> > > @@ -8,7 +8,7 @@
> > >    PCI Root Bridges. So it means platform needs install PCI Root Bridge IO
> > > protocol for each
> > >
> > >    PCI Root Bus and install PCI Host Bridge Resource Allocation Protocol.
> > >
> > >
> > >
> > > -Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
> > >
> > > +Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
> > >
> > >  SPDX-License-Identifier: BSD-2-Clause-Patent
> > >
> > >
> > >
> > >  **/
> > >
> > > @@ -34,8 +34,6 @@ BOOLEAN                                       gFullEnumeration     =
> > TRUE;
> > >  UINT64                                        gAllOne              = 0xFFFFFFFFFFFFFFFFULL;
> > >
> > >  UINT64                                        gAllZero             = 0;
> > >
> > >
> > >
> > > -EFI_PCI_PLATFORM_PROTOCOL                     *gPciPlatformProtocol;
> > >
> > > -EFI_PCI_OVERRIDE_PROTOCOL                     *gPciOverrideProtocol;
> > >
> > >  EDKII_IOMMU_PROTOCOL                          *mIoMmuProtocol;
> > >
> > >
> > >
> > >
> > >
> > > @@ -266,24 +264,7 @@ PciBusDriverBindingStart (
> > >    // If PCI Platform protocol is available, get it now.
> > >
> > >    // If the platform implements this, it must be installed before BDS phase
> > >
> > >    //
> > >
> > > -  gPciPlatformProtocol = NULL;
> > >
> > > -  gBS->LocateProtocol (
> > >
> > > -        &gEfiPciPlatformProtocolGuid,
> > >
> > > -        NULL,
> > >
> > > -        (VOID **) &gPciPlatformProtocol
> > >
> > > -        );
> > >
> > > -
> > >
> > > -  //
> > >
> > > -  // If PCI Platform protocol doesn't exist, try to Pci Override Protocol.
> > >
> > > -  //
> > >
> > > -  if (gPciPlatformProtocol == NULL) {
> > >
> > > -    gPciOverrideProtocol = NULL;
> > >
> > > -    gBS->LocateProtocol (
> > >
> > > -          &gEfiPciOverrideProtocolGuid,
> > >
> > > -          NULL,
> > >
> > > -          (VOID **) &gPciOverrideProtocol
> > >
> > > -          );
> > >
> > > -  }
> > >
> > > +  GetPciPlatformProtocol ();
> > >
> > >
> > >
> > >    if (mIoMmuProtocol == NULL) {
> > >
> > >      gBS->LocateProtocol (
> > >
> > > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> > > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> > > index 504a1b1c12..7955bf8a26 100644
> > > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> > > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> > > @@ -27,6 +27,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
> > >  #include <Protocol/PciOverride.h>
> > >
> > >  #include <Protocol/PciEnumerationComplete.h>
> > >
> > >  #include <Protocol/IoMmu.h>
> > >
> > > +#include <Protocol/PciPlatform2.h>
> > >
> > > +#include <Protocol/PciOverride2.h>
> > >
> > >
> > >
> > >  #include <Library/DebugLib.h>
> > >
> > >  #include <Library/UefiDriverEntryPoint.h>
> > >
> > > @@ -79,6 +81,7 @@ typedef enum {
> > >  #include "PciPowerManagement.h"
> > >
> > >  #include "PciHotPlugSupport.h"
> > >
> > >  #include "PciLib.h"
> > >
> > > +#include "PciFeatureSupport.h"
> > >
> > >
> > >
> > >  #define VGABASE1  0x3B0
> > >
> > >  #define VGALIMIT1 0x3BB
> > >
> > > @@ -263,9 +266,13 @@ struct _PCI_IO_DEVICE {
> > >
> > >
> > >    BOOLEAN                                   IsPciExp;
> > >
> > >    //
> > >
> > > -  // For SR-IOV
> > >
> > > +  // For PCI Express Capability List Structure
> > >
> > >    //
> > >
> > >    UINT8                                     PciExpressCapabilityOffset;
> > >
> > > +  PCI_CAPABILITY_PCIEXP                     PciExpStruct;
> > >
> > > +  //
> > >
> > > +  // For SR-IOV
> > >
> > > +  //
> > >
> > >    UINT32                                    AriCapabilityOffset;
> > >
> > >    UINT32                                    SrIovCapabilityOffset;
> > >
> > >    UINT32                                    MrIovCapabilityOffset;
> > >
> > > @@ -279,6 +286,11 @@ struct _PCI_IO_DEVICE {
> > >    // This field is used to support this case.
> > >
> > >    //
> > >
> > >    UINT16                                    BridgeIoAlignment;
> > >
> > > +  //
> > >
> > > +  // Other PCI features setup flags
> > >
> > > +  //
> > >
> > > +  UINT8                                     SetupMPS;
> > >
> > > +  UINT8                                     SetupMRRS;
> > >
> > >  };
> > >
> > >
> > >
> > >  #define PCI_IO_DEVICE_FROM_PCI_IO_THIS(a) \
> > >
> > > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
> > > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
> > > index 05c22025b8..13768d7ded 100644
> > > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
> > > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
> > > @@ -2,7 +2,7 @@
> > >  #  The PCI bus driver will probe all PCI devices and allocate MMIO and IO
> > > space for these devices.
> > >
> > >  #  Please use PCD feature flag PcdPciBusHotplugDeviceSupport to enable
> > > hot plug supporting.
> > >
> > >  #
> > >
> > > -#  Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
> > >
> > > +#  Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
> > >
> > >  #
> > >
> > >  #  SPDX-License-Identifier: BSD-2-Clause-Patent
> > >
> > >  #
> > >
> > > @@ -57,6 +57,10 @@
> > >    PciCommand.h
> > >
> > >    PciIo.h
> > >
> > >    PciBus.h
> > >
> > > +  PciFeatureSupport.c
> > >
> > > +  PciFeatureSupport.h
> > >
> > > +  PciPlatformSupport.c
> > >
> > > +  PciPlatformSupport.h
> > >
> > >
> > >
> > >  [Packages]
> > >
> > >    MdePkg/MdePkg.dec
> > >
> > > @@ -91,6 +95,8 @@
> > >    gEfiLoadFile2ProtocolGuid                       ## SOMETIMES_PRODUCES
> > >
> > >    gEdkiiIoMmuProtocolGuid                         ## SOMETIMES_CONSUMES
> > >
> > >    gEfiLoadedImageDevicePathProtocolGuid           ## CONSUMES
> > >
> > > +  gEfiPciPlatformProtocol2Guid                     ## SOMETIMES_CONSUMES
> > >
> > > +  gEfiPciOverrideProtocol2Guid                     ## SOMETIMES_CONSUMES
> > >
> > >
> > >
> > >  [FeaturePcd]
> > >
> > >    gEfiMdeModulePkgTokenSpaceGuid.PcdPciBusHotplugDeviceSupport
> > ##
> > > CONSUMES
> > >
> > > @@ -104,6 +110,7 @@
> > >    gEfiMdeModulePkgTokenSpaceGuid.PcdAriSupport                  ##
> > CONSUMES
> > >
> > >    gEfiMdeModulePkgTokenSpaceGuid.PcdMrIovSupport                ##
> > > CONSUMES
> > >
> > >    gEfiMdeModulePkgTokenSpaceGuid.PcdPciDisableBusEnumeration    ##
> > > SOMETIMES_CONSUMES
> > >
> > > +  gEfiMdeModulePkgTokenSpaceGuid.PcdOtherPciFeatures                    ##
> > > CONSUMES
> > >
> > >
> > >
> > >  [UserExtensions.TianoCore."ExtraFiles"]
> > >
> > >    PciBusDxeExtra.uni
> > >
> > > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
> > > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
> > > index b7832c6970..0f76ab1cd5 100644
> > > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
> > > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
> > > @@ -170,6 +170,8 @@ DestroyRootBridgeByHandle (
> > >
> > >
> > >      if (Temp->Handle == Controller) {
> > >
> > >
> > >
> > > +      DestroyRootBridgePciFeaturesConfigCompletionList ( Temp);
> > >
> > > +
> > >
> > >        RemoveEntryList (CurrentLink);
> > >
> > >
> > >
> > >        DestroyPciDeviceTree (Temp);
> > >
> > > @@ -208,8 +210,6 @@ RegisterPciDevice (
> > >    )
> > >
> > >  {
> > >
> > >    EFI_STATUS          Status;
> > >
> > > -  VOID                *PlatformOpRomBuffer;
> > >
> > > -  UINTN               PlatformOpRomSize;
> > >
> > >    EFI_PCI_IO_PROTOCOL *PciIo;
> > >
> > >    UINT8               Data8;
> > >
> > >    BOOLEAN             HasEfiImage;
> > >
> > > @@ -244,49 +244,13 @@ RegisterPciDevice (
> > >      //
> > >
> > >      // Get the OpRom provided by platform
> > >
> > >      //
> > >
> > > -    if (gPciPlatformProtocol != NULL) {
> > >
> > > -      Status = gPciPlatformProtocol->GetPciRom (
> > >
> > > -                                       gPciPlatformProtocol,
> > >
> > > -                                       PciIoDevice->Handle,
> > >
> > > -                                       &PlatformOpRomBuffer,
> > >
> > > -                                       &PlatformOpRomSize
> > >
> > > -                                       );
> > >
> > > -      if (!EFI_ERROR (Status)) {
> > >
> > > -        PciIoDevice->EmbeddedRom    = FALSE;
> > >
> > > -        PciIoDevice->RomSize        = (UINT32) PlatformOpRomSize;
> > >
> > > -        PciIoDevice->PciIo.RomSize  = PlatformOpRomSize;
> > >
> > > -        PciIoDevice->PciIo.RomImage = PlatformOpRomBuffer;
> > >
> > > -        //
> > >
> > > -        // For OpROM read from gPciPlatformProtocol:
> > >
> > > -        // Add the Rom Image to internal database for later PCI light
> > > enumeration
> > >
> > > -        //
> > >
> > > -        PciRomAddImageMapping (
> > >
> > > -          NULL,
> > >
> > > -          PciIoDevice->PciRootBridgeIo->SegmentNumber,
> > >
> > > -          PciIoDevice->BusNumber,
> > >
> > > -          PciIoDevice->DeviceNumber,
> > >
> > > -          PciIoDevice->FunctionNumber,
> > >
> > > -          PciIoDevice->PciIo.RomImage,
> > >
> > > -          PciIoDevice->PciIo.RomSize
> > >
> > > -          );
> > >
> > > -      }
> > >
> > > -    } else if (gPciOverrideProtocol != NULL) {
> > >
> > > -      Status = gPciOverrideProtocol->GetPciRom (
> > >
> > > -                                       gPciOverrideProtocol,
> > >
> > > -                                       PciIoDevice->Handle,
> > >
> > > -                                       &PlatformOpRomBuffer,
> > >
> > > -                                       &PlatformOpRomSize
> > >
> > > -                                       );
> > >
> > > -      if (!EFI_ERROR (Status)) {
> > >
> > > -        PciIoDevice->EmbeddedRom    = FALSE;
> > >
> > > -        PciIoDevice->RomSize        = (UINT32) PlatformOpRomSize;
> > >
> > > -        PciIoDevice->PciIo.RomSize  = PlatformOpRomSize;
> > >
> > > -        PciIoDevice->PciIo.RomImage = PlatformOpRomBuffer;
> > >
> > > -        //
> > >
> > > -        // For OpROM read from gPciOverrideProtocol:
> > >
> > > -        // Add the Rom Image to internal database for later PCI light
> > > enumeration
> > >
> > > -        //
> > >
> > > -        PciRomAddImageMapping (
> > >
> > > +    Status = GetPlatformPciOptionRom ( Controller, PciIoDevice);
> > >
> > > +    if (!EFI_ERROR (Status)) {
> > >
> > > +      //
> > >
> > > +      // For OpROM read from the PCI Platform Protocol:
> > >
> > > +      // Add the Rom Image to internal database for later PCI light
> > > enumeration
> > >
> > > +      //
> > >
> > > +      PciRomAddImageMapping (
> > >
> > >            NULL,
> > >
> > >            PciIoDevice->PciRootBridgeIo->SegmentNumber,
> > >
> > >            PciIoDevice->BusNumber,
> > >
> > > @@ -294,8 +258,7 @@ RegisterPciDevice (
> > >            PciIoDevice->FunctionNumber,
> > >
> > >            PciIoDevice->PciIo.RomImage,
> > >
> > >            PciIoDevice->PciIo.RomSize
> > >
> > > -          );
> > >
> > > -      }
> > >
> > > +        );
> > >
> > >      }
> > >
> > >    }
> > >
> > >
> > >
> > > @@ -597,7 +560,7 @@ DeRegisterPciDevice (
> > >  }
> > >
> > >
> > >
> > >  /**
> > >
> > > -  Start to manage the PCI device on the specified root bridge or PCI-PCI
> > > Bridge.
> > >
> > > +  Start the PCI root Ports or PCI-PCI Bridge only.
> > >
> > >
> > >
> > >    @param Controller          The root bridge handle.
> > >
> > >    @param RootBridge          A pointer to the PCI_IO_DEVICE.
> > >
> > > @@ -612,7 +575,82 @@ DeRegisterPciDevice (
> > >
> > >
> > >  **/
> > >
> > >  EFI_STATUS
> > >
> > > -StartPciDevicesOnBridge (
> > >
> > > +StartPciRootPortsOnBridge (
> > >
> > > +  IN EFI_HANDLE                          Controller,
> > >
> > > +  IN PCI_IO_DEVICE                       *RootBridge
> > >
> > > +  )
> > >
> > > +
> > >
> > > +{
> > >
> > > +  PCI_IO_DEVICE             *PciIoDevice;
> > >
> > > +  EFI_STATUS                Status;
> > >
> > > +  LIST_ENTRY                *CurrentLink;
> > >
> > > +  UINT64                    Supports;
> > >
> > > +
> > >
> > > +  PciIoDevice = NULL;
> > >
> > > +  CurrentLink = RootBridge->ChildList.ForwardLink;
> > >
> > > +
> > >
> > > +  while (CurrentLink != NULL && CurrentLink != &RootBridge->ChildList) {
> > >
> > > +
> > >
> > > +    PciIoDevice = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
> > >
> > > +
> > >
> > > +    //
> > >
> > > +    // check if the device has been assigned with required resource
> > >
> > > +    // and registered
> > >
> > > +    //
> > >
> > > +    if (!PciIoDevice->Registered && !PciIoDevice->Allocated) {
> > >
> > > +      return EFI_NOT_READY;
> > >
> > > +    }
> > >
> > > +
> > >
> > > +    if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {
> > >
> > > +      Status = StartPciRootPortsOnBridge (
> > >
> > > +                 Controller,
> > >
> > > +                 PciIoDevice
> > >
> > > +                 );
> > >
> > > +
> > >
> > > +      PciIoDevice->PciIo.Attributes (
> > >
> > > +                           &(PciIoDevice->PciIo),
> > >
> > > +                           EfiPciIoAttributeOperationSupported,
> > >
> > > +                           0,
> > >
> > > +                           &Supports
> > >
> > > +                         );
> > >
> > > +      Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;
> > >
> > > +      PciIoDevice->PciIo.Attributes (
> > >
> > > +                           &(PciIoDevice->PciIo),
> > >
> > > +                           EfiPciIoAttributeOperationEnable,
> > >
> > > +                           Supports,
> > >
> > > +                           NULL
> > >
> > > +                         );
> > >
> > > +
> > >
> > > +    }
> > >
> > > +
> > >
> > > +    CurrentLink = CurrentLink->ForwardLink;
> > >
> > > +  }
> > >
> > > +
> > >
> > > +  if (PciIoDevice == NULL) {
> > >
> > > +    return EFI_NOT_FOUND;
> > >
> > > +  } else {
> > >
> > > +    return EFI_SUCCESS;
> > >
> > > +  }
> > >
> > > +}
> > >
> > > +
> > >
> > > +
> > >
> > > +/**
> > >
> > > +  Register to manage the PCI device on the specified root bridge or PCI-PCI
> > > Bridge.
> > >
> > > +
> > >
> > > +  @param Controller          The root bridge handle.
> > >
> > > +  @param RootBridge          A pointer to the PCI_IO_DEVICE.
> > >
> > > +  @param RemainingDevicePath A pointer to the
> > > EFI_DEVICE_PATH_PROTOCOL.
> > >
> > > +  @param NumberOfChildren    Children number.
> > >
> > > +  @param ChildHandleBuffer   A pointer to the child handle buffer.
> > >
> > > +
> > >
> > > +  @retval EFI_NOT_READY   Device is not allocated.
> > >
> > > +  @retval EFI_UNSUPPORTED Device only support PCI-PCI bridge.
> > >
> > > +  @retval EFI_NOT_FOUND   Can not find the specific device.
> > >
> > > +  @retval EFI_SUCCESS     Success to start Pci devices on bridge.
> > >
> > > +
> > >
> > > +**/
> > >
> > > +EFI_STATUS
> > >
> > > +RegisterPciDevicesOnBridge (
> > >
> > >    IN EFI_HANDLE                          Controller,
> > >
> > >    IN PCI_IO_DEVICE                       *RootBridge,
> > >
> > >    IN EFI_DEVICE_PATH_PROTOCOL            *RemainingDevicePath,
> > >
> > > @@ -626,7 +664,6 @@ StartPciDevicesOnBridge (
> > >    EFI_DEVICE_PATH_PROTOCOL  *CurrentDevicePath;
> > >
> > >    EFI_STATUS                Status;
> > >
> > >    LIST_ENTRY                *CurrentLink;
> > >
> > > -  UINT64                    Supports;
> > >
> > >
> > >
> > >    PciIoDevice = NULL;
> > >
> > >    CurrentLink = RootBridge->ChildList.ForwardLink;
> > >
> > > @@ -681,7 +718,7 @@ StartPciDevicesOnBridge (
> > >        // If it is a PPB
> > >
> > >        //
> > >
> > >        if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {
> > >
> > > -        Status = StartPciDevicesOnBridge (
> > >
> > > +        Status = RegisterPciDevicesOnBridge (
> > >
> > >                     Controller,
> > >
> > >                     PciIoDevice,
> > >
> > >                     CurrentDevicePath,
> > >
> > > @@ -689,20 +726,6 @@ StartPciDevicesOnBridge (
> > >                     ChildHandleBuffer
> > >
> > >                     );
> > >
> > >
> > >
> > > -        PciIoDevice->PciIo.Attributes (
> > >
> > > -                             &(PciIoDevice->PciIo),
> > >
> > > -                             EfiPciIoAttributeOperationSupported,
> > >
> > > -                             0,
> > >
> > > -                             &Supports
> > >
> > > -                             );
> > >
> > > -        Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;
> > >
> > > -        PciIoDevice->PciIo.Attributes (
> > >
> > > -                             &(PciIoDevice->PciIo),
> > >
> > > -                             EfiPciIoAttributeOperationEnable,
> > >
> > > -                             Supports,
> > >
> > > -                             NULL
> > >
> > > -                             );
> > >
> > > -
> > >
> > >          return Status;
> > >
> > >        } else {
> > >
> > >
> > >
> > > @@ -733,28 +756,13 @@ StartPciDevicesOnBridge (
> > >        }
> > >
> > >
> > >
> > >        if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {
> > >
> > > -        Status = StartPciDevicesOnBridge (
> > >
> > > +        Status = RegisterPciDevicesOnBridge (
> > >
> > >                     Controller,
> > >
> > >                     PciIoDevice,
> > >
> > >                     RemainingDevicePath,
> > >
> > >                     NumberOfChildren,
> > >
> > >                     ChildHandleBuffer
> > >
> > >                     );
> > >
> > > -
> > >
> > > -        PciIoDevice->PciIo.Attributes (
> > >
> > > -                             &(PciIoDevice->PciIo),
> > >
> > > -                             EfiPciIoAttributeOperationSupported,
> > >
> > > -                             0,
> > >
> > > -                             &Supports
> > >
> > > -                             );
> > >
> > > -        Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;
> > >
> > > -        PciIoDevice->PciIo.Attributes (
> > >
> > > -                             &(PciIoDevice->PciIo),
> > >
> > > -                             EfiPciIoAttributeOperationEnable,
> > >
> > > -                             Supports,
> > >
> > > -                             NULL
> > >
> > > -                             );
> > >
> > > -
> > >
> > >        }
> > >
> > >
> > >
> > >        CurrentLink = CurrentLink->ForwardLink;
> > >
> > > @@ -768,6 +776,65 @@ StartPciDevicesOnBridge (
> > >    }
> > >
> > >  }
> > >
> > >
> > >
> > > +/**
> > >
> > > +  Start to manage the PCI device on the specified root bridge or PCI-PCI
> > > Bridge.
> > >
> > > +
> > >
> > > +  @param Controller          The root bridge handle.
> > >
> > > +  @param RootBridge          A pointer to the PCI_IO_DEVICE.
> > >
> > > +  @param RemainingDevicePath A pointer to the
> > > EFI_DEVICE_PATH_PROTOCOL.
> > >
> > > +  @param NumberOfChildren    Children number.
> > >
> > > +  @param ChildHandleBuffer   A pointer to the child handle buffer.
> > >
> > > +
> > >
> > > +  @retval EFI_NOT_READY   Device is not allocated.
> > >
> > > +  @retval EFI_UNSUPPORTED Device only support PCI-PCI bridge.
> > >
> > > +  @retval EFI_NOT_FOUND   Can not find the specific device.
> > >
> > > +  @retval EFI_SUCCESS     Success to start Pci devices on bridge.
> > >
> > > +
> > >
> > > +**/
> > >
> > > +EFI_STATUS
> > >
> > > +StartPciDevicesOnBridge (
> > >
> > > +  IN EFI_HANDLE                          Controller,
> > >
> > > +  IN PCI_IO_DEVICE                       *RootBridge,
> > >
> > > +  IN EFI_DEVICE_PATH_PROTOCOL            *RemainingDevicePath,
> > >
> > > +  IN OUT UINT8                           *NumberOfChildren,
> > >
> > > +  IN OUT EFI_HANDLE                      *ChildHandleBuffer
> > >
> > > +  )
> > >
> > > +
> > >
> > > +{
> > >
> > > +  EFI_STATUS                Status;
> > >
> > > +
> > >
> > > +  //
> > >
> > > +  // first register all the PCI devices
> > >
> > > +  //
> > >
> > > +  Status = RegisterPciDevicesOnBridge (
> > >
> > > +             Controller,
> > >
> > > +             RootBridge,
> > >
> > > +             RemainingDevicePath,
> > >
> > > +             NumberOfChildren,
> > >
> > > +             ChildHandleBuffer
> > >
> > > +             );
> > >
> > > +
> > >
> > > +  if (EFI_ERROR (Status) == EFI_NOT_FOUND) {
> > >
> > > +    return Status;
> > >
> > > +  } else {
> > >
> > > +    if ( CheckOtherPciFeaturesPcd ()) {
> > >
> > > +      //
> > >
> > > +      // the late configuration of PCI features
> > >
> > > +      //
> > >
> > > +      Status = EnumerateOtherPciFeatures (
> > >
> > > +                  RootBridge
> > >
> > > +                );
> > >
> > > +    }
> > >
> > > +    //
> > >
> > > +    // finally start those PCI bridge port devices only
> > >
> > > +    //
> > >
> > > +    return StartPciRootPortsOnBridge (
> > >
> > > +            Controller,
> > >
> > > +            RootBridge
> > >
> > > +            );
> > >
> > > +  }
> > >
> > > +}
> > >
> > > +
> > >
> > >  /**
> > >
> > >    Start to manage all the PCI devices it found previously under
> > >
> > >    the entire host bridge.
> > >
> > > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c
> > > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c
> > > index 8db1ebf8ec..0a56668380 100644
> > > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c
> > > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c
> > > @@ -1003,7 +1003,7 @@ PciHostBridgeAdjustAllocation (
> > >      Status = RejectPciDevice (PciResNode->PciDev);
> > >
> > >      if (Status == EFI_SUCCESS) {
> > >
> > >        DEBUG ((
> > >
> > > -        EFI_D_ERROR,
> > >
> > > +        DEBUG_ERROR,
> > >
> > >          "PciBus: [%02x|%02x|%02x] was rejected due to resource
> > > confliction.\n",
> > >
> > >          PciResNode->PciDev->BusNumber, PciResNode->PciDev-
> > > >DeviceNumber, PciResNode->PciDev->FunctionNumber
> > >
> > >          ));
> > >
> > > @@ -1746,7 +1746,7 @@ NotifyPhase (
> > >
> > >
> > >    HostBridgeHandle  = NULL;
> > >
> > >    RootBridgeHandle  = NULL;
> > >
> > > -  if (gPciPlatformProtocol != NULL) {
> > >
> > > +  if ( CheckPciPlatformProtocolInstall()) {
> > >
> > >      //
> > >
> > >      // Get Host Bridge Handle.
> > >
> > >      //
> > >
> > > @@ -1770,42 +1770,11 @@ NotifyPhase (
> > >      //
> > >
> > >      // Call PlatformPci::PlatformNotify() if the protocol is present.
> > >
> > >      //
> > >
> > > -    gPciPlatformProtocol->PlatformNotify (
> > >
> > > -                            gPciPlatformProtocol,
> > >
> > > -                            HostBridgeHandle,
> > >
> > > -                            Phase,
> > >
> > > -                            ChipsetEntry
> > >
> > > -                            );
> > >
> > > -  } else if (gPciOverrideProtocol != NULL){
> > >
> > > -    //
> > >
> > > -    // Get Host Bridge Handle.
> > >
> > > -    //
> > >
> > > -    PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle);
> > >
> > > -
> > >
> > > -    //
> > >
> > > -    // Get the rootbridge Io protocol to find the host bridge handle
> > >
> > > -    //
> > >
> > > -    Status = gBS->HandleProtocol (
> > >
> > > -                    RootBridgeHandle,
> > >
> > > -                    &gEfiPciRootBridgeIoProtocolGuid,
> > >
> > > -                    (VOID **) &PciRootBridgeIo
> > >
> > > -                    );
> > >
> > > -
> > >
> > > -    if (EFI_ERROR (Status)) {
> > >
> > > -      return EFI_NOT_FOUND;
> > >
> > > -    }
> > >
> > > -
> > >
> > > -    HostBridgeHandle = PciRootBridgeIo->ParentHandle;
> > >
> > > -
> > >
> > > -    //
> > >
> > > -    // Call PlatformPci::PhaseNotify() if the protocol is present.
> > >
> > > -    //
> > >
> > > -    gPciOverrideProtocol->PlatformNotify (
> > >
> > > -                            gPciOverrideProtocol,
> > >
> > > -                            HostBridgeHandle,
> > >
> > > -                            Phase,
> > >
> > > -                            ChipsetEntry
> > >
> > > -                            );
> > >
> > > +    PciPlatformNotifyPhase (
> > >
> > > +        HostBridgeHandle,
> > >
> > > +        Phase,
> > >
> > > +        ChipsetEntry
> > >
> > > +        );
> > >
> > >    }
> > >
> > >
> > >
> > >    Status = PciResAlloc->NotifyPhase (
> > >
> > > @@ -1813,27 +1782,15 @@ NotifyPhase (
> > >                            Phase
> > >
> > >                            );
> > >
> > >
> > >
> > > -  if (gPciPlatformProtocol != NULL) {
> > >
> > > +  if ( CheckPciPlatformProtocolInstall()) {
> > >
> > >      //
> > >
> > >      // Call PlatformPci::PlatformNotify() if the protocol is present.
> > >
> > >      //
> > >
> > > -    gPciPlatformProtocol->PlatformNotify (
> > >
> > > -                            gPciPlatformProtocol,
> > >
> > > -                            HostBridgeHandle,
> > >
> > > -                            Phase,
> > >
> > > -                            ChipsetExit
> > >
> > > -                            );
> > >
> > > -
> > >
> > > -  } else if (gPciOverrideProtocol != NULL) {
> > >
> > > -    //
> > >
> > > -    // Call PlatformPci::PhaseNotify() if the protocol is present.
> > >
> > > -    //
> > >
> > > -    gPciOverrideProtocol->PlatformNotify (
> > >
> > > -                            gPciOverrideProtocol,
> > >
> > > -                            HostBridgeHandle,
> > >
> > > -                            Phase,
> > >
> > > -                            ChipsetExit
> > >
> > > -                            );
> > >
> > > +    PciPlatformNotifyPhase (
> > >
> > > +        HostBridgeHandle,
> > >
> > > +        Phase,
> > >
> > > +        ChipsetExit
> > >
> > > +        );
> > >
> > >    }
> > >
> > >
> > >
> > >    return Status;
> > >
> > > @@ -1914,31 +1871,16 @@ PreprocessController (
> > >    RootBridgePciAddress.Bus              = Bus;
> > >
> > >    RootBridgePciAddress.ExtendedRegister = 0;
> > >
> > >
> > >
> > > -  if (gPciPlatformProtocol != NULL) {
> > >
> > > -    //
> > >
> > > -    // Call PlatformPci::PrepController() if the protocol is present.
> > >
> > > -    //
> > >
> > > -    gPciPlatformProtocol->PlatformPrepController (
> > >
> > > -                            gPciPlatformProtocol,
> > >
> > > -                            HostBridgeHandle,
> > >
> > > -                            RootBridgeHandle,
> > >
> > > -                            RootBridgePciAddress,
> > >
> > > -                            Phase,
> > >
> > > -                            ChipsetEntry
> > >
> > > -                            );
> > >
> > > -  } else if (gPciOverrideProtocol != NULL) {
> > >
> > > -    //
> > >
> > > -    // Call PlatformPci::PrepController() if the protocol is present.
> > >
> > > -    //
> > >
> > > -    gPciOverrideProtocol->PlatformPrepController (
> > >
> > > -                            gPciOverrideProtocol,
> > >
> > > -                            HostBridgeHandle,
> > >
> > > -                            RootBridgeHandle,
> > >
> > > -                            RootBridgePciAddress,
> > >
> > > -                            Phase,
> > >
> > > -                            ChipsetEntry
> > >
> > > -                            );
> > >
> > > -  }
> > >
> > > +  //
> > >
> > > +  // Call PlatformPci::PrepController() if the protocol is present.
> > >
> > > +  //
> > >
> > > +  PciPlatformPreprocessController (
> > >
> > > +      HostBridgeHandle,
> > >
> > > +      RootBridgeHandle,
> > >
> > > +      RootBridgePciAddress,
> > >
> > > +      Phase,
> > >
> > > +      ChipsetEntry
> > >
> > > +    );
> > >
> > >
> > >
> > >    Status = PciResAlloc->PreprocessController (
> > >
> > >                            PciResAlloc,
> > >
> > > @@ -1947,31 +1889,16 @@ PreprocessController (
> > >                            Phase
> > >
> > >                            );
> > >
> > >
> > >
> > > -  if (gPciPlatformProtocol != NULL) {
> > >
> > > -    //
> > >
> > > -    // Call PlatformPci::PrepController() if the protocol is present.
> > >
> > > -    //
> > >
> > > -    gPciPlatformProtocol->PlatformPrepController (
> > >
> > > -                            gPciPlatformProtocol,
> > >
> > > -                            HostBridgeHandle,
> > >
> > > -                            RootBridgeHandle,
> > >
> > > -                            RootBridgePciAddress,
> > >
> > > -                            Phase,
> > >
> > > -                            ChipsetExit
> > >
> > > -                            );
> > >
> > > -  } else if (gPciOverrideProtocol != NULL) {
> > >
> > > -    //
> > >
> > > -    // Call PlatformPci::PrepController() if the protocol is present.
> > >
> > > -    //
> > >
> > > -    gPciOverrideProtocol->PlatformPrepController (
> > >
> > > -                            gPciOverrideProtocol,
> > >
> > > -                            HostBridgeHandle,
> > >
> > > -                            RootBridgeHandle,
> > >
> > > -                            RootBridgePciAddress,
> > >
> > > -                            Phase,
> > >
> > > -                            ChipsetExit
> > >
> > > -                            );
> > >
> > > -  }
> > >
> > > +  //
> > >
> > > +  // Call PlatformPci::PrepController() if the protocol is present.
> > >
> > > +  //
> > >
> > > +  PciPlatformPreprocessController (
> > >
> > > +      HostBridgeHandle,
> > >
> > > +      RootBridgeHandle,
> > >
> > > +      RootBridgePciAddress,
> > >
> > > +      Phase,
> > >
> > > +      ChipsetExit
> > >
> > > +    );
> > >
> > >
> > >
> > >    return EFI_SUCCESS;
> > >
> > >  }
> > >
> > > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
> > > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
> > > index c7eafff593..2343702154 100644
> > > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
> > > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
> > > @@ -230,7 +230,7 @@ PciSearchDevice (
> > >    PciIoDevice = NULL;
> > >
> > >
> > >
> > >    DEBUG ((
> > >
> > > -    EFI_D_INFO,
> > >
> > > +    DEBUG_INFO,
> > >
> > >      "PciBus: Discovered %s @ [%02x|%02x|%02x]\n",
> > >
> > >      IS_PCI_BRIDGE (Pci) ?     L"PPB" :
> > >
> > >      IS_CARDBUS_BRIDGE (Pci) ? L"P2C" :
> > >
> > > @@ -397,7 +397,7 @@ DumpPpbPaddingResource (
> > >
> > >
> > >      if ((Type != PciBarTypeUnknown) && ((ResourceType ==
> > > PciBarTypeUnknown) || (ResourceType == Type))) {
> > >
> > >        DEBUG ((
> > >
> > > -        EFI_D_INFO,
> > >
> > > +        DEBUG_INFO,
> > >
> > >          "   Padding: Type = %s; Alignment = 0x%lx;\tLength = 0x%lx\n",
> > >
> > >          mBarTypeStr[Type], Descriptor->AddrRangeMax, Descriptor->AddrLen
> > >
> > >          ));
> > >
> > > @@ -424,7 +424,7 @@ DumpPciBars (
> > >      }
> > >
> > >
> > >
> > >      DEBUG ((
> > >
> > > -      EFI_D_INFO,
> > >
> > > +      DEBUG_INFO,
> > >
> > >        "   BAR[%d]: Type = %s; Alignment = 0x%lx;\tLength = 0x%lx;\tOffset =
> > > 0x%02x\n",
> > >
> > >        Index, mBarTypeStr[MIN (PciIoDevice->PciBar[Index].BarType,
> > > PciBarTypeMaxType)],
> > >
> > >        PciIoDevice->PciBar[Index].Alignment, PciIoDevice-
> > > >PciBar[Index].Length, PciIoDevice->PciBar[Index].Offset
> > >
> > > @@ -437,13 +437,13 @@ DumpPciBars (
> > >      }
> > >
> > >
> > >
> > >      DEBUG ((
> > >
> > > -      EFI_D_INFO,
> > >
> > > +      DEBUG_INFO,
> > >
> > >        " VFBAR[%d]: Type = %s; Alignment = 0x%lx;\tLength = 0x%lx;\tOffset =
> > > 0x%02x\n",
> > >
> > >        Index, mBarTypeStr[MIN (PciIoDevice->VfPciBar[Index].BarType,
> > > PciBarTypeMaxType)],
> > >
> > >        PciIoDevice->VfPciBar[Index].Alignment, PciIoDevice-
> > > >VfPciBar[Index].Length, PciIoDevice->VfPciBar[Index].Offset
> > >
> > >        ));
> > >
> > >    }
> > >
> > > -  DEBUG ((EFI_D_INFO, "\n"));
> > >
> > > +  DEBUG ((DEBUG_INFO, "\n"));
> > >
> > >  }
> > >
> > >
> > >
> > >  /**
> > >
> > > @@ -1903,7 +1903,7 @@ PciParseBar (
> > >        // Fix the length to support some special 64 bit BAR
> > >
> > >        //
> > >
> > >        if (Value == 0) {
> > >
> > > -        DEBUG ((EFI_D_INFO, "[PciBus]BAR probing for upper 32bit of MEM64
> > > BAR returns 0, change to 0xFFFFFFFF.\n"));
> > >
> > > +        DEBUG ((DEBUG_INFO, "[PciBus]BAR probing for upper 32bit of
> > MEM64
> > > BAR returns 0, change to 0xFFFFFFFF.\n"));
> > >
> > >          Value = (UINT32) -1;
> > >
> > >        } else {
> > >
> > >          Value |= ((UINT32)(-1) << HighBitSet32 (Value));
> > >
> > > @@ -2153,7 +2153,17 @@ CreatePciIoDevice (
> > >               NULL
> > >
> > >               );
> > >
> > >    if (!EFI_ERROR (Status)) {
> > >
> > > -    PciIoDevice->IsPciExp = TRUE;
> > >
> > > +  PciIoDevice->IsPciExp = TRUE;
> > >
> > > +    //
> > >
> > > +    // read the PCI device's entire PCI Express Capability structure
> > >
> > > +    //
> > >
> > > +    PciIo->Pci.Read (
> > >
> > > +                  PciIo,
> > >
> > > +                  EfiPciIoWidthUint8,
> > >
> > > +                  PciIoDevice->PciExpressCapabilityOffset,
> > >
> > > +                  sizeof (PCI_CAPABILITY_PCIEXP) / sizeof (UINT8),
> > >
> > > +                  &PciIoDevice->PciExpStruct
> > >
> > > +                );
> > >
> > >    }
> > >
> > >
> > >
> > >    if (PcdGetBool (PcdAriSupport)) {
> > >
> > > @@ -2206,7 +2216,7 @@ CreatePciIoDevice (
> > >                                &Data32
> > >
> > >                                );
> > >
> > >            DEBUG ((
> > >
> > > -            EFI_D_INFO,
> > >
> > > +            DEBUG_INFO,
> > >
> > >              " ARI: forwarding enabled for PPB[%02x:%02x:%02x]\n",
> > >
> > >              Bridge->BusNumber,
> > >
> > >              Bridge->DeviceNumber,
> > >
> > > @@ -2215,7 +2225,7 @@ CreatePciIoDevice (
> > >          }
> > >
> > >        }
> > >
> > >
> > >
> > > -      DEBUG ((EFI_D_INFO, " ARI: CapOffset = 0x%x\n", PciIoDevice-
> > > >AriCapabilityOffset));
> > >
> > > +      DEBUG ((DEBUG_INFO, " ARI: CapOffset = 0x%x\n", PciIoDevice-
> > > >AriCapabilityOffset));
> > >
> > >      }
> > >
> > >    }
> > >
> > >
> > >
> > > @@ -2325,12 +2335,12 @@ CreatePciIoDevice (
> > >        PciIoDevice->ReservedBusNum = (UINT16)(EFI_PCI_BUS_OF_RID
> > (LastVF)
> > > - Bus + 1);
> > >
> > >
> > >
> > >        DEBUG ((
> > >
> > > -        EFI_D_INFO,
> > >
> > > +        DEBUG_INFO,
> > >
> > >          " SR-IOV: SupportedPageSize = 0x%x; SystemPageSize = 0x%x;
> > > FirstVFOffset = 0x%x;\n",
> > >
> > >          SupportedPageSize, PciIoDevice->SystemPageSize >> 12, FirstVFOffset
> > >
> > >          ));
> > >
> > >        DEBUG ((
> > >
> > > -        EFI_D_INFO,
> > >
> > > +        DEBUG_INFO,
> > >
> > >          "         InitialVFs = 0x%x; ReservedBusNum = 0x%x; CapOffset = 0x%x\n",
> > >
> > >          PciIoDevice->InitialVFs, PciIoDevice->ReservedBusNum, PciIoDevice-
> > > >SrIovCapabilityOffset
> > >
> > >          ));
> > >
> > > @@ -2345,7 +2355,7 @@ CreatePciIoDevice (
> > >                 NULL
> > >
> > >                 );
> > >
> > >      if (!EFI_ERROR (Status)) {
> > >
> > > -      DEBUG ((EFI_D_INFO, " MR-IOV: CapOffset = 0x%x\n", PciIoDevice-
> > > >MrIovCapabilityOffset));
> > >
> > > +      DEBUG ((DEBUG_INFO, " MR-IOV: CapOffset = 0x%x\n", PciIoDevice-
> > > >MrIovCapabilityOffset));
> > >
> > >      }
> > >
> > >    }
> > >
> > >
> > >
> > > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> > > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> > > new file mode 100644
> > > index 0000000000..0819da6536
> > > --- /dev/null
> > > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> > > @@ -0,0 +1,1601 @@
> > > +/** @file
> > >
> > > +  PCI standard feature support functions implementation for PCI Bus
> > > module..
> > >
> > > +
> > >
> > > +Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> > >
> > > +SPDX-License-Identifier: BSD-2-Clause-Patent
> > >
> > > +
> > >
> > > +**/
> > >
> > > +
> > >
> > > +#include "PciFeatureSupport.h"
> > >
> > > +
> > >
> > > +/**
> > >
> > > +  A gobal pointer to PRIMARY_ROOT_PORT_NODE buffer to track all the
> > > primary physical
> > >
> > > +  PCI Root Ports (PCI Controllers) for a given PCI Root Bridge instance while
> > >
> > > +  enumerating to configure the PCI features
> > >
> > > +**/
> > >
> > > +PRIMARY_ROOT_PORT_NODE                      *mPrimaryRootPortList;
> > >
> > > +
> > >
> > > +/**
> > >
> > > +  A gobal pointer to OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > buffer
> > > all the PCI
> > >
> > > +  Feature configuration Table nodes to pair against each of the
> > > PRIMARY_ROOT_PORT_NODE
> > >
> > > +  buffer nodes. Each node of these is used to align all the PCI devices
> > > originating
> > >
> > > +  from the PCI Root Port devices of a PCI Root Bridge instance
> > >
> > > +**/
> > >
> > > +OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > > *mPciFeaturesConfigurationTableInstances;
> > >
> > > +
> > >
> > > +/**
> > >
> > > +  A global pointer to PCI_FEATURE_CONFIGURATION_COMPLETION_LIST,
> > > which stores all
> > >
> > > +  the PCI Root Bridge instances that are enumerated for the other PCI
> > > features,
> > >
> > > +  like MaxPayloadSize & MaxReadReqSize; during the the Start() interface
> > of
> > > the
> > >
> > > +  driver binding protocol. The records pointed by this pointer would be
> > > destroyed
> > >
> > > +  when the DXE core invokes the Stop() interface.
> > >
> > > +**/
> > >
> > > +PCI_FEATURE_CONFIGURATION_COMPLETION_LIST
> > > *mPciFeaturesConfigurationCompletionList = NULL;
> > >
> > > +
> > >
> > > +/**
> > >
> > > +  Main routine to indicate platform selection of any of the other PCI
> > features
> > >
> > > +  to be configured by this driver
> > >
> > > +
> > >
> > > +  @retval TRUE    platform has selected the other PCI features to be
> > > configured
> > >
> > > +          FALSE   platform has not selected any of the other PCI features
> > >
> > > +**/
> > >
> > > +BOOLEAN
> > >
> > > +CheckOtherPciFeaturesPcd (
> > >
> > > +  )
> > >
> > > +{
> > >
> > > +  return PcdGet32 ( PcdOtherPciFeatures) ? TRUE : FALSE;
> > >
> > > +}
> > >
> > > +
> > >
> > > +/**
> > >
> > > +  Main routine to indicate whether the platform has selected the
> > > Max_Payload_Size
> > >
> > > +  PCI feature to be configured by this driver
> > >
> > > +
> > >
> > > +  @retval TRUE    platform has selected the Max_Payload_Size to be
> > > configured
> > >
> > > +          FALSE   platform has not selected this feature
> > >
> > > +**/
> > >
> > > +BOOLEAN
> > >
> > > +SetupMaxPayloadSize (
> > >
> > > +  )
> > >
> > > +{
> > >
> > > +  return (PcdGet32 ( PcdOtherPciFeatures) &
> > > PCI_FEATURE_SUPPORT_FLAG_MPS) ? TRUE : FALSE;
> > >
> > > +}
> > >
> > > +
> > >
> > > +/**
> > >
> > > +  Main routine to indicate whether the platform has selected the
> > > Max_Read_Req_Size
> > >
> > > +  PCI feature to be configured by this driver
> > >
> > > +
> > >
> > > +  @retval TRUE    platform has selected the Max_Read_Req_Size to be
> > > configured
> > >
> > > +          FALSE   platform has not selected this feature
> > >
> > > +**/
> > >
> > > +BOOLEAN
> > >
> > > +SetupMaxReadReqSize (
> > >
> > > +  )
> > >
> > > +{
> > >
> > > +  return (PcdGet32 ( PcdOtherPciFeatures) &
> > > PCI_FEATURE_SUPPORT_FLAG_MRRS) ? TRUE : FALSE;
> > >
> > > +}
> > >
> > > +
> > >
> > > +/**
> > >
> > > +  Helper routine which determines whether the given PCI Root Bridge
> > > instance
> > >
> > > +  record already exist. This routine shall help avoid duplicate record
> > creation
> > >
> > > +  in case of re-enumeration of PCI configuation features.
> > >
> > > +
> > >
> > > +  @param  RootBridge              A pointer to the PCI_IO_DEVICE for the Root
> > > Bridge
> > >
> > > +  @param  PciFeatureConfigRecord  A pointer to a pointer for type
> > >
> > > +                                  PCI_FEATURE_CONFIGURATION_COMPLETION_LIST
> > >
> > > +                                  record, Use to return the specific record.
> > >
> > > +
> > >
> > > +  @retval TRUE                    Record already exist
> > >
> > > +          FALSE                   Record does not exist for the given PCI Root Bridge
> > >
> > > +**/
> > >
> > > +BOOLEAN
> > >
> > > +CheckPciFeatureConfigurationRecordExist (
> > >
> > > +  IN  PCI_IO_DEVICE                             *RootBridge,
> > >
> > > +  OUT PCI_FEATURE_CONFIGURATION_COMPLETION_LIST
> > > **PciFeatureConfigRecord
> > >
> > > +  )
> > >
> > > +{
> > >
> > > +  LIST_ENTRY                                  *Link;
> > >
> > > +  PCI_FEATURE_CONFIGURATION_COMPLETION_LIST   *Temp;
> > >
> > > +
> > >
> > > +  if ( mPciFeaturesConfigurationCompletionList) {
> > >
> > > +    Link = &mPciFeaturesConfigurationCompletionList->RootBridgeLink;
> > >
> > > +
> > >
> > > +    do {
> > >
> > > +      Temp =
> > > PCI_FEATURE_CONFIGURATION_COMPLETION_LIST_FROM_LINK (Link);
> > >
> > > +      if ( Temp->RootBridgeHandle == RootBridge->Handle) {
> > >
> > > +        *PciFeatureConfigRecord = Temp;
> > >
> > > +        return TRUE;
> > >
> > > +      }
> > >
> > > +      Link = Link->ForwardLink;
> > >
> > > +    } while (Link != &mPciFeaturesConfigurationCompletionList-
> > > >RootBridgeLink);
> > >
> > > +  }
> > >
> > > +  //
> > >
> > > +  // not found on the PCI feature configuration completion list
> > >
> > > +  //
> > >
> > > +  *PciFeatureConfigRecord = NULL;
> > >
> > > +  return FALSE;
> > >
> > > +}
> > >
> > > +
> > >
> > > +/**
> > >
> > > +  This routine is primarily to avoid multiple configuration of PCI features
> > >
> > > +  to the same PCI Root Bridge due to EDK2 core's ConnectController calls
> > on
> > >
> > > +  all the EFI handles. This routine also provide re-enumeration of the PCI
> > >
> > > +  features on the same PCI Root Bridge based on the policy of
> > > ReEnumeratePciFeatureConfiguration
> > >
> > > +  of the PCI_FEATURE_CONFIGURATION_COMPLETION_LIST.
> > >
> > > +
> > >
> > > +  @param  RootBridge              A pointer to the PCI_IO_DEVICE for the Root
> > > Bridge
> > >
> > > +
> > >
> > > +  @retval TRUE                    PCI Feature configuration required for the PCI
> > >
> > > +                                  Root Bridge
> > >
> > > +          FALSE                   PCI Feature configuration is not required to be
> > >
> > > +                                  re-enumerated for the PCI Root Bridge
> > >
> > > +**/
> > >
> > > +BOOLEAN
> > >
> > > +CheckPciFeaturesConfigurationRequired (
> > >
> > > +  IN PCI_IO_DEVICE          *RootBridge
> > >
> > > +  )
> > >
> > > +{
> > >
> > > +  LIST_ENTRY                                  *Link;
> > >
> > > +  PCI_FEATURE_CONFIGURATION_COMPLETION_LIST   *Temp;
> > >
> > > +
> > >
> > > +  if ( mPciFeaturesConfigurationCompletionList) {
> > >
> > > +    Link = &mPciFeaturesConfigurationCompletionList->RootBridgeLink;
> > >
> > > +
> > >
> > > +    do {
> > >
> > > +      Temp =
> > > PCI_FEATURE_CONFIGURATION_COMPLETION_LIST_FROM_LINK (Link);
> > >
> > > +      if ( Temp->RootBridgeHandle == RootBridge->Handle) {
> > >
> > > +        return Temp->ReEnumeratePciFeatureConfiguration;
> > >
> > > +      }
> > >
> > > +      Link = Link->ForwardLink;
> > >
> > > +    } while (Link != &mPciFeaturesConfigurationCompletionList-
> > > >RootBridgeLink);
> > >
> > > +  }
> > >
> > > +  //
> > >
> > > +  // not found on the PCI feature configuration completion list, return as
> > > required
> > >
> > > +  //
> > >
> > > +  return TRUE;
> > >
> > > +}
> > >
> > > +
> > >
> > > +/**
> > >
> > > +  This routine finds the duplicate record if exist and assigns the re-
> > > enumeration
> > >
> > > +  requirement flag, as passed as input. It creates new record for the PCI
> > > Root
> > >
> > > +  Bridge and appends the list after updating its re-enumeration flag.
> > >
> > > +
> > >
> > > +  @param  RootBridge            A pointer to PCI_IO_DEVICE of the Root
> > Bridge
> > >
> > > +  @param  ReEnumerationRequired A BOOLEAN for recording the re-
> > > enumeration requirement
> > >
> > > +
> > >
> > > +  @retval EFI_SUCCESS           new record inserted into the list or updated
> > the
> > >
> > > +                                existing record
> > >
> > > +          EFI_INVALID_PARAMETER Unexpected error as
> > > CheckPciFeatureConfigurationRecordExist
> > >
> > > +                                reports as record exist but does not return its pointer
> > >
> > > +          EFI_OUT_OF_RESOURCES  Not able to create PCI features
> > configuratin
> > > complete
> > >
> > > +                                record for the RootBridge
> > >
> > > +**/
> > >
> > > +EFI_STATUS
> > >
> > > +AddRootBridgeInPciFeaturesConfigCompletionList (
> > >
> > > +  IN PCI_IO_DEVICE          *RootBridge,
> > >
> > > +  IN BOOLEAN                ReEnumerationRequired
> > >
> > > +  )
> > >
> > > +{
> > >
> > > +  PCI_FEATURE_CONFIGURATION_COMPLETION_LIST   *Temp;
> > >
> > > +
> > >
> > > +  if ( CheckPciFeatureConfigurationRecordExist ( RootBridge, &Temp)) {
> > >
> > > +    //
> > >
> > > +    // this PCI Root Bridge record already exist; it may have been re-
> > > enumerated
> > >
> > > +    // hence just update its enumeration required flag again to exit
> > >
> > > +    //
> > >
> > > +    if ( Temp) {
> > >
> > > +      Temp->ReEnumeratePciFeatureConfiguration  =
> > > ReEnumerationRequired;
> > >
> > > +      return EFI_SUCCESS;
> > >
> > > +    } else {
> > >
> > > +      //
> > >
> > > +      // PCI feature configuration complete record reported as exist and no
> > >
> > > +      // record pointer returned
> > >
> > > +      //
> > >
> > > +      return EFI_INVALID_PARAMETER;
> > >
> > > +    }
> > >
> > > +
> > >
> > > +  } else {
> > >
> > > +
> > >
> > > +    Temp = AllocateZeroPool ( sizeof
> > > ( PCI_FEATURE_CONFIGURATION_COMPLETION_LIST));
> > >
> > > +    if ( !Temp) {
> > >
> > > +      return EFI_OUT_OF_RESOURCES;
> > >
> > > +    }
> > >
> > > +    Temp->Signature                           =
> > > PCI_FEATURE_CONFIGURATION_SIGNATURE;
> > >
> > > +    Temp->RootBridgeHandle                    = RootBridge->Handle;
> > >
> > > +    Temp->ReEnumeratePciFeatureConfiguration  =
> > ReEnumerationRequired;
> > >
> > > +    if ( mPciFeaturesConfigurationCompletionList) {
> > >
> > > +      InsertTailList ( &mPciFeaturesConfigurationCompletionList-
> > > >RootBridgeLink,
> > >
> > > +                       &Temp->RootBridgeLink);
> > >
> > > +    } else {
> > >
> > > +      //
> > >
> > > +      // init the very first node of the Root Bridge
> > >
> > > +      //
> > >
> > > +      mPciFeaturesConfigurationCompletionList = Temp;
> > >
> > > +      InitializeListHead ( &mPciFeaturesConfigurationCompletionList-
> > > >RootBridgeLink);
> > >
> > > +    }
> > >
> > > +  }
> > >
> > > +  return EFI_SUCCESS;
> > >
> > > +}
> > >
> > > +
> > >
> > > +/**
> > >
> > > +  Free up memory alloted for the primary physical PCI Root ports of the
> > PCI
> > > Root
> > >
> > > +  Bridge instance. Free up all the nodes of type
> > > PRIMARY_ROOT_PORT_NODE.
> > >
> > > +**/
> > >
> > > +VOID
> > >
> > > +DestroyPrimaryRootPortNodes ()
> > >
> > > +{
> > >
> > > +  LIST_ENTRY                *Link;
> > >
> > > +  PRIMARY_ROOT_PORT_NODE    *Temp;
> > >
> > > +
> > >
> > > +  if ( mPrimaryRootPortList) {
> > >
> > > +    Link = &mPrimaryRootPortList->NeighborRootPort;
> > >
> > > +
> > >
> > > +    if ( IsListEmpty ( Link)) {
> > >
> > > +      FreePool ( mPrimaryRootPortList);
> > >
> > > +    } else {
> > >
> > > +      do {
> > >
> > > +        if ( Link->ForwardLink != &mPrimaryRootPortList->NeighborRootPort)
> > {
> > >
> > > +          Link = Link->ForwardLink;
> > >
> > > +        }
> > >
> > > +        Temp = PRIMARY_ROOT_PORT_NODE_FROM_LINK ( Link);
> > >
> > > +        Link = RemoveEntryList ( Link);
> > >
> > > +        FreePool ( Temp);
> > >
> > > +      } while ( !IsListEmpty ( Link));
> > >
> > > +      FreePool ( mPrimaryRootPortList);
> > >
> > > +    }
> > >
> > > +    mPrimaryRootPortList = NULL;
> > >
> > > +  }
> > >
> > > +}
> > >
> > > +
> > >
> > > +/**
> > >
> > > +  Free up the memory allocated for temporarily maintaining the PCI
> > feature
> > >
> > > +  configuration table for all the nodes of the primary PCI Root port.
> > >
> > > +  Free up memory alloted for
> > > OTHER_PCI_FEATURES_CONFIGURATION_TABLE.
> > >
> > > +**/
> > >
> > > +VOID
> > >
> > > +ErasePciFeaturesConfigurationTable (
> > >
> > > +  )
> > >
> > > +{
> > >
> > > +  if ( mPciFeaturesConfigurationTableInstances) {
> > >
> > > +    FreePool ( mPciFeaturesConfigurationTableInstances);
> > >
> > > +  }
> > >
> > > +  mPciFeaturesConfigurationTableInstances = NULL;
> > >
> > > +}
> > >
> > > +
> > >
> > > +/**
> > >
> > > +  Routine meant for initializing any global variables used. It primarily cleans
> > >
> > > +  up the internal data structure memory allocated for the previous PCI
> > Root
> > > Bridge
> > >
> > > +  instance. This should be the first routine to call for any virtual PCI Root
> > >
> > > +  Bridge instance.
> > >
> > > +**/
> > >
> > > +VOID
> > >
> > > +SetupPciFeaturesConfigurationDefaults ()
> > >
> > > +{
> > >
> > > +  //
> > >
> > > +  // delete the primary root port list
> > >
> > > +  //
> > >
> > > +  if (mPrimaryRootPortList) {
> > >
> > > +    DestroyPrimaryRootPortNodes ();
> > >
> > > +  }
> > >
> > > +
> > >
> > > +  if ( mPciFeaturesConfigurationTableInstances) {
> > >
> > > +    ErasePciFeaturesConfigurationTable ();
> > >
> > > +  }
> > >
> > > +}
> > >
> > > +
> > >
> > > +/**
> > >
> > > +  Helper routine to determine whether the PCI device is a physical root
> > port
> > >
> > > +  recorded in the list.
> > >
> > > +
> > >
> > > +  @param  PciDevice                       A pointer to the PCI_IO_DEVICE.
> > >
> > > +
> > >
> > > +  @retval TRUE                            The PCI device instance is a primary
> > >
> > > +                                          primary physical PCI Root Port
> > >
> > > +          FALSE                           Not a primary physical PCI Root port
> > >
> > > +**/
> > >
> > > +BOOLEAN
> > >
> > > +CheckRootBridgePrimaryPort (
> > >
> > > +  IN PCI_IO_DEVICE          *PciDevice
> > >
> > > +  )
> > >
> > > +{
> > >
> > > +  LIST_ENTRY                *Link;
> > >
> > > +  PRIMARY_ROOT_PORT_NODE    *Temp;
> > >
> > > +
> > >
> > > +  if ( !mPrimaryRootPortList) {
> > >
> > > +    return FALSE;
> > >
> > > +  }
> > >
> > > +  Link = &mPrimaryRootPortList->NeighborRootPort;
> > >
> > > +  do {
> > >
> > > +    Temp = PRIMARY_ROOT_PORT_NODE_FROM_LINK ( Link);
> > >
> > > +    if ( Temp->RootBridgeHandle == PciDevice->Parent->Handle
> > >
> > > +        && Temp->RootPortHandle == PciDevice->Handle) {
> > >
> > > +      //
> > >
> > > +      // the given PCI device is the primary root port of the Root Bridge
> > > controller
> > >
> > > +      //
> > >
> > > +      return TRUE;
> > >
> > > +    }
> > >
> > > +    Link = Link->ForwardLink;
> > >
> > > +  } while ( Link != &mPrimaryRootPortList->NeighborRootPort);
> > >
> > > +  //
> > >
> > > +  // the given PCI device is not the primary root port of the Bridge
> > controller
> > >
> > > +  //
> > >
> > > +  return FALSE;
> > >
> > > +}
> > >
> > > +
> > >
> > > +/**
> > >
> > > +  Main routine to determine the child PCI devices of a physical PCI bridge
> > > device
> > >
> > > +  and group them under a common internal PCI features Configuration
> > table.
> > >
> > > +
> > >
> > > +  @param  PciDevice                       A pointer to the PCI_IO_DEVICE.
> > >
> > > +  @param  PciFeaturesConfigTable          A pointer to a pointer to the
> > >
> > > +                                          OTHER_PCI_FEATURES_CONFIGURATION_TABLE.
> > >
> > > +                                          Returns NULL in case of RCiEP or the PCI
> > >
> > > +                                          device does match with any of the physical
> > >
> > > +                                          Root ports, or it does not belong to any
> > >
> > > +                                          Root port's PCU bus range (not a child)
> > >
> > > +
> > >
> > > +  @retval EFI_SUCCESS                     able to determine the PCI feature
> > >
> > > +                                          configuration table. For RCiEP since
> > >
> > > +                                          since it is not prepared.
> > >
> > > +          EFI_NOT_FOUND                   the PCI feature configuration table does
> > >
> > > +                                          not exist as the PCI physical Bridge device
> > >
> > > +                                          is not found for this device's parent
> > >
> > > +                                          Root Bridge instance
> > >
> > > +**/
> > >
> > > +EFI_STATUS
> > >
> > > +GetPciFeaturesConfigurationTable (
> > >
> > > +  IN  PCI_IO_DEVICE                           *PciDevice,
> > >
> > > +  OUT OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > > **PciFeaturesConfigTable
> > >
> > > +  )
> > >
> > > +{
> > >
> > > +  LIST_ENTRY                *Link;
> > >
> > > +  PRIMARY_ROOT_PORT_NODE    *Temp;
> > >
> > > +
> > >
> > > +  if ( !mPrimaryRootPortList) {
> > >
> > > +    *PciFeaturesConfigTable = NULL;
> > >
> > > +    return EFI_NOT_FOUND;
> > >
> > > +  }
> > >
> > > +
> > >
> > > +  //
> > >
> > > +  // The PCI features configuration table is not built for RCiEP, return NULL
> > >
> > > +  //
> > >
> > > +  if ( PciDevice->PciExpStruct.Capability.Bits.DevicePortType == \
> > >
> > > +        PCIE_DEVICE_PORT_TYPE_ROOT_COMPLEX_INTEGRATED_ENDPOINT)
> > > {
> > >
> > > +    *PciFeaturesConfigTable = NULL;
> > >
> > > +    return EFI_SUCCESS;
> > >
> > > +  }
> > >
> > > +
> > >
> > > +  Link = &mPrimaryRootPortList->NeighborRootPort;
> > >
> > > +  do {
> > >
> > > +    Temp = PRIMARY_ROOT_PORT_NODE_FROM_LINK ( Link);
> > >
> > > +    if ( Temp->RootBridgeHandle == PciDevice->Parent->Handle
> > >
> > > +        && Temp->RootPortHandle == PciDevice->Handle) {
> > >
> > > +      //
> > >
> > > +      // the given PCI device is the primary root port of the Root Bridge
> > > controller
> > >
> > > +      //
> > >
> > > +      *PciFeaturesConfigTable = Temp-
> > >OtherPciFeaturesConfigurationTable;
> > >
> > > +      return EFI_SUCCESS;
> > >
> > > +    } else {
> > >
> > > +      //
> > >
> > > +      // check this PCI device belongs to the primary root port of the root
> > > bridge
> > >
> > > +      //
> > >
> > > +      if ( PciDevice->BusNumber >= Temp->SecondaryBusStart
> > >
> > > +          && PciDevice->BusNumber <= Temp->SecondaryBusEnd) {
> > >
> > > +        *PciFeaturesConfigTable = Temp-
> > >OtherPciFeaturesConfigurationTable;
> > >
> > > +        return EFI_SUCCESS;
> > >
> > > +      }
> > >
> > > +    }
> > >
> > > +    Link = Link->ForwardLink;
> > >
> > > +  } while ( Link != &mPrimaryRootPortList->NeighborRootPort);
> > >
> > > +  //
> > >
> > > +  // the PCI device must be RCiEP, does not belong to any primary root
> > port
> > >
> > > +  //
> > >
> > > +  *PciFeaturesConfigTable = NULL;
> > >
> > > +  return EFI_SUCCESS;
> > >
> > > +}
> > >
> > > +
> > >
> > > +/**
> > >
> > > +  The helper routine to retrieve the PCI bus numbers from the PCI Bridge
> > or
> > > Root
> > >
> > > +  port device. Assumes the input PCI device has the PCI Type 1
> > configuration
> > > header.
> > >
> > > +
> > >
> > > +  @param  PciDevice                       A pointer to the PCI_IO_DEVICE.
> > >
> > > +  @param  PrimaryBusNumber                A pointer to return the PCI Priamry
> > >
> > > +                                          Bus number.
> > >
> > > +  @param  SecondaryBusNumber              A pointer to return the PCI
> > > Secondary
> > >
> > > +                                          Bus number.
> > >
> > > +  @param  SubordinateBusNumber            A pointer to return the PCI
> > > Subordinate
> > >
> > > +                                          Bus number.
> > >
> > > +
> > >
> > > +  @retval EFI_SUCCESS           The data was read from the PCI device.
> > >
> > > +  @retval EFI_UNSUPPORTED       The address range specified by Offset,
> > > Width, and Count is not
> > >
> > > +                                valid for the PCI configuration header of the PCI device.
> > >
> > > +  @retval EFI_INVALID_PARAMETER input parameters provided to the
> > read
> > > operation were invalid.
> > >
> > > +**/
> > >
> > > +EFI_STATUS
> > >
> > > +GetPciRootPortBusAssigned (
> > >
> > > +  IN  PCI_IO_DEVICE                           *PciDevice,
> > >
> > > +  OUT UINT8                                   *PrimaryBusNumber,
> > >
> > > +  OUT UINT8                                   *SecondaryBusNumber,
> > >
> > > +  OUT UINT8                                   *SubordinateBusNumber
> > >
> > > +  )
> > >
> > > +{
> > >
> > > +  EFI_STATUS                                  Status;
> > >
> > > +  UINT32                                      RootPortBusAssigned;
> > >
> > > +
> > >
> > > +  Status = PciDevice->PciIo.Pci.Read (
> > >
> > > +                                  &PciDevice->PciIo,
> > >
> > > +                                  EfiPciIoWidthUint32,
> > >
> > > +                                  PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET,
> > >
> > > +                                  1,
> > >
> > > +                                  &RootPortBusAssigned
> > >
> > > +                                );
> > >
> > > +  if ( !EFI_ERROR(Status)) {
> > >
> > > +    if ( PrimaryBusNumber) {
> > >
> > > +      *PrimaryBusNumber = (UINT8) (0xFF & RootPortBusAssigned);
> > >
> > > +    }
> > >
> > > +    if ( SecondaryBusNumber) {
> > >
> > > +      *SecondaryBusNumber = (UINT8)(0xFF & (RootPortBusAssigned >> 8));
> > >
> > > +    }
> > >
> > > +    if ( SubordinateBusNumber) {
> > >
> > > +      *SubordinateBusNumber = (UINT8)(0xFF & (RootPortBusAssigned >>
> > > 16));
> > >
> > > +    }
> > >
> > > +  }
> > >
> > > +  return Status;
> > >
> > > +}
> > >
> > > +
> > >
> > > +/**
> > >
> > > +  This routine determines the existance of the child PCI device for the
> > given
> > >
> > > +  PCI Root / Bridge Port device. Always assumes the input PCI device is the
> > > bridge
> > >
> > > +  or PCI-PCI Bridge device. This routine should not be used with PCI
> > > endpoint device.
> > >
> > > +
> > >
> > > +  @param  PciDevice                       A pointer to the PCI_IO_DEVICE.
> > >
> > > +
> > >
> > > +  @retval TRUE                            child device exist
> > >
> > > +          FALSE                           no child device
> > >
> > > +**/
> > >
> > > +BOOLEAN
> > >
> > > +IsPciRootPortEmpty (
> > >
> > > +  IN  PCI_IO_DEVICE                           *PciDevice
> > >
> > > +  )
> > >
> > > +{
> > >
> > > +  UINT8                                       SecBus,
> > >
> > > +                                              SubBus;
> > >
> > > +  EFI_STATUS                                  Status;
> > >
> > > +  LIST_ENTRY                                  *Link;
> > >
> > > +  PCI_IO_DEVICE                               *NextPciDevice;
> > >
> > > +
> > >
> > > +  //
> > >
> > > +  // check secondary & suboridinate bus numbers for its endpoint device
> > >
> > > +  // existance
> > >
> > > +  //
> > >
> > > +  Status = GetPciRootPortBusAssigned ( PciDevice, NULL, &SecBus,
> > > &SubBus);
> > >
> > > +  if ( !EFI_ERROR( Status)) {
> > >
> > > +    Link = PciDevice->ChildList.ForwardLink;
> > >
> > > +    if ( IsListEmpty ( Link)) {
> > >
> > > +      //
> > >
> > > +      // return as PCI Root port empty
> > >
> > > +      //
> > >
> > > +      DEBUG (( DEBUG_INFO, "RP empty,"));
> > >
> > > +      return TRUE;
> > >
> > > +    }
> > >
> > > +    do {
> > >
> > > +      NextPciDevice = PCI_IO_DEVICE_FROM_LINK ( Link);
> > >
> > > +      DEBUG (( DEBUG_INFO, "dev@%x", NextPciDevice->BusNumber));
> > >
> > > +
> > >
> > > +      if ( NextPciDevice->BusNumber >= SecBus
> > >
> > > +          && NextPciDevice->BusNumber <= SubBus) {
> > >
> > > +
> > >
> > > +        return FALSE;
> > >
> > > +      }
> > >
> > > +
> > >
> > > +      Link = Link->ForwardLink;
> > >
> > > +    } while ( Link != &PciDevice->ChildList);
> > >
> > > +  } else {
> > >
> > > +    SecBus = SubBus = 0;
> > >
> > > +    DEBUG (( DEBUG_ERROR, "unable to retrieve root port's bus range
> > > assigned!!!"));
> > >
> > > +  }
> > >
> > > +
> > >
> > > +  //
> > >
> > > +  // return as PCI Root port empty
> > >
> > > +  //
> > >
> > > +  return TRUE;
> > >
> > > +}
> > >
> > > +
> > >
> > > +/**
> > >
> > > +  The main routine which process the PCI feature Max_Payload_Size as
> > per
> > > the
> > >
> > > +  device-specific platform policy, as well as in complaince with the PCI Base
> > >
> > > +  specification Revision 4, that aligns the value for the entire PCI heirarchy
> > >
> > > +  starting from its physical PCI Root port / Bridge device.
> > >
> > > +
> > >
> > > +  @param PciDevice                      A pointer to the PCI_IO_DEVICE.
> > >
> > > +  @param PciConfigPhase                 for the PCI feature configuration phases:
> > >
> > > +                                        PciFeatureGetDevicePolicy & PciFeatureSetupPhase
> > >
> > > +  @param PciFeaturesConfigurationTable  pointer to
> > > OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > >
> > > +
> > >
> > > +  @retval EFI_SUCCESS                   processing of PCI feature
> > > Max_Payload_Size
> > >
> > > +                                        is successful.
> > >
> > > +**/
> > >
> > > +EFI_STATUS
> > >
> > > +ProcessMaxPayloadSize (
> > >
> > > +  IN  PCI_IO_DEVICE                           *PciDevice,
> > >
> > > +  IN  PCI_FEATURE_CONFIGURATION_PHASE         PciConfigPhase,
> > >
> > > +  IN  OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > > *PciFeaturesConfigurationTable
> > >
> > > +  )
> > >
> > > +{
> > >
> > > +  PCI_REG_PCIE_DEVICE_CAPABILITY          PciDeviceCap;
> > >
> > > +  UINT8                                   MpsValue;
> > >
> > > +
> > >
> > > +
> > >
> > > +  PciDeviceCap.Uint32 = PciDevice->PciExpStruct.DeviceCapability.Uint32;
> > >
> > > +
> > >
> > > +  if ( PciConfigPhase == PciFeatureGetDevicePolicy) {
> > >
> > > +    if ( SetupMpsAsPerDeviceCapability ( PciDevice->SetupMPS))
> > >
> > > +    {
> > >
> > > +      MpsValue = (UINT8)PciDeviceCap.Bits.MaxPayloadSize;
> > >
> > > +      //
> > >
> > > +      // no change to PCI Root ports without any endpoint device
> > >
> > > +      //
> > >
> > > +      if ( IS_PCI_BRIDGE ( &PciDevice->Pci) &&
> > > PciDeviceCap.Bits.MaxPayloadSize) {
> > >
> > > +        if ( IsPciRootPortEmpty ( PciDevice)) {
> > >
> > > +          MpsValue = PCIE_MAX_PAYLOAD_SIZE_128B;
> > >
> > > +          DEBUG (( DEBUG_INFO, "(reset RP MPS to min.)"));
> > >
> > > +        }
> > >
> > > +      }
> > >
> > > +    } else {
> > >
> > > +      MpsValue = TranslateMpsSetupValueToPci ( PciDevice->SetupMPS);
> > >
> > > +    }
> > >
> > > +    //
> > >
> > > +    // discard device policy override request if greater than PCI device
> > > capability
> > >
> > > +    //
> > >
> > > +    PciDevice->SetupMPS =
> > MIN( (UINT8)PciDeviceCap.Bits.MaxPayloadSize,
> > > MpsValue);
> > >
> > > +  }
> > >
> > > +
> > >
> > > +  //
> > >
> > > +  // align the MPS of the tree to the HCF with this device
> > >
> > > +  //
> > >
> > > +  if ( PciFeaturesConfigurationTable) {
> > >
> > > +    MpsValue = PciFeaturesConfigurationTable->Max_Payload_Size;
> > >
> > > +
> > >
> > > +    MpsValue = MIN ( PciDevice->SetupMPS, MpsValue);
> > >
> > > +    PciDevice->SetupMPS = MIN ( PciDevice->SetupMPS, MpsValue);
> > >
> > > +
> > >
> > > +    if ( MpsValue != PciFeaturesConfigurationTable->Max_Payload_Size) {
> > >
> > > +      DEBUG (( DEBUG_INFO, "reset MPS of the tree to %d,", MpsValue));
> > >
> > > +      PciFeaturesConfigurationTable->Max_Payload_Size = MpsValue;
> > >
> > > +    }
> > >
> > > +  }
> > >
> > > +
> > >
> > > +  DEBUG (( DEBUG_INFO,
> > >
> > > +      "Max_Payload_Size: %d [DevCap:%d],",
> > >
> > > +      PciDevice->SetupMPS, PciDeviceCap.Bits.MaxPayloadSize
> > >
> > > +  ));
> > >
> > > +  return EFI_SUCCESS;
> > >
> > > +}
> > >
> > > +
> > >
> > > +/**
> > >
> > > +  The main routine which process the PCI feature Max_Read_Req_Size as
> > > per the
> > >
> > > +  device-specific platform policy, as well as in complaince with the PCI Base
> > >
> > > +  specification Revision 4, that aligns the value for the entire PCI heirarchy
> > >
> > > +  starting from its physical PCI Root port / Bridge device.
> > >
> > > +
> > >
> > > +  @param PciDevice                      A pointer to the PCI_IO_DEVICE.
> > >
> > > +  @param PciConfigPhase                 for the PCI feature configuration phases:
> > >
> > > +                                        PciFeatureGetDevicePolicy & PciFeatureSetupPhase
> > >
> > > +  @param PciFeaturesConfigurationTable  pointer to
> > > OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > >
> > > +
> > >
> > > +  @retval EFI_SUCCESS                   processing of PCI feature
> > > Max_Read_Req_Size
> > >
> > > +                                        is successful.
> > >
> > > +**/
> > >
> > > +EFI_STATUS
> > >
> > > +ProcessMaxReadReqSize (
> > >
> > > +  IN  PCI_IO_DEVICE                           *PciDevice,
> > >
> > > +  IN  PCI_FEATURE_CONFIGURATION_PHASE         PciConfigPhase,
> > >
> > > +  IN  OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > > *PciFeaturesConfigurationTable
> > >
> > > +  )
> > >
> > > +{
> > >
> > > +  PCI_REG_PCIE_DEVICE_CAPABILITY  PciDeviceCap;
> > >
> > > +  UINT8                           MrrsValue;
> > >
> > > +
> > >
> > > +  PciDeviceCap.Uint32 = PciDevice->PciExpStruct.DeviceCapability.Uint32;
> > >
> > > +
> > >
> > > +  if ( PciConfigPhase == PciFeatureGetDevicePolicy) {
> > >
> > > +    if ( SetupMrrsAsPerDeviceCapability ( PciDevice->SetupMRRS))
> > >
> > > +    {
> > >
> > > +      //
> > >
> > > +      // The maximum read request size is not the data packet size of the
> > TLP,
> > >
> > > +      // but the memory read request size, and set to the function as a
> > > requestor
> > >
> > > +      // to not exceed this limit.
> > >
> > > +      // However, for the PCI device capable of isochronous traffic; this
> > > memory read
> > >
> > > +      // request size should not extend beyond the Max_Payload_Size. Thus,
> > > in case if
> > >
> > > +      // device policy return by platform indicates to set as per device
> > > capability
> > >
> > > +      // than set as per Max_Payload_Size configuration value
> > >
> > > +      //
> > >
> > > +      if ( SetupMaxPayloadSize()) {
> > >
> > > +        MrrsValue = PciDevice->SetupMPS;
> > >
> > > +      } else {
> > >
> > > +        //
> > >
> > > +        // in case this driver is not required to configure the
> > Max_Payload_Size
> > >
> > > +        // than consider programming HCF of the device capability's
> > > Max_Payload_Size
> > >
> > > +        // in this PCI hierarchy; thus making this an implementation specific
> > > feature
> > >
> > > +        // which the platform should avoid. For better results, the platform
> > > should
> > >
> > > +        // make both the Max_Payload_Size & Max_Read_Request_Size to
> > be
> > > configured
> > >
> > > +        // by this driver
> > >
> > > +        //
> > >
> > > +        MrrsValue = (UINT8)PciDeviceCap.Bits.MaxPayloadSize;
> > >
> > > +      }
> > >
> > > +    } else {
> > >
> > > +      //
> > >
> > > +      // override as per platform based device policy
> > >
> > > +      //
> > >
> > > +      MrrsValue = TranslateMrrsSetupValueToPci ( PciDevice->SetupMRRS);
> > >
> > > +      //
> > >
> > > +      // align this device's Max_Read_Request_Size value to the entire PCI
> > > tree
> > >
> > > +      //
> > >
> > > +      if ( PciFeaturesConfigurationTable) {
> > >
> > > +        if ( !PciFeaturesConfigurationTable->Lock_Max_Read_Request_Size)
> > {
> > >
> > > +          PciFeaturesConfigurationTable->Lock_Max_Read_Request_Size =
> > > TRUE;
> > >
> > > +          PciFeaturesConfigurationTable->Max_Read_Request_Size =
> > > MrrsValue;
> > >
> > > +        } else {
> > >
> > > +          //
> > >
> > > +          // in case of another user enforced value of MRRS within the same
> > > tree,
> > >
> > > +          // pick the smallest between the locked value and this value; to set
> > >
> > > +          // across entire PCI tree nodes
> > >
> > > +          //
> > >
> > > +          MrrsValue = MIN (
> > >
> > > +                        MrrsValue,
> > >
> > > +                        PciFeaturesConfigurationTable->Max_Read_Request_Size
> > >
> > > +                        );
> > >
> > > +          PciFeaturesConfigurationTable->Max_Read_Request_Size =
> > > MrrsValue;
> > >
> > > +        }
> > >
> > > +      }
> > >
> > > +    }
> > >
> > > +    //
> > >
> > > +    // align this device's Max_Read_Request_Size to derived configuration
> > > value
> > >
> > > +    //
> > >
> > > +    PciDevice->SetupMRRS = MrrsValue;
> > >
> > > +
> > >
> > > +  }
> > >
> > > +
> > >
> > > +  //
> > >
> > > +  // align the Max_Read_Request_Size of the PCI tree based on 3
> > conditions:
> > >
> > > +  // first, if user defines MRRS for any one PCI device in the tree than align
> > >
> > > +  // all the devices in the PCI tree.
> > >
> > > +  // second, if user override is not define for this PCI tree than setup the
> > > MRRS
> > >
> > > +  // based on MPS value of the tree to meet the criteria for the
> > isochronous
> > >
> > > +  // traffic.
> > >
> > > +  // third, if no user override, or platform firmware policy has not selected
> > >
> > > +  // this PCI bus driver to configure the MPS; than configure the MRRS to a
> > >
> > > +  // highest common value of PCI device capability for the MPS found
> > among
> > > all
> > >
> > > +  // the PCI devices in this tree
> > >
> > > +  //
> > >
> > > +  if ( PciFeaturesConfigurationTable) {
> > >
> > > +    if ( PciFeaturesConfigurationTable->Lock_Max_Read_Request_Size) {
> > >
> > > +      PciDevice->SetupMRRS = PciFeaturesConfigurationTable-
> > > >Max_Read_Request_Size;
> > >
> > > +    } else {
> > >
> > > +      if ( SetupMaxPayloadSize()) {
> > >
> > > +        PciDevice->SetupMRRS = PciDevice->SetupMPS;
> > >
> > > +      } else {
> > >
> > > +        PciDevice->SetupMRRS = MIN (
> > >
> > > +                                PciDevice->SetupMRRS,
> > >
> > > +                                PciFeaturesConfigurationTable-
> > >Max_Read_Request_Size
> > >
> > > +                                );
> > >
> > > +      }
> > >
> > > +      PciFeaturesConfigurationTable->Max_Read_Request_Size =
> > PciDevice-
> > > >SetupMRRS;
> > >
> > > +    }
> > >
> > > +  }
> > >
> > > +  DEBUG (( DEBUG_INFO, "Max_Read_Request_Size: %d\n", PciDevice-
> > > >SetupMRRS));
> > >
> > > +
> > >
> > > +  return EFI_SUCCESS;
> > >
> > > +}
> > >
> > > +
> > >
> > > +/**
> > >
> > > +  Overrides the PCI Device Control register MaxPayloadSize register field;
> > if
> > >
> > > +  the hardware value is different than the intended value.
> > >
> > > +
> > >
> > > +  @param  PciDevice             A pointer to the PCI_IO_DEVICE instance.
> > >
> > > +
> > >
> > > +  @retval EFI_SUCCESS           The data was read from or written to the PCI
> > > device.
> > >
> > > +  @retval EFI_UNSUPPORTED       The address range specified by Offset,
> > > Width, and Count is not
> > >
> > > +                                valid for the PCI configuration header of the PCI
> controller.
> > >
> > > +  @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid.
> > >
> > > +
> > >
> > > +**/
> > >
> > > +EFI_STATUS
> > >
> > > +OverrideMaxPayloadSize (
> > >
> > > +  IN PCI_IO_DEVICE          *PciDevice
> > >
> > > +  )
> > >
> > > +{
> > >
> > > +  PCI_REG_PCIE_DEVICE_CONTROL PcieDev;
> > >
> > > +  UINT32                      Offset;
> > >
> > > +  EFI_STATUS                  Status;
> > >
> > > +
> > >
> > > +  PcieDev.Uint16 = 0;
> > >
> > > +  Offset = PciDevice->PciExpressCapabilityOffset +
> > >
> > > +               OFFSET_OF (PCI_CAPABILITY_PCIEXP, DeviceControl);
> > >
> > > +  Status = PciDevice->PciIo.Pci.Read (
> > >
> > > +                                  &PciDevice->PciIo,
> > >
> > > +                                  EfiPciIoWidthUint16,
> > >
> > > +                                  Offset,
> > >
> > > +                                  1,
> > >
> > > +                                  &PcieDev.Uint16
> > >
> > > +                                );
> > >
> > > +  if ( EFI_ERROR(Status)){
> > >
> > > +    DEBUG (( DEBUG_ERROR, "Unexpected DeviceControl register (0x%x)
> > > read error!",
> > >
> > > +        Offset
> > >
> > > +    ));
> > >
> > > +    return Status;
> > >
> > > +  }
> > >
> > > +  if ( PcieDev.Bits.MaxPayloadSize != PciDevice->SetupMPS) {
> > >
> > > +    PcieDev.Bits.MaxPayloadSize = PciDevice->SetupMPS;
> > >
> > > +    DEBUG (( DEBUG_INFO, "Max_Payload_Size=%d,", PciDevice-
> > > >SetupMPS));
> > >
> > > +
> > >
> > > +    Status = PciDevice->PciIo.Pci.Write (
> > >
> > > +                                    &PciDevice->PciIo,
> > >
> > > +                                    EfiPciIoWidthUint16,
> > >
> > > +                                    Offset,
> > >
> > > +                                    1,
> > >
> > > +                                    &PcieDev.Uint16
> > >
> > > +                                  );
> > >
> > > +    if ( !EFI_ERROR(Status)) {
> > >
> > > +      PciDevice->PciExpStruct.DeviceControl.Uint16 = PcieDev.Uint16;
> > >
> > > +    } else {
> > >
> > > +      DEBUG (( DEBUG_ERROR, "Unexpected DeviceControl register (0x%x)
> > > write error!",
> > >
> > > +          Offset
> > >
> > > +      ));
> > >
> > > +    }
> > >
> > > +  } else {
> > >
> > > +    DEBUG (( DEBUG_INFO, "No write of Max_Payload_Size=%d,",
> > PciDevice-
> > > >SetupMPS));
> > >
> > > +  }
> > >
> > > +
> > >
> > > +  return Status;
> > >
> > > +}
> > >
> > > +
> > >
> > > +/**
> > >
> > > +  Overrides the PCI Device Control register MaxPayloadSize register field;
> > if
> > >
> > > +  the hardware value is different than the intended value.
> > >
> > > +
> > >
> > > +  @param  PciDevice             A pointer to the PCI_IO_DEVICE instance.
> > >
> > > +
> > >
> > > +  @retval EFI_SUCCESS           The data was read from or written to the PCI
> > > controller.
> > >
> > > +  @retval EFI_UNSUPPORTED       The address range specified by Offset,
> > > Width, and Count is not
> > >
> > > +                                valid for the PCI configuration header of the PCI
> controller.
> > >
> > > +  @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid.
> > >
> > > +
> > >
> > > +**/
> > >
> > > +EFI_STATUS
> > >
> > > +OverrideMaxReadReqSize (
> > >
> > > +  IN PCI_IO_DEVICE          *PciDevice
> > >
> > > +  )
> > >
> > > +{
> > >
> > > +  PCI_REG_PCIE_DEVICE_CONTROL PcieDev;
> > >
> > > +  UINT32                      Offset;
> > >
> > > +  EFI_STATUS                  Status;
> > >
> > > +
> > >
> > > +  PcieDev.Uint16 = 0;
> > >
> > > +  Offset = PciDevice->PciExpressCapabilityOffset +
> > >
> > > +               OFFSET_OF (PCI_CAPABILITY_PCIEXP, DeviceControl);
> > >
> > > +  Status = PciDevice->PciIo.Pci.Read (
> > >
> > > +                                  &PciDevice->PciIo,
> > >
> > > +                                  EfiPciIoWidthUint16,
> > >
> > > +                                  Offset,
> > >
> > > +                                  1,
> > >
> > > +                                  &PcieDev.Uint16
> > >
> > > +                                );
> > >
> > > +  if ( EFI_ERROR(Status)){
> > >
> > > +    DEBUG (( DEBUG_ERROR, "Unexpected DeviceControl register (0x%x)
> > > read error!",
> > >
> > > +        Offset
> > >
> > > +    ));
> > >
> > > +    return Status;
> > >
> > > +  }
> > >
> > > +  if ( PcieDev.Bits.MaxReadRequestSize != PciDevice->SetupMRRS) {
> > >
> > > +    PcieDev.Bits.MaxReadRequestSize = PciDevice->SetupMRRS;
> > >
> > > +    DEBUG (( DEBUG_INFO, "Max_Read_Request_Size: %d\n", PciDevice-
> > > >SetupMRRS));
> > >
> > > +
> > >
> > > +    Status = PciDevice->PciIo.Pci.Write (
> > >
> > > +                                    &PciDevice->PciIo,
> > >
> > > +                                    EfiPciIoWidthUint16,
> > >
> > > +                                    Offset,
> > >
> > > +                                    1,
> > >
> > > +                                    &PcieDev.Uint16
> > >
> > > +                                  );
> > >
> > > +    if ( !EFI_ERROR(Status)) {
> > >
> > > +      PciDevice->PciExpStruct.DeviceControl.Uint16 = PcieDev.Uint16;
> > >
> > > +    } else {
> > >
> > > +      DEBUG (( DEBUG_ERROR, "Unexpected DeviceControl register (0x%x)
> > > write error!",
> > >
> > > +          Offset
> > >
> > > +      ));
> > >
> > > +    }
> > >
> > > +  } else {
> > >
> > > +    DEBUG (( DEBUG_INFO, "No write of Max_Read_Request_Size=%d\n",
> > > PciDevice->SetupMRRS));
> > >
> > > +  }
> > >
> > > +
> > >
> > > +  return Status;
> > >
> > > +}
> > >
> > > +
> > >
> > > +/**
> > >
> > > +  helper routine to dump the PCIe Device Port Type
> > >
> > > +**/
> > >
> > > +VOID
> > >
> > > +DumpDevicePortType (
> > >
> > > +  IN  UINT8   DevicePortType
> > >
> > > +  )
> > >
> > > +{
> > >
> > > +  switch ( DevicePortType){
> > >
> > > +    case PCIE_DEVICE_PORT_TYPE_PCIE_ENDPOINT:
> > >
> > > +      DEBUG (( DEBUG_INFO, "PCIe endpoint found\n"));
> > >
> > > +      break;
> > >
> > > +    case PCIE_DEVICE_PORT_TYPE_LEGACY_PCIE_ENDPOINT:
> > >
> > > +      DEBUG (( DEBUG_INFO, "legacy PCI endpoint found\n"));
> > >
> > > +      break;
> > >
> > > +    case PCIE_DEVICE_PORT_TYPE_ROOT_PORT:
> > >
> > > +      DEBUG (( DEBUG_INFO, "PCIe Root Port found\n"));
> > >
> > > +      break;
> > >
> > > +    case PCIE_DEVICE_PORT_TYPE_UPSTREAM_PORT:
> > >
> > > +      DEBUG (( DEBUG_INFO, "PCI switch upstream port found\n"));
> > >
> > > +      break;
> > >
> > > +    case PCIE_DEVICE_PORT_TYPE_DOWNSTREAM_PORT:
> > >
> > > +      DEBUG (( DEBUG_INFO, "PCI switch downstream port found\n"));
> > >
> > > +      break;
> > >
> > > +    case PCIE_DEVICE_PORT_TYPE_PCIE_TO_PCI_BRIDGE:
> > >
> > > +      DEBUG (( DEBUG_INFO, "PCIe-PCI bridge found\n"));
> > >
> > > +      break;
> > >
> > > +    case PCIE_DEVICE_PORT_TYPE_PCI_TO_PCIE_BRIDGE:
> > >
> > > +      DEBUG (( DEBUG_INFO, "PCI-PCIe bridge found\n"));
> > >
> > > +      break;
> > >
> > > +    case
> > > PCIE_DEVICE_PORT_TYPE_ROOT_COMPLEX_INTEGRATED_ENDPOINT:
> > >
> > > +      DEBUG (( DEBUG_INFO, "RCiEP found\n"));
> > >
> > > +      break;
> > >
> > > +    case PCIE_DEVICE_PORT_TYPE_ROOT_COMPLEX_EVENT_COLLECTOR:
> > >
> > > +      DEBUG (( DEBUG_INFO, "RC Event Collector found\n"));
> > >
> > > +      break;
> > >
> > > +  }
> > >
> > > +}
> > >
> > > +
> > >
> > > +/**
> > >
> > > +   Process each PCI device as per the pltaform and device-specific policy.
> > >
> > > +
> > >
> > > +  @param RootBridge             A pointer to the PCI_IO_DEVICE.
> > >
> > > +
> > >
> > > +  @retval EFI_SUCCESS           processing each PCI feature as per policy
> > > defined
> > >
> > > +                                was successful.
> > >
> > > + **/
> > >
> > > +EFI_STATUS
> > >
> > > +SetupDevicePciFeatures (
> > >
> > > +  IN  PCI_IO_DEVICE                   *PciDevice,
> > >
> > > +  IN  PCI_FEATURE_CONFIGURATION_PHASE PciConfigPhase
> > >
> > > +  )
> > >
> > > +{
> > >
> > > +  EFI_STATUS                              Status;
> > >
> > > +  PCI_REG_PCIE_CAPABILITY                 PcieCap;
> > >
> > > +  OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > > *OtherPciFeaturesConfigTable;
> > >
> > > +
> > >
> > > +  PcieCap.Uint16 = PciDevice->PciExpStruct.Capability.Uint16;
> > >
> > > +  DumpDevicePortType ( (UINT8)PcieCap.Bits.DevicePortType);
> > >
> > > +
> > >
> > > +  OtherPciFeaturesConfigTable = NULL;
> > >
> > > +  Status = GetPciFeaturesConfigurationTable ( PciDevice,
> > > &OtherPciFeaturesConfigTable);
> > >
> > > +  if ( EFI_ERROR( Status)) {
> > >
> > > +    DEBUG ((
> > >
> > > +        EFI_D_WARN, "No primary root port found in these root bridge
> > > nodes!\n"
> > >
> > > +    ));
> > >
> > > +  } else if ( !OtherPciFeaturesConfigTable) {
> > >
> > > +    DEBUG ((
> > >
> > > +        DEBUG_INFO, "No PCI features config. table for this device!\n"
> > >
> > > +    ));
> > >
> > > +  } else {
> > >
> > > +    DEBUG ((
> > >
> > > +        DEBUG_INFO, "using PCI features config. table ID: %d\n",
> > >
> > > +        OtherPciFeaturesConfigTable->ID
> > >
> > > +    ));
> > >
> > > +  }
> > >
> > > +
> > >
> > > +  if ( PciConfigPhase == PciFeatureGetDevicePolicy) {
> > >
> > > +    Status = GetPciDevicePlatformPolicy ( PciDevice);
> > >
> > > +    if ( EFI_ERROR(Status)) {
> > >
> > > +      DEBUG ((
> > >
> > > +          DEBUG_ERROR, "Error in obtaining PCI device policy!!!\n"
> > >
> > > +      ));
> > >
> > > +    }
> > >
> > > +  }
> > >
> > > +
> > >
> > > +  if ( SetupMaxPayloadSize ()) {
> > >
> > > +    Status = ProcessMaxPayloadSize (
> > >
> > > +              PciDevice,
> > >
> > > +              PciConfigPhase,
> > >
> > > +              OtherPciFeaturesConfigTable
> > >
> > > +              );
> > >
> > > +  }
> > >
> > > +  //
> > >
> > > +  // implementation specific rule:- the MRRS of any PCI device should be
> > > processed
> > >
> > > +  // only after the MPS is processed for that device
> > >
> > > +  //
> > >
> > > +  if ( SetupMaxReadReqSize ()) {
> > >
> > > +    Status = ProcessMaxReadReqSize (
> > >
> > > +              PciDevice,
> > >
> > > +              PciConfigPhase,
> > >
> > > +              OtherPciFeaturesConfigTable
> > >
> > > +              );
> > >
> > > +  }
> > >
> > > +  return Status;
> > >
> > > +}
> > >
> > > +
> > >
> > > +/**
> > >
> > > +  Traverse all the nodes from the root bridge or PCI-PCI bridge instance, to
> > >
> > > +  configure the PCI features as per the device-specific platform policy, and
> > >
> > > +  as per the device capability, as applicable.
> > >
> > > +
> > >
> > > +  @param RootBridge             A pointer to the PCI_IO_DEVICE.
> > >
> > > +
> > >
> > > +  @retval EFI_SUCCESS           Traversing all the nodes of the root bridge
> > >
> > > +                                instances were successfull.
> > >
> > > +**/
> > >
> > > +EFI_STATUS
> > >
> > > +SetupPciFeatures (
> > >
> > > +  IN  PCI_IO_DEVICE                   *RootBridge,
> > >
> > > +  IN  PCI_FEATURE_CONFIGURATION_PHASE PciConfigPhase
> > >
> > > +  )
> > >
> > > +{
> > >
> > > +  EFI_STATUS           Status;
> > >
> > > +  LIST_ENTRY           *Link;
> > >
> > > +  PCI_IO_DEVICE        *Device;
> > >
> > > +
> > >
> > > +  for ( Link = RootBridge->ChildList.ForwardLink
> > >
> > > +      ; Link != &RootBridge->ChildList
> > >
> > > +      ; Link = Link->ForwardLink
> > >
> > > +  ) {
> > >
> > > +    Device = PCI_IO_DEVICE_FROM_LINK (Link);
> > >
> > > +    if (IS_PCI_BRIDGE (&Device->Pci)) {
> > >
> > > +      DEBUG ((
> > >
> > > +          DEBUG_INFO, "::Bridge [%02x|%02x|%02x] -",
> > >
> > > +          Device->BusNumber, Device->DeviceNumber, Device-
> > > >FunctionNumber
> > >
> > > +      ));
> > >
> > > +      if (Device->IsPciExp) {
> > >
> > > +        Status = SetupDevicePciFeatures ( Device, PciConfigPhase);
> > >
> > > +      } else {
> > >
> > > +        DEBUG (( DEBUG_INFO, "Not a PCIe capable device!\n"));
> > >
> > > +        //
> > >
> > > +        // PCI Bridge which does not have PCI Express Capability structure
> > >
> > > +        // cannot process this kind of PCI Bridge device
> > >
> > > +        //
> > >
> > > +
> > >
> > > +      }
> > >
> > > +
> > >
> > > +      SetupPciFeatures ( Device, PciConfigPhase);
> > >
> > > +    } else {
> > >
> > > +      DEBUG ((
> > >
> > > +          DEBUG_INFO, "::Device [%02x|%02x|%02x] -",
> > >
> > > +          Device->BusNumber, Device->DeviceNumber, Device-
> > > >FunctionNumber
> > >
> > > +      ));
> > >
> > > +      if (Device->IsPciExp) {
> > >
> > > +
> > >
> > > +        Status = SetupDevicePciFeatures ( Device, PciConfigPhase);
> > >
> > > +      } else {
> > >
> > > +        DEBUG (( DEBUG_INFO, "Not a PCIe capable device!\n"));
> > >
> > > +        //
> > >
> > > +        // PCI Device which does not have PCI Express Capability structure
> > >
> > > +        // cannot process this kind of PCI device
> > >
> > > +        //
> > >
> > > +      }
> > >
> > > +    }
> > >
> > > +  }
> > >
> > > +
> > >
> > > +  return EFI_SUCCESS;
> > >
> > > +}
> > >
> > > +
> > >
> > > +/**
> > >
> > > +  Program the PCI device, to override the PCI features as per the policy,
> > >
> > > +  resolved from previous traverse.
> > >
> > > +
> > >
> > > +  @param RootBridge             A pointer to the PCI_IO_DEVICE.
> > >
> > > +
> > >
> > > +  @retval EFI_SUCCESS           The other PCI features configuration during
> > > enumeration
> > >
> > > +                                of all the nodes of the PCI root bridge instance were
> > >
> > > +                                programmed in PCI-compliance pattern along with the
> > >
> > > +                                device-specific policy, as applicable.
> > >
> > > +  @retval EFI_UNSUPPORTED       One of the override operation maong the
> > > nodes of
> > >
> > > +                                the PCI hierarchy resulted in a incompatible address
> > >
> > > +                                range.
> > >
> > > +  @retval EFI_INVALID_PARAMETER The override operation is performed
> > > with invalid input
> > >
> > > +                                parameters.
> > >
> > > +**/
> > >
> > > +EFI_STATUS
> > >
> > > +ProgramDevicePciFeatures (
> > >
> > > +  IN PCI_IO_DEVICE          *PciDevice
> > >
> > > +  )
> > >
> > > +{
> > >
> > > +  EFI_STATUS           Status;
> > >
> > > +
> > >
> > > +  if ( SetupMaxPayloadSize ()) {
> > >
> > > +    Status = OverrideMaxPayloadSize (PciDevice);
> > >
> > > +  }
> > >
> > > +  if ( SetupMaxReadReqSize ()) {
> > >
> > > +    Status = OverrideMaxReadReqSize (PciDevice);
> > >
> > > +  }
> > >
> > > +  return Status;
> > >
> > > +}
> > >
> > > +
> > >
> > > +/**
> > >
> > > +  Program all the nodes of the specified root bridge or PCI-PCI Bridge, to
> > >
> > > +  override the PCI features.
> > >
> > > +
> > >
> > > +  @param RootBridge             A pointer to the PCI_IO_DEVICE.
> > >
> > > +
> > >
> > > +  @retval EFI_SUCCESS           The other PCI features configuration during
> > > enumeration
> > >
> > > +                                of all the nodes of the PCI root bridge instance were
> > >
> > > +                                programmed in PCI-compliance pattern along with the
> > >
> > > +                                device-specific policy, as applicable.
> > >
> > > +  @retval EFI_UNSUPPORTED       One of the override operation maong the
> > > nodes of
> > >
> > > +                                the PCI hierarchy resulted in a incompatible address
> > >
> > > +                                range.
> > >
> > > +  @retval EFI_INVALID_PARAMETER The override operation is performed
> > > with invalid input
> > >
> > > +                                parameters.
> > >
> > > +**/
> > >
> > > +EFI_STATUS
> > >
> > > +ProgramPciFeatures (
> > >
> > > +  IN PCI_IO_DEVICE          *RootBridge
> > >
> > > +  )
> > >
> > > +{
> > >
> > > +  EFI_STATUS           Status;
> > >
> > > +  LIST_ENTRY           *Link;
> > >
> > > +  PCI_IO_DEVICE        *Device;
> > >
> > > +
> > >
> > > +  for ( Link = RootBridge->ChildList.ForwardLink
> > >
> > > +      ; Link != &RootBridge->ChildList
> > >
> > > +      ; Link = Link->ForwardLink
> > >
> > > +  ) {
> > >
> > > +    Device = PCI_IO_DEVICE_FROM_LINK (Link);
> > >
> > > +    if (IS_PCI_BRIDGE (&Device->Pci)) {
> > >
> > > +      DEBUG ((
> > >
> > > +          DEBUG_INFO, "::Bridge [%02x|%02x|%02x] -",
> > >
> > > +          Device->BusNumber, Device->DeviceNumber, Device-
> > > >FunctionNumber
> > >
> > > +      ));
> > >
> > > +      if (Device->IsPciExp) {
> > >
> > > +        DEBUG (( DEBUG_INFO, "ready to override!\n"));
> > >
> > > +
> > >
> > > +        Status = ProgramDevicePciFeatures ( Device);
> > >
> > > +      } else {
> > >
> > > +        DEBUG (( DEBUG_INFO, "skipped!\n"));
> > >
> > > +        //
> > >
> > > +        // PCI Bridge which does not have PCI Express Capability structure
> > >
> > > +        // cannot process this kind of PCI Bridge device
> > >
> > > +        //
> > >
> > > +
> > >
> > > +      }
> > >
> > > +
> > >
> > > +      Status = ProgramPciFeatures ( Device);
> > >
> > > +    } else {
> > >
> > > +      DEBUG ((
> > >
> > > +          DEBUG_INFO, "::Device [%02x|%02x|%02x] -",
> > >
> > > +          Device->BusNumber, Device->DeviceNumber, Device-
> > > >FunctionNumber
> > >
> > > +      ));
> > >
> > > +      if (Device->IsPciExp) {
> > >
> > > +        DEBUG (( DEBUG_INFO, "ready to override!\n"));
> > >
> > > +
> > >
> > > +        Status = ProgramDevicePciFeatures ( Device);
> > >
> > > +      } else {
> > >
> > > +        DEBUG (( DEBUG_INFO, "skipped!\n"));
> > >
> > > +        //
> > >
> > > +        // PCI Device which does not have PCI Express Capability structure
> > >
> > > +        // cannot process this kind of PCI device
> > >
> > > +        //
> > >
> > > +      }
> > >
> > > +    }
> > >
> > > +  }
> > >
> > > +
> > >
> > > +  return Status;
> > >
> > > +}
> > >
> > > +
> > >
> > > +/**
> > >
> > > +  Create a node of type PRIMARY_ROOT_PORT_NODE for the given PCI
> > > device, and
> > >
> > > +  assigns EFI handles of its Root Bridge and its own, along with its PCI Bus
> > >
> > > +  range for the secondary and subordinate bus range.
> > >
> > > +
> > >
> > > +  @param  RootBridge          A pointer to the PCI_IO_DEVICE for its PCI Root
> > > Bridge
> > >
> > > +  @param  Device              A pointer to the PCI_IO_DEVICE for the PCI
> > > controller
> > >
> > > +  @param  RootPortSecBus      PCI controller's Secondary Bus number
> > >
> > > +  @param  RootPortSubBus      PCI controller's Subordinate Bus number
> > >
> > > +  @param  PrimaryRootPortNode A pointer to the
> > > PRIMARY_ROOT_PORT_NODE to return
> > >
> > > +                              the newly created node for the PCI controller. In
> > >
> > > +                              case of error nothing is return in this.
> > >
> > > +
> > >
> > > +  @retval EFI_SUCCESS           new node of PRIMARY_ROOT_PORT_NODE is
> > > returned for
> > >
> > > +                                the PCI controller
> > >
> > > +          EFI_OUT_OF_RESOURCES  unable to create the node for the PCI
> > > controller
> > >
> > > +          EFI_INVALID_PARAMETER unable to store the node as the input
> > > buffer is
> > >
> > > +                                not empty (*PrimaryRootPortNode)
> > >
> > > +**/
> > >
> > > +EFI_STATUS
> > >
> > > +CreatePrimaryPciRootPortNode (
> > >
> > > +  IN  PCI_IO_DEVICE           *RootBridge,
> > >
> > > +  IN  PCI_IO_DEVICE           *Device,
> > >
> > > +  IN  UINT8                   RootPortSecBus,
> > >
> > > +  IN  UINT8                   RootPortSubBus,
> > >
> > > +  OUT PRIMARY_ROOT_PORT_NODE  **PrimaryRootPortNode
> > >
> > > +  )
> > >
> > > +{
> > >
> > > +  PRIMARY_ROOT_PORT_NODE      *RootPortNode = NULL;
> > >
> > > +
> > >
> > > +  if ( !*PrimaryRootPortNode) {
> > >
> > > +    RootPortNode                    = AllocateZeroPool ( sizeof
> > > (PRIMARY_ROOT_PORT_NODE));
> > >
> > > +    if ( RootPortNode == NULL) {
> > >
> > > +      return EFI_OUT_OF_RESOURCES;
> > >
> > > +    }
> > >
> > > +    RootPortNode->Signature         = PCI_ROOT_PORT_SIGNATURE;
> > >
> > > +    RootPortNode->RootBridgeHandle  = RootBridge->Handle;
> > >
> > > +    RootPortNode->RootPortHandle    = Device->Handle;
> > >
> > > +    RootPortNode->SecondaryBusStart = RootPortSecBus;
> > >
> > > +    RootPortNode->SecondaryBusEnd   = RootPortSubBus;
> > >
> > > +    InitializeListHead ( &RootPortNode->NeighborRootPort);
> > >
> > > +    *PrimaryRootPortNode = RootPortNode;
> > >
> > > +    return EFI_SUCCESS;
> > >
> > > +  } else {
> > >
> > > +    return EFI_INVALID_PARAMETER;
> > >
> > > +  }
> > >
> > > +}
> > >
> > > +
> > >
> > > +/**
> > >
> > > +  Checks to report whether the input PCI controller's secondary /
> > > subordinate
> > >
> > > +  bus numbers are within the recorded list of other PCI controllers (root
> > > ports).
> > >
> > > +
> > >
> > > +  @param  RootPortNode      A pointer to the first node of
> > > PRIMARY_ROOT_PORT_NODE
> > >
> > > +  @param  RootPortSecBus    PCI secondary bus number of the PCI
> > controller
> > > found
> > >
> > > +  @param  RootPortSubBus    PCI subordinate bus number of the PCI Root
> > > Port found
> > >
> > > +
> > >
> > > +  @retval TRUE              A child PCI Root port found
> > >
> > > +          FALSE             A new PCI controller found
> > >
> > > +**/
> > >
> > > +BOOLEAN
> > >
> > > +CheckChildRootPort (
> > >
> > > +  IN      PRIMARY_ROOT_PORT_NODE  *RootPortNode,
> > >
> > > +  IN      UINT8                   RootPortSecBus,
> > >
> > > +  IN      UINT8                   RootPortSubBus
> > >
> > > +)
> > >
> > > +{
> > >
> > > +  LIST_ENTRY              *Link;
> > >
> > > +  PRIMARY_ROOT_PORT_NODE  *Temp;
> > >
> > > +
> > >
> > > +  if ( !RootPortNode) {
> > >
> > > +    return FALSE;
> > >
> > > +  }
> > >
> > > +  Link = &RootPortNode->NeighborRootPort;
> > >
> > > +  do {
> > >
> > > +    Temp = PRIMARY_ROOT_PORT_NODE_FROM_LINK ( Link);
> > >
> > > +    if ( RootPortSecBus >= Temp->SecondaryBusStart
> > >
> > > +        && RootPortSubBus <= Temp->SecondaryBusEnd) {
> > >
> > > +      //
> > >
> > > +      // given root port's secondary & subordinate within its primary ports
> > >
> > > +      // hence return as child port
> > >
> > > +      //
> > >
> > > +      return TRUE;
> > >
> > > +    }
> > >
> > > +    Link = Link->ForwardLink;
> > >
> > > +  } while (Link != &RootPortNode->NeighborRootPort);
> > >
> > > +  //
> > >
> > > +  // the given root port's secondary / subordinate bus numbers do not
> > > belong to
> > >
> > > +  // any existing primary root port's bus range hence consider another
> > > primary
> > >
> > > +  // root port of the root bridge controller
> > >
> > > +  //
> > >
> > > +  return FALSE;
> > >
> > > +}
> > >
> > > +
> > >
> > > +/**
> > >
> > > +  Create the vector of PCI Feature configuration table as per the number
> > of
> > >
> > > +  the PCI Root Ports given, assigns default value to the PCI features
> > > supported
> > >
> > > +  and assign its address to the global variable
> > > "mPciFeaturesConfigurationTableInstances".
> > >
> > > +
> > >
> > > +  @param  NumberOfRootPorts   An input arguement of UINTN to indicate
> > > number of
> > >
> > > +                              primary PCI physical Root Bridge devices found
> > >
> > > +
> > >
> > > +  @retval EFI_OUT_OF_RESOURCES  unable to allocate buffer to store PCI
> > > feature
> > >
> > > +                                configuration table for all the physical PCI root
> > >
> > > +                                ports given
> > >
> > > +          EFI_SUCCESS           PCI Feature COnfiguration table created for all
> > >
> > > +                                the PCI Rooot ports reported
> > >
> > > + */
> > >
> > > +EFI_STATUS
> > >
> > > +CreatePciFeaturesConfigurationTableInstances (
> > >
> > > +  IN  UINTN NumberOfRootPorts
> > >
> > > +  )
> > >
> > > +{
> > >
> > > +  OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > > *PciRootBridgePortFeatures = NULL;
> > >
> > > +  UINTN                                     Instances;
> > >
> > > +
> > >
> > > +  PciRootBridgePortFeatures = AllocateZeroPool (
> > >
> > > +                                sizeof ( OTHER_PCI_FEATURES_CONFIGURATION_TABLE)
> > *
> > > NumberOfRootPorts
> > >
> > > +                                );
> > >
> > > +  if ( !PciRootBridgePortFeatures) {
> > >
> > > +    return EFI_OUT_OF_RESOURCES;
> > >
> > > +  }
> > >
> > > +
> > >
> > > +  for ( Instances = 0; Instances < NumberOfRootPorts; Instances++) {
> > >
> > > +    PciRootBridgePortFeatures [Instances].ID                    = Instances + 1;
> > >
> > > +    PciRootBridgePortFeatures [Instances].Max_Payload_Size      =
> > > PCIE_MAX_PAYLOAD_SIZE_4096B;
> > >
> > > +    PciRootBridgePortFeatures [Instances].Max_Read_Request_Size =
> > > PCIE_MAX_READ_REQ_SIZE_4096B;
> > >
> > > +    PciRootBridgePortFeatures [Instances].Lock_Max_Read_Request_Size
> > =
> > > FALSE;
> > >
> > > +  }
> > >
> > > +  mPciFeaturesConfigurationTableInstances = PciRootBridgePortFeatures;
> > >
> > > +  return EFI_SUCCESS;
> > >
> > > +}
> > >
> > > +
> > >
> > > +/**
> > >
> > > +  This routine pairs the each PCI Root Port node with one of the PCI
> > Feature
> > >
> > > +  Configuration Table node. Each physical PCI Root Port has its own PCI
> > > feature
> > >
> > > +  configuration table which will used for aligning all its downstream
> > > components.
> > >
> > > +
> > >
> > > +  @param  NumberOfRootPorts     inputs the number of physical PCI root
> > > ports
> > >
> > > +                                found on the Root bridge instance
> > >
> > > +
> > >
> > > +  @retval EFI_INVALID_PARAMETER if the primary PCI root ports list is
> > > vacant when
> > >
> > > +                                there is one or more PCI Root port indicated as per
> > >
> > > +                                input parameter
> > >
> > > +          EFI_UNSUPPORTED       The PCI Root Port nodes not paired equally
> > with
> > >
> > > +                                the PCI Configuration Table nodes
> > >
> > > +          EFI_SUCCESS           each PCI feature configuration node is paired
> > > equally
> > >
> > > +                                with each PCI Root port in the list
> > >
> > > +**/
> > >
> > > +EFI_STATUS
> > >
> > > +AssignPciFeaturesConfigurationTable (
> > >
> > > +  IN  UINTN NumberOfRootPorts
> > >
> > > +  )
> > >
> > > +{
> > >
> > > +  UINTN                       Instances;
> > >
> > > +  LIST_ENTRY                  *Link;
> > >
> > > +  PRIMARY_ROOT_PORT_NODE      *Temp;
> > >
> > > +
> > >
> > > +  if ( !mPrimaryRootPortList
> > >
> > > +      && NumberOfRootPorts) {
> > >
> > > +    DEBUG ((
> > >
> > > +        DEBUG_ERROR,
> > >
> > > +        "Critical error! no internal table setup for %d PCI Root ports \n",
> > >
> > > +        NumberOfRootPorts
> > >
> > > +    ));
> > >
> > > +    return EFI_INVALID_PARAMETER;
> > >
> > > +  }
> > >
> > > +
> > >
> > > +  if ( NumberOfRootPorts) {
> > >
> > > +    Link = &mPrimaryRootPortList->NeighborRootPort;
> > >
> > > +    for ( Instances = 0
> > >
> > > +        ; (Instances < NumberOfRootPorts)
> > >
> > > +        ; Instances++
> > >
> > > +    ) {
> > >
> > > +      Temp = PRIMARY_ROOT_PORT_NODE_FROM_LINK ( Link);
> > >
> > > +      Temp->OtherPciFeaturesConfigurationTable =
> > > &mPciFeaturesConfigurationTableInstances [Instances];
> > >
> > > +      DEBUG ((
> > >
> > > +          DEBUG_INFO,
> > >
> > > +          "Assigned to %dth primary root port\n",
> > >
> > > +          Instances
> > >
> > > +      ));
> > >
> > > +
> > >
> > > +      Link = Link->ForwardLink;
> > >
> > > +    }
> > >
> > > +    if ( Link != &mPrimaryRootPortList->NeighborRootPort) {
> > >
> > > +      DEBUG ((
> > >
> > > +          DEBUG_ERROR,
> > >
> > > +          "Error!! PCI Root Port list is not properly matched with Config., Table
> > > list \n"
> > >
> > > +      ));
> > >
> > > +      return EFI_UNSUPPORTED;
> > >
> > > +    }
> > >
> > > +  }
> > >
> > > +  return  EFI_SUCCESS;
> > >
> > > +}
> > >
> > > +
> > >
> > > +/**
> > >
> > > +  Prepare each PCI Controller (Root Port) with its own PCI Feature
> > > configuration
> > >
> > > +  table node that can be used for tracking to align all PCI nodes in its
> > > hierarchy.
> > >
> > > +
> > >
> > > +  @param  PrimaryRootPorts      A pointer to PRIMARY_ROOT_PORT_NODE
> > >
> > > +  @param  NumberOfRootPorts     Total number of pysical primary PCI
> > Root
> > > ports
> > >
> > > +
> > >
> > > +  @retval EFI_OUT_OF_RESOURCES  unable to allocate buffer to store PCI
> > > feature
> > >
> > > +                                configuration table for all the physical PCI root
> > >
> > > +                                ports given
> > >
> > > +          EFI_INVALID_PARAMETER if the primary PCI root ports list is vacant
> > > when
> > >
> > > +                                there is one or more PCI Root port indicated as per
> > >
> > > +                                input parameter
> > >
> > > +          EFI_UNSUPPORTED       The PCI Root Port nodes not paired equally
> > with
> > >
> > > +                                the PCI Configuration Table nodes
> > >
> > > +          EFI_SUCCESS           each PCI feature configuration node is paired
> > > equally
> > >
> > > +                                with each PCI Root port in the list
> > >
> > > +**/
> > >
> > > +EFI_STATUS
> > >
> > > +PreparePciControllerConfigurationTable (
> > >
> > > +  IN  PRIMARY_ROOT_PORT_NODE    *PrimaryRootPorts,
> > >
> > > +  IN  UINTN                     NumberOfRootPorts
> > >
> > > +  )
> > >
> > > +{
> > >
> > > +  EFI_STATUS                    Status;
> > >
> > > +
> > >
> > > +  mPrimaryRootPortList = PrimaryRootPorts;
> > >
> > > +  DEBUG ((
> > >
> > > +      DEBUG_INFO, "Number of primary Root Ports found on this bridge
> > > = %d\n",
> > >
> > > +      NumberOfRootPorts
> > >
> > > +  ));
> > >
> > > +
> > >
> > > +  Status = CreatePciFeaturesConfigurationTableInstances
> > > ( NumberOfRootPorts);
> > >
> > > +  if ( EFI_ERROR(Status)) {
> > >
> > > +    DEBUG ((
> > >
> > > +        DEBUG_ERROR, "Unexpected memory node creation error for PCI
> > > features!\n"
> > >
> > > +    ));
> > >
> > > +  } else {
> > >
> > > +    //
> > >
> > > +    // align the primary root port nodes list with the PCI Feature
> > configuration
> > >
> > > +    // table. Note that the PCI Feature configuration table is not maintain
> > for
> > >
> > > +    // the RCiEP devices
> > >
> > > +    //
> > >
> > > +    Status = AssignPciFeaturesConfigurationTable ( NumberOfRootPorts);
> > >
> > > +  }
> > >
> > > +  return Status;
> > >
> > > +}
> > >
> > > +
> > >
> > > +/**
> > >
> > > +  Scan all the nodes of the RootBridge to identify and create a separate list
> > >
> > > +  of all primary physical PCI root ports and link each with its own instance
> > of
> > >
> > > +  the PCI Feature Configuration Table.
> > >
> > > +
> > >
> > > +  @param  RootBridge    A pointer to the PCI_IO_DEVICE of the PCI Root
> > > Bridge
> > >
> > > +
> > >
> > > +  @retval EFI_OUT_OF_RESOURCES  unable to allocate buffer to store PCI
> > > feature
> > >
> > > +                                configuration table for all the physical PCI root
> > >
> > > +                                ports given
> > >
> > > +          EFI_NOT_FOUND         No PCI Bridge device found
> > >
> > > +          EFI_SUCCESS           PCI Feature COnfiguration table created for all
> > >
> > > +                                the PCI Rooot ports found
> > >
> > > +          EFI_INVALID_PARAMETER invalid parameter passed to the routine
> > > which
> > >
> > > +                                creates the PCI controller node for the primary
> > >
> > > +                                Root post list
> > >
> > > +**/
> > >
> > > +EFI_STATUS
> > >
> > > +RecordPciRootPortBridges (
> > >
> > > +  IN  PCI_IO_DEVICE           *RootBridge
> > >
> > > +  )
> > >
> > > +{
> > >
> > > +  EFI_STATUS              Status = EFI_NOT_FOUND;
> > >
> > > +  LIST_ENTRY              *Link;
> > >
> > > +  PCI_IO_DEVICE           *Device;
> > >
> > > +  UINTN                   NumberOfRootPorts;
> > >
> > > +  PRIMARY_ROOT_PORT_NODE  *PrimaryRootPorts,
> > >
> > > +                          *TempNode;
> > >
> > > +  UINT8                   RootPortSecBus,
> > >
> > > +                          RootPortSubBus;
> > >
> > > +
> > >
> > > +  DEBUG ((
> > >
> > > +      DEBUG_INFO, "<<********** RecordPciRootPortBridges -start
> > > *************>>\n"
> > >
> > > +  ));
> > >
> > > +  NumberOfRootPorts = 0;
> > >
> > > +  PrimaryRootPorts = NULL;
> > >
> > > +  for ( Link = RootBridge->ChildList.ForwardLink
> > >
> > > +      ; Link != &RootBridge->ChildList
> > >
> > > +      ; Link = Link->ForwardLink
> > >
> > > +  ) {
> > >
> > > +    Device = PCI_IO_DEVICE_FROM_LINK (Link);
> > >
> > > +    if (IS_PCI_BRIDGE (&Device->Pci)) {
> > >
> > > +      Status = GetPciRootPortBusAssigned (
> > >
> > > +                  Device,
> > >
> > > +                  NULL,
> > >
> > > +                  &RootPortSecBus,
> > >
> > > +                  &RootPortSubBus
> > >
> > > +                  );
> > >
> > > +      if ( !EFI_ERROR(Status)) {
> > >
> > > +        DEBUG ((
> > >
> > > +            DEBUG_INFO, "::Device [%02x|%02x|%02x] - SecBus=0x%x,
> > > SubBus=0x%x\n",
> > >
> > > +            Device->BusNumber, Device->DeviceNumber, Device-
> > > >FunctionNumber,
> > >
> > > +            RootPortSecBus, RootPortSubBus
> > >
> > > +        ));
> > >
> > > +      } else {
> > >
> > > +        DEBUG ((
> > >
> > > +            DEBUG_ERROR, "Unexpected read error [0x%lx]::Device
> > > [%02x|%02x|%02x]\n",
> > >
> > > +            Status, Device->BusNumber, Device->DeviceNumber, Device-
> > > >FunctionNumber
> > >
> > > +        ));
> > >
> > > +        RootPortSecBus = RootPortSubBus = 0;
> > >
> > > +        continue;
> > >
> > > +      }
> > >
> > > +
> > >
> > > +      if ( !PrimaryRootPorts) {
> > >
> > > +        NumberOfRootPorts++;
> > >
> > > +        Status = CreatePrimaryPciRootPortNode (
> > >
> > > +                    RootBridge,
> > >
> > > +                    Device,
> > >
> > > +                    RootPortSecBus,
> > >
> > > +                    RootPortSubBus,
> > >
> > > +                    &PrimaryRootPorts
> > >
> > > +                    );
> > >
> > > +        if ( EFI_ERROR(Status)) {
> > >
> > > +          //
> > >
> > > +          // abort mission to scan for all primary roots ports of a bridge
> > >
> > > +          // controller if error encountered for very first PCI primary root port
> > >
> > > +          //
> > >
> > > +          DEBUG ((
> > >
> > > +              DEBUG_ERROR, "Unexpected node creation error [0x%lx]::Device
> > > [%02x|%02x|%02x]\n",
> > >
> > > +              Status, Device->BusNumber, Device->DeviceNumber, Device-
> > > >FunctionNumber
> > >
> > > +          ));
> > >
> > > +          return Status;
> > >
> > > +        }
> > >
> > > +        DEBUG ((
> > >
> > > +            DEBUG_INFO, "first primary root port found::Device
> > > [%02x|%02x|%02x]\n",
> > >
> > > +            Device->BusNumber, Device->DeviceNumber, Device-
> > > >FunctionNumber
> > >
> > > +        ));
> > >
> > > +      } else {
> > >
> > > +        if ( !CheckChildRootPort ( PrimaryRootPorts, RootPortSecBus,
> > > RootPortSubBus)) {
> > >
> > > +          NumberOfRootPorts++;
> > >
> > > +          TempNode = NULL;
> > >
> > > +          Status = CreatePrimaryPciRootPortNode (
> > >
> > > +                      RootBridge,
> > >
> > > +                      Device,
> > >
> > > +                      RootPortSecBus,
> > >
> > > +                      RootPortSubBus,
> > >
> > > +                      &TempNode
> > >
> > > +                      );
> > >
> > > +          if ( !EFI_ERROR(Status)) {
> > >
> > > +            //
> > >
> > > +            // another primary root port found on the same bridge controller
> > >
> > > +            // insert in the node list
> > >
> > > +            //
> > >
> > > +            InsertTailList ( &PrimaryRootPorts->NeighborRootPort,
> > &TempNode-
> > > >NeighborRootPort);
> > >
> > > +            DEBUG ((
> > >
> > > +                DEBUG_INFO, "next primary root port found::Device
> > > [%02x|%02x|%02x]\n",
> > >
> > > +                Device->BusNumber, Device->DeviceNumber, Device-
> > > >FunctionNumber
> > >
> > > +            ));
> > >
> > > +          } else {
> > >
> > > +            DEBUG ((
> > >
> > > +                DEBUG_ERROR, "Unexpected node creation error [0x%lx]::Device
> > > [%02x|%02x|%02x]\n",
> > >
> > > +                Status, Device->BusNumber, Device->DeviceNumber, Device-
> > > >FunctionNumber
> > >
> > > +            ));
> > >
> > > +          }
> > >
> > > +        }
> > >
> > > +      }
> > >
> > > +    }
> > >
> > > +  }
> > >
> > > +  //
> > >
> > > +  // prepare the PCI root port and its feature configuration table list
> > >
> > > +  //
> > >
> > > +  if ( NumberOfRootPorts) {
> > >
> > > +    Status = PreparePciControllerConfigurationTable (
> > >
> > > +                PrimaryRootPorts,
> > >
> > > +                NumberOfRootPorts
> > >
> > > +              );
> > >
> > > +
> > >
> > > +  } else {
> > >
> > > +    DEBUG ((
> > >
> > > +        DEBUG_INFO, "No PCI Root port found on this bridge!\n"
> > >
> > > +    ));
> > >
> > > +  }
> > >
> > > +
> > >
> > > +  DEBUG ((
> > >
> > > +      DEBUG_INFO, "<<********** RecordPciRootPortBridges - end
> > > **********>>\n"
> > >
> > > +  ));
> > >
> > > +  return Status;
> > >
> > > +}
> > >
> > > +
> > >
> > > +/**
> > >
> > > +  Enumerate all the nodes of the specified root bridge or PCI-PCI Bridge, to
> > >
> > > +  configure the other PCI features.
> > >
> > > +
> > >
> > > +  @param RootBridge          A pointer to the PCI_IO_DEVICE.
> > >
> > > +
> > >
> > > +  @retval EFI_SUCCESS           The other PCI features configuration during
> > > enumeration
> > >
> > > +                                of all the nodes of the PCI root bridge instance were
> > >
> > > +                                programmed in PCI-compliance pattern along with the
> > >
> > > +                                device-specific policy, as applicable.
> > >
> > > +  @retval EFI_UNSUPPORTED       One of the override operation maong the
> > > nodes of
> > >
> > > +                                the PCI hierarchy resulted in a incompatible address
> > >
> > > +                                range.
> > >
> > > +  @retval EFI_INVALID_PARAMETER The override operation is performed
> > > with invalid input
> > >
> > > +                                parameters.
> > >
> > > +**/
> > >
> > > +EFI_STATUS
> > >
> > > +EnumerateOtherPciFeatures (
> > >
> > > +  IN PCI_IO_DEVICE          *RootBridge
> > >
> > > +  )
> > >
> > > +{
> > >
> > > +  EFI_STATUS            Status;
> > >
> > > +  CHAR16                *Str;
> > >
> > > +  UINTN                 OtherPciFeatureConfigPhase;
> > >
> > > +
> > >
> > > +  //
> > >
> > > +  // check on PCI features configuration is complete and re-enumeration is
> > > required
> > >
> > > +  //
> > >
> > > +  if ( !CheckPciFeaturesConfigurationRequired ( RootBridge)) {
> > >
> > > +    return EFI_ALREADY_STARTED;
> > >
> > > +  }
> > >
> > > +
> > >
> > > +  Str = ConvertDevicePathToText (
> > >
> > > +          DevicePathFromHandle (RootBridge->Handle),
> > >
> > > +          FALSE,
> > >
> > > +          FALSE
> > >
> > > +        );
> > >
> > > +  DEBUG ((DEBUG_INFO, "Enumerating PCI features for Root Bridge %s\n",
> > > Str != NULL ? Str : L""));
> > >
> > > +
> > >
> > > +  for ( OtherPciFeatureConfigPhase = PciFeatureRootBridgeScan
> > >
> > > +      ; OtherPciFeatureConfigPhase <= PciFeatureConfigurationComplete
> > >
> > > +      ; OtherPciFeatureConfigPhase++
> > >
> > > +      ) {
> > >
> > > +    switch ( OtherPciFeatureConfigPhase){
> > >
> > > +      case  PciFeatureRootBridgeScan:
> > >
> > > +        SetupPciFeaturesConfigurationDefaults ();
> > >
> > > +        //
> > >
> > > +        //first scan the entire root bridge heirarchy for the primary PCI root
> > > ports
> > >
> > > +        //
> > >
> > > +        RecordPciRootPortBridges ( RootBridge);
> > >
> > > +        break;
> > >
> > > +
> > >
> > > +      case  PciFeatureGetDevicePolicy:
> > >
> > > +      case  PciFeatureSetupPhase:
> > >
> > > +        DEBUG ((
> > >
> > > +            DEBUG_INFO, "<<********** SetupPciFeatures - start
> > > **********>>\n"
> > >
> > > +        ));
> > >
> > > +        //
> > >
> > > +        // enumerate the other PCI features
> > >
> > > +        //
> > >
> > > +        Status = SetupPciFeatures ( RootBridge, OtherPciFeatureConfigPhase);
> > >
> > > +
> > >
> > > +        DEBUG ((
> > >
> > > +            DEBUG_INFO, "<<********** SetupPciFeatures - end
> > > **********>>\n"
> > >
> > > +        ));
> > >
> > > +        break;
> > >
> > > +
> > >
> > > +      case  PciFeatureConfigurationPhase:
> > >
> > > +        //
> > >
> > > +        // override the PCI features as per enumeration phase
> > >
> > > +        //
> > >
> > > +        DEBUG ((DEBUG_INFO, "PCI features override for Root Bridge %s\n",
> > > Str != NULL ? Str : L""));
> > >
> > > +        DEBUG ((
> > >
> > > +            DEBUG_INFO, "<<********** ProgramPciFeatures - start
> > > **********>>\n"
> > >
> > > +        ));
> > >
> > > +        Status = ProgramPciFeatures ( RootBridge);
> > >
> > > +        DEBUG ((
> > >
> > > +            DEBUG_INFO, "<<********** ProgramPciFeatures - end
> > > **********>>\n"
> > >
> > > +        ));
> > >
> > > +        break;
> > >
> > > +
> > >
> > > +      case  PciFeatureConfigurationComplete:
> > >
> > > +        //
> > >
> > > +        // clean up the temporary resource nodes created for this root bridge
> > >
> > > +        //
> > >
> > > +        DestroyPrimaryRootPortNodes ();
> > >
> > > +
> > >
> > > +        ErasePciFeaturesConfigurationTable ();
> > >
> > > +    }
> > >
> > > +  }
> > >
> > > +
> > >
> > > +  if (Str != NULL) {
> > >
> > > +    FreePool (Str);
> > >
> > > +  }
> > >
> > > +  //
> > >
> > > +  // mark this root bridge as PCI features configuration complete, and no
> > > new
> > >
> > > +  // enumeration is required
> > >
> > > +  //
> > >
> > > +  AddRootBridgeInPciFeaturesConfigCompletionList ( RootBridge, FALSE);
> > >
> > > +  return Status;
> > >
> > > +}
> > >
> > > +
> > >
> > > +/**
> > >
> > > +  This routine is invoked from the Stop () interface for the EFI handle of
> > the
> > >
> > > +  RootBridge. Free up its node of type
> > > PCI_FEATURE_CONFIGURATION_COMPLETION_LIST.
> > >
> > > +
> > >
> > > +  @param  RootBridge      A pointer to the PCI_IO_DEVICE
> > >
> > > +**/
> > >
> > > +VOID
> > >
> > > +DestroyRootBridgePciFeaturesConfigCompletionList (
> > >
> > > +  IN PCI_IO_DEVICE          *RootBridge
> > >
> > > +  )
> > >
> > > +{
> > >
> > > +  LIST_ENTRY                                  *Link;
> > >
> > > +  PCI_FEATURE_CONFIGURATION_COMPLETION_LIST   *Temp;
> > >
> > > +
> > >
> > > +  if ( mPciFeaturesConfigurationCompletionList) {
> > >
> > > +    Link = &mPciFeaturesConfigurationCompletionList->RootBridgeLink;
> > >
> > > +
> > >
> > > +    do {
> > >
> > > +      Temp =
> > > PCI_FEATURE_CONFIGURATION_COMPLETION_LIST_FROM_LINK (Link);
> > >
> > > +      if ( Temp->RootBridgeHandle == RootBridge->Handle) {
> > >
> > > +        RemoveEntryList ( Link);
> > >
> > > +        FreePool ( Temp);
> > >
> > > +        return;
> > >
> > > +      }
> > >
> > > +      Link = Link->ForwardLink;
> > >
> > > +    } while (Link != &mPciFeaturesConfigurationCompletionList-
> > > >RootBridgeLink);
> > >
> > > +  }
> > >
> > > +  //
> > >
> > > +  // not found on the PCI feature configuration completion list, return
> > >
> > > +  //
> > >
> > > +  return;
> > >
> > > +}
> > >
> > > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> > > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> > > new file mode 100644
> > > index 0000000000..9f225fa993
> > > --- /dev/null
> > > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> > > @@ -0,0 +1,201 @@
> > > +/** @file
> > >
> > > +  PCI standard feature support functions implementation for PCI Bus
> > > module..
> > >
> > > +
> > >
> > > +Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> > >
> > > +SPDX-License-Identifier: BSD-2-Clause-Patent
> > >
> > > +
> > >
> > > +**/
> > >
> > > +
> > >
> > > +#ifndef _EFI_PCI_FEATURES_SUPPORT_H_
> > >
> > > +#define _EFI_PCI_FEATURES_SUPPORT_H_
> > >
> > > +
> > >
> > > +#include "PciBus.h"
> > >
> > > +#include "PciPlatformSupport.h"
> > >
> > > +
> > >
> > > +//
> > >
> > > +// Macro definitions for the PCI Features support PCD
> > >
> > > +//
> > >
> > > +#define PCI_FEATURE_SUPPORT_FLAG_MPS  BIT0
> > >
> > > +#define PCI_FEATURE_SUPPORT_FLAG_MRRS BIT1
> > >
> > > +
> > >
> > > +//
> > >
> > > +// defines the data structure to hold the details of the PCI Root port
> > devices
> > >
> > > +//
> > >
> > > +typedef struct _PRIMARY_ROOT_PORT_NODE
> > > PRIMARY_ROOT_PORT_NODE;
> > >
> > > +
> > >
> > > +//
> > >
> > > +// defines the data structure to hold the configuration data for the other
> > > PCI
> > >
> > > +// features
> > >
> > > +//
> > >
> > > +typedef struct _OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > > OTHER_PCI_FEATURES_CONFIGURATION_TABLE;
> > >
> > > +
> > >
> > > +//
> > >
> > > +// Defines for the PCI features configuration completion and re-
> > > enumeration list
> > >
> > > +//
> > >
> > > +typedef struct _PCI_FEATURE_CONFIGURATION_COMPLETION_LIST
> > > PCI_FEATURE_CONFIGURATION_COMPLETION_LIST;
> > >
> > > +
> > >
> > > +//
> > >
> > > +// Signature value for the PCI Root Port node
> > >
> > > +//
> > >
> > > +#define PCI_ROOT_PORT_SIGNATURE               SIGNATURE_32 ('p', 'c', 'i',
> > 'p')
> > >
> > > +
> > >
> > > +//
> > >
> > > +// Definitions of the PCI Root Port data structure members
> > >
> > > +//
> > >
> > > +struct _PRIMARY_ROOT_PORT_NODE {
> > >
> > > +  //
> > >
> > > +  // Signature header
> > >
> > > +  //
> > >
> > > +  UINT32                                    Signature;
> > >
> > > +  //
> > >
> > > +  // linked list pointers to next node
> > >
> > > +  //
> > >
> > > +  LIST_ENTRY                                NeighborRootPort;
> > >
> > > +  //
> > >
> > > +  // EFI handle of the parent Root Bridge instance
> > >
> > > +  //
> > >
> > > +  EFI_HANDLE                                RootBridgeHandle;
> > >
> > > +  //
> > >
> > > +  // EFI handle of the PCI controller
> > >
> > > +  //
> > >
> > > +  EFI_HANDLE                                RootPortHandle;
> > >
> > > +  //
> > >
> > > +  // PCI Secondary bus value of the PCI controller
> > >
> > > +  //
> > >
> > > +  UINT8                                     SecondaryBusStart;
> > >
> > > +  //
> > >
> > > +  // PCI Subordinate bus value of the PCI controller
> > >
> > > +  //
> > >
> > > +  UINT8                                     SecondaryBusEnd;
> > >
> > > +  //
> > >
> > > +  // pointer to the corresponding PCI feature configuration Table node
> > >
> > > +  //
> > >
> > > +  OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > > *OtherPciFeaturesConfigurationTable;
> > >
> > > +};
> > >
> > > +
> > >
> > > +#define PRIMARY_ROOT_PORT_NODE_FROM_LINK(a) \
> > >
> > > +  CR (a, PRIMARY_ROOT_PORT_NODE, NeighborRootPort,
> > > PCI_ROOT_PORT_SIGNATURE)
> > >
> > > +
> > >
> > > +//
> > >
> > > +// Definition of the PCI Feature configuration Table members
> > >
> > > +//
> > >
> > > +struct _OTHER_PCI_FEATURES_CONFIGURATION_TABLE {
> > >
> > > +  //
> > >
> > > +  // Configuration Table ID
> > >
> > > +  //
> > >
> > > +  UINTN                                     ID;
> > >
> > > +  //
> > >
> > > +  // to configure the PCI feature Maximum payload size to maintain the
> > data
> > > packet
> > >
> > > +  // size among all the PCI devices in the PCI hierarchy
> > >
> > > +  //
> > >
> > > +  UINT8                                     Max_Payload_Size;
> > >
> > > +  //
> > >
> > > +  // to configure the PCI feature maximum read request size to maintain
> > the
> > > memory
> > >
> > > +  // requester size among all the PCI devices in the PCI hierarchy
> > >
> > > +  //
> > >
> > > +  UINT8                                     Max_Read_Request_Size;
> > >
> > > +  //
> > >
> > > +  // lock the Max_Read_Request_Size for the entire PCI tree of a root port
> > >
> > > +  //
> > >
> > > +  BOOLEAN                                   Lock_Max_Read_Request_Size;
> > >
> > > +};
> > >
> > > +
> > >
> > > +
> > >
> > > +//
> > >
> > > +// PCI feature configuration node signature value
> > >
> > > +//
> > >
> > > +#define PCI_FEATURE_CONFIGURATION_SIGNATURE
> > > SIGNATURE_32 ('p', 'c', 'i', 'f')
> > >
> > > +
> > >
> > > +struct _PCI_FEATURE_CONFIGURATION_COMPLETION_LIST {
> > >
> > > +  //
> > >
> > > +  // Signature header
> > >
> > > +  //
> > >
> > > +  UINT32                                    Signature;
> > >
> > > +  //
> > >
> > > +  // link to next Root Bridge whose PCI Feature configuration is complete
> > >
> > > +  //
> > >
> > > +  LIST_ENTRY                                RootBridgeLink;
> > >
> > > +  //
> > >
> > > +  // EFI handle of the Root Bridge whose PCI feature configuration is
> > > complete
> > >
> > > +  //
> > >
> > > +  EFI_HANDLE                                RootBridgeHandle;
> > >
> > > +  //
> > >
> > > +  // indication for complete re-enumeration of the PCI feature
> > configuration
> > >
> > > +  //
> > >
> > > +  BOOLEAN                                   ReEnumeratePciFeatureConfiguration;
> > >
> > > +};
> > >
> > > +
> > >
> > > +#define
> > > PCI_FEATURE_CONFIGURATION_COMPLETION_LIST_FROM_LINK(a) \
> > >
> > > +  CR (a, PCI_FEATURE_CONFIGURATION_COMPLETION_LIST,
> > > RootBridgeLink, PCI_FEATURE_CONFIGURATION_SIGNATURE)
> > >
> > > +
> > >
> > > +//
> > >
> > > +// Declaration of the internal sub-phases within the PCI Feature
> > > enumeration
> > >
> > > +//
> > >
> > > +typedef enum {
> > >
> > > +  //
> > >
> > > +  // initial phase in configuring the other PCI features to record the primary
> > >
> > > +  // root ports
> > >
> > > +  //
> > >
> > > +  PciFeatureRootBridgeScan,
> > >
> > > +  //
> > >
> > > +  // get the PCI device-specific platform policies and align with device
> > > capabilities
> > >
> > > +  //
> > >
> > > +  PciFeatureGetDevicePolicy,
> > >
> > > +  //
> > >
> > > +  // align all PCI nodes in the PCI heirarchical tree
> > >
> > > +  //
> > >
> > > +  PciFeatureSetupPhase,
> > >
> > > +  //
> > >
> > > +  // finally override to complete configuration of the PCI feature
> > >
> > > +  //
> > >
> > > +  PciFeatureConfigurationPhase,
> > >
> > > +  //
> > >
> > > +  // PCI feature configuration complete
> > >
> > > +  //
> > >
> > > +  PciFeatureConfigurationComplete
> > >
> > > +
> > >
> > > +}PCI_FEATURE_CONFIGURATION_PHASE;
> > >
> > > +
> > >
> > > +/**
> > >
> > > +  Main routine to indicate platform selection of any of the other PCI
> > features
> > >
> > > +  to be configured by this driver
> > >
> > > +
> > >
> > > +  @retval TRUE    platform has selected the other PCI features to be
> > > configured
> > >
> > > +          FALSE   platform has not selected any of the other PCI features
> > >
> > > +**/
> > >
> > > +BOOLEAN
> > >
> > > +CheckOtherPciFeaturesPcd (
> > >
> > > +  );
> > >
> > > +
> > >
> > > +/**
> > >
> > > +  Enumerate all the nodes of the specified root bridge or PCI-PCI Bridge, to
> > >
> > > +  configure the other PCI features.
> > >
> > > +
> > >
> > > +  @param RootBridge          A pointer to the PCI_IO_DEVICE.
> > >
> > > +
> > >
> > > +  @retval EFI_SUCCESS           The other PCI features configuration during
> > > enumeration
> > >
> > > +                                of all the nodes of the PCI root bridge instance were
> > >
> > > +                                programmed in PCI-compliance pattern along with the
> > >
> > > +                                device-specific policy, as applicable.
> > >
> > > +  @retval EFI_UNSUPPORTED       One of the override operation maong the
> > > nodes of
> > >
> > > +                                the PCI hierarchy resulted in a incompatible address
> > >
> > > +                                range.
> > >
> > > +  @retval EFI_INVALID_PARAMETER The override operation is performed
> > > with invalid input
> > >
> > > +                                parameters.
> > >
> > > +**/
> > >
> > > +EFI_STATUS
> > >
> > > +EnumerateOtherPciFeatures (
> > >
> > > +  IN PCI_IO_DEVICE           *RootBridge
> > >
> > > +  );
> > >
> > > +
> > >
> > > +/**
> > >
> > > +  This routine is invoked from the Stop () interface for the EFI handle of
> > the
> > >
> > > +  RootBridge. Free up its node of type
> > > PCI_FEATURE_CONFIGURATION_COMPLETION_LIST.
> > >
> > > +
> > >
> > > +  @param  RootBridge      A pointer to the PCI_IO_DEVICE
> > >
> > > +**/
> > >
> > > +VOID
> > >
> > > +DestroyRootBridgePciFeaturesConfigCompletionList (
> > >
> > > +  IN PCI_IO_DEVICE          *RootBridge
> > >
> > > +  );
> > >
> > > +#endif
> > >
> > > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> > > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> > > new file mode 100644
> > > index 0000000000..d94037d69a
> > > --- /dev/null
> > > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> > > @@ -0,0 +1,565 @@
> > > +/** @file
> > >
> > > +  This file encapsulate the usage of PCI Platform Protocol
> > >
> > > +
> > >
> > > +  This file define the necessary hooks used to obtain the platform
> > >
> > > +  level data and policies which could be used in the PCI Enumeration
> > phases
> > >
> > > +
> > >
> > > +Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> > >
> > > +SPDX-License-Identifier: BSD-2-Clause-Patent
> > >
> > > +
> > >
> > > +**/
> > >
> > > +
> > >
> > > +#include "PciPlatformSupport.h"
> > >
> > > +
> > >
> > > +EFI_PCI_PLATFORM_PROTOCOL                     *mPciPlatformProtocol;
> > >
> > > +EFI_PCI_OVERRIDE_PROTOCOL                     *mPciOverrideProtocol;
> > >
> > > +
> > >
> > > +EFI_PCI_PLATFORM_PROTOCOL2                    *mPciPlatformProtocol2;
> > >
> > > +EFI_PCI_OVERRIDE_PROTOCOL2                    *mPciOverrideProtocol2;
> > >
> > > +
> > >
> > > +
> > >
> > > +/**
> > >
> > > +  This function retrieves the PCI Platform Protocol published by platform
> > > driver
> > >
> > > +
> > >
> > > +**/
> > >
> > > +VOID
> > >
> > > +GetPciPlatformProtocol (
> > >
> > > +  )
> > >
> > > +{
> > >
> > > +  mPciPlatformProtocol2 = NULL;
> > >
> > > +  gBS->LocateProtocol (
> > >
> > > +      &gEfiPciPlatformProtocol2Guid,
> > >
> > > +      NULL,
> > >
> > > +      (VOID **) &mPciPlatformProtocol2
> > >
> > > +  );
> > >
> > > +
> > >
> > > +  //
> > >
> > > +  // If PCI Platform protocol doesn't exist, try to get Pci Override Protocol.
> > >
> > > +  //
> > >
> > > +  if (mPciPlatformProtocol2 == NULL) {
> > >
> > > +    mPciOverrideProtocol2 = NULL;
> > >
> > > +    gBS->LocateProtocol (
> > >
> > > +        &gEfiPciOverrideProtocol2Guid,
> > >
> > > +        NULL,
> > >
> > > +        (VOID **) &mPciOverrideProtocol2
> > >
> > > +    );
> > >
> > > +  }
> > >
> > > +  //
> > >
> > > +  // fetch the old PCI Platform Protocols if new are not installed
> > >
> > > +  //
> > >
> > > +  if (mPciOverrideProtocol2 == NULL) {
> > >
> > > +
> > >
> > > +    mPciPlatformProtocol = NULL;
> > >
> > > +    gBS->LocateProtocol (
> > >
> > > +        &gEfiPciPlatformProtocolGuid,
> > >
> > > +        NULL,
> > >
> > > +        (VOID **) &mPciPlatformProtocol
> > >
> > > +    );
> > >
> > > +
> > >
> > > +    //
> > >
> > > +    // If PCI Platform protocol doesn't exist, try to  get Pci Override Protocol.
> > >
> > > +    //
> > >
> > > +    if (mPciPlatformProtocol == NULL) {
> > >
> > > +      mPciOverrideProtocol = NULL;
> > >
> > > +      gBS->LocateProtocol (
> > >
> > > +          &gEfiPciOverrideProtocolGuid,
> > >
> > > +          NULL,
> > >
> > > +          (VOID **) &mPciOverrideProtocol
> > >
> > > +      );
> > >
> > > +    }
> > >
> > > +  }
> > >
> > > +}
> > >
> > > +
> > >
> > > +/**
> > >
> > > +  This function indicates the presence of PCI Platform driver
> > >
> > > +  @retval     TRUE or FALSE
> > >
> > > +**/
> > >
> > > +BOOLEAN
> > >
> > > +CheckPciPlatformProtocolInstall (
> > >
> > > +  )
> > >
> > > +{
> > >
> > > +  if (mPciPlatformProtocol2 != NULL) {
> > >
> > > +    return TRUE;
> > >
> > > +  } else if (mPciOverrideProtocol2 != NULL) {
> > >
> > > +    return TRUE;
> > >
> > > +  } else {
> > >
> > > +    if (mPciPlatformProtocol != NULL) {
> > >
> > > +      return TRUE;
> > >
> > > +    } else if (mPciOverrideProtocol != NULL){
> > >
> > > +      return TRUE;
> > >
> > > +    }
> > >
> > > +  }
> > >
> > > +  return FALSE;
> > >
> > > +}
> > >
> > > +
> > >
> > > +/**
> > >
> > > +  Provides the hooks from the PCI bus driver to every PCI controller
> > > (device/function) at various
> > >
> > > +  stages of the PCI enumeration process that allow the host bridge driver
> > to
> > > preinitialize individual
> > >
> > > +  PCI controllers before enumeration.
> > >
> > > +
> > >
> > > +  This function is called during the PCI enumeration process. No specific
> > > action is expected from this
> > >
> > > +  member function. It allows the host bridge driver to preinitialize
> > individual
> > > PCI controllers before
> > >
> > > +  enumeration.
> > >
> > > +
> > >
> > > +  @param[in] HostBridgeHandle     The associated PCI host bridge handle.
> > >
> > > +  @param[in] RootBridgeHandle     The associated PCI root bridge handle.
> > >
> > > +  @param[in] RootBridgePciAddress The address of the PCI device on the
> > > PCI bus.
> > >
> > > +  @param[in] Phase          The phase of the PCI controller enumeration.
> > >
> > > +  @param[in] ExecPhase      Defines the execution phase of the PCI chipset
> > > driver.
> > >
> > > +
> > >
> > > +  @retval    Status         returns the status from the PCI Platform protocol as
> > is
> > >
> > > +
> > >
> > > +**/
> > >
> > > +EFI_STATUS
> > >
> > > +PciPlatformPreprocessController (
> > >
> > > +  IN EFI_HANDLE                                    HostBridgeHandle,
> > >
> > > +  IN EFI_HANDLE                                    RootBridgeHandle,
> > >
> > > +  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS
> > > RootBridgePciAddress,
> > >
> > > +  IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE  Phase,
> > >
> > > +  IN EFI_PCI_EXECUTION_PHASE                       ExecPhase
> > >
> > > +  )
> > >
> > > +{
> > >
> > > +  EFI_STATUS  Status;
> > >
> > > +
> > >
> > > +  if (mPciPlatformProtocol2 != NULL) {
> > >
> > > +    //
> > >
> > > +    // Call PlatformPci::PrepController() if the protocol is present.
> > >
> > > +    //
> > >
> > > +    Status = mPciPlatformProtocol2->PlatformPrepController (
> > >
> > > +
> > > (EFI_PCI_PLATFORM_PROTOCOL*)mPciPlatformProtocol2,
> > >
> > > +                                      HostBridgeHandle,
> > >
> > > +                                      RootBridgeHandle,
> > >
> > > +                                      RootBridgePciAddress,
> > >
> > > +                                      Phase,
> > >
> > > +                                      ExecPhase
> > >
> > > +                                    );
> > >
> > > +  } else if (mPciOverrideProtocol2 != NULL) {
> > >
> > > +    //
> > >
> > > +    // Call PlatformPci::PrepController() if the protocol is present.
> > >
> > > +    //
> > >
> > > +    Status = mPciOverrideProtocol2->PlatformPrepController (
> > >
> > > +
> > > (EFI_PCI_PLATFORM_PROTOCOL*)mPciOverrideProtocol2,
> > >
> > > +                                      HostBridgeHandle,
> > >
> > > +                                      RootBridgeHandle,
> > >
> > > +                                      RootBridgePciAddress,
> > >
> > > +                                      Phase,
> > >
> > > +                                      ExecPhase
> > >
> > > +                                    );
> > >
> > > +  } else {
> > >
> > > +    if (mPciPlatformProtocol != NULL) {
> > >
> > > +      //
> > >
> > > +      // Call PlatformPci::PrepController() if the protocol is present.
> > >
> > > +      //
> > >
> > > +      Status = mPciPlatformProtocol->PlatformPrepController (
> > >
> > > +                                      mPciPlatformProtocol,
> > >
> > > +                                      HostBridgeHandle,
> > >
> > > +                                      RootBridgeHandle,
> > >
> > > +                                      RootBridgePciAddress,
> > >
> > > +                                      Phase,
> > >
> > > +                                      ExecPhase
> > >
> > > +                                    );
> > >
> > > +    } else if (mPciOverrideProtocol != NULL) {
> > >
> > > +      //
> > >
> > > +      // Call PlatformPci::PrepController() if the protocol is present.
> > >
> > > +      //
> > >
> > > +      Status = mPciOverrideProtocol->PlatformPrepController (
> > >
> > > +                                      mPciOverrideProtocol,
> > >
> > > +                                      HostBridgeHandle,
> > >
> > > +                                      RootBridgeHandle,
> > >
> > > +                                      RootBridgePciAddress,
> > >
> > > +                                      Phase,
> > >
> > > +                                      ExecPhase
> > >
> > > +                                    );
> > >
> > > +    } else {
> > >
> > > +      //
> > >
> > > +      // return PCI Platform Protocol not found
> > >
> > > +      //
> > >
> > > +      return EFI_NOT_FOUND;
> > >
> > > +    }
> > >
> > > +  }
> > >
> > > +  return Status;
> > >
> > > +}
> > >
> > > +
> > >
> > > +/**
> > >
> > > +  This function notifies the PCI Platform driver about the PCI host bridge
> > > resource
> > >
> > > +  allocation phase and PCI execution phase.
> > >
> > > +
> > >
> > > +  @param[in]  HostBridge     The handle of the host bridge controller.
> > >
> > > +  @param[in]  Phase          The phase of the PCI bus enumeration.
> > >
> > > +  @param[in]  ExecPhase      Defines the execution phase of the PCI
> > chipset
> > > driver.
> > >
> > > +  @retval     Status          returns the status from the PCI Platform protocol
> > as
> > > is
> > >
> > > +
> > >
> > > +**/
> > >
> > > +EFI_STATUS
> > >
> > > +PciPlatformNotifyPhase (
> > >
> > > +  IN  EFI_HANDLE                                      HostBridgeHandle,
> > >
> > > +  IN  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE   Phase,
> > >
> > > +  IN  EFI_PCI_EXECUTION_PHASE                         ExecPhase
> > >
> > > +  )
> > >
> > > +{
> > >
> > > +  EFI_STATUS  Status;
> > >
> > > +
> > >
> > > +  if ( mPciPlatformProtocol2 != NULL) {
> > >
> > > +    Status = mPciPlatformProtocol2->PlatformNotify (
> > >
> > > +
> > > (EFI_PCI_PLATFORM_PROTOCOL*)mPciPlatformProtocol2,
> > >
> > > +                                      HostBridgeHandle,
> > >
> > > +                                      Phase,
> > >
> > > +                                      ExecPhase
> > >
> > > +                                    );
> > >
> > > +  } else if ( mPciOverrideProtocol2 != NULL) {
> > >
> > > +    Status = mPciOverrideProtocol2->PlatformNotify (
> > >
> > > +
> > > (EFI_PCI_PLATFORM_PROTOCOL*)mPciOverrideProtocol2,
> > >
> > > +                                      HostBridgeHandle,
> > >
> > > +                                      Phase,
> > >
> > > +                                      ExecPhase
> > >
> > > +                                    );
> > >
> > > +  } else {
> > >
> > > +
> > >
> > > +    if ( mPciPlatformProtocol != NULL) {
> > >
> > > +      Status = mPciPlatformProtocol->PlatformNotify (
> > >
> > > +                                      mPciPlatformProtocol,
> > >
> > > +                                      HostBridgeHandle,
> > >
> > > +                                      Phase,
> > >
> > > +                                      ExecPhase
> > >
> > > +                                    );
> > >
> > > +    } else if ( mPciOverrideProtocol != NULL){
> > >
> > > +      Status = mPciOverrideProtocol->PlatformNotify (
> > >
> > > +                                      mPciOverrideProtocol,
> > >
> > > +                                      HostBridgeHandle,
> > >
> > > +                                      Phase,
> > >
> > > +                                      ExecPhase
> > >
> > > +                                    );
> > >
> > > +    } else {
> > >
> > > +      //
> > >
> > > +      // return PCI Platform Protocol not found
> > >
> > > +      //
> > >
> > > +      return EFI_NOT_FOUND;
> > >
> > > +    }
> > >
> > > +  }
> > >
> > > +  return Status;
> > >
> > > +}
> > >
> > > +
> > >
> > > +/**
> > >
> > > +  This function retrieves the PCI platform policy.
> > >
> > > +
> > >
> > > +  @param  PciPolicy     pointer to the legacy EFI_PCI_PLATFORM_POLICY
> > >
> > > +  @retval Status        returns the status from the PCI Platform protocol as is
> > >
> > > +
> > >
> > > +**/
> > >
> > > +EFI_STATUS
> > >
> > > +PciGetPlatformPolicy (
> > >
> > > +  OUT EFI_PCI_PLATFORM_POLICY *PciPolicy
> > >
> > > +  )
> > >
> > > +{
> > >
> > > +  EFI_STATUS  Status;
> > >
> > > +
> > >
> > > +  if ( mPciPlatformProtocol2 != NULL) {
> > >
> > > +      Status = mPciPlatformProtocol2->GetPlatformPolicy (
> > >
> > > +
> > > (EFI_PCI_PLATFORM_PROTOCOL*)mPciPlatformProtocol2,
> > >
> > > +                                        PciPolicy
> > >
> > > +                                      );
> > >
> > > +  } else if ( mPciOverrideProtocol2 != NULL) {
> > >
> > > +      Status = mPciOverrideProtocol2->GetPlatformPolicy (
> > >
> > > +
> > > (EFI_PCI_PLATFORM_PROTOCOL*)mPciOverrideProtocol2,
> > >
> > > +                                        PciPolicy
> > >
> > > +                                      );
> > >
> > > +  } else {
> > >
> > > +    if ( mPciPlatformProtocol != NULL) {
> > >
> > > +      Status = mPciPlatformProtocol->GetPlatformPolicy (
> > >
> > > +                                      mPciPlatformProtocol,
> > >
> > > +                                      PciPolicy
> > >
> > > +                                    );
> > >
> > > +    }
> > >
> > > +
> > >
> > > +    if ( mPciOverrideProtocol != NULL) {
> > >
> > > +      Status = mPciOverrideProtocol->GetPlatformPolicy (
> > >
> > > +                                      mPciOverrideProtocol,
> > >
> > > +                                      PciPolicy
> > >
> > > +                                    );
> > >
> > > +    } else {
> > >
> > > +      //
> > >
> > > +      // return PCI Platform Protocol not found
> > >
> > > +      //
> > >
> > > +      return EFI_NOT_FOUND;
> > >
> > > +    }
> > >
> > > +  }
> > >
> > > +  return Status;
> > >
> > > +}
> > >
> > > +
> > >
> > > +/**
> > >
> > > +  This function retrieves the Option ROM image and size from the Platform.
> > >
> > > +
> > >
> > > +  It uses the PCI_IO_DEVICE internal fields are used to store OpROM
> > > image/size
> > >
> > > +
> > >
> > > +  @param Controller     An EFI handle for the PCI bus controller.
> > >
> > > +  @param PciIoDevice    A PCI_IO_DEVICE pointer to the PCI IO device to
> > be
> > > registered.
> > >
> > > +
> > >
> > > +  @retval EFI_SUCCESS            The option ROM was available for this device
> > > and loaded into memory.
> > >
> > > +  @retval EFI_NOT_FOUND          No option ROM was available for this
> > device.
> > >
> > > +  @retval EFI_OUT_OF_RESOURCES   No memory was available to load the
> > > option ROM.
> > >
> > > +  @retval EFI_DEVICE_ERROR       An error occurred in obtaining the option
> > > ROM.
> > >
> > > +
> > >
> > > +**/
> > >
> > > +EFI_STATUS
> > >
> > > +GetPlatformPciOptionRom (
> > >
> > > +  IN  EFI_HANDLE                    Controller,
> > >
> > > +  IN  PCI_IO_DEVICE                 *PciIoDevice
> > >
> > > +  )
> > >
> > > +{
> > >
> > > +  EFI_STATUS  Status;
> > >
> > > +  VOID        *PlatformOpRomBuffer;
> > >
> > > +  UINTN       PlatformOpRomSize;
> > >
> > > +
> > >
> > > +  if (mPciPlatformProtocol2 != NULL) {
> > >
> > > +    Status = mPciPlatformProtocol2->GetPciRom (
> > >
> > > +
> > > (EFI_PCI_PLATFORM_PROTOCOL*)mPciPlatformProtocol2,
> > >
> > > +                                      PciIoDevice->Handle,
> > >
> > > +                                      &PlatformOpRomBuffer,
> > >
> > > +                                      &PlatformOpRomSize
> > >
> > > +                                      );
> > >
> > > +  } else if (mPciOverrideProtocol2 != NULL) {
> > >
> > > +    Status = mPciOverrideProtocol2->GetPciRom (
> > >
> > > +
> > > (EFI_PCI_PLATFORM_PROTOCOL*)mPciOverrideProtocol2,
> > >
> > > +                                      PciIoDevice->Handle,
> > >
> > > +                                      &PlatformOpRomBuffer,
> > >
> > > +                                      &PlatformOpRomSize
> > >
> > > +                                      );
> > >
> > > +  } else {
> > >
> > > +    if (mPciPlatformProtocol != NULL) {
> > >
> > > +      Status = mPciPlatformProtocol->GetPciRom (
> > >
> > > +                                      mPciPlatformProtocol,
> > >
> > > +                                      PciIoDevice->Handle,
> > >
> > > +                                      &PlatformOpRomBuffer,
> > >
> > > +                                      &PlatformOpRomSize
> > >
> > > +                                      );
> > >
> > > +    } else if (mPciOverrideProtocol != NULL) {
> > >
> > > +      Status = mPciOverrideProtocol->GetPciRom (
> > >
> > > +                                        mPciOverrideProtocol,
> > >
> > > +                                        PciIoDevice->Handle,
> > >
> > > +                                        &PlatformOpRomBuffer,
> > >
> > > +                                        &PlatformOpRomSize
> > >
> > > +                                        );
> > >
> > > +    } else {
> > >
> > > +      //
> > >
> > > +      // return PCI Platform Protocol not found
> > >
> > > +      //
> > >
> > > +      return EFI_NOT_FOUND;
> > >
> > > +    }
> > >
> > > +  }
> > >
> > > +
> > >
> > > +  if (!EFI_ERROR (Status)) {
> > >
> > > +    PciIoDevice->EmbeddedRom    = FALSE;
> > >
> > > +    PciIoDevice->RomSize        = (UINT32)PlatformOpRomSize;
> > >
> > > +    PciIoDevice->PciIo.RomSize  = PlatformOpRomSize;
> > >
> > > +    PciIoDevice->PciIo.RomImage = PlatformOpRomBuffer;
> > >
> > > +  }
> > >
> > > +  return Status;
> > >
> > > +}
> > >
> > > +
> > >
> > > +/**
> > >
> > > +  Helper routine to indicate whether the given PCI device specific policy
> > > value
> > >
> > > +  dictates to override the Max_Payload_Size to a particular value, or set as
> > > per
> > >
> > > +  device capability.
> > >
> > > +
> > >
> > > +  @param  MPS     Input device-specific policy should be in terms of type
> > >
> > > +                  EFI_PCI_CONF_MAX_PAYLOAD_SIZE
> > >
> > > +
> > >
> > > +  @retval TRUE    Setup Max_Payload_Size as per device capability
> > >
> > > +          FALSE   override as per device-specific platform policy
> > >
> > > +**/
> > >
> > > +BOOLEAN
> > >
> > > +SetupMpsAsPerDeviceCapability (
> > >
> > > +  IN  UINT8                   MPS
> > >
> > > +)
> > >
> > > +{
> > >
> > > +  if ( MPS == EFI_PCI_CONF_MAX_PAYLOAD_SIZE_AUTO) {
> > >
> > > +    return TRUE;
> > >
> > > +  } else {
> > >
> > > +    return FALSE;
> > >
> > > +  }
> > >
> > > +}
> > >
> > > +
> > >
> > > +/**
> > >
> > > +  Helper routine to indicate whether the given PCI device specific policy
> > > value
> > >
> > > +  dictates to override the Max_Read_Req_Size to a particular value, or set
> > as
> > > per
> > >
> > > +  device capability.
> > >
> > > +
> > >
> > > +  @param  MRRS    Input device-specific policy should be in terms of type
> > >
> > > +                  EFI_PCI_CONF_MAX_READ_REQ_SIZE
> > >
> > > +
> > >
> > > +  @retval TRUE    Setup Max_Read_Req_Size as per device capability
> > >
> > > +          FALSE   override as per device-specific platform policy
> > >
> > > +**/
> > >
> > > +BOOLEAN
> > >
> > > +SetupMrrsAsPerDeviceCapability (
> > >
> > > +  IN  UINT8                   MRRS
> > >
> > > +)
> > >
> > > +{
> > >
> > > +  if ( MRRS == EFI_PCI_CONF_MAX_READ_REQ_SIZE_AUTO) {
> > >
> > > +    return TRUE;
> > >
> > > +  } else {
> > >
> > > +    return FALSE;
> > >
> > > +  }
> > >
> > > +}
> > >
> > > +
> > >
> > > +/**
> > >
> > > +  Routine to translate the given device-specific platform policy from type
> > >
> > > +  EFI_PCI_CONF_MAX_PAYLOAD_SIZE to HW-specific value, as per PCI
> > Base
> > > Specification
> > >
> > > +  Revision 4.0; for the PCI feature Max_Payload_Size.
> > >
> > > +
> > >
> > > +  @param  MPS     Input device-specific policy should be in terms of type
> > >
> > > +                  EFI_PCI_CONF_MAX_PAYLOAD_SIZE
> > >
> > > +
> > >
> > > +  @retval         Range values for the Max_Payload_Size as defined in the
> > PCI
> > >
> > > +                  Base Specification 4.0
> > >
> > > +**/
> > >
> > > +UINT8
> > >
> > > +TranslateMpsSetupValueToPci (
> > >
> > > +  IN  UINT8                   MPS
> > >
> > > +)
> > >
> > > +{
> > >
> > > +  switch (MPS) {
> > >
> > > +    case EFI_PCI_CONF_MAX_PAYLOAD_SIZE_128B:
> > >
> > > +      return PCIE_MAX_PAYLOAD_SIZE_128B;
> > >
> > > +    case EFI_PCI_CONF_MAX_PAYLOAD_SIZE_256B:
> > >
> > > +      return PCIE_MAX_PAYLOAD_SIZE_256B;
> > >
> > > +    case EFI_PCI_CONF_MAX_PAYLOAD_SIZE_512B:
> > >
> > > +      return PCIE_MAX_PAYLOAD_SIZE_512B;
> > >
> > > +    case EFI_PCI_CONF_MAX_PAYLOAD_SIZE_1024B:
> > >
> > > +      return PCIE_MAX_PAYLOAD_SIZE_1024B;
> > >
> > > +    case EFI_PCI_CONF_MAX_PAYLOAD_SIZE_2048B:
> > >
> > > +      return PCIE_MAX_PAYLOAD_SIZE_2048B;
> > >
> > > +    case EFI_PCI_CONF_MAX_PAYLOAD_SIZE_4096B:
> > >
> > > +      return PCIE_MAX_PAYLOAD_SIZE_4096B;
> > >
> > > +    default:
> > >
> > > +      return PCIE_MAX_PAYLOAD_SIZE_128B;
> > >
> > > +  }
> > >
> > > +}
> > >
> > > +
> > >
> > > +/**
> > >
> > > +  Routine to translate the given device-specific platform policy from type
> > >
> > > +  EFI_PCI_CONF_MAX_READ_REQ_SIZE to HW-specific value, as per PCI
> > > Base Specification
> > >
> > > +  Revision 4.0; for the PCI feature Max_Read_Req_Size.
> > >
> > > +
> > >
> > > +  @param  MRRS    Input device-specific policy should be in terms of type
> > >
> > > +                  EFI_PCI_CONF_MAX_READ_REQ_SIZE
> > >
> > > +
> > >
> > > +  @retval         Range values for the Max_Read_Req_Size as defined in the
> > > PCI
> > >
> > > +                  Base Specification 4.0
> > >
> > > +**/
> > >
> > > +UINT8
> > >
> > > +TranslateMrrsSetupValueToPci (
> > >
> > > +  IN  UINT8                   MRRS
> > >
> > > +)
> > >
> > > +{
> > >
> > > +  switch (MRRS) {
> > >
> > > +    case EFI_PCI_CONF_MAX_READ_REQ_SIZE_128B:
> > >
> > > +      return PCIE_MAX_READ_REQ_SIZE_128B;
> > >
> > > +    case EFI_PCI_CONF_MAX_READ_REQ_SIZE_256B:
> > >
> > > +      return PCIE_MAX_READ_REQ_SIZE_256B;
> > >
> > > +    case EFI_PCI_CONF_MAX_READ_REQ_SIZE_512B:
> > >
> > > +      return PCIE_MAX_READ_REQ_SIZE_512B;
> > >
> > > +    case EFI_PCI_CONF_MAX_READ_REQ_SIZE_1024B:
> > >
> > > +      return PCIE_MAX_READ_REQ_SIZE_1024B;
> > >
> > > +    case EFI_PCI_CONF_MAX_READ_REQ_SIZE_2048B:
> > >
> > > +      return PCIE_MAX_READ_REQ_SIZE_2048B;
> > >
> > > +    case EFI_PCI_CONF_MAX_READ_REQ_SIZE_4096B:
> > >
> > > +      return PCIE_MAX_READ_REQ_SIZE_4096B;
> > >
> > > +    default:
> > >
> > > +      return PCIE_MAX_READ_REQ_SIZE_128B;
> > >
> > > +  }
> > >
> > > +}
> > >
> > > +
> > >
> > > +/**
> > >
> > > +  Generic routine to setup the PCI features as per its predetermined
> > > defaults.
> > >
> > > +**/
> > >
> > > +VOID
> > >
> > > +SetupDefaultsDevicePlatformPolicy (
> > >
> > > +  IN  PCI_IO_DEVICE               *PciDevice
> > >
> > > +  )
> > >
> > > +{
> > >
> > > +  PciDevice->SetupMPS = EFI_PCI_CONF_MAX_PAYLOAD_SIZE_AUTO;
> > >
> > > +  PciDevice->SetupMRRS = EFI_PCI_CONF_MAX_READ_REQ_SIZE_AUTO;
> > >
> > > +}
> > >
> > > +
> > >
> > > +/**
> > >
> > > +  Intermediate routine to either get the PCI device specific platform
> > policies
> > >
> > > +  through the PCI Platform Protocol, or its alias the PCI Override Protocol.
> > >
> > > +
> > >
> > > +  @param  PciIoDevice         A pointer to PCI_IO_DEVICE
> > >
> > > +  @param  PciPlatformProtocol A pointer to
> > > EFI_PCI_PLATFORM_PROTOCOL2
> > >
> > > +
> > >
> > > +  @retval EFI_STATUS          The direct status from the PCI Platform Protocol
> > >
> > > +  @retval EFI_SUCCESS         if on returning predetermined PCI features
> > > defaults,
> > >
> > > +                              for the case when protocol returns as EFI_UNSUPPORTED
> > >
> > > +                              to indicate PCI device exist and it has no platform
> > >
> > > +                              policy defined.
> > >
> > > +**/
> > >
> > > +EFI_STATUS
> > >
> > > +GetPciDevicePlatformPolicyEx (
> > >
> > > +  IN  PCI_IO_DEVICE               *PciIoDevice,
> > >
> > > +  IN  EFI_PCI_PLATFORM_PROTOCOL2  *PciPlatformProtocol
> > >
> > > +  )
> > >
> > > +{
> > >
> > > +  EFI_PCI_PLATFORM_EXTENDED_POLICY  PciPlatformExtendedPolicy;
> > >
> > > +  EFI_STATUS                        Status;
> > >
> > > +
> > >
> > > +  ZeroMem ( &PciPlatformExtendedPolicy, sizeof
> > > (EFI_PCI_PLATFORM_EXTENDED_POLICY));
> > >
> > > +  Status = PciPlatformProtocol->GetDevicePolicy (
> > >
> > > +                                  PciPlatformProtocol,
> > >
> > > +                                  PciIoDevice->Handle,
> > >
> > > +                                  &PciPlatformExtendedPolicy
> > >
> > > +                                  );
> > >
> > > +  //
> > >
> > > +  // platform chipset policies are returned for this PCI device
> > >
> > > +  //
> > >
> > > +  if (!EFI_ERROR(Status)) {
> > >
> > > +    PciIoDevice->SetupMPS = PciPlatformExtendedPolicy.DeviceCtlMPS;
> > >
> > > +    PciIoDevice->SetupMRRS = PciPlatformExtendedPolicy.DeviceCtlMRRS;
> > >
> > > +  }
> > >
> > > +  //
> > >
> > > +  // platform chipset policies are not provided for this PCI device
> > >
> > > +  //
> > >
> > > +  if (EFI_ERROR(Status) == EFI_UNSUPPORTED) {
> > >
> > > +    //
> > >
> > > +    // let the enumeration happen as per the PCI standard way
> > >
> > > +    //
> > >
> > > +    SetupDefaultsDevicePlatformPolicy ( PciIoDevice);
> > >
> > > +    return EFI_SUCCESS;
> > >
> > > +  }
> > >
> > > +
> > >
> > > +  return Status;
> > >
> > > +}
> > >
> > > +
> > >
> > > +/**
> > >
> > > +  Gets the PCI device-specific platform policy from the PCI Platform
> > Protocol.
> > >
> > > +  If no PCI Platform protocol is published than setup the PCI feature to
> > > predetermined
> > >
> > > +  defaults, in order to align all the PCI devices in the PCI hierarchy, as
> > > applicable.
> > >
> > > +
> > >
> > > +  @param  PciDevice     A pointer to PCI_IO_DEVICE
> > >
> > > +
> > >
> > > +  @retval EFI_STATUS    The direct status from the PCI Platform Protocol
> > >
> > > +  @retval EFI_SUCCESS   On return of predetermined PCI features defaults,
> > > for
> > >
> > > +                        the case when protocol returns as EFI_UNSUPPORTED to
> > >
> > > +                        indicate PCI device exist and it has no platform policy
> > >
> > > +                        defined. Also, on returns when no PCI Platform Protocol
> > >
> > > +                        exist.
> > >
> > > +**/
> > >
> > > +EFI_STATUS
> > >
> > > +GetPciDevicePlatformPolicy (
> > >
> > > +  IN PCI_IO_DEVICE          *PciDevice
> > >
> > > +  )
> > >
> > > +{
> > >
> > > +  if ( mPciPlatformProtocol2 != NULL) {
> > >
> > > +    return GetPciDevicePlatformPolicyEx ( PciDevice,
> > mPciPlatformProtocol2);
> > >
> > > +  } else if (mPciOverrideProtocol2 != NULL) {
> > >
> > > +    return GetPciDevicePlatformPolicyEx ( PciDevice,
> > mPciOverrideProtocol2);
> > >
> > > +  } else {
> > >
> > > +    //
> > >
> > > +    // new PCI Platform Protocol 2 is not installed; let the enumeration
> > > happen
> > >
> > > +    // as per PCI standard way
> > >
> > > +    //
> > >
> > > +    SetupDefaultsDevicePlatformPolicy ( PciDevice);
> > >
> > > +    return EFI_SUCCESS;
> > >
> > > +  }
> > >
> > > +}
> > >
> > > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
> > > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
> > > new file mode 100644
> > > index 0000000000..d54e46b950
> > > --- /dev/null
> > > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
> > > @@ -0,0 +1,193 @@
> > > +/** @file
> > >
> > > +  This file encapsulate the usage of PCI Platform Protocol
> > >
> > > +
> > >
> > > +  This file define the necessary hooks used to obtain the platform
> > >
> > > +  level data and policies which could be used in the PCI Enumeration
> > phases
> > >
> > > +
> > >
> > > +Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> > >
> > > +SPDX-License-Identifier: BSD-2-Clause-Patent
> > >
> > > +
> > >
> > > +**/
> > >
> > > +
> > >
> > > +
> > >
> > > +#ifndef _EFI_PCI_PLATFORM_SUPPORT_H_
> > >
> > > +#define _EFI_PCI_PLATFORM_SUPPORT_H_
> > >
> > > +
> > >
> > > +#include "PciBus.h"
> > >
> > > +
> > >
> > > +/**
> > >
> > > +  This function retrieves the PCI Platform Protocol published by platform
> > > driver
> > >
> > > +
> > >
> > > +**/
> > >
> > > +VOID
> > >
> > > +GetPciPlatformProtocol (
> > >
> > > +  );
> > >
> > > +
> > >
> > > +/**
> > >
> > > +  This function indicates the presence of PCI Platform driver
> > >
> > > +  @retval     TRUE or FALSE
> > >
> > > +**/
> > >
> > > +BOOLEAN
> > >
> > > +CheckPciPlatformProtocolInstall (
> > >
> > > +  );
> > >
> > > +
> > >
> > > +
> > >
> > > +/**
> > >
> > > +  Provides the hooks from the PCI bus driver to every PCI controller
> > > (device/function) at various
> > >
> > > +  stages of the PCI enumeration process that allow the host bridge driver
> > to
> > > preinitialize individual
> > >
> > > +  PCI controllers before enumeration.
> > >
> > > +
> > >
> > > +  This function is called during the PCI enumeration process. No specific
> > > action is expected from this
> > >
> > > +  member function. It allows the host bridge driver to preinitialize
> > individual
> > > PCI controllers before
> > >
> > > +  enumeration.
> > >
> > > +
> > >
> > > +  @param[in] HostBridgeHandle     The associated PCI host bridge handle.
> > >
> > > +  @param[in] RootBridgeHandle     The associated PCI root bridge handle.
> > >
> > > +  @param[in] RootBridgePciAddress The address of the PCI device on the
> > > PCI bus.
> > >
> > > +  @param[in] Phase          The phase of the PCI controller enumeration.
> > >
> > > +  @param[in] ExecPhase      Defines the execution phase of the PCI chipset
> > > driver.
> > >
> > > +
> > >
> > > +  @retval    Status         returns the status from the PCI Platform protocol as
> > is
> > >
> > > +
> > >
> > > +**/
> > >
> > > +EFI_STATUS
> > >
> > > +PciPlatformPreprocessController (
> > >
> > > +  IN EFI_HANDLE                                    HostBridgeHandle,
> > >
> > > +  IN EFI_HANDLE                                    RootBridgeHandle,
> > >
> > > +  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS
> > > RootBridgePciAddress,
> > >
> > > +  IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE  Phase,
> > >
> > > +  IN EFI_PCI_EXECUTION_PHASE                       ExecPhase
> > >
> > > +  );
> > >
> > > +
> > >
> > > +/**
> > >
> > > +  This function notifies the PCI Platform driver about the PCI host bridge
> > > resource
> > >
> > > +  allocation phase and PCI execution phase.
> > >
> > > +
> > >
> > > +  @param[in]  HostBridge     The handle of the host bridge controller.
> > >
> > > +  @param[in]  Phase          The phase of the PCI bus enumeration.
> > >
> > > +  @param[in]  ExecPhase      Defines the execution phase of the PCI
> > chipset
> > > driver.
> > >
> > > +  @retval     Status          returns the status from the PCI Platform protocol
> > as
> > > is
> > >
> > > +
> > >
> > > +**/
> > >
> > > +EFI_STATUS
> > >
> > > +PciPlatformNotifyPhase (
> > >
> > > +  IN  EFI_HANDLE                                      HostBridgeHandle,
> > >
> > > +  IN  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE   Phase,
> > >
> > > +  IN  EFI_PCI_EXECUTION_PHASE                         ExecPhase
> > >
> > > +  );
> > >
> > > +
> > >
> > > +/**
> > >
> > > +  This function retrieves the PCI platform policy.
> > >
> > > +
> > >
> > > +  @param  PciPolicy     pointer to the legacy EFI_PCI_PLATFORM_POLICY
> > >
> > > +  @retval Status        returns the status from the PCI Platform protocol as is
> > >
> > > +
> > >
> > > +**/
> > >
> > > +EFI_STATUS
> > >
> > > +PciGetPlatformPolicy (
> > >
> > > +  OUT EFI_PCI_PLATFORM_POLICY *PciPolicy
> > >
> > > +  );
> > >
> > > +
> > >
> > > +/**
> > >
> > > +  This function retrieves the Option ROM image and size from the Platform.
> > >
> > > +
> > >
> > > +  It uses the PCI_IO_DEVICE internal fields are used to store OpROM
> > > image/size
> > >
> > > +
> > >
> > > +  @param Controller     An EFI handle for the PCI bus controller.
> > >
> > > +  @param PciIoDevice    A PCI_IO_DEVICE pointer to the PCI IO device to
> > be
> > > registered.
> > >
> > > +
> > >
> > > +  @retval EFI_SUCCESS            The option ROM was available for this device
> > > and loaded into memory.
> > >
> > > +  @retval EFI_NOT_FOUND          No option ROM was available for this
> > device.
> > >
> > > +  @retval EFI_OUT_OF_RESOURCES   No memory was available to load the
> > > option ROM.
> > >
> > > +  @retval EFI_DEVICE_ERROR       An error occurred in obtaining the option
> > > ROM.
> > >
> > > +
> > >
> > > +**/
> > >
> > > +EFI_STATUS
> > >
> > > +GetPlatformPciOptionRom (
> > >
> > > +  IN  EFI_HANDLE                    Controller,
> > >
> > > +  IN  PCI_IO_DEVICE                 *PciIoDevice
> > >
> > > +  );
> > >
> > > +
> > >
> > > +/**
> > >
> > > +  Gets the PCI device-specific platform policy from the PCI Platform
> > Protocol.
> > >
> > > +  If no PCI Platform protocol is published than setup the PCI feature to
> > > predetermined
> > >
> > > +  defaults, in order to align all the PCI devices in the PCI hierarchy, as
> > > applicable.
> > >
> > > +
> > >
> > > +  @param  PciDevice     A pointer to PCI_IO_DEVICE
> > >
> > > +
> > >
> > > +  @retval EFI_STATUS    The direct status from the PCI Platform Protocol
> > >
> > > +  @retval EFI_SUCCESS   On return of predetermined PCI features defaults,
> > > for
> > >
> > > +                        the case when protocol returns as EFI_UNSUPPORTED to
> > >
> > > +                        indicate PCI device exist and it has no platform policy
> > >
> > > +                        defined. Also, on returns when no PCI Platform Protocol
> > >
> > > +                        exist.
> > >
> > > +**/
> > >
> > > +EFI_STATUS
> > >
> > > +GetPciDevicePlatformPolicy (
> > >
> > > +  IN PCI_IO_DEVICE          *PciDevice
> > >
> > > +  );
> > >
> > > +
> > >
> > > +/**
> > >
> > > +  Helper routine to indicate whether the given PCI device specific policy
> > > value
> > >
> > > +  dictates to override the Max_Payload_Size to a particular value, or set as
> > > per
> > >
> > > +  device capability.
> > >
> > > +
> > >
> > > +  @param  MPS     Input device-specific policy should be in terms of type
> > >
> > > +                  EFI_PCI_CONF_MAX_PAYLOAD_SIZE
> > >
> > > +
> > >
> > > +  @retval TRUE    Setup Max_Payload_Size as per device capability
> > >
> > > +          FALSE   override as per device-specific platform policy
> > >
> > > +**/
> > >
> > > +BOOLEAN
> > >
> > > +SetupMpsAsPerDeviceCapability (
> > >
> > > +  IN  UINT8                   MPS
> > >
> > > +);
> > >
> > > +
> > >
> > > +/**
> > >
> > > +  Helper routine to indicate whether the given PCI device specific policy
> > > value
> > >
> > > +  dictates to override the Max_Read_Req_Size to a particular value, or set
> > as
> > > per
> > >
> > > +  device capability.
> > >
> > > +
> > >
> > > +  @param  MRRS    Input device-specific policy should be in terms of type
> > >
> > > +                  EFI_PCI_CONF_MAX_READ_REQ_SIZE
> > >
> > > +
> > >
> > > +  @retval TRUE    Setup Max_Read_Req_Size as per device capability
> > >
> > > +          FALSE   override as per device-specific platform policy
> > >
> > > +**/
> > >
> > > +BOOLEAN
> > >
> > > +SetupMrrsAsPerDeviceCapability (
> > >
> > > +  IN  UINT8                   MRRS
> > >
> > > +);
> > >
> > > +
> > >
> > > +/**
> > >
> > > +  Routine to translate the given device-specific platform policy from type
> > >
> > > +  EFI_PCI_CONF_MAX_PAYLOAD_SIZE to HW-specific value, as per PCI
> > Base
> > > Specification
> > >
> > > +  Revision 4.0; for the PCI feature Max_Payload_Size.
> > >
> > > +
> > >
> > > +  @param  MPS     Input device-specific policy should be in terms of type
> > >
> > > +                  EFI_PCI_CONF_MAX_PAYLOAD_SIZE
> > >
> > > +
> > >
> > > +  @retval         Range values for the Max_Payload_Size as defined in the
> > PCI
> > >
> > > +                  Base Specification 4.0
> > >
> > > +**/
> > >
> > > +UINT8
> > >
> > > +TranslateMpsSetupValueToPci (
> > >
> > > +  IN  UINT8                   MPS
> > >
> > > +);
> > >
> > > +
> > >
> > > +/**
> > >
> > > +  Routine to translate the given device-specific platform policy from type
> > >
> > > +  EFI_PCI_CONF_MAX_READ_REQ_SIZE to HW-specific value, as per PCI
> > > Base Specification
> > >
> > > +  Revision 4.0; for the PCI feature Max_Read_Req_Size.
> > >
> > > +
> > >
> > > +  @param  MRRS    Input device-specific policy should be in terms of type
> > >
> > > +                  EFI_PCI_CONF_MAX_READ_REQ_SIZE
> > >
> > > +
> > >
> > > +  @retval         Range values for the Max_Read_Req_Size as defined in the
> > > PCI
> > >
> > > +                  Base Specification 4.0
> > >
> > > +**/
> > >
> > > +UINT8
> > >
> > > +TranslateMrrsSetupValueToPci (
> > >
> > > +  IN  UINT8                   MRRS
> > >
> > > +);
> > >
> > > +#endif
> > >
> > > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c
> > > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c
> > > index 4969ee0f64..755423f77b 100644
> > > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c
> > > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c
> > > @@ -198,20 +198,7 @@ CalculateApertureIo16 (
> > >      //
> > >
> > >      Status = EFI_NOT_FOUND;
> > >
> > >      PciPolicy = 0;
> > >
> > > -    if (gPciPlatformProtocol != NULL) {
> > >
> > > -      Status = gPciPlatformProtocol->GetPlatformPolicy (
> > >
> > > -                                       gPciPlatformProtocol,
> > >
> > > -                                       &PciPolicy
> > >
> > > -                                       );
> > >
> > > -    }
> > >
> > > -
> > >
> > > -    if (EFI_ERROR (Status) && gPciOverrideProtocol != NULL) {
> > >
> > > -      Status = gPciOverrideProtocol->GetPlatformPolicy (
> > >
> > > -                                       gPciOverrideProtocol,
> > >
> > > -                                       &PciPolicy
> > >
> > > -                                       );
> > >
> > > -    }
> > >
> > > -
> > >
> > > +    Status = PciGetPlatformPolicy ( &PciPolicy);
> > >
> > >      if (!EFI_ERROR (Status)) {
> > >
> > >        if ((PciPolicy & EFI_RESERVE_ISA_IO_ALIAS) != 0) {
> > >
> > >          mReserveIsaAliases = TRUE;
> > >
> > > diff --git a/MdeModulePkg/MdeModulePkg.dec
> > > b/MdeModulePkg/MdeModulePkg.dec
> > > index 17beb45235..7bcbe5a3ea 100644
> > > --- a/MdeModulePkg/MdeModulePkg.dec
> > > +++ b/MdeModulePkg/MdeModulePkg.dec
> > > @@ -1026,6 +1026,16 @@
> > >    # @Prompt Enable UEFI Stack Guard.
> > >
> > >
> > >
> > gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard|FALSE|BOOLEAN|0
> > > x30001055
> > >
> > >
> > >
> > > +  ## This PCD is to indicate the PCI Bus driver to setup other new PCI
> > > features.
> > >
> > > +  #  Each PCI feature is represented by its mask bit position and it
> > configures
> > >
> > > +  #  if that bit is set.
> > >
> > > +  #
> > >
> > > +  #   Bit 0 - if set, the PCI Bus driver programs the device's
> > > Max_Payload_Size.<BR>
> > >
> > > +  #   Bit 1 - if set, the PCI Bus driver programs the device's
> > > Max_Read_Req_Size.<BR>
> > >
> > > +  #   Bit 2 to 31 - Reserved for future use by the PCI Bus driver.<BR>
> > >
> > > +  # @Prompt The UEFI PCU Bus driver enables the new set of other PCI
> > > Features.
> > >
> > > +
> > >
> > gEfiMdeModulePkgTokenSpaceGuid.PcdOtherPciFeatures|0x00000003|UIN
> > > T32|0x30001056
> > >
> > > +
> > >
> > >  [PcdsFixedAtBuild, PcdsPatchableInModule]
> > >
> > >    ## Dynamic type PCD can be registered callback function for Pcd setting
> > > action.
> > >
> > >    #  PcdMaxPeiPcdCallBackNumberPerPcdEntry indicates the maximum
> > > number of callback function
> > >
> > > --
> > > 2.21.0.windows.1


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

View/Reply Online (#48974): https://edk2.groups.io/g/devel/message/48974
Mute This Topic: https://groups.io/mt/34264504/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub  [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-

Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH] PciBusDxe: New PCI features Max_Payload_Size, Max_Read_Req_Size
Posted by Ni, Ray 4 years, 5 months ago
> > More comments:
> > 1. IsPciRootPortEmpty(): can you just check whether PciDevice->ChildList is
> > empty by using IsListEmpty (&PciDevice->ChildList)?
> OK, will do the additional check.

Can that be the only check?

> 
> > 2. Can you point to me which spec requires the MPS to be 128 for empty
> root
> > ports?
> Refer the PCI Express Base Specification Revision 5, chapter 7.5.3.4
> Implementation Notes section.
Can you please paste the specific wording that supports the logic to program MPS to 128B for empty root ports?
Below wording seems to require 128B only for special OSes that don't support PCIE.
" For example, if the operating system environment does not comprehend PCI Express, firmware probably should
not program a non-default Max_Payload_Size for a hierarchy that supports Hot-Plug operations"

> 
> > 3. GetPciRootPortBusAssigned() is dangerous because it assumes the input
> > PciDevice points to the bridge.
> Good catch! Will make the right change.

As we discussed over phone, using device path can eliminate the needs of comparing bus number. Then this function is not needed.

> 
> > 4. RecordPciRootPortBridges() could be simplified to just collect all
> PciDevice
> > instances who:
> >     a. belongs to the linked list of the root bridge
> >     b. is a bridge
> I can see if I can optimize further, but do note that I need to align the PCI
> feature Max_Payload_Size and Max_Read_Request_Size among all the child
> PCI devices of the Root Port (RP) in the Root Complex (RC) and since a single
> RC is known to have multiple RP I need to maintain the list of all the primary
> RP in the Root Bridge handle so that each primary RP can have its PCI
> configuration table to track the Max_Payload_Size and
> Max_Read_Request_Size that needs to be assigned to all its child PCI devices
> in the tree.

I am not suggesting to stop collecting all root ports.
Can you simplify the logic of RecordPciRootPortBridges() as below?
  for each node in PciRootBridge.ChildList:
    if (!IsListEmpty (node.ChildList)) {
      RootPortList.add (node)

> > > 2. GetPciPlatformProtocol(): better to rename to InitializePciPlatform ().
> To me, the word "Initialize" would mean also installing the PCI Platform
> Protocol which is not the case with the PCI Bus driver; since it only fetches
> the existing protocol already installed by the platform...
I agree with your concern : )
But "Get" means to return the PciPlatform protocol back through function return result.
How about "Locate"?

> 
> > > 3. Why the type cast is needed in below code? If it is because
> PciPlatform2
> > > protocol reuses the prototype of GetPciRom defined for PciPlatform
> protocol,
> > > I suggest you define GetPciRom for PciPlatform2. Type redefinition
> seems a
> > > duplication. But below type-cast is more annoyed.
> > >
> > >     Status = mPciPlatformProtocol2->GetPciRom (
> > >
> > (EFI_PCI_PLATFORM_PROTOCOL*)mPciPlatformProtocol2,
> > >                                       PciIoDevice->Handle,
> > >                                       &PlatformOpRomBuffer,
> > >                                       &PlatformOpRomSize
> > >                                       );
> > >
> Yes, the PciPlatform2.h which I had submitted to the edk2-staging branch
> previously; includes the PciPlatform.h during compilation. Even I was thinking
> the same and since the new definition of the PCI Platform Protocol has to
> used in future; I can port the legacy definitions into the new definition source
> file itself to avoid further change in future.

Thanks.

> 
> > > 4. Please run ECC tool and fix all coding style issue
> I thought the ECC tool is used once the changes are submitted into the
> Gerritt by the maintainer; it is good if I can use it offline; please let me know
> where to get this tool.

The tool is inside BaseTools\BinWrappers\WindowsLike\Ecc.bat.

> 
> > > 5. I don't quite understand what *primary* PCI root port is. So I don't
> quite
> > > understand what RecordPciRootPortBridges() does.
> I used the word primary for the PCI Root port to indicate the first level Root
> port in the RC of the host; there can be multiple first level PCI RP in the Root
> Bridge handle and each RP can have its downstream hierarchy which in turn
> can be the PCIe-PCIe/PCI/PCI-X bridge devices and its endpoint devices.
> Since the RP and its downstream PCI bridges both have the same PCI Type 1
> PCI Configuration header, I have to maintain the list of first level RP of the
> Root Bridge handle.
> 
> > >
> > > Thanks,
> > > Ray
> > >
> > > > -----Original Message-----
> > > > From: Javeed, Ashraf <ashraf.javeed@intel.com>
> > > > Sent: Monday, September 23, 2019 10:21 PM
> > > > To: devel@edk2.groups.io
> > > > Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A
> > > <hao.a.wu@intel.com>;
> > > > Ni, Ray <ray.ni@intel.com>
> > > > Subject: [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH] PciBusDxe: New
> PCI
> > > > features Max_Payload_Size, Max_Read_Req_Size
> > > >
> > > > REF: https://bugzilla.tianocore.org/show_bug.cgi?id=2194
> > > >
> > > > The EDK2 Kernel PciBusDxe driver is enhanced to enable the
> configuration
> > > > of PCI features like Max_Payload_Size and Max_Read_Req_Size.
> > > >
> > > > Max_Payload_Size:- The PCI Device Control register provides this
> feature
> > > > register field which controls the maximum data packet (TLP) size that a
> > > > PCI device should maintain as a requester. The PCI Bus driver is
> required
> > > > to maintain a highest common value supported by all the PCI devices in
> a
> > > > PCIe hierarchy, especially in case of isochronous applications.
> > > >
> > > > Max_Read_Req_Size:- The PCI Device Control register provides this
> > > feature
> > > > register field which controls the maximum memory read request size
> that a
> > > > PCI device should maintain as a requester. The PCI Bus driver is
> required
> > > > to maintain a common value, same as Max_Payload_Size, in case of
> > > > isochronous applications only; or else, it should maintain the user
> > > > requested value uniformly in a PCIe hierarchy (PCI root port and its
> > > > downstream devices).
> > > >
> > > > The PCI Base Specification 4 Revision 1 contains detailed information
> > > > about these features. The EDK2 PCI Bus driver needs to enable the
> > > > configuration of these features as per the PCI Base specification.
> > > >
> > > > The EDK2 PCI Bus driver also needs to take the PCI device-specific
> > > > platform policy into the consideration while programming these
> features;
> > > > thus the code changes to support these, is explicitly dependent on the
> > > > new PCI Platform Protocol interface definition defined in the below
> > > > record:-
> > > > https://bugzilla.tianocore.org/show_bug.cgi?id=1954
> > > >
> > > > Signed-off-by: Ashraf Javeed <ashraf.javeed@intel.com>
> > > > Cc: Jian J Wang <jian.j.wang@intel.com>
> > > > Cc: Hao A Wu <hao.a.wu@intel.com>
> > > > Cc: Ray Ni <ray.ni@intel.com>
> > > > ---
> > > >  MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c               |   23 ++------------
> > > >  MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h               |   14 ++++++++-
> > > >  MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf          |    9 +++++-
> > > >  MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c     |  229
> > > >
> > >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > ++++++++++++++++++++++++++++------------------------------------------
> -----
> > > -
> > > >  MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c        |  139
> > > > ++++++++++++++++++++-------------------------------------------------------
> ----
> > > ---
> > > >  MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c |   34
> > > > ++++++++++++--------
> > > >  MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c    | 1601
> > > >
> > >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > >
> > >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > >
> > >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > >
> > >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > >
> > >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > >
> > >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > >
> > >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > >
> > >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > >
> > >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > >
> > >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > >
> > >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > >
> > >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > >
> > >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > >
> > >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > >
> > >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > >
> > >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > +++++++++
> > > >  MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h    |  201
> > > >
> > >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > >
> > >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > ++
> > > >  MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c   |  565
> > > >
> > >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > >
> > >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > >
> > >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > >
> > >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > >
> > >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > +++++++++++++++++++++++++++++++++++++++++
> > > >  MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h   |  193
> > > >
> > >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > >
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > >  MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c   |   15 +-----
> ---
> > > >  MdeModulePkg/MdeModulePkg.dec                         |   10 ++++++
> > > >  12 files changed, 2797 insertions(+), 236 deletions(-)
> > > >
> > > > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c
> > > > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c
> > > > index b020ce50ce..2503b298f4 100644
> > > > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c
> > > > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c
> > > > @@ -8,7 +8,7 @@
> > > >    PCI Root Bridges. So it means platform needs install PCI Root Bridge IO
> > > > protocol for each
> > > >
> > > >    PCI Root Bus and install PCI Host Bridge Resource Allocation Protocol.
> > > >
> > > >
> > > >
> > > > -Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
> > > >
> > > > +Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
> > > >
> > > >  SPDX-License-Identifier: BSD-2-Clause-Patent
> > > >
> > > >
> > > >
> > > >  **/
> > > >
> > > > @@ -34,8 +34,6 @@ BOOLEAN                                       gFullEnumeration     =
> > > TRUE;
> > > >  UINT64                                        gAllOne              = 0xFFFFFFFFFFFFFFFFULL;
> > > >
> > > >  UINT64                                        gAllZero             = 0;
> > > >
> > > >
> > > >
> > > > -EFI_PCI_PLATFORM_PROTOCOL                     *gPciPlatformProtocol;
> > > >
> > > > -EFI_PCI_OVERRIDE_PROTOCOL                     *gPciOverrideProtocol;
> > > >
> > > >  EDKII_IOMMU_PROTOCOL                          *mIoMmuProtocol;
> > > >
> > > >
> > > >
> > > >
> > > >
> > > > @@ -266,24 +264,7 @@ PciBusDriverBindingStart (
> > > >    // If PCI Platform protocol is available, get it now.
> > > >
> > > >    // If the platform implements this, it must be installed before BDS
> phase
> > > >
> > > >    //
> > > >
> > > > -  gPciPlatformProtocol = NULL;
> > > >
> > > > -  gBS->LocateProtocol (
> > > >
> > > > -        &gEfiPciPlatformProtocolGuid,
> > > >
> > > > -        NULL,
> > > >
> > > > -        (VOID **) &gPciPlatformProtocol
> > > >
> > > > -        );
> > > >
> > > > -
> > > >
> > > > -  //
> > > >
> > > > -  // If PCI Platform protocol doesn't exist, try to Pci Override Protocol.
> > > >
> > > > -  //
> > > >
> > > > -  if (gPciPlatformProtocol == NULL) {
> > > >
> > > > -    gPciOverrideProtocol = NULL;
> > > >
> > > > -    gBS->LocateProtocol (
> > > >
> > > > -          &gEfiPciOverrideProtocolGuid,
> > > >
> > > > -          NULL,
> > > >
> > > > -          (VOID **) &gPciOverrideProtocol
> > > >
> > > > -          );
> > > >
> > > > -  }
> > > >
> > > > +  GetPciPlatformProtocol ();
> > > >
> > > >
> > > >
> > > >    if (mIoMmuProtocol == NULL) {
> > > >
> > > >      gBS->LocateProtocol (
> > > >
> > > > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> > > > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> > > > index 504a1b1c12..7955bf8a26 100644
> > > > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> > > > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> > > > @@ -27,6 +27,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
> > > >  #include <Protocol/PciOverride.h>
> > > >
> > > >  #include <Protocol/PciEnumerationComplete.h>
> > > >
> > > >  #include <Protocol/IoMmu.h>
> > > >
> > > > +#include <Protocol/PciPlatform2.h>
> > > >
> > > > +#include <Protocol/PciOverride2.h>
> > > >
> > > >
> > > >
> > > >  #include <Library/DebugLib.h>
> > > >
> > > >  #include <Library/UefiDriverEntryPoint.h>
> > > >
> > > > @@ -79,6 +81,7 @@ typedef enum {
> > > >  #include "PciPowerManagement.h"
> > > >
> > > >  #include "PciHotPlugSupport.h"
> > > >
> > > >  #include "PciLib.h"
> > > >
> > > > +#include "PciFeatureSupport.h"
> > > >
> > > >
> > > >
> > > >  #define VGABASE1  0x3B0
> > > >
> > > >  #define VGALIMIT1 0x3BB
> > > >
> > > > @@ -263,9 +266,13 @@ struct _PCI_IO_DEVICE {
> > > >
> > > >
> > > >    BOOLEAN                                   IsPciExp;
> > > >
> > > >    //
> > > >
> > > > -  // For SR-IOV
> > > >
> > > > +  // For PCI Express Capability List Structure
> > > >
> > > >    //
> > > >
> > > >    UINT8                                     PciExpressCapabilityOffset;
> > > >
> > > > +  PCI_CAPABILITY_PCIEXP                     PciExpStruct;
> > > >
> > > > +  //
> > > >
> > > > +  // For SR-IOV
> > > >
> > > > +  //
> > > >
> > > >    UINT32                                    AriCapabilityOffset;
> > > >
> > > >    UINT32                                    SrIovCapabilityOffset;
> > > >
> > > >    UINT32                                    MrIovCapabilityOffset;
> > > >
> > > > @@ -279,6 +286,11 @@ struct _PCI_IO_DEVICE {
> > > >    // This field is used to support this case.
> > > >
> > > >    //
> > > >
> > > >    UINT16                                    BridgeIoAlignment;
> > > >
> > > > +  //
> > > >
> > > > +  // Other PCI features setup flags
> > > >
> > > > +  //
> > > >
> > > > +  UINT8                                     SetupMPS;
> > > >
> > > > +  UINT8                                     SetupMRRS;
> > > >
> > > >  };
> > > >
> > > >
> > > >
> > > >  #define PCI_IO_DEVICE_FROM_PCI_IO_THIS(a) \
> > > >
> > > > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
> > > > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
> > > > index 05c22025b8..13768d7ded 100644
> > > > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
> > > > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
> > > > @@ -2,7 +2,7 @@
> > > >  #  The PCI bus driver will probe all PCI devices and allocate MMIO and
> IO
> > > > space for these devices.
> > > >
> > > >  #  Please use PCD feature flag PcdPciBusHotplugDeviceSupport to
> enable
> > > > hot plug supporting.
> > > >
> > > >  #
> > > >
> > > > -#  Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
> > > >
> > > > +#  Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
> > > >
> > > >  #
> > > >
> > > >  #  SPDX-License-Identifier: BSD-2-Clause-Patent
> > > >
> > > >  #
> > > >
> > > > @@ -57,6 +57,10 @@
> > > >    PciCommand.h
> > > >
> > > >    PciIo.h
> > > >
> > > >    PciBus.h
> > > >
> > > > +  PciFeatureSupport.c
> > > >
> > > > +  PciFeatureSupport.h
> > > >
> > > > +  PciPlatformSupport.c
> > > >
> > > > +  PciPlatformSupport.h
> > > >
> > > >
> > > >
> > > >  [Packages]
> > > >
> > > >    MdePkg/MdePkg.dec
> > > >
> > > > @@ -91,6 +95,8 @@
> > > >    gEfiLoadFile2ProtocolGuid                       ## SOMETIMES_PRODUCES
> > > >
> > > >    gEdkiiIoMmuProtocolGuid                         ## SOMETIMES_CONSUMES
> > > >
> > > >    gEfiLoadedImageDevicePathProtocolGuid           ## CONSUMES
> > > >
> > > > +  gEfiPciPlatformProtocol2Guid                     ## SOMETIMES_CONSUMES
> > > >
> > > > +  gEfiPciOverrideProtocol2Guid                     ## SOMETIMES_CONSUMES
> > > >
> > > >
> > > >
> > > >  [FeaturePcd]
> > > >
> > > >    gEfiMdeModulePkgTokenSpaceGuid.PcdPciBusHotplugDeviceSupport
> > > ##
> > > > CONSUMES
> > > >
> > > > @@ -104,6 +110,7 @@
> > > >    gEfiMdeModulePkgTokenSpaceGuid.PcdAriSupport                  ##
> > > CONSUMES
> > > >
> > > >    gEfiMdeModulePkgTokenSpaceGuid.PcdMrIovSupport                ##
> > > > CONSUMES
> > > >
> > > >    gEfiMdeModulePkgTokenSpaceGuid.PcdPciDisableBusEnumeration
> ##
> > > > SOMETIMES_CONSUMES
> > > >
> > > > +  gEfiMdeModulePkgTokenSpaceGuid.PcdOtherPciFeatures
> ##
> > > > CONSUMES
> > > >
> > > >
> > > >
> > > >  [UserExtensions.TianoCore."ExtraFiles"]
> > > >
> > > >    PciBusDxeExtra.uni
> > > >
> > > > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
> > > > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
> > > > index b7832c6970..0f76ab1cd5 100644
> > > > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
> > > > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
> > > > @@ -170,6 +170,8 @@ DestroyRootBridgeByHandle (
> > > >
> > > >
> > > >      if (Temp->Handle == Controller) {
> > > >
> > > >
> > > >
> > > > +      DestroyRootBridgePciFeaturesConfigCompletionList ( Temp);
> > > >
> > > > +
> > > >
> > > >        RemoveEntryList (CurrentLink);
> > > >
> > > >
> > > >
> > > >        DestroyPciDeviceTree (Temp);
> > > >
> > > > @@ -208,8 +210,6 @@ RegisterPciDevice (
> > > >    )
> > > >
> > > >  {
> > > >
> > > >    EFI_STATUS          Status;
> > > >
> > > > -  VOID                *PlatformOpRomBuffer;
> > > >
> > > > -  UINTN               PlatformOpRomSize;
> > > >
> > > >    EFI_PCI_IO_PROTOCOL *PciIo;
> > > >
> > > >    UINT8               Data8;
> > > >
> > > >    BOOLEAN             HasEfiImage;
> > > >
> > > > @@ -244,49 +244,13 @@ RegisterPciDevice (
> > > >      //
> > > >
> > > >      // Get the OpRom provided by platform
> > > >
> > > >      //
> > > >
> > > > -    if (gPciPlatformProtocol != NULL) {
> > > >
> > > > -      Status = gPciPlatformProtocol->GetPciRom (
> > > >
> > > > -                                       gPciPlatformProtocol,
> > > >
> > > > -                                       PciIoDevice->Handle,
> > > >
> > > > -                                       &PlatformOpRomBuffer,
> > > >
> > > > -                                       &PlatformOpRomSize
> > > >
> > > > -                                       );
> > > >
> > > > -      if (!EFI_ERROR (Status)) {
> > > >
> > > > -        PciIoDevice->EmbeddedRom    = FALSE;
> > > >
> > > > -        PciIoDevice->RomSize        = (UINT32) PlatformOpRomSize;
> > > >
> > > > -        PciIoDevice->PciIo.RomSize  = PlatformOpRomSize;
> > > >
> > > > -        PciIoDevice->PciIo.RomImage = PlatformOpRomBuffer;
> > > >
> > > > -        //
> > > >
> > > > -        // For OpROM read from gPciPlatformProtocol:
> > > >
> > > > -        // Add the Rom Image to internal database for later PCI light
> > > > enumeration
> > > >
> > > > -        //
> > > >
> > > > -        PciRomAddImageMapping (
> > > >
> > > > -          NULL,
> > > >
> > > > -          PciIoDevice->PciRootBridgeIo->SegmentNumber,
> > > >
> > > > -          PciIoDevice->BusNumber,
> > > >
> > > > -          PciIoDevice->DeviceNumber,
> > > >
> > > > -          PciIoDevice->FunctionNumber,
> > > >
> > > > -          PciIoDevice->PciIo.RomImage,
> > > >
> > > > -          PciIoDevice->PciIo.RomSize
> > > >
> > > > -          );
> > > >
> > > > -      }
> > > >
> > > > -    } else if (gPciOverrideProtocol != NULL) {
> > > >
> > > > -      Status = gPciOverrideProtocol->GetPciRom (
> > > >
> > > > -                                       gPciOverrideProtocol,
> > > >
> > > > -                                       PciIoDevice->Handle,
> > > >
> > > > -                                       &PlatformOpRomBuffer,
> > > >
> > > > -                                       &PlatformOpRomSize
> > > >
> > > > -                                       );
> > > >
> > > > -      if (!EFI_ERROR (Status)) {
> > > >
> > > > -        PciIoDevice->EmbeddedRom    = FALSE;
> > > >
> > > > -        PciIoDevice->RomSize        = (UINT32) PlatformOpRomSize;
> > > >
> > > > -        PciIoDevice->PciIo.RomSize  = PlatformOpRomSize;
> > > >
> > > > -        PciIoDevice->PciIo.RomImage = PlatformOpRomBuffer;
> > > >
> > > > -        //
> > > >
> > > > -        // For OpROM read from gPciOverrideProtocol:
> > > >
> > > > -        // Add the Rom Image to internal database for later PCI light
> > > > enumeration
> > > >
> > > > -        //
> > > >
> > > > -        PciRomAddImageMapping (
> > > >
> > > > +    Status = GetPlatformPciOptionRom ( Controller, PciIoDevice);
> > > >
> > > > +    if (!EFI_ERROR (Status)) {
> > > >
> > > > +      //
> > > >
> > > > +      // For OpROM read from the PCI Platform Protocol:
> > > >
> > > > +      // Add the Rom Image to internal database for later PCI light
> > > > enumeration
> > > >
> > > > +      //
> > > >
> > > > +      PciRomAddImageMapping (
> > > >
> > > >            NULL,
> > > >
> > > >            PciIoDevice->PciRootBridgeIo->SegmentNumber,
> > > >
> > > >            PciIoDevice->BusNumber,
> > > >
> > > > @@ -294,8 +258,7 @@ RegisterPciDevice (
> > > >            PciIoDevice->FunctionNumber,
> > > >
> > > >            PciIoDevice->PciIo.RomImage,
> > > >
> > > >            PciIoDevice->PciIo.RomSize
> > > >
> > > > -          );
> > > >
> > > > -      }
> > > >
> > > > +        );
> > > >
> > > >      }
> > > >
> > > >    }
> > > >
> > > >
> > > >
> > > > @@ -597,7 +560,7 @@ DeRegisterPciDevice (
> > > >  }
> > > >
> > > >
> > > >
> > > >  /**
> > > >
> > > > -  Start to manage the PCI device on the specified root bridge or PCI-PCI
> > > > Bridge.
> > > >
> > > > +  Start the PCI root Ports or PCI-PCI Bridge only.
> > > >
> > > >
> > > >
> > > >    @param Controller          The root bridge handle.
> > > >
> > > >    @param RootBridge          A pointer to the PCI_IO_DEVICE.
> > > >
> > > > @@ -612,7 +575,82 @@ DeRegisterPciDevice (
> > > >
> > > >
> > > >  **/
> > > >
> > > >  EFI_STATUS
> > > >
> > > > -StartPciDevicesOnBridge (
> > > >
> > > > +StartPciRootPortsOnBridge (
> > > >
> > > > +  IN EFI_HANDLE                          Controller,
> > > >
> > > > +  IN PCI_IO_DEVICE                       *RootBridge
> > > >
> > > > +  )
> > > >
> > > > +
> > > >
> > > > +{
> > > >
> > > > +  PCI_IO_DEVICE             *PciIoDevice;
> > > >
> > > > +  EFI_STATUS                Status;
> > > >
> > > > +  LIST_ENTRY                *CurrentLink;
> > > >
> > > > +  UINT64                    Supports;
> > > >
> > > > +
> > > >
> > > > +  PciIoDevice = NULL;
> > > >
> > > > +  CurrentLink = RootBridge->ChildList.ForwardLink;
> > > >
> > > > +
> > > >
> > > > +  while (CurrentLink != NULL && CurrentLink != &RootBridge->ChildList)
> {
> > > >
> > > > +
> > > >
> > > > +    PciIoDevice = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
> > > >
> > > > +
> > > >
> > > > +    //
> > > >
> > > > +    // check if the device has been assigned with required resource
> > > >
> > > > +    // and registered
> > > >
> > > > +    //
> > > >
> > > > +    if (!PciIoDevice->Registered && !PciIoDevice->Allocated) {
> > > >
> > > > +      return EFI_NOT_READY;
> > > >
> > > > +    }
> > > >
> > > > +
> > > >
> > > > +    if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {
> > > >
> > > > +      Status = StartPciRootPortsOnBridge (
> > > >
> > > > +                 Controller,
> > > >
> > > > +                 PciIoDevice
> > > >
> > > > +                 );
> > > >
> > > > +
> > > >
> > > > +      PciIoDevice->PciIo.Attributes (
> > > >
> > > > +                           &(PciIoDevice->PciIo),
> > > >
> > > > +                           EfiPciIoAttributeOperationSupported,
> > > >
> > > > +                           0,
> > > >
> > > > +                           &Supports
> > > >
> > > > +                         );
> > > >
> > > > +      Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;
> > > >
> > > > +      PciIoDevice->PciIo.Attributes (
> > > >
> > > > +                           &(PciIoDevice->PciIo),
> > > >
> > > > +                           EfiPciIoAttributeOperationEnable,
> > > >
> > > > +                           Supports,
> > > >
> > > > +                           NULL
> > > >
> > > > +                         );
> > > >
> > > > +
> > > >
> > > > +    }
> > > >
> > > > +
> > > >
> > > > +    CurrentLink = CurrentLink->ForwardLink;
> > > >
> > > > +  }
> > > >
> > > > +
> > > >
> > > > +  if (PciIoDevice == NULL) {
> > > >
> > > > +    return EFI_NOT_FOUND;
> > > >
> > > > +  } else {
> > > >
> > > > +    return EFI_SUCCESS;
> > > >
> > > > +  }
> > > >
> > > > +}
> > > >
> > > > +
> > > >
> > > > +
> > > >
> > > > +/**
> > > >
> > > > +  Register to manage the PCI device on the specified root bridge or
> PCI-PCI
> > > > Bridge.
> > > >
> > > > +
> > > >
> > > > +  @param Controller          The root bridge handle.
> > > >
> > > > +  @param RootBridge          A pointer to the PCI_IO_DEVICE.
> > > >
> > > > +  @param RemainingDevicePath A pointer to the
> > > > EFI_DEVICE_PATH_PROTOCOL.
> > > >
> > > > +  @param NumberOfChildren    Children number.
> > > >
> > > > +  @param ChildHandleBuffer   A pointer to the child handle buffer.
> > > >
> > > > +
> > > >
> > > > +  @retval EFI_NOT_READY   Device is not allocated.
> > > >
> > > > +  @retval EFI_UNSUPPORTED Device only support PCI-PCI bridge.
> > > >
> > > > +  @retval EFI_NOT_FOUND   Can not find the specific device.
> > > >
> > > > +  @retval EFI_SUCCESS     Success to start Pci devices on bridge.
> > > >
> > > > +
> > > >
> > > > +**/
> > > >
> > > > +EFI_STATUS
> > > >
> > > > +RegisterPciDevicesOnBridge (
> > > >
> > > >    IN EFI_HANDLE                          Controller,
> > > >
> > > >    IN PCI_IO_DEVICE                       *RootBridge,
> > > >
> > > >    IN EFI_DEVICE_PATH_PROTOCOL            *RemainingDevicePath,
> > > >
> > > > @@ -626,7 +664,6 @@ StartPciDevicesOnBridge (
> > > >    EFI_DEVICE_PATH_PROTOCOL  *CurrentDevicePath;
> > > >
> > > >    EFI_STATUS                Status;
> > > >
> > > >    LIST_ENTRY                *CurrentLink;
> > > >
> > > > -  UINT64                    Supports;
> > > >
> > > >
> > > >
> > > >    PciIoDevice = NULL;
> > > >
> > > >    CurrentLink = RootBridge->ChildList.ForwardLink;
> > > >
> > > > @@ -681,7 +718,7 @@ StartPciDevicesOnBridge (
> > > >        // If it is a PPB
> > > >
> > > >        //
> > > >
> > > >        if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {
> > > >
> > > > -        Status = StartPciDevicesOnBridge (
> > > >
> > > > +        Status = RegisterPciDevicesOnBridge (
> > > >
> > > >                     Controller,
> > > >
> > > >                     PciIoDevice,
> > > >
> > > >                     CurrentDevicePath,
> > > >
> > > > @@ -689,20 +726,6 @@ StartPciDevicesOnBridge (
> > > >                     ChildHandleBuffer
> > > >
> > > >                     );
> > > >
> > > >
> > > >
> > > > -        PciIoDevice->PciIo.Attributes (
> > > >
> > > > -                             &(PciIoDevice->PciIo),
> > > >
> > > > -                             EfiPciIoAttributeOperationSupported,
> > > >
> > > > -                             0,
> > > >
> > > > -                             &Supports
> > > >
> > > > -                             );
> > > >
> > > > -        Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;
> > > >
> > > > -        PciIoDevice->PciIo.Attributes (
> > > >
> > > > -                             &(PciIoDevice->PciIo),
> > > >
> > > > -                             EfiPciIoAttributeOperationEnable,
> > > >
> > > > -                             Supports,
> > > >
> > > > -                             NULL
> > > >
> > > > -                             );
> > > >
> > > > -
> > > >
> > > >          return Status;
> > > >
> > > >        } else {
> > > >
> > > >
> > > >
> > > > @@ -733,28 +756,13 @@ StartPciDevicesOnBridge (
> > > >        }
> > > >
> > > >
> > > >
> > > >        if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {
> > > >
> > > > -        Status = StartPciDevicesOnBridge (
> > > >
> > > > +        Status = RegisterPciDevicesOnBridge (
> > > >
> > > >                     Controller,
> > > >
> > > >                     PciIoDevice,
> > > >
> > > >                     RemainingDevicePath,
> > > >
> > > >                     NumberOfChildren,
> > > >
> > > >                     ChildHandleBuffer
> > > >
> > > >                     );
> > > >
> > > > -
> > > >
> > > > -        PciIoDevice->PciIo.Attributes (
> > > >
> > > > -                             &(PciIoDevice->PciIo),
> > > >
> > > > -                             EfiPciIoAttributeOperationSupported,
> > > >
> > > > -                             0,
> > > >
> > > > -                             &Supports
> > > >
> > > > -                             );
> > > >
> > > > -        Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;
> > > >
> > > > -        PciIoDevice->PciIo.Attributes (
> > > >
> > > > -                             &(PciIoDevice->PciIo),
> > > >
> > > > -                             EfiPciIoAttributeOperationEnable,
> > > >
> > > > -                             Supports,
> > > >
> > > > -                             NULL
> > > >
> > > > -                             );
> > > >
> > > > -
> > > >
> > > >        }
> > > >
> > > >
> > > >
> > > >        CurrentLink = CurrentLink->ForwardLink;
> > > >
> > > > @@ -768,6 +776,65 @@ StartPciDevicesOnBridge (
> > > >    }
> > > >
> > > >  }
> > > >
> > > >
> > > >
> > > > +/**
> > > >
> > > > +  Start to manage the PCI device on the specified root bridge or PCI-PCI
> > > > Bridge.
> > > >
> > > > +
> > > >
> > > > +  @param Controller          The root bridge handle.
> > > >
> > > > +  @param RootBridge          A pointer to the PCI_IO_DEVICE.
> > > >
> > > > +  @param RemainingDevicePath A pointer to the
> > > > EFI_DEVICE_PATH_PROTOCOL.
> > > >
> > > > +  @param NumberOfChildren    Children number.
> > > >
> > > > +  @param ChildHandleBuffer   A pointer to the child handle buffer.
> > > >
> > > > +
> > > >
> > > > +  @retval EFI_NOT_READY   Device is not allocated.
> > > >
> > > > +  @retval EFI_UNSUPPORTED Device only support PCI-PCI bridge.
> > > >
> > > > +  @retval EFI_NOT_FOUND   Can not find the specific device.
> > > >
> > > > +  @retval EFI_SUCCESS     Success to start Pci devices on bridge.
> > > >
> > > > +
> > > >
> > > > +**/
> > > >
> > > > +EFI_STATUS
> > > >
> > > > +StartPciDevicesOnBridge (
> > > >
> > > > +  IN EFI_HANDLE                          Controller,
> > > >
> > > > +  IN PCI_IO_DEVICE                       *RootBridge,
> > > >
> > > > +  IN EFI_DEVICE_PATH_PROTOCOL            *RemainingDevicePath,
> > > >
> > > > +  IN OUT UINT8                           *NumberOfChildren,
> > > >
> > > > +  IN OUT EFI_HANDLE                      *ChildHandleBuffer
> > > >
> > > > +  )
> > > >
> > > > +
> > > >
> > > > +{
> > > >
> > > > +  EFI_STATUS                Status;
> > > >
> > > > +
> > > >
> > > > +  //
> > > >
> > > > +  // first register all the PCI devices
> > > >
> > > > +  //
> > > >
> > > > +  Status = RegisterPciDevicesOnBridge (
> > > >
> > > > +             Controller,
> > > >
> > > > +             RootBridge,
> > > >
> > > > +             RemainingDevicePath,
> > > >
> > > > +             NumberOfChildren,
> > > >
> > > > +             ChildHandleBuffer
> > > >
> > > > +             );
> > > >
> > > > +
> > > >
> > > > +  if (EFI_ERROR (Status) == EFI_NOT_FOUND) {
> > > >
> > > > +    return Status;
> > > >
> > > > +  } else {
> > > >
> > > > +    if ( CheckOtherPciFeaturesPcd ()) {
> > > >
> > > > +      //
> > > >
> > > > +      // the late configuration of PCI features
> > > >
> > > > +      //
> > > >
> > > > +      Status = EnumerateOtherPciFeatures (
> > > >
> > > > +                  RootBridge
> > > >
> > > > +                );
> > > >
> > > > +    }
> > > >
> > > > +    //
> > > >
> > > > +    // finally start those PCI bridge port devices only
> > > >
> > > > +    //
> > > >
> > > > +    return StartPciRootPortsOnBridge (
> > > >
> > > > +            Controller,
> > > >
> > > > +            RootBridge
> > > >
> > > > +            );
> > > >
> > > > +  }
> > > >
> > > > +}
> > > >
> > > > +
> > > >
> > > >  /**
> > > >
> > > >    Start to manage all the PCI devices it found previously under
> > > >
> > > >    the entire host bridge.
> > > >
> > > > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c
> > > > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c
> > > > index 8db1ebf8ec..0a56668380 100644
> > > > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c
> > > > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c
> > > > @@ -1003,7 +1003,7 @@ PciHostBridgeAdjustAllocation (
> > > >      Status = RejectPciDevice (PciResNode->PciDev);
> > > >
> > > >      if (Status == EFI_SUCCESS) {
> > > >
> > > >        DEBUG ((
> > > >
> > > > -        EFI_D_ERROR,
> > > >
> > > > +        DEBUG_ERROR,
> > > >
> > > >          "PciBus: [%02x|%02x|%02x] was rejected due to resource
> > > > confliction.\n",
> > > >
> > > >          PciResNode->PciDev->BusNumber, PciResNode->PciDev-
> > > > >DeviceNumber, PciResNode->PciDev->FunctionNumber
> > > >
> > > >          ));
> > > >
> > > > @@ -1746,7 +1746,7 @@ NotifyPhase (
> > > >
> > > >
> > > >    HostBridgeHandle  = NULL;
> > > >
> > > >    RootBridgeHandle  = NULL;
> > > >
> > > > -  if (gPciPlatformProtocol != NULL) {
> > > >
> > > > +  if ( CheckPciPlatformProtocolInstall()) {
> > > >
> > > >      //
> > > >
> > > >      // Get Host Bridge Handle.
> > > >
> > > >      //
> > > >
> > > > @@ -1770,42 +1770,11 @@ NotifyPhase (
> > > >      //
> > > >
> > > >      // Call PlatformPci::PlatformNotify() if the protocol is present.
> > > >
> > > >      //
> > > >
> > > > -    gPciPlatformProtocol->PlatformNotify (
> > > >
> > > > -                            gPciPlatformProtocol,
> > > >
> > > > -                            HostBridgeHandle,
> > > >
> > > > -                            Phase,
> > > >
> > > > -                            ChipsetEntry
> > > >
> > > > -                            );
> > > >
> > > > -  } else if (gPciOverrideProtocol != NULL){
> > > >
> > > > -    //
> > > >
> > > > -    // Get Host Bridge Handle.
> > > >
> > > > -    //
> > > >
> > > > -    PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle);
> > > >
> > > > -
> > > >
> > > > -    //
> > > >
> > > > -    // Get the rootbridge Io protocol to find the host bridge handle
> > > >
> > > > -    //
> > > >
> > > > -    Status = gBS->HandleProtocol (
> > > >
> > > > -                    RootBridgeHandle,
> > > >
> > > > -                    &gEfiPciRootBridgeIoProtocolGuid,
> > > >
> > > > -                    (VOID **) &PciRootBridgeIo
> > > >
> > > > -                    );
> > > >
> > > > -
> > > >
> > > > -    if (EFI_ERROR (Status)) {
> > > >
> > > > -      return EFI_NOT_FOUND;
> > > >
> > > > -    }
> > > >
> > > > -
> > > >
> > > > -    HostBridgeHandle = PciRootBridgeIo->ParentHandle;
> > > >
> > > > -
> > > >
> > > > -    //
> > > >
> > > > -    // Call PlatformPci::PhaseNotify() if the protocol is present.
> > > >
> > > > -    //
> > > >
> > > > -    gPciOverrideProtocol->PlatformNotify (
> > > >
> > > > -                            gPciOverrideProtocol,
> > > >
> > > > -                            HostBridgeHandle,
> > > >
> > > > -                            Phase,
> > > >
> > > > -                            ChipsetEntry
> > > >
> > > > -                            );
> > > >
> > > > +    PciPlatformNotifyPhase (
> > > >
> > > > +        HostBridgeHandle,
> > > >
> > > > +        Phase,
> > > >
> > > > +        ChipsetEntry
> > > >
> > > > +        );
> > > >
> > > >    }
> > > >
> > > >
> > > >
> > > >    Status = PciResAlloc->NotifyPhase (
> > > >
> > > > @@ -1813,27 +1782,15 @@ NotifyPhase (
> > > >                            Phase
> > > >
> > > >                            );
> > > >
> > > >
> > > >
> > > > -  if (gPciPlatformProtocol != NULL) {
> > > >
> > > > +  if ( CheckPciPlatformProtocolInstall()) {
> > > >
> > > >      //
> > > >
> > > >      // Call PlatformPci::PlatformNotify() if the protocol is present.
> > > >
> > > >      //
> > > >
> > > > -    gPciPlatformProtocol->PlatformNotify (
> > > >
> > > > -                            gPciPlatformProtocol,
> > > >
> > > > -                            HostBridgeHandle,
> > > >
> > > > -                            Phase,
> > > >
> > > > -                            ChipsetExit
> > > >
> > > > -                            );
> > > >
> > > > -
> > > >
> > > > -  } else if (gPciOverrideProtocol != NULL) {
> > > >
> > > > -    //
> > > >
> > > > -    // Call PlatformPci::PhaseNotify() if the protocol is present.
> > > >
> > > > -    //
> > > >
> > > > -    gPciOverrideProtocol->PlatformNotify (
> > > >
> > > > -                            gPciOverrideProtocol,
> > > >
> > > > -                            HostBridgeHandle,
> > > >
> > > > -                            Phase,
> > > >
> > > > -                            ChipsetExit
> > > >
> > > > -                            );
> > > >
> > > > +    PciPlatformNotifyPhase (
> > > >
> > > > +        HostBridgeHandle,
> > > >
> > > > +        Phase,
> > > >
> > > > +        ChipsetExit
> > > >
> > > > +        );
> > > >
> > > >    }
> > > >
> > > >
> > > >
> > > >    return Status;
> > > >
> > > > @@ -1914,31 +1871,16 @@ PreprocessController (
> > > >    RootBridgePciAddress.Bus              = Bus;
> > > >
> > > >    RootBridgePciAddress.ExtendedRegister = 0;
> > > >
> > > >
> > > >
> > > > -  if (gPciPlatformProtocol != NULL) {
> > > >
> > > > -    //
> > > >
> > > > -    // Call PlatformPci::PrepController() if the protocol is present.
> > > >
> > > > -    //
> > > >
> > > > -    gPciPlatformProtocol->PlatformPrepController (
> > > >
> > > > -                            gPciPlatformProtocol,
> > > >
> > > > -                            HostBridgeHandle,
> > > >
> > > > -                            RootBridgeHandle,
> > > >
> > > > -                            RootBridgePciAddress,
> > > >
> > > > -                            Phase,
> > > >
> > > > -                            ChipsetEntry
> > > >
> > > > -                            );
> > > >
> > > > -  } else if (gPciOverrideProtocol != NULL) {
> > > >
> > > > -    //
> > > >
> > > > -    // Call PlatformPci::PrepController() if the protocol is present.
> > > >
> > > > -    //
> > > >
> > > > -    gPciOverrideProtocol->PlatformPrepController (
> > > >
> > > > -                            gPciOverrideProtocol,
> > > >
> > > > -                            HostBridgeHandle,
> > > >
> > > > -                            RootBridgeHandle,
> > > >
> > > > -                            RootBridgePciAddress,
> > > >
> > > > -                            Phase,
> > > >
> > > > -                            ChipsetEntry
> > > >
> > > > -                            );
> > > >
> > > > -  }
> > > >
> > > > +  //
> > > >
> > > > +  // Call PlatformPci::PrepController() if the protocol is present.
> > > >
> > > > +  //
> > > >
> > > > +  PciPlatformPreprocessController (
> > > >
> > > > +      HostBridgeHandle,
> > > >
> > > > +      RootBridgeHandle,
> > > >
> > > > +      RootBridgePciAddress,
> > > >
> > > > +      Phase,
> > > >
> > > > +      ChipsetEntry
> > > >
> > > > +    );
> > > >
> > > >
> > > >
> > > >    Status = PciResAlloc->PreprocessController (
> > > >
> > > >                            PciResAlloc,
> > > >
> > > > @@ -1947,31 +1889,16 @@ PreprocessController (
> > > >                            Phase
> > > >
> > > >                            );
> > > >
> > > >
> > > >
> > > > -  if (gPciPlatformProtocol != NULL) {
> > > >
> > > > -    //
> > > >
> > > > -    // Call PlatformPci::PrepController() if the protocol is present.
> > > >
> > > > -    //
> > > >
> > > > -    gPciPlatformProtocol->PlatformPrepController (
> > > >
> > > > -                            gPciPlatformProtocol,
> > > >
> > > > -                            HostBridgeHandle,
> > > >
> > > > -                            RootBridgeHandle,
> > > >
> > > > -                            RootBridgePciAddress,
> > > >
> > > > -                            Phase,
> > > >
> > > > -                            ChipsetExit
> > > >
> > > > -                            );
> > > >
> > > > -  } else if (gPciOverrideProtocol != NULL) {
> > > >
> > > > -    //
> > > >
> > > > -    // Call PlatformPci::PrepController() if the protocol is present.
> > > >
> > > > -    //
> > > >
> > > > -    gPciOverrideProtocol->PlatformPrepController (
> > > >
> > > > -                            gPciOverrideProtocol,
> > > >
> > > > -                            HostBridgeHandle,
> > > >
> > > > -                            RootBridgeHandle,
> > > >
> > > > -                            RootBridgePciAddress,
> > > >
> > > > -                            Phase,
> > > >
> > > > -                            ChipsetExit
> > > >
> > > > -                            );
> > > >
> > > > -  }
> > > >
> > > > +  //
> > > >
> > > > +  // Call PlatformPci::PrepController() if the protocol is present.
> > > >
> > > > +  //
> > > >
> > > > +  PciPlatformPreprocessController (
> > > >
> > > > +      HostBridgeHandle,
> > > >
> > > > +      RootBridgeHandle,
> > > >
> > > > +      RootBridgePciAddress,
> > > >
> > > > +      Phase,
> > > >
> > > > +      ChipsetExit
> > > >
> > > > +    );
> > > >
> > > >
> > > >
> > > >    return EFI_SUCCESS;
> > > >
> > > >  }
> > > >
> > > > diff --git
> a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
> > > > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
> > > > index c7eafff593..2343702154 100644
> > > > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
> > > > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
> > > > @@ -230,7 +230,7 @@ PciSearchDevice (
> > > >    PciIoDevice = NULL;
> > > >
> > > >
> > > >
> > > >    DEBUG ((
> > > >
> > > > -    EFI_D_INFO,
> > > >
> > > > +    DEBUG_INFO,
> > > >
> > > >      "PciBus: Discovered %s @ [%02x|%02x|%02x]\n",
> > > >
> > > >      IS_PCI_BRIDGE (Pci) ?     L"PPB" :
> > > >
> > > >      IS_CARDBUS_BRIDGE (Pci) ? L"P2C" :
> > > >
> > > > @@ -397,7 +397,7 @@ DumpPpbPaddingResource (
> > > >
> > > >
> > > >      if ((Type != PciBarTypeUnknown) && ((ResourceType ==
> > > > PciBarTypeUnknown) || (ResourceType == Type))) {
> > > >
> > > >        DEBUG ((
> > > >
> > > > -        EFI_D_INFO,
> > > >
> > > > +        DEBUG_INFO,
> > > >
> > > >          "   Padding: Type = %s; Alignment = 0x%lx;\tLength = 0x%lx\n",
> > > >
> > > >          mBarTypeStr[Type], Descriptor->AddrRangeMax, Descriptor-
> >AddrLen
> > > >
> > > >          ));
> > > >
> > > > @@ -424,7 +424,7 @@ DumpPciBars (
> > > >      }
> > > >
> > > >
> > > >
> > > >      DEBUG ((
> > > >
> > > > -      EFI_D_INFO,
> > > >
> > > > +      DEBUG_INFO,
> > > >
> > > >        "   BAR[%d]: Type = %s; Alignment = 0x%lx;\tLength = 0x%lx;\tOffset
> =
> > > > 0x%02x\n",
> > > >
> > > >        Index, mBarTypeStr[MIN (PciIoDevice->PciBar[Index].BarType,
> > > > PciBarTypeMaxType)],
> > > >
> > > >        PciIoDevice->PciBar[Index].Alignment, PciIoDevice-
> > > > >PciBar[Index].Length, PciIoDevice->PciBar[Index].Offset
> > > >
> > > > @@ -437,13 +437,13 @@ DumpPciBars (
> > > >      }
> > > >
> > > >
> > > >
> > > >      DEBUG ((
> > > >
> > > > -      EFI_D_INFO,
> > > >
> > > > +      DEBUG_INFO,
> > > >
> > > >        " VFBAR[%d]: Type = %s; Alignment = 0x%lx;\tLength =
> 0x%lx;\tOffset =
> > > > 0x%02x\n",
> > > >
> > > >        Index, mBarTypeStr[MIN (PciIoDevice->VfPciBar[Index].BarType,
> > > > PciBarTypeMaxType)],
> > > >
> > > >        PciIoDevice->VfPciBar[Index].Alignment, PciIoDevice-
> > > > >VfPciBar[Index].Length, PciIoDevice->VfPciBar[Index].Offset
> > > >
> > > >        ));
> > > >
> > > >    }
> > > >
> > > > -  DEBUG ((EFI_D_INFO, "\n"));
> > > >
> > > > +  DEBUG ((DEBUG_INFO, "\n"));
> > > >
> > > >  }
> > > >
> > > >
> > > >
> > > >  /**
> > > >
> > > > @@ -1903,7 +1903,7 @@ PciParseBar (
> > > >        // Fix the length to support some special 64 bit BAR
> > > >
> > > >        //
> > > >
> > > >        if (Value == 0) {
> > > >
> > > > -        DEBUG ((EFI_D_INFO, "[PciBus]BAR probing for upper 32bit of
> MEM64
> > > > BAR returns 0, change to 0xFFFFFFFF.\n"));
> > > >
> > > > +        DEBUG ((DEBUG_INFO, "[PciBus]BAR probing for upper 32bit of
> > > MEM64
> > > > BAR returns 0, change to 0xFFFFFFFF.\n"));
> > > >
> > > >          Value = (UINT32) -1;
> > > >
> > > >        } else {
> > > >
> > > >          Value |= ((UINT32)(-1) << HighBitSet32 (Value));
> > > >
> > > > @@ -2153,7 +2153,17 @@ CreatePciIoDevice (
> > > >               NULL
> > > >
> > > >               );
> > > >
> > > >    if (!EFI_ERROR (Status)) {
> > > >
> > > > -    PciIoDevice->IsPciExp = TRUE;
> > > >
> > > > +  PciIoDevice->IsPciExp = TRUE;
> > > >
> > > > +    //
> > > >
> > > > +    // read the PCI device's entire PCI Express Capability structure
> > > >
> > > > +    //
> > > >
> > > > +    PciIo->Pci.Read (
> > > >
> > > > +                  PciIo,
> > > >
> > > > +                  EfiPciIoWidthUint8,
> > > >
> > > > +                  PciIoDevice->PciExpressCapabilityOffset,
> > > >
> > > > +                  sizeof (PCI_CAPABILITY_PCIEXP) / sizeof (UINT8),
> > > >
> > > > +                  &PciIoDevice->PciExpStruct
> > > >
> > > > +                );
> > > >
> > > >    }
> > > >
> > > >
> > > >
> > > >    if (PcdGetBool (PcdAriSupport)) {
> > > >
> > > > @@ -2206,7 +2216,7 @@ CreatePciIoDevice (
> > > >                                &Data32
> > > >
> > > >                                );
> > > >
> > > >            DEBUG ((
> > > >
> > > > -            EFI_D_INFO,
> > > >
> > > > +            DEBUG_INFO,
> > > >
> > > >              " ARI: forwarding enabled for PPB[%02x:%02x:%02x]\n",
> > > >
> > > >              Bridge->BusNumber,
> > > >
> > > >              Bridge->DeviceNumber,
> > > >
> > > > @@ -2215,7 +2225,7 @@ CreatePciIoDevice (
> > > >          }
> > > >
> > > >        }
> > > >
> > > >
> > > >
> > > > -      DEBUG ((EFI_D_INFO, " ARI: CapOffset = 0x%x\n", PciIoDevice-
> > > > >AriCapabilityOffset));
> > > >
> > > > +      DEBUG ((DEBUG_INFO, " ARI: CapOffset = 0x%x\n", PciIoDevice-
> > > > >AriCapabilityOffset));
> > > >
> > > >      }
> > > >
> > > >    }
> > > >
> > > >
> > > >
> > > > @@ -2325,12 +2335,12 @@ CreatePciIoDevice (
> > > >        PciIoDevice->ReservedBusNum = (UINT16)(EFI_PCI_BUS_OF_RID
> > > (LastVF)
> > > > - Bus + 1);
> > > >
> > > >
> > > >
> > > >        DEBUG ((
> > > >
> > > > -        EFI_D_INFO,
> > > >
> > > > +        DEBUG_INFO,
> > > >
> > > >          " SR-IOV: SupportedPageSize = 0x%x; SystemPageSize = 0x%x;
> > > > FirstVFOffset = 0x%x;\n",
> > > >
> > > >          SupportedPageSize, PciIoDevice->SystemPageSize >> 12,
> FirstVFOffset
> > > >
> > > >          ));
> > > >
> > > >        DEBUG ((
> > > >
> > > > -        EFI_D_INFO,
> > > >
> > > > +        DEBUG_INFO,
> > > >
> > > >          "         InitialVFs = 0x%x; ReservedBusNum = 0x%x; CapOffset =
> 0x%x\n",
> > > >
> > > >          PciIoDevice->InitialVFs, PciIoDevice->ReservedBusNum,
> PciIoDevice-
> > > > >SrIovCapabilityOffset
> > > >
> > > >          ));
> > > >
> > > > @@ -2345,7 +2355,7 @@ CreatePciIoDevice (
> > > >                 NULL
> > > >
> > > >                 );
> > > >
> > > >      if (!EFI_ERROR (Status)) {
> > > >
> > > > -      DEBUG ((EFI_D_INFO, " MR-IOV: CapOffset = 0x%x\n", PciIoDevice-
> > > > >MrIovCapabilityOffset));
> > > >
> > > > +      DEBUG ((DEBUG_INFO, " MR-IOV: CapOffset = 0x%x\n",
> PciIoDevice-
> > > > >MrIovCapabilityOffset));
> > > >
> > > >      }
> > > >
> > > >    }
> > > >
> > > >
> > > >
> > > > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> > > > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> > > > new file mode 100644
> > > > index 0000000000..0819da6536
> > > > --- /dev/null
> > > > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> > > > @@ -0,0 +1,1601 @@
> > > > +/** @file
> > > >
> > > > +  PCI standard feature support functions implementation for PCI Bus
> > > > module..
> > > >
> > > > +
> > > >
> > > > +Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> > > >
> > > > +SPDX-License-Identifier: BSD-2-Clause-Patent
> > > >
> > > > +
> > > >
> > > > +**/
> > > >
> > > > +
> > > >
> > > > +#include "PciFeatureSupport.h"
> > > >
> > > > +
> > > >
> > > > +/**
> > > >
> > > > +  A gobal pointer to PRIMARY_ROOT_PORT_NODE buffer to track all
> the
> > > > primary physical
> > > >
> > > > +  PCI Root Ports (PCI Controllers) for a given PCI Root Bridge instance
> while
> > > >
> > > > +  enumerating to configure the PCI features
> > > >
> > > > +**/
> > > >
> > > > +PRIMARY_ROOT_PORT_NODE                      *mPrimaryRootPortList;
> > > >
> > > > +
> > > >
> > > > +/**
> > > >
> > > > +  A gobal pointer to OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > > buffer
> > > > all the PCI
> > > >
> > > > +  Feature configuration Table nodes to pair against each of the
> > > > PRIMARY_ROOT_PORT_NODE
> > > >
> > > > +  buffer nodes. Each node of these is used to align all the PCI devices
> > > > originating
> > > >
> > > > +  from the PCI Root Port devices of a PCI Root Bridge instance
> > > >
> > > > +**/
> > > >
> > > > +OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > > > *mPciFeaturesConfigurationTableInstances;
> > > >
> > > > +
> > > >
> > > > +/**
> > > >
> > > > +  A global pointer to
> PCI_FEATURE_CONFIGURATION_COMPLETION_LIST,
> > > > which stores all
> > > >
> > > > +  the PCI Root Bridge instances that are enumerated for the other PCI
> > > > features,
> > > >
> > > > +  like MaxPayloadSize & MaxReadReqSize; during the the Start()
> interface
> > > of
> > > > the
> > > >
> > > > +  driver binding protocol. The records pointed by this pointer would be
> > > > destroyed
> > > >
> > > > +  when the DXE core invokes the Stop() interface.
> > > >
> > > > +**/
> > > >
> > > > +PCI_FEATURE_CONFIGURATION_COMPLETION_LIST
> > > > *mPciFeaturesConfigurationCompletionList = NULL;
> > > >
> > > > +
> > > >
> > > > +/**
> > > >
> > > > +  Main routine to indicate platform selection of any of the other PCI
> > > features
> > > >
> > > > +  to be configured by this driver
> > > >
> > > > +
> > > >
> > > > +  @retval TRUE    platform has selected the other PCI features to be
> > > > configured
> > > >
> > > > +          FALSE   platform has not selected any of the other PCI features
> > > >
> > > > +**/
> > > >
> > > > +BOOLEAN
> > > >
> > > > +CheckOtherPciFeaturesPcd (
> > > >
> > > > +  )
> > > >
> > > > +{
> > > >
> > > > +  return PcdGet32 ( PcdOtherPciFeatures) ? TRUE : FALSE;
> > > >
> > > > +}
> > > >
> > > > +
> > > >
> > > > +/**
> > > >
> > > > +  Main routine to indicate whether the platform has selected the
> > > > Max_Payload_Size
> > > >
> > > > +  PCI feature to be configured by this driver
> > > >
> > > > +
> > > >
> > > > +  @retval TRUE    platform has selected the Max_Payload_Size to be
> > > > configured
> > > >
> > > > +          FALSE   platform has not selected this feature
> > > >
> > > > +**/
> > > >
> > > > +BOOLEAN
> > > >
> > > > +SetupMaxPayloadSize (
> > > >
> > > > +  )
> > > >
> > > > +{
> > > >
> > > > +  return (PcdGet32 ( PcdOtherPciFeatures) &
> > > > PCI_FEATURE_SUPPORT_FLAG_MPS) ? TRUE : FALSE;
> > > >
> > > > +}
> > > >
> > > > +
> > > >
> > > > +/**
> > > >
> > > > +  Main routine to indicate whether the platform has selected the
> > > > Max_Read_Req_Size
> > > >
> > > > +  PCI feature to be configured by this driver
> > > >
> > > > +
> > > >
> > > > +  @retval TRUE    platform has selected the Max_Read_Req_Size to be
> > > > configured
> > > >
> > > > +          FALSE   platform has not selected this feature
> > > >
> > > > +**/
> > > >
> > > > +BOOLEAN
> > > >
> > > > +SetupMaxReadReqSize (
> > > >
> > > > +  )
> > > >
> > > > +{
> > > >
> > > > +  return (PcdGet32 ( PcdOtherPciFeatures) &
> > > > PCI_FEATURE_SUPPORT_FLAG_MRRS) ? TRUE : FALSE;
> > > >
> > > > +}
> > > >
> > > > +
> > > >
> > > > +/**
> > > >
> > > > +  Helper routine which determines whether the given PCI Root Bridge
> > > > instance
> > > >
> > > > +  record already exist. This routine shall help avoid duplicate record
> > > creation
> > > >
> > > > +  in case of re-enumeration of PCI configuation features.
> > > >
> > > > +
> > > >
> > > > +  @param  RootBridge              A pointer to the PCI_IO_DEVICE for the
> Root
> > > > Bridge
> > > >
> > > > +  @param  PciFeatureConfigRecord  A pointer to a pointer for type
> > > >
> > > > +                                  PCI_FEATURE_CONFIGURATION_COMPLETION_LIST
> > > >
> > > > +                                  record, Use to return the specific record.
> > > >
> > > > +
> > > >
> > > > +  @retval TRUE                    Record already exist
> > > >
> > > > +          FALSE                   Record does not exist for the given PCI Root
> Bridge
> > > >
> > > > +**/
> > > >
> > > > +BOOLEAN
> > > >
> > > > +CheckPciFeatureConfigurationRecordExist (
> > > >
> > > > +  IN  PCI_IO_DEVICE                             *RootBridge,
> > > >
> > > > +  OUT PCI_FEATURE_CONFIGURATION_COMPLETION_LIST
> > > > **PciFeatureConfigRecord
> > > >
> > > > +  )
> > > >
> > > > +{
> > > >
> > > > +  LIST_ENTRY                                  *Link;
> > > >
> > > > +  PCI_FEATURE_CONFIGURATION_COMPLETION_LIST   *Temp;
> > > >
> > > > +
> > > >
> > > > +  if ( mPciFeaturesConfigurationCompletionList) {
> > > >
> > > > +    Link = &mPciFeaturesConfigurationCompletionList->RootBridgeLink;
> > > >
> > > > +
> > > >
> > > > +    do {
> > > >
> > > > +      Temp =
> > > > PCI_FEATURE_CONFIGURATION_COMPLETION_LIST_FROM_LINK
> (Link);
> > > >
> > > > +      if ( Temp->RootBridgeHandle == RootBridge->Handle) {
> > > >
> > > > +        *PciFeatureConfigRecord = Temp;
> > > >
> > > > +        return TRUE;
> > > >
> > > > +      }
> > > >
> > > > +      Link = Link->ForwardLink;
> > > >
> > > > +    } while (Link != &mPciFeaturesConfigurationCompletionList-
> > > > >RootBridgeLink);
> > > >
> > > > +  }
> > > >
> > > > +  //
> > > >
> > > > +  // not found on the PCI feature configuration completion list
> > > >
> > > > +  //
> > > >
> > > > +  *PciFeatureConfigRecord = NULL;
> > > >
> > > > +  return FALSE;
> > > >
> > > > +}
> > > >
> > > > +
> > > >
> > > > +/**
> > > >
> > > > +  This routine is primarily to avoid multiple configuration of PCI features
> > > >
> > > > +  to the same PCI Root Bridge due to EDK2 core's ConnectController
> calls
> > > on
> > > >
> > > > +  all the EFI handles. This routine also provide re-enumeration of the
> PCI
> > > >
> > > > +  features on the same PCI Root Bridge based on the policy of
> > > > ReEnumeratePciFeatureConfiguration
> > > >
> > > > +  of the PCI_FEATURE_CONFIGURATION_COMPLETION_LIST.
> > > >
> > > > +
> > > >
> > > > +  @param  RootBridge              A pointer to the PCI_IO_DEVICE for the
> Root
> > > > Bridge
> > > >
> > > > +
> > > >
> > > > +  @retval TRUE                    PCI Feature configuration required for the PCI
> > > >
> > > > +                                  Root Bridge
> > > >
> > > > +          FALSE                   PCI Feature configuration is not required to be
> > > >
> > > > +                                  re-enumerated for the PCI Root Bridge
> > > >
> > > > +**/
> > > >
> > > > +BOOLEAN
> > > >
> > > > +CheckPciFeaturesConfigurationRequired (
> > > >
> > > > +  IN PCI_IO_DEVICE          *RootBridge
> > > >
> > > > +  )
> > > >
> > > > +{
> > > >
> > > > +  LIST_ENTRY                                  *Link;
> > > >
> > > > +  PCI_FEATURE_CONFIGURATION_COMPLETION_LIST   *Temp;
> > > >
> > > > +
> > > >
> > > > +  if ( mPciFeaturesConfigurationCompletionList) {
> > > >
> > > > +    Link = &mPciFeaturesConfigurationCompletionList->RootBridgeLink;
> > > >
> > > > +
> > > >
> > > > +    do {
> > > >
> > > > +      Temp =
> > > > PCI_FEATURE_CONFIGURATION_COMPLETION_LIST_FROM_LINK
> (Link);
> > > >
> > > > +      if ( Temp->RootBridgeHandle == RootBridge->Handle) {
> > > >
> > > > +        return Temp->ReEnumeratePciFeatureConfiguration;
> > > >
> > > > +      }
> > > >
> > > > +      Link = Link->ForwardLink;
> > > >
> > > > +    } while (Link != &mPciFeaturesConfigurationCompletionList-
> > > > >RootBridgeLink);
> > > >
> > > > +  }
> > > >
> > > > +  //
> > > >
> > > > +  // not found on the PCI feature configuration completion list, return
> as
> > > > required
> > > >
> > > > +  //
> > > >
> > > > +  return TRUE;
> > > >
> > > > +}
> > > >
> > > > +
> > > >
> > > > +/**
> > > >
> > > > +  This routine finds the duplicate record if exist and assigns the re-
> > > > enumeration
> > > >
> > > > +  requirement flag, as passed as input. It creates new record for the
> PCI
> > > > Root
> > > >
> > > > +  Bridge and appends the list after updating its re-enumeration flag.
> > > >
> > > > +
> > > >
> > > > +  @param  RootBridge            A pointer to PCI_IO_DEVICE of the Root
> > > Bridge
> > > >
> > > > +  @param  ReEnumerationRequired A BOOLEAN for recording the re-
> > > > enumeration requirement
> > > >
> > > > +
> > > >
> > > > +  @retval EFI_SUCCESS           new record inserted into the list or
> updated
> > > the
> > > >
> > > > +                                existing record
> > > >
> > > > +          EFI_INVALID_PARAMETER Unexpected error as
> > > > CheckPciFeatureConfigurationRecordExist
> > > >
> > > > +                                reports as record exist but does not return its pointer
> > > >
> > > > +          EFI_OUT_OF_RESOURCES  Not able to create PCI features
> > > configuratin
> > > > complete
> > > >
> > > > +                                record for the RootBridge
> > > >
> > > > +**/
> > > >
> > > > +EFI_STATUS
> > > >
> > > > +AddRootBridgeInPciFeaturesConfigCompletionList (
> > > >
> > > > +  IN PCI_IO_DEVICE          *RootBridge,
> > > >
> > > > +  IN BOOLEAN                ReEnumerationRequired
> > > >
> > > > +  )
> > > >
> > > > +{
> > > >
> > > > +  PCI_FEATURE_CONFIGURATION_COMPLETION_LIST   *Temp;
> > > >
> > > > +
> > > >
> > > > +  if ( CheckPciFeatureConfigurationRecordExist ( RootBridge, &Temp))
> {
> > > >
> > > > +    //
> > > >
> > > > +    // this PCI Root Bridge record already exist; it may have been re-
> > > > enumerated
> > > >
> > > > +    // hence just update its enumeration required flag again to exit
> > > >
> > > > +    //
> > > >
> > > > +    if ( Temp) {
> > > >
> > > > +      Temp->ReEnumeratePciFeatureConfiguration  =
> > > > ReEnumerationRequired;
> > > >
> > > > +      return EFI_SUCCESS;
> > > >
> > > > +    } else {
> > > >
> > > > +      //
> > > >
> > > > +      // PCI feature configuration complete record reported as exist and
> no
> > > >
> > > > +      // record pointer returned
> > > >
> > > > +      //
> > > >
> > > > +      return EFI_INVALID_PARAMETER;
> > > >
> > > > +    }
> > > >
> > > > +
> > > >
> > > > +  } else {
> > > >
> > > > +
> > > >
> > > > +    Temp = AllocateZeroPool ( sizeof
> > > > ( PCI_FEATURE_CONFIGURATION_COMPLETION_LIST));
> > > >
> > > > +    if ( !Temp) {
> > > >
> > > > +      return EFI_OUT_OF_RESOURCES;
> > > >
> > > > +    }
> > > >
> > > > +    Temp->Signature                           =
> > > > PCI_FEATURE_CONFIGURATION_SIGNATURE;
> > > >
> > > > +    Temp->RootBridgeHandle                    = RootBridge->Handle;
> > > >
> > > > +    Temp->ReEnumeratePciFeatureConfiguration  =
> > > ReEnumerationRequired;
> > > >
> > > > +    if ( mPciFeaturesConfigurationCompletionList) {
> > > >
> > > > +      InsertTailList ( &mPciFeaturesConfigurationCompletionList-
> > > > >RootBridgeLink,
> > > >
> > > > +                       &Temp->RootBridgeLink);
> > > >
> > > > +    } else {
> > > >
> > > > +      //
> > > >
> > > > +      // init the very first node of the Root Bridge
> > > >
> > > > +      //
> > > >
> > > > +      mPciFeaturesConfigurationCompletionList = Temp;
> > > >
> > > > +      InitializeListHead ( &mPciFeaturesConfigurationCompletionList-
> > > > >RootBridgeLink);
> > > >
> > > > +    }
> > > >
> > > > +  }
> > > >
> > > > +  return EFI_SUCCESS;
> > > >
> > > > +}
> > > >
> > > > +
> > > >
> > > > +/**
> > > >
> > > > +  Free up memory alloted for the primary physical PCI Root ports of the
> > > PCI
> > > > Root
> > > >
> > > > +  Bridge instance. Free up all the nodes of type
> > > > PRIMARY_ROOT_PORT_NODE.
> > > >
> > > > +**/
> > > >
> > > > +VOID
> > > >
> > > > +DestroyPrimaryRootPortNodes ()
> > > >
> > > > +{
> > > >
> > > > +  LIST_ENTRY                *Link;
> > > >
> > > > +  PRIMARY_ROOT_PORT_NODE    *Temp;
> > > >
> > > > +
> > > >
> > > > +  if ( mPrimaryRootPortList) {
> > > >
> > > > +    Link = &mPrimaryRootPortList->NeighborRootPort;
> > > >
> > > > +
> > > >
> > > > +    if ( IsListEmpty ( Link)) {
> > > >
> > > > +      FreePool ( mPrimaryRootPortList);
> > > >
> > > > +    } else {
> > > >
> > > > +      do {
> > > >
> > > > +        if ( Link->ForwardLink != &mPrimaryRootPortList-
> >NeighborRootPort)
> > > {
> > > >
> > > > +          Link = Link->ForwardLink;
> > > >
> > > > +        }
> > > >
> > > > +        Temp = PRIMARY_ROOT_PORT_NODE_FROM_LINK ( Link);
> > > >
> > > > +        Link = RemoveEntryList ( Link);
> > > >
> > > > +        FreePool ( Temp);
> > > >
> > > > +      } while ( !IsListEmpty ( Link));
> > > >
> > > > +      FreePool ( mPrimaryRootPortList);
> > > >
> > > > +    }
> > > >
> > > > +    mPrimaryRootPortList = NULL;
> > > >
> > > > +  }
> > > >
> > > > +}
> > > >
> > > > +
> > > >
> > > > +/**
> > > >
> > > > +  Free up the memory allocated for temporarily maintaining the PCI
> > > feature
> > > >
> > > > +  configuration table for all the nodes of the primary PCI Root port.
> > > >
> > > > +  Free up memory alloted for
> > > > OTHER_PCI_FEATURES_CONFIGURATION_TABLE.
> > > >
> > > > +**/
> > > >
> > > > +VOID
> > > >
> > > > +ErasePciFeaturesConfigurationTable (
> > > >
> > > > +  )
> > > >
> > > > +{
> > > >
> > > > +  if ( mPciFeaturesConfigurationTableInstances) {
> > > >
> > > > +    FreePool ( mPciFeaturesConfigurationTableInstances);
> > > >
> > > > +  }
> > > >
> > > > +  mPciFeaturesConfigurationTableInstances = NULL;
> > > >
> > > > +}
> > > >
> > > > +
> > > >
> > > > +/**
> > > >
> > > > +  Routine meant for initializing any global variables used. It primarily
> cleans
> > > >
> > > > +  up the internal data structure memory allocated for the previous PCI
> > > Root
> > > > Bridge
> > > >
> > > > +  instance. This should be the first routine to call for any virtual PCI
> Root
> > > >
> > > > +  Bridge instance.
> > > >
> > > > +**/
> > > >
> > > > +VOID
> > > >
> > > > +SetupPciFeaturesConfigurationDefaults ()
> > > >
> > > > +{
> > > >
> > > > +  //
> > > >
> > > > +  // delete the primary root port list
> > > >
> > > > +  //
> > > >
> > > > +  if (mPrimaryRootPortList) {
> > > >
> > > > +    DestroyPrimaryRootPortNodes ();
> > > >
> > > > +  }
> > > >
> > > > +
> > > >
> > > > +  if ( mPciFeaturesConfigurationTableInstances) {
> > > >
> > > > +    ErasePciFeaturesConfigurationTable ();
> > > >
> > > > +  }
> > > >
> > > > +}
> > > >
> > > > +
> > > >
> > > > +/**
> > > >
> > > > +  Helper routine to determine whether the PCI device is a physical root
> > > port
> > > >
> > > > +  recorded in the list.
> > > >
> > > > +
> > > >
> > > > +  @param  PciDevice                       A pointer to the PCI_IO_DEVICE.
> > > >
> > > > +
> > > >
> > > > +  @retval TRUE                            The PCI device instance is a primary
> > > >
> > > > +                                          primary physical PCI Root Port
> > > >
> > > > +          FALSE                           Not a primary physical PCI Root port
> > > >
> > > > +**/
> > > >
> > > > +BOOLEAN
> > > >
> > > > +CheckRootBridgePrimaryPort (
> > > >
> > > > +  IN PCI_IO_DEVICE          *PciDevice
> > > >
> > > > +  )
> > > >
> > > > +{
> > > >
> > > > +  LIST_ENTRY                *Link;
> > > >
> > > > +  PRIMARY_ROOT_PORT_NODE    *Temp;
> > > >
> > > > +
> > > >
> > > > +  if ( !mPrimaryRootPortList) {
> > > >
> > > > +    return FALSE;
> > > >
> > > > +  }
> > > >
> > > > +  Link = &mPrimaryRootPortList->NeighborRootPort;
> > > >
> > > > +  do {
> > > >
> > > > +    Temp = PRIMARY_ROOT_PORT_NODE_FROM_LINK ( Link);
> > > >
> > > > +    if ( Temp->RootBridgeHandle == PciDevice->Parent->Handle
> > > >
> > > > +        && Temp->RootPortHandle == PciDevice->Handle) {
> > > >
> > > > +      //
> > > >
> > > > +      // the given PCI device is the primary root port of the Root Bridge
> > > > controller
> > > >
> > > > +      //
> > > >
> > > > +      return TRUE;
> > > >
> > > > +    }
> > > >
> > > > +    Link = Link->ForwardLink;
> > > >
> > > > +  } while ( Link != &mPrimaryRootPortList->NeighborRootPort);
> > > >
> > > > +  //
> > > >
> > > > +  // the given PCI device is not the primary root port of the Bridge
> > > controller
> > > >
> > > > +  //
> > > >
> > > > +  return FALSE;
> > > >
> > > > +}
> > > >
> > > > +
> > > >
> > > > +/**
> > > >
> > > > +  Main routine to determine the child PCI devices of a physical PCI
> bridge
> > > > device
> > > >
> > > > +  and group them under a common internal PCI features Configuration
> > > table.
> > > >
> > > > +
> > > >
> > > > +  @param  PciDevice                       A pointer to the PCI_IO_DEVICE.
> > > >
> > > > +  @param  PciFeaturesConfigTable          A pointer to a pointer to the
> > > >
> > > > +                                          OTHER_PCI_FEATURES_CONFIGURATION_TABLE.
> > > >
> > > > +                                          Returns NULL in case of RCiEP or the PCI
> > > >
> > > > +                                          device does match with any of the physical
> > > >
> > > > +                                          Root ports, or it does not belong to any
> > > >
> > > > +                                          Root port's PCU bus range (not a child)
> > > >
> > > > +
> > > >
> > > > +  @retval EFI_SUCCESS                     able to determine the PCI feature
> > > >
> > > > +                                          configuration table. For RCiEP since
> > > >
> > > > +                                          since it is not prepared.
> > > >
> > > > +          EFI_NOT_FOUND                   the PCI feature configuration table
> does
> > > >
> > > > +                                          not exist as the PCI physical Bridge device
> > > >
> > > > +                                          is not found for this device's parent
> > > >
> > > > +                                          Root Bridge instance
> > > >
> > > > +**/
> > > >
> > > > +EFI_STATUS
> > > >
> > > > +GetPciFeaturesConfigurationTable (
> > > >
> > > > +  IN  PCI_IO_DEVICE                           *PciDevice,
> > > >
> > > > +  OUT OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > > > **PciFeaturesConfigTable
> > > >
> > > > +  )
> > > >
> > > > +{
> > > >
> > > > +  LIST_ENTRY                *Link;
> > > >
> > > > +  PRIMARY_ROOT_PORT_NODE    *Temp;
> > > >
> > > > +
> > > >
> > > > +  if ( !mPrimaryRootPortList) {
> > > >
> > > > +    *PciFeaturesConfigTable = NULL;
> > > >
> > > > +    return EFI_NOT_FOUND;
> > > >
> > > > +  }
> > > >
> > > > +
> > > >
> > > > +  //
> > > >
> > > > +  // The PCI features configuration table is not built for RCiEP, return
> NULL
> > > >
> > > > +  //
> > > >
> > > > +  if ( PciDevice->PciExpStruct.Capability.Bits.DevicePortType == \
> > > >
> > > > +
> PCIE_DEVICE_PORT_TYPE_ROOT_COMPLEX_INTEGRATED_ENDPOINT)
> > > > {
> > > >
> > > > +    *PciFeaturesConfigTable = NULL;
> > > >
> > > > +    return EFI_SUCCESS;
> > > >
> > > > +  }
> > > >
> > > > +
> > > >
> > > > +  Link = &mPrimaryRootPortList->NeighborRootPort;
> > > >
> > > > +  do {
> > > >
> > > > +    Temp = PRIMARY_ROOT_PORT_NODE_FROM_LINK ( Link);
> > > >
> > > > +    if ( Temp->RootBridgeHandle == PciDevice->Parent->Handle
> > > >
> > > > +        && Temp->RootPortHandle == PciDevice->Handle) {
> > > >
> > > > +      //
> > > >
> > > > +      // the given PCI device is the primary root port of the Root Bridge
> > > > controller
> > > >
> > > > +      //
> > > >
> > > > +      *PciFeaturesConfigTable = Temp-
> > > >OtherPciFeaturesConfigurationTable;
> > > >
> > > > +      return EFI_SUCCESS;
> > > >
> > > > +    } else {
> > > >
> > > > +      //
> > > >
> > > > +      // check this PCI device belongs to the primary root port of the root
> > > > bridge
> > > >
> > > > +      //
> > > >
> > > > +      if ( PciDevice->BusNumber >= Temp->SecondaryBusStart
> > > >
> > > > +          && PciDevice->BusNumber <= Temp->SecondaryBusEnd) {
> > > >
> > > > +        *PciFeaturesConfigTable = Temp-
> > > >OtherPciFeaturesConfigurationTable;
> > > >
> > > > +        return EFI_SUCCESS;
> > > >
> > > > +      }
> > > >
> > > > +    }
> > > >
> > > > +    Link = Link->ForwardLink;
> > > >
> > > > +  } while ( Link != &mPrimaryRootPortList->NeighborRootPort);
> > > >
> > > > +  //
> > > >
> > > > +  // the PCI device must be RCiEP, does not belong to any primary root
> > > port
> > > >
> > > > +  //
> > > >
> > > > +  *PciFeaturesConfigTable = NULL;
> > > >
> > > > +  return EFI_SUCCESS;
> > > >
> > > > +}
> > > >
> > > > +
> > > >
> > > > +/**
> > > >
> > > > +  The helper routine to retrieve the PCI bus numbers from the PCI
> Bridge
> > > or
> > > > Root
> > > >
> > > > +  port device. Assumes the input PCI device has the PCI Type 1
> > > configuration
> > > > header.
> > > >
> > > > +
> > > >
> > > > +  @param  PciDevice                       A pointer to the PCI_IO_DEVICE.
> > > >
> > > > +  @param  PrimaryBusNumber                A pointer to return the PCI
> Priamry
> > > >
> > > > +                                          Bus number.
> > > >
> > > > +  @param  SecondaryBusNumber              A pointer to return the PCI
> > > > Secondary
> > > >
> > > > +                                          Bus number.
> > > >
> > > > +  @param  SubordinateBusNumber            A pointer to return the PCI
> > > > Subordinate
> > > >
> > > > +                                          Bus number.
> > > >
> > > > +
> > > >
> > > > +  @retval EFI_SUCCESS           The data was read from the PCI device.
> > > >
> > > > +  @retval EFI_UNSUPPORTED       The address range specified by Offset,
> > > > Width, and Count is not
> > > >
> > > > +                                valid for the PCI configuration header of the PCI device.
> > > >
> > > > +  @retval EFI_INVALID_PARAMETER input parameters provided to the
> > > read
> > > > operation were invalid.
> > > >
> > > > +**/
> > > >
> > > > +EFI_STATUS
> > > >
> > > > +GetPciRootPortBusAssigned (
> > > >
> > > > +  IN  PCI_IO_DEVICE                           *PciDevice,
> > > >
> > > > +  OUT UINT8                                   *PrimaryBusNumber,
> > > >
> > > > +  OUT UINT8                                   *SecondaryBusNumber,
> > > >
> > > > +  OUT UINT8                                   *SubordinateBusNumber
> > > >
> > > > +  )
> > > >
> > > > +{
> > > >
> > > > +  EFI_STATUS                                  Status;
> > > >
> > > > +  UINT32                                      RootPortBusAssigned;
> > > >
> > > > +
> > > >
> > > > +  Status = PciDevice->PciIo.Pci.Read (
> > > >
> > > > +                                  &PciDevice->PciIo,
> > > >
> > > > +                                  EfiPciIoWidthUint32,
> > > >
> > > > +                                  PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET,
> > > >
> > > > +                                  1,
> > > >
> > > > +                                  &RootPortBusAssigned
> > > >
> > > > +                                );
> > > >
> > > > +  if ( !EFI_ERROR(Status)) {
> > > >
> > > > +    if ( PrimaryBusNumber) {
> > > >
> > > > +      *PrimaryBusNumber = (UINT8) (0xFF & RootPortBusAssigned);
> > > >
> > > > +    }
> > > >
> > > > +    if ( SecondaryBusNumber) {
> > > >
> > > > +      *SecondaryBusNumber = (UINT8)(0xFF & (RootPortBusAssigned >>
> 8));
> > > >
> > > > +    }
> > > >
> > > > +    if ( SubordinateBusNumber) {
> > > >
> > > > +      *SubordinateBusNumber = (UINT8)(0xFF &
> (RootPortBusAssigned >>
> > > > 16));
> > > >
> > > > +    }
> > > >
> > > > +  }
> > > >
> > > > +  return Status;
> > > >
> > > > +}
> > > >
> > > > +
> > > >
> > > > +/**
> > > >
> > > > +  This routine determines the existance of the child PCI device for the
> > > given
> > > >
> > > > +  PCI Root / Bridge Port device. Always assumes the input PCI device is
> the
> > > > bridge
> > > >
> > > > +  or PCI-PCI Bridge device. This routine should not be used with PCI
> > > > endpoint device.
> > > >
> > > > +
> > > >
> > > > +  @param  PciDevice                       A pointer to the PCI_IO_DEVICE.
> > > >
> > > > +
> > > >
> > > > +  @retval TRUE                            child device exist
> > > >
> > > > +          FALSE                           no child device
> > > >
> > > > +**/
> > > >
> > > > +BOOLEAN
> > > >
> > > > +IsPciRootPortEmpty (
> > > >
> > > > +  IN  PCI_IO_DEVICE                           *PciDevice
> > > >
> > > > +  )
> > > >
> > > > +{
> > > >
> > > > +  UINT8                                       SecBus,
> > > >
> > > > +                                              SubBus;
> > > >
> > > > +  EFI_STATUS                                  Status;
> > > >
> > > > +  LIST_ENTRY                                  *Link;
> > > >
> > > > +  PCI_IO_DEVICE                               *NextPciDevice;
> > > >
> > > > +
> > > >
> > > > +  //
> > > >
> > > > +  // check secondary & suboridinate bus numbers for its endpoint
> device
> > > >
> > > > +  // existance
> > > >
> > > > +  //
> > > >
> > > > +  Status = GetPciRootPortBusAssigned ( PciDevice, NULL, &SecBus,
> > > > &SubBus);
> > > >
> > > > +  if ( !EFI_ERROR( Status)) {
> > > >
> > > > +    Link = PciDevice->ChildList.ForwardLink;
> > > >
> > > > +    if ( IsListEmpty ( Link)) {
> > > >
> > > > +      //
> > > >
> > > > +      // return as PCI Root port empty
> > > >
> > > > +      //
> > > >
> > > > +      DEBUG (( DEBUG_INFO, "RP empty,"));
> > > >
> > > > +      return TRUE;
> > > >
> > > > +    }
> > > >
> > > > +    do {
> > > >
> > > > +      NextPciDevice = PCI_IO_DEVICE_FROM_LINK ( Link);
> > > >
> > > > +      DEBUG (( DEBUG_INFO, "dev@%x", NextPciDevice->BusNumber));
> > > >
> > > > +
> > > >
> > > > +      if ( NextPciDevice->BusNumber >= SecBus
> > > >
> > > > +          && NextPciDevice->BusNumber <= SubBus) {
> > > >
> > > > +
> > > >
> > > > +        return FALSE;
> > > >
> > > > +      }
> > > >
> > > > +
> > > >
> > > > +      Link = Link->ForwardLink;
> > > >
> > > > +    } while ( Link != &PciDevice->ChildList);
> > > >
> > > > +  } else {
> > > >
> > > > +    SecBus = SubBus = 0;
> > > >
> > > > +    DEBUG (( DEBUG_ERROR, "unable to retrieve root port's bus range
> > > > assigned!!!"));
> > > >
> > > > +  }
> > > >
> > > > +
> > > >
> > > > +  //
> > > >
> > > > +  // return as PCI Root port empty
> > > >
> > > > +  //
> > > >
> > > > +  return TRUE;
> > > >
> > > > +}
> > > >
> > > > +
> > > >
> > > > +/**
> > > >
> > > > +  The main routine which process the PCI feature Max_Payload_Size as
> > > per
> > > > the
> > > >
> > > > +  device-specific platform policy, as well as in complaince with the PCI
> Base
> > > >
> > > > +  specification Revision 4, that aligns the value for the entire PCI
> heirarchy
> > > >
> > > > +  starting from its physical PCI Root port / Bridge device.
> > > >
> > > > +
> > > >
> > > > +  @param PciDevice                      A pointer to the PCI_IO_DEVICE.
> > > >
> > > > +  @param PciConfigPhase                 for the PCI feature configuration
> phases:
> > > >
> > > > +                                        PciFeatureGetDevicePolicy &
> PciFeatureSetupPhase
> > > >
> > > > +  @param PciFeaturesConfigurationTable  pointer to
> > > > OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > > >
> > > > +
> > > >
> > > > +  @retval EFI_SUCCESS                   processing of PCI feature
> > > > Max_Payload_Size
> > > >
> > > > +                                        is successful.
> > > >
> > > > +**/
> > > >
> > > > +EFI_STATUS
> > > >
> > > > +ProcessMaxPayloadSize (
> > > >
> > > > +  IN  PCI_IO_DEVICE                           *PciDevice,
> > > >
> > > > +  IN  PCI_FEATURE_CONFIGURATION_PHASE         PciConfigPhase,
> > > >
> > > > +  IN  OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > > > *PciFeaturesConfigurationTable
> > > >
> > > > +  )
> > > >
> > > > +{
> > > >
> > > > +  PCI_REG_PCIE_DEVICE_CAPABILITY          PciDeviceCap;
> > > >
> > > > +  UINT8                                   MpsValue;
> > > >
> > > > +
> > > >
> > > > +
> > > >
> > > > +  PciDeviceCap.Uint32 = PciDevice-
> >PciExpStruct.DeviceCapability.Uint32;
> > > >
> > > > +
> > > >
> > > > +  if ( PciConfigPhase == PciFeatureGetDevicePolicy) {
> > > >
> > > > +    if ( SetupMpsAsPerDeviceCapability ( PciDevice->SetupMPS))
> > > >
> > > > +    {
> > > >
> > > > +      MpsValue = (UINT8)PciDeviceCap.Bits.MaxPayloadSize;
> > > >
> > > > +      //
> > > >
> > > > +      // no change to PCI Root ports without any endpoint device
> > > >
> > > > +      //
> > > >
> > > > +      if ( IS_PCI_BRIDGE ( &PciDevice->Pci) &&
> > > > PciDeviceCap.Bits.MaxPayloadSize) {
> > > >
> > > > +        if ( IsPciRootPortEmpty ( PciDevice)) {
> > > >
> > > > +          MpsValue = PCIE_MAX_PAYLOAD_SIZE_128B;
> > > >
> > > > +          DEBUG (( DEBUG_INFO, "(reset RP MPS to min.)"));
> > > >
> > > > +        }
> > > >
> > > > +      }
> > > >
> > > > +    } else {
> > > >
> > > > +      MpsValue = TranslateMpsSetupValueToPci ( PciDevice-
> >SetupMPS);
> > > >
> > > > +    }
> > > >
> > > > +    //
> > > >
> > > > +    // discard device policy override request if greater than PCI device
> > > > capability
> > > >
> > > > +    //
> > > >
> > > > +    PciDevice->SetupMPS =
> > > MIN( (UINT8)PciDeviceCap.Bits.MaxPayloadSize,
> > > > MpsValue);
> > > >
> > > > +  }
> > > >
> > > > +
> > > >
> > > > +  //
> > > >
> > > > +  // align the MPS of the tree to the HCF with this device
> > > >
> > > > +  //
> > > >
> > > > +  if ( PciFeaturesConfigurationTable) {
> > > >
> > > > +    MpsValue = PciFeaturesConfigurationTable->Max_Payload_Size;
> > > >
> > > > +
> > > >
> > > > +    MpsValue = MIN ( PciDevice->SetupMPS, MpsValue);
> > > >
> > > > +    PciDevice->SetupMPS = MIN ( PciDevice->SetupMPS, MpsValue);
> > > >
> > > > +
> > > >
> > > > +    if ( MpsValue != PciFeaturesConfigurationTable->Max_Payload_Size)
> {
> > > >
> > > > +      DEBUG (( DEBUG_INFO, "reset MPS of the tree to %d,",
> MpsValue));
> > > >
> > > > +      PciFeaturesConfigurationTable->Max_Payload_Size = MpsValue;
> > > >
> > > > +    }
> > > >
> > > > +  }
> > > >
> > > > +
> > > >
> > > > +  DEBUG (( DEBUG_INFO,
> > > >
> > > > +      "Max_Payload_Size: %d [DevCap:%d],",
> > > >
> > > > +      PciDevice->SetupMPS, PciDeviceCap.Bits.MaxPayloadSize
> > > >
> > > > +  ));
> > > >
> > > > +  return EFI_SUCCESS;
> > > >
> > > > +}
> > > >
> > > > +
> > > >
> > > > +/**
> > > >
> > > > +  The main routine which process the PCI feature Max_Read_Req_Size
> as
> > > > per the
> > > >
> > > > +  device-specific platform policy, as well as in complaince with the PCI
> Base
> > > >
> > > > +  specification Revision 4, that aligns the value for the entire PCI
> heirarchy
> > > >
> > > > +  starting from its physical PCI Root port / Bridge device.
> > > >
> > > > +
> > > >
> > > > +  @param PciDevice                      A pointer to the PCI_IO_DEVICE.
> > > >
> > > > +  @param PciConfigPhase                 for the PCI feature configuration
> phases:
> > > >
> > > > +                                        PciFeatureGetDevicePolicy &
> PciFeatureSetupPhase
> > > >
> > > > +  @param PciFeaturesConfigurationTable  pointer to
> > > > OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > > >
> > > > +
> > > >
> > > > +  @retval EFI_SUCCESS                   processing of PCI feature
> > > > Max_Read_Req_Size
> > > >
> > > > +                                        is successful.
> > > >
> > > > +**/
> > > >
> > > > +EFI_STATUS
> > > >
> > > > +ProcessMaxReadReqSize (
> > > >
> > > > +  IN  PCI_IO_DEVICE                           *PciDevice,
> > > >
> > > > +  IN  PCI_FEATURE_CONFIGURATION_PHASE         PciConfigPhase,
> > > >
> > > > +  IN  OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > > > *PciFeaturesConfigurationTable
> > > >
> > > > +  )
> > > >
> > > > +{
> > > >
> > > > +  PCI_REG_PCIE_DEVICE_CAPABILITY  PciDeviceCap;
> > > >
> > > > +  UINT8                           MrrsValue;
> > > >
> > > > +
> > > >
> > > > +  PciDeviceCap.Uint32 = PciDevice-
> >PciExpStruct.DeviceCapability.Uint32;
> > > >
> > > > +
> > > >
> > > > +  if ( PciConfigPhase == PciFeatureGetDevicePolicy) {
> > > >
> > > > +    if ( SetupMrrsAsPerDeviceCapability ( PciDevice->SetupMRRS))
> > > >
> > > > +    {
> > > >
> > > > +      //
> > > >
> > > > +      // The maximum read request size is not the data packet size of the
> > > TLP,
> > > >
> > > > +      // but the memory read request size, and set to the function as a
> > > > requestor
> > > >
> > > > +      // to not exceed this limit.
> > > >
> > > > +      // However, for the PCI device capable of isochronous traffic; this
> > > > memory read
> > > >
> > > > +      // request size should not extend beyond the Max_Payload_Size.
> Thus,
> > > > in case if
> > > >
> > > > +      // device policy return by platform indicates to set as per device
> > > > capability
> > > >
> > > > +      // than set as per Max_Payload_Size configuration value
> > > >
> > > > +      //
> > > >
> > > > +      if ( SetupMaxPayloadSize()) {
> > > >
> > > > +        MrrsValue = PciDevice->SetupMPS;
> > > >
> > > > +      } else {
> > > >
> > > > +        //
> > > >
> > > > +        // in case this driver is not required to configure the
> > > Max_Payload_Size
> > > >
> > > > +        // than consider programming HCF of the device capability's
> > > > Max_Payload_Size
> > > >
> > > > +        // in this PCI hierarchy; thus making this an implementation
> specific
> > > > feature
> > > >
> > > > +        // which the platform should avoid. For better results, the
> platform
> > > > should
> > > >
> > > > +        // make both the Max_Payload_Size & Max_Read_Request_Size
> to
> > > be
> > > > configured
> > > >
> > > > +        // by this driver
> > > >
> > > > +        //
> > > >
> > > > +        MrrsValue = (UINT8)PciDeviceCap.Bits.MaxPayloadSize;
> > > >
> > > > +      }
> > > >
> > > > +    } else {
> > > >
> > > > +      //
> > > >
> > > > +      // override as per platform based device policy
> > > >
> > > > +      //
> > > >
> > > > +      MrrsValue = TranslateMrrsSetupValueToPci ( PciDevice-
> >SetupMRRS);
> > > >
> > > > +      //
> > > >
> > > > +      // align this device's Max_Read_Request_Size value to the entire
> PCI
> > > > tree
> > > >
> > > > +      //
> > > >
> > > > +      if ( PciFeaturesConfigurationTable) {
> > > >
> > > > +        if ( !PciFeaturesConfigurationTable-
> >Lock_Max_Read_Request_Size)
> > > {
> > > >
> > > > +          PciFeaturesConfigurationTable->Lock_Max_Read_Request_Size
> =
> > > > TRUE;
> > > >
> > > > +          PciFeaturesConfigurationTable->Max_Read_Request_Size =
> > > > MrrsValue;
> > > >
> > > > +        } else {
> > > >
> > > > +          //
> > > >
> > > > +          // in case of another user enforced value of MRRS within the
> same
> > > > tree,
> > > >
> > > > +          // pick the smallest between the locked value and this value; to
> set
> > > >
> > > > +          // across entire PCI tree nodes
> > > >
> > > > +          //
> > > >
> > > > +          MrrsValue = MIN (
> > > >
> > > > +                        MrrsValue,
> > > >
> > > > +                        PciFeaturesConfigurationTable->Max_Read_Request_Size
> > > >
> > > > +                        );
> > > >
> > > > +          PciFeaturesConfigurationTable->Max_Read_Request_Size =
> > > > MrrsValue;
> > > >
> > > > +        }
> > > >
> > > > +      }
> > > >
> > > > +    }
> > > >
> > > > +    //
> > > >
> > > > +    // align this device's Max_Read_Request_Size to derived
> configuration
> > > > value
> > > >
> > > > +    //
> > > >
> > > > +    PciDevice->SetupMRRS = MrrsValue;
> > > >
> > > > +
> > > >
> > > > +  }
> > > >
> > > > +
> > > >
> > > > +  //
> > > >
> > > > +  // align the Max_Read_Request_Size of the PCI tree based on 3
> > > conditions:
> > > >
> > > > +  // first, if user defines MRRS for any one PCI device in the tree than
> align
> > > >
> > > > +  // all the devices in the PCI tree.
> > > >
> > > > +  // second, if user override is not define for this PCI tree than setup
> the
> > > > MRRS
> > > >
> > > > +  // based on MPS value of the tree to meet the criteria for the
> > > isochronous
> > > >
> > > > +  // traffic.
> > > >
> > > > +  // third, if no user override, or platform firmware policy has not
> selected
> > > >
> > > > +  // this PCI bus driver to configure the MPS; than configure the MRRS
> to a
> > > >
> > > > +  // highest common value of PCI device capability for the MPS found
> > > among
> > > > all
> > > >
> > > > +  // the PCI devices in this tree
> > > >
> > > > +  //
> > > >
> > > > +  if ( PciFeaturesConfigurationTable) {
> > > >
> > > > +    if ( PciFeaturesConfigurationTable->Lock_Max_Read_Request_Size)
> {
> > > >
> > > > +      PciDevice->SetupMRRS = PciFeaturesConfigurationTable-
> > > > >Max_Read_Request_Size;
> > > >
> > > > +    } else {
> > > >
> > > > +      if ( SetupMaxPayloadSize()) {
> > > >
> > > > +        PciDevice->SetupMRRS = PciDevice->SetupMPS;
> > > >
> > > > +      } else {
> > > >
> > > > +        PciDevice->SetupMRRS = MIN (
> > > >
> > > > +                                PciDevice->SetupMRRS,
> > > >
> > > > +                                PciFeaturesConfigurationTable-
> > > >Max_Read_Request_Size
> > > >
> > > > +                                );
> > > >
> > > > +      }
> > > >
> > > > +      PciFeaturesConfigurationTable->Max_Read_Request_Size =
> > > PciDevice-
> > > > >SetupMRRS;
> > > >
> > > > +    }
> > > >
> > > > +  }
> > > >
> > > > +  DEBUG (( DEBUG_INFO, "Max_Read_Request_Size: %d\n",
> PciDevice-
> > > > >SetupMRRS));
> > > >
> > > > +
> > > >
> > > > +  return EFI_SUCCESS;
> > > >
> > > > +}
> > > >
> > > > +
> > > >
> > > > +/**
> > > >
> > > > +  Overrides the PCI Device Control register MaxPayloadSize register
> field;
> > > if
> > > >
> > > > +  the hardware value is different than the intended value.
> > > >
> > > > +
> > > >
> > > > +  @param  PciDevice             A pointer to the PCI_IO_DEVICE instance.
> > > >
> > > > +
> > > >
> > > > +  @retval EFI_SUCCESS           The data was read from or written to the
> PCI
> > > > device.
> > > >
> > > > +  @retval EFI_UNSUPPORTED       The address range specified by Offset,
> > > > Width, and Count is not
> > > >
> > > > +                                valid for the PCI configuration header of the PCI
> > controller.
> > > >
> > > > +  @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid.
> > > >
> > > > +
> > > >
> > > > +**/
> > > >
> > > > +EFI_STATUS
> > > >
> > > > +OverrideMaxPayloadSize (
> > > >
> > > > +  IN PCI_IO_DEVICE          *PciDevice
> > > >
> > > > +  )
> > > >
> > > > +{
> > > >
> > > > +  PCI_REG_PCIE_DEVICE_CONTROL PcieDev;
> > > >
> > > > +  UINT32                      Offset;
> > > >
> > > > +  EFI_STATUS                  Status;
> > > >
> > > > +
> > > >
> > > > +  PcieDev.Uint16 = 0;
> > > >
> > > > +  Offset = PciDevice->PciExpressCapabilityOffset +
> > > >
> > > > +               OFFSET_OF (PCI_CAPABILITY_PCIEXP, DeviceControl);
> > > >
> > > > +  Status = PciDevice->PciIo.Pci.Read (
> > > >
> > > > +                                  &PciDevice->PciIo,
> > > >
> > > > +                                  EfiPciIoWidthUint16,
> > > >
> > > > +                                  Offset,
> > > >
> > > > +                                  1,
> > > >
> > > > +                                  &PcieDev.Uint16
> > > >
> > > > +                                );
> > > >
> > > > +  if ( EFI_ERROR(Status)){
> > > >
> > > > +    DEBUG (( DEBUG_ERROR, "Unexpected DeviceControl register
> (0x%x)
> > > > read error!",
> > > >
> > > > +        Offset
> > > >
> > > > +    ));
> > > >
> > > > +    return Status;
> > > >
> > > > +  }
> > > >
> > > > +  if ( PcieDev.Bits.MaxPayloadSize != PciDevice->SetupMPS) {
> > > >
> > > > +    PcieDev.Bits.MaxPayloadSize = PciDevice->SetupMPS;
> > > >
> > > > +    DEBUG (( DEBUG_INFO, "Max_Payload_Size=%d,", PciDevice-
> > > > >SetupMPS));
> > > >
> > > > +
> > > >
> > > > +    Status = PciDevice->PciIo.Pci.Write (
> > > >
> > > > +                                    &PciDevice->PciIo,
> > > >
> > > > +                                    EfiPciIoWidthUint16,
> > > >
> > > > +                                    Offset,
> > > >
> > > > +                                    1,
> > > >
> > > > +                                    &PcieDev.Uint16
> > > >
> > > > +                                  );
> > > >
> > > > +    if ( !EFI_ERROR(Status)) {
> > > >
> > > > +      PciDevice->PciExpStruct.DeviceControl.Uint16 = PcieDev.Uint16;
> > > >
> > > > +    } else {
> > > >
> > > > +      DEBUG (( DEBUG_ERROR, "Unexpected DeviceControl register
> (0x%x)
> > > > write error!",
> > > >
> > > > +          Offset
> > > >
> > > > +      ));
> > > >
> > > > +    }
> > > >
> > > > +  } else {
> > > >
> > > > +    DEBUG (( DEBUG_INFO, "No write of Max_Payload_Size=%d,",
> > > PciDevice-
> > > > >SetupMPS));
> > > >
> > > > +  }
> > > >
> > > > +
> > > >
> > > > +  return Status;
> > > >
> > > > +}
> > > >
> > > > +
> > > >
> > > > +/**
> > > >
> > > > +  Overrides the PCI Device Control register MaxPayloadSize register
> field;
> > > if
> > > >
> > > > +  the hardware value is different than the intended value.
> > > >
> > > > +
> > > >
> > > > +  @param  PciDevice             A pointer to the PCI_IO_DEVICE instance.
> > > >
> > > > +
> > > >
> > > > +  @retval EFI_SUCCESS           The data was read from or written to the
> PCI
> > > > controller.
> > > >
> > > > +  @retval EFI_UNSUPPORTED       The address range specified by Offset,
> > > > Width, and Count is not
> > > >
> > > > +                                valid for the PCI configuration header of the PCI
> > controller.
> > > >
> > > > +  @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid.
> > > >
> > > > +
> > > >
> > > > +**/
> > > >
> > > > +EFI_STATUS
> > > >
> > > > +OverrideMaxReadReqSize (
> > > >
> > > > +  IN PCI_IO_DEVICE          *PciDevice
> > > >
> > > > +  )
> > > >
> > > > +{
> > > >
> > > > +  PCI_REG_PCIE_DEVICE_CONTROL PcieDev;
> > > >
> > > > +  UINT32                      Offset;
> > > >
> > > > +  EFI_STATUS                  Status;
> > > >
> > > > +
> > > >
> > > > +  PcieDev.Uint16 = 0;
> > > >
> > > > +  Offset = PciDevice->PciExpressCapabilityOffset +
> > > >
> > > > +               OFFSET_OF (PCI_CAPABILITY_PCIEXP, DeviceControl);
> > > >
> > > > +  Status = PciDevice->PciIo.Pci.Read (
> > > >
> > > > +                                  &PciDevice->PciIo,
> > > >
> > > > +                                  EfiPciIoWidthUint16,
> > > >
> > > > +                                  Offset,
> > > >
> > > > +                                  1,
> > > >
> > > > +                                  &PcieDev.Uint16
> > > >
> > > > +                                );
> > > >
> > > > +  if ( EFI_ERROR(Status)){
> > > >
> > > > +    DEBUG (( DEBUG_ERROR, "Unexpected DeviceControl register
> (0x%x)
> > > > read error!",
> > > >
> > > > +        Offset
> > > >
> > > > +    ));
> > > >
> > > > +    return Status;
> > > >
> > > > +  }
> > > >
> > > > +  if ( PcieDev.Bits.MaxReadRequestSize != PciDevice->SetupMRRS) {
> > > >
> > > > +    PcieDev.Bits.MaxReadRequestSize = PciDevice->SetupMRRS;
> > > >
> > > > +    DEBUG (( DEBUG_INFO, "Max_Read_Request_Size: %d\n",
> PciDevice-
> > > > >SetupMRRS));
> > > >
> > > > +
> > > >
> > > > +    Status = PciDevice->PciIo.Pci.Write (
> > > >
> > > > +                                    &PciDevice->PciIo,
> > > >
> > > > +                                    EfiPciIoWidthUint16,
> > > >
> > > > +                                    Offset,
> > > >
> > > > +                                    1,
> > > >
> > > > +                                    &PcieDev.Uint16
> > > >
> > > > +                                  );
> > > >
> > > > +    if ( !EFI_ERROR(Status)) {
> > > >
> > > > +      PciDevice->PciExpStruct.DeviceControl.Uint16 = PcieDev.Uint16;
> > > >
> > > > +    } else {
> > > >
> > > > +      DEBUG (( DEBUG_ERROR, "Unexpected DeviceControl register
> (0x%x)
> > > > write error!",
> > > >
> > > > +          Offset
> > > >
> > > > +      ));
> > > >
> > > > +    }
> > > >
> > > > +  } else {
> > > >
> > > > +    DEBUG (( DEBUG_INFO, "No write of
> Max_Read_Request_Size=%d\n",
> > > > PciDevice->SetupMRRS));
> > > >
> > > > +  }
> > > >
> > > > +
> > > >
> > > > +  return Status;
> > > >
> > > > +}
> > > >
> > > > +
> > > >
> > > > +/**
> > > >
> > > > +  helper routine to dump the PCIe Device Port Type
> > > >
> > > > +**/
> > > >
> > > > +VOID
> > > >
> > > > +DumpDevicePortType (
> > > >
> > > > +  IN  UINT8   DevicePortType
> > > >
> > > > +  )
> > > >
> > > > +{
> > > >
> > > > +  switch ( DevicePortType){
> > > >
> > > > +    case PCIE_DEVICE_PORT_TYPE_PCIE_ENDPOINT:
> > > >
> > > > +      DEBUG (( DEBUG_INFO, "PCIe endpoint found\n"));
> > > >
> > > > +      break;
> > > >
> > > > +    case PCIE_DEVICE_PORT_TYPE_LEGACY_PCIE_ENDPOINT:
> > > >
> > > > +      DEBUG (( DEBUG_INFO, "legacy PCI endpoint found\n"));
> > > >
> > > > +      break;
> > > >
> > > > +    case PCIE_DEVICE_PORT_TYPE_ROOT_PORT:
> > > >
> > > > +      DEBUG (( DEBUG_INFO, "PCIe Root Port found\n"));
> > > >
> > > > +      break;
> > > >
> > > > +    case PCIE_DEVICE_PORT_TYPE_UPSTREAM_PORT:
> > > >
> > > > +      DEBUG (( DEBUG_INFO, "PCI switch upstream port found\n"));
> > > >
> > > > +      break;
> > > >
> > > > +    case PCIE_DEVICE_PORT_TYPE_DOWNSTREAM_PORT:
> > > >
> > > > +      DEBUG (( DEBUG_INFO, "PCI switch downstream port found\n"));
> > > >
> > > > +      break;
> > > >
> > > > +    case PCIE_DEVICE_PORT_TYPE_PCIE_TO_PCI_BRIDGE:
> > > >
> > > > +      DEBUG (( DEBUG_INFO, "PCIe-PCI bridge found\n"));
> > > >
> > > > +      break;
> > > >
> > > > +    case PCIE_DEVICE_PORT_TYPE_PCI_TO_PCIE_BRIDGE:
> > > >
> > > > +      DEBUG (( DEBUG_INFO, "PCI-PCIe bridge found\n"));
> > > >
> > > > +      break;
> > > >
> > > > +    case
> > > > PCIE_DEVICE_PORT_TYPE_ROOT_COMPLEX_INTEGRATED_ENDPOINT:
> > > >
> > > > +      DEBUG (( DEBUG_INFO, "RCiEP found\n"));
> > > >
> > > > +      break;
> > > >
> > > > +    case
> PCIE_DEVICE_PORT_TYPE_ROOT_COMPLEX_EVENT_COLLECTOR:
> > > >
> > > > +      DEBUG (( DEBUG_INFO, "RC Event Collector found\n"));
> > > >
> > > > +      break;
> > > >
> > > > +  }
> > > >
> > > > +}
> > > >
> > > > +
> > > >
> > > > +/**
> > > >
> > > > +   Process each PCI device as per the pltaform and device-specific
> policy.
> > > >
> > > > +
> > > >
> > > > +  @param RootBridge             A pointer to the PCI_IO_DEVICE.
> > > >
> > > > +
> > > >
> > > > +  @retval EFI_SUCCESS           processing each PCI feature as per policy
> > > > defined
> > > >
> > > > +                                was successful.
> > > >
> > > > + **/
> > > >
> > > > +EFI_STATUS
> > > >
> > > > +SetupDevicePciFeatures (
> > > >
> > > > +  IN  PCI_IO_DEVICE                   *PciDevice,
> > > >
> > > > +  IN  PCI_FEATURE_CONFIGURATION_PHASE PciConfigPhase
> > > >
> > > > +  )
> > > >
> > > > +{
> > > >
> > > > +  EFI_STATUS                              Status;
> > > >
> > > > +  PCI_REG_PCIE_CAPABILITY                 PcieCap;
> > > >
> > > > +  OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > > > *OtherPciFeaturesConfigTable;
> > > >
> > > > +
> > > >
> > > > +  PcieCap.Uint16 = PciDevice->PciExpStruct.Capability.Uint16;
> > > >
> > > > +  DumpDevicePortType ( (UINT8)PcieCap.Bits.DevicePortType);
> > > >
> > > > +
> > > >
> > > > +  OtherPciFeaturesConfigTable = NULL;
> > > >
> > > > +  Status = GetPciFeaturesConfigurationTable ( PciDevice,
> > > > &OtherPciFeaturesConfigTable);
> > > >
> > > > +  if ( EFI_ERROR( Status)) {
> > > >
> > > > +    DEBUG ((
> > > >
> > > > +        EFI_D_WARN, "No primary root port found in these root bridge
> > > > nodes!\n"
> > > >
> > > > +    ));
> > > >
> > > > +  } else if ( !OtherPciFeaturesConfigTable) {
> > > >
> > > > +    DEBUG ((
> > > >
> > > > +        DEBUG_INFO, "No PCI features config. table for this device!\n"
> > > >
> > > > +    ));
> > > >
> > > > +  } else {
> > > >
> > > > +    DEBUG ((
> > > >
> > > > +        DEBUG_INFO, "using PCI features config. table ID: %d\n",
> > > >
> > > > +        OtherPciFeaturesConfigTable->ID
> > > >
> > > > +    ));
> > > >
> > > > +  }
> > > >
> > > > +
> > > >
> > > > +  if ( PciConfigPhase == PciFeatureGetDevicePolicy) {
> > > >
> > > > +    Status = GetPciDevicePlatformPolicy ( PciDevice);
> > > >
> > > > +    if ( EFI_ERROR(Status)) {
> > > >
> > > > +      DEBUG ((
> > > >
> > > > +          DEBUG_ERROR, "Error in obtaining PCI device policy!!!\n"
> > > >
> > > > +      ));
> > > >
> > > > +    }
> > > >
> > > > +  }
> > > >
> > > > +
> > > >
> > > > +  if ( SetupMaxPayloadSize ()) {
> > > >
> > > > +    Status = ProcessMaxPayloadSize (
> > > >
> > > > +              PciDevice,
> > > >
> > > > +              PciConfigPhase,
> > > >
> > > > +              OtherPciFeaturesConfigTable
> > > >
> > > > +              );
> > > >
> > > > +  }
> > > >
> > > > +  //
> > > >
> > > > +  // implementation specific rule:- the MRRS of any PCI device should
> be
> > > > processed
> > > >
> > > > +  // only after the MPS is processed for that device
> > > >
> > > > +  //
> > > >
> > > > +  if ( SetupMaxReadReqSize ()) {
> > > >
> > > > +    Status = ProcessMaxReadReqSize (
> > > >
> > > > +              PciDevice,
> > > >
> > > > +              PciConfigPhase,
> > > >
> > > > +              OtherPciFeaturesConfigTable
> > > >
> > > > +              );
> > > >
> > > > +  }
> > > >
> > > > +  return Status;
> > > >
> > > > +}
> > > >
> > > > +
> > > >
> > > > +/**
> > > >
> > > > +  Traverse all the nodes from the root bridge or PCI-PCI bridge instance,
> to
> > > >
> > > > +  configure the PCI features as per the device-specific platform policy,
> and
> > > >
> > > > +  as per the device capability, as applicable.
> > > >
> > > > +
> > > >
> > > > +  @param RootBridge             A pointer to the PCI_IO_DEVICE.
> > > >
> > > > +
> > > >
> > > > +  @retval EFI_SUCCESS           Traversing all the nodes of the root bridge
> > > >
> > > > +                                instances were successfull.
> > > >
> > > > +**/
> > > >
> > > > +EFI_STATUS
> > > >
> > > > +SetupPciFeatures (
> > > >
> > > > +  IN  PCI_IO_DEVICE                   *RootBridge,
> > > >
> > > > +  IN  PCI_FEATURE_CONFIGURATION_PHASE PciConfigPhase
> > > >
> > > > +  )
> > > >
> > > > +{
> > > >
> > > > +  EFI_STATUS           Status;
> > > >
> > > > +  LIST_ENTRY           *Link;
> > > >
> > > > +  PCI_IO_DEVICE        *Device;
> > > >
> > > > +
> > > >
> > > > +  for ( Link = RootBridge->ChildList.ForwardLink
> > > >
> > > > +      ; Link != &RootBridge->ChildList
> > > >
> > > > +      ; Link = Link->ForwardLink
> > > >
> > > > +  ) {
> > > >
> > > > +    Device = PCI_IO_DEVICE_FROM_LINK (Link);
> > > >
> > > > +    if (IS_PCI_BRIDGE (&Device->Pci)) {
> > > >
> > > > +      DEBUG ((
> > > >
> > > > +          DEBUG_INFO, "::Bridge [%02x|%02x|%02x] -",
> > > >
> > > > +          Device->BusNumber, Device->DeviceNumber, Device-
> > > > >FunctionNumber
> > > >
> > > > +      ));
> > > >
> > > > +      if (Device->IsPciExp) {
> > > >
> > > > +        Status = SetupDevicePciFeatures ( Device, PciConfigPhase);
> > > >
> > > > +      } else {
> > > >
> > > > +        DEBUG (( DEBUG_INFO, "Not a PCIe capable device!\n"));
> > > >
> > > > +        //
> > > >
> > > > +        // PCI Bridge which does not have PCI Express Capability structure
> > > >
> > > > +        // cannot process this kind of PCI Bridge device
> > > >
> > > > +        //
> > > >
> > > > +
> > > >
> > > > +      }
> > > >
> > > > +
> > > >
> > > > +      SetupPciFeatures ( Device, PciConfigPhase);
> > > >
> > > > +    } else {
> > > >
> > > > +      DEBUG ((
> > > >
> > > > +          DEBUG_INFO, "::Device [%02x|%02x|%02x] -",
> > > >
> > > > +          Device->BusNumber, Device->DeviceNumber, Device-
> > > > >FunctionNumber
> > > >
> > > > +      ));
> > > >
> > > > +      if (Device->IsPciExp) {
> > > >
> > > > +
> > > >
> > > > +        Status = SetupDevicePciFeatures ( Device, PciConfigPhase);
> > > >
> > > > +      } else {
> > > >
> > > > +        DEBUG (( DEBUG_INFO, "Not a PCIe capable device!\n"));
> > > >
> > > > +        //
> > > >
> > > > +        // PCI Device which does not have PCI Express Capability structure
> > > >
> > > > +        // cannot process this kind of PCI device
> > > >
> > > > +        //
> > > >
> > > > +      }
> > > >
> > > > +    }
> > > >
> > > > +  }
> > > >
> > > > +
> > > >
> > > > +  return EFI_SUCCESS;
> > > >
> > > > +}
> > > >
> > > > +
> > > >
> > > > +/**
> > > >
> > > > +  Program the PCI device, to override the PCI features as per the policy,
> > > >
> > > > +  resolved from previous traverse.
> > > >
> > > > +
> > > >
> > > > +  @param RootBridge             A pointer to the PCI_IO_DEVICE.
> > > >
> > > > +
> > > >
> > > > +  @retval EFI_SUCCESS           The other PCI features configuration
> during
> > > > enumeration
> > > >
> > > > +                                of all the nodes of the PCI root bridge instance were
> > > >
> > > > +                                programmed in PCI-compliance pattern along with the
> > > >
> > > > +                                device-specific policy, as applicable.
> > > >
> > > > +  @retval EFI_UNSUPPORTED       One of the override operation maong
> the
> > > > nodes of
> > > >
> > > > +                                the PCI hierarchy resulted in a incompatible address
> > > >
> > > > +                                range.
> > > >
> > > > +  @retval EFI_INVALID_PARAMETER The override operation is
> performed
> > > > with invalid input
> > > >
> > > > +                                parameters.
> > > >
> > > > +**/
> > > >
> > > > +EFI_STATUS
> > > >
> > > > +ProgramDevicePciFeatures (
> > > >
> > > > +  IN PCI_IO_DEVICE          *PciDevice
> > > >
> > > > +  )
> > > >
> > > > +{
> > > >
> > > > +  EFI_STATUS           Status;
> > > >
> > > > +
> > > >
> > > > +  if ( SetupMaxPayloadSize ()) {
> > > >
> > > > +    Status = OverrideMaxPayloadSize (PciDevice);
> > > >
> > > > +  }
> > > >
> > > > +  if ( SetupMaxReadReqSize ()) {
> > > >
> > > > +    Status = OverrideMaxReadReqSize (PciDevice);
> > > >
> > > > +  }
> > > >
> > > > +  return Status;
> > > >
> > > > +}
> > > >
> > > > +
> > > >
> > > > +/**
> > > >
> > > > +  Program all the nodes of the specified root bridge or PCI-PCI Bridge,
> to
> > > >
> > > > +  override the PCI features.
> > > >
> > > > +
> > > >
> > > > +  @param RootBridge             A pointer to the PCI_IO_DEVICE.
> > > >
> > > > +
> > > >
> > > > +  @retval EFI_SUCCESS           The other PCI features configuration
> during
> > > > enumeration
> > > >
> > > > +                                of all the nodes of the PCI root bridge instance were
> > > >
> > > > +                                programmed in PCI-compliance pattern along with the
> > > >
> > > > +                                device-specific policy, as applicable.
> > > >
> > > > +  @retval EFI_UNSUPPORTED       One of the override operation maong
> the
> > > > nodes of
> > > >
> > > > +                                the PCI hierarchy resulted in a incompatible address
> > > >
> > > > +                                range.
> > > >
> > > > +  @retval EFI_INVALID_PARAMETER The override operation is
> performed
> > > > with invalid input
> > > >
> > > > +                                parameters.
> > > >
> > > > +**/
> > > >
> > > > +EFI_STATUS
> > > >
> > > > +ProgramPciFeatures (
> > > >
> > > > +  IN PCI_IO_DEVICE          *RootBridge
> > > >
> > > > +  )
> > > >
> > > > +{
> > > >
> > > > +  EFI_STATUS           Status;
> > > >
> > > > +  LIST_ENTRY           *Link;
> > > >
> > > > +  PCI_IO_DEVICE        *Device;
> > > >
> > > > +
> > > >
> > > > +  for ( Link = RootBridge->ChildList.ForwardLink
> > > >
> > > > +      ; Link != &RootBridge->ChildList
> > > >
> > > > +      ; Link = Link->ForwardLink
> > > >
> > > > +  ) {
> > > >
> > > > +    Device = PCI_IO_DEVICE_FROM_LINK (Link);
> > > >
> > > > +    if (IS_PCI_BRIDGE (&Device->Pci)) {
> > > >
> > > > +      DEBUG ((
> > > >
> > > > +          DEBUG_INFO, "::Bridge [%02x|%02x|%02x] -",
> > > >
> > > > +          Device->BusNumber, Device->DeviceNumber, Device-
> > > > >FunctionNumber
> > > >
> > > > +      ));
> > > >
> > > > +      if (Device->IsPciExp) {
> > > >
> > > > +        DEBUG (( DEBUG_INFO, "ready to override!\n"));
> > > >
> > > > +
> > > >
> > > > +        Status = ProgramDevicePciFeatures ( Device);
> > > >
> > > > +      } else {
> > > >
> > > > +        DEBUG (( DEBUG_INFO, "skipped!\n"));
> > > >
> > > > +        //
> > > >
> > > > +        // PCI Bridge which does not have PCI Express Capability structure
> > > >
> > > > +        // cannot process this kind of PCI Bridge device
> > > >
> > > > +        //
> > > >
> > > > +
> > > >
> > > > +      }
> > > >
> > > > +
> > > >
> > > > +      Status = ProgramPciFeatures ( Device);
> > > >
> > > > +    } else {
> > > >
> > > > +      DEBUG ((
> > > >
> > > > +          DEBUG_INFO, "::Device [%02x|%02x|%02x] -",
> > > >
> > > > +          Device->BusNumber, Device->DeviceNumber, Device-
> > > > >FunctionNumber
> > > >
> > > > +      ));
> > > >
> > > > +      if (Device->IsPciExp) {
> > > >
> > > > +        DEBUG (( DEBUG_INFO, "ready to override!\n"));
> > > >
> > > > +
> > > >
> > > > +        Status = ProgramDevicePciFeatures ( Device);
> > > >
> > > > +      } else {
> > > >
> > > > +        DEBUG (( DEBUG_INFO, "skipped!\n"));
> > > >
> > > > +        //
> > > >
> > > > +        // PCI Device which does not have PCI Express Capability structure
> > > >
> > > > +        // cannot process this kind of PCI device
> > > >
> > > > +        //
> > > >
> > > > +      }
> > > >
> > > > +    }
> > > >
> > > > +  }
> > > >
> > > > +
> > > >
> > > > +  return Status;
> > > >
> > > > +}
> > > >
> > > > +
> > > >
> > > > +/**
> > > >
> > > > +  Create a node of type PRIMARY_ROOT_PORT_NODE for the given
> PCI
> > > > device, and
> > > >
> > > > +  assigns EFI handles of its Root Bridge and its own, along with its PCI
> Bus
> > > >
> > > > +  range for the secondary and subordinate bus range.
> > > >
> > > > +
> > > >
> > > > +  @param  RootBridge          A pointer to the PCI_IO_DEVICE for its PCI
> Root
> > > > Bridge
> > > >
> > > > +  @param  Device              A pointer to the PCI_IO_DEVICE for the PCI
> > > > controller
> > > >
> > > > +  @param  RootPortSecBus      PCI controller's Secondary Bus number
> > > >
> > > > +  @param  RootPortSubBus      PCI controller's Subordinate Bus number
> > > >
> > > > +  @param  PrimaryRootPortNode A pointer to the
> > > > PRIMARY_ROOT_PORT_NODE to return
> > > >
> > > > +                              the newly created node for the PCI controller. In
> > > >
> > > > +                              case of error nothing is return in this.
> > > >
> > > > +
> > > >
> > > > +  @retval EFI_SUCCESS           new node of
> PRIMARY_ROOT_PORT_NODE is
> > > > returned for
> > > >
> > > > +                                the PCI controller
> > > >
> > > > +          EFI_OUT_OF_RESOURCES  unable to create the node for the PCI
> > > > controller
> > > >
> > > > +          EFI_INVALID_PARAMETER unable to store the node as the input
> > > > buffer is
> > > >
> > > > +                                not empty (*PrimaryRootPortNode)
> > > >
> > > > +**/
> > > >
> > > > +EFI_STATUS
> > > >
> > > > +CreatePrimaryPciRootPortNode (
> > > >
> > > > +  IN  PCI_IO_DEVICE           *RootBridge,
> > > >
> > > > +  IN  PCI_IO_DEVICE           *Device,
> > > >
> > > > +  IN  UINT8                   RootPortSecBus,
> > > >
> > > > +  IN  UINT8                   RootPortSubBus,
> > > >
> > > > +  OUT PRIMARY_ROOT_PORT_NODE  **PrimaryRootPortNode
> > > >
> > > > +  )
> > > >
> > > > +{
> > > >
> > > > +  PRIMARY_ROOT_PORT_NODE      *RootPortNode = NULL;
> > > >
> > > > +
> > > >
> > > > +  if ( !*PrimaryRootPortNode) {
> > > >
> > > > +    RootPortNode                    = AllocateZeroPool ( sizeof
> > > > (PRIMARY_ROOT_PORT_NODE));
> > > >
> > > > +    if ( RootPortNode == NULL) {
> > > >
> > > > +      return EFI_OUT_OF_RESOURCES;
> > > >
> > > > +    }
> > > >
> > > > +    RootPortNode->Signature         = PCI_ROOT_PORT_SIGNATURE;
> > > >
> > > > +    RootPortNode->RootBridgeHandle  = RootBridge->Handle;
> > > >
> > > > +    RootPortNode->RootPortHandle    = Device->Handle;
> > > >
> > > > +    RootPortNode->SecondaryBusStart = RootPortSecBus;
> > > >
> > > > +    RootPortNode->SecondaryBusEnd   = RootPortSubBus;
> > > >
> > > > +    InitializeListHead ( &RootPortNode->NeighborRootPort);
> > > >
> > > > +    *PrimaryRootPortNode = RootPortNode;
> > > >
> > > > +    return EFI_SUCCESS;
> > > >
> > > > +  } else {
> > > >
> > > > +    return EFI_INVALID_PARAMETER;
> > > >
> > > > +  }
> > > >
> > > > +}
> > > >
> > > > +
> > > >
> > > > +/**
> > > >
> > > > +  Checks to report whether the input PCI controller's secondary /
> > > > subordinate
> > > >
> > > > +  bus numbers are within the recorded list of other PCI controllers
> (root
> > > > ports).
> > > >
> > > > +
> > > >
> > > > +  @param  RootPortNode      A pointer to the first node of
> > > > PRIMARY_ROOT_PORT_NODE
> > > >
> > > > +  @param  RootPortSecBus    PCI secondary bus number of the PCI
> > > controller
> > > > found
> > > >
> > > > +  @param  RootPortSubBus    PCI subordinate bus number of the PCI
> Root
> > > > Port found
> > > >
> > > > +
> > > >
> > > > +  @retval TRUE              A child PCI Root port found
> > > >
> > > > +          FALSE             A new PCI controller found
> > > >
> > > > +**/
> > > >
> > > > +BOOLEAN
> > > >
> > > > +CheckChildRootPort (
> > > >
> > > > +  IN      PRIMARY_ROOT_PORT_NODE  *RootPortNode,
> > > >
> > > > +  IN      UINT8                   RootPortSecBus,
> > > >
> > > > +  IN      UINT8                   RootPortSubBus
> > > >
> > > > +)
> > > >
> > > > +{
> > > >
> > > > +  LIST_ENTRY              *Link;
> > > >
> > > > +  PRIMARY_ROOT_PORT_NODE  *Temp;
> > > >
> > > > +
> > > >
> > > > +  if ( !RootPortNode) {
> > > >
> > > > +    return FALSE;
> > > >
> > > > +  }
> > > >
> > > > +  Link = &RootPortNode->NeighborRootPort;
> > > >
> > > > +  do {
> > > >
> > > > +    Temp = PRIMARY_ROOT_PORT_NODE_FROM_LINK ( Link);
> > > >
> > > > +    if ( RootPortSecBus >= Temp->SecondaryBusStart
> > > >
> > > > +        && RootPortSubBus <= Temp->SecondaryBusEnd) {
> > > >
> > > > +      //
> > > >
> > > > +      // given root port's secondary & subordinate within its primary
> ports
> > > >
> > > > +      // hence return as child port
> > > >
> > > > +      //
> > > >
> > > > +      return TRUE;
> > > >
> > > > +    }
> > > >
> > > > +    Link = Link->ForwardLink;
> > > >
> > > > +  } while (Link != &RootPortNode->NeighborRootPort);
> > > >
> > > > +  //
> > > >
> > > > +  // the given root port's secondary / subordinate bus numbers do not
> > > > belong to
> > > >
> > > > +  // any existing primary root port's bus range hence consider another
> > > > primary
> > > >
> > > > +  // root port of the root bridge controller
> > > >
> > > > +  //
> > > >
> > > > +  return FALSE;
> > > >
> > > > +}
> > > >
> > > > +
> > > >
> > > > +/**
> > > >
> > > > +  Create the vector of PCI Feature configuration table as per the
> number
> > > of
> > > >
> > > > +  the PCI Root Ports given, assigns default value to the PCI features
> > > > supported
> > > >
> > > > +  and assign its address to the global variable
> > > > "mPciFeaturesConfigurationTableInstances".
> > > >
> > > > +
> > > >
> > > > +  @param  NumberOfRootPorts   An input arguement of UINTN to
> indicate
> > > > number of
> > > >
> > > > +                              primary PCI physical Root Bridge devices found
> > > >
> > > > +
> > > >
> > > > +  @retval EFI_OUT_OF_RESOURCES  unable to allocate buffer to store
> PCI
> > > > feature
> > > >
> > > > +                                configuration table for all the physical PCI root
> > > >
> > > > +                                ports given
> > > >
> > > > +          EFI_SUCCESS           PCI Feature COnfiguration table created for all
> > > >
> > > > +                                the PCI Rooot ports reported
> > > >
> > > > + */
> > > >
> > > > +EFI_STATUS
> > > >
> > > > +CreatePciFeaturesConfigurationTableInstances (
> > > >
> > > > +  IN  UINTN NumberOfRootPorts
> > > >
> > > > +  )
> > > >
> > > > +{
> > > >
> > > > +  OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > > > *PciRootBridgePortFeatures = NULL;
> > > >
> > > > +  UINTN                                     Instances;
> > > >
> > > > +
> > > >
> > > > +  PciRootBridgePortFeatures = AllocateZeroPool (
> > > >
> > > > +                                sizeof
> ( OTHER_PCI_FEATURES_CONFIGURATION_TABLE)
> > > *
> > > > NumberOfRootPorts
> > > >
> > > > +                                );
> > > >
> > > > +  if ( !PciRootBridgePortFeatures) {
> > > >
> > > > +    return EFI_OUT_OF_RESOURCES;
> > > >
> > > > +  }
> > > >
> > > > +
> > > >
> > > > +  for ( Instances = 0; Instances < NumberOfRootPorts; Instances++) {
> > > >
> > > > +    PciRootBridgePortFeatures [Instances].ID                    = Instances + 1;
> > > >
> > > > +    PciRootBridgePortFeatures [Instances].Max_Payload_Size      =
> > > > PCIE_MAX_PAYLOAD_SIZE_4096B;
> > > >
> > > > +    PciRootBridgePortFeatures [Instances].Max_Read_Request_Size =
> > > > PCIE_MAX_READ_REQ_SIZE_4096B;
> > > >
> > > > +    PciRootBridgePortFeatures
> [Instances].Lock_Max_Read_Request_Size
> > > =
> > > > FALSE;
> > > >
> > > > +  }
> > > >
> > > > +  mPciFeaturesConfigurationTableInstances =
> PciRootBridgePortFeatures;
> > > >
> > > > +  return EFI_SUCCESS;
> > > >
> > > > +}
> > > >
> > > > +
> > > >
> > > > +/**
> > > >
> > > > +  This routine pairs the each PCI Root Port node with one of the PCI
> > > Feature
> > > >
> > > > +  Configuration Table node. Each physical PCI Root Port has its own PCI
> > > > feature
> > > >
> > > > +  configuration table which will used for aligning all its downstream
> > > > components.
> > > >
> > > > +
> > > >
> > > > +  @param  NumberOfRootPorts     inputs the number of physical PCI
> root
> > > > ports
> > > >
> > > > +                                found on the Root bridge instance
> > > >
> > > > +
> > > >
> > > > +  @retval EFI_INVALID_PARAMETER if the primary PCI root ports list is
> > > > vacant when
> > > >
> > > > +                                there is one or more PCI Root port indicated as per
> > > >
> > > > +                                input parameter
> > > >
> > > > +          EFI_UNSUPPORTED       The PCI Root Port nodes not paired
> equally
> > > with
> > > >
> > > > +                                the PCI Configuration Table nodes
> > > >
> > > > +          EFI_SUCCESS           each PCI feature configuration node is paired
> > > > equally
> > > >
> > > > +                                with each PCI Root port in the list
> > > >
> > > > +**/
> > > >
> > > > +EFI_STATUS
> > > >
> > > > +AssignPciFeaturesConfigurationTable (
> > > >
> > > > +  IN  UINTN NumberOfRootPorts
> > > >
> > > > +  )
> > > >
> > > > +{
> > > >
> > > > +  UINTN                       Instances;
> > > >
> > > > +  LIST_ENTRY                  *Link;
> > > >
> > > > +  PRIMARY_ROOT_PORT_NODE      *Temp;
> > > >
> > > > +
> > > >
> > > > +  if ( !mPrimaryRootPortList
> > > >
> > > > +      && NumberOfRootPorts) {
> > > >
> > > > +    DEBUG ((
> > > >
> > > > +        DEBUG_ERROR,
> > > >
> > > > +        "Critical error! no internal table setup for %d PCI Root ports \n",
> > > >
> > > > +        NumberOfRootPorts
> > > >
> > > > +    ));
> > > >
> > > > +    return EFI_INVALID_PARAMETER;
> > > >
> > > > +  }
> > > >
> > > > +
> > > >
> > > > +  if ( NumberOfRootPorts) {
> > > >
> > > > +    Link = &mPrimaryRootPortList->NeighborRootPort;
> > > >
> > > > +    for ( Instances = 0
> > > >
> > > > +        ; (Instances < NumberOfRootPorts)
> > > >
> > > > +        ; Instances++
> > > >
> > > > +    ) {
> > > >
> > > > +      Temp = PRIMARY_ROOT_PORT_NODE_FROM_LINK ( Link);
> > > >
> > > > +      Temp->OtherPciFeaturesConfigurationTable =
> > > > &mPciFeaturesConfigurationTableInstances [Instances];
> > > >
> > > > +      DEBUG ((
> > > >
> > > > +          DEBUG_INFO,
> > > >
> > > > +          "Assigned to %dth primary root port\n",
> > > >
> > > > +          Instances
> > > >
> > > > +      ));
> > > >
> > > > +
> > > >
> > > > +      Link = Link->ForwardLink;
> > > >
> > > > +    }
> > > >
> > > > +    if ( Link != &mPrimaryRootPortList->NeighborRootPort) {
> > > >
> > > > +      DEBUG ((
> > > >
> > > > +          DEBUG_ERROR,
> > > >
> > > > +          "Error!! PCI Root Port list is not properly matched with Config.,
> Table
> > > > list \n"
> > > >
> > > > +      ));
> > > >
> > > > +      return EFI_UNSUPPORTED;
> > > >
> > > > +    }
> > > >
> > > > +  }
> > > >
> > > > +  return  EFI_SUCCESS;
> > > >
> > > > +}
> > > >
> > > > +
> > > >
> > > > +/**
> > > >
> > > > +  Prepare each PCI Controller (Root Port) with its own PCI Feature
> > > > configuration
> > > >
> > > > +  table node that can be used for tracking to align all PCI nodes in its
> > > > hierarchy.
> > > >
> > > > +
> > > >
> > > > +  @param  PrimaryRootPorts      A pointer to
> PRIMARY_ROOT_PORT_NODE
> > > >
> > > > +  @param  NumberOfRootPorts     Total number of pysical primary PCI
> > > Root
> > > > ports
> > > >
> > > > +
> > > >
> > > > +  @retval EFI_OUT_OF_RESOURCES  unable to allocate buffer to store
> PCI
> > > > feature
> > > >
> > > > +                                configuration table for all the physical PCI root
> > > >
> > > > +                                ports given
> > > >
> > > > +          EFI_INVALID_PARAMETER if the primary PCI root ports list is
> vacant
> > > > when
> > > >
> > > > +                                there is one or more PCI Root port indicated as per
> > > >
> > > > +                                input parameter
> > > >
> > > > +          EFI_UNSUPPORTED       The PCI Root Port nodes not paired
> equally
> > > with
> > > >
> > > > +                                the PCI Configuration Table nodes
> > > >
> > > > +          EFI_SUCCESS           each PCI feature configuration node is paired
> > > > equally
> > > >
> > > > +                                with each PCI Root port in the list
> > > >
> > > > +**/
> > > >
> > > > +EFI_STATUS
> > > >
> > > > +PreparePciControllerConfigurationTable (
> > > >
> > > > +  IN  PRIMARY_ROOT_PORT_NODE    *PrimaryRootPorts,
> > > >
> > > > +  IN  UINTN                     NumberOfRootPorts
> > > >
> > > > +  )
> > > >
> > > > +{
> > > >
> > > > +  EFI_STATUS                    Status;
> > > >
> > > > +
> > > >
> > > > +  mPrimaryRootPortList = PrimaryRootPorts;
> > > >
> > > > +  DEBUG ((
> > > >
> > > > +      DEBUG_INFO, "Number of primary Root Ports found on this bridge
> > > > = %d\n",
> > > >
> > > > +      NumberOfRootPorts
> > > >
> > > > +  ));
> > > >
> > > > +
> > > >
> > > > +  Status = CreatePciFeaturesConfigurationTableInstances
> > > > ( NumberOfRootPorts);
> > > >
> > > > +  if ( EFI_ERROR(Status)) {
> > > >
> > > > +    DEBUG ((
> > > >
> > > > +        DEBUG_ERROR, "Unexpected memory node creation error for PCI
> > > > features!\n"
> > > >
> > > > +    ));
> > > >
> > > > +  } else {
> > > >
> > > > +    //
> > > >
> > > > +    // align the primary root port nodes list with the PCI Feature
> > > configuration
> > > >
> > > > +    // table. Note that the PCI Feature configuration table is not
> maintain
> > > for
> > > >
> > > > +    // the RCiEP devices
> > > >
> > > > +    //
> > > >
> > > > +    Status = AssignPciFeaturesConfigurationTable
> ( NumberOfRootPorts);
> > > >
> > > > +  }
> > > >
> > > > +  return Status;
> > > >
> > > > +}
> > > >
> > > > +
> > > >
> > > > +/**
> > > >
> > > > +  Scan all the nodes of the RootBridge to identify and create a separate
> list
> > > >
> > > > +  of all primary physical PCI root ports and link each with its own
> instance
> > > of
> > > >
> > > > +  the PCI Feature Configuration Table.
> > > >
> > > > +
> > > >
> > > > +  @param  RootBridge    A pointer to the PCI_IO_DEVICE of the PCI
> Root
> > > > Bridge
> > > >
> > > > +
> > > >
> > > > +  @retval EFI_OUT_OF_RESOURCES  unable to allocate buffer to store
> PCI
> > > > feature
> > > >
> > > > +                                configuration table for all the physical PCI root
> > > >
> > > > +                                ports given
> > > >
> > > > +          EFI_NOT_FOUND         No PCI Bridge device found
> > > >
> > > > +          EFI_SUCCESS           PCI Feature COnfiguration table created for all
> > > >
> > > > +                                the PCI Rooot ports found
> > > >
> > > > +          EFI_INVALID_PARAMETER invalid parameter passed to the
> routine
> > > > which
> > > >
> > > > +                                creates the PCI controller node for the primary
> > > >
> > > > +                                Root post list
> > > >
> > > > +**/
> > > >
> > > > +EFI_STATUS
> > > >
> > > > +RecordPciRootPortBridges (
> > > >
> > > > +  IN  PCI_IO_DEVICE           *RootBridge
> > > >
> > > > +  )
> > > >
> > > > +{
> > > >
> > > > +  EFI_STATUS              Status = EFI_NOT_FOUND;
> > > >
> > > > +  LIST_ENTRY              *Link;
> > > >
> > > > +  PCI_IO_DEVICE           *Device;
> > > >
> > > > +  UINTN                   NumberOfRootPorts;
> > > >
> > > > +  PRIMARY_ROOT_PORT_NODE  *PrimaryRootPorts,
> > > >
> > > > +                          *TempNode;
> > > >
> > > > +  UINT8                   RootPortSecBus,
> > > >
> > > > +                          RootPortSubBus;
> > > >
> > > > +
> > > >
> > > > +  DEBUG ((
> > > >
> > > > +      DEBUG_INFO, "<<********** RecordPciRootPortBridges -start
> > > > *************>>\n"
> > > >
> > > > +  ));
> > > >
> > > > +  NumberOfRootPorts = 0;
> > > >
> > > > +  PrimaryRootPorts = NULL;
> > > >
> > > > +  for ( Link = RootBridge->ChildList.ForwardLink
> > > >
> > > > +      ; Link != &RootBridge->ChildList
> > > >
> > > > +      ; Link = Link->ForwardLink
> > > >
> > > > +  ) {
> > > >
> > > > +    Device = PCI_IO_DEVICE_FROM_LINK (Link);
> > > >
> > > > +    if (IS_PCI_BRIDGE (&Device->Pci)) {
> > > >
> > > > +      Status = GetPciRootPortBusAssigned (
> > > >
> > > > +                  Device,
> > > >
> > > > +                  NULL,
> > > >
> > > > +                  &RootPortSecBus,
> > > >
> > > > +                  &RootPortSubBus
> > > >
> > > > +                  );
> > > >
> > > > +      if ( !EFI_ERROR(Status)) {
> > > >
> > > > +        DEBUG ((
> > > >
> > > > +            DEBUG_INFO, "::Device [%02x|%02x|%02x] - SecBus=0x%x,
> > > > SubBus=0x%x\n",
> > > >
> > > > +            Device->BusNumber, Device->DeviceNumber, Device-
> > > > >FunctionNumber,
> > > >
> > > > +            RootPortSecBus, RootPortSubBus
> > > >
> > > > +        ));
> > > >
> > > > +      } else {
> > > >
> > > > +        DEBUG ((
> > > >
> > > > +            DEBUG_ERROR, "Unexpected read error [0x%lx]::Device
> > > > [%02x|%02x|%02x]\n",
> > > >
> > > > +            Status, Device->BusNumber, Device->DeviceNumber, Device-
> > > > >FunctionNumber
> > > >
> > > > +        ));
> > > >
> > > > +        RootPortSecBus = RootPortSubBus = 0;
> > > >
> > > > +        continue;
> > > >
> > > > +      }
> > > >
> > > > +
> > > >
> > > > +      if ( !PrimaryRootPorts) {
> > > >
> > > > +        NumberOfRootPorts++;
> > > >
> > > > +        Status = CreatePrimaryPciRootPortNode (
> > > >
> > > > +                    RootBridge,
> > > >
> > > > +                    Device,
> > > >
> > > > +                    RootPortSecBus,
> > > >
> > > > +                    RootPortSubBus,
> > > >
> > > > +                    &PrimaryRootPorts
> > > >
> > > > +                    );
> > > >
> > > > +        if ( EFI_ERROR(Status)) {
> > > >
> > > > +          //
> > > >
> > > > +          // abort mission to scan for all primary roots ports of a bridge
> > > >
> > > > +          // controller if error encountered for very first PCI primary root
> port
> > > >
> > > > +          //
> > > >
> > > > +          DEBUG ((
> > > >
> > > > +              DEBUG_ERROR, "Unexpected node creation error
> [0x%lx]::Device
> > > > [%02x|%02x|%02x]\n",
> > > >
> > > > +              Status, Device->BusNumber, Device->DeviceNumber, Device-
> > > > >FunctionNumber
> > > >
> > > > +          ));
> > > >
> > > > +          return Status;
> > > >
> > > > +        }
> > > >
> > > > +        DEBUG ((
> > > >
> > > > +            DEBUG_INFO, "first primary root port found::Device
> > > > [%02x|%02x|%02x]\n",
> > > >
> > > > +            Device->BusNumber, Device->DeviceNumber, Device-
> > > > >FunctionNumber
> > > >
> > > > +        ));
> > > >
> > > > +      } else {
> > > >
> > > > +        if ( !CheckChildRootPort ( PrimaryRootPorts, RootPortSecBus,
> > > > RootPortSubBus)) {
> > > >
> > > > +          NumberOfRootPorts++;
> > > >
> > > > +          TempNode = NULL;
> > > >
> > > > +          Status = CreatePrimaryPciRootPortNode (
> > > >
> > > > +                      RootBridge,
> > > >
> > > > +                      Device,
> > > >
> > > > +                      RootPortSecBus,
> > > >
> > > > +                      RootPortSubBus,
> > > >
> > > > +                      &TempNode
> > > >
> > > > +                      );
> > > >
> > > > +          if ( !EFI_ERROR(Status)) {
> > > >
> > > > +            //
> > > >
> > > > +            // another primary root port found on the same bridge
> controller
> > > >
> > > > +            // insert in the node list
> > > >
> > > > +            //
> > > >
> > > > +            InsertTailList ( &PrimaryRootPorts->NeighborRootPort,
> > > &TempNode-
> > > > >NeighborRootPort);
> > > >
> > > > +            DEBUG ((
> > > >
> > > > +                DEBUG_INFO, "next primary root port found::Device
> > > > [%02x|%02x|%02x]\n",
> > > >
> > > > +                Device->BusNumber, Device->DeviceNumber, Device-
> > > > >FunctionNumber
> > > >
> > > > +            ));
> > > >
> > > > +          } else {
> > > >
> > > > +            DEBUG ((
> > > >
> > > > +                DEBUG_ERROR, "Unexpected node creation error
> [0x%lx]::Device
> > > > [%02x|%02x|%02x]\n",
> > > >
> > > > +                Status, Device->BusNumber, Device->DeviceNumber, Device-
> > > > >FunctionNumber
> > > >
> > > > +            ));
> > > >
> > > > +          }
> > > >
> > > > +        }
> > > >
> > > > +      }
> > > >
> > > > +    }
> > > >
> > > > +  }
> > > >
> > > > +  //
> > > >
> > > > +  // prepare the PCI root port and its feature configuration table list
> > > >
> > > > +  //
> > > >
> > > > +  if ( NumberOfRootPorts) {
> > > >
> > > > +    Status = PreparePciControllerConfigurationTable (
> > > >
> > > > +                PrimaryRootPorts,
> > > >
> > > > +                NumberOfRootPorts
> > > >
> > > > +              );
> > > >
> > > > +
> > > >
> > > > +  } else {
> > > >
> > > > +    DEBUG ((
> > > >
> > > > +        DEBUG_INFO, "No PCI Root port found on this bridge!\n"
> > > >
> > > > +    ));
> > > >
> > > > +  }
> > > >
> > > > +
> > > >
> > > > +  DEBUG ((
> > > >
> > > > +      DEBUG_INFO, "<<********** RecordPciRootPortBridges - end
> > > > **********>>\n"
> > > >
> > > > +  ));
> > > >
> > > > +  return Status;
> > > >
> > > > +}
> > > >
> > > > +
> > > >
> > > > +/**
> > > >
> > > > +  Enumerate all the nodes of the specified root bridge or PCI-PCI
> Bridge, to
> > > >
> > > > +  configure the other PCI features.
> > > >
> > > > +
> > > >
> > > > +  @param RootBridge          A pointer to the PCI_IO_DEVICE.
> > > >
> > > > +
> > > >
> > > > +  @retval EFI_SUCCESS           The other PCI features configuration
> during
> > > > enumeration
> > > >
> > > > +                                of all the nodes of the PCI root bridge instance were
> > > >
> > > > +                                programmed in PCI-compliance pattern along with the
> > > >
> > > > +                                device-specific policy, as applicable.
> > > >
> > > > +  @retval EFI_UNSUPPORTED       One of the override operation maong
> the
> > > > nodes of
> > > >
> > > > +                                the PCI hierarchy resulted in a incompatible address
> > > >
> > > > +                                range.
> > > >
> > > > +  @retval EFI_INVALID_PARAMETER The override operation is
> performed
> > > > with invalid input
> > > >
> > > > +                                parameters.
> > > >
> > > > +**/
> > > >
> > > > +EFI_STATUS
> > > >
> > > > +EnumerateOtherPciFeatures (
> > > >
> > > > +  IN PCI_IO_DEVICE          *RootBridge
> > > >
> > > > +  )
> > > >
> > > > +{
> > > >
> > > > +  EFI_STATUS            Status;
> > > >
> > > > +  CHAR16                *Str;
> > > >
> > > > +  UINTN                 OtherPciFeatureConfigPhase;
> > > >
> > > > +
> > > >
> > > > +  //
> > > >
> > > > +  // check on PCI features configuration is complete and re-
> enumeration is
> > > > required
> > > >
> > > > +  //
> > > >
> > > > +  if ( !CheckPciFeaturesConfigurationRequired ( RootBridge)) {
> > > >
> > > > +    return EFI_ALREADY_STARTED;
> > > >
> > > > +  }
> > > >
> > > > +
> > > >
> > > > +  Str = ConvertDevicePathToText (
> > > >
> > > > +          DevicePathFromHandle (RootBridge->Handle),
> > > >
> > > > +          FALSE,
> > > >
> > > > +          FALSE
> > > >
> > > > +        );
> > > >
> > > > +  DEBUG ((DEBUG_INFO, "Enumerating PCI features for Root
> Bridge %s\n",
> > > > Str != NULL ? Str : L""));
> > > >
> > > > +
> > > >
> > > > +  for ( OtherPciFeatureConfigPhase = PciFeatureRootBridgeScan
> > > >
> > > > +      ; OtherPciFeatureConfigPhase <=
> PciFeatureConfigurationComplete
> > > >
> > > > +      ; OtherPciFeatureConfigPhase++
> > > >
> > > > +      ) {
> > > >
> > > > +    switch ( OtherPciFeatureConfigPhase){
> > > >
> > > > +      case  PciFeatureRootBridgeScan:
> > > >
> > > > +        SetupPciFeaturesConfigurationDefaults ();
> > > >
> > > > +        //
> > > >
> > > > +        //first scan the entire root bridge heirarchy for the primary PCI
> root
> > > > ports
> > > >
> > > > +        //
> > > >
> > > > +        RecordPciRootPortBridges ( RootBridge);
> > > >
> > > > +        break;
> > > >
> > > > +
> > > >
> > > > +      case  PciFeatureGetDevicePolicy:
> > > >
> > > > +      case  PciFeatureSetupPhase:
> > > >
> > > > +        DEBUG ((
> > > >
> > > > +            DEBUG_INFO, "<<********** SetupPciFeatures - start
> > > > **********>>\n"
> > > >
> > > > +        ));
> > > >
> > > > +        //
> > > >
> > > > +        // enumerate the other PCI features
> > > >
> > > > +        //
> > > >
> > > > +        Status = SetupPciFeatures ( RootBridge,
> OtherPciFeatureConfigPhase);
> > > >
> > > > +
> > > >
> > > > +        DEBUG ((
> > > >
> > > > +            DEBUG_INFO, "<<********** SetupPciFeatures - end
> > > > **********>>\n"
> > > >
> > > > +        ));
> > > >
> > > > +        break;
> > > >
> > > > +
> > > >
> > > > +      case  PciFeatureConfigurationPhase:
> > > >
> > > > +        //
> > > >
> > > > +        // override the PCI features as per enumeration phase
> > > >
> > > > +        //
> > > >
> > > > +        DEBUG ((DEBUG_INFO, "PCI features override for Root
> Bridge %s\n",
> > > > Str != NULL ? Str : L""));
> > > >
> > > > +        DEBUG ((
> > > >
> > > > +            DEBUG_INFO, "<<********** ProgramPciFeatures - start
> > > > **********>>\n"
> > > >
> > > > +        ));
> > > >
> > > > +        Status = ProgramPciFeatures ( RootBridge);
> > > >
> > > > +        DEBUG ((
> > > >
> > > > +            DEBUG_INFO, "<<********** ProgramPciFeatures - end
> > > > **********>>\n"
> > > >
> > > > +        ));
> > > >
> > > > +        break;
> > > >
> > > > +
> > > >
> > > > +      case  PciFeatureConfigurationComplete:
> > > >
> > > > +        //
> > > >
> > > > +        // clean up the temporary resource nodes created for this root
> bridge
> > > >
> > > > +        //
> > > >
> > > > +        DestroyPrimaryRootPortNodes ();
> > > >
> > > > +
> > > >
> > > > +        ErasePciFeaturesConfigurationTable ();
> > > >
> > > > +    }
> > > >
> > > > +  }
> > > >
> > > > +
> > > >
> > > > +  if (Str != NULL) {
> > > >
> > > > +    FreePool (Str);
> > > >
> > > > +  }
> > > >
> > > > +  //
> > > >
> > > > +  // mark this root bridge as PCI features configuration complete, and
> no
> > > > new
> > > >
> > > > +  // enumeration is required
> > > >
> > > > +  //
> > > >
> > > > +  AddRootBridgeInPciFeaturesConfigCompletionList ( RootBridge,
> FALSE);
> > > >
> > > > +  return Status;
> > > >
> > > > +}
> > > >
> > > > +
> > > >
> > > > +/**
> > > >
> > > > +  This routine is invoked from the Stop () interface for the EFI handle of
> > > the
> > > >
> > > > +  RootBridge. Free up its node of type
> > > > PCI_FEATURE_CONFIGURATION_COMPLETION_LIST.
> > > >
> > > > +
> > > >
> > > > +  @param  RootBridge      A pointer to the PCI_IO_DEVICE
> > > >
> > > > +**/
> > > >
> > > > +VOID
> > > >
> > > > +DestroyRootBridgePciFeaturesConfigCompletionList (
> > > >
> > > > +  IN PCI_IO_DEVICE          *RootBridge
> > > >
> > > > +  )
> > > >
> > > > +{
> > > >
> > > > +  LIST_ENTRY                                  *Link;
> > > >
> > > > +  PCI_FEATURE_CONFIGURATION_COMPLETION_LIST   *Temp;
> > > >
> > > > +
> > > >
> > > > +  if ( mPciFeaturesConfigurationCompletionList) {
> > > >
> > > > +    Link = &mPciFeaturesConfigurationCompletionList->RootBridgeLink;
> > > >
> > > > +
> > > >
> > > > +    do {
> > > >
> > > > +      Temp =
> > > > PCI_FEATURE_CONFIGURATION_COMPLETION_LIST_FROM_LINK
> (Link);
> > > >
> > > > +      if ( Temp->RootBridgeHandle == RootBridge->Handle) {
> > > >
> > > > +        RemoveEntryList ( Link);
> > > >
> > > > +        FreePool ( Temp);
> > > >
> > > > +        return;
> > > >
> > > > +      }
> > > >
> > > > +      Link = Link->ForwardLink;
> > > >
> > > > +    } while (Link != &mPciFeaturesConfigurationCompletionList-
> > > > >RootBridgeLink);
> > > >
> > > > +  }
> > > >
> > > > +  //
> > > >
> > > > +  // not found on the PCI feature configuration completion list, return
> > > >
> > > > +  //
> > > >
> > > > +  return;
> > > >
> > > > +}
> > > >
> > > > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> > > > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> > > > new file mode 100644
> > > > index 0000000000..9f225fa993
> > > > --- /dev/null
> > > > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> > > > @@ -0,0 +1,201 @@
> > > > +/** @file
> > > >
> > > > +  PCI standard feature support functions implementation for PCI Bus
> > > > module..
> > > >
> > > > +
> > > >
> > > > +Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> > > >
> > > > +SPDX-License-Identifier: BSD-2-Clause-Patent
> > > >
> > > > +
> > > >
> > > > +**/
> > > >
> > > > +
> > > >
> > > > +#ifndef _EFI_PCI_FEATURES_SUPPORT_H_
> > > >
> > > > +#define _EFI_PCI_FEATURES_SUPPORT_H_
> > > >
> > > > +
> > > >
> > > > +#include "PciBus.h"
> > > >
> > > > +#include "PciPlatformSupport.h"
> > > >
> > > > +
> > > >
> > > > +//
> > > >
> > > > +// Macro definitions for the PCI Features support PCD
> > > >
> > > > +//
> > > >
> > > > +#define PCI_FEATURE_SUPPORT_FLAG_MPS  BIT0
> > > >
> > > > +#define PCI_FEATURE_SUPPORT_FLAG_MRRS BIT1
> > > >
> > > > +
> > > >
> > > > +//
> > > >
> > > > +// defines the data structure to hold the details of the PCI Root port
> > > devices
> > > >
> > > > +//
> > > >
> > > > +typedef struct _PRIMARY_ROOT_PORT_NODE
> > > > PRIMARY_ROOT_PORT_NODE;
> > > >
> > > > +
> > > >
> > > > +//
> > > >
> > > > +// defines the data structure to hold the configuration data for the
> other
> > > > PCI
> > > >
> > > > +// features
> > > >
> > > > +//
> > > >
> > > > +typedef struct _OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > > > OTHER_PCI_FEATURES_CONFIGURATION_TABLE;
> > > >
> > > > +
> > > >
> > > > +//
> > > >
> > > > +// Defines for the PCI features configuration completion and re-
> > > > enumeration list
> > > >
> > > > +//
> > > >
> > > > +typedef struct _PCI_FEATURE_CONFIGURATION_COMPLETION_LIST
> > > > PCI_FEATURE_CONFIGURATION_COMPLETION_LIST;
> > > >
> > > > +
> > > >
> > > > +//
> > > >
> > > > +// Signature value for the PCI Root Port node
> > > >
> > > > +//
> > > >
> > > > +#define PCI_ROOT_PORT_SIGNATURE               SIGNATURE_32 ('p', 'c',
> 'i',
> > > 'p')
> > > >
> > > > +
> > > >
> > > > +//
> > > >
> > > > +// Definitions of the PCI Root Port data structure members
> > > >
> > > > +//
> > > >
> > > > +struct _PRIMARY_ROOT_PORT_NODE {
> > > >
> > > > +  //
> > > >
> > > > +  // Signature header
> > > >
> > > > +  //
> > > >
> > > > +  UINT32                                    Signature;
> > > >
> > > > +  //
> > > >
> > > > +  // linked list pointers to next node
> > > >
> > > > +  //
> > > >
> > > > +  LIST_ENTRY                                NeighborRootPort;
> > > >
> > > > +  //
> > > >
> > > > +  // EFI handle of the parent Root Bridge instance
> > > >
> > > > +  //
> > > >
> > > > +  EFI_HANDLE                                RootBridgeHandle;
> > > >
> > > > +  //
> > > >
> > > > +  // EFI handle of the PCI controller
> > > >
> > > > +  //
> > > >
> > > > +  EFI_HANDLE                                RootPortHandle;
> > > >
> > > > +  //
> > > >
> > > > +  // PCI Secondary bus value of the PCI controller
> > > >
> > > > +  //
> > > >
> > > > +  UINT8                                     SecondaryBusStart;
> > > >
> > > > +  //
> > > >
> > > > +  // PCI Subordinate bus value of the PCI controller
> > > >
> > > > +  //
> > > >
> > > > +  UINT8                                     SecondaryBusEnd;
> > > >
> > > > +  //
> > > >
> > > > +  // pointer to the corresponding PCI feature configuration Table node
> > > >
> > > > +  //
> > > >
> > > > +  OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > > > *OtherPciFeaturesConfigurationTable;
> > > >
> > > > +};
> > > >
> > > > +
> > > >
> > > > +#define PRIMARY_ROOT_PORT_NODE_FROM_LINK(a) \
> > > >
> > > > +  CR (a, PRIMARY_ROOT_PORT_NODE, NeighborRootPort,
> > > > PCI_ROOT_PORT_SIGNATURE)
> > > >
> > > > +
> > > >
> > > > +//
> > > >
> > > > +// Definition of the PCI Feature configuration Table members
> > > >
> > > > +//
> > > >
> > > > +struct _OTHER_PCI_FEATURES_CONFIGURATION_TABLE {
> > > >
> > > > +  //
> > > >
> > > > +  // Configuration Table ID
> > > >
> > > > +  //
> > > >
> > > > +  UINTN                                     ID;
> > > >
> > > > +  //
> > > >
> > > > +  // to configure the PCI feature Maximum payload size to maintain the
> > > data
> > > > packet
> > > >
> > > > +  // size among all the PCI devices in the PCI hierarchy
> > > >
> > > > +  //
> > > >
> > > > +  UINT8                                     Max_Payload_Size;
> > > >
> > > > +  //
> > > >
> > > > +  // to configure the PCI feature maximum read request size to
> maintain
> > > the
> > > > memory
> > > >
> > > > +  // requester size among all the PCI devices in the PCI hierarchy
> > > >
> > > > +  //
> > > >
> > > > +  UINT8                                     Max_Read_Request_Size;
> > > >
> > > > +  //
> > > >
> > > > +  // lock the Max_Read_Request_Size for the entire PCI tree of a root
> port
> > > >
> > > > +  //
> > > >
> > > > +  BOOLEAN                                   Lock_Max_Read_Request_Size;
> > > >
> > > > +};
> > > >
> > > > +
> > > >
> > > > +
> > > >
> > > > +//
> > > >
> > > > +// PCI feature configuration node signature value
> > > >
> > > > +//
> > > >
> > > > +#define PCI_FEATURE_CONFIGURATION_SIGNATURE
> > > > SIGNATURE_32 ('p', 'c', 'i', 'f')
> > > >
> > > > +
> > > >
> > > > +struct _PCI_FEATURE_CONFIGURATION_COMPLETION_LIST {
> > > >
> > > > +  //
> > > >
> > > > +  // Signature header
> > > >
> > > > +  //
> > > >
> > > > +  UINT32                                    Signature;
> > > >
> > > > +  //
> > > >
> > > > +  // link to next Root Bridge whose PCI Feature configuration is
> complete
> > > >
> > > > +  //
> > > >
> > > > +  LIST_ENTRY                                RootBridgeLink;
> > > >
> > > > +  //
> > > >
> > > > +  // EFI handle of the Root Bridge whose PCI feature configuration is
> > > > complete
> > > >
> > > > +  //
> > > >
> > > > +  EFI_HANDLE                                RootBridgeHandle;
> > > >
> > > > +  //
> > > >
> > > > +  // indication for complete re-enumeration of the PCI feature
> > > configuration
> > > >
> > > > +  //
> > > >
> > > > +  BOOLEAN                                   ReEnumeratePciFeatureConfiguration;
> > > >
> > > > +};
> > > >
> > > > +
> > > >
> > > > +#define
> > > > PCI_FEATURE_CONFIGURATION_COMPLETION_LIST_FROM_LINK(a) \
> > > >
> > > > +  CR (a, PCI_FEATURE_CONFIGURATION_COMPLETION_LIST,
> > > > RootBridgeLink, PCI_FEATURE_CONFIGURATION_SIGNATURE)
> > > >
> > > > +
> > > >
> > > > +//
> > > >
> > > > +// Declaration of the internal sub-phases within the PCI Feature
> > > > enumeration
> > > >
> > > > +//
> > > >
> > > > +typedef enum {
> > > >
> > > > +  //
> > > >
> > > > +  // initial phase in configuring the other PCI features to record the
> primary
> > > >
> > > > +  // root ports
> > > >
> > > > +  //
> > > >
> > > > +  PciFeatureRootBridgeScan,
> > > >
> > > > +  //
> > > >
> > > > +  // get the PCI device-specific platform policies and align with device
> > > > capabilities
> > > >
> > > > +  //
> > > >
> > > > +  PciFeatureGetDevicePolicy,
> > > >
> > > > +  //
> > > >
> > > > +  // align all PCI nodes in the PCI heirarchical tree
> > > >
> > > > +  //
> > > >
> > > > +  PciFeatureSetupPhase,
> > > >
> > > > +  //
> > > >
> > > > +  // finally override to complete configuration of the PCI feature
> > > >
> > > > +  //
> > > >
> > > > +  PciFeatureConfigurationPhase,
> > > >
> > > > +  //
> > > >
> > > > +  // PCI feature configuration complete
> > > >
> > > > +  //
> > > >
> > > > +  PciFeatureConfigurationComplete
> > > >
> > > > +
> > > >
> > > > +}PCI_FEATURE_CONFIGURATION_PHASE;
> > > >
> > > > +
> > > >
> > > > +/**
> > > >
> > > > +  Main routine to indicate platform selection of any of the other PCI
> > > features
> > > >
> > > > +  to be configured by this driver
> > > >
> > > > +
> > > >
> > > > +  @retval TRUE    platform has selected the other PCI features to be
> > > > configured
> > > >
> > > > +          FALSE   platform has not selected any of the other PCI features
> > > >
> > > > +**/
> > > >
> > > > +BOOLEAN
> > > >
> > > > +CheckOtherPciFeaturesPcd (
> > > >
> > > > +  );
> > > >
> > > > +
> > > >
> > > > +/**
> > > >
> > > > +  Enumerate all the nodes of the specified root bridge or PCI-PCI
> Bridge, to
> > > >
> > > > +  configure the other PCI features.
> > > >
> > > > +
> > > >
> > > > +  @param RootBridge          A pointer to the PCI_IO_DEVICE.
> > > >
> > > > +
> > > >
> > > > +  @retval EFI_SUCCESS           The other PCI features configuration
> during
> > > > enumeration
> > > >
> > > > +                                of all the nodes of the PCI root bridge instance were
> > > >
> > > > +                                programmed in PCI-compliance pattern along with the
> > > >
> > > > +                                device-specific policy, as applicable.
> > > >
> > > > +  @retval EFI_UNSUPPORTED       One of the override operation maong
> the
> > > > nodes of
> > > >
> > > > +                                the PCI hierarchy resulted in a incompatible address
> > > >
> > > > +                                range.
> > > >
> > > > +  @retval EFI_INVALID_PARAMETER The override operation is
> performed
> > > > with invalid input
> > > >
> > > > +                                parameters.
> > > >
> > > > +**/
> > > >
> > > > +EFI_STATUS
> > > >
> > > > +EnumerateOtherPciFeatures (
> > > >
> > > > +  IN PCI_IO_DEVICE           *RootBridge
> > > >
> > > > +  );
> > > >
> > > > +
> > > >
> > > > +/**
> > > >
> > > > +  This routine is invoked from the Stop () interface for the EFI handle of
> > > the
> > > >
> > > > +  RootBridge. Free up its node of type
> > > > PCI_FEATURE_CONFIGURATION_COMPLETION_LIST.
> > > >
> > > > +
> > > >
> > > > +  @param  RootBridge      A pointer to the PCI_IO_DEVICE
> > > >
> > > > +**/
> > > >
> > > > +VOID
> > > >
> > > > +DestroyRootBridgePciFeaturesConfigCompletionList (
> > > >
> > > > +  IN PCI_IO_DEVICE          *RootBridge
> > > >
> > > > +  );
> > > >
> > > > +#endif
> > > >
> > > > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> > > > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> > > > new file mode 100644
> > > > index 0000000000..d94037d69a
> > > > --- /dev/null
> > > > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> > > > @@ -0,0 +1,565 @@
> > > > +/** @file
> > > >
> > > > +  This file encapsulate the usage of PCI Platform Protocol
> > > >
> > > > +
> > > >
> > > > +  This file define the necessary hooks used to obtain the platform
> > > >
> > > > +  level data and policies which could be used in the PCI Enumeration
> > > phases
> > > >
> > > > +
> > > >
> > > > +Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> > > >
> > > > +SPDX-License-Identifier: BSD-2-Clause-Patent
> > > >
> > > > +
> > > >
> > > > +**/
> > > >
> > > > +
> > > >
> > > > +#include "PciPlatformSupport.h"
> > > >
> > > > +
> > > >
> > > > +EFI_PCI_PLATFORM_PROTOCOL                     *mPciPlatformProtocol;
> > > >
> > > > +EFI_PCI_OVERRIDE_PROTOCOL                     *mPciOverrideProtocol;
> > > >
> > > > +
> > > >
> > > > +EFI_PCI_PLATFORM_PROTOCOL2                    *mPciPlatformProtocol2;
> > > >
> > > > +EFI_PCI_OVERRIDE_PROTOCOL2                    *mPciOverrideProtocol2;
> > > >
> > > > +
> > > >
> > > > +
> > > >
> > > > +/**
> > > >
> > > > +  This function retrieves the PCI Platform Protocol published by
> platform
> > > > driver
> > > >
> > > > +
> > > >
> > > > +**/
> > > >
> > > > +VOID
> > > >
> > > > +GetPciPlatformProtocol (
> > > >
> > > > +  )
> > > >
> > > > +{
> > > >
> > > > +  mPciPlatformProtocol2 = NULL;
> > > >
> > > > +  gBS->LocateProtocol (
> > > >
> > > > +      &gEfiPciPlatformProtocol2Guid,
> > > >
> > > > +      NULL,
> > > >
> > > > +      (VOID **) &mPciPlatformProtocol2
> > > >
> > > > +  );
> > > >
> > > > +
> > > >
> > > > +  //
> > > >
> > > > +  // If PCI Platform protocol doesn't exist, try to get Pci Override
> Protocol.
> > > >
> > > > +  //
> > > >
> > > > +  if (mPciPlatformProtocol2 == NULL) {
> > > >
> > > > +    mPciOverrideProtocol2 = NULL;
> > > >
> > > > +    gBS->LocateProtocol (
> > > >
> > > > +        &gEfiPciOverrideProtocol2Guid,
> > > >
> > > > +        NULL,
> > > >
> > > > +        (VOID **) &mPciOverrideProtocol2
> > > >
> > > > +    );
> > > >
> > > > +  }
> > > >
> > > > +  //
> > > >
> > > > +  // fetch the old PCI Platform Protocols if new are not installed
> > > >
> > > > +  //
> > > >
> > > > +  if (mPciOverrideProtocol2 == NULL) {
> > > >
> > > > +
> > > >
> > > > +    mPciPlatformProtocol = NULL;
> > > >
> > > > +    gBS->LocateProtocol (
> > > >
> > > > +        &gEfiPciPlatformProtocolGuid,
> > > >
> > > > +        NULL,
> > > >
> > > > +        (VOID **) &mPciPlatformProtocol
> > > >
> > > > +    );
> > > >
> > > > +
> > > >
> > > > +    //
> > > >
> > > > +    // If PCI Platform protocol doesn't exist, try to  get Pci Override
> Protocol.
> > > >
> > > > +    //
> > > >
> > > > +    if (mPciPlatformProtocol == NULL) {
> > > >
> > > > +      mPciOverrideProtocol = NULL;
> > > >
> > > > +      gBS->LocateProtocol (
> > > >
> > > > +          &gEfiPciOverrideProtocolGuid,
> > > >
> > > > +          NULL,
> > > >
> > > > +          (VOID **) &mPciOverrideProtocol
> > > >
> > > > +      );
> > > >
> > > > +    }
> > > >
> > > > +  }
> > > >
> > > > +}
> > > >
> > > > +
> > > >
> > > > +/**
> > > >
> > > > +  This function indicates the presence of PCI Platform driver
> > > >
> > > > +  @retval     TRUE or FALSE
> > > >
> > > > +**/
> > > >
> > > > +BOOLEAN
> > > >
> > > > +CheckPciPlatformProtocolInstall (
> > > >
> > > > +  )
> > > >
> > > > +{
> > > >
> > > > +  if (mPciPlatformProtocol2 != NULL) {
> > > >
> > > > +    return TRUE;
> > > >
> > > > +  } else if (mPciOverrideProtocol2 != NULL) {
> > > >
> > > > +    return TRUE;
> > > >
> > > > +  } else {
> > > >
> > > > +    if (mPciPlatformProtocol != NULL) {
> > > >
> > > > +      return TRUE;
> > > >
> > > > +    } else if (mPciOverrideProtocol != NULL){
> > > >
> > > > +      return TRUE;
> > > >
> > > > +    }
> > > >
> > > > +  }
> > > >
> > > > +  return FALSE;
> > > >
> > > > +}
> > > >
> > > > +
> > > >
> > > > +/**
> > > >
> > > > +  Provides the hooks from the PCI bus driver to every PCI controller
> > > > (device/function) at various
> > > >
> > > > +  stages of the PCI enumeration process that allow the host bridge
> driver
> > > to
> > > > preinitialize individual
> > > >
> > > > +  PCI controllers before enumeration.
> > > >
> > > > +
> > > >
> > > > +  This function is called during the PCI enumeration process. No specific
> > > > action is expected from this
> > > >
> > > > +  member function. It allows the host bridge driver to preinitialize
> > > individual
> > > > PCI controllers before
> > > >
> > > > +  enumeration.
> > > >
> > > > +
> > > >
> > > > +  @param[in] HostBridgeHandle     The associated PCI host bridge
> handle.
> > > >
> > > > +  @param[in] RootBridgeHandle     The associated PCI root bridge
> handle.
> > > >
> > > > +  @param[in] RootBridgePciAddress The address of the PCI device on
> the
> > > > PCI bus.
> > > >
> > > > +  @param[in] Phase          The phase of the PCI controller enumeration.
> > > >
> > > > +  @param[in] ExecPhase      Defines the execution phase of the PCI
> chipset
> > > > driver.
> > > >
> > > > +
> > > >
> > > > +  @retval    Status         returns the status from the PCI Platform
> protocol as
> > > is
> > > >
> > > > +
> > > >
> > > > +**/
> > > >
> > > > +EFI_STATUS
> > > >
> > > > +PciPlatformPreprocessController (
> > > >
> > > > +  IN EFI_HANDLE                                    HostBridgeHandle,
> > > >
> > > > +  IN EFI_HANDLE                                    RootBridgeHandle,
> > > >
> > > > +  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS
> > > > RootBridgePciAddress,
> > > >
> > > > +  IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE  Phase,
> > > >
> > > > +  IN EFI_PCI_EXECUTION_PHASE                       ExecPhase
> > > >
> > > > +  )
> > > >
> > > > +{
> > > >
> > > > +  EFI_STATUS  Status;
> > > >
> > > > +
> > > >
> > > > +  if (mPciPlatformProtocol2 != NULL) {
> > > >
> > > > +    //
> > > >
> > > > +    // Call PlatformPci::PrepController() if the protocol is present.
> > > >
> > > > +    //
> > > >
> > > > +    Status = mPciPlatformProtocol2->PlatformPrepController (
> > > >
> > > > +
> > > > (EFI_PCI_PLATFORM_PROTOCOL*)mPciPlatformProtocol2,
> > > >
> > > > +                                      HostBridgeHandle,
> > > >
> > > > +                                      RootBridgeHandle,
> > > >
> > > > +                                      RootBridgePciAddress,
> > > >
> > > > +                                      Phase,
> > > >
> > > > +                                      ExecPhase
> > > >
> > > > +                                    );
> > > >
> > > > +  } else if (mPciOverrideProtocol2 != NULL) {
> > > >
> > > > +    //
> > > >
> > > > +    // Call PlatformPci::PrepController() if the protocol is present.
> > > >
> > > > +    //
> > > >
> > > > +    Status = mPciOverrideProtocol2->PlatformPrepController (
> > > >
> > > > +
> > > > (EFI_PCI_PLATFORM_PROTOCOL*)mPciOverrideProtocol2,
> > > >
> > > > +                                      HostBridgeHandle,
> > > >
> > > > +                                      RootBridgeHandle,
> > > >
> > > > +                                      RootBridgePciAddress,
> > > >
> > > > +                                      Phase,
> > > >
> > > > +                                      ExecPhase
> > > >
> > > > +                                    );
> > > >
> > > > +  } else {
> > > >
> > > > +    if (mPciPlatformProtocol != NULL) {
> > > >
> > > > +      //
> > > >
> > > > +      // Call PlatformPci::PrepController() if the protocol is present.
> > > >
> > > > +      //
> > > >
> > > > +      Status = mPciPlatformProtocol->PlatformPrepController (
> > > >
> > > > +                                      mPciPlatformProtocol,
> > > >
> > > > +                                      HostBridgeHandle,
> > > >
> > > > +                                      RootBridgeHandle,
> > > >
> > > > +                                      RootBridgePciAddress,
> > > >
> > > > +                                      Phase,
> > > >
> > > > +                                      ExecPhase
> > > >
> > > > +                                    );
> > > >
> > > > +    } else if (mPciOverrideProtocol != NULL) {
> > > >
> > > > +      //
> > > >
> > > > +      // Call PlatformPci::PrepController() if the protocol is present.
> > > >
> > > > +      //
> > > >
> > > > +      Status = mPciOverrideProtocol->PlatformPrepController (
> > > >
> > > > +                                      mPciOverrideProtocol,
> > > >
> > > > +                                      HostBridgeHandle,
> > > >
> > > > +                                      RootBridgeHandle,
> > > >
> > > > +                                      RootBridgePciAddress,
> > > >
> > > > +                                      Phase,
> > > >
> > > > +                                      ExecPhase
> > > >
> > > > +                                    );
> > > >
> > > > +    } else {
> > > >
> > > > +      //
> > > >
> > > > +      // return PCI Platform Protocol not found
> > > >
> > > > +      //
> > > >
> > > > +      return EFI_NOT_FOUND;
> > > >
> > > > +    }
> > > >
> > > > +  }
> > > >
> > > > +  return Status;
> > > >
> > > > +}
> > > >
> > > > +
> > > >
> > > > +/**
> > > >
> > > > +  This function notifies the PCI Platform driver about the PCI host
> bridge
> > > > resource
> > > >
> > > > +  allocation phase and PCI execution phase.
> > > >
> > > > +
> > > >
> > > > +  @param[in]  HostBridge     The handle of the host bridge controller.
> > > >
> > > > +  @param[in]  Phase          The phase of the PCI bus enumeration.
> > > >
> > > > +  @param[in]  ExecPhase      Defines the execution phase of the PCI
> > > chipset
> > > > driver.
> > > >
> > > > +  @retval     Status          returns the status from the PCI Platform
> protocol
> > > as
> > > > is
> > > >
> > > > +
> > > >
> > > > +**/
> > > >
> > > > +EFI_STATUS
> > > >
> > > > +PciPlatformNotifyPhase (
> > > >
> > > > +  IN  EFI_HANDLE                                      HostBridgeHandle,
> > > >
> > > > +  IN  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE   Phase,
> > > >
> > > > +  IN  EFI_PCI_EXECUTION_PHASE                         ExecPhase
> > > >
> > > > +  )
> > > >
> > > > +{
> > > >
> > > > +  EFI_STATUS  Status;
> > > >
> > > > +
> > > >
> > > > +  if ( mPciPlatformProtocol2 != NULL) {
> > > >
> > > > +    Status = mPciPlatformProtocol2->PlatformNotify (
> > > >
> > > > +
> > > > (EFI_PCI_PLATFORM_PROTOCOL*)mPciPlatformProtocol2,
> > > >
> > > > +                                      HostBridgeHandle,
> > > >
> > > > +                                      Phase,
> > > >
> > > > +                                      ExecPhase
> > > >
> > > > +                                    );
> > > >
> > > > +  } else if ( mPciOverrideProtocol2 != NULL) {
> > > >
> > > > +    Status = mPciOverrideProtocol2->PlatformNotify (
> > > >
> > > > +
> > > > (EFI_PCI_PLATFORM_PROTOCOL*)mPciOverrideProtocol2,
> > > >
> > > > +                                      HostBridgeHandle,
> > > >
> > > > +                                      Phase,
> > > >
> > > > +                                      ExecPhase
> > > >
> > > > +                                    );
> > > >
> > > > +  } else {
> > > >
> > > > +
> > > >
> > > > +    if ( mPciPlatformProtocol != NULL) {
> > > >
> > > > +      Status = mPciPlatformProtocol->PlatformNotify (
> > > >
> > > > +                                      mPciPlatformProtocol,
> > > >
> > > > +                                      HostBridgeHandle,
> > > >
> > > > +                                      Phase,
> > > >
> > > > +                                      ExecPhase
> > > >
> > > > +                                    );
> > > >
> > > > +    } else if ( mPciOverrideProtocol != NULL){
> > > >
> > > > +      Status = mPciOverrideProtocol->PlatformNotify (
> > > >
> > > > +                                      mPciOverrideProtocol,
> > > >
> > > > +                                      HostBridgeHandle,
> > > >
> > > > +                                      Phase,
> > > >
> > > > +                                      ExecPhase
> > > >
> > > > +                                    );
> > > >
> > > > +    } else {
> > > >
> > > > +      //
> > > >
> > > > +      // return PCI Platform Protocol not found
> > > >
> > > > +      //
> > > >
> > > > +      return EFI_NOT_FOUND;
> > > >
> > > > +    }
> > > >
> > > > +  }
> > > >
> > > > +  return Status;
> > > >
> > > > +}
> > > >
> > > > +
> > > >
> > > > +/**
> > > >
> > > > +  This function retrieves the PCI platform policy.
> > > >
> > > > +
> > > >
> > > > +  @param  PciPolicy     pointer to the legacy
> EFI_PCI_PLATFORM_POLICY
> > > >
> > > > +  @retval Status        returns the status from the PCI Platform protocol
> as is
> > > >
> > > > +
> > > >
> > > > +**/
> > > >
> > > > +EFI_STATUS
> > > >
> > > > +PciGetPlatformPolicy (
> > > >
> > > > +  OUT EFI_PCI_PLATFORM_POLICY *PciPolicy
> > > >
> > > > +  )
> > > >
> > > > +{
> > > >
> > > > +  EFI_STATUS  Status;
> > > >
> > > > +
> > > >
> > > > +  if ( mPciPlatformProtocol2 != NULL) {
> > > >
> > > > +      Status = mPciPlatformProtocol2->GetPlatformPolicy (
> > > >
> > > > +
> > > > (EFI_PCI_PLATFORM_PROTOCOL*)mPciPlatformProtocol2,
> > > >
> > > > +                                        PciPolicy
> > > >
> > > > +                                      );
> > > >
> > > > +  } else if ( mPciOverrideProtocol2 != NULL) {
> > > >
> > > > +      Status = mPciOverrideProtocol2->GetPlatformPolicy (
> > > >
> > > > +
> > > > (EFI_PCI_PLATFORM_PROTOCOL*)mPciOverrideProtocol2,
> > > >
> > > > +                                        PciPolicy
> > > >
> > > > +                                      );
> > > >
> > > > +  } else {
> > > >
> > > > +    if ( mPciPlatformProtocol != NULL) {
> > > >
> > > > +      Status = mPciPlatformProtocol->GetPlatformPolicy (
> > > >
> > > > +                                      mPciPlatformProtocol,
> > > >
> > > > +                                      PciPolicy
> > > >
> > > > +                                    );
> > > >
> > > > +    }
> > > >
> > > > +
> > > >
> > > > +    if ( mPciOverrideProtocol != NULL) {
> > > >
> > > > +      Status = mPciOverrideProtocol->GetPlatformPolicy (
> > > >
> > > > +                                      mPciOverrideProtocol,
> > > >
> > > > +                                      PciPolicy
> > > >
> > > > +                                    );
> > > >
> > > > +    } else {
> > > >
> > > > +      //
> > > >
> > > > +      // return PCI Platform Protocol not found
> > > >
> > > > +      //
> > > >
> > > > +      return EFI_NOT_FOUND;
> > > >
> > > > +    }
> > > >
> > > > +  }
> > > >
> > > > +  return Status;
> > > >
> > > > +}
> > > >
> > > > +
> > > >
> > > > +/**
> > > >
> > > > +  This function retrieves the Option ROM image and size from the
> Platform.
> > > >
> > > > +
> > > >
> > > > +  It uses the PCI_IO_DEVICE internal fields are used to store OpROM
> > > > image/size
> > > >
> > > > +
> > > >
> > > > +  @param Controller     An EFI handle for the PCI bus controller.
> > > >
> > > > +  @param PciIoDevice    A PCI_IO_DEVICE pointer to the PCI IO device
> to
> > > be
> > > > registered.
> > > >
> > > > +
> > > >
> > > > +  @retval EFI_SUCCESS            The option ROM was available for this
> device
> > > > and loaded into memory.
> > > >
> > > > +  @retval EFI_NOT_FOUND          No option ROM was available for this
> > > device.
> > > >
> > > > +  @retval EFI_OUT_OF_RESOURCES   No memory was available to load
> the
> > > > option ROM.
> > > >
> > > > +  @retval EFI_DEVICE_ERROR       An error occurred in obtaining the
> option
> > > > ROM.
> > > >
> > > > +
> > > >
> > > > +**/
> > > >
> > > > +EFI_STATUS
> > > >
> > > > +GetPlatformPciOptionRom (
> > > >
> > > > +  IN  EFI_HANDLE                    Controller,
> > > >
> > > > +  IN  PCI_IO_DEVICE                 *PciIoDevice
> > > >
> > > > +  )
> > > >
> > > > +{
> > > >
> > > > +  EFI_STATUS  Status;
> > > >
> > > > +  VOID        *PlatformOpRomBuffer;
> > > >
> > > > +  UINTN       PlatformOpRomSize;
> > > >
> > > > +
> > > >
> > > > +  if (mPciPlatformProtocol2 != NULL) {
> > > >
> > > > +    Status = mPciPlatformProtocol2->GetPciRom (
> > > >
> > > > +
> > > > (EFI_PCI_PLATFORM_PROTOCOL*)mPciPlatformProtocol2,
> > > >
> > > > +                                      PciIoDevice->Handle,
> > > >
> > > > +                                      &PlatformOpRomBuffer,
> > > >
> > > > +                                      &PlatformOpRomSize
> > > >
> > > > +                                      );
> > > >
> > > > +  } else if (mPciOverrideProtocol2 != NULL) {
> > > >
> > > > +    Status = mPciOverrideProtocol2->GetPciRom (
> > > >
> > > > +
> > > > (EFI_PCI_PLATFORM_PROTOCOL*)mPciOverrideProtocol2,
> > > >
> > > > +                                      PciIoDevice->Handle,
> > > >
> > > > +                                      &PlatformOpRomBuffer,
> > > >
> > > > +                                      &PlatformOpRomSize
> > > >
> > > > +                                      );
> > > >
> > > > +  } else {
> > > >
> > > > +    if (mPciPlatformProtocol != NULL) {
> > > >
> > > > +      Status = mPciPlatformProtocol->GetPciRom (
> > > >
> > > > +                                      mPciPlatformProtocol,
> > > >
> > > > +                                      PciIoDevice->Handle,
> > > >
> > > > +                                      &PlatformOpRomBuffer,
> > > >
> > > > +                                      &PlatformOpRomSize
> > > >
> > > > +                                      );
> > > >
> > > > +    } else if (mPciOverrideProtocol != NULL) {
> > > >
> > > > +      Status = mPciOverrideProtocol->GetPciRom (
> > > >
> > > > +                                        mPciOverrideProtocol,
> > > >
> > > > +                                        PciIoDevice->Handle,
> > > >
> > > > +                                        &PlatformOpRomBuffer,
> > > >
> > > > +                                        &PlatformOpRomSize
> > > >
> > > > +                                        );
> > > >
> > > > +    } else {
> > > >
> > > > +      //
> > > >
> > > > +      // return PCI Platform Protocol not found
> > > >
> > > > +      //
> > > >
> > > > +      return EFI_NOT_FOUND;
> > > >
> > > > +    }
> > > >
> > > > +  }
> > > >
> > > > +
> > > >
> > > > +  if (!EFI_ERROR (Status)) {
> > > >
> > > > +    PciIoDevice->EmbeddedRom    = FALSE;
> > > >
> > > > +    PciIoDevice->RomSize        = (UINT32)PlatformOpRomSize;
> > > >
> > > > +    PciIoDevice->PciIo.RomSize  = PlatformOpRomSize;
> > > >
> > > > +    PciIoDevice->PciIo.RomImage = PlatformOpRomBuffer;
> > > >
> > > > +  }
> > > >
> > > > +  return Status;
> > > >
> > > > +}
> > > >
> > > > +
> > > >
> > > > +/**
> > > >
> > > > +  Helper routine to indicate whether the given PCI device specific
> policy
> > > > value
> > > >
> > > > +  dictates to override the Max_Payload_Size to a particular value, or
> set as
> > > > per
> > > >
> > > > +  device capability.
> > > >
> > > > +
> > > >
> > > > +  @param  MPS     Input device-specific policy should be in terms of
> type
> > > >
> > > > +                  EFI_PCI_CONF_MAX_PAYLOAD_SIZE
> > > >
> > > > +
> > > >
> > > > +  @retval TRUE    Setup Max_Payload_Size as per device capability
> > > >
> > > > +          FALSE   override as per device-specific platform policy
> > > >
> > > > +**/
> > > >
> > > > +BOOLEAN
> > > >
> > > > +SetupMpsAsPerDeviceCapability (
> > > >
> > > > +  IN  UINT8                   MPS
> > > >
> > > > +)
> > > >
> > > > +{
> > > >
> > > > +  if ( MPS == EFI_PCI_CONF_MAX_PAYLOAD_SIZE_AUTO) {
> > > >
> > > > +    return TRUE;
> > > >
> > > > +  } else {
> > > >
> > > > +    return FALSE;
> > > >
> > > > +  }
> > > >
> > > > +}
> > > >
> > > > +
> > > >
> > > > +/**
> > > >
> > > > +  Helper routine to indicate whether the given PCI device specific
> policy
> > > > value
> > > >
> > > > +  dictates to override the Max_Read_Req_Size to a particular value, or
> set
> > > as
> > > > per
> > > >
> > > > +  device capability.
> > > >
> > > > +
> > > >
> > > > +  @param  MRRS    Input device-specific policy should be in terms of
> type
> > > >
> > > > +                  EFI_PCI_CONF_MAX_READ_REQ_SIZE
> > > >
> > > > +
> > > >
> > > > +  @retval TRUE    Setup Max_Read_Req_Size as per device capability
> > > >
> > > > +          FALSE   override as per device-specific platform policy
> > > >
> > > > +**/
> > > >
> > > > +BOOLEAN
> > > >
> > > > +SetupMrrsAsPerDeviceCapability (
> > > >
> > > > +  IN  UINT8                   MRRS
> > > >
> > > > +)
> > > >
> > > > +{
> > > >
> > > > +  if ( MRRS == EFI_PCI_CONF_MAX_READ_REQ_SIZE_AUTO) {
> > > >
> > > > +    return TRUE;
> > > >
> > > > +  } else {
> > > >
> > > > +    return FALSE;
> > > >
> > > > +  }
> > > >
> > > > +}
> > > >
> > > > +
> > > >
> > > > +/**
> > > >
> > > > +  Routine to translate the given device-specific platform policy from
> type
> > > >
> > > > +  EFI_PCI_CONF_MAX_PAYLOAD_SIZE to HW-specific value, as per PCI
> > > Base
> > > > Specification
> > > >
> > > > +  Revision 4.0; for the PCI feature Max_Payload_Size.
> > > >
> > > > +
> > > >
> > > > +  @param  MPS     Input device-specific policy should be in terms of
> type
> > > >
> > > > +                  EFI_PCI_CONF_MAX_PAYLOAD_SIZE
> > > >
> > > > +
> > > >
> > > > +  @retval         Range values for the Max_Payload_Size as defined in the
> > > PCI
> > > >
> > > > +                  Base Specification 4.0
> > > >
> > > > +**/
> > > >
> > > > +UINT8
> > > >
> > > > +TranslateMpsSetupValueToPci (
> > > >
> > > > +  IN  UINT8                   MPS
> > > >
> > > > +)
> > > >
> > > > +{
> > > >
> > > > +  switch (MPS) {
> > > >
> > > > +    case EFI_PCI_CONF_MAX_PAYLOAD_SIZE_128B:
> > > >
> > > > +      return PCIE_MAX_PAYLOAD_SIZE_128B;
> > > >
> > > > +    case EFI_PCI_CONF_MAX_PAYLOAD_SIZE_256B:
> > > >
> > > > +      return PCIE_MAX_PAYLOAD_SIZE_256B;
> > > >
> > > > +    case EFI_PCI_CONF_MAX_PAYLOAD_SIZE_512B:
> > > >
> > > > +      return PCIE_MAX_PAYLOAD_SIZE_512B;
> > > >
> > > > +    case EFI_PCI_CONF_MAX_PAYLOAD_SIZE_1024B:
> > > >
> > > > +      return PCIE_MAX_PAYLOAD_SIZE_1024B;
> > > >
> > > > +    case EFI_PCI_CONF_MAX_PAYLOAD_SIZE_2048B:
> > > >
> > > > +      return PCIE_MAX_PAYLOAD_SIZE_2048B;
> > > >
> > > > +    case EFI_PCI_CONF_MAX_PAYLOAD_SIZE_4096B:
> > > >
> > > > +      return PCIE_MAX_PAYLOAD_SIZE_4096B;
> > > >
> > > > +    default:
> > > >
> > > > +      return PCIE_MAX_PAYLOAD_SIZE_128B;
> > > >
> > > > +  }
> > > >
> > > > +}
> > > >
> > > > +
> > > >
> > > > +/**
> > > >
> > > > +  Routine to translate the given device-specific platform policy from
> type
> > > >
> > > > +  EFI_PCI_CONF_MAX_READ_REQ_SIZE to HW-specific value, as per
> PCI
> > > > Base Specification
> > > >
> > > > +  Revision 4.0; for the PCI feature Max_Read_Req_Size.
> > > >
> > > > +
> > > >
> > > > +  @param  MRRS    Input device-specific policy should be in terms of
> type
> > > >
> > > > +                  EFI_PCI_CONF_MAX_READ_REQ_SIZE
> > > >
> > > > +
> > > >
> > > > +  @retval         Range values for the Max_Read_Req_Size as defined in
> the
> > > > PCI
> > > >
> > > > +                  Base Specification 4.0
> > > >
> > > > +**/
> > > >
> > > > +UINT8
> > > >
> > > > +TranslateMrrsSetupValueToPci (
> > > >
> > > > +  IN  UINT8                   MRRS
> > > >
> > > > +)
> > > >
> > > > +{
> > > >
> > > > +  switch (MRRS) {
> > > >
> > > > +    case EFI_PCI_CONF_MAX_READ_REQ_SIZE_128B:
> > > >
> > > > +      return PCIE_MAX_READ_REQ_SIZE_128B;
> > > >
> > > > +    case EFI_PCI_CONF_MAX_READ_REQ_SIZE_256B:
> > > >
> > > > +      return PCIE_MAX_READ_REQ_SIZE_256B;
> > > >
> > > > +    case EFI_PCI_CONF_MAX_READ_REQ_SIZE_512B:
> > > >
> > > > +      return PCIE_MAX_READ_REQ_SIZE_512B;
> > > >
> > > > +    case EFI_PCI_CONF_MAX_READ_REQ_SIZE_1024B:
> > > >
> > > > +      return PCIE_MAX_READ_REQ_SIZE_1024B;
> > > >
> > > > +    case EFI_PCI_CONF_MAX_READ_REQ_SIZE_2048B:
> > > >
> > > > +      return PCIE_MAX_READ_REQ_SIZE_2048B;
> > > >
> > > > +    case EFI_PCI_CONF_MAX_READ_REQ_SIZE_4096B:
> > > >
> > > > +      return PCIE_MAX_READ_REQ_SIZE_4096B;
> > > >
> > > > +    default:
> > > >
> > > > +      return PCIE_MAX_READ_REQ_SIZE_128B;
> > > >
> > > > +  }
> > > >
> > > > +}
> > > >
> > > > +
> > > >
> > > > +/**
> > > >
> > > > +  Generic routine to setup the PCI features as per its predetermined
> > > > defaults.
> > > >
> > > > +**/
> > > >
> > > > +VOID
> > > >
> > > > +SetupDefaultsDevicePlatformPolicy (
> > > >
> > > > +  IN  PCI_IO_DEVICE               *PciDevice
> > > >
> > > > +  )
> > > >
> > > > +{
> > > >
> > > > +  PciDevice->SetupMPS = EFI_PCI_CONF_MAX_PAYLOAD_SIZE_AUTO;
> > > >
> > > > +  PciDevice->SetupMRRS =
> EFI_PCI_CONF_MAX_READ_REQ_SIZE_AUTO;
> > > >
> > > > +}
> > > >
> > > > +
> > > >
> > > > +/**
> > > >
> > > > +  Intermediate routine to either get the PCI device specific platform
> > > policies
> > > >
> > > > +  through the PCI Platform Protocol, or its alias the PCI Override
> Protocol.
> > > >
> > > > +
> > > >
> > > > +  @param  PciIoDevice         A pointer to PCI_IO_DEVICE
> > > >
> > > > +  @param  PciPlatformProtocol A pointer to
> > > > EFI_PCI_PLATFORM_PROTOCOL2
> > > >
> > > > +
> > > >
> > > > +  @retval EFI_STATUS          The direct status from the PCI Platform
> Protocol
> > > >
> > > > +  @retval EFI_SUCCESS         if on returning predetermined PCI features
> > > > defaults,
> > > >
> > > > +                              for the case when protocol returns as
> EFI_UNSUPPORTED
> > > >
> > > > +                              to indicate PCI device exist and it has no platform
> > > >
> > > > +                              policy defined.
> > > >
> > > > +**/
> > > >
> > > > +EFI_STATUS
> > > >
> > > > +GetPciDevicePlatformPolicyEx (
> > > >
> > > > +  IN  PCI_IO_DEVICE               *PciIoDevice,
> > > >
> > > > +  IN  EFI_PCI_PLATFORM_PROTOCOL2  *PciPlatformProtocol
> > > >
> > > > +  )
> > > >
> > > > +{
> > > >
> > > > +  EFI_PCI_PLATFORM_EXTENDED_POLICY  PciPlatformExtendedPolicy;
> > > >
> > > > +  EFI_STATUS                        Status;
> > > >
> > > > +
> > > >
> > > > +  ZeroMem ( &PciPlatformExtendedPolicy, sizeof
> > > > (EFI_PCI_PLATFORM_EXTENDED_POLICY));
> > > >
> > > > +  Status = PciPlatformProtocol->GetDevicePolicy (
> > > >
> > > > +                                  PciPlatformProtocol,
> > > >
> > > > +                                  PciIoDevice->Handle,
> > > >
> > > > +                                  &PciPlatformExtendedPolicy
> > > >
> > > > +                                  );
> > > >
> > > > +  //
> > > >
> > > > +  // platform chipset policies are returned for this PCI device
> > > >
> > > > +  //
> > > >
> > > > +  if (!EFI_ERROR(Status)) {
> > > >
> > > > +    PciIoDevice->SetupMPS = PciPlatformExtendedPolicy.DeviceCtlMPS;
> > > >
> > > > +    PciIoDevice->SetupMRRS =
> PciPlatformExtendedPolicy.DeviceCtlMRRS;
> > > >
> > > > +  }
> > > >
> > > > +  //
> > > >
> > > > +  // platform chipset policies are not provided for this PCI device
> > > >
> > > > +  //
> > > >
> > > > +  if (EFI_ERROR(Status) == EFI_UNSUPPORTED) {
> > > >
> > > > +    //
> > > >
> > > > +    // let the enumeration happen as per the PCI standard way
> > > >
> > > > +    //
> > > >
> > > > +    SetupDefaultsDevicePlatformPolicy ( PciIoDevice);
> > > >
> > > > +    return EFI_SUCCESS;
> > > >
> > > > +  }
> > > >
> > > > +
> > > >
> > > > +  return Status;
> > > >
> > > > +}
> > > >
> > > > +
> > > >
> > > > +/**
> > > >
> > > > +  Gets the PCI device-specific platform policy from the PCI Platform
> > > Protocol.
> > > >
> > > > +  If no PCI Platform protocol is published than setup the PCI feature to
> > > > predetermined
> > > >
> > > > +  defaults, in order to align all the PCI devices in the PCI hierarchy, as
> > > > applicable.
> > > >
> > > > +
> > > >
> > > > +  @param  PciDevice     A pointer to PCI_IO_DEVICE
> > > >
> > > > +
> > > >
> > > > +  @retval EFI_STATUS    The direct status from the PCI Platform
> Protocol
> > > >
> > > > +  @retval EFI_SUCCESS   On return of predetermined PCI features
> defaults,
> > > > for
> > > >
> > > > +                        the case when protocol returns as EFI_UNSUPPORTED to
> > > >
> > > > +                        indicate PCI device exist and it has no platform policy
> > > >
> > > > +                        defined. Also, on returns when no PCI Platform Protocol
> > > >
> > > > +                        exist.
> > > >
> > > > +**/
> > > >
> > > > +EFI_STATUS
> > > >
> > > > +GetPciDevicePlatformPolicy (
> > > >
> > > > +  IN PCI_IO_DEVICE          *PciDevice
> > > >
> > > > +  )
> > > >
> > > > +{
> > > >
> > > > +  if ( mPciPlatformProtocol2 != NULL) {
> > > >
> > > > +    return GetPciDevicePlatformPolicyEx ( PciDevice,
> > > mPciPlatformProtocol2);
> > > >
> > > > +  } else if (mPciOverrideProtocol2 != NULL) {
> > > >
> > > > +    return GetPciDevicePlatformPolicyEx ( PciDevice,
> > > mPciOverrideProtocol2);
> > > >
> > > > +  } else {
> > > >
> > > > +    //
> > > >
> > > > +    // new PCI Platform Protocol 2 is not installed; let the enumeration
> > > > happen
> > > >
> > > > +    // as per PCI standard way
> > > >
> > > > +    //
> > > >
> > > > +    SetupDefaultsDevicePlatformPolicy ( PciDevice);
> > > >
> > > > +    return EFI_SUCCESS;
> > > >
> > > > +  }
> > > >
> > > > +}
> > > >
> > > > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
> > > > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
> > > > new file mode 100644
> > > > index 0000000000..d54e46b950
> > > > --- /dev/null
> > > > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
> > > > @@ -0,0 +1,193 @@
> > > > +/** @file
> > > >
> > > > +  This file encapsulate the usage of PCI Platform Protocol
> > > >
> > > > +
> > > >
> > > > +  This file define the necessary hooks used to obtain the platform
> > > >
> > > > +  level data and policies which could be used in the PCI Enumeration
> > > phases
> > > >
> > > > +
> > > >
> > > > +Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> > > >
> > > > +SPDX-License-Identifier: BSD-2-Clause-Patent
> > > >
> > > > +
> > > >
> > > > +**/
> > > >
> > > > +
> > > >
> > > > +
> > > >
> > > > +#ifndef _EFI_PCI_PLATFORM_SUPPORT_H_
> > > >
> > > > +#define _EFI_PCI_PLATFORM_SUPPORT_H_
> > > >
> > > > +
> > > >
> > > > +#include "PciBus.h"
> > > >
> > > > +
> > > >
> > > > +/**
> > > >
> > > > +  This function retrieves the PCI Platform Protocol published by
> platform
> > > > driver
> > > >
> > > > +
> > > >
> > > > +**/
> > > >
> > > > +VOID
> > > >
> > > > +GetPciPlatformProtocol (
> > > >
> > > > +  );
> > > >
> > > > +
> > > >
> > > > +/**
> > > >
> > > > +  This function indicates the presence of PCI Platform driver
> > > >
> > > > +  @retval     TRUE or FALSE
> > > >
> > > > +**/
> > > >
> > > > +BOOLEAN
> > > >
> > > > +CheckPciPlatformProtocolInstall (
> > > >
> > > > +  );
> > > >
> > > > +
> > > >
> > > > +
> > > >
> > > > +/**
> > > >
> > > > +  Provides the hooks from the PCI bus driver to every PCI controller
> > > > (device/function) at various
> > > >
> > > > +  stages of the PCI enumeration process that allow the host bridge
> driver
> > > to
> > > > preinitialize individual
> > > >
> > > > +  PCI controllers before enumeration.
> > > >
> > > > +
> > > >
> > > > +  This function is called during the PCI enumeration process. No specific
> > > > action is expected from this
> > > >
> > > > +  member function. It allows the host bridge driver to preinitialize
> > > individual
> > > > PCI controllers before
> > > >
> > > > +  enumeration.
> > > >
> > > > +
> > > >
> > > > +  @param[in] HostBridgeHandle     The associated PCI host bridge
> handle.
> > > >
> > > > +  @param[in] RootBridgeHandle     The associated PCI root bridge
> handle.
> > > >
> > > > +  @param[in] RootBridgePciAddress The address of the PCI device on
> the
> > > > PCI bus.
> > > >
> > > > +  @param[in] Phase          The phase of the PCI controller enumeration.
> > > >
> > > > +  @param[in] ExecPhase      Defines the execution phase of the PCI
> chipset
> > > > driver.
> > > >
> > > > +
> > > >
> > > > +  @retval    Status         returns the status from the PCI Platform
> protocol as
> > > is
> > > >
> > > > +
> > > >
> > > > +**/
> > > >
> > > > +EFI_STATUS
> > > >
> > > > +PciPlatformPreprocessController (
> > > >
> > > > +  IN EFI_HANDLE                                    HostBridgeHandle,
> > > >
> > > > +  IN EFI_HANDLE                                    RootBridgeHandle,
> > > >
> > > > +  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS
> > > > RootBridgePciAddress,
> > > >
> > > > +  IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE  Phase,
> > > >
> > > > +  IN EFI_PCI_EXECUTION_PHASE                       ExecPhase
> > > >
> > > > +  );
> > > >
> > > > +
> > > >
> > > > +/**
> > > >
> > > > +  This function notifies the PCI Platform driver about the PCI host
> bridge
> > > > resource
> > > >
> > > > +  allocation phase and PCI execution phase.
> > > >
> > > > +
> > > >
> > > > +  @param[in]  HostBridge     The handle of the host bridge controller.
> > > >
> > > > +  @param[in]  Phase          The phase of the PCI bus enumeration.
> > > >
> > > > +  @param[in]  ExecPhase      Defines the execution phase of the PCI
> > > chipset
> > > > driver.
> > > >
> > > > +  @retval     Status          returns the status from the PCI Platform
> protocol
> > > as
> > > > is
> > > >
> > > > +
> > > >
> > > > +**/
> > > >
> > > > +EFI_STATUS
> > > >
> > > > +PciPlatformNotifyPhase (
> > > >
> > > > +  IN  EFI_HANDLE                                      HostBridgeHandle,
> > > >
> > > > +  IN  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE   Phase,
> > > >
> > > > +  IN  EFI_PCI_EXECUTION_PHASE                         ExecPhase
> > > >
> > > > +  );
> > > >
> > > > +
> > > >
> > > > +/**
> > > >
> > > > +  This function retrieves the PCI platform policy.
> > > >
> > > > +
> > > >
> > > > +  @param  PciPolicy     pointer to the legacy
> EFI_PCI_PLATFORM_POLICY
> > > >
> > > > +  @retval Status        returns the status from the PCI Platform protocol
> as is
> > > >
> > > > +
> > > >
> > > > +**/
> > > >
> > > > +EFI_STATUS
> > > >
> > > > +PciGetPlatformPolicy (
> > > >
> > > > +  OUT EFI_PCI_PLATFORM_POLICY *PciPolicy
> > > >
> > > > +  );
> > > >
> > > > +
> > > >
> > > > +/**
> > > >
> > > > +  This function retrieves the Option ROM image and size from the
> Platform.
> > > >
> > > > +
> > > >
> > > > +  It uses the PCI_IO_DEVICE internal fields are used to store OpROM
> > > > image/size
> > > >
> > > > +
> > > >
> > > > +  @param Controller     An EFI handle for the PCI bus controller.
> > > >
> > > > +  @param PciIoDevice    A PCI_IO_DEVICE pointer to the PCI IO device
> to
> > > be
> > > > registered.
> > > >
> > > > +
> > > >
> > > > +  @retval EFI_SUCCESS            The option ROM was available for this
> device
> > > > and loaded into memory.
> > > >
> > > > +  @retval EFI_NOT_FOUND          No option ROM was available for this
> > > device.
> > > >
> > > > +  @retval EFI_OUT_OF_RESOURCES   No memory was available to load
> the
> > > > option ROM.
> > > >
> > > > +  @retval EFI_DEVICE_ERROR       An error occurred in obtaining the
> option
> > > > ROM.
> > > >
> > > > +
> > > >
> > > > +**/
> > > >
> > > > +EFI_STATUS
> > > >
> > > > +GetPlatformPciOptionRom (
> > > >
> > > > +  IN  EFI_HANDLE                    Controller,
> > > >
> > > > +  IN  PCI_IO_DEVICE                 *PciIoDevice
> > > >
> > > > +  );
> > > >
> > > > +
> > > >
> > > > +/**
> > > >
> > > > +  Gets the PCI device-specific platform policy from the PCI Platform
> > > Protocol.
> > > >
> > > > +  If no PCI Platform protocol is published than setup the PCI feature to
> > > > predetermined
> > > >
> > > > +  defaults, in order to align all the PCI devices in the PCI hierarchy, as
> > > > applicable.
> > > >
> > > > +
> > > >
> > > > +  @param  PciDevice     A pointer to PCI_IO_DEVICE
> > > >
> > > > +
> > > >
> > > > +  @retval EFI_STATUS    The direct status from the PCI Platform
> Protocol
> > > >
> > > > +  @retval EFI_SUCCESS   On return of predetermined PCI features
> defaults,
> > > > for
> > > >
> > > > +                        the case when protocol returns as EFI_UNSUPPORTED to
> > > >
> > > > +                        indicate PCI device exist and it has no platform policy
> > > >
> > > > +                        defined. Also, on returns when no PCI Platform Protocol
> > > >
> > > > +                        exist.
> > > >
> > > > +**/
> > > >
> > > > +EFI_STATUS
> > > >
> > > > +GetPciDevicePlatformPolicy (
> > > >
> > > > +  IN PCI_IO_DEVICE          *PciDevice
> > > >
> > > > +  );
> > > >
> > > > +
> > > >
> > > > +/**
> > > >
> > > > +  Helper routine to indicate whether the given PCI device specific
> policy
> > > > value
> > > >
> > > > +  dictates to override the Max_Payload_Size to a particular value, or
> set as
> > > > per
> > > >
> > > > +  device capability.
> > > >
> > > > +
> > > >
> > > > +  @param  MPS     Input device-specific policy should be in terms of
> type
> > > >
> > > > +                  EFI_PCI_CONF_MAX_PAYLOAD_SIZE
> > > >
> > > > +
> > > >
> > > > +  @retval TRUE    Setup Max_Payload_Size as per device capability
> > > >
> > > > +          FALSE   override as per device-specific platform policy
> > > >
> > > > +**/
> > > >
> > > > +BOOLEAN
> > > >
> > > > +SetupMpsAsPerDeviceCapability (
> > > >
> > > > +  IN  UINT8                   MPS
> > > >
> > > > +);
> > > >
> > > > +
> > > >
> > > > +/**
> > > >
> > > > +  Helper routine to indicate whether the given PCI device specific
> policy
> > > > value
> > > >
> > > > +  dictates to override the Max_Read_Req_Size to a particular value, or
> set
> > > as
> > > > per
> > > >
> > > > +  device capability.
> > > >
> > > > +
> > > >
> > > > +  @param  MRRS    Input device-specific policy should be in terms of
> type
> > > >
> > > > +                  EFI_PCI_CONF_MAX_READ_REQ_SIZE
> > > >
> > > > +
> > > >
> > > > +  @retval TRUE    Setup Max_Read_Req_Size as per device capability
> > > >
> > > > +          FALSE   override as per device-specific platform policy
> > > >
> > > > +**/
> > > >
> > > > +BOOLEAN
> > > >
> > > > +SetupMrrsAsPerDeviceCapability (
> > > >
> > > > +  IN  UINT8                   MRRS
> > > >
> > > > +);
> > > >
> > > > +
> > > >
> > > > +/**
> > > >
> > > > +  Routine to translate the given device-specific platform policy from
> type
> > > >
> > > > +  EFI_PCI_CONF_MAX_PAYLOAD_SIZE to HW-specific value, as per PCI
> > > Base
> > > > Specification
> > > >
> > > > +  Revision 4.0; for the PCI feature Max_Payload_Size.
> > > >
> > > > +
> > > >
> > > > +  @param  MPS     Input device-specific policy should be in terms of
> type
> > > >
> > > > +                  EFI_PCI_CONF_MAX_PAYLOAD_SIZE
> > > >
> > > > +
> > > >
> > > > +  @retval         Range values for the Max_Payload_Size as defined in the
> > > PCI
> > > >
> > > > +                  Base Specification 4.0
> > > >
> > > > +**/
> > > >
> > > > +UINT8
> > > >
> > > > +TranslateMpsSetupValueToPci (
> > > >
> > > > +  IN  UINT8                   MPS
> > > >
> > > > +);
> > > >
> > > > +
> > > >
> > > > +/**
> > > >
> > > > +  Routine to translate the given device-specific platform policy from
> type
> > > >
> > > > +  EFI_PCI_CONF_MAX_READ_REQ_SIZE to HW-specific value, as per
> PCI
> > > > Base Specification
> > > >
> > > > +  Revision 4.0; for the PCI feature Max_Read_Req_Size.
> > > >
> > > > +
> > > >
> > > > +  @param  MRRS    Input device-specific policy should be in terms of
> type
> > > >
> > > > +                  EFI_PCI_CONF_MAX_READ_REQ_SIZE
> > > >
> > > > +
> > > >
> > > > +  @retval         Range values for the Max_Read_Req_Size as defined in
> the
> > > > PCI
> > > >
> > > > +                  Base Specification 4.0
> > > >
> > > > +**/
> > > >
> > > > +UINT8
> > > >
> > > > +TranslateMrrsSetupValueToPci (
> > > >
> > > > +  IN  UINT8                   MRRS
> > > >
> > > > +);
> > > >
> > > > +#endif
> > > >
> > > > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c
> > > > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c
> > > > index 4969ee0f64..755423f77b 100644
> > > > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c
> > > > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c
> > > > @@ -198,20 +198,7 @@ CalculateApertureIo16 (
> > > >      //
> > > >
> > > >      Status = EFI_NOT_FOUND;
> > > >
> > > >      PciPolicy = 0;
> > > >
> > > > -    if (gPciPlatformProtocol != NULL) {
> > > >
> > > > -      Status = gPciPlatformProtocol->GetPlatformPolicy (
> > > >
> > > > -                                       gPciPlatformProtocol,
> > > >
> > > > -                                       &PciPolicy
> > > >
> > > > -                                       );
> > > >
> > > > -    }
> > > >
> > > > -
> > > >
> > > > -    if (EFI_ERROR (Status) && gPciOverrideProtocol != NULL) {
> > > >
> > > > -      Status = gPciOverrideProtocol->GetPlatformPolicy (
> > > >
> > > > -                                       gPciOverrideProtocol,
> > > >
> > > > -                                       &PciPolicy
> > > >
> > > > -                                       );
> > > >
> > > > -    }
> > > >
> > > > -
> > > >
> > > > +    Status = PciGetPlatformPolicy ( &PciPolicy);
> > > >
> > > >      if (!EFI_ERROR (Status)) {
> > > >
> > > >        if ((PciPolicy & EFI_RESERVE_ISA_IO_ALIAS) != 0) {
> > > >
> > > >          mReserveIsaAliases = TRUE;
> > > >
> > > > diff --git a/MdeModulePkg/MdeModulePkg.dec
> > > > b/MdeModulePkg/MdeModulePkg.dec
> > > > index 17beb45235..7bcbe5a3ea 100644
> > > > --- a/MdeModulePkg/MdeModulePkg.dec
> > > > +++ b/MdeModulePkg/MdeModulePkg.dec
> > > > @@ -1026,6 +1026,16 @@
> > > >    # @Prompt Enable UEFI Stack Guard.
> > > >
> > > >
> > > >
> > >
> gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard|FALSE|BOOLEAN|0
> > > > x30001055
> > > >
> > > >
> > > >
> > > > +  ## This PCD is to indicate the PCI Bus driver to setup other new PCI
> > > > features.
> > > >
> > > > +  #  Each PCI feature is represented by its mask bit position and it
> > > configures
> > > >
> > > > +  #  if that bit is set.
> > > >
> > > > +  #
> > > >
> > > > +  #   Bit 0 - if set, the PCI Bus driver programs the device's
> > > > Max_Payload_Size.<BR>
> > > >
> > > > +  #   Bit 1 - if set, the PCI Bus driver programs the device's
> > > > Max_Read_Req_Size.<BR>
> > > >
> > > > +  #   Bit 2 to 31 - Reserved for future use by the PCI Bus driver.<BR>
> > > >
> > > > +  # @Prompt The UEFI PCU Bus driver enables the new set of other PCI
> > > > Features.
> > > >
> > > > +
> > > >
> > >
> gEfiMdeModulePkgTokenSpaceGuid.PcdOtherPciFeatures|0x00000003|UIN
> > > > T32|0x30001056
> > > >
> > > > +
> > > >
> > > >  [PcdsFixedAtBuild, PcdsPatchableInModule]
> > > >
> > > >    ## Dynamic type PCD can be registered callback function for Pcd
> setting
> > > > action.
> > > >
> > > >    #  PcdMaxPeiPcdCallBackNumberPerPcdEntry indicates the maximum
> > > > number of callback function
> > > >
> > > > --
> > > > 2.21.0.windows.1


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

View/Reply Online (#48983): https://edk2.groups.io/g/devel/message/48983
Mute This Topic: https://groups.io/mt/34264504/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub  [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-

Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH] PciBusDxe: New PCI features Max_Payload_Size, Max_Read_Req_Size
Posted by Javeed, Ashraf 4 years, 5 months ago

> -----Original Message-----
> From: Ni, Ray <ray.ni@intel.com>
> Sent: Tuesday, October 15, 2019 1:18 PM
> To: Javeed, Ashraf <ashraf.javeed@intel.com>; 'devel@edk2.groups.io'
> <devel@edk2.groups.io>
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>
> Subject: RE: [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH] PciBusDxe: New PCI
> features Max_Payload_Size, Max_Read_Req_Size
> 
> > > More comments:
> > > 1. IsPciRootPortEmpty(): can you just check whether PciDevice->ChildList is
> > > empty by using IsListEmpty (&PciDevice->ChildList)?
> > OK, will do the additional check.
> 
> Can that be the only check?
It cannot be the only check when I am parsing the list as it is going to loop over; or may be where exactly you want to have this check? I understand it can be the first check before traversing the list.

> 
> >
> > > 2. Can you point to me which spec requires the MPS to be 128 for empty
> > root
> > > ports?
> > Refer the PCI Express Base Specification Revision 5, chapter 7.5.3.4
> > Implementation Notes section.
> Can you please paste the specific wording that supports the logic to program
> MPS to 128B for empty root ports?
> Below wording seems to require 128B only for special OSes that don't support
> PCIE.
> " For example, if the operating system environment does not comprehend PCI
> Express, firmware probably should
> not program a non-default Max_Payload_Size for a hierarchy that supports Hot-
> Plug operations"
Yes; since the PCI Bus driver does not know what OS it is going to boot to, it has to assume for the worst and set it to default, or leave it to default as the HW default is set to 128B. Besides, the Max_Payload_Size is for the Data Packet size,  since the PCI RP is empty there is no point changing to any other value as there won't be any PCI transactions.

> 
> >
> > > 3. GetPciRootPortBusAssigned() is dangerous because it assumes the input
> > > PciDevice points to the bridge.
> > Good catch! Will make the right change.
> 
> As we discussed over phone, using device path can eliminate the needs of
> comparing bus number. Then this function is not needed.
Yes, I am looking towards that direction.

> 
> >
> > > 4. RecordPciRootPortBridges() could be simplified to just collect all
> > PciDevice
> > > instances who:
> > >     a. belongs to the linked list of the root bridge
> > >     b. is a bridge
> > I can see if I can optimize further, but do note that I need to align the PCI
> > feature Max_Payload_Size and Max_Read_Request_Size among all the child
> > PCI devices of the Root Port (RP) in the Root Complex (RC) and since a single
> > RC is known to have multiple RP I need to maintain the list of all the primary
> > RP in the Root Bridge handle so that each primary RP can have its PCI
> > configuration table to track the Max_Payload_Size and
> > Max_Read_Request_Size that needs to be assigned to all its child PCI devices
> > in the tree.
> 
> I am not suggesting to stop collecting all root ports.
> Can you simplify the logic of RecordPciRootPortBridges() as below?
>   for each node in PciRootBridge.ChildList:
>     if (!IsListEmpty (node.ChildList)) {
>       RootPortList.add (node)
OK, will do.

> 
> > > > 2. GetPciPlatformProtocol(): better to rename to InitializePciPlatform ().
> > To me, the word "Initialize" would mean also installing the PCI Platform
> > Protocol which is not the case with the PCI Bus driver; since it only fetches
> > the existing protocol already installed by the platform...
> I agree with your concern : )
> But "Get" means to return the PciPlatform protocol back through function return
> result.
> How about "Locate"?
Ok, will use this key word.

> 
> >
> > > > 3. Why the type cast is needed in below code? If it is because
> > PciPlatform2
> > > > protocol reuses the prototype of GetPciRom defined for PciPlatform
> > protocol,
> > > > I suggest you define GetPciRom for PciPlatform2. Type redefinition
> > seems a
> > > > duplication. But below type-cast is more annoyed.
> > > >
> > > >     Status = mPciPlatformProtocol2->GetPciRom (
> > > >
> > > (EFI_PCI_PLATFORM_PROTOCOL*)mPciPlatformProtocol2,
> > > >                                       PciIoDevice->Handle,
> > > >                                       &PlatformOpRomBuffer,
> > > >                                       &PlatformOpRomSize
> > > >                                       );
> > > >
> > Yes, the PciPlatform2.h which I had submitted to the edk2-staging branch
> > previously; includes the PciPlatform.h during compilation. Even I was thinking
> > the same and since the new definition of the PCI Platform Protocol has to
> > used in future; I can port the legacy definitions into the new definition source
> > file itself to avoid further change in future.
> 
> Thanks.
> 
> >
> > > > 4. Please run ECC tool and fix all coding style issue
> > I thought the ECC tool is used once the changes are submitted into the
> > Gerritt by the maintainer; it is good if I can use it offline; please let me know
> > where to get this tool.
> 
> The tool is inside BaseTools\BinWrappers\WindowsLike\Ecc.bat.
Thanks! Will use this. By the way; I did make the code changes by referring the "EDK-II C Coding Style Standards Specification".

> 
> >
> > > > 5. I don't quite understand what *primary* PCI root port is. So I don't
> > quite
> > > > understand what RecordPciRootPortBridges() does.
> > I used the word primary for the PCI Root port to indicate the first level Root
> > port in the RC of the host; there can be multiple first level PCI RP in the Root
> > Bridge handle and each RP can have its downstream hierarchy which in turn
> > can be the PCIe-PCIe/PCI/PCI-X bridge devices and its endpoint devices.
> > Since the RP and its downstream PCI bridges both have the same PCI Type 1
> > PCI Configuration header, I have to maintain the list of first level RP of the
> > Root Bridge handle.
> >
> > > >
> > > > Thanks,
> > > > Ray
> > > >
> > > > > -----Original Message-----
> > > > > From: Javeed, Ashraf <ashraf.javeed@intel.com>
> > > > > Sent: Monday, September 23, 2019 10:21 PM
> > > > > To: devel@edk2.groups.io
> > > > > Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A
> > > > <hao.a.wu@intel.com>;
> > > > > Ni, Ray <ray.ni@intel.com>
> > > > > Subject: [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH] PciBusDxe: New
> > PCI
> > > > > features Max_Payload_Size, Max_Read_Req_Size
> > > > >
> > > > > REF: https://bugzilla.tianocore.org/show_bug.cgi?id=2194
> > > > >
> > > > > The EDK2 Kernel PciBusDxe driver is enhanced to enable the
> > configuration
> > > > > of PCI features like Max_Payload_Size and Max_Read_Req_Size.
> > > > >
> > > > > Max_Payload_Size:- The PCI Device Control register provides this
> > feature
> > > > > register field which controls the maximum data packet (TLP) size that a
> > > > > PCI device should maintain as a requester. The PCI Bus driver is
> > required
> > > > > to maintain a highest common value supported by all the PCI devices in
> > a
> > > > > PCIe hierarchy, especially in case of isochronous applications.
> > > > >
> > > > > Max_Read_Req_Size:- The PCI Device Control register provides this
> > > > feature
> > > > > register field which controls the maximum memory read request size
> > that a
> > > > > PCI device should maintain as a requester. The PCI Bus driver is
> > required
> > > > > to maintain a common value, same as Max_Payload_Size, in case of
> > > > > isochronous applications only; or else, it should maintain the user
> > > > > requested value uniformly in a PCIe hierarchy (PCI root port and its
> > > > > downstream devices).
> > > > >
> > > > > The PCI Base Specification 4 Revision 1 contains detailed information
> > > > > about these features. The EDK2 PCI Bus driver needs to enable the
> > > > > configuration of these features as per the PCI Base specification.
> > > > >
> > > > > The EDK2 PCI Bus driver also needs to take the PCI device-specific
> > > > > platform policy into the consideration while programming these
> > features;
> > > > > thus the code changes to support these, is explicitly dependent on the
> > > > > new PCI Platform Protocol interface definition defined in the below
> > > > > record:-
> > > > > https://bugzilla.tianocore.org/show_bug.cgi?id=1954
> > > > >
> > > > > Signed-off-by: Ashraf Javeed <ashraf.javeed@intel.com>
> > > > > Cc: Jian J Wang <jian.j.wang@intel.com>
> > > > > Cc: Hao A Wu <hao.a.wu@intel.com>
> > > > > Cc: Ray Ni <ray.ni@intel.com>
> > > > > ---
> > > > >  MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c               |   23 ++------------
> > > > >  MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h               |   14 ++++++++-
> > > > >  MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf          |    9 +++++-
> > > > >  MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c     |  229
> > > > >
> > > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > > ++++++++++++++++++++++++++++------------------------------------------
> > -----
> > > > -
> > > > >  MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c        |  139
> > > > > ++++++++++++++++++++-------------------------------------------------------
> > ----
> > > > ---
> > > > >  MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c |   34
> > > > > ++++++++++++--------
> > > > >  MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c    | 1601
> > > > >
> > > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > >
> > > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > >
> > > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > >
> > > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > >
> > > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > >
> > > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > >
> > > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > >
> > > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > >
> > > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > >
> > > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > >
> > > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > >
> > > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > >
> > > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > >
> > > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > >
> > > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > >
> > > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > > +++++++++
> > > > >  MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h    |  201
> > > > >
> > > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > >
> > > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > > ++
> > > > >  MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c   |  565
> > > > >
> > > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > >
> > > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > >
> > > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > >
> > > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > >
> > > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > > +++++++++++++++++++++++++++++++++++++++++
> > > > >  MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h   |  193
> > > > >
> > > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > >
> > +++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > >  MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c   |   15 +-----
> > ---
> > > > >  MdeModulePkg/MdeModulePkg.dec                         |   10 ++++++
> > > > >  12 files changed, 2797 insertions(+), 236 deletions(-)
> > > > >
> > > > > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c
> > > > > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c
> > > > > index b020ce50ce..2503b298f4 100644
> > > > > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c
> > > > > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c
> > > > > @@ -8,7 +8,7 @@
> > > > >    PCI Root Bridges. So it means platform needs install PCI Root Bridge IO
> > > > > protocol for each
> > > > >
> > > > >    PCI Root Bus and install PCI Host Bridge Resource Allocation Protocol.
> > > > >
> > > > >
> > > > >
> > > > > -Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
> > > > >
> > > > > +Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
> > > > >
> > > > >  SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > >
> > > > >
> > > > >
> > > > >  **/
> > > > >
> > > > > @@ -34,8 +34,6 @@ BOOLEAN                                       gFullEnumeration
> =
> > > > TRUE;
> > > > >  UINT64                                        gAllOne              = 0xFFFFFFFFFFFFFFFFULL;
> > > > >
> > > > >  UINT64                                        gAllZero             = 0;
> > > > >
> > > > >
> > > > >
> > > > > -EFI_PCI_PLATFORM_PROTOCOL                     *gPciPlatformProtocol;
> > > > >
> > > > > -EFI_PCI_OVERRIDE_PROTOCOL                     *gPciOverrideProtocol;
> > > > >
> > > > >  EDKII_IOMMU_PROTOCOL                          *mIoMmuProtocol;
> > > > >
> > > > >
> > > > >
> > > > >
> > > > >
> > > > > @@ -266,24 +264,7 @@ PciBusDriverBindingStart (
> > > > >    // If PCI Platform protocol is available, get it now.
> > > > >
> > > > >    // If the platform implements this, it must be installed before BDS
> > phase
> > > > >
> > > > >    //
> > > > >
> > > > > -  gPciPlatformProtocol = NULL;
> > > > >
> > > > > -  gBS->LocateProtocol (
> > > > >
> > > > > -        &gEfiPciPlatformProtocolGuid,
> > > > >
> > > > > -        NULL,
> > > > >
> > > > > -        (VOID **) &gPciPlatformProtocol
> > > > >
> > > > > -        );
> > > > >
> > > > > -
> > > > >
> > > > > -  //
> > > > >
> > > > > -  // If PCI Platform protocol doesn't exist, try to Pci Override Protocol.
> > > > >
> > > > > -  //
> > > > >
> > > > > -  if (gPciPlatformProtocol == NULL) {
> > > > >
> > > > > -    gPciOverrideProtocol = NULL;
> > > > >
> > > > > -    gBS->LocateProtocol (
> > > > >
> > > > > -          &gEfiPciOverrideProtocolGuid,
> > > > >
> > > > > -          NULL,
> > > > >
> > > > > -          (VOID **) &gPciOverrideProtocol
> > > > >
> > > > > -          );
> > > > >
> > > > > -  }
> > > > >
> > > > > +  GetPciPlatformProtocol ();
> > > > >
> > > > >
> > > > >
> > > > >    if (mIoMmuProtocol == NULL) {
> > > > >
> > > > >      gBS->LocateProtocol (
> > > > >
> > > > > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> > > > > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> > > > > index 504a1b1c12..7955bf8a26 100644
> > > > > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> > > > > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> > > > > @@ -27,6 +27,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > >  #include <Protocol/PciOverride.h>
> > > > >
> > > > >  #include <Protocol/PciEnumerationComplete.h>
> > > > >
> > > > >  #include <Protocol/IoMmu.h>
> > > > >
> > > > > +#include <Protocol/PciPlatform2.h>
> > > > >
> > > > > +#include <Protocol/PciOverride2.h>
> > > > >
> > > > >
> > > > >
> > > > >  #include <Library/DebugLib.h>
> > > > >
> > > > >  #include <Library/UefiDriverEntryPoint.h>
> > > > >
> > > > > @@ -79,6 +81,7 @@ typedef enum {
> > > > >  #include "PciPowerManagement.h"
> > > > >
> > > > >  #include "PciHotPlugSupport.h"
> > > > >
> > > > >  #include "PciLib.h"
> > > > >
> > > > > +#include "PciFeatureSupport.h"
> > > > >
> > > > >
> > > > >
> > > > >  #define VGABASE1  0x3B0
> > > > >
> > > > >  #define VGALIMIT1 0x3BB
> > > > >
> > > > > @@ -263,9 +266,13 @@ struct _PCI_IO_DEVICE {
> > > > >
> > > > >
> > > > >    BOOLEAN                                   IsPciExp;
> > > > >
> > > > >    //
> > > > >
> > > > > -  // For SR-IOV
> > > > >
> > > > > +  // For PCI Express Capability List Structure
> > > > >
> > > > >    //
> > > > >
> > > > >    UINT8                                     PciExpressCapabilityOffset;
> > > > >
> > > > > +  PCI_CAPABILITY_PCIEXP                     PciExpStruct;
> > > > >
> > > > > +  //
> > > > >
> > > > > +  // For SR-IOV
> > > > >
> > > > > +  //
> > > > >
> > > > >    UINT32                                    AriCapabilityOffset;
> > > > >
> > > > >    UINT32                                    SrIovCapabilityOffset;
> > > > >
> > > > >    UINT32                                    MrIovCapabilityOffset;
> > > > >
> > > > > @@ -279,6 +286,11 @@ struct _PCI_IO_DEVICE {
> > > > >    // This field is used to support this case.
> > > > >
> > > > >    //
> > > > >
> > > > >    UINT16                                    BridgeIoAlignment;
> > > > >
> > > > > +  //
> > > > >
> > > > > +  // Other PCI features setup flags
> > > > >
> > > > > +  //
> > > > >
> > > > > +  UINT8                                     SetupMPS;
> > > > >
> > > > > +  UINT8                                     SetupMRRS;
> > > > >
> > > > >  };
> > > > >
> > > > >
> > > > >
> > > > >  #define PCI_IO_DEVICE_FROM_PCI_IO_THIS(a) \
> > > > >
> > > > > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
> > > > > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
> > > > > index 05c22025b8..13768d7ded 100644
> > > > > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
> > > > > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
> > > > > @@ -2,7 +2,7 @@
> > > > >  #  The PCI bus driver will probe all PCI devices and allocate MMIO and
> > IO
> > > > > space for these devices.
> > > > >
> > > > >  #  Please use PCD feature flag PcdPciBusHotplugDeviceSupport to
> > enable
> > > > > hot plug supporting.
> > > > >
> > > > >  #
> > > > >
> > > > > -#  Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
> > > > >
> > > > > +#  Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
> > > > >
> > > > >  #
> > > > >
> > > > >  #  SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > >
> > > > >  #
> > > > >
> > > > > @@ -57,6 +57,10 @@
> > > > >    PciCommand.h
> > > > >
> > > > >    PciIo.h
> > > > >
> > > > >    PciBus.h
> > > > >
> > > > > +  PciFeatureSupport.c
> > > > >
> > > > > +  PciFeatureSupport.h
> > > > >
> > > > > +  PciPlatformSupport.c
> > > > >
> > > > > +  PciPlatformSupport.h
> > > > >
> > > > >
> > > > >
> > > > >  [Packages]
> > > > >
> > > > >    MdePkg/MdePkg.dec
> > > > >
> > > > > @@ -91,6 +95,8 @@
> > > > >    gEfiLoadFile2ProtocolGuid                       ## SOMETIMES_PRODUCES
> > > > >
> > > > >    gEdkiiIoMmuProtocolGuid                         ## SOMETIMES_CONSUMES
> > > > >
> > > > >    gEfiLoadedImageDevicePathProtocolGuid           ## CONSUMES
> > > > >
> > > > > +  gEfiPciPlatformProtocol2Guid                     ## SOMETIMES_CONSUMES
> > > > >
> > > > > +  gEfiPciOverrideProtocol2Guid                     ## SOMETIMES_CONSUMES
> > > > >
> > > > >
> > > > >
> > > > >  [FeaturePcd]
> > > > >
> > > > >    gEfiMdeModulePkgTokenSpaceGuid.PcdPciBusHotplugDeviceSupport
> > > > ##
> > > > > CONSUMES
> > > > >
> > > > > @@ -104,6 +110,7 @@
> > > > >    gEfiMdeModulePkgTokenSpaceGuid.PcdAriSupport                  ##
> > > > CONSUMES
> > > > >
> > > > >    gEfiMdeModulePkgTokenSpaceGuid.PcdMrIovSupport                ##
> > > > > CONSUMES
> > > > >
> > > > >    gEfiMdeModulePkgTokenSpaceGuid.PcdPciDisableBusEnumeration
> > ##
> > > > > SOMETIMES_CONSUMES
> > > > >
> > > > > +  gEfiMdeModulePkgTokenSpaceGuid.PcdOtherPciFeatures
> > ##
> > > > > CONSUMES
> > > > >
> > > > >
> > > > >
> > > > >  [UserExtensions.TianoCore."ExtraFiles"]
> > > > >
> > > > >    PciBusDxeExtra.uni
> > > > >
> > > > > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
> > > > > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
> > > > > index b7832c6970..0f76ab1cd5 100644
> > > > > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
> > > > > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
> > > > > @@ -170,6 +170,8 @@ DestroyRootBridgeByHandle (
> > > > >
> > > > >
> > > > >      if (Temp->Handle == Controller) {
> > > > >
> > > > >
> > > > >
> > > > > +      DestroyRootBridgePciFeaturesConfigCompletionList ( Temp);
> > > > >
> > > > > +
> > > > >
> > > > >        RemoveEntryList (CurrentLink);
> > > > >
> > > > >
> > > > >
> > > > >        DestroyPciDeviceTree (Temp);
> > > > >
> > > > > @@ -208,8 +210,6 @@ RegisterPciDevice (
> > > > >    )
> > > > >
> > > > >  {
> > > > >
> > > > >    EFI_STATUS          Status;
> > > > >
> > > > > -  VOID                *PlatformOpRomBuffer;
> > > > >
> > > > > -  UINTN               PlatformOpRomSize;
> > > > >
> > > > >    EFI_PCI_IO_PROTOCOL *PciIo;
> > > > >
> > > > >    UINT8               Data8;
> > > > >
> > > > >    BOOLEAN             HasEfiImage;
> > > > >
> > > > > @@ -244,49 +244,13 @@ RegisterPciDevice (
> > > > >      //
> > > > >
> > > > >      // Get the OpRom provided by platform
> > > > >
> > > > >      //
> > > > >
> > > > > -    if (gPciPlatformProtocol != NULL) {
> > > > >
> > > > > -      Status = gPciPlatformProtocol->GetPciRom (
> > > > >
> > > > > -                                       gPciPlatformProtocol,
> > > > >
> > > > > -                                       PciIoDevice->Handle,
> > > > >
> > > > > -                                       &PlatformOpRomBuffer,
> > > > >
> > > > > -                                       &PlatformOpRomSize
> > > > >
> > > > > -                                       );
> > > > >
> > > > > -      if (!EFI_ERROR (Status)) {
> > > > >
> > > > > -        PciIoDevice->EmbeddedRom    = FALSE;
> > > > >
> > > > > -        PciIoDevice->RomSize        = (UINT32) PlatformOpRomSize;
> > > > >
> > > > > -        PciIoDevice->PciIo.RomSize  = PlatformOpRomSize;
> > > > >
> > > > > -        PciIoDevice->PciIo.RomImage = PlatformOpRomBuffer;
> > > > >
> > > > > -        //
> > > > >
> > > > > -        // For OpROM read from gPciPlatformProtocol:
> > > > >
> > > > > -        // Add the Rom Image to internal database for later PCI light
> > > > > enumeration
> > > > >
> > > > > -        //
> > > > >
> > > > > -        PciRomAddImageMapping (
> > > > >
> > > > > -          NULL,
> > > > >
> > > > > -          PciIoDevice->PciRootBridgeIo->SegmentNumber,
> > > > >
> > > > > -          PciIoDevice->BusNumber,
> > > > >
> > > > > -          PciIoDevice->DeviceNumber,
> > > > >
> > > > > -          PciIoDevice->FunctionNumber,
> > > > >
> > > > > -          PciIoDevice->PciIo.RomImage,
> > > > >
> > > > > -          PciIoDevice->PciIo.RomSize
> > > > >
> > > > > -          );
> > > > >
> > > > > -      }
> > > > >
> > > > > -    } else if (gPciOverrideProtocol != NULL) {
> > > > >
> > > > > -      Status = gPciOverrideProtocol->GetPciRom (
> > > > >
> > > > > -                                       gPciOverrideProtocol,
> > > > >
> > > > > -                                       PciIoDevice->Handle,
> > > > >
> > > > > -                                       &PlatformOpRomBuffer,
> > > > >
> > > > > -                                       &PlatformOpRomSize
> > > > >
> > > > > -                                       );
> > > > >
> > > > > -      if (!EFI_ERROR (Status)) {
> > > > >
> > > > > -        PciIoDevice->EmbeddedRom    = FALSE;
> > > > >
> > > > > -        PciIoDevice->RomSize        = (UINT32) PlatformOpRomSize;
> > > > >
> > > > > -        PciIoDevice->PciIo.RomSize  = PlatformOpRomSize;
> > > > >
> > > > > -        PciIoDevice->PciIo.RomImage = PlatformOpRomBuffer;
> > > > >
> > > > > -        //
> > > > >
> > > > > -        // For OpROM read from gPciOverrideProtocol:
> > > > >
> > > > > -        // Add the Rom Image to internal database for later PCI light
> > > > > enumeration
> > > > >
> > > > > -        //
> > > > >
> > > > > -        PciRomAddImageMapping (
> > > > >
> > > > > +    Status = GetPlatformPciOptionRom ( Controller, PciIoDevice);
> > > > >
> > > > > +    if (!EFI_ERROR (Status)) {
> > > > >
> > > > > +      //
> > > > >
> > > > > +      // For OpROM read from the PCI Platform Protocol:
> > > > >
> > > > > +      // Add the Rom Image to internal database for later PCI light
> > > > > enumeration
> > > > >
> > > > > +      //
> > > > >
> > > > > +      PciRomAddImageMapping (
> > > > >
> > > > >            NULL,
> > > > >
> > > > >            PciIoDevice->PciRootBridgeIo->SegmentNumber,
> > > > >
> > > > >            PciIoDevice->BusNumber,
> > > > >
> > > > > @@ -294,8 +258,7 @@ RegisterPciDevice (
> > > > >            PciIoDevice->FunctionNumber,
> > > > >
> > > > >            PciIoDevice->PciIo.RomImage,
> > > > >
> > > > >            PciIoDevice->PciIo.RomSize
> > > > >
> > > > > -          );
> > > > >
> > > > > -      }
> > > > >
> > > > > +        );
> > > > >
> > > > >      }
> > > > >
> > > > >    }
> > > > >
> > > > >
> > > > >
> > > > > @@ -597,7 +560,7 @@ DeRegisterPciDevice (
> > > > >  }
> > > > >
> > > > >
> > > > >
> > > > >  /**
> > > > >
> > > > > -  Start to manage the PCI device on the specified root bridge or PCI-PCI
> > > > > Bridge.
> > > > >
> > > > > +  Start the PCI root Ports or PCI-PCI Bridge only.
> > > > >
> > > > >
> > > > >
> > > > >    @param Controller          The root bridge handle.
> > > > >
> > > > >    @param RootBridge          A pointer to the PCI_IO_DEVICE.
> > > > >
> > > > > @@ -612,7 +575,82 @@ DeRegisterPciDevice (
> > > > >
> > > > >
> > > > >  **/
> > > > >
> > > > >  EFI_STATUS
> > > > >
> > > > > -StartPciDevicesOnBridge (
> > > > >
> > > > > +StartPciRootPortsOnBridge (
> > > > >
> > > > > +  IN EFI_HANDLE                          Controller,
> > > > >
> > > > > +  IN PCI_IO_DEVICE                       *RootBridge
> > > > >
> > > > > +  )
> > > > >
> > > > > +
> > > > >
> > > > > +{
> > > > >
> > > > > +  PCI_IO_DEVICE             *PciIoDevice;
> > > > >
> > > > > +  EFI_STATUS                Status;
> > > > >
> > > > > +  LIST_ENTRY                *CurrentLink;
> > > > >
> > > > > +  UINT64                    Supports;
> > > > >
> > > > > +
> > > > >
> > > > > +  PciIoDevice = NULL;
> > > > >
> > > > > +  CurrentLink = RootBridge->ChildList.ForwardLink;
> > > > >
> > > > > +
> > > > >
> > > > > +  while (CurrentLink != NULL && CurrentLink != &RootBridge->ChildList)
> > {
> > > > >
> > > > > +
> > > > >
> > > > > +    PciIoDevice = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
> > > > >
> > > > > +
> > > > >
> > > > > +    //
> > > > >
> > > > > +    // check if the device has been assigned with required resource
> > > > >
> > > > > +    // and registered
> > > > >
> > > > > +    //
> > > > >
> > > > > +    if (!PciIoDevice->Registered && !PciIoDevice->Allocated) {
> > > > >
> > > > > +      return EFI_NOT_READY;
> > > > >
> > > > > +    }
> > > > >
> > > > > +
> > > > >
> > > > > +    if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {
> > > > >
> > > > > +      Status = StartPciRootPortsOnBridge (
> > > > >
> > > > > +                 Controller,
> > > > >
> > > > > +                 PciIoDevice
> > > > >
> > > > > +                 );
> > > > >
> > > > > +
> > > > >
> > > > > +      PciIoDevice->PciIo.Attributes (
> > > > >
> > > > > +                           &(PciIoDevice->PciIo),
> > > > >
> > > > > +                           EfiPciIoAttributeOperationSupported,
> > > > >
> > > > > +                           0,
> > > > >
> > > > > +                           &Supports
> > > > >
> > > > > +                         );
> > > > >
> > > > > +      Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;
> > > > >
> > > > > +      PciIoDevice->PciIo.Attributes (
> > > > >
> > > > > +                           &(PciIoDevice->PciIo),
> > > > >
> > > > > +                           EfiPciIoAttributeOperationEnable,
> > > > >
> > > > > +                           Supports,
> > > > >
> > > > > +                           NULL
> > > > >
> > > > > +                         );
> > > > >
> > > > > +
> > > > >
> > > > > +    }
> > > > >
> > > > > +
> > > > >
> > > > > +    CurrentLink = CurrentLink->ForwardLink;
> > > > >
> > > > > +  }
> > > > >
> > > > > +
> > > > >
> > > > > +  if (PciIoDevice == NULL) {
> > > > >
> > > > > +    return EFI_NOT_FOUND;
> > > > >
> > > > > +  } else {
> > > > >
> > > > > +    return EFI_SUCCESS;
> > > > >
> > > > > +  }
> > > > >
> > > > > +}
> > > > >
> > > > > +
> > > > >
> > > > > +
> > > > >
> > > > > +/**
> > > > >
> > > > > +  Register to manage the PCI device on the specified root bridge or
> > PCI-PCI
> > > > > Bridge.
> > > > >
> > > > > +
> > > > >
> > > > > +  @param Controller          The root bridge handle.
> > > > >
> > > > > +  @param RootBridge          A pointer to the PCI_IO_DEVICE.
> > > > >
> > > > > +  @param RemainingDevicePath A pointer to the
> > > > > EFI_DEVICE_PATH_PROTOCOL.
> > > > >
> > > > > +  @param NumberOfChildren    Children number.
> > > > >
> > > > > +  @param ChildHandleBuffer   A pointer to the child handle buffer.
> > > > >
> > > > > +
> > > > >
> > > > > +  @retval EFI_NOT_READY   Device is not allocated.
> > > > >
> > > > > +  @retval EFI_UNSUPPORTED Device only support PCI-PCI bridge.
> > > > >
> > > > > +  @retval EFI_NOT_FOUND   Can not find the specific device.
> > > > >
> > > > > +  @retval EFI_SUCCESS     Success to start Pci devices on bridge.
> > > > >
> > > > > +
> > > > >
> > > > > +**/
> > > > >
> > > > > +EFI_STATUS
> > > > >
> > > > > +RegisterPciDevicesOnBridge (
> > > > >
> > > > >    IN EFI_HANDLE                          Controller,
> > > > >
> > > > >    IN PCI_IO_DEVICE                       *RootBridge,
> > > > >
> > > > >    IN EFI_DEVICE_PATH_PROTOCOL            *RemainingDevicePath,
> > > > >
> > > > > @@ -626,7 +664,6 @@ StartPciDevicesOnBridge (
> > > > >    EFI_DEVICE_PATH_PROTOCOL  *CurrentDevicePath;
> > > > >
> > > > >    EFI_STATUS                Status;
> > > > >
> > > > >    LIST_ENTRY                *CurrentLink;
> > > > >
> > > > > -  UINT64                    Supports;
> > > > >
> > > > >
> > > > >
> > > > >    PciIoDevice = NULL;
> > > > >
> > > > >    CurrentLink = RootBridge->ChildList.ForwardLink;
> > > > >
> > > > > @@ -681,7 +718,7 @@ StartPciDevicesOnBridge (
> > > > >        // If it is a PPB
> > > > >
> > > > >        //
> > > > >
> > > > >        if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {
> > > > >
> > > > > -        Status = StartPciDevicesOnBridge (
> > > > >
> > > > > +        Status = RegisterPciDevicesOnBridge (
> > > > >
> > > > >                     Controller,
> > > > >
> > > > >                     PciIoDevice,
> > > > >
> > > > >                     CurrentDevicePath,
> > > > >
> > > > > @@ -689,20 +726,6 @@ StartPciDevicesOnBridge (
> > > > >                     ChildHandleBuffer
> > > > >
> > > > >                     );
> > > > >
> > > > >
> > > > >
> > > > > -        PciIoDevice->PciIo.Attributes (
> > > > >
> > > > > -                             &(PciIoDevice->PciIo),
> > > > >
> > > > > -                             EfiPciIoAttributeOperationSupported,
> > > > >
> > > > > -                             0,
> > > > >
> > > > > -                             &Supports
> > > > >
> > > > > -                             );
> > > > >
> > > > > -        Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;
> > > > >
> > > > > -        PciIoDevice->PciIo.Attributes (
> > > > >
> > > > > -                             &(PciIoDevice->PciIo),
> > > > >
> > > > > -                             EfiPciIoAttributeOperationEnable,
> > > > >
> > > > > -                             Supports,
> > > > >
> > > > > -                             NULL
> > > > >
> > > > > -                             );
> > > > >
> > > > > -
> > > > >
> > > > >          return Status;
> > > > >
> > > > >        } else {
> > > > >
> > > > >
> > > > >
> > > > > @@ -733,28 +756,13 @@ StartPciDevicesOnBridge (
> > > > >        }
> > > > >
> > > > >
> > > > >
> > > > >        if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {
> > > > >
> > > > > -        Status = StartPciDevicesOnBridge (
> > > > >
> > > > > +        Status = RegisterPciDevicesOnBridge (
> > > > >
> > > > >                     Controller,
> > > > >
> > > > >                     PciIoDevice,
> > > > >
> > > > >                     RemainingDevicePath,
> > > > >
> > > > >                     NumberOfChildren,
> > > > >
> > > > >                     ChildHandleBuffer
> > > > >
> > > > >                     );
> > > > >
> > > > > -
> > > > >
> > > > > -        PciIoDevice->PciIo.Attributes (
> > > > >
> > > > > -                             &(PciIoDevice->PciIo),
> > > > >
> > > > > -                             EfiPciIoAttributeOperationSupported,
> > > > >
> > > > > -                             0,
> > > > >
> > > > > -                             &Supports
> > > > >
> > > > > -                             );
> > > > >
> > > > > -        Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;
> > > > >
> > > > > -        PciIoDevice->PciIo.Attributes (
> > > > >
> > > > > -                             &(PciIoDevice->PciIo),
> > > > >
> > > > > -                             EfiPciIoAttributeOperationEnable,
> > > > >
> > > > > -                             Supports,
> > > > >
> > > > > -                             NULL
> > > > >
> > > > > -                             );
> > > > >
> > > > > -
> > > > >
> > > > >        }
> > > > >
> > > > >
> > > > >
> > > > >        CurrentLink = CurrentLink->ForwardLink;
> > > > >
> > > > > @@ -768,6 +776,65 @@ StartPciDevicesOnBridge (
> > > > >    }
> > > > >
> > > > >  }
> > > > >
> > > > >
> > > > >
> > > > > +/**
> > > > >
> > > > > +  Start to manage the PCI device on the specified root bridge or PCI-PCI
> > > > > Bridge.
> > > > >
> > > > > +
> > > > >
> > > > > +  @param Controller          The root bridge handle.
> > > > >
> > > > > +  @param RootBridge          A pointer to the PCI_IO_DEVICE.
> > > > >
> > > > > +  @param RemainingDevicePath A pointer to the
> > > > > EFI_DEVICE_PATH_PROTOCOL.
> > > > >
> > > > > +  @param NumberOfChildren    Children number.
> > > > >
> > > > > +  @param ChildHandleBuffer   A pointer to the child handle buffer.
> > > > >
> > > > > +
> > > > >
> > > > > +  @retval EFI_NOT_READY   Device is not allocated.
> > > > >
> > > > > +  @retval EFI_UNSUPPORTED Device only support PCI-PCI bridge.
> > > > >
> > > > > +  @retval EFI_NOT_FOUND   Can not find the specific device.
> > > > >
> > > > > +  @retval EFI_SUCCESS     Success to start Pci devices on bridge.
> > > > >
> > > > > +
> > > > >
> > > > > +**/
> > > > >
> > > > > +EFI_STATUS
> > > > >
> > > > > +StartPciDevicesOnBridge (
> > > > >
> > > > > +  IN EFI_HANDLE                          Controller,
> > > > >
> > > > > +  IN PCI_IO_DEVICE                       *RootBridge,
> > > > >
> > > > > +  IN EFI_DEVICE_PATH_PROTOCOL            *RemainingDevicePath,
> > > > >
> > > > > +  IN OUT UINT8                           *NumberOfChildren,
> > > > >
> > > > > +  IN OUT EFI_HANDLE                      *ChildHandleBuffer
> > > > >
> > > > > +  )
> > > > >
> > > > > +
> > > > >
> > > > > +{
> > > > >
> > > > > +  EFI_STATUS                Status;
> > > > >
> > > > > +
> > > > >
> > > > > +  //
> > > > >
> > > > > +  // first register all the PCI devices
> > > > >
> > > > > +  //
> > > > >
> > > > > +  Status = RegisterPciDevicesOnBridge (
> > > > >
> > > > > +             Controller,
> > > > >
> > > > > +             RootBridge,
> > > > >
> > > > > +             RemainingDevicePath,
> > > > >
> > > > > +             NumberOfChildren,
> > > > >
> > > > > +             ChildHandleBuffer
> > > > >
> > > > > +             );
> > > > >
> > > > > +
> > > > >
> > > > > +  if (EFI_ERROR (Status) == EFI_NOT_FOUND) {
> > > > >
> > > > > +    return Status;
> > > > >
> > > > > +  } else {
> > > > >
> > > > > +    if ( CheckOtherPciFeaturesPcd ()) {
> > > > >
> > > > > +      //
> > > > >
> > > > > +      // the late configuration of PCI features
> > > > >
> > > > > +      //
> > > > >
> > > > > +      Status = EnumerateOtherPciFeatures (
> > > > >
> > > > > +                  RootBridge
> > > > >
> > > > > +                );
> > > > >
> > > > > +    }
> > > > >
> > > > > +    //
> > > > >
> > > > > +    // finally start those PCI bridge port devices only
> > > > >
> > > > > +    //
> > > > >
> > > > > +    return StartPciRootPortsOnBridge (
> > > > >
> > > > > +            Controller,
> > > > >
> > > > > +            RootBridge
> > > > >
> > > > > +            );
> > > > >
> > > > > +  }
> > > > >
> > > > > +}
> > > > >
> > > > > +
> > > > >
> > > > >  /**
> > > > >
> > > > >    Start to manage all the PCI devices it found previously under
> > > > >
> > > > >    the entire host bridge.
> > > > >
> > > > > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c
> > > > > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c
> > > > > index 8db1ebf8ec..0a56668380 100644
> > > > > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c
> > > > > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c
> > > > > @@ -1003,7 +1003,7 @@ PciHostBridgeAdjustAllocation (
> > > > >      Status = RejectPciDevice (PciResNode->PciDev);
> > > > >
> > > > >      if (Status == EFI_SUCCESS) {
> > > > >
> > > > >        DEBUG ((
> > > > >
> > > > > -        EFI_D_ERROR,
> > > > >
> > > > > +        DEBUG_ERROR,
> > > > >
> > > > >          "PciBus: [%02x|%02x|%02x] was rejected due to resource
> > > > > confliction.\n",
> > > > >
> > > > >          PciResNode->PciDev->BusNumber, PciResNode->PciDev-
> > > > > >DeviceNumber, PciResNode->PciDev->FunctionNumber
> > > > >
> > > > >          ));
> > > > >
> > > > > @@ -1746,7 +1746,7 @@ NotifyPhase (
> > > > >
> > > > >
> > > > >    HostBridgeHandle  = NULL;
> > > > >
> > > > >    RootBridgeHandle  = NULL;
> > > > >
> > > > > -  if (gPciPlatformProtocol != NULL) {
> > > > >
> > > > > +  if ( CheckPciPlatformProtocolInstall()) {
> > > > >
> > > > >      //
> > > > >
> > > > >      // Get Host Bridge Handle.
> > > > >
> > > > >      //
> > > > >
> > > > > @@ -1770,42 +1770,11 @@ NotifyPhase (
> > > > >      //
> > > > >
> > > > >      // Call PlatformPci::PlatformNotify() if the protocol is present.
> > > > >
> > > > >      //
> > > > >
> > > > > -    gPciPlatformProtocol->PlatformNotify (
> > > > >
> > > > > -                            gPciPlatformProtocol,
> > > > >
> > > > > -                            HostBridgeHandle,
> > > > >
> > > > > -                            Phase,
> > > > >
> > > > > -                            ChipsetEntry
> > > > >
> > > > > -                            );
> > > > >
> > > > > -  } else if (gPciOverrideProtocol != NULL){
> > > > >
> > > > > -    //
> > > > >
> > > > > -    // Get Host Bridge Handle.
> > > > >
> > > > > -    //
> > > > >
> > > > > -    PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle);
> > > > >
> > > > > -
> > > > >
> > > > > -    //
> > > > >
> > > > > -    // Get the rootbridge Io protocol to find the host bridge handle
> > > > >
> > > > > -    //
> > > > >
> > > > > -    Status = gBS->HandleProtocol (
> > > > >
> > > > > -                    RootBridgeHandle,
> > > > >
> > > > > -                    &gEfiPciRootBridgeIoProtocolGuid,
> > > > >
> > > > > -                    (VOID **) &PciRootBridgeIo
> > > > >
> > > > > -                    );
> > > > >
> > > > > -
> > > > >
> > > > > -    if (EFI_ERROR (Status)) {
> > > > >
> > > > > -      return EFI_NOT_FOUND;
> > > > >
> > > > > -    }
> > > > >
> > > > > -
> > > > >
> > > > > -    HostBridgeHandle = PciRootBridgeIo->ParentHandle;
> > > > >
> > > > > -
> > > > >
> > > > > -    //
> > > > >
> > > > > -    // Call PlatformPci::PhaseNotify() if the protocol is present.
> > > > >
> > > > > -    //
> > > > >
> > > > > -    gPciOverrideProtocol->PlatformNotify (
> > > > >
> > > > > -                            gPciOverrideProtocol,
> > > > >
> > > > > -                            HostBridgeHandle,
> > > > >
> > > > > -                            Phase,
> > > > >
> > > > > -                            ChipsetEntry
> > > > >
> > > > > -                            );
> > > > >
> > > > > +    PciPlatformNotifyPhase (
> > > > >
> > > > > +        HostBridgeHandle,
> > > > >
> > > > > +        Phase,
> > > > >
> > > > > +        ChipsetEntry
> > > > >
> > > > > +        );
> > > > >
> > > > >    }
> > > > >
> > > > >
> > > > >
> > > > >    Status = PciResAlloc->NotifyPhase (
> > > > >
> > > > > @@ -1813,27 +1782,15 @@ NotifyPhase (
> > > > >                            Phase
> > > > >
> > > > >                            );
> > > > >
> > > > >
> > > > >
> > > > > -  if (gPciPlatformProtocol != NULL) {
> > > > >
> > > > > +  if ( CheckPciPlatformProtocolInstall()) {
> > > > >
> > > > >      //
> > > > >
> > > > >      // Call PlatformPci::PlatformNotify() if the protocol is present.
> > > > >
> > > > >      //
> > > > >
> > > > > -    gPciPlatformProtocol->PlatformNotify (
> > > > >
> > > > > -                            gPciPlatformProtocol,
> > > > >
> > > > > -                            HostBridgeHandle,
> > > > >
> > > > > -                            Phase,
> > > > >
> > > > > -                            ChipsetExit
> > > > >
> > > > > -                            );
> > > > >
> > > > > -
> > > > >
> > > > > -  } else if (gPciOverrideProtocol != NULL) {
> > > > >
> > > > > -    //
> > > > >
> > > > > -    // Call PlatformPci::PhaseNotify() if the protocol is present.
> > > > >
> > > > > -    //
> > > > >
> > > > > -    gPciOverrideProtocol->PlatformNotify (
> > > > >
> > > > > -                            gPciOverrideProtocol,
> > > > >
> > > > > -                            HostBridgeHandle,
> > > > >
> > > > > -                            Phase,
> > > > >
> > > > > -                            ChipsetExit
> > > > >
> > > > > -                            );
> > > > >
> > > > > +    PciPlatformNotifyPhase (
> > > > >
> > > > > +        HostBridgeHandle,
> > > > >
> > > > > +        Phase,
> > > > >
> > > > > +        ChipsetExit
> > > > >
> > > > > +        );
> > > > >
> > > > >    }
> > > > >
> > > > >
> > > > >
> > > > >    return Status;
> > > > >
> > > > > @@ -1914,31 +1871,16 @@ PreprocessController (
> > > > >    RootBridgePciAddress.Bus              = Bus;
> > > > >
> > > > >    RootBridgePciAddress.ExtendedRegister = 0;
> > > > >
> > > > >
> > > > >
> > > > > -  if (gPciPlatformProtocol != NULL) {
> > > > >
> > > > > -    //
> > > > >
> > > > > -    // Call PlatformPci::PrepController() if the protocol is present.
> > > > >
> > > > > -    //
> > > > >
> > > > > -    gPciPlatformProtocol->PlatformPrepController (
> > > > >
> > > > > -                            gPciPlatformProtocol,
> > > > >
> > > > > -                            HostBridgeHandle,
> > > > >
> > > > > -                            RootBridgeHandle,
> > > > >
> > > > > -                            RootBridgePciAddress,
> > > > >
> > > > > -                            Phase,
> > > > >
> > > > > -                            ChipsetEntry
> > > > >
> > > > > -                            );
> > > > >
> > > > > -  } else if (gPciOverrideProtocol != NULL) {
> > > > >
> > > > > -    //
> > > > >
> > > > > -    // Call PlatformPci::PrepController() if the protocol is present.
> > > > >
> > > > > -    //
> > > > >
> > > > > -    gPciOverrideProtocol->PlatformPrepController (
> > > > >
> > > > > -                            gPciOverrideProtocol,
> > > > >
> > > > > -                            HostBridgeHandle,
> > > > >
> > > > > -                            RootBridgeHandle,
> > > > >
> > > > > -                            RootBridgePciAddress,
> > > > >
> > > > > -                            Phase,
> > > > >
> > > > > -                            ChipsetEntry
> > > > >
> > > > > -                            );
> > > > >
> > > > > -  }
> > > > >
> > > > > +  //
> > > > >
> > > > > +  // Call PlatformPci::PrepController() if the protocol is present.
> > > > >
> > > > > +  //
> > > > >
> > > > > +  PciPlatformPreprocessController (
> > > > >
> > > > > +      HostBridgeHandle,
> > > > >
> > > > > +      RootBridgeHandle,
> > > > >
> > > > > +      RootBridgePciAddress,
> > > > >
> > > > > +      Phase,
> > > > >
> > > > > +      ChipsetEntry
> > > > >
> > > > > +    );
> > > > >
> > > > >
> > > > >
> > > > >    Status = PciResAlloc->PreprocessController (
> > > > >
> > > > >                            PciResAlloc,
> > > > >
> > > > > @@ -1947,31 +1889,16 @@ PreprocessController (
> > > > >                            Phase
> > > > >
> > > > >                            );
> > > > >
> > > > >
> > > > >
> > > > > -  if (gPciPlatformProtocol != NULL) {
> > > > >
> > > > > -    //
> > > > >
> > > > > -    // Call PlatformPci::PrepController() if the protocol is present.
> > > > >
> > > > > -    //
> > > > >
> > > > > -    gPciPlatformProtocol->PlatformPrepController (
> > > > >
> > > > > -                            gPciPlatformProtocol,
> > > > >
> > > > > -                            HostBridgeHandle,
> > > > >
> > > > > -                            RootBridgeHandle,
> > > > >
> > > > > -                            RootBridgePciAddress,
> > > > >
> > > > > -                            Phase,
> > > > >
> > > > > -                            ChipsetExit
> > > > >
> > > > > -                            );
> > > > >
> > > > > -  } else if (gPciOverrideProtocol != NULL) {
> > > > >
> > > > > -    //
> > > > >
> > > > > -    // Call PlatformPci::PrepController() if the protocol is present.
> > > > >
> > > > > -    //
> > > > >
> > > > > -    gPciOverrideProtocol->PlatformPrepController (
> > > > >
> > > > > -                            gPciOverrideProtocol,
> > > > >
> > > > > -                            HostBridgeHandle,
> > > > >
> > > > > -                            RootBridgeHandle,
> > > > >
> > > > > -                            RootBridgePciAddress,
> > > > >
> > > > > -                            Phase,
> > > > >
> > > > > -                            ChipsetExit
> > > > >
> > > > > -                            );
> > > > >
> > > > > -  }
> > > > >
> > > > > +  //
> > > > >
> > > > > +  // Call PlatformPci::PrepController() if the protocol is present.
> > > > >
> > > > > +  //
> > > > >
> > > > > +  PciPlatformPreprocessController (
> > > > >
> > > > > +      HostBridgeHandle,
> > > > >
> > > > > +      RootBridgeHandle,
> > > > >
> > > > > +      RootBridgePciAddress,
> > > > >
> > > > > +      Phase,
> > > > >
> > > > > +      ChipsetExit
> > > > >
> > > > > +    );
> > > > >
> > > > >
> > > > >
> > > > >    return EFI_SUCCESS;
> > > > >
> > > > >  }
> > > > >
> > > > > diff --git
> > a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
> > > > > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
> > > > > index c7eafff593..2343702154 100644
> > > > > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
> > > > > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
> > > > > @@ -230,7 +230,7 @@ PciSearchDevice (
> > > > >    PciIoDevice = NULL;
> > > > >
> > > > >
> > > > >
> > > > >    DEBUG ((
> > > > >
> > > > > -    EFI_D_INFO,
> > > > >
> > > > > +    DEBUG_INFO,
> > > > >
> > > > >      "PciBus: Discovered %s @ [%02x|%02x|%02x]\n",
> > > > >
> > > > >      IS_PCI_BRIDGE (Pci) ?     L"PPB" :
> > > > >
> > > > >      IS_CARDBUS_BRIDGE (Pci) ? L"P2C" :
> > > > >
> > > > > @@ -397,7 +397,7 @@ DumpPpbPaddingResource (
> > > > >
> > > > >
> > > > >      if ((Type != PciBarTypeUnknown) && ((ResourceType ==
> > > > > PciBarTypeUnknown) || (ResourceType == Type))) {
> > > > >
> > > > >        DEBUG ((
> > > > >
> > > > > -        EFI_D_INFO,
> > > > >
> > > > > +        DEBUG_INFO,
> > > > >
> > > > >          "   Padding: Type = %s; Alignment = 0x%lx;\tLength = 0x%lx\n",
> > > > >
> > > > >          mBarTypeStr[Type], Descriptor->AddrRangeMax, Descriptor-
> > >AddrLen
> > > > >
> > > > >          ));
> > > > >
> > > > > @@ -424,7 +424,7 @@ DumpPciBars (
> > > > >      }
> > > > >
> > > > >
> > > > >
> > > > >      DEBUG ((
> > > > >
> > > > > -      EFI_D_INFO,
> > > > >
> > > > > +      DEBUG_INFO,
> > > > >
> > > > >        "   BAR[%d]: Type = %s; Alignment = 0x%lx;\tLength = 0x%lx;\tOffset
> > =
> > > > > 0x%02x\n",
> > > > >
> > > > >        Index, mBarTypeStr[MIN (PciIoDevice->PciBar[Index].BarType,
> > > > > PciBarTypeMaxType)],
> > > > >
> > > > >        PciIoDevice->PciBar[Index].Alignment, PciIoDevice-
> > > > > >PciBar[Index].Length, PciIoDevice->PciBar[Index].Offset
> > > > >
> > > > > @@ -437,13 +437,13 @@ DumpPciBars (
> > > > >      }
> > > > >
> > > > >
> > > > >
> > > > >      DEBUG ((
> > > > >
> > > > > -      EFI_D_INFO,
> > > > >
> > > > > +      DEBUG_INFO,
> > > > >
> > > > >        " VFBAR[%d]: Type = %s; Alignment = 0x%lx;\tLength =
> > 0x%lx;\tOffset =
> > > > > 0x%02x\n",
> > > > >
> > > > >        Index, mBarTypeStr[MIN (PciIoDevice->VfPciBar[Index].BarType,
> > > > > PciBarTypeMaxType)],
> > > > >
> > > > >        PciIoDevice->VfPciBar[Index].Alignment, PciIoDevice-
> > > > > >VfPciBar[Index].Length, PciIoDevice->VfPciBar[Index].Offset
> > > > >
> > > > >        ));
> > > > >
> > > > >    }
> > > > >
> > > > > -  DEBUG ((EFI_D_INFO, "\n"));
> > > > >
> > > > > +  DEBUG ((DEBUG_INFO, "\n"));
> > > > >
> > > > >  }
> > > > >
> > > > >
> > > > >
> > > > >  /**
> > > > >
> > > > > @@ -1903,7 +1903,7 @@ PciParseBar (
> > > > >        // Fix the length to support some special 64 bit BAR
> > > > >
> > > > >        //
> > > > >
> > > > >        if (Value == 0) {
> > > > >
> > > > > -        DEBUG ((EFI_D_INFO, "[PciBus]BAR probing for upper 32bit of
> > MEM64
> > > > > BAR returns 0, change to 0xFFFFFFFF.\n"));
> > > > >
> > > > > +        DEBUG ((DEBUG_INFO, "[PciBus]BAR probing for upper 32bit of
> > > > MEM64
> > > > > BAR returns 0, change to 0xFFFFFFFF.\n"));
> > > > >
> > > > >          Value = (UINT32) -1;
> > > > >
> > > > >        } else {
> > > > >
> > > > >          Value |= ((UINT32)(-1) << HighBitSet32 (Value));
> > > > >
> > > > > @@ -2153,7 +2153,17 @@ CreatePciIoDevice (
> > > > >               NULL
> > > > >
> > > > >               );
> > > > >
> > > > >    if (!EFI_ERROR (Status)) {
> > > > >
> > > > > -    PciIoDevice->IsPciExp = TRUE;
> > > > >
> > > > > +  PciIoDevice->IsPciExp = TRUE;
> > > > >
> > > > > +    //
> > > > >
> > > > > +    // read the PCI device's entire PCI Express Capability structure
> > > > >
> > > > > +    //
> > > > >
> > > > > +    PciIo->Pci.Read (
> > > > >
> > > > > +                  PciIo,
> > > > >
> > > > > +                  EfiPciIoWidthUint8,
> > > > >
> > > > > +                  PciIoDevice->PciExpressCapabilityOffset,
> > > > >
> > > > > +                  sizeof (PCI_CAPABILITY_PCIEXP) / sizeof (UINT8),
> > > > >
> > > > > +                  &PciIoDevice->PciExpStruct
> > > > >
> > > > > +                );
> > > > >
> > > > >    }
> > > > >
> > > > >
> > > > >
> > > > >    if (PcdGetBool (PcdAriSupport)) {
> > > > >
> > > > > @@ -2206,7 +2216,7 @@ CreatePciIoDevice (
> > > > >                                &Data32
> > > > >
> > > > >                                );
> > > > >
> > > > >            DEBUG ((
> > > > >
> > > > > -            EFI_D_INFO,
> > > > >
> > > > > +            DEBUG_INFO,
> > > > >
> > > > >              " ARI: forwarding enabled for PPB[%02x:%02x:%02x]\n",
> > > > >
> > > > >              Bridge->BusNumber,
> > > > >
> > > > >              Bridge->DeviceNumber,
> > > > >
> > > > > @@ -2215,7 +2225,7 @@ CreatePciIoDevice (
> > > > >          }
> > > > >
> > > > >        }
> > > > >
> > > > >
> > > > >
> > > > > -      DEBUG ((EFI_D_INFO, " ARI: CapOffset = 0x%x\n", PciIoDevice-
> > > > > >AriCapabilityOffset));
> > > > >
> > > > > +      DEBUG ((DEBUG_INFO, " ARI: CapOffset = 0x%x\n", PciIoDevice-
> > > > > >AriCapabilityOffset));
> > > > >
> > > > >      }
> > > > >
> > > > >    }
> > > > >
> > > > >
> > > > >
> > > > > @@ -2325,12 +2335,12 @@ CreatePciIoDevice (
> > > > >        PciIoDevice->ReservedBusNum = (UINT16)(EFI_PCI_BUS_OF_RID
> > > > (LastVF)
> > > > > - Bus + 1);
> > > > >
> > > > >
> > > > >
> > > > >        DEBUG ((
> > > > >
> > > > > -        EFI_D_INFO,
> > > > >
> > > > > +        DEBUG_INFO,
> > > > >
> > > > >          " SR-IOV: SupportedPageSize = 0x%x; SystemPageSize = 0x%x;
> > > > > FirstVFOffset = 0x%x;\n",
> > > > >
> > > > >          SupportedPageSize, PciIoDevice->SystemPageSize >> 12,
> > FirstVFOffset
> > > > >
> > > > >          ));
> > > > >
> > > > >        DEBUG ((
> > > > >
> > > > > -        EFI_D_INFO,
> > > > >
> > > > > +        DEBUG_INFO,
> > > > >
> > > > >          "         InitialVFs = 0x%x; ReservedBusNum = 0x%x; CapOffset =
> > 0x%x\n",
> > > > >
> > > > >          PciIoDevice->InitialVFs, PciIoDevice->ReservedBusNum,
> > PciIoDevice-
> > > > > >SrIovCapabilityOffset
> > > > >
> > > > >          ));
> > > > >
> > > > > @@ -2345,7 +2355,7 @@ CreatePciIoDevice (
> > > > >                 NULL
> > > > >
> > > > >                 );
> > > > >
> > > > >      if (!EFI_ERROR (Status)) {
> > > > >
> > > > > -      DEBUG ((EFI_D_INFO, " MR-IOV: CapOffset = 0x%x\n", PciIoDevice-
> > > > > >MrIovCapabilityOffset));
> > > > >
> > > > > +      DEBUG ((DEBUG_INFO, " MR-IOV: CapOffset = 0x%x\n",
> > PciIoDevice-
> > > > > >MrIovCapabilityOffset));
> > > > >
> > > > >      }
> > > > >
> > > > >    }
> > > > >
> > > > >
> > > > >
> > > > > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> > > > > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> > > > > new file mode 100644
> > > > > index 0000000000..0819da6536
> > > > > --- /dev/null
> > > > > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> > > > > @@ -0,0 +1,1601 @@
> > > > > +/** @file
> > > > >
> > > > > +  PCI standard feature support functions implementation for PCI Bus
> > > > > module..
> > > > >
> > > > > +
> > > > >
> > > > > +Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> > > > >
> > > > > +SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > >
> > > > > +
> > > > >
> > > > > +**/
> > > > >
> > > > > +
> > > > >
> > > > > +#include "PciFeatureSupport.h"
> > > > >
> > > > > +
> > > > >
> > > > > +/**
> > > > >
> > > > > +  A gobal pointer to PRIMARY_ROOT_PORT_NODE buffer to track all
> > the
> > > > > primary physical
> > > > >
> > > > > +  PCI Root Ports (PCI Controllers) for a given PCI Root Bridge instance
> > while
> > > > >
> > > > > +  enumerating to configure the PCI features
> > > > >
> > > > > +**/
> > > > >
> > > > > +PRIMARY_ROOT_PORT_NODE                      *mPrimaryRootPortList;
> > > > >
> > > > > +
> > > > >
> > > > > +/**
> > > > >
> > > > > +  A gobal pointer to OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > > > buffer
> > > > > all the PCI
> > > > >
> > > > > +  Feature configuration Table nodes to pair against each of the
> > > > > PRIMARY_ROOT_PORT_NODE
> > > > >
> > > > > +  buffer nodes. Each node of these is used to align all the PCI devices
> > > > > originating
> > > > >
> > > > > +  from the PCI Root Port devices of a PCI Root Bridge instance
> > > > >
> > > > > +**/
> > > > >
> > > > > +OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > > > > *mPciFeaturesConfigurationTableInstances;
> > > > >
> > > > > +
> > > > >
> > > > > +/**
> > > > >
> > > > > +  A global pointer to
> > PCI_FEATURE_CONFIGURATION_COMPLETION_LIST,
> > > > > which stores all
> > > > >
> > > > > +  the PCI Root Bridge instances that are enumerated for the other PCI
> > > > > features,
> > > > >
> > > > > +  like MaxPayloadSize & MaxReadReqSize; during the the Start()
> > interface
> > > > of
> > > > > the
> > > > >
> > > > > +  driver binding protocol. The records pointed by this pointer would be
> > > > > destroyed
> > > > >
> > > > > +  when the DXE core invokes the Stop() interface.
> > > > >
> > > > > +**/
> > > > >
> > > > > +PCI_FEATURE_CONFIGURATION_COMPLETION_LIST
> > > > > *mPciFeaturesConfigurationCompletionList = NULL;
> > > > >
> > > > > +
> > > > >
> > > > > +/**
> > > > >
> > > > > +  Main routine to indicate platform selection of any of the other PCI
> > > > features
> > > > >
> > > > > +  to be configured by this driver
> > > > >
> > > > > +
> > > > >
> > > > > +  @retval TRUE    platform has selected the other PCI features to be
> > > > > configured
> > > > >
> > > > > +          FALSE   platform has not selected any of the other PCI features
> > > > >
> > > > > +**/
> > > > >
> > > > > +BOOLEAN
> > > > >
> > > > > +CheckOtherPciFeaturesPcd (
> > > > >
> > > > > +  )
> > > > >
> > > > > +{
> > > > >
> > > > > +  return PcdGet32 ( PcdOtherPciFeatures) ? TRUE : FALSE;
> > > > >
> > > > > +}
> > > > >
> > > > > +
> > > > >
> > > > > +/**
> > > > >
> > > > > +  Main routine to indicate whether the platform has selected the
> > > > > Max_Payload_Size
> > > > >
> > > > > +  PCI feature to be configured by this driver
> > > > >
> > > > > +
> > > > >
> > > > > +  @retval TRUE    platform has selected the Max_Payload_Size to be
> > > > > configured
> > > > >
> > > > > +          FALSE   platform has not selected this feature
> > > > >
> > > > > +**/
> > > > >
> > > > > +BOOLEAN
> > > > >
> > > > > +SetupMaxPayloadSize (
> > > > >
> > > > > +  )
> > > > >
> > > > > +{
> > > > >
> > > > > +  return (PcdGet32 ( PcdOtherPciFeatures) &
> > > > > PCI_FEATURE_SUPPORT_FLAG_MPS) ? TRUE : FALSE;
> > > > >
> > > > > +}
> > > > >
> > > > > +
> > > > >
> > > > > +/**
> > > > >
> > > > > +  Main routine to indicate whether the platform has selected the
> > > > > Max_Read_Req_Size
> > > > >
> > > > > +  PCI feature to be configured by this driver
> > > > >
> > > > > +
> > > > >
> > > > > +  @retval TRUE    platform has selected the Max_Read_Req_Size to be
> > > > > configured
> > > > >
> > > > > +          FALSE   platform has not selected this feature
> > > > >
> > > > > +**/
> > > > >
> > > > > +BOOLEAN
> > > > >
> > > > > +SetupMaxReadReqSize (
> > > > >
> > > > > +  )
> > > > >
> > > > > +{
> > > > >
> > > > > +  return (PcdGet32 ( PcdOtherPciFeatures) &
> > > > > PCI_FEATURE_SUPPORT_FLAG_MRRS) ? TRUE : FALSE;
> > > > >
> > > > > +}
> > > > >
> > > > > +
> > > > >
> > > > > +/**
> > > > >
> > > > > +  Helper routine which determines whether the given PCI Root Bridge
> > > > > instance
> > > > >
> > > > > +  record already exist. This routine shall help avoid duplicate record
> > > > creation
> > > > >
> > > > > +  in case of re-enumeration of PCI configuation features.
> > > > >
> > > > > +
> > > > >
> > > > > +  @param  RootBridge              A pointer to the PCI_IO_DEVICE for the
> > Root
> > > > > Bridge
> > > > >
> > > > > +  @param  PciFeatureConfigRecord  A pointer to a pointer for type
> > > > >
> > > > > +                                  PCI_FEATURE_CONFIGURATION_COMPLETION_LIST
> > > > >
> > > > > +                                  record, Use to return the specific record.
> > > > >
> > > > > +
> > > > >
> > > > > +  @retval TRUE                    Record already exist
> > > > >
> > > > > +          FALSE                   Record does not exist for the given PCI Root
> > Bridge
> > > > >
> > > > > +**/
> > > > >
> > > > > +BOOLEAN
> > > > >
> > > > > +CheckPciFeatureConfigurationRecordExist (
> > > > >
> > > > > +  IN  PCI_IO_DEVICE                             *RootBridge,
> > > > >
> > > > > +  OUT PCI_FEATURE_CONFIGURATION_COMPLETION_LIST
> > > > > **PciFeatureConfigRecord
> > > > >
> > > > > +  )
> > > > >
> > > > > +{
> > > > >
> > > > > +  LIST_ENTRY                                  *Link;
> > > > >
> > > > > +  PCI_FEATURE_CONFIGURATION_COMPLETION_LIST   *Temp;
> > > > >
> > > > > +
> > > > >
> > > > > +  if ( mPciFeaturesConfigurationCompletionList) {
> > > > >
> > > > > +    Link = &mPciFeaturesConfigurationCompletionList->RootBridgeLink;
> > > > >
> > > > > +
> > > > >
> > > > > +    do {
> > > > >
> > > > > +      Temp =
> > > > > PCI_FEATURE_CONFIGURATION_COMPLETION_LIST_FROM_LINK
> > (Link);
> > > > >
> > > > > +      if ( Temp->RootBridgeHandle == RootBridge->Handle) {
> > > > >
> > > > > +        *PciFeatureConfigRecord = Temp;
> > > > >
> > > > > +        return TRUE;
> > > > >
> > > > > +      }
> > > > >
> > > > > +      Link = Link->ForwardLink;
> > > > >
> > > > > +    } while (Link != &mPciFeaturesConfigurationCompletionList-
> > > > > >RootBridgeLink);
> > > > >
> > > > > +  }
> > > > >
> > > > > +  //
> > > > >
> > > > > +  // not found on the PCI feature configuration completion list
> > > > >
> > > > > +  //
> > > > >
> > > > > +  *PciFeatureConfigRecord = NULL;
> > > > >
> > > > > +  return FALSE;
> > > > >
> > > > > +}
> > > > >
> > > > > +
> > > > >
> > > > > +/**
> > > > >
> > > > > +  This routine is primarily to avoid multiple configuration of PCI features
> > > > >
> > > > > +  to the same PCI Root Bridge due to EDK2 core's ConnectController
> > calls
> > > > on
> > > > >
> > > > > +  all the EFI handles. This routine also provide re-enumeration of the
> > PCI
> > > > >
> > > > > +  features on the same PCI Root Bridge based on the policy of
> > > > > ReEnumeratePciFeatureConfiguration
> > > > >
> > > > > +  of the PCI_FEATURE_CONFIGURATION_COMPLETION_LIST.
> > > > >
> > > > > +
> > > > >
> > > > > +  @param  RootBridge              A pointer to the PCI_IO_DEVICE for the
> > Root
> > > > > Bridge
> > > > >
> > > > > +
> > > > >
> > > > > +  @retval TRUE                    PCI Feature configuration required for the PCI
> > > > >
> > > > > +                                  Root Bridge
> > > > >
> > > > > +          FALSE                   PCI Feature configuration is not required to be
> > > > >
> > > > > +                                  re-enumerated for the PCI Root Bridge
> > > > >
> > > > > +**/
> > > > >
> > > > > +BOOLEAN
> > > > >
> > > > > +CheckPciFeaturesConfigurationRequired (
> > > > >
> > > > > +  IN PCI_IO_DEVICE          *RootBridge
> > > > >
> > > > > +  )
> > > > >
> > > > > +{
> > > > >
> > > > > +  LIST_ENTRY                                  *Link;
> > > > >
> > > > > +  PCI_FEATURE_CONFIGURATION_COMPLETION_LIST   *Temp;
> > > > >
> > > > > +
> > > > >
> > > > > +  if ( mPciFeaturesConfigurationCompletionList) {
> > > > >
> > > > > +    Link = &mPciFeaturesConfigurationCompletionList->RootBridgeLink;
> > > > >
> > > > > +
> > > > >
> > > > > +    do {
> > > > >
> > > > > +      Temp =
> > > > > PCI_FEATURE_CONFIGURATION_COMPLETION_LIST_FROM_LINK
> > (Link);
> > > > >
> > > > > +      if ( Temp->RootBridgeHandle == RootBridge->Handle) {
> > > > >
> > > > > +        return Temp->ReEnumeratePciFeatureConfiguration;
> > > > >
> > > > > +      }
> > > > >
> > > > > +      Link = Link->ForwardLink;
> > > > >
> > > > > +    } while (Link != &mPciFeaturesConfigurationCompletionList-
> > > > > >RootBridgeLink);
> > > > >
> > > > > +  }
> > > > >
> > > > > +  //
> > > > >
> > > > > +  // not found on the PCI feature configuration completion list, return
> > as
> > > > > required
> > > > >
> > > > > +  //
> > > > >
> > > > > +  return TRUE;
> > > > >
> > > > > +}
> > > > >
> > > > > +
> > > > >
> > > > > +/**
> > > > >
> > > > > +  This routine finds the duplicate record if exist and assigns the re-
> > > > > enumeration
> > > > >
> > > > > +  requirement flag, as passed as input. It creates new record for the
> > PCI
> > > > > Root
> > > > >
> > > > > +  Bridge and appends the list after updating its re-enumeration flag.
> > > > >
> > > > > +
> > > > >
> > > > > +  @param  RootBridge            A pointer to PCI_IO_DEVICE of the Root
> > > > Bridge
> > > > >
> > > > > +  @param  ReEnumerationRequired A BOOLEAN for recording the re-
> > > > > enumeration requirement
> > > > >
> > > > > +
> > > > >
> > > > > +  @retval EFI_SUCCESS           new record inserted into the list or
> > updated
> > > > the
> > > > >
> > > > > +                                existing record
> > > > >
> > > > > +          EFI_INVALID_PARAMETER Unexpected error as
> > > > > CheckPciFeatureConfigurationRecordExist
> > > > >
> > > > > +                                reports as record exist but does not return its pointer
> > > > >
> > > > > +          EFI_OUT_OF_RESOURCES  Not able to create PCI features
> > > > configuratin
> > > > > complete
> > > > >
> > > > > +                                record for the RootBridge
> > > > >
> > > > > +**/
> > > > >
> > > > > +EFI_STATUS
> > > > >
> > > > > +AddRootBridgeInPciFeaturesConfigCompletionList (
> > > > >
> > > > > +  IN PCI_IO_DEVICE          *RootBridge,
> > > > >
> > > > > +  IN BOOLEAN                ReEnumerationRequired
> > > > >
> > > > > +  )
> > > > >
> > > > > +{
> > > > >
> > > > > +  PCI_FEATURE_CONFIGURATION_COMPLETION_LIST   *Temp;
> > > > >
> > > > > +
> > > > >
> > > > > +  if ( CheckPciFeatureConfigurationRecordExist ( RootBridge, &Temp))
> > {
> > > > >
> > > > > +    //
> > > > >
> > > > > +    // this PCI Root Bridge record already exist; it may have been re-
> > > > > enumerated
> > > > >
> > > > > +    // hence just update its enumeration required flag again to exit
> > > > >
> > > > > +    //
> > > > >
> > > > > +    if ( Temp) {
> > > > >
> > > > > +      Temp->ReEnumeratePciFeatureConfiguration  =
> > > > > ReEnumerationRequired;
> > > > >
> > > > > +      return EFI_SUCCESS;
> > > > >
> > > > > +    } else {
> > > > >
> > > > > +      //
> > > > >
> > > > > +      // PCI feature configuration complete record reported as exist and
> > no
> > > > >
> > > > > +      // record pointer returned
> > > > >
> > > > > +      //
> > > > >
> > > > > +      return EFI_INVALID_PARAMETER;
> > > > >
> > > > > +    }
> > > > >
> > > > > +
> > > > >
> > > > > +  } else {
> > > > >
> > > > > +
> > > > >
> > > > > +    Temp = AllocateZeroPool ( sizeof
> > > > > ( PCI_FEATURE_CONFIGURATION_COMPLETION_LIST));
> > > > >
> > > > > +    if ( !Temp) {
> > > > >
> > > > > +      return EFI_OUT_OF_RESOURCES;
> > > > >
> > > > > +    }
> > > > >
> > > > > +    Temp->Signature                           =
> > > > > PCI_FEATURE_CONFIGURATION_SIGNATURE;
> > > > >
> > > > > +    Temp->RootBridgeHandle                    = RootBridge->Handle;
> > > > >
> > > > > +    Temp->ReEnumeratePciFeatureConfiguration  =
> > > > ReEnumerationRequired;
> > > > >
> > > > > +    if ( mPciFeaturesConfigurationCompletionList) {
> > > > >
> > > > > +      InsertTailList ( &mPciFeaturesConfigurationCompletionList-
> > > > > >RootBridgeLink,
> > > > >
> > > > > +                       &Temp->RootBridgeLink);
> > > > >
> > > > > +    } else {
> > > > >
> > > > > +      //
> > > > >
> > > > > +      // init the very first node of the Root Bridge
> > > > >
> > > > > +      //
> > > > >
> > > > > +      mPciFeaturesConfigurationCompletionList = Temp;
> > > > >
> > > > > +      InitializeListHead ( &mPciFeaturesConfigurationCompletionList-
> > > > > >RootBridgeLink);
> > > > >
> > > > > +    }
> > > > >
> > > > > +  }
> > > > >
> > > > > +  return EFI_SUCCESS;
> > > > >
> > > > > +}
> > > > >
> > > > > +
> > > > >
> > > > > +/**
> > > > >
> > > > > +  Free up memory alloted for the primary physical PCI Root ports of the
> > > > PCI
> > > > > Root
> > > > >
> > > > > +  Bridge instance. Free up all the nodes of type
> > > > > PRIMARY_ROOT_PORT_NODE.
> > > > >
> > > > > +**/
> > > > >
> > > > > +VOID
> > > > >
> > > > > +DestroyPrimaryRootPortNodes ()
> > > > >
> > > > > +{
> > > > >
> > > > > +  LIST_ENTRY                *Link;
> > > > >
> > > > > +  PRIMARY_ROOT_PORT_NODE    *Temp;
> > > > >
> > > > > +
> > > > >
> > > > > +  if ( mPrimaryRootPortList) {
> > > > >
> > > > > +    Link = &mPrimaryRootPortList->NeighborRootPort;
> > > > >
> > > > > +
> > > > >
> > > > > +    if ( IsListEmpty ( Link)) {
> > > > >
> > > > > +      FreePool ( mPrimaryRootPortList);
> > > > >
> > > > > +    } else {
> > > > >
> > > > > +      do {
> > > > >
> > > > > +        if ( Link->ForwardLink != &mPrimaryRootPortList-
> > >NeighborRootPort)
> > > > {
> > > > >
> > > > > +          Link = Link->ForwardLink;
> > > > >
> > > > > +        }
> > > > >
> > > > > +        Temp = PRIMARY_ROOT_PORT_NODE_FROM_LINK ( Link);
> > > > >
> > > > > +        Link = RemoveEntryList ( Link);
> > > > >
> > > > > +        FreePool ( Temp);
> > > > >
> > > > > +      } while ( !IsListEmpty ( Link));
> > > > >
> > > > > +      FreePool ( mPrimaryRootPortList);
> > > > >
> > > > > +    }
> > > > >
> > > > > +    mPrimaryRootPortList = NULL;
> > > > >
> > > > > +  }
> > > > >
> > > > > +}
> > > > >
> > > > > +
> > > > >
> > > > > +/**
> > > > >
> > > > > +  Free up the memory allocated for temporarily maintaining the PCI
> > > > feature
> > > > >
> > > > > +  configuration table for all the nodes of the primary PCI Root port.
> > > > >
> > > > > +  Free up memory alloted for
> > > > > OTHER_PCI_FEATURES_CONFIGURATION_TABLE.
> > > > >
> > > > > +**/
> > > > >
> > > > > +VOID
> > > > >
> > > > > +ErasePciFeaturesConfigurationTable (
> > > > >
> > > > > +  )
> > > > >
> > > > > +{
> > > > >
> > > > > +  if ( mPciFeaturesConfigurationTableInstances) {
> > > > >
> > > > > +    FreePool ( mPciFeaturesConfigurationTableInstances);
> > > > >
> > > > > +  }
> > > > >
> > > > > +  mPciFeaturesConfigurationTableInstances = NULL;
> > > > >
> > > > > +}
> > > > >
> > > > > +
> > > > >
> > > > > +/**
> > > > >
> > > > > +  Routine meant for initializing any global variables used. It primarily
> > cleans
> > > > >
> > > > > +  up the internal data structure memory allocated for the previous PCI
> > > > Root
> > > > > Bridge
> > > > >
> > > > > +  instance. This should be the first routine to call for any virtual PCI
> > Root
> > > > >
> > > > > +  Bridge instance.
> > > > >
> > > > > +**/
> > > > >
> > > > > +VOID
> > > > >
> > > > > +SetupPciFeaturesConfigurationDefaults ()
> > > > >
> > > > > +{
> > > > >
> > > > > +  //
> > > > >
> > > > > +  // delete the primary root port list
> > > > >
> > > > > +  //
> > > > >
> > > > > +  if (mPrimaryRootPortList) {
> > > > >
> > > > > +    DestroyPrimaryRootPortNodes ();
> > > > >
> > > > > +  }
> > > > >
> > > > > +
> > > > >
> > > > > +  if ( mPciFeaturesConfigurationTableInstances) {
> > > > >
> > > > > +    ErasePciFeaturesConfigurationTable ();
> > > > >
> > > > > +  }
> > > > >
> > > > > +}
> > > > >
> > > > > +
> > > > >
> > > > > +/**
> > > > >
> > > > > +  Helper routine to determine whether the PCI device is a physical root
> > > > port
> > > > >
> > > > > +  recorded in the list.
> > > > >
> > > > > +
> > > > >
> > > > > +  @param  PciDevice                       A pointer to the PCI_IO_DEVICE.
> > > > >
> > > > > +
> > > > >
> > > > > +  @retval TRUE                            The PCI device instance is a primary
> > > > >
> > > > > +                                          primary physical PCI Root Port
> > > > >
> > > > > +          FALSE                           Not a primary physical PCI Root port
> > > > >
> > > > > +**/
> > > > >
> > > > > +BOOLEAN
> > > > >
> > > > > +CheckRootBridgePrimaryPort (
> > > > >
> > > > > +  IN PCI_IO_DEVICE          *PciDevice
> > > > >
> > > > > +  )
> > > > >
> > > > > +{
> > > > >
> > > > > +  LIST_ENTRY                *Link;
> > > > >
> > > > > +  PRIMARY_ROOT_PORT_NODE    *Temp;
> > > > >
> > > > > +
> > > > >
> > > > > +  if ( !mPrimaryRootPortList) {
> > > > >
> > > > > +    return FALSE;
> > > > >
> > > > > +  }
> > > > >
> > > > > +  Link = &mPrimaryRootPortList->NeighborRootPort;
> > > > >
> > > > > +  do {
> > > > >
> > > > > +    Temp = PRIMARY_ROOT_PORT_NODE_FROM_LINK ( Link);
> > > > >
> > > > > +    if ( Temp->RootBridgeHandle == PciDevice->Parent->Handle
> > > > >
> > > > > +        && Temp->RootPortHandle == PciDevice->Handle) {
> > > > >
> > > > > +      //
> > > > >
> > > > > +      // the given PCI device is the primary root port of the Root Bridge
> > > > > controller
> > > > >
> > > > > +      //
> > > > >
> > > > > +      return TRUE;
> > > > >
> > > > > +    }
> > > > >
> > > > > +    Link = Link->ForwardLink;
> > > > >
> > > > > +  } while ( Link != &mPrimaryRootPortList->NeighborRootPort);
> > > > >
> > > > > +  //
> > > > >
> > > > > +  // the given PCI device is not the primary root port of the Bridge
> > > > controller
> > > > >
> > > > > +  //
> > > > >
> > > > > +  return FALSE;
> > > > >
> > > > > +}
> > > > >
> > > > > +
> > > > >
> > > > > +/**
> > > > >
> > > > > +  Main routine to determine the child PCI devices of a physical PCI
> > bridge
> > > > > device
> > > > >
> > > > > +  and group them under a common internal PCI features Configuration
> > > > table.
> > > > >
> > > > > +
> > > > >
> > > > > +  @param  PciDevice                       A pointer to the PCI_IO_DEVICE.
> > > > >
> > > > > +  @param  PciFeaturesConfigTable          A pointer to a pointer to the
> > > > >
> > > > > +
> OTHER_PCI_FEATURES_CONFIGURATION_TABLE.
> > > > >
> > > > > +                                          Returns NULL in case of RCiEP or the PCI
> > > > >
> > > > > +                                          device does match with any of the physical
> > > > >
> > > > > +                                          Root ports, or it does not belong to any
> > > > >
> > > > > +                                          Root port's PCU bus range (not a child)
> > > > >
> > > > > +
> > > > >
> > > > > +  @retval EFI_SUCCESS                     able to determine the PCI feature
> > > > >
> > > > > +                                          configuration table. For RCiEP since
> > > > >
> > > > > +                                          since it is not prepared.
> > > > >
> > > > > +          EFI_NOT_FOUND                   the PCI feature configuration table
> > does
> > > > >
> > > > > +                                          not exist as the PCI physical Bridge device
> > > > >
> > > > > +                                          is not found for this device's parent
> > > > >
> > > > > +                                          Root Bridge instance
> > > > >
> > > > > +**/
> > > > >
> > > > > +EFI_STATUS
> > > > >
> > > > > +GetPciFeaturesConfigurationTable (
> > > > >
> > > > > +  IN  PCI_IO_DEVICE                           *PciDevice,
> > > > >
> > > > > +  OUT OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > > > > **PciFeaturesConfigTable
> > > > >
> > > > > +  )
> > > > >
> > > > > +{
> > > > >
> > > > > +  LIST_ENTRY                *Link;
> > > > >
> > > > > +  PRIMARY_ROOT_PORT_NODE    *Temp;
> > > > >
> > > > > +
> > > > >
> > > > > +  if ( !mPrimaryRootPortList) {
> > > > >
> > > > > +    *PciFeaturesConfigTable = NULL;
> > > > >
> > > > > +    return EFI_NOT_FOUND;
> > > > >
> > > > > +  }
> > > > >
> > > > > +
> > > > >
> > > > > +  //
> > > > >
> > > > > +  // The PCI features configuration table is not built for RCiEP, return
> > NULL
> > > > >
> > > > > +  //
> > > > >
> > > > > +  if ( PciDevice->PciExpStruct.Capability.Bits.DevicePortType == \
> > > > >
> > > > > +
> > PCIE_DEVICE_PORT_TYPE_ROOT_COMPLEX_INTEGRATED_ENDPOINT)
> > > > > {
> > > > >
> > > > > +    *PciFeaturesConfigTable = NULL;
> > > > >
> > > > > +    return EFI_SUCCESS;
> > > > >
> > > > > +  }
> > > > >
> > > > > +
> > > > >
> > > > > +  Link = &mPrimaryRootPortList->NeighborRootPort;
> > > > >
> > > > > +  do {
> > > > >
> > > > > +    Temp = PRIMARY_ROOT_PORT_NODE_FROM_LINK ( Link);
> > > > >
> > > > > +    if ( Temp->RootBridgeHandle == PciDevice->Parent->Handle
> > > > >
> > > > > +        && Temp->RootPortHandle == PciDevice->Handle) {
> > > > >
> > > > > +      //
> > > > >
> > > > > +      // the given PCI device is the primary root port of the Root Bridge
> > > > > controller
> > > > >
> > > > > +      //
> > > > >
> > > > > +      *PciFeaturesConfigTable = Temp-
> > > > >OtherPciFeaturesConfigurationTable;
> > > > >
> > > > > +      return EFI_SUCCESS;
> > > > >
> > > > > +    } else {
> > > > >
> > > > > +      //
> > > > >
> > > > > +      // check this PCI device belongs to the primary root port of the root
> > > > > bridge
> > > > >
> > > > > +      //
> > > > >
> > > > > +      if ( PciDevice->BusNumber >= Temp->SecondaryBusStart
> > > > >
> > > > > +          && PciDevice->BusNumber <= Temp->SecondaryBusEnd) {
> > > > >
> > > > > +        *PciFeaturesConfigTable = Temp-
> > > > >OtherPciFeaturesConfigurationTable;
> > > > >
> > > > > +        return EFI_SUCCESS;
> > > > >
> > > > > +      }
> > > > >
> > > > > +    }
> > > > >
> > > > > +    Link = Link->ForwardLink;
> > > > >
> > > > > +  } while ( Link != &mPrimaryRootPortList->NeighborRootPort);
> > > > >
> > > > > +  //
> > > > >
> > > > > +  // the PCI device must be RCiEP, does not belong to any primary root
> > > > port
> > > > >
> > > > > +  //
> > > > >
> > > > > +  *PciFeaturesConfigTable = NULL;
> > > > >
> > > > > +  return EFI_SUCCESS;
> > > > >
> > > > > +}
> > > > >
> > > > > +
> > > > >
> > > > > +/**
> > > > >
> > > > > +  The helper routine to retrieve the PCI bus numbers from the PCI
> > Bridge
> > > > or
> > > > > Root
> > > > >
> > > > > +  port device. Assumes the input PCI device has the PCI Type 1
> > > > configuration
> > > > > header.
> > > > >
> > > > > +
> > > > >
> > > > > +  @param  PciDevice                       A pointer to the PCI_IO_DEVICE.
> > > > >
> > > > > +  @param  PrimaryBusNumber                A pointer to return the PCI
> > Priamry
> > > > >
> > > > > +                                          Bus number.
> > > > >
> > > > > +  @param  SecondaryBusNumber              A pointer to return the PCI
> > > > > Secondary
> > > > >
> > > > > +                                          Bus number.
> > > > >
> > > > > +  @param  SubordinateBusNumber            A pointer to return the PCI
> > > > > Subordinate
> > > > >
> > > > > +                                          Bus number.
> > > > >
> > > > > +
> > > > >
> > > > > +  @retval EFI_SUCCESS           The data was read from the PCI device.
> > > > >
> > > > > +  @retval EFI_UNSUPPORTED       The address range specified by Offset,
> > > > > Width, and Count is not
> > > > >
> > > > > +                                valid for the PCI configuration header of the PCI
> device.
> > > > >
> > > > > +  @retval EFI_INVALID_PARAMETER input parameters provided to the
> > > > read
> > > > > operation were invalid.
> > > > >
> > > > > +**/
> > > > >
> > > > > +EFI_STATUS
> > > > >
> > > > > +GetPciRootPortBusAssigned (
> > > > >
> > > > > +  IN  PCI_IO_DEVICE                           *PciDevice,
> > > > >
> > > > > +  OUT UINT8                                   *PrimaryBusNumber,
> > > > >
> > > > > +  OUT UINT8                                   *SecondaryBusNumber,
> > > > >
> > > > > +  OUT UINT8                                   *SubordinateBusNumber
> > > > >
> > > > > +  )
> > > > >
> > > > > +{
> > > > >
> > > > > +  EFI_STATUS                                  Status;
> > > > >
> > > > > +  UINT32                                      RootPortBusAssigned;
> > > > >
> > > > > +
> > > > >
> > > > > +  Status = PciDevice->PciIo.Pci.Read (
> > > > >
> > > > > +                                  &PciDevice->PciIo,
> > > > >
> > > > > +                                  EfiPciIoWidthUint32,
> > > > >
> > > > > +                                  PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET,
> > > > >
> > > > > +                                  1,
> > > > >
> > > > > +                                  &RootPortBusAssigned
> > > > >
> > > > > +                                );
> > > > >
> > > > > +  if ( !EFI_ERROR(Status)) {
> > > > >
> > > > > +    if ( PrimaryBusNumber) {
> > > > >
> > > > > +      *PrimaryBusNumber = (UINT8) (0xFF & RootPortBusAssigned);
> > > > >
> > > > > +    }
> > > > >
> > > > > +    if ( SecondaryBusNumber) {
> > > > >
> > > > > +      *SecondaryBusNumber = (UINT8)(0xFF & (RootPortBusAssigned >>
> > 8));
> > > > >
> > > > > +    }
> > > > >
> > > > > +    if ( SubordinateBusNumber) {
> > > > >
> > > > > +      *SubordinateBusNumber = (UINT8)(0xFF &
> > (RootPortBusAssigned >>
> > > > > 16));
> > > > >
> > > > > +    }
> > > > >
> > > > > +  }
> > > > >
> > > > > +  return Status;
> > > > >
> > > > > +}
> > > > >
> > > > > +
> > > > >
> > > > > +/**
> > > > >
> > > > > +  This routine determines the existance of the child PCI device for the
> > > > given
> > > > >
> > > > > +  PCI Root / Bridge Port device. Always assumes the input PCI device is
> > the
> > > > > bridge
> > > > >
> > > > > +  or PCI-PCI Bridge device. This routine should not be used with PCI
> > > > > endpoint device.
> > > > >
> > > > > +
> > > > >
> > > > > +  @param  PciDevice                       A pointer to the PCI_IO_DEVICE.
> > > > >
> > > > > +
> > > > >
> > > > > +  @retval TRUE                            child device exist
> > > > >
> > > > > +          FALSE                           no child device
> > > > >
> > > > > +**/
> > > > >
> > > > > +BOOLEAN
> > > > >
> > > > > +IsPciRootPortEmpty (
> > > > >
> > > > > +  IN  PCI_IO_DEVICE                           *PciDevice
> > > > >
> > > > > +  )
> > > > >
> > > > > +{
> > > > >
> > > > > +  UINT8                                       SecBus,
> > > > >
> > > > > +                                              SubBus;
> > > > >
> > > > > +  EFI_STATUS                                  Status;
> > > > >
> > > > > +  LIST_ENTRY                                  *Link;
> > > > >
> > > > > +  PCI_IO_DEVICE                               *NextPciDevice;
> > > > >
> > > > > +
> > > > >
> > > > > +  //
> > > > >
> > > > > +  // check secondary & suboridinate bus numbers for its endpoint
> > device
> > > > >
> > > > > +  // existance
> > > > >
> > > > > +  //
> > > > >
> > > > > +  Status = GetPciRootPortBusAssigned ( PciDevice, NULL, &SecBus,
> > > > > &SubBus);
> > > > >
> > > > > +  if ( !EFI_ERROR( Status)) {
> > > > >
> > > > > +    Link = PciDevice->ChildList.ForwardLink;
> > > > >
> > > > > +    if ( IsListEmpty ( Link)) {
> > > > >
> > > > > +      //
> > > > >
> > > > > +      // return as PCI Root port empty
> > > > >
> > > > > +      //
> > > > >
> > > > > +      DEBUG (( DEBUG_INFO, "RP empty,"));
> > > > >
> > > > > +      return TRUE;
> > > > >
> > > > > +    }
> > > > >
> > > > > +    do {
> > > > >
> > > > > +      NextPciDevice = PCI_IO_DEVICE_FROM_LINK ( Link);
> > > > >
> > > > > +      DEBUG (( DEBUG_INFO, "dev@%x", NextPciDevice->BusNumber));
> > > > >
> > > > > +
> > > > >
> > > > > +      if ( NextPciDevice->BusNumber >= SecBus
> > > > >
> > > > > +          && NextPciDevice->BusNumber <= SubBus) {
> > > > >
> > > > > +
> > > > >
> > > > > +        return FALSE;
> > > > >
> > > > > +      }
> > > > >
> > > > > +
> > > > >
> > > > > +      Link = Link->ForwardLink;
> > > > >
> > > > > +    } while ( Link != &PciDevice->ChildList);
> > > > >
> > > > > +  } else {
> > > > >
> > > > > +    SecBus = SubBus = 0;
> > > > >
> > > > > +    DEBUG (( DEBUG_ERROR, "unable to retrieve root port's bus range
> > > > > assigned!!!"));
> > > > >
> > > > > +  }
> > > > >
> > > > > +
> > > > >
> > > > > +  //
> > > > >
> > > > > +  // return as PCI Root port empty
> > > > >
> > > > > +  //
> > > > >
> > > > > +  return TRUE;
> > > > >
> > > > > +}
> > > > >
> > > > > +
> > > > >
> > > > > +/**
> > > > >
> > > > > +  The main routine which process the PCI feature Max_Payload_Size as
> > > > per
> > > > > the
> > > > >
> > > > > +  device-specific platform policy, as well as in complaince with the PCI
> > Base
> > > > >
> > > > > +  specification Revision 4, that aligns the value for the entire PCI
> > heirarchy
> > > > >
> > > > > +  starting from its physical PCI Root port / Bridge device.
> > > > >
> > > > > +
> > > > >
> > > > > +  @param PciDevice                      A pointer to the PCI_IO_DEVICE.
> > > > >
> > > > > +  @param PciConfigPhase                 for the PCI feature configuration
> > phases:
> > > > >
> > > > > +                                        PciFeatureGetDevicePolicy &
> > PciFeatureSetupPhase
> > > > >
> > > > > +  @param PciFeaturesConfigurationTable  pointer to
> > > > > OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > > > >
> > > > > +
> > > > >
> > > > > +  @retval EFI_SUCCESS                   processing of PCI feature
> > > > > Max_Payload_Size
> > > > >
> > > > > +                                        is successful.
> > > > >
> > > > > +**/
> > > > >
> > > > > +EFI_STATUS
> > > > >
> > > > > +ProcessMaxPayloadSize (
> > > > >
> > > > > +  IN  PCI_IO_DEVICE                           *PciDevice,
> > > > >
> > > > > +  IN  PCI_FEATURE_CONFIGURATION_PHASE         PciConfigPhase,
> > > > >
> > > > > +  IN  OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > > > > *PciFeaturesConfigurationTable
> > > > >
> > > > > +  )
> > > > >
> > > > > +{
> > > > >
> > > > > +  PCI_REG_PCIE_DEVICE_CAPABILITY          PciDeviceCap;
> > > > >
> > > > > +  UINT8                                   MpsValue;
> > > > >
> > > > > +
> > > > >
> > > > > +
> > > > >
> > > > > +  PciDeviceCap.Uint32 = PciDevice-
> > >PciExpStruct.DeviceCapability.Uint32;
> > > > >
> > > > > +
> > > > >
> > > > > +  if ( PciConfigPhase == PciFeatureGetDevicePolicy) {
> > > > >
> > > > > +    if ( SetupMpsAsPerDeviceCapability ( PciDevice->SetupMPS))
> > > > >
> > > > > +    {
> > > > >
> > > > > +      MpsValue = (UINT8)PciDeviceCap.Bits.MaxPayloadSize;
> > > > >
> > > > > +      //
> > > > >
> > > > > +      // no change to PCI Root ports without any endpoint device
> > > > >
> > > > > +      //
> > > > >
> > > > > +      if ( IS_PCI_BRIDGE ( &PciDevice->Pci) &&
> > > > > PciDeviceCap.Bits.MaxPayloadSize) {
> > > > >
> > > > > +        if ( IsPciRootPortEmpty ( PciDevice)) {
> > > > >
> > > > > +          MpsValue = PCIE_MAX_PAYLOAD_SIZE_128B;
> > > > >
> > > > > +          DEBUG (( DEBUG_INFO, "(reset RP MPS to min.)"));
> > > > >
> > > > > +        }
> > > > >
> > > > > +      }
> > > > >
> > > > > +    } else {
> > > > >
> > > > > +      MpsValue = TranslateMpsSetupValueToPci ( PciDevice-
> > >SetupMPS);
> > > > >
> > > > > +    }
> > > > >
> > > > > +    //
> > > > >
> > > > > +    // discard device policy override request if greater than PCI device
> > > > > capability
> > > > >
> > > > > +    //
> > > > >
> > > > > +    PciDevice->SetupMPS =
> > > > MIN( (UINT8)PciDeviceCap.Bits.MaxPayloadSize,
> > > > > MpsValue);
> > > > >
> > > > > +  }
> > > > >
> > > > > +
> > > > >
> > > > > +  //
> > > > >
> > > > > +  // align the MPS of the tree to the HCF with this device
> > > > >
> > > > > +  //
> > > > >
> > > > > +  if ( PciFeaturesConfigurationTable) {
> > > > >
> > > > > +    MpsValue = PciFeaturesConfigurationTable->Max_Payload_Size;
> > > > >
> > > > > +
> > > > >
> > > > > +    MpsValue = MIN ( PciDevice->SetupMPS, MpsValue);
> > > > >
> > > > > +    PciDevice->SetupMPS = MIN ( PciDevice->SetupMPS, MpsValue);
> > > > >
> > > > > +
> > > > >
> > > > > +    if ( MpsValue != PciFeaturesConfigurationTable->Max_Payload_Size)
> > {
> > > > >
> > > > > +      DEBUG (( DEBUG_INFO, "reset MPS of the tree to %d,",
> > MpsValue));
> > > > >
> > > > > +      PciFeaturesConfigurationTable->Max_Payload_Size = MpsValue;
> > > > >
> > > > > +    }
> > > > >
> > > > > +  }
> > > > >
> > > > > +
> > > > >
> > > > > +  DEBUG (( DEBUG_INFO,
> > > > >
> > > > > +      "Max_Payload_Size: %d [DevCap:%d],",
> > > > >
> > > > > +      PciDevice->SetupMPS, PciDeviceCap.Bits.MaxPayloadSize
> > > > >
> > > > > +  ));
> > > > >
> > > > > +  return EFI_SUCCESS;
> > > > >
> > > > > +}
> > > > >
> > > > > +
> > > > >
> > > > > +/**
> > > > >
> > > > > +  The main routine which process the PCI feature Max_Read_Req_Size
> > as
> > > > > per the
> > > > >
> > > > > +  device-specific platform policy, as well as in complaince with the PCI
> > Base
> > > > >
> > > > > +  specification Revision 4, that aligns the value for the entire PCI
> > heirarchy
> > > > >
> > > > > +  starting from its physical PCI Root port / Bridge device.
> > > > >
> > > > > +
> > > > >
> > > > > +  @param PciDevice                      A pointer to the PCI_IO_DEVICE.
> > > > >
> > > > > +  @param PciConfigPhase                 for the PCI feature configuration
> > phases:
> > > > >
> > > > > +                                        PciFeatureGetDevicePolicy &
> > PciFeatureSetupPhase
> > > > >
> > > > > +  @param PciFeaturesConfigurationTable  pointer to
> > > > > OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > > > >
> > > > > +
> > > > >
> > > > > +  @retval EFI_SUCCESS                   processing of PCI feature
> > > > > Max_Read_Req_Size
> > > > >
> > > > > +                                        is successful.
> > > > >
> > > > > +**/
> > > > >
> > > > > +EFI_STATUS
> > > > >
> > > > > +ProcessMaxReadReqSize (
> > > > >
> > > > > +  IN  PCI_IO_DEVICE                           *PciDevice,
> > > > >
> > > > > +  IN  PCI_FEATURE_CONFIGURATION_PHASE         PciConfigPhase,
> > > > >
> > > > > +  IN  OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > > > > *PciFeaturesConfigurationTable
> > > > >
> > > > > +  )
> > > > >
> > > > > +{
> > > > >
> > > > > +  PCI_REG_PCIE_DEVICE_CAPABILITY  PciDeviceCap;
> > > > >
> > > > > +  UINT8                           MrrsValue;
> > > > >
> > > > > +
> > > > >
> > > > > +  PciDeviceCap.Uint32 = PciDevice-
> > >PciExpStruct.DeviceCapability.Uint32;
> > > > >
> > > > > +
> > > > >
> > > > > +  if ( PciConfigPhase == PciFeatureGetDevicePolicy) {
> > > > >
> > > > > +    if ( SetupMrrsAsPerDeviceCapability ( PciDevice->SetupMRRS))
> > > > >
> > > > > +    {
> > > > >
> > > > > +      //
> > > > >
> > > > > +      // The maximum read request size is not the data packet size of the
> > > > TLP,
> > > > >
> > > > > +      // but the memory read request size, and set to the function as a
> > > > > requestor
> > > > >
> > > > > +      // to not exceed this limit.
> > > > >
> > > > > +      // However, for the PCI device capable of isochronous traffic; this
> > > > > memory read
> > > > >
> > > > > +      // request size should not extend beyond the Max_Payload_Size.
> > Thus,
> > > > > in case if
> > > > >
> > > > > +      // device policy return by platform indicates to set as per device
> > > > > capability
> > > > >
> > > > > +      // than set as per Max_Payload_Size configuration value
> > > > >
> > > > > +      //
> > > > >
> > > > > +      if ( SetupMaxPayloadSize()) {
> > > > >
> > > > > +        MrrsValue = PciDevice->SetupMPS;
> > > > >
> > > > > +      } else {
> > > > >
> > > > > +        //
> > > > >
> > > > > +        // in case this driver is not required to configure the
> > > > Max_Payload_Size
> > > > >
> > > > > +        // than consider programming HCF of the device capability's
> > > > > Max_Payload_Size
> > > > >
> > > > > +        // in this PCI hierarchy; thus making this an implementation
> > specific
> > > > > feature
> > > > >
> > > > > +        // which the platform should avoid. For better results, the
> > platform
> > > > > should
> > > > >
> > > > > +        // make both the Max_Payload_Size & Max_Read_Request_Size
> > to
> > > > be
> > > > > configured
> > > > >
> > > > > +        // by this driver
> > > > >
> > > > > +        //
> > > > >
> > > > > +        MrrsValue = (UINT8)PciDeviceCap.Bits.MaxPayloadSize;
> > > > >
> > > > > +      }
> > > > >
> > > > > +    } else {
> > > > >
> > > > > +      //
> > > > >
> > > > > +      // override as per platform based device policy
> > > > >
> > > > > +      //
> > > > >
> > > > > +      MrrsValue = TranslateMrrsSetupValueToPci ( PciDevice-
> > >SetupMRRS);
> > > > >
> > > > > +      //
> > > > >
> > > > > +      // align this device's Max_Read_Request_Size value to the entire
> > PCI
> > > > > tree
> > > > >
> > > > > +      //
> > > > >
> > > > > +      if ( PciFeaturesConfigurationTable) {
> > > > >
> > > > > +        if ( !PciFeaturesConfigurationTable-
> > >Lock_Max_Read_Request_Size)
> > > > {
> > > > >
> > > > > +          PciFeaturesConfigurationTable->Lock_Max_Read_Request_Size
> > =
> > > > > TRUE;
> > > > >
> > > > > +          PciFeaturesConfigurationTable->Max_Read_Request_Size =
> > > > > MrrsValue;
> > > > >
> > > > > +        } else {
> > > > >
> > > > > +          //
> > > > >
> > > > > +          // in case of another user enforced value of MRRS within the
> > same
> > > > > tree,
> > > > >
> > > > > +          // pick the smallest between the locked value and this value; to
> > set
> > > > >
> > > > > +          // across entire PCI tree nodes
> > > > >
> > > > > +          //
> > > > >
> > > > > +          MrrsValue = MIN (
> > > > >
> > > > > +                        MrrsValue,
> > > > >
> > > > > +                        PciFeaturesConfigurationTable->Max_Read_Request_Size
> > > > >
> > > > > +                        );
> > > > >
> > > > > +          PciFeaturesConfigurationTable->Max_Read_Request_Size =
> > > > > MrrsValue;
> > > > >
> > > > > +        }
> > > > >
> > > > > +      }
> > > > >
> > > > > +    }
> > > > >
> > > > > +    //
> > > > >
> > > > > +    // align this device's Max_Read_Request_Size to derived
> > configuration
> > > > > value
> > > > >
> > > > > +    //
> > > > >
> > > > > +    PciDevice->SetupMRRS = MrrsValue;
> > > > >
> > > > > +
> > > > >
> > > > > +  }
> > > > >
> > > > > +
> > > > >
> > > > > +  //
> > > > >
> > > > > +  // align the Max_Read_Request_Size of the PCI tree based on 3
> > > > conditions:
> > > > >
> > > > > +  // first, if user defines MRRS for any one PCI device in the tree than
> > align
> > > > >
> > > > > +  // all the devices in the PCI tree.
> > > > >
> > > > > +  // second, if user override is not define for this PCI tree than setup
> > the
> > > > > MRRS
> > > > >
> > > > > +  // based on MPS value of the tree to meet the criteria for the
> > > > isochronous
> > > > >
> > > > > +  // traffic.
> > > > >
> > > > > +  // third, if no user override, or platform firmware policy has not
> > selected
> > > > >
> > > > > +  // this PCI bus driver to configure the MPS; than configure the MRRS
> > to a
> > > > >
> > > > > +  // highest common value of PCI device capability for the MPS found
> > > > among
> > > > > all
> > > > >
> > > > > +  // the PCI devices in this tree
> > > > >
> > > > > +  //
> > > > >
> > > > > +  if ( PciFeaturesConfigurationTable) {
> > > > >
> > > > > +    if ( PciFeaturesConfigurationTable->Lock_Max_Read_Request_Size)
> > {
> > > > >
> > > > > +      PciDevice->SetupMRRS = PciFeaturesConfigurationTable-
> > > > > >Max_Read_Request_Size;
> > > > >
> > > > > +    } else {
> > > > >
> > > > > +      if ( SetupMaxPayloadSize()) {
> > > > >
> > > > > +        PciDevice->SetupMRRS = PciDevice->SetupMPS;
> > > > >
> > > > > +      } else {
> > > > >
> > > > > +        PciDevice->SetupMRRS = MIN (
> > > > >
> > > > > +                                PciDevice->SetupMRRS,
> > > > >
> > > > > +                                PciFeaturesConfigurationTable-
> > > > >Max_Read_Request_Size
> > > > >
> > > > > +                                );
> > > > >
> > > > > +      }
> > > > >
> > > > > +      PciFeaturesConfigurationTable->Max_Read_Request_Size =
> > > > PciDevice-
> > > > > >SetupMRRS;
> > > > >
> > > > > +    }
> > > > >
> > > > > +  }
> > > > >
> > > > > +  DEBUG (( DEBUG_INFO, "Max_Read_Request_Size: %d\n",
> > PciDevice-
> > > > > >SetupMRRS));
> > > > >
> > > > > +
> > > > >
> > > > > +  return EFI_SUCCESS;
> > > > >
> > > > > +}
> > > > >
> > > > > +
> > > > >
> > > > > +/**
> > > > >
> > > > > +  Overrides the PCI Device Control register MaxPayloadSize register
> > field;
> > > > if
> > > > >
> > > > > +  the hardware value is different than the intended value.
> > > > >
> > > > > +
> > > > >
> > > > > +  @param  PciDevice             A pointer to the PCI_IO_DEVICE instance.
> > > > >
> > > > > +
> > > > >
> > > > > +  @retval EFI_SUCCESS           The data was read from or written to the
> > PCI
> > > > > device.
> > > > >
> > > > > +  @retval EFI_UNSUPPORTED       The address range specified by Offset,
> > > > > Width, and Count is not
> > > > >
> > > > > +                                valid for the PCI configuration header of the PCI
> > > controller.
> > > > >
> > > > > +  @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid.
> > > > >
> > > > > +
> > > > >
> > > > > +**/
> > > > >
> > > > > +EFI_STATUS
> > > > >
> > > > > +OverrideMaxPayloadSize (
> > > > >
> > > > > +  IN PCI_IO_DEVICE          *PciDevice
> > > > >
> > > > > +  )
> > > > >
> > > > > +{
> > > > >
> > > > > +  PCI_REG_PCIE_DEVICE_CONTROL PcieDev;
> > > > >
> > > > > +  UINT32                      Offset;
> > > > >
> > > > > +  EFI_STATUS                  Status;
> > > > >
> > > > > +
> > > > >
> > > > > +  PcieDev.Uint16 = 0;
> > > > >
> > > > > +  Offset = PciDevice->PciExpressCapabilityOffset +
> > > > >
> > > > > +               OFFSET_OF (PCI_CAPABILITY_PCIEXP, DeviceControl);
> > > > >
> > > > > +  Status = PciDevice->PciIo.Pci.Read (
> > > > >
> > > > > +                                  &PciDevice->PciIo,
> > > > >
> > > > > +                                  EfiPciIoWidthUint16,
> > > > >
> > > > > +                                  Offset,
> > > > >
> > > > > +                                  1,
> > > > >
> > > > > +                                  &PcieDev.Uint16
> > > > >
> > > > > +                                );
> > > > >
> > > > > +  if ( EFI_ERROR(Status)){
> > > > >
> > > > > +    DEBUG (( DEBUG_ERROR, "Unexpected DeviceControl register
> > (0x%x)
> > > > > read error!",
> > > > >
> > > > > +        Offset
> > > > >
> > > > > +    ));
> > > > >
> > > > > +    return Status;
> > > > >
> > > > > +  }
> > > > >
> > > > > +  if ( PcieDev.Bits.MaxPayloadSize != PciDevice->SetupMPS) {
> > > > >
> > > > > +    PcieDev.Bits.MaxPayloadSize = PciDevice->SetupMPS;
> > > > >
> > > > > +    DEBUG (( DEBUG_INFO, "Max_Payload_Size=%d,", PciDevice-
> > > > > >SetupMPS));
> > > > >
> > > > > +
> > > > >
> > > > > +    Status = PciDevice->PciIo.Pci.Write (
> > > > >
> > > > > +                                    &PciDevice->PciIo,
> > > > >
> > > > > +                                    EfiPciIoWidthUint16,
> > > > >
> > > > > +                                    Offset,
> > > > >
> > > > > +                                    1,
> > > > >
> > > > > +                                    &PcieDev.Uint16
> > > > >
> > > > > +                                  );
> > > > >
> > > > > +    if ( !EFI_ERROR(Status)) {
> > > > >
> > > > > +      PciDevice->PciExpStruct.DeviceControl.Uint16 = PcieDev.Uint16;
> > > > >
> > > > > +    } else {
> > > > >
> > > > > +      DEBUG (( DEBUG_ERROR, "Unexpected DeviceControl register
> > (0x%x)
> > > > > write error!",
> > > > >
> > > > > +          Offset
> > > > >
> > > > > +      ));
> > > > >
> > > > > +    }
> > > > >
> > > > > +  } else {
> > > > >
> > > > > +    DEBUG (( DEBUG_INFO, "No write of Max_Payload_Size=%d,",
> > > > PciDevice-
> > > > > >SetupMPS));
> > > > >
> > > > > +  }
> > > > >
> > > > > +
> > > > >
> > > > > +  return Status;
> > > > >
> > > > > +}
> > > > >
> > > > > +
> > > > >
> > > > > +/**
> > > > >
> > > > > +  Overrides the PCI Device Control register MaxPayloadSize register
> > field;
> > > > if
> > > > >
> > > > > +  the hardware value is different than the intended value.
> > > > >
> > > > > +
> > > > >
> > > > > +  @param  PciDevice             A pointer to the PCI_IO_DEVICE instance.
> > > > >
> > > > > +
> > > > >
> > > > > +  @retval EFI_SUCCESS           The data was read from or written to the
> > PCI
> > > > > controller.
> > > > >
> > > > > +  @retval EFI_UNSUPPORTED       The address range specified by Offset,
> > > > > Width, and Count is not
> > > > >
> > > > > +                                valid for the PCI configuration header of the PCI
> > > controller.
> > > > >
> > > > > +  @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid.
> > > > >
> > > > > +
> > > > >
> > > > > +**/
> > > > >
> > > > > +EFI_STATUS
> > > > >
> > > > > +OverrideMaxReadReqSize (
> > > > >
> > > > > +  IN PCI_IO_DEVICE          *PciDevice
> > > > >
> > > > > +  )
> > > > >
> > > > > +{
> > > > >
> > > > > +  PCI_REG_PCIE_DEVICE_CONTROL PcieDev;
> > > > >
> > > > > +  UINT32                      Offset;
> > > > >
> > > > > +  EFI_STATUS                  Status;
> > > > >
> > > > > +
> > > > >
> > > > > +  PcieDev.Uint16 = 0;
> > > > >
> > > > > +  Offset = PciDevice->PciExpressCapabilityOffset +
> > > > >
> > > > > +               OFFSET_OF (PCI_CAPABILITY_PCIEXP, DeviceControl);
> > > > >
> > > > > +  Status = PciDevice->PciIo.Pci.Read (
> > > > >
> > > > > +                                  &PciDevice->PciIo,
> > > > >
> > > > > +                                  EfiPciIoWidthUint16,
> > > > >
> > > > > +                                  Offset,
> > > > >
> > > > > +                                  1,
> > > > >
> > > > > +                                  &PcieDev.Uint16
> > > > >
> > > > > +                                );
> > > > >
> > > > > +  if ( EFI_ERROR(Status)){
> > > > >
> > > > > +    DEBUG (( DEBUG_ERROR, "Unexpected DeviceControl register
> > (0x%x)
> > > > > read error!",
> > > > >
> > > > > +        Offset
> > > > >
> > > > > +    ));
> > > > >
> > > > > +    return Status;
> > > > >
> > > > > +  }
> > > > >
> > > > > +  if ( PcieDev.Bits.MaxReadRequestSize != PciDevice->SetupMRRS) {
> > > > >
> > > > > +    PcieDev.Bits.MaxReadRequestSize = PciDevice->SetupMRRS;
> > > > >
> > > > > +    DEBUG (( DEBUG_INFO, "Max_Read_Request_Size: %d\n",
> > PciDevice-
> > > > > >SetupMRRS));
> > > > >
> > > > > +
> > > > >
> > > > > +    Status = PciDevice->PciIo.Pci.Write (
> > > > >
> > > > > +                                    &PciDevice->PciIo,
> > > > >
> > > > > +                                    EfiPciIoWidthUint16,
> > > > >
> > > > > +                                    Offset,
> > > > >
> > > > > +                                    1,
> > > > >
> > > > > +                                    &PcieDev.Uint16
> > > > >
> > > > > +                                  );
> > > > >
> > > > > +    if ( !EFI_ERROR(Status)) {
> > > > >
> > > > > +      PciDevice->PciExpStruct.DeviceControl.Uint16 = PcieDev.Uint16;
> > > > >
> > > > > +    } else {
> > > > >
> > > > > +      DEBUG (( DEBUG_ERROR, "Unexpected DeviceControl register
> > (0x%x)
> > > > > write error!",
> > > > >
> > > > > +          Offset
> > > > >
> > > > > +      ));
> > > > >
> > > > > +    }
> > > > >
> > > > > +  } else {
> > > > >
> > > > > +    DEBUG (( DEBUG_INFO, "No write of
> > Max_Read_Request_Size=%d\n",
> > > > > PciDevice->SetupMRRS));
> > > > >
> > > > > +  }
> > > > >
> > > > > +
> > > > >
> > > > > +  return Status;
> > > > >
> > > > > +}
> > > > >
> > > > > +
> > > > >
> > > > > +/**
> > > > >
> > > > > +  helper routine to dump the PCIe Device Port Type
> > > > >
> > > > > +**/
> > > > >
> > > > > +VOID
> > > > >
> > > > > +DumpDevicePortType (
> > > > >
> > > > > +  IN  UINT8   DevicePortType
> > > > >
> > > > > +  )
> > > > >
> > > > > +{
> > > > >
> > > > > +  switch ( DevicePortType){
> > > > >
> > > > > +    case PCIE_DEVICE_PORT_TYPE_PCIE_ENDPOINT:
> > > > >
> > > > > +      DEBUG (( DEBUG_INFO, "PCIe endpoint found\n"));
> > > > >
> > > > > +      break;
> > > > >
> > > > > +    case PCIE_DEVICE_PORT_TYPE_LEGACY_PCIE_ENDPOINT:
> > > > >
> > > > > +      DEBUG (( DEBUG_INFO, "legacy PCI endpoint found\n"));
> > > > >
> > > > > +      break;
> > > > >
> > > > > +    case PCIE_DEVICE_PORT_TYPE_ROOT_PORT:
> > > > >
> > > > > +      DEBUG (( DEBUG_INFO, "PCIe Root Port found\n"));
> > > > >
> > > > > +      break;
> > > > >
> > > > > +    case PCIE_DEVICE_PORT_TYPE_UPSTREAM_PORT:
> > > > >
> > > > > +      DEBUG (( DEBUG_INFO, "PCI switch upstream port found\n"));
> > > > >
> > > > > +      break;
> > > > >
> > > > > +    case PCIE_DEVICE_PORT_TYPE_DOWNSTREAM_PORT:
> > > > >
> > > > > +      DEBUG (( DEBUG_INFO, "PCI switch downstream port found\n"));
> > > > >
> > > > > +      break;
> > > > >
> > > > > +    case PCIE_DEVICE_PORT_TYPE_PCIE_TO_PCI_BRIDGE:
> > > > >
> > > > > +      DEBUG (( DEBUG_INFO, "PCIe-PCI bridge found\n"));
> > > > >
> > > > > +      break;
> > > > >
> > > > > +    case PCIE_DEVICE_PORT_TYPE_PCI_TO_PCIE_BRIDGE:
> > > > >
> > > > > +      DEBUG (( DEBUG_INFO, "PCI-PCIe bridge found\n"));
> > > > >
> > > > > +      break;
> > > > >
> > > > > +    case
> > > > > PCIE_DEVICE_PORT_TYPE_ROOT_COMPLEX_INTEGRATED_ENDPOINT:
> > > > >
> > > > > +      DEBUG (( DEBUG_INFO, "RCiEP found\n"));
> > > > >
> > > > > +      break;
> > > > >
> > > > > +    case
> > PCIE_DEVICE_PORT_TYPE_ROOT_COMPLEX_EVENT_COLLECTOR:
> > > > >
> > > > > +      DEBUG (( DEBUG_INFO, "RC Event Collector found\n"));
> > > > >
> > > > > +      break;
> > > > >
> > > > > +  }
> > > > >
> > > > > +}
> > > > >
> > > > > +
> > > > >
> > > > > +/**
> > > > >
> > > > > +   Process each PCI device as per the pltaform and device-specific
> > policy.
> > > > >
> > > > > +
> > > > >
> > > > > +  @param RootBridge             A pointer to the PCI_IO_DEVICE.
> > > > >
> > > > > +
> > > > >
> > > > > +  @retval EFI_SUCCESS           processing each PCI feature as per policy
> > > > > defined
> > > > >
> > > > > +                                was successful.
> > > > >
> > > > > + **/
> > > > >
> > > > > +EFI_STATUS
> > > > >
> > > > > +SetupDevicePciFeatures (
> > > > >
> > > > > +  IN  PCI_IO_DEVICE                   *PciDevice,
> > > > >
> > > > > +  IN  PCI_FEATURE_CONFIGURATION_PHASE PciConfigPhase
> > > > >
> > > > > +  )
> > > > >
> > > > > +{
> > > > >
> > > > > +  EFI_STATUS                              Status;
> > > > >
> > > > > +  PCI_REG_PCIE_CAPABILITY                 PcieCap;
> > > > >
> > > > > +  OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > > > > *OtherPciFeaturesConfigTable;
> > > > >
> > > > > +
> > > > >
> > > > > +  PcieCap.Uint16 = PciDevice->PciExpStruct.Capability.Uint16;
> > > > >
> > > > > +  DumpDevicePortType ( (UINT8)PcieCap.Bits.DevicePortType);
> > > > >
> > > > > +
> > > > >
> > > > > +  OtherPciFeaturesConfigTable = NULL;
> > > > >
> > > > > +  Status = GetPciFeaturesConfigurationTable ( PciDevice,
> > > > > &OtherPciFeaturesConfigTable);
> > > > >
> > > > > +  if ( EFI_ERROR( Status)) {
> > > > >
> > > > > +    DEBUG ((
> > > > >
> > > > > +        EFI_D_WARN, "No primary root port found in these root bridge
> > > > > nodes!\n"
> > > > >
> > > > > +    ));
> > > > >
> > > > > +  } else if ( !OtherPciFeaturesConfigTable) {
> > > > >
> > > > > +    DEBUG ((
> > > > >
> > > > > +        DEBUG_INFO, "No PCI features config. table for this device!\n"
> > > > >
> > > > > +    ));
> > > > >
> > > > > +  } else {
> > > > >
> > > > > +    DEBUG ((
> > > > >
> > > > > +        DEBUG_INFO, "using PCI features config. table ID: %d\n",
> > > > >
> > > > > +        OtherPciFeaturesConfigTable->ID
> > > > >
> > > > > +    ));
> > > > >
> > > > > +  }
> > > > >
> > > > > +
> > > > >
> > > > > +  if ( PciConfigPhase == PciFeatureGetDevicePolicy) {
> > > > >
> > > > > +    Status = GetPciDevicePlatformPolicy ( PciDevice);
> > > > >
> > > > > +    if ( EFI_ERROR(Status)) {
> > > > >
> > > > > +      DEBUG ((
> > > > >
> > > > > +          DEBUG_ERROR, "Error in obtaining PCI device policy!!!\n"
> > > > >
> > > > > +      ));
> > > > >
> > > > > +    }
> > > > >
> > > > > +  }
> > > > >
> > > > > +
> > > > >
> > > > > +  if ( SetupMaxPayloadSize ()) {
> > > > >
> > > > > +    Status = ProcessMaxPayloadSize (
> > > > >
> > > > > +              PciDevice,
> > > > >
> > > > > +              PciConfigPhase,
> > > > >
> > > > > +              OtherPciFeaturesConfigTable
> > > > >
> > > > > +              );
> > > > >
> > > > > +  }
> > > > >
> > > > > +  //
> > > > >
> > > > > +  // implementation specific rule:- the MRRS of any PCI device should
> > be
> > > > > processed
> > > > >
> > > > > +  // only after the MPS is processed for that device
> > > > >
> > > > > +  //
> > > > >
> > > > > +  if ( SetupMaxReadReqSize ()) {
> > > > >
> > > > > +    Status = ProcessMaxReadReqSize (
> > > > >
> > > > > +              PciDevice,
> > > > >
> > > > > +              PciConfigPhase,
> > > > >
> > > > > +              OtherPciFeaturesConfigTable
> > > > >
> > > > > +              );
> > > > >
> > > > > +  }
> > > > >
> > > > > +  return Status;
> > > > >
> > > > > +}
> > > > >
> > > > > +
> > > > >
> > > > > +/**
> > > > >
> > > > > +  Traverse all the nodes from the root bridge or PCI-PCI bridge instance,
> > to
> > > > >
> > > > > +  configure the PCI features as per the device-specific platform policy,
> > and
> > > > >
> > > > > +  as per the device capability, as applicable.
> > > > >
> > > > > +
> > > > >
> > > > > +  @param RootBridge             A pointer to the PCI_IO_DEVICE.
> > > > >
> > > > > +
> > > > >
> > > > > +  @retval EFI_SUCCESS           Traversing all the nodes of the root bridge
> > > > >
> > > > > +                                instances were successfull.
> > > > >
> > > > > +**/
> > > > >
> > > > > +EFI_STATUS
> > > > >
> > > > > +SetupPciFeatures (
> > > > >
> > > > > +  IN  PCI_IO_DEVICE                   *RootBridge,
> > > > >
> > > > > +  IN  PCI_FEATURE_CONFIGURATION_PHASE PciConfigPhase
> > > > >
> > > > > +  )
> > > > >
> > > > > +{
> > > > >
> > > > > +  EFI_STATUS           Status;
> > > > >
> > > > > +  LIST_ENTRY           *Link;
> > > > >
> > > > > +  PCI_IO_DEVICE        *Device;
> > > > >
> > > > > +
> > > > >
> > > > > +  for ( Link = RootBridge->ChildList.ForwardLink
> > > > >
> > > > > +      ; Link != &RootBridge->ChildList
> > > > >
> > > > > +      ; Link = Link->ForwardLink
> > > > >
> > > > > +  ) {
> > > > >
> > > > > +    Device = PCI_IO_DEVICE_FROM_LINK (Link);
> > > > >
> > > > > +    if (IS_PCI_BRIDGE (&Device->Pci)) {
> > > > >
> > > > > +      DEBUG ((
> > > > >
> > > > > +          DEBUG_INFO, "::Bridge [%02x|%02x|%02x] -",
> > > > >
> > > > > +          Device->BusNumber, Device->DeviceNumber, Device-
> > > > > >FunctionNumber
> > > > >
> > > > > +      ));
> > > > >
> > > > > +      if (Device->IsPciExp) {
> > > > >
> > > > > +        Status = SetupDevicePciFeatures ( Device, PciConfigPhase);
> > > > >
> > > > > +      } else {
> > > > >
> > > > > +        DEBUG (( DEBUG_INFO, "Not a PCIe capable device!\n"));
> > > > >
> > > > > +        //
> > > > >
> > > > > +        // PCI Bridge which does not have PCI Express Capability structure
> > > > >
> > > > > +        // cannot process this kind of PCI Bridge device
> > > > >
> > > > > +        //
> > > > >
> > > > > +
> > > > >
> > > > > +      }
> > > > >
> > > > > +
> > > > >
> > > > > +      SetupPciFeatures ( Device, PciConfigPhase);
> > > > >
> > > > > +    } else {
> > > > >
> > > > > +      DEBUG ((
> > > > >
> > > > > +          DEBUG_INFO, "::Device [%02x|%02x|%02x] -",
> > > > >
> > > > > +          Device->BusNumber, Device->DeviceNumber, Device-
> > > > > >FunctionNumber
> > > > >
> > > > > +      ));
> > > > >
> > > > > +      if (Device->IsPciExp) {
> > > > >
> > > > > +
> > > > >
> > > > > +        Status = SetupDevicePciFeatures ( Device, PciConfigPhase);
> > > > >
> > > > > +      } else {
> > > > >
> > > > > +        DEBUG (( DEBUG_INFO, "Not a PCIe capable device!\n"));
> > > > >
> > > > > +        //
> > > > >
> > > > > +        // PCI Device which does not have PCI Express Capability structure
> > > > >
> > > > > +        // cannot process this kind of PCI device
> > > > >
> > > > > +        //
> > > > >
> > > > > +      }
> > > > >
> > > > > +    }
> > > > >
> > > > > +  }
> > > > >
> > > > > +
> > > > >
> > > > > +  return EFI_SUCCESS;
> > > > >
> > > > > +}
> > > > >
> > > > > +
> > > > >
> > > > > +/**
> > > > >
> > > > > +  Program the PCI device, to override the PCI features as per the policy,
> > > > >
> > > > > +  resolved from previous traverse.
> > > > >
> > > > > +
> > > > >
> > > > > +  @param RootBridge             A pointer to the PCI_IO_DEVICE.
> > > > >
> > > > > +
> > > > >
> > > > > +  @retval EFI_SUCCESS           The other PCI features configuration
> > during
> > > > > enumeration
> > > > >
> > > > > +                                of all the nodes of the PCI root bridge instance were
> > > > >
> > > > > +                                programmed in PCI-compliance pattern along with the
> > > > >
> > > > > +                                device-specific policy, as applicable.
> > > > >
> > > > > +  @retval EFI_UNSUPPORTED       One of the override operation maong
> > the
> > > > > nodes of
> > > > >
> > > > > +                                the PCI hierarchy resulted in a incompatible address
> > > > >
> > > > > +                                range.
> > > > >
> > > > > +  @retval EFI_INVALID_PARAMETER The override operation is
> > performed
> > > > > with invalid input
> > > > >
> > > > > +                                parameters.
> > > > >
> > > > > +**/
> > > > >
> > > > > +EFI_STATUS
> > > > >
> > > > > +ProgramDevicePciFeatures (
> > > > >
> > > > > +  IN PCI_IO_DEVICE          *PciDevice
> > > > >
> > > > > +  )
> > > > >
> > > > > +{
> > > > >
> > > > > +  EFI_STATUS           Status;
> > > > >
> > > > > +
> > > > >
> > > > > +  if ( SetupMaxPayloadSize ()) {
> > > > >
> > > > > +    Status = OverrideMaxPayloadSize (PciDevice);
> > > > >
> > > > > +  }
> > > > >
> > > > > +  if ( SetupMaxReadReqSize ()) {
> > > > >
> > > > > +    Status = OverrideMaxReadReqSize (PciDevice);
> > > > >
> > > > > +  }
> > > > >
> > > > > +  return Status;
> > > > >
> > > > > +}
> > > > >
> > > > > +
> > > > >
> > > > > +/**
> > > > >
> > > > > +  Program all the nodes of the specified root bridge or PCI-PCI Bridge,
> > to
> > > > >
> > > > > +  override the PCI features.
> > > > >
> > > > > +
> > > > >
> > > > > +  @param RootBridge             A pointer to the PCI_IO_DEVICE.
> > > > >
> > > > > +
> > > > >
> > > > > +  @retval EFI_SUCCESS           The other PCI features configuration
> > during
> > > > > enumeration
> > > > >
> > > > > +                                of all the nodes of the PCI root bridge instance were
> > > > >
> > > > > +                                programmed in PCI-compliance pattern along with the
> > > > >
> > > > > +                                device-specific policy, as applicable.
> > > > >
> > > > > +  @retval EFI_UNSUPPORTED       One of the override operation maong
> > the
> > > > > nodes of
> > > > >
> > > > > +                                the PCI hierarchy resulted in a incompatible address
> > > > >
> > > > > +                                range.
> > > > >
> > > > > +  @retval EFI_INVALID_PARAMETER The override operation is
> > performed
> > > > > with invalid input
> > > > >
> > > > > +                                parameters.
> > > > >
> > > > > +**/
> > > > >
> > > > > +EFI_STATUS
> > > > >
> > > > > +ProgramPciFeatures (
> > > > >
> > > > > +  IN PCI_IO_DEVICE          *RootBridge
> > > > >
> > > > > +  )
> > > > >
> > > > > +{
> > > > >
> > > > > +  EFI_STATUS           Status;
> > > > >
> > > > > +  LIST_ENTRY           *Link;
> > > > >
> > > > > +  PCI_IO_DEVICE        *Device;
> > > > >
> > > > > +
> > > > >
> > > > > +  for ( Link = RootBridge->ChildList.ForwardLink
> > > > >
> > > > > +      ; Link != &RootBridge->ChildList
> > > > >
> > > > > +      ; Link = Link->ForwardLink
> > > > >
> > > > > +  ) {
> > > > >
> > > > > +    Device = PCI_IO_DEVICE_FROM_LINK (Link);
> > > > >
> > > > > +    if (IS_PCI_BRIDGE (&Device->Pci)) {
> > > > >
> > > > > +      DEBUG ((
> > > > >
> > > > > +          DEBUG_INFO, "::Bridge [%02x|%02x|%02x] -",
> > > > >
> > > > > +          Device->BusNumber, Device->DeviceNumber, Device-
> > > > > >FunctionNumber
> > > > >
> > > > > +      ));
> > > > >
> > > > > +      if (Device->IsPciExp) {
> > > > >
> > > > > +        DEBUG (( DEBUG_INFO, "ready to override!\n"));
> > > > >
> > > > > +
> > > > >
> > > > > +        Status = ProgramDevicePciFeatures ( Device);
> > > > >
> > > > > +      } else {
> > > > >
> > > > > +        DEBUG (( DEBUG_INFO, "skipped!\n"));
> > > > >
> > > > > +        //
> > > > >
> > > > > +        // PCI Bridge which does not have PCI Express Capability structure
> > > > >
> > > > > +        // cannot process this kind of PCI Bridge device
> > > > >
> > > > > +        //
> > > > >
> > > > > +
> > > > >
> > > > > +      }
> > > > >
> > > > > +
> > > > >
> > > > > +      Status = ProgramPciFeatures ( Device);
> > > > >
> > > > > +    } else {
> > > > >
> > > > > +      DEBUG ((
> > > > >
> > > > > +          DEBUG_INFO, "::Device [%02x|%02x|%02x] -",
> > > > >
> > > > > +          Device->BusNumber, Device->DeviceNumber, Device-
> > > > > >FunctionNumber
> > > > >
> > > > > +      ));
> > > > >
> > > > > +      if (Device->IsPciExp) {
> > > > >
> > > > > +        DEBUG (( DEBUG_INFO, "ready to override!\n"));
> > > > >
> > > > > +
> > > > >
> > > > > +        Status = ProgramDevicePciFeatures ( Device);
> > > > >
> > > > > +      } else {
> > > > >
> > > > > +        DEBUG (( DEBUG_INFO, "skipped!\n"));
> > > > >
> > > > > +        //
> > > > >
> > > > > +        // PCI Device which does not have PCI Express Capability structure
> > > > >
> > > > > +        // cannot process this kind of PCI device
> > > > >
> > > > > +        //
> > > > >
> > > > > +      }
> > > > >
> > > > > +    }
> > > > >
> > > > > +  }
> > > > >
> > > > > +
> > > > >
> > > > > +  return Status;
> > > > >
> > > > > +}
> > > > >
> > > > > +
> > > > >
> > > > > +/**
> > > > >
> > > > > +  Create a node of type PRIMARY_ROOT_PORT_NODE for the given
> > PCI
> > > > > device, and
> > > > >
> > > > > +  assigns EFI handles of its Root Bridge and its own, along with its PCI
> > Bus
> > > > >
> > > > > +  range for the secondary and subordinate bus range.
> > > > >
> > > > > +
> > > > >
> > > > > +  @param  RootBridge          A pointer to the PCI_IO_DEVICE for its PCI
> > Root
> > > > > Bridge
> > > > >
> > > > > +  @param  Device              A pointer to the PCI_IO_DEVICE for the PCI
> > > > > controller
> > > > >
> > > > > +  @param  RootPortSecBus      PCI controller's Secondary Bus number
> > > > >
> > > > > +  @param  RootPortSubBus      PCI controller's Subordinate Bus number
> > > > >
> > > > > +  @param  PrimaryRootPortNode A pointer to the
> > > > > PRIMARY_ROOT_PORT_NODE to return
> > > > >
> > > > > +                              the newly created node for the PCI controller. In
> > > > >
> > > > > +                              case of error nothing is return in this.
> > > > >
> > > > > +
> > > > >
> > > > > +  @retval EFI_SUCCESS           new node of
> > PRIMARY_ROOT_PORT_NODE is
> > > > > returned for
> > > > >
> > > > > +                                the PCI controller
> > > > >
> > > > > +          EFI_OUT_OF_RESOURCES  unable to create the node for the PCI
> > > > > controller
> > > > >
> > > > > +          EFI_INVALID_PARAMETER unable to store the node as the input
> > > > > buffer is
> > > > >
> > > > > +                                not empty (*PrimaryRootPortNode)
> > > > >
> > > > > +**/
> > > > >
> > > > > +EFI_STATUS
> > > > >
> > > > > +CreatePrimaryPciRootPortNode (
> > > > >
> > > > > +  IN  PCI_IO_DEVICE           *RootBridge,
> > > > >
> > > > > +  IN  PCI_IO_DEVICE           *Device,
> > > > >
> > > > > +  IN  UINT8                   RootPortSecBus,
> > > > >
> > > > > +  IN  UINT8                   RootPortSubBus,
> > > > >
> > > > > +  OUT PRIMARY_ROOT_PORT_NODE  **PrimaryRootPortNode
> > > > >
> > > > > +  )
> > > > >
> > > > > +{
> > > > >
> > > > > +  PRIMARY_ROOT_PORT_NODE      *RootPortNode = NULL;
> > > > >
> > > > > +
> > > > >
> > > > > +  if ( !*PrimaryRootPortNode) {
> > > > >
> > > > > +    RootPortNode                    = AllocateZeroPool ( sizeof
> > > > > (PRIMARY_ROOT_PORT_NODE));
> > > > >
> > > > > +    if ( RootPortNode == NULL) {
> > > > >
> > > > > +      return EFI_OUT_OF_RESOURCES;
> > > > >
> > > > > +    }
> > > > >
> > > > > +    RootPortNode->Signature         = PCI_ROOT_PORT_SIGNATURE;
> > > > >
> > > > > +    RootPortNode->RootBridgeHandle  = RootBridge->Handle;
> > > > >
> > > > > +    RootPortNode->RootPortHandle    = Device->Handle;
> > > > >
> > > > > +    RootPortNode->SecondaryBusStart = RootPortSecBus;
> > > > >
> > > > > +    RootPortNode->SecondaryBusEnd   = RootPortSubBus;
> > > > >
> > > > > +    InitializeListHead ( &RootPortNode->NeighborRootPort);
> > > > >
> > > > > +    *PrimaryRootPortNode = RootPortNode;
> > > > >
> > > > > +    return EFI_SUCCESS;
> > > > >
> > > > > +  } else {
> > > > >
> > > > > +    return EFI_INVALID_PARAMETER;
> > > > >
> > > > > +  }
> > > > >
> > > > > +}
> > > > >
> > > > > +
> > > > >
> > > > > +/**
> > > > >
> > > > > +  Checks to report whether the input PCI controller's secondary /
> > > > > subordinate
> > > > >
> > > > > +  bus numbers are within the recorded list of other PCI controllers
> > (root
> > > > > ports).
> > > > >
> > > > > +
> > > > >
> > > > > +  @param  RootPortNode      A pointer to the first node of
> > > > > PRIMARY_ROOT_PORT_NODE
> > > > >
> > > > > +  @param  RootPortSecBus    PCI secondary bus number of the PCI
> > > > controller
> > > > > found
> > > > >
> > > > > +  @param  RootPortSubBus    PCI subordinate bus number of the PCI
> > Root
> > > > > Port found
> > > > >
> > > > > +
> > > > >
> > > > > +  @retval TRUE              A child PCI Root port found
> > > > >
> > > > > +          FALSE             A new PCI controller found
> > > > >
> > > > > +**/
> > > > >
> > > > > +BOOLEAN
> > > > >
> > > > > +CheckChildRootPort (
> > > > >
> > > > > +  IN      PRIMARY_ROOT_PORT_NODE  *RootPortNode,
> > > > >
> > > > > +  IN      UINT8                   RootPortSecBus,
> > > > >
> > > > > +  IN      UINT8                   RootPortSubBus
> > > > >
> > > > > +)
> > > > >
> > > > > +{
> > > > >
> > > > > +  LIST_ENTRY              *Link;
> > > > >
> > > > > +  PRIMARY_ROOT_PORT_NODE  *Temp;
> > > > >
> > > > > +
> > > > >
> > > > > +  if ( !RootPortNode) {
> > > > >
> > > > > +    return FALSE;
> > > > >
> > > > > +  }
> > > > >
> > > > > +  Link = &RootPortNode->NeighborRootPort;
> > > > >
> > > > > +  do {
> > > > >
> > > > > +    Temp = PRIMARY_ROOT_PORT_NODE_FROM_LINK ( Link);
> > > > >
> > > > > +    if ( RootPortSecBus >= Temp->SecondaryBusStart
> > > > >
> > > > > +        && RootPortSubBus <= Temp->SecondaryBusEnd) {
> > > > >
> > > > > +      //
> > > > >
> > > > > +      // given root port's secondary & subordinate within its primary
> > ports
> > > > >
> > > > > +      // hence return as child port
> > > > >
> > > > > +      //
> > > > >
> > > > > +      return TRUE;
> > > > >
> > > > > +    }
> > > > >
> > > > > +    Link = Link->ForwardLink;
> > > > >
> > > > > +  } while (Link != &RootPortNode->NeighborRootPort);
> > > > >
> > > > > +  //
> > > > >
> > > > > +  // the given root port's secondary / subordinate bus numbers do not
> > > > > belong to
> > > > >
> > > > > +  // any existing primary root port's bus range hence consider another
> > > > > primary
> > > > >
> > > > > +  // root port of the root bridge controller
> > > > >
> > > > > +  //
> > > > >
> > > > > +  return FALSE;
> > > > >
> > > > > +}
> > > > >
> > > > > +
> > > > >
> > > > > +/**
> > > > >
> > > > > +  Create the vector of PCI Feature configuration table as per the
> > number
> > > > of
> > > > >
> > > > > +  the PCI Root Ports given, assigns default value to the PCI features
> > > > > supported
> > > > >
> > > > > +  and assign its address to the global variable
> > > > > "mPciFeaturesConfigurationTableInstances".
> > > > >
> > > > > +
> > > > >
> > > > > +  @param  NumberOfRootPorts   An input arguement of UINTN to
> > indicate
> > > > > number of
> > > > >
> > > > > +                              primary PCI physical Root Bridge devices found
> > > > >
> > > > > +
> > > > >
> > > > > +  @retval EFI_OUT_OF_RESOURCES  unable to allocate buffer to store
> > PCI
> > > > > feature
> > > > >
> > > > > +                                configuration table for all the physical PCI root
> > > > >
> > > > > +                                ports given
> > > > >
> > > > > +          EFI_SUCCESS           PCI Feature COnfiguration table created for all
> > > > >
> > > > > +                                the PCI Rooot ports reported
> > > > >
> > > > > + */
> > > > >
> > > > > +EFI_STATUS
> > > > >
> > > > > +CreatePciFeaturesConfigurationTableInstances (
> > > > >
> > > > > +  IN  UINTN NumberOfRootPorts
> > > > >
> > > > > +  )
> > > > >
> > > > > +{
> > > > >
> > > > > +  OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > > > > *PciRootBridgePortFeatures = NULL;
> > > > >
> > > > > +  UINTN                                     Instances;
> > > > >
> > > > > +
> > > > >
> > > > > +  PciRootBridgePortFeatures = AllocateZeroPool (
> > > > >
> > > > > +                                sizeof
> > ( OTHER_PCI_FEATURES_CONFIGURATION_TABLE)
> > > > *
> > > > > NumberOfRootPorts
> > > > >
> > > > > +                                );
> > > > >
> > > > > +  if ( !PciRootBridgePortFeatures) {
> > > > >
> > > > > +    return EFI_OUT_OF_RESOURCES;
> > > > >
> > > > > +  }
> > > > >
> > > > > +
> > > > >
> > > > > +  for ( Instances = 0; Instances < NumberOfRootPorts; Instances++) {
> > > > >
> > > > > +    PciRootBridgePortFeatures [Instances].ID                    = Instances + 1;
> > > > >
> > > > > +    PciRootBridgePortFeatures [Instances].Max_Payload_Size      =
> > > > > PCIE_MAX_PAYLOAD_SIZE_4096B;
> > > > >
> > > > > +    PciRootBridgePortFeatures [Instances].Max_Read_Request_Size =
> > > > > PCIE_MAX_READ_REQ_SIZE_4096B;
> > > > >
> > > > > +    PciRootBridgePortFeatures
> > [Instances].Lock_Max_Read_Request_Size
> > > > =
> > > > > FALSE;
> > > > >
> > > > > +  }
> > > > >
> > > > > +  mPciFeaturesConfigurationTableInstances =
> > PciRootBridgePortFeatures;
> > > > >
> > > > > +  return EFI_SUCCESS;
> > > > >
> > > > > +}
> > > > >
> > > > > +
> > > > >
> > > > > +/**
> > > > >
> > > > > +  This routine pairs the each PCI Root Port node with one of the PCI
> > > > Feature
> > > > >
> > > > > +  Configuration Table node. Each physical PCI Root Port has its own PCI
> > > > > feature
> > > > >
> > > > > +  configuration table which will used for aligning all its downstream
> > > > > components.
> > > > >
> > > > > +
> > > > >
> > > > > +  @param  NumberOfRootPorts     inputs the number of physical PCI
> > root
> > > > > ports
> > > > >
> > > > > +                                found on the Root bridge instance
> > > > >
> > > > > +
> > > > >
> > > > > +  @retval EFI_INVALID_PARAMETER if the primary PCI root ports list is
> > > > > vacant when
> > > > >
> > > > > +                                there is one or more PCI Root port indicated as per
> > > > >
> > > > > +                                input parameter
> > > > >
> > > > > +          EFI_UNSUPPORTED       The PCI Root Port nodes not paired
> > equally
> > > > with
> > > > >
> > > > > +                                the PCI Configuration Table nodes
> > > > >
> > > > > +          EFI_SUCCESS           each PCI feature configuration node is paired
> > > > > equally
> > > > >
> > > > > +                                with each PCI Root port in the list
> > > > >
> > > > > +**/
> > > > >
> > > > > +EFI_STATUS
> > > > >
> > > > > +AssignPciFeaturesConfigurationTable (
> > > > >
> > > > > +  IN  UINTN NumberOfRootPorts
> > > > >
> > > > > +  )
> > > > >
> > > > > +{
> > > > >
> > > > > +  UINTN                       Instances;
> > > > >
> > > > > +  LIST_ENTRY                  *Link;
> > > > >
> > > > > +  PRIMARY_ROOT_PORT_NODE      *Temp;
> > > > >
> > > > > +
> > > > >
> > > > > +  if ( !mPrimaryRootPortList
> > > > >
> > > > > +      && NumberOfRootPorts) {
> > > > >
> > > > > +    DEBUG ((
> > > > >
> > > > > +        DEBUG_ERROR,
> > > > >
> > > > > +        "Critical error! no internal table setup for %d PCI Root ports \n",
> > > > >
> > > > > +        NumberOfRootPorts
> > > > >
> > > > > +    ));
> > > > >
> > > > > +    return EFI_INVALID_PARAMETER;
> > > > >
> > > > > +  }
> > > > >
> > > > > +
> > > > >
> > > > > +  if ( NumberOfRootPorts) {
> > > > >
> > > > > +    Link = &mPrimaryRootPortList->NeighborRootPort;
> > > > >
> > > > > +    for ( Instances = 0
> > > > >
> > > > > +        ; (Instances < NumberOfRootPorts)
> > > > >
> > > > > +        ; Instances++
> > > > >
> > > > > +    ) {
> > > > >
> > > > > +      Temp = PRIMARY_ROOT_PORT_NODE_FROM_LINK ( Link);
> > > > >
> > > > > +      Temp->OtherPciFeaturesConfigurationTable =
> > > > > &mPciFeaturesConfigurationTableInstances [Instances];
> > > > >
> > > > > +      DEBUG ((
> > > > >
> > > > > +          DEBUG_INFO,
> > > > >
> > > > > +          "Assigned to %dth primary root port\n",
> > > > >
> > > > > +          Instances
> > > > >
> > > > > +      ));
> > > > >
> > > > > +
> > > > >
> > > > > +      Link = Link->ForwardLink;
> > > > >
> > > > > +    }
> > > > >
> > > > > +    if ( Link != &mPrimaryRootPortList->NeighborRootPort) {
> > > > >
> > > > > +      DEBUG ((
> > > > >
> > > > > +          DEBUG_ERROR,
> > > > >
> > > > > +          "Error!! PCI Root Port list is not properly matched with Config.,
> > Table
> > > > > list \n"
> > > > >
> > > > > +      ));
> > > > >
> > > > > +      return EFI_UNSUPPORTED;
> > > > >
> > > > > +    }
> > > > >
> > > > > +  }
> > > > >
> > > > > +  return  EFI_SUCCESS;
> > > > >
> > > > > +}
> > > > >
> > > > > +
> > > > >
> > > > > +/**
> > > > >
> > > > > +  Prepare each PCI Controller (Root Port) with its own PCI Feature
> > > > > configuration
> > > > >
> > > > > +  table node that can be used for tracking to align all PCI nodes in its
> > > > > hierarchy.
> > > > >
> > > > > +
> > > > >
> > > > > +  @param  PrimaryRootPorts      A pointer to
> > PRIMARY_ROOT_PORT_NODE
> > > > >
> > > > > +  @param  NumberOfRootPorts     Total number of pysical primary PCI
> > > > Root
> > > > > ports
> > > > >
> > > > > +
> > > > >
> > > > > +  @retval EFI_OUT_OF_RESOURCES  unable to allocate buffer to store
> > PCI
> > > > > feature
> > > > >
> > > > > +                                configuration table for all the physical PCI root
> > > > >
> > > > > +                                ports given
> > > > >
> > > > > +          EFI_INVALID_PARAMETER if the primary PCI root ports list is
> > vacant
> > > > > when
> > > > >
> > > > > +                                there is one or more PCI Root port indicated as per
> > > > >
> > > > > +                                input parameter
> > > > >
> > > > > +          EFI_UNSUPPORTED       The PCI Root Port nodes not paired
> > equally
> > > > with
> > > > >
> > > > > +                                the PCI Configuration Table nodes
> > > > >
> > > > > +          EFI_SUCCESS           each PCI feature configuration node is paired
> > > > > equally
> > > > >
> > > > > +                                with each PCI Root port in the list
> > > > >
> > > > > +**/
> > > > >
> > > > > +EFI_STATUS
> > > > >
> > > > > +PreparePciControllerConfigurationTable (
> > > > >
> > > > > +  IN  PRIMARY_ROOT_PORT_NODE    *PrimaryRootPorts,
> > > > >
> > > > > +  IN  UINTN                     NumberOfRootPorts
> > > > >
> > > > > +  )
> > > > >
> > > > > +{
> > > > >
> > > > > +  EFI_STATUS                    Status;
> > > > >
> > > > > +
> > > > >
> > > > > +  mPrimaryRootPortList = PrimaryRootPorts;
> > > > >
> > > > > +  DEBUG ((
> > > > >
> > > > > +      DEBUG_INFO, "Number of primary Root Ports found on this bridge
> > > > > = %d\n",
> > > > >
> > > > > +      NumberOfRootPorts
> > > > >
> > > > > +  ));
> > > > >
> > > > > +
> > > > >
> > > > > +  Status = CreatePciFeaturesConfigurationTableInstances
> > > > > ( NumberOfRootPorts);
> > > > >
> > > > > +  if ( EFI_ERROR(Status)) {
> > > > >
> > > > > +    DEBUG ((
> > > > >
> > > > > +        DEBUG_ERROR, "Unexpected memory node creation error for PCI
> > > > > features!\n"
> > > > >
> > > > > +    ));
> > > > >
> > > > > +  } else {
> > > > >
> > > > > +    //
> > > > >
> > > > > +    // align the primary root port nodes list with the PCI Feature
> > > > configuration
> > > > >
> > > > > +    // table. Note that the PCI Feature configuration table is not
> > maintain
> > > > for
> > > > >
> > > > > +    // the RCiEP devices
> > > > >
> > > > > +    //
> > > > >
> > > > > +    Status = AssignPciFeaturesConfigurationTable
> > ( NumberOfRootPorts);
> > > > >
> > > > > +  }
> > > > >
> > > > > +  return Status;
> > > > >
> > > > > +}
> > > > >
> > > > > +
> > > > >
> > > > > +/**
> > > > >
> > > > > +  Scan all the nodes of the RootBridge to identify and create a separate
> > list
> > > > >
> > > > > +  of all primary physical PCI root ports and link each with its own
> > instance
> > > > of
> > > > >
> > > > > +  the PCI Feature Configuration Table.
> > > > >
> > > > > +
> > > > >
> > > > > +  @param  RootBridge    A pointer to the PCI_IO_DEVICE of the PCI
> > Root
> > > > > Bridge
> > > > >
> > > > > +
> > > > >
> > > > > +  @retval EFI_OUT_OF_RESOURCES  unable to allocate buffer to store
> > PCI
> > > > > feature
> > > > >
> > > > > +                                configuration table for all the physical PCI root
> > > > >
> > > > > +                                ports given
> > > > >
> > > > > +          EFI_NOT_FOUND         No PCI Bridge device found
> > > > >
> > > > > +          EFI_SUCCESS           PCI Feature COnfiguration table created for all
> > > > >
> > > > > +                                the PCI Rooot ports found
> > > > >
> > > > > +          EFI_INVALID_PARAMETER invalid parameter passed to the
> > routine
> > > > > which
> > > > >
> > > > > +                                creates the PCI controller node for the primary
> > > > >
> > > > > +                                Root post list
> > > > >
> > > > > +**/
> > > > >
> > > > > +EFI_STATUS
> > > > >
> > > > > +RecordPciRootPortBridges (
> > > > >
> > > > > +  IN  PCI_IO_DEVICE           *RootBridge
> > > > >
> > > > > +  )
> > > > >
> > > > > +{
> > > > >
> > > > > +  EFI_STATUS              Status = EFI_NOT_FOUND;
> > > > >
> > > > > +  LIST_ENTRY              *Link;
> > > > >
> > > > > +  PCI_IO_DEVICE           *Device;
> > > > >
> > > > > +  UINTN                   NumberOfRootPorts;
> > > > >
> > > > > +  PRIMARY_ROOT_PORT_NODE  *PrimaryRootPorts,
> > > > >
> > > > > +                          *TempNode;
> > > > >
> > > > > +  UINT8                   RootPortSecBus,
> > > > >
> > > > > +                          RootPortSubBus;
> > > > >
> > > > > +
> > > > >
> > > > > +  DEBUG ((
> > > > >
> > > > > +      DEBUG_INFO, "<<********** RecordPciRootPortBridges -start
> > > > > *************>>\n"
> > > > >
> > > > > +  ));
> > > > >
> > > > > +  NumberOfRootPorts = 0;
> > > > >
> > > > > +  PrimaryRootPorts = NULL;
> > > > >
> > > > > +  for ( Link = RootBridge->ChildList.ForwardLink
> > > > >
> > > > > +      ; Link != &RootBridge->ChildList
> > > > >
> > > > > +      ; Link = Link->ForwardLink
> > > > >
> > > > > +  ) {
> > > > >
> > > > > +    Device = PCI_IO_DEVICE_FROM_LINK (Link);
> > > > >
> > > > > +    if (IS_PCI_BRIDGE (&Device->Pci)) {
> > > > >
> > > > > +      Status = GetPciRootPortBusAssigned (
> > > > >
> > > > > +                  Device,
> > > > >
> > > > > +                  NULL,
> > > > >
> > > > > +                  &RootPortSecBus,
> > > > >
> > > > > +                  &RootPortSubBus
> > > > >
> > > > > +                  );
> > > > >
> > > > > +      if ( !EFI_ERROR(Status)) {
> > > > >
> > > > > +        DEBUG ((
> > > > >
> > > > > +            DEBUG_INFO, "::Device [%02x|%02x|%02x] - SecBus=0x%x,
> > > > > SubBus=0x%x\n",
> > > > >
> > > > > +            Device->BusNumber, Device->DeviceNumber, Device-
> > > > > >FunctionNumber,
> > > > >
> > > > > +            RootPortSecBus, RootPortSubBus
> > > > >
> > > > > +        ));
> > > > >
> > > > > +      } else {
> > > > >
> > > > > +        DEBUG ((
> > > > >
> > > > > +            DEBUG_ERROR, "Unexpected read error [0x%lx]::Device
> > > > > [%02x|%02x|%02x]\n",
> > > > >
> > > > > +            Status, Device->BusNumber, Device->DeviceNumber, Device-
> > > > > >FunctionNumber
> > > > >
> > > > > +        ));
> > > > >
> > > > > +        RootPortSecBus = RootPortSubBus = 0;
> > > > >
> > > > > +        continue;
> > > > >
> > > > > +      }
> > > > >
> > > > > +
> > > > >
> > > > > +      if ( !PrimaryRootPorts) {
> > > > >
> > > > > +        NumberOfRootPorts++;
> > > > >
> > > > > +        Status = CreatePrimaryPciRootPortNode (
> > > > >
> > > > > +                    RootBridge,
> > > > >
> > > > > +                    Device,
> > > > >
> > > > > +                    RootPortSecBus,
> > > > >
> > > > > +                    RootPortSubBus,
> > > > >
> > > > > +                    &PrimaryRootPorts
> > > > >
> > > > > +                    );
> > > > >
> > > > > +        if ( EFI_ERROR(Status)) {
> > > > >
> > > > > +          //
> > > > >
> > > > > +          // abort mission to scan for all primary roots ports of a bridge
> > > > >
> > > > > +          // controller if error encountered for very first PCI primary root
> > port
> > > > >
> > > > > +          //
> > > > >
> > > > > +          DEBUG ((
> > > > >
> > > > > +              DEBUG_ERROR, "Unexpected node creation error
> > [0x%lx]::Device
> > > > > [%02x|%02x|%02x]\n",
> > > > >
> > > > > +              Status, Device->BusNumber, Device->DeviceNumber, Device-
> > > > > >FunctionNumber
> > > > >
> > > > > +          ));
> > > > >
> > > > > +          return Status;
> > > > >
> > > > > +        }
> > > > >
> > > > > +        DEBUG ((
> > > > >
> > > > > +            DEBUG_INFO, "first primary root port found::Device
> > > > > [%02x|%02x|%02x]\n",
> > > > >
> > > > > +            Device->BusNumber, Device->DeviceNumber, Device-
> > > > > >FunctionNumber
> > > > >
> > > > > +        ));
> > > > >
> > > > > +      } else {
> > > > >
> > > > > +        if ( !CheckChildRootPort ( PrimaryRootPorts, RootPortSecBus,
> > > > > RootPortSubBus)) {
> > > > >
> > > > > +          NumberOfRootPorts++;
> > > > >
> > > > > +          TempNode = NULL;
> > > > >
> > > > > +          Status = CreatePrimaryPciRootPortNode (
> > > > >
> > > > > +                      RootBridge,
> > > > >
> > > > > +                      Device,
> > > > >
> > > > > +                      RootPortSecBus,
> > > > >
> > > > > +                      RootPortSubBus,
> > > > >
> > > > > +                      &TempNode
> > > > >
> > > > > +                      );
> > > > >
> > > > > +          if ( !EFI_ERROR(Status)) {
> > > > >
> > > > > +            //
> > > > >
> > > > > +            // another primary root port found on the same bridge
> > controller
> > > > >
> > > > > +            // insert in the node list
> > > > >
> > > > > +            //
> > > > >
> > > > > +            InsertTailList ( &PrimaryRootPorts->NeighborRootPort,
> > > > &TempNode-
> > > > > >NeighborRootPort);
> > > > >
> > > > > +            DEBUG ((
> > > > >
> > > > > +                DEBUG_INFO, "next primary root port found::Device
> > > > > [%02x|%02x|%02x]\n",
> > > > >
> > > > > +                Device->BusNumber, Device->DeviceNumber, Device-
> > > > > >FunctionNumber
> > > > >
> > > > > +            ));
> > > > >
> > > > > +          } else {
> > > > >
> > > > > +            DEBUG ((
> > > > >
> > > > > +                DEBUG_ERROR, "Unexpected node creation error
> > [0x%lx]::Device
> > > > > [%02x|%02x|%02x]\n",
> > > > >
> > > > > +                Status, Device->BusNumber, Device->DeviceNumber, Device-
> > > > > >FunctionNumber
> > > > >
> > > > > +            ));
> > > > >
> > > > > +          }
> > > > >
> > > > > +        }
> > > > >
> > > > > +      }
> > > > >
> > > > > +    }
> > > > >
> > > > > +  }
> > > > >
> > > > > +  //
> > > > >
> > > > > +  // prepare the PCI root port and its feature configuration table list
> > > > >
> > > > > +  //
> > > > >
> > > > > +  if ( NumberOfRootPorts) {
> > > > >
> > > > > +    Status = PreparePciControllerConfigurationTable (
> > > > >
> > > > > +                PrimaryRootPorts,
> > > > >
> > > > > +                NumberOfRootPorts
> > > > >
> > > > > +              );
> > > > >
> > > > > +
> > > > >
> > > > > +  } else {
> > > > >
> > > > > +    DEBUG ((
> > > > >
> > > > > +        DEBUG_INFO, "No PCI Root port found on this bridge!\n"
> > > > >
> > > > > +    ));
> > > > >
> > > > > +  }
> > > > >
> > > > > +
> > > > >
> > > > > +  DEBUG ((
> > > > >
> > > > > +      DEBUG_INFO, "<<********** RecordPciRootPortBridges - end
> > > > > **********>>\n"
> > > > >
> > > > > +  ));
> > > > >
> > > > > +  return Status;
> > > > >
> > > > > +}
> > > > >
> > > > > +
> > > > >
> > > > > +/**
> > > > >
> > > > > +  Enumerate all the nodes of the specified root bridge or PCI-PCI
> > Bridge, to
> > > > >
> > > > > +  configure the other PCI features.
> > > > >
> > > > > +
> > > > >
> > > > > +  @param RootBridge          A pointer to the PCI_IO_DEVICE.
> > > > >
> > > > > +
> > > > >
> > > > > +  @retval EFI_SUCCESS           The other PCI features configuration
> > during
> > > > > enumeration
> > > > >
> > > > > +                                of all the nodes of the PCI root bridge instance were
> > > > >
> > > > > +                                programmed in PCI-compliance pattern along with the
> > > > >
> > > > > +                                device-specific policy, as applicable.
> > > > >
> > > > > +  @retval EFI_UNSUPPORTED       One of the override operation maong
> > the
> > > > > nodes of
> > > > >
> > > > > +                                the PCI hierarchy resulted in a incompatible address
> > > > >
> > > > > +                                range.
> > > > >
> > > > > +  @retval EFI_INVALID_PARAMETER The override operation is
> > performed
> > > > > with invalid input
> > > > >
> > > > > +                                parameters.
> > > > >
> > > > > +**/
> > > > >
> > > > > +EFI_STATUS
> > > > >
> > > > > +EnumerateOtherPciFeatures (
> > > > >
> > > > > +  IN PCI_IO_DEVICE          *RootBridge
> > > > >
> > > > > +  )
> > > > >
> > > > > +{
> > > > >
> > > > > +  EFI_STATUS            Status;
> > > > >
> > > > > +  CHAR16                *Str;
> > > > >
> > > > > +  UINTN                 OtherPciFeatureConfigPhase;
> > > > >
> > > > > +
> > > > >
> > > > > +  //
> > > > >
> > > > > +  // check on PCI features configuration is complete and re-
> > enumeration is
> > > > > required
> > > > >
> > > > > +  //
> > > > >
> > > > > +  if ( !CheckPciFeaturesConfigurationRequired ( RootBridge)) {
> > > > >
> > > > > +    return EFI_ALREADY_STARTED;
> > > > >
> > > > > +  }
> > > > >
> > > > > +
> > > > >
> > > > > +  Str = ConvertDevicePathToText (
> > > > >
> > > > > +          DevicePathFromHandle (RootBridge->Handle),
> > > > >
> > > > > +          FALSE,
> > > > >
> > > > > +          FALSE
> > > > >
> > > > > +        );
> > > > >
> > > > > +  DEBUG ((DEBUG_INFO, "Enumerating PCI features for Root
> > Bridge %s\n",
> > > > > Str != NULL ? Str : L""));
> > > > >
> > > > > +
> > > > >
> > > > > +  for ( OtherPciFeatureConfigPhase = PciFeatureRootBridgeScan
> > > > >
> > > > > +      ; OtherPciFeatureConfigPhase <=
> > PciFeatureConfigurationComplete
> > > > >
> > > > > +      ; OtherPciFeatureConfigPhase++
> > > > >
> > > > > +      ) {
> > > > >
> > > > > +    switch ( OtherPciFeatureConfigPhase){
> > > > >
> > > > > +      case  PciFeatureRootBridgeScan:
> > > > >
> > > > > +        SetupPciFeaturesConfigurationDefaults ();
> > > > >
> > > > > +        //
> > > > >
> > > > > +        //first scan the entire root bridge heirarchy for the primary PCI
> > root
> > > > > ports
> > > > >
> > > > > +        //
> > > > >
> > > > > +        RecordPciRootPortBridges ( RootBridge);
> > > > >
> > > > > +        break;
> > > > >
> > > > > +
> > > > >
> > > > > +      case  PciFeatureGetDevicePolicy:
> > > > >
> > > > > +      case  PciFeatureSetupPhase:
> > > > >
> > > > > +        DEBUG ((
> > > > >
> > > > > +            DEBUG_INFO, "<<********** SetupPciFeatures - start
> > > > > **********>>\n"
> > > > >
> > > > > +        ));
> > > > >
> > > > > +        //
> > > > >
> > > > > +        // enumerate the other PCI features
> > > > >
> > > > > +        //
> > > > >
> > > > > +        Status = SetupPciFeatures ( RootBridge,
> > OtherPciFeatureConfigPhase);
> > > > >
> > > > > +
> > > > >
> > > > > +        DEBUG ((
> > > > >
> > > > > +            DEBUG_INFO, "<<********** SetupPciFeatures - end
> > > > > **********>>\n"
> > > > >
> > > > > +        ));
> > > > >
> > > > > +        break;
> > > > >
> > > > > +
> > > > >
> > > > > +      case  PciFeatureConfigurationPhase:
> > > > >
> > > > > +        //
> > > > >
> > > > > +        // override the PCI features as per enumeration phase
> > > > >
> > > > > +        //
> > > > >
> > > > > +        DEBUG ((DEBUG_INFO, "PCI features override for Root
> > Bridge %s\n",
> > > > > Str != NULL ? Str : L""));
> > > > >
> > > > > +        DEBUG ((
> > > > >
> > > > > +            DEBUG_INFO, "<<********** ProgramPciFeatures - start
> > > > > **********>>\n"
> > > > >
> > > > > +        ));
> > > > >
> > > > > +        Status = ProgramPciFeatures ( RootBridge);
> > > > >
> > > > > +        DEBUG ((
> > > > >
> > > > > +            DEBUG_INFO, "<<********** ProgramPciFeatures - end
> > > > > **********>>\n"
> > > > >
> > > > > +        ));
> > > > >
> > > > > +        break;
> > > > >
> > > > > +
> > > > >
> > > > > +      case  PciFeatureConfigurationComplete:
> > > > >
> > > > > +        //
> > > > >
> > > > > +        // clean up the temporary resource nodes created for this root
> > bridge
> > > > >
> > > > > +        //
> > > > >
> > > > > +        DestroyPrimaryRootPortNodes ();
> > > > >
> > > > > +
> > > > >
> > > > > +        ErasePciFeaturesConfigurationTable ();
> > > > >
> > > > > +    }
> > > > >
> > > > > +  }
> > > > >
> > > > > +
> > > > >
> > > > > +  if (Str != NULL) {
> > > > >
> > > > > +    FreePool (Str);
> > > > >
> > > > > +  }
> > > > >
> > > > > +  //
> > > > >
> > > > > +  // mark this root bridge as PCI features configuration complete, and
> > no
> > > > > new
> > > > >
> > > > > +  // enumeration is required
> > > > >
> > > > > +  //
> > > > >
> > > > > +  AddRootBridgeInPciFeaturesConfigCompletionList ( RootBridge,
> > FALSE);
> > > > >
> > > > > +  return Status;
> > > > >
> > > > > +}
> > > > >
> > > > > +
> > > > >
> > > > > +/**
> > > > >
> > > > > +  This routine is invoked from the Stop () interface for the EFI handle of
> > > > the
> > > > >
> > > > > +  RootBridge. Free up its node of type
> > > > > PCI_FEATURE_CONFIGURATION_COMPLETION_LIST.
> > > > >
> > > > > +
> > > > >
> > > > > +  @param  RootBridge      A pointer to the PCI_IO_DEVICE
> > > > >
> > > > > +**/
> > > > >
> > > > > +VOID
> > > > >
> > > > > +DestroyRootBridgePciFeaturesConfigCompletionList (
> > > > >
> > > > > +  IN PCI_IO_DEVICE          *RootBridge
> > > > >
> > > > > +  )
> > > > >
> > > > > +{
> > > > >
> > > > > +  LIST_ENTRY                                  *Link;
> > > > >
> > > > > +  PCI_FEATURE_CONFIGURATION_COMPLETION_LIST   *Temp;
> > > > >
> > > > > +
> > > > >
> > > > > +  if ( mPciFeaturesConfigurationCompletionList) {
> > > > >
> > > > > +    Link = &mPciFeaturesConfigurationCompletionList->RootBridgeLink;
> > > > >
> > > > > +
> > > > >
> > > > > +    do {
> > > > >
> > > > > +      Temp =
> > > > > PCI_FEATURE_CONFIGURATION_COMPLETION_LIST_FROM_LINK
> > (Link);
> > > > >
> > > > > +      if ( Temp->RootBridgeHandle == RootBridge->Handle) {
> > > > >
> > > > > +        RemoveEntryList ( Link);
> > > > >
> > > > > +        FreePool ( Temp);
> > > > >
> > > > > +        return;
> > > > >
> > > > > +      }
> > > > >
> > > > > +      Link = Link->ForwardLink;
> > > > >
> > > > > +    } while (Link != &mPciFeaturesConfigurationCompletionList-
> > > > > >RootBridgeLink);
> > > > >
> > > > > +  }
> > > > >
> > > > > +  //
> > > > >
> > > > > +  // not found on the PCI feature configuration completion list, return
> > > > >
> > > > > +  //
> > > > >
> > > > > +  return;
> > > > >
> > > > > +}
> > > > >
> > > > > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> > > > > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> > > > > new file mode 100644
> > > > > index 0000000000..9f225fa993
> > > > > --- /dev/null
> > > > > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> > > > > @@ -0,0 +1,201 @@
> > > > > +/** @file
> > > > >
> > > > > +  PCI standard feature support functions implementation for PCI Bus
> > > > > module..
> > > > >
> > > > > +
> > > > >
> > > > > +Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> > > > >
> > > > > +SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > >
> > > > > +
> > > > >
> > > > > +**/
> > > > >
> > > > > +
> > > > >
> > > > > +#ifndef _EFI_PCI_FEATURES_SUPPORT_H_
> > > > >
> > > > > +#define _EFI_PCI_FEATURES_SUPPORT_H_
> > > > >
> > > > > +
> > > > >
> > > > > +#include "PciBus.h"
> > > > >
> > > > > +#include "PciPlatformSupport.h"
> > > > >
> > > > > +
> > > > >
> > > > > +//
> > > > >
> > > > > +// Macro definitions for the PCI Features support PCD
> > > > >
> > > > > +//
> > > > >
> > > > > +#define PCI_FEATURE_SUPPORT_FLAG_MPS  BIT0
> > > > >
> > > > > +#define PCI_FEATURE_SUPPORT_FLAG_MRRS BIT1
> > > > >
> > > > > +
> > > > >
> > > > > +//
> > > > >
> > > > > +// defines the data structure to hold the details of the PCI Root port
> > > > devices
> > > > >
> > > > > +//
> > > > >
> > > > > +typedef struct _PRIMARY_ROOT_PORT_NODE
> > > > > PRIMARY_ROOT_PORT_NODE;
> > > > >
> > > > > +
> > > > >
> > > > > +//
> > > > >
> > > > > +// defines the data structure to hold the configuration data for the
> > other
> > > > > PCI
> > > > >
> > > > > +// features
> > > > >
> > > > > +//
> > > > >
> > > > > +typedef struct _OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > > > > OTHER_PCI_FEATURES_CONFIGURATION_TABLE;
> > > > >
> > > > > +
> > > > >
> > > > > +//
> > > > >
> > > > > +// Defines for the PCI features configuration completion and re-
> > > > > enumeration list
> > > > >
> > > > > +//
> > > > >
> > > > > +typedef struct _PCI_FEATURE_CONFIGURATION_COMPLETION_LIST
> > > > > PCI_FEATURE_CONFIGURATION_COMPLETION_LIST;
> > > > >
> > > > > +
> > > > >
> > > > > +//
> > > > >
> > > > > +// Signature value for the PCI Root Port node
> > > > >
> > > > > +//
> > > > >
> > > > > +#define PCI_ROOT_PORT_SIGNATURE               SIGNATURE_32 ('p', 'c',
> > 'i',
> > > > 'p')
> > > > >
> > > > > +
> > > > >
> > > > > +//
> > > > >
> > > > > +// Definitions of the PCI Root Port data structure members
> > > > >
> > > > > +//
> > > > >
> > > > > +struct _PRIMARY_ROOT_PORT_NODE {
> > > > >
> > > > > +  //
> > > > >
> > > > > +  // Signature header
> > > > >
> > > > > +  //
> > > > >
> > > > > +  UINT32                                    Signature;
> > > > >
> > > > > +  //
> > > > >
> > > > > +  // linked list pointers to next node
> > > > >
> > > > > +  //
> > > > >
> > > > > +  LIST_ENTRY                                NeighborRootPort;
> > > > >
> > > > > +  //
> > > > >
> > > > > +  // EFI handle of the parent Root Bridge instance
> > > > >
> > > > > +  //
> > > > >
> > > > > +  EFI_HANDLE                                RootBridgeHandle;
> > > > >
> > > > > +  //
> > > > >
> > > > > +  // EFI handle of the PCI controller
> > > > >
> > > > > +  //
> > > > >
> > > > > +  EFI_HANDLE                                RootPortHandle;
> > > > >
> > > > > +  //
> > > > >
> > > > > +  // PCI Secondary bus value of the PCI controller
> > > > >
> > > > > +  //
> > > > >
> > > > > +  UINT8                                     SecondaryBusStart;
> > > > >
> > > > > +  //
> > > > >
> > > > > +  // PCI Subordinate bus value of the PCI controller
> > > > >
> > > > > +  //
> > > > >
> > > > > +  UINT8                                     SecondaryBusEnd;
> > > > >
> > > > > +  //
> > > > >
> > > > > +  // pointer to the corresponding PCI feature configuration Table node
> > > > >
> > > > > +  //
> > > > >
> > > > > +  OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > > > > *OtherPciFeaturesConfigurationTable;
> > > > >
> > > > > +};
> > > > >
> > > > > +
> > > > >
> > > > > +#define PRIMARY_ROOT_PORT_NODE_FROM_LINK(a) \
> > > > >
> > > > > +  CR (a, PRIMARY_ROOT_PORT_NODE, NeighborRootPort,
> > > > > PCI_ROOT_PORT_SIGNATURE)
> > > > >
> > > > > +
> > > > >
> > > > > +//
> > > > >
> > > > > +// Definition of the PCI Feature configuration Table members
> > > > >
> > > > > +//
> > > > >
> > > > > +struct _OTHER_PCI_FEATURES_CONFIGURATION_TABLE {
> > > > >
> > > > > +  //
> > > > >
> > > > > +  // Configuration Table ID
> > > > >
> > > > > +  //
> > > > >
> > > > > +  UINTN                                     ID;
> > > > >
> > > > > +  //
> > > > >
> > > > > +  // to configure the PCI feature Maximum payload size to maintain the
> > > > data
> > > > > packet
> > > > >
> > > > > +  // size among all the PCI devices in the PCI hierarchy
> > > > >
> > > > > +  //
> > > > >
> > > > > +  UINT8                                     Max_Payload_Size;
> > > > >
> > > > > +  //
> > > > >
> > > > > +  // to configure the PCI feature maximum read request size to
> > maintain
> > > > the
> > > > > memory
> > > > >
> > > > > +  // requester size among all the PCI devices in the PCI hierarchy
> > > > >
> > > > > +  //
> > > > >
> > > > > +  UINT8                                     Max_Read_Request_Size;
> > > > >
> > > > > +  //
> > > > >
> > > > > +  // lock the Max_Read_Request_Size for the entire PCI tree of a root
> > port
> > > > >
> > > > > +  //
> > > > >
> > > > > +  BOOLEAN                                   Lock_Max_Read_Request_Size;
> > > > >
> > > > > +};
> > > > >
> > > > > +
> > > > >
> > > > > +
> > > > >
> > > > > +//
> > > > >
> > > > > +// PCI feature configuration node signature value
> > > > >
> > > > > +//
> > > > >
> > > > > +#define PCI_FEATURE_CONFIGURATION_SIGNATURE
> > > > > SIGNATURE_32 ('p', 'c', 'i', 'f')
> > > > >
> > > > > +
> > > > >
> > > > > +struct _PCI_FEATURE_CONFIGURATION_COMPLETION_LIST {
> > > > >
> > > > > +  //
> > > > >
> > > > > +  // Signature header
> > > > >
> > > > > +  //
> > > > >
> > > > > +  UINT32                                    Signature;
> > > > >
> > > > > +  //
> > > > >
> > > > > +  // link to next Root Bridge whose PCI Feature configuration is
> > complete
> > > > >
> > > > > +  //
> > > > >
> > > > > +  LIST_ENTRY                                RootBridgeLink;
> > > > >
> > > > > +  //
> > > > >
> > > > > +  // EFI handle of the Root Bridge whose PCI feature configuration is
> > > > > complete
> > > > >
> > > > > +  //
> > > > >
> > > > > +  EFI_HANDLE                                RootBridgeHandle;
> > > > >
> > > > > +  //
> > > > >
> > > > > +  // indication for complete re-enumeration of the PCI feature
> > > > configuration
> > > > >
> > > > > +  //
> > > > >
> > > > > +  BOOLEAN                                   ReEnumeratePciFeatureConfiguration;
> > > > >
> > > > > +};
> > > > >
> > > > > +
> > > > >
> > > > > +#define
> > > > > PCI_FEATURE_CONFIGURATION_COMPLETION_LIST_FROM_LINK(a) \
> > > > >
> > > > > +  CR (a, PCI_FEATURE_CONFIGURATION_COMPLETION_LIST,
> > > > > RootBridgeLink, PCI_FEATURE_CONFIGURATION_SIGNATURE)
> > > > >
> > > > > +
> > > > >
> > > > > +//
> > > > >
> > > > > +// Declaration of the internal sub-phases within the PCI Feature
> > > > > enumeration
> > > > >
> > > > > +//
> > > > >
> > > > > +typedef enum {
> > > > >
> > > > > +  //
> > > > >
> > > > > +  // initial phase in configuring the other PCI features to record the
> > primary
> > > > >
> > > > > +  // root ports
> > > > >
> > > > > +  //
> > > > >
> > > > > +  PciFeatureRootBridgeScan,
> > > > >
> > > > > +  //
> > > > >
> > > > > +  // get the PCI device-specific platform policies and align with device
> > > > > capabilities
> > > > >
> > > > > +  //
> > > > >
> > > > > +  PciFeatureGetDevicePolicy,
> > > > >
> > > > > +  //
> > > > >
> > > > > +  // align all PCI nodes in the PCI heirarchical tree
> > > > >
> > > > > +  //
> > > > >
> > > > > +  PciFeatureSetupPhase,
> > > > >
> > > > > +  //
> > > > >
> > > > > +  // finally override to complete configuration of the PCI feature
> > > > >
> > > > > +  //
> > > > >
> > > > > +  PciFeatureConfigurationPhase,
> > > > >
> > > > > +  //
> > > > >
> > > > > +  // PCI feature configuration complete
> > > > >
> > > > > +  //
> > > > >
> > > > > +  PciFeatureConfigurationComplete
> > > > >
> > > > > +
> > > > >
> > > > > +}PCI_FEATURE_CONFIGURATION_PHASE;
> > > > >
> > > > > +
> > > > >
> > > > > +/**
> > > > >
> > > > > +  Main routine to indicate platform selection of any of the other PCI
> > > > features
> > > > >
> > > > > +  to be configured by this driver
> > > > >
> > > > > +
> > > > >
> > > > > +  @retval TRUE    platform has selected the other PCI features to be
> > > > > configured
> > > > >
> > > > > +          FALSE   platform has not selected any of the other PCI features
> > > > >
> > > > > +**/
> > > > >
> > > > > +BOOLEAN
> > > > >
> > > > > +CheckOtherPciFeaturesPcd (
> > > > >
> > > > > +  );
> > > > >
> > > > > +
> > > > >
> > > > > +/**
> > > > >
> > > > > +  Enumerate all the nodes of the specified root bridge or PCI-PCI
> > Bridge, to
> > > > >
> > > > > +  configure the other PCI features.
> > > > >
> > > > > +
> > > > >
> > > > > +  @param RootBridge          A pointer to the PCI_IO_DEVICE.
> > > > >
> > > > > +
> > > > >
> > > > > +  @retval EFI_SUCCESS           The other PCI features configuration
> > during
> > > > > enumeration
> > > > >
> > > > > +                                of all the nodes of the PCI root bridge instance were
> > > > >
> > > > > +                                programmed in PCI-compliance pattern along with the
> > > > >
> > > > > +                                device-specific policy, as applicable.
> > > > >
> > > > > +  @retval EFI_UNSUPPORTED       One of the override operation maong
> > the
> > > > > nodes of
> > > > >
> > > > > +                                the PCI hierarchy resulted in a incompatible address
> > > > >
> > > > > +                                range.
> > > > >
> > > > > +  @retval EFI_INVALID_PARAMETER The override operation is
> > performed
> > > > > with invalid input
> > > > >
> > > > > +                                parameters.
> > > > >
> > > > > +**/
> > > > >
> > > > > +EFI_STATUS
> > > > >
> > > > > +EnumerateOtherPciFeatures (
> > > > >
> > > > > +  IN PCI_IO_DEVICE           *RootBridge
> > > > >
> > > > > +  );
> > > > >
> > > > > +
> > > > >
> > > > > +/**
> > > > >
> > > > > +  This routine is invoked from the Stop () interface for the EFI handle of
> > > > the
> > > > >
> > > > > +  RootBridge. Free up its node of type
> > > > > PCI_FEATURE_CONFIGURATION_COMPLETION_LIST.
> > > > >
> > > > > +
> > > > >
> > > > > +  @param  RootBridge      A pointer to the PCI_IO_DEVICE
> > > > >
> > > > > +**/
> > > > >
> > > > > +VOID
> > > > >
> > > > > +DestroyRootBridgePciFeaturesConfigCompletionList (
> > > > >
> > > > > +  IN PCI_IO_DEVICE          *RootBridge
> > > > >
> > > > > +  );
> > > > >
> > > > > +#endif
> > > > >
> > > > > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> > > > > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> > > > > new file mode 100644
> > > > > index 0000000000..d94037d69a
> > > > > --- /dev/null
> > > > > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> > > > > @@ -0,0 +1,565 @@
> > > > > +/** @file
> > > > >
> > > > > +  This file encapsulate the usage of PCI Platform Protocol
> > > > >
> > > > > +
> > > > >
> > > > > +  This file define the necessary hooks used to obtain the platform
> > > > >
> > > > > +  level data and policies which could be used in the PCI Enumeration
> > > > phases
> > > > >
> > > > > +
> > > > >
> > > > > +Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> > > > >
> > > > > +SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > >
> > > > > +
> > > > >
> > > > > +**/
> > > > >
> > > > > +
> > > > >
> > > > > +#include "PciPlatformSupport.h"
> > > > >
> > > > > +
> > > > >
> > > > > +EFI_PCI_PLATFORM_PROTOCOL                     *mPciPlatformProtocol;
> > > > >
> > > > > +EFI_PCI_OVERRIDE_PROTOCOL                     *mPciOverrideProtocol;
> > > > >
> > > > > +
> > > > >
> > > > > +EFI_PCI_PLATFORM_PROTOCOL2                    *mPciPlatformProtocol2;
> > > > >
> > > > > +EFI_PCI_OVERRIDE_PROTOCOL2                    *mPciOverrideProtocol2;
> > > > >
> > > > > +
> > > > >
> > > > > +
> > > > >
> > > > > +/**
> > > > >
> > > > > +  This function retrieves the PCI Platform Protocol published by
> > platform
> > > > > driver
> > > > >
> > > > > +
> > > > >
> > > > > +**/
> > > > >
> > > > > +VOID
> > > > >
> > > > > +GetPciPlatformProtocol (
> > > > >
> > > > > +  )
> > > > >
> > > > > +{
> > > > >
> > > > > +  mPciPlatformProtocol2 = NULL;
> > > > >
> > > > > +  gBS->LocateProtocol (
> > > > >
> > > > > +      &gEfiPciPlatformProtocol2Guid,
> > > > >
> > > > > +      NULL,
> > > > >
> > > > > +      (VOID **) &mPciPlatformProtocol2
> > > > >
> > > > > +  );
> > > > >
> > > > > +
> > > > >
> > > > > +  //
> > > > >
> > > > > +  // If PCI Platform protocol doesn't exist, try to get Pci Override
> > Protocol.
> > > > >
> > > > > +  //
> > > > >
> > > > > +  if (mPciPlatformProtocol2 == NULL) {
> > > > >
> > > > > +    mPciOverrideProtocol2 = NULL;
> > > > >
> > > > > +    gBS->LocateProtocol (
> > > > >
> > > > > +        &gEfiPciOverrideProtocol2Guid,
> > > > >
> > > > > +        NULL,
> > > > >
> > > > > +        (VOID **) &mPciOverrideProtocol2
> > > > >
> > > > > +    );
> > > > >
> > > > > +  }
> > > > >
> > > > > +  //
> > > > >
> > > > > +  // fetch the old PCI Platform Protocols if new are not installed
> > > > >
> > > > > +  //
> > > > >
> > > > > +  if (mPciOverrideProtocol2 == NULL) {
> > > > >
> > > > > +
> > > > >
> > > > > +    mPciPlatformProtocol = NULL;
> > > > >
> > > > > +    gBS->LocateProtocol (
> > > > >
> > > > > +        &gEfiPciPlatformProtocolGuid,
> > > > >
> > > > > +        NULL,
> > > > >
> > > > > +        (VOID **) &mPciPlatformProtocol
> > > > >
> > > > > +    );
> > > > >
> > > > > +
> > > > >
> > > > > +    //
> > > > >
> > > > > +    // If PCI Platform protocol doesn't exist, try to  get Pci Override
> > Protocol.
> > > > >
> > > > > +    //
> > > > >
> > > > > +    if (mPciPlatformProtocol == NULL) {
> > > > >
> > > > > +      mPciOverrideProtocol = NULL;
> > > > >
> > > > > +      gBS->LocateProtocol (
> > > > >
> > > > > +          &gEfiPciOverrideProtocolGuid,
> > > > >
> > > > > +          NULL,
> > > > >
> > > > > +          (VOID **) &mPciOverrideProtocol
> > > > >
> > > > > +      );
> > > > >
> > > > > +    }
> > > > >
> > > > > +  }
> > > > >
> > > > > +}
> > > > >
> > > > > +
> > > > >
> > > > > +/**
> > > > >
> > > > > +  This function indicates the presence of PCI Platform driver
> > > > >
> > > > > +  @retval     TRUE or FALSE
> > > > >
> > > > > +**/
> > > > >
> > > > > +BOOLEAN
> > > > >
> > > > > +CheckPciPlatformProtocolInstall (
> > > > >
> > > > > +  )
> > > > >
> > > > > +{
> > > > >
> > > > > +  if (mPciPlatformProtocol2 != NULL) {
> > > > >
> > > > > +    return TRUE;
> > > > >
> > > > > +  } else if (mPciOverrideProtocol2 != NULL) {
> > > > >
> > > > > +    return TRUE;
> > > > >
> > > > > +  } else {
> > > > >
> > > > > +    if (mPciPlatformProtocol != NULL) {
> > > > >
> > > > > +      return TRUE;
> > > > >
> > > > > +    } else if (mPciOverrideProtocol != NULL){
> > > > >
> > > > > +      return TRUE;
> > > > >
> > > > > +    }
> > > > >
> > > > > +  }
> > > > >
> > > > > +  return FALSE;
> > > > >
> > > > > +}
> > > > >
> > > > > +
> > > > >
> > > > > +/**
> > > > >
> > > > > +  Provides the hooks from the PCI bus driver to every PCI controller
> > > > > (device/function) at various
> > > > >
> > > > > +  stages of the PCI enumeration process that allow the host bridge
> > driver
> > > > to
> > > > > preinitialize individual
> > > > >
> > > > > +  PCI controllers before enumeration.
> > > > >
> > > > > +
> > > > >
> > > > > +  This function is called during the PCI enumeration process. No specific
> > > > > action is expected from this
> > > > >
> > > > > +  member function. It allows the host bridge driver to preinitialize
> > > > individual
> > > > > PCI controllers before
> > > > >
> > > > > +  enumeration.
> > > > >
> > > > > +
> > > > >
> > > > > +  @param[in] HostBridgeHandle     The associated PCI host bridge
> > handle.
> > > > >
> > > > > +  @param[in] RootBridgeHandle     The associated PCI root bridge
> > handle.
> > > > >
> > > > > +  @param[in] RootBridgePciAddress The address of the PCI device on
> > the
> > > > > PCI bus.
> > > > >
> > > > > +  @param[in] Phase          The phase of the PCI controller enumeration.
> > > > >
> > > > > +  @param[in] ExecPhase      Defines the execution phase of the PCI
> > chipset
> > > > > driver.
> > > > >
> > > > > +
> > > > >
> > > > > +  @retval    Status         returns the status from the PCI Platform
> > protocol as
> > > > is
> > > > >
> > > > > +
> > > > >
> > > > > +**/
> > > > >
> > > > > +EFI_STATUS
> > > > >
> > > > > +PciPlatformPreprocessController (
> > > > >
> > > > > +  IN EFI_HANDLE                                    HostBridgeHandle,
> > > > >
> > > > > +  IN EFI_HANDLE                                    RootBridgeHandle,
> > > > >
> > > > > +  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS
> > > > > RootBridgePciAddress,
> > > > >
> > > > > +  IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE  Phase,
> > > > >
> > > > > +  IN EFI_PCI_EXECUTION_PHASE                       ExecPhase
> > > > >
> > > > > +  )
> > > > >
> > > > > +{
> > > > >
> > > > > +  EFI_STATUS  Status;
> > > > >
> > > > > +
> > > > >
> > > > > +  if (mPciPlatformProtocol2 != NULL) {
> > > > >
> > > > > +    //
> > > > >
> > > > > +    // Call PlatformPci::PrepController() if the protocol is present.
> > > > >
> > > > > +    //
> > > > >
> > > > > +    Status = mPciPlatformProtocol2->PlatformPrepController (
> > > > >
> > > > > +
> > > > > (EFI_PCI_PLATFORM_PROTOCOL*)mPciPlatformProtocol2,
> > > > >
> > > > > +                                      HostBridgeHandle,
> > > > >
> > > > > +                                      RootBridgeHandle,
> > > > >
> > > > > +                                      RootBridgePciAddress,
> > > > >
> > > > > +                                      Phase,
> > > > >
> > > > > +                                      ExecPhase
> > > > >
> > > > > +                                    );
> > > > >
> > > > > +  } else if (mPciOverrideProtocol2 != NULL) {
> > > > >
> > > > > +    //
> > > > >
> > > > > +    // Call PlatformPci::PrepController() if the protocol is present.
> > > > >
> > > > > +    //
> > > > >
> > > > > +    Status = mPciOverrideProtocol2->PlatformPrepController (
> > > > >
> > > > > +
> > > > > (EFI_PCI_PLATFORM_PROTOCOL*)mPciOverrideProtocol2,
> > > > >
> > > > > +                                      HostBridgeHandle,
> > > > >
> > > > > +                                      RootBridgeHandle,
> > > > >
> > > > > +                                      RootBridgePciAddress,
> > > > >
> > > > > +                                      Phase,
> > > > >
> > > > > +                                      ExecPhase
> > > > >
> > > > > +                                    );
> > > > >
> > > > > +  } else {
> > > > >
> > > > > +    if (mPciPlatformProtocol != NULL) {
> > > > >
> > > > > +      //
> > > > >
> > > > > +      // Call PlatformPci::PrepController() if the protocol is present.
> > > > >
> > > > > +      //
> > > > >
> > > > > +      Status = mPciPlatformProtocol->PlatformPrepController (
> > > > >
> > > > > +                                      mPciPlatformProtocol,
> > > > >
> > > > > +                                      HostBridgeHandle,
> > > > >
> > > > > +                                      RootBridgeHandle,
> > > > >
> > > > > +                                      RootBridgePciAddress,
> > > > >
> > > > > +                                      Phase,
> > > > >
> > > > > +                                      ExecPhase
> > > > >
> > > > > +                                    );
> > > > >
> > > > > +    } else if (mPciOverrideProtocol != NULL) {
> > > > >
> > > > > +      //
> > > > >
> > > > > +      // Call PlatformPci::PrepController() if the protocol is present.
> > > > >
> > > > > +      //
> > > > >
> > > > > +      Status = mPciOverrideProtocol->PlatformPrepController (
> > > > >
> > > > > +                                      mPciOverrideProtocol,
> > > > >
> > > > > +                                      HostBridgeHandle,
> > > > >
> > > > > +                                      RootBridgeHandle,
> > > > >
> > > > > +                                      RootBridgePciAddress,
> > > > >
> > > > > +                                      Phase,
> > > > >
> > > > > +                                      ExecPhase
> > > > >
> > > > > +                                    );
> > > > >
> > > > > +    } else {
> > > > >
> > > > > +      //
> > > > >
> > > > > +      // return PCI Platform Protocol not found
> > > > >
> > > > > +      //
> > > > >
> > > > > +      return EFI_NOT_FOUND;
> > > > >
> > > > > +    }
> > > > >
> > > > > +  }
> > > > >
> > > > > +  return Status;
> > > > >
> > > > > +}
> > > > >
> > > > > +
> > > > >
> > > > > +/**
> > > > >
> > > > > +  This function notifies the PCI Platform driver about the PCI host
> > bridge
> > > > > resource
> > > > >
> > > > > +  allocation phase and PCI execution phase.
> > > > >
> > > > > +
> > > > >
> > > > > +  @param[in]  HostBridge     The handle of the host bridge controller.
> > > > >
> > > > > +  @param[in]  Phase          The phase of the PCI bus enumeration.
> > > > >
> > > > > +  @param[in]  ExecPhase      Defines the execution phase of the PCI
> > > > chipset
> > > > > driver.
> > > > >
> > > > > +  @retval     Status          returns the status from the PCI Platform
> > protocol
> > > > as
> > > > > is
> > > > >
> > > > > +
> > > > >
> > > > > +**/
> > > > >
> > > > > +EFI_STATUS
> > > > >
> > > > > +PciPlatformNotifyPhase (
> > > > >
> > > > > +  IN  EFI_HANDLE                                      HostBridgeHandle,
> > > > >
> > > > > +  IN  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE   Phase,
> > > > >
> > > > > +  IN  EFI_PCI_EXECUTION_PHASE                         ExecPhase
> > > > >
> > > > > +  )
> > > > >
> > > > > +{
> > > > >
> > > > > +  EFI_STATUS  Status;
> > > > >
> > > > > +
> > > > >
> > > > > +  if ( mPciPlatformProtocol2 != NULL) {
> > > > >
> > > > > +    Status = mPciPlatformProtocol2->PlatformNotify (
> > > > >
> > > > > +
> > > > > (EFI_PCI_PLATFORM_PROTOCOL*)mPciPlatformProtocol2,
> > > > >
> > > > > +                                      HostBridgeHandle,
> > > > >
> > > > > +                                      Phase,
> > > > >
> > > > > +                                      ExecPhase
> > > > >
> > > > > +                                    );
> > > > >
> > > > > +  } else if ( mPciOverrideProtocol2 != NULL) {
> > > > >
> > > > > +    Status = mPciOverrideProtocol2->PlatformNotify (
> > > > >
> > > > > +
> > > > > (EFI_PCI_PLATFORM_PROTOCOL*)mPciOverrideProtocol2,
> > > > >
> > > > > +                                      HostBridgeHandle,
> > > > >
> > > > > +                                      Phase,
> > > > >
> > > > > +                                      ExecPhase
> > > > >
> > > > > +                                    );
> > > > >
> > > > > +  } else {
> > > > >
> > > > > +
> > > > >
> > > > > +    if ( mPciPlatformProtocol != NULL) {
> > > > >
> > > > > +      Status = mPciPlatformProtocol->PlatformNotify (
> > > > >
> > > > > +                                      mPciPlatformProtocol,
> > > > >
> > > > > +                                      HostBridgeHandle,
> > > > >
> > > > > +                                      Phase,
> > > > >
> > > > > +                                      ExecPhase
> > > > >
> > > > > +                                    );
> > > > >
> > > > > +    } else if ( mPciOverrideProtocol != NULL){
> > > > >
> > > > > +      Status = mPciOverrideProtocol->PlatformNotify (
> > > > >
> > > > > +                                      mPciOverrideProtocol,
> > > > >
> > > > > +                                      HostBridgeHandle,
> > > > >
> > > > > +                                      Phase,
> > > > >
> > > > > +                                      ExecPhase
> > > > >
> > > > > +                                    );
> > > > >
> > > > > +    } else {
> > > > >
> > > > > +      //
> > > > >
> > > > > +      // return PCI Platform Protocol not found
> > > > >
> > > > > +      //
> > > > >
> > > > > +      return EFI_NOT_FOUND;
> > > > >
> > > > > +    }
> > > > >
> > > > > +  }
> > > > >
> > > > > +  return Status;
> > > > >
> > > > > +}
> > > > >
> > > > > +
> > > > >
> > > > > +/**
> > > > >
> > > > > +  This function retrieves the PCI platform policy.
> > > > >
> > > > > +
> > > > >
> > > > > +  @param  PciPolicy     pointer to the legacy
> > EFI_PCI_PLATFORM_POLICY
> > > > >
> > > > > +  @retval Status        returns the status from the PCI Platform protocol
> > as is
> > > > >
> > > > > +
> > > > >
> > > > > +**/
> > > > >
> > > > > +EFI_STATUS
> > > > >
> > > > > +PciGetPlatformPolicy (
> > > > >
> > > > > +  OUT EFI_PCI_PLATFORM_POLICY *PciPolicy
> > > > >
> > > > > +  )
> > > > >
> > > > > +{
> > > > >
> > > > > +  EFI_STATUS  Status;
> > > > >
> > > > > +
> > > > >
> > > > > +  if ( mPciPlatformProtocol2 != NULL) {
> > > > >
> > > > > +      Status = mPciPlatformProtocol2->GetPlatformPolicy (
> > > > >
> > > > > +
> > > > > (EFI_PCI_PLATFORM_PROTOCOL*)mPciPlatformProtocol2,
> > > > >
> > > > > +                                        PciPolicy
> > > > >
> > > > > +                                      );
> > > > >
> > > > > +  } else if ( mPciOverrideProtocol2 != NULL) {
> > > > >
> > > > > +      Status = mPciOverrideProtocol2->GetPlatformPolicy (
> > > > >
> > > > > +
> > > > > (EFI_PCI_PLATFORM_PROTOCOL*)mPciOverrideProtocol2,
> > > > >
> > > > > +                                        PciPolicy
> > > > >
> > > > > +                                      );
> > > > >
> > > > > +  } else {
> > > > >
> > > > > +    if ( mPciPlatformProtocol != NULL) {
> > > > >
> > > > > +      Status = mPciPlatformProtocol->GetPlatformPolicy (
> > > > >
> > > > > +                                      mPciPlatformProtocol,
> > > > >
> > > > > +                                      PciPolicy
> > > > >
> > > > > +                                    );
> > > > >
> > > > > +    }
> > > > >
> > > > > +
> > > > >
> > > > > +    if ( mPciOverrideProtocol != NULL) {
> > > > >
> > > > > +      Status = mPciOverrideProtocol->GetPlatformPolicy (
> > > > >
> > > > > +                                      mPciOverrideProtocol,
> > > > >
> > > > > +                                      PciPolicy
> > > > >
> > > > > +                                    );
> > > > >
> > > > > +    } else {
> > > > >
> > > > > +      //
> > > > >
> > > > > +      // return PCI Platform Protocol not found
> > > > >
> > > > > +      //
> > > > >
> > > > > +      return EFI_NOT_FOUND;
> > > > >
> > > > > +    }
> > > > >
> > > > > +  }
> > > > >
> > > > > +  return Status;
> > > > >
> > > > > +}
> > > > >
> > > > > +
> > > > >
> > > > > +/**
> > > > >
> > > > > +  This function retrieves the Option ROM image and size from the
> > Platform.
> > > > >
> > > > > +
> > > > >
> > > > > +  It uses the PCI_IO_DEVICE internal fields are used to store OpROM
> > > > > image/size
> > > > >
> > > > > +
> > > > >
> > > > > +  @param Controller     An EFI handle for the PCI bus controller.
> > > > >
> > > > > +  @param PciIoDevice    A PCI_IO_DEVICE pointer to the PCI IO device
> > to
> > > > be
> > > > > registered.
> > > > >
> > > > > +
> > > > >
> > > > > +  @retval EFI_SUCCESS            The option ROM was available for this
> > device
> > > > > and loaded into memory.
> > > > >
> > > > > +  @retval EFI_NOT_FOUND          No option ROM was available for this
> > > > device.
> > > > >
> > > > > +  @retval EFI_OUT_OF_RESOURCES   No memory was available to load
> > the
> > > > > option ROM.
> > > > >
> > > > > +  @retval EFI_DEVICE_ERROR       An error occurred in obtaining the
> > option
> > > > > ROM.
> > > > >
> > > > > +
> > > > >
> > > > > +**/
> > > > >
> > > > > +EFI_STATUS
> > > > >
> > > > > +GetPlatformPciOptionRom (
> > > > >
> > > > > +  IN  EFI_HANDLE                    Controller,
> > > > >
> > > > > +  IN  PCI_IO_DEVICE                 *PciIoDevice
> > > > >
> > > > > +  )
> > > > >
> > > > > +{
> > > > >
> > > > > +  EFI_STATUS  Status;
> > > > >
> > > > > +  VOID        *PlatformOpRomBuffer;
> > > > >
> > > > > +  UINTN       PlatformOpRomSize;
> > > > >
> > > > > +
> > > > >
> > > > > +  if (mPciPlatformProtocol2 != NULL) {
> > > > >
> > > > > +    Status = mPciPlatformProtocol2->GetPciRom (
> > > > >
> > > > > +
> > > > > (EFI_PCI_PLATFORM_PROTOCOL*)mPciPlatformProtocol2,
> > > > >
> > > > > +                                      PciIoDevice->Handle,
> > > > >
> > > > > +                                      &PlatformOpRomBuffer,
> > > > >
> > > > > +                                      &PlatformOpRomSize
> > > > >
> > > > > +                                      );
> > > > >
> > > > > +  } else if (mPciOverrideProtocol2 != NULL) {
> > > > >
> > > > > +    Status = mPciOverrideProtocol2->GetPciRom (
> > > > >
> > > > > +
> > > > > (EFI_PCI_PLATFORM_PROTOCOL*)mPciOverrideProtocol2,
> > > > >
> > > > > +                                      PciIoDevice->Handle,
> > > > >
> > > > > +                                      &PlatformOpRomBuffer,
> > > > >
> > > > > +                                      &PlatformOpRomSize
> > > > >
> > > > > +                                      );
> > > > >
> > > > > +  } else {
> > > > >
> > > > > +    if (mPciPlatformProtocol != NULL) {
> > > > >
> > > > > +      Status = mPciPlatformProtocol->GetPciRom (
> > > > >
> > > > > +                                      mPciPlatformProtocol,
> > > > >
> > > > > +                                      PciIoDevice->Handle,
> > > > >
> > > > > +                                      &PlatformOpRomBuffer,
> > > > >
> > > > > +                                      &PlatformOpRomSize
> > > > >
> > > > > +                                      );
> > > > >
> > > > > +    } else if (mPciOverrideProtocol != NULL) {
> > > > >
> > > > > +      Status = mPciOverrideProtocol->GetPciRom (
> > > > >
> > > > > +                                        mPciOverrideProtocol,
> > > > >
> > > > > +                                        PciIoDevice->Handle,
> > > > >
> > > > > +                                        &PlatformOpRomBuffer,
> > > > >
> > > > > +                                        &PlatformOpRomSize
> > > > >
> > > > > +                                        );
> > > > >
> > > > > +    } else {
> > > > >
> > > > > +      //
> > > > >
> > > > > +      // return PCI Platform Protocol not found
> > > > >
> > > > > +      //
> > > > >
> > > > > +      return EFI_NOT_FOUND;
> > > > >
> > > > > +    }
> > > > >
> > > > > +  }
> > > > >
> > > > > +
> > > > >
> > > > > +  if (!EFI_ERROR (Status)) {
> > > > >
> > > > > +    PciIoDevice->EmbeddedRom    = FALSE;
> > > > >
> > > > > +    PciIoDevice->RomSize        = (UINT32)PlatformOpRomSize;
> > > > >
> > > > > +    PciIoDevice->PciIo.RomSize  = PlatformOpRomSize;
> > > > >
> > > > > +    PciIoDevice->PciIo.RomImage = PlatformOpRomBuffer;
> > > > >
> > > > > +  }
> > > > >
> > > > > +  return Status;
> > > > >
> > > > > +}
> > > > >
> > > > > +
> > > > >
> > > > > +/**
> > > > >
> > > > > +  Helper routine to indicate whether the given PCI device specific
> > policy
> > > > > value
> > > > >
> > > > > +  dictates to override the Max_Payload_Size to a particular value, or
> > set as
> > > > > per
> > > > >
> > > > > +  device capability.
> > > > >
> > > > > +
> > > > >
> > > > > +  @param  MPS     Input device-specific policy should be in terms of
> > type
> > > > >
> > > > > +                  EFI_PCI_CONF_MAX_PAYLOAD_SIZE
> > > > >
> > > > > +
> > > > >
> > > > > +  @retval TRUE    Setup Max_Payload_Size as per device capability
> > > > >
> > > > > +          FALSE   override as per device-specific platform policy
> > > > >
> > > > > +**/
> > > > >
> > > > > +BOOLEAN
> > > > >
> > > > > +SetupMpsAsPerDeviceCapability (
> > > > >
> > > > > +  IN  UINT8                   MPS
> > > > >
> > > > > +)
> > > > >
> > > > > +{
> > > > >
> > > > > +  if ( MPS == EFI_PCI_CONF_MAX_PAYLOAD_SIZE_AUTO) {
> > > > >
> > > > > +    return TRUE;
> > > > >
> > > > > +  } else {
> > > > >
> > > > > +    return FALSE;
> > > > >
> > > > > +  }
> > > > >
> > > > > +}
> > > > >
> > > > > +
> > > > >
> > > > > +/**
> > > > >
> > > > > +  Helper routine to indicate whether the given PCI device specific
> > policy
> > > > > value
> > > > >
> > > > > +  dictates to override the Max_Read_Req_Size to a particular value, or
> > set
> > > > as
> > > > > per
> > > > >
> > > > > +  device capability.
> > > > >
> > > > > +
> > > > >
> > > > > +  @param  MRRS    Input device-specific policy should be in terms of
> > type
> > > > >
> > > > > +                  EFI_PCI_CONF_MAX_READ_REQ_SIZE
> > > > >
> > > > > +
> > > > >
> > > > > +  @retval TRUE    Setup Max_Read_Req_Size as per device capability
> > > > >
> > > > > +          FALSE   override as per device-specific platform policy
> > > > >
> > > > > +**/
> > > > >
> > > > > +BOOLEAN
> > > > >
> > > > > +SetupMrrsAsPerDeviceCapability (
> > > > >
> > > > > +  IN  UINT8                   MRRS
> > > > >
> > > > > +)
> > > > >
> > > > > +{
> > > > >
> > > > > +  if ( MRRS == EFI_PCI_CONF_MAX_READ_REQ_SIZE_AUTO) {
> > > > >
> > > > > +    return TRUE;
> > > > >
> > > > > +  } else {
> > > > >
> > > > > +    return FALSE;
> > > > >
> > > > > +  }
> > > > >
> > > > > +}
> > > > >
> > > > > +
> > > > >
> > > > > +/**
> > > > >
> > > > > +  Routine to translate the given device-specific platform policy from
> > type
> > > > >
> > > > > +  EFI_PCI_CONF_MAX_PAYLOAD_SIZE to HW-specific value, as per PCI
> > > > Base
> > > > > Specification
> > > > >
> > > > > +  Revision 4.0; for the PCI feature Max_Payload_Size.
> > > > >
> > > > > +
> > > > >
> > > > > +  @param  MPS     Input device-specific policy should be in terms of
> > type
> > > > >
> > > > > +                  EFI_PCI_CONF_MAX_PAYLOAD_SIZE
> > > > >
> > > > > +
> > > > >
> > > > > +  @retval         Range values for the Max_Payload_Size as defined in the
> > > > PCI
> > > > >
> > > > > +                  Base Specification 4.0
> > > > >
> > > > > +**/
> > > > >
> > > > > +UINT8
> > > > >
> > > > > +TranslateMpsSetupValueToPci (
> > > > >
> > > > > +  IN  UINT8                   MPS
> > > > >
> > > > > +)
> > > > >
> > > > > +{
> > > > >
> > > > > +  switch (MPS) {
> > > > >
> > > > > +    case EFI_PCI_CONF_MAX_PAYLOAD_SIZE_128B:
> > > > >
> > > > > +      return PCIE_MAX_PAYLOAD_SIZE_128B;
> > > > >
> > > > > +    case EFI_PCI_CONF_MAX_PAYLOAD_SIZE_256B:
> > > > >
> > > > > +      return PCIE_MAX_PAYLOAD_SIZE_256B;
> > > > >
> > > > > +    case EFI_PCI_CONF_MAX_PAYLOAD_SIZE_512B:
> > > > >
> > > > > +      return PCIE_MAX_PAYLOAD_SIZE_512B;
> > > > >
> > > > > +    case EFI_PCI_CONF_MAX_PAYLOAD_SIZE_1024B:
> > > > >
> > > > > +      return PCIE_MAX_PAYLOAD_SIZE_1024B;
> > > > >
> > > > > +    case EFI_PCI_CONF_MAX_PAYLOAD_SIZE_2048B:
> > > > >
> > > > > +      return PCIE_MAX_PAYLOAD_SIZE_2048B;
> > > > >
> > > > > +    case EFI_PCI_CONF_MAX_PAYLOAD_SIZE_4096B:
> > > > >
> > > > > +      return PCIE_MAX_PAYLOAD_SIZE_4096B;
> > > > >
> > > > > +    default:
> > > > >
> > > > > +      return PCIE_MAX_PAYLOAD_SIZE_128B;
> > > > >
> > > > > +  }
> > > > >
> > > > > +}
> > > > >
> > > > > +
> > > > >
> > > > > +/**
> > > > >
> > > > > +  Routine to translate the given device-specific platform policy from
> > type
> > > > >
> > > > > +  EFI_PCI_CONF_MAX_READ_REQ_SIZE to HW-specific value, as per
> > PCI
> > > > > Base Specification
> > > > >
> > > > > +  Revision 4.0; for the PCI feature Max_Read_Req_Size.
> > > > >
> > > > > +
> > > > >
> > > > > +  @param  MRRS    Input device-specific policy should be in terms of
> > type
> > > > >
> > > > > +                  EFI_PCI_CONF_MAX_READ_REQ_SIZE
> > > > >
> > > > > +
> > > > >
> > > > > +  @retval         Range values for the Max_Read_Req_Size as defined in
> > the
> > > > > PCI
> > > > >
> > > > > +                  Base Specification 4.0
> > > > >
> > > > > +**/
> > > > >
> > > > > +UINT8
> > > > >
> > > > > +TranslateMrrsSetupValueToPci (
> > > > >
> > > > > +  IN  UINT8                   MRRS
> > > > >
> > > > > +)
> > > > >
> > > > > +{
> > > > >
> > > > > +  switch (MRRS) {
> > > > >
> > > > > +    case EFI_PCI_CONF_MAX_READ_REQ_SIZE_128B:
> > > > >
> > > > > +      return PCIE_MAX_READ_REQ_SIZE_128B;
> > > > >
> > > > > +    case EFI_PCI_CONF_MAX_READ_REQ_SIZE_256B:
> > > > >
> > > > > +      return PCIE_MAX_READ_REQ_SIZE_256B;
> > > > >
> > > > > +    case EFI_PCI_CONF_MAX_READ_REQ_SIZE_512B:
> > > > >
> > > > > +      return PCIE_MAX_READ_REQ_SIZE_512B;
> > > > >
> > > > > +    case EFI_PCI_CONF_MAX_READ_REQ_SIZE_1024B:
> > > > >
> > > > > +      return PCIE_MAX_READ_REQ_SIZE_1024B;
> > > > >
> > > > > +    case EFI_PCI_CONF_MAX_READ_REQ_SIZE_2048B:
> > > > >
> > > > > +      return PCIE_MAX_READ_REQ_SIZE_2048B;
> > > > >
> > > > > +    case EFI_PCI_CONF_MAX_READ_REQ_SIZE_4096B:
> > > > >
> > > > > +      return PCIE_MAX_READ_REQ_SIZE_4096B;
> > > > >
> > > > > +    default:
> > > > >
> > > > > +      return PCIE_MAX_READ_REQ_SIZE_128B;
> > > > >
> > > > > +  }
> > > > >
> > > > > +}
> > > > >
> > > > > +
> > > > >
> > > > > +/**
> > > > >
> > > > > +  Generic routine to setup the PCI features as per its predetermined
> > > > > defaults.
> > > > >
> > > > > +**/
> > > > >
> > > > > +VOID
> > > > >
> > > > > +SetupDefaultsDevicePlatformPolicy (
> > > > >
> > > > > +  IN  PCI_IO_DEVICE               *PciDevice
> > > > >
> > > > > +  )
> > > > >
> > > > > +{
> > > > >
> > > > > +  PciDevice->SetupMPS = EFI_PCI_CONF_MAX_PAYLOAD_SIZE_AUTO;
> > > > >
> > > > > +  PciDevice->SetupMRRS =
> > EFI_PCI_CONF_MAX_READ_REQ_SIZE_AUTO;
> > > > >
> > > > > +}
> > > > >
> > > > > +
> > > > >
> > > > > +/**
> > > > >
> > > > > +  Intermediate routine to either get the PCI device specific platform
> > > > policies
> > > > >
> > > > > +  through the PCI Platform Protocol, or its alias the PCI Override
> > Protocol.
> > > > >
> > > > > +
> > > > >
> > > > > +  @param  PciIoDevice         A pointer to PCI_IO_DEVICE
> > > > >
> > > > > +  @param  PciPlatformProtocol A pointer to
> > > > > EFI_PCI_PLATFORM_PROTOCOL2
> > > > >
> > > > > +
> > > > >
> > > > > +  @retval EFI_STATUS          The direct status from the PCI Platform
> > Protocol
> > > > >
> > > > > +  @retval EFI_SUCCESS         if on returning predetermined PCI features
> > > > > defaults,
> > > > >
> > > > > +                              for the case when protocol returns as
> > EFI_UNSUPPORTED
> > > > >
> > > > > +                              to indicate PCI device exist and it has no platform
> > > > >
> > > > > +                              policy defined.
> > > > >
> > > > > +**/
> > > > >
> > > > > +EFI_STATUS
> > > > >
> > > > > +GetPciDevicePlatformPolicyEx (
> > > > >
> > > > > +  IN  PCI_IO_DEVICE               *PciIoDevice,
> > > > >
> > > > > +  IN  EFI_PCI_PLATFORM_PROTOCOL2  *PciPlatformProtocol
> > > > >
> > > > > +  )
> > > > >
> > > > > +{
> > > > >
> > > > > +  EFI_PCI_PLATFORM_EXTENDED_POLICY  PciPlatformExtendedPolicy;
> > > > >
> > > > > +  EFI_STATUS                        Status;
> > > > >
> > > > > +
> > > > >
> > > > > +  ZeroMem ( &PciPlatformExtendedPolicy, sizeof
> > > > > (EFI_PCI_PLATFORM_EXTENDED_POLICY));
> > > > >
> > > > > +  Status = PciPlatformProtocol->GetDevicePolicy (
> > > > >
> > > > > +                                  PciPlatformProtocol,
> > > > >
> > > > > +                                  PciIoDevice->Handle,
> > > > >
> > > > > +                                  &PciPlatformExtendedPolicy
> > > > >
> > > > > +                                  );
> > > > >
> > > > > +  //
> > > > >
> > > > > +  // platform chipset policies are returned for this PCI device
> > > > >
> > > > > +  //
> > > > >
> > > > > +  if (!EFI_ERROR(Status)) {
> > > > >
> > > > > +    PciIoDevice->SetupMPS = PciPlatformExtendedPolicy.DeviceCtlMPS;
> > > > >
> > > > > +    PciIoDevice->SetupMRRS =
> > PciPlatformExtendedPolicy.DeviceCtlMRRS;
> > > > >
> > > > > +  }
> > > > >
> > > > > +  //
> > > > >
> > > > > +  // platform chipset policies are not provided for this PCI device
> > > > >
> > > > > +  //
> > > > >
> > > > > +  if (EFI_ERROR(Status) == EFI_UNSUPPORTED) {
> > > > >
> > > > > +    //
> > > > >
> > > > > +    // let the enumeration happen as per the PCI standard way
> > > > >
> > > > > +    //
> > > > >
> > > > > +    SetupDefaultsDevicePlatformPolicy ( PciIoDevice);
> > > > >
> > > > > +    return EFI_SUCCESS;
> > > > >
> > > > > +  }
> > > > >
> > > > > +
> > > > >
> > > > > +  return Status;
> > > > >
> > > > > +}
> > > > >
> > > > > +
> > > > >
> > > > > +/**
> > > > >
> > > > > +  Gets the PCI device-specific platform policy from the PCI Platform
> > > > Protocol.
> > > > >
> > > > > +  If no PCI Platform protocol is published than setup the PCI feature to
> > > > > predetermined
> > > > >
> > > > > +  defaults, in order to align all the PCI devices in the PCI hierarchy, as
> > > > > applicable.
> > > > >
> > > > > +
> > > > >
> > > > > +  @param  PciDevice     A pointer to PCI_IO_DEVICE
> > > > >
> > > > > +
> > > > >
> > > > > +  @retval EFI_STATUS    The direct status from the PCI Platform
> > Protocol
> > > > >
> > > > > +  @retval EFI_SUCCESS   On return of predetermined PCI features
> > defaults,
> > > > > for
> > > > >
> > > > > +                        the case when protocol returns as EFI_UNSUPPORTED to
> > > > >
> > > > > +                        indicate PCI device exist and it has no platform policy
> > > > >
> > > > > +                        defined. Also, on returns when no PCI Platform Protocol
> > > > >
> > > > > +                        exist.
> > > > >
> > > > > +**/
> > > > >
> > > > > +EFI_STATUS
> > > > >
> > > > > +GetPciDevicePlatformPolicy (
> > > > >
> > > > > +  IN PCI_IO_DEVICE          *PciDevice
> > > > >
> > > > > +  )
> > > > >
> > > > > +{
> > > > >
> > > > > +  if ( mPciPlatformProtocol2 != NULL) {
> > > > >
> > > > > +    return GetPciDevicePlatformPolicyEx ( PciDevice,
> > > > mPciPlatformProtocol2);
> > > > >
> > > > > +  } else if (mPciOverrideProtocol2 != NULL) {
> > > > >
> > > > > +    return GetPciDevicePlatformPolicyEx ( PciDevice,
> > > > mPciOverrideProtocol2);
> > > > >
> > > > > +  } else {
> > > > >
> > > > > +    //
> > > > >
> > > > > +    // new PCI Platform Protocol 2 is not installed; let the enumeration
> > > > > happen
> > > > >
> > > > > +    // as per PCI standard way
> > > > >
> > > > > +    //
> > > > >
> > > > > +    SetupDefaultsDevicePlatformPolicy ( PciDevice);
> > > > >
> > > > > +    return EFI_SUCCESS;
> > > > >
> > > > > +  }
> > > > >
> > > > > +}
> > > > >
> > > > > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
> > > > > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
> > > > > new file mode 100644
> > > > > index 0000000000..d54e46b950
> > > > > --- /dev/null
> > > > > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
> > > > > @@ -0,0 +1,193 @@
> > > > > +/** @file
> > > > >
> > > > > +  This file encapsulate the usage of PCI Platform Protocol
> > > > >
> > > > > +
> > > > >
> > > > > +  This file define the necessary hooks used to obtain the platform
> > > > >
> > > > > +  level data and policies which could be used in the PCI Enumeration
> > > > phases
> > > > >
> > > > > +
> > > > >
> > > > > +Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> > > > >
> > > > > +SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > >
> > > > > +
> > > > >
> > > > > +**/
> > > > >
> > > > > +
> > > > >
> > > > > +
> > > > >
> > > > > +#ifndef _EFI_PCI_PLATFORM_SUPPORT_H_
> > > > >
> > > > > +#define _EFI_PCI_PLATFORM_SUPPORT_H_
> > > > >
> > > > > +
> > > > >
> > > > > +#include "PciBus.h"
> > > > >
> > > > > +
> > > > >
> > > > > +/**
> > > > >
> > > > > +  This function retrieves the PCI Platform Protocol published by
> > platform
> > > > > driver
> > > > >
> > > > > +
> > > > >
> > > > > +**/
> > > > >
> > > > > +VOID
> > > > >
> > > > > +GetPciPlatformProtocol (
> > > > >
> > > > > +  );
> > > > >
> > > > > +
> > > > >
> > > > > +/**
> > > > >
> > > > > +  This function indicates the presence of PCI Platform driver
> > > > >
> > > > > +  @retval     TRUE or FALSE
> > > > >
> > > > > +**/
> > > > >
> > > > > +BOOLEAN
> > > > >
> > > > > +CheckPciPlatformProtocolInstall (
> > > > >
> > > > > +  );
> > > > >
> > > > > +
> > > > >
> > > > > +
> > > > >
> > > > > +/**
> > > > >
> > > > > +  Provides the hooks from the PCI bus driver to every PCI controller
> > > > > (device/function) at various
> > > > >
> > > > > +  stages of the PCI enumeration process that allow the host bridge
> > driver
> > > > to
> > > > > preinitialize individual
> > > > >
> > > > > +  PCI controllers before enumeration.
> > > > >
> > > > > +
> > > > >
> > > > > +  This function is called during the PCI enumeration process. No specific
> > > > > action is expected from this
> > > > >
> > > > > +  member function. It allows the host bridge driver to preinitialize
> > > > individual
> > > > > PCI controllers before
> > > > >
> > > > > +  enumeration.
> > > > >
> > > > > +
> > > > >
> > > > > +  @param[in] HostBridgeHandle     The associated PCI host bridge
> > handle.
> > > > >
> > > > > +  @param[in] RootBridgeHandle     The associated PCI root bridge
> > handle.
> > > > >
> > > > > +  @param[in] RootBridgePciAddress The address of the PCI device on
> > the
> > > > > PCI bus.
> > > > >
> > > > > +  @param[in] Phase          The phase of the PCI controller enumeration.
> > > > >
> > > > > +  @param[in] ExecPhase      Defines the execution phase of the PCI
> > chipset
> > > > > driver.
> > > > >
> > > > > +
> > > > >
> > > > > +  @retval    Status         returns the status from the PCI Platform
> > protocol as
> > > > is
> > > > >
> > > > > +
> > > > >
> > > > > +**/
> > > > >
> > > > > +EFI_STATUS
> > > > >
> > > > > +PciPlatformPreprocessController (
> > > > >
> > > > > +  IN EFI_HANDLE                                    HostBridgeHandle,
> > > > >
> > > > > +  IN EFI_HANDLE                                    RootBridgeHandle,
> > > > >
> > > > > +  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS
> > > > > RootBridgePciAddress,
> > > > >
> > > > > +  IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE  Phase,
> > > > >
> > > > > +  IN EFI_PCI_EXECUTION_PHASE                       ExecPhase
> > > > >
> > > > > +  );
> > > > >
> > > > > +
> > > > >
> > > > > +/**
> > > > >
> > > > > +  This function notifies the PCI Platform driver about the PCI host
> > bridge
> > > > > resource
> > > > >
> > > > > +  allocation phase and PCI execution phase.
> > > > >
> > > > > +
> > > > >
> > > > > +  @param[in]  HostBridge     The handle of the host bridge controller.
> > > > >
> > > > > +  @param[in]  Phase          The phase of the PCI bus enumeration.
> > > > >
> > > > > +  @param[in]  ExecPhase      Defines the execution phase of the PCI
> > > > chipset
> > > > > driver.
> > > > >
> > > > > +  @retval     Status          returns the status from the PCI Platform
> > protocol
> > > > as
> > > > > is
> > > > >
> > > > > +
> > > > >
> > > > > +**/
> > > > >
> > > > > +EFI_STATUS
> > > > >
> > > > > +PciPlatformNotifyPhase (
> > > > >
> > > > > +  IN  EFI_HANDLE                                      HostBridgeHandle,
> > > > >
> > > > > +  IN  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE   Phase,
> > > > >
> > > > > +  IN  EFI_PCI_EXECUTION_PHASE                         ExecPhase
> > > > >
> > > > > +  );
> > > > >
> > > > > +
> > > > >
> > > > > +/**
> > > > >
> > > > > +  This function retrieves the PCI platform policy.
> > > > >
> > > > > +
> > > > >
> > > > > +  @param  PciPolicy     pointer to the legacy
> > EFI_PCI_PLATFORM_POLICY
> > > > >
> > > > > +  @retval Status        returns the status from the PCI Platform protocol
> > as is
> > > > >
> > > > > +
> > > > >
> > > > > +**/
> > > > >
> > > > > +EFI_STATUS
> > > > >
> > > > > +PciGetPlatformPolicy (
> > > > >
> > > > > +  OUT EFI_PCI_PLATFORM_POLICY *PciPolicy
> > > > >
> > > > > +  );
> > > > >
> > > > > +
> > > > >
> > > > > +/**
> > > > >
> > > > > +  This function retrieves the Option ROM image and size from the
> > Platform.
> > > > >
> > > > > +
> > > > >
> > > > > +  It uses the PCI_IO_DEVICE internal fields are used to store OpROM
> > > > > image/size
> > > > >
> > > > > +
> > > > >
> > > > > +  @param Controller     An EFI handle for the PCI bus controller.
> > > > >
> > > > > +  @param PciIoDevice    A PCI_IO_DEVICE pointer to the PCI IO device
> > to
> > > > be
> > > > > registered.
> > > > >
> > > > > +
> > > > >
> > > > > +  @retval EFI_SUCCESS            The option ROM was available for this
> > device
> > > > > and loaded into memory.
> > > > >
> > > > > +  @retval EFI_NOT_FOUND          No option ROM was available for this
> > > > device.
> > > > >
> > > > > +  @retval EFI_OUT_OF_RESOURCES   No memory was available to load
> > the
> > > > > option ROM.
> > > > >
> > > > > +  @retval EFI_DEVICE_ERROR       An error occurred in obtaining the
> > option
> > > > > ROM.
> > > > >
> > > > > +
> > > > >
> > > > > +**/
> > > > >
> > > > > +EFI_STATUS
> > > > >
> > > > > +GetPlatformPciOptionRom (
> > > > >
> > > > > +  IN  EFI_HANDLE                    Controller,
> > > > >
> > > > > +  IN  PCI_IO_DEVICE                 *PciIoDevice
> > > > >
> > > > > +  );
> > > > >
> > > > > +
> > > > >
> > > > > +/**
> > > > >
> > > > > +  Gets the PCI device-specific platform policy from the PCI Platform
> > > > Protocol.
> > > > >
> > > > > +  If no PCI Platform protocol is published than setup the PCI feature to
> > > > > predetermined
> > > > >
> > > > > +  defaults, in order to align all the PCI devices in the PCI hierarchy, as
> > > > > applicable.
> > > > >
> > > > > +
> > > > >
> > > > > +  @param  PciDevice     A pointer to PCI_IO_DEVICE
> > > > >
> > > > > +
> > > > >
> > > > > +  @retval EFI_STATUS    The direct status from the PCI Platform
> > Protocol
> > > > >
> > > > > +  @retval EFI_SUCCESS   On return of predetermined PCI features
> > defaults,
> > > > > for
> > > > >
> > > > > +                        the case when protocol returns as EFI_UNSUPPORTED to
> > > > >
> > > > > +                        indicate PCI device exist and it has no platform policy
> > > > >
> > > > > +                        defined. Also, on returns when no PCI Platform Protocol
> > > > >
> > > > > +                        exist.
> > > > >
> > > > > +**/
> > > > >
> > > > > +EFI_STATUS
> > > > >
> > > > > +GetPciDevicePlatformPolicy (
> > > > >
> > > > > +  IN PCI_IO_DEVICE          *PciDevice
> > > > >
> > > > > +  );
> > > > >
> > > > > +
> > > > >
> > > > > +/**
> > > > >
> > > > > +  Helper routine to indicate whether the given PCI device specific
> > policy
> > > > > value
> > > > >
> > > > > +  dictates to override the Max_Payload_Size to a particular value, or
> > set as
> > > > > per
> > > > >
> > > > > +  device capability.
> > > > >
> > > > > +
> > > > >
> > > > > +  @param  MPS     Input device-specific policy should be in terms of
> > type
> > > > >
> > > > > +                  EFI_PCI_CONF_MAX_PAYLOAD_SIZE
> > > > >
> > > > > +
> > > > >
> > > > > +  @retval TRUE    Setup Max_Payload_Size as per device capability
> > > > >
> > > > > +          FALSE   override as per device-specific platform policy
> > > > >
> > > > > +**/
> > > > >
> > > > > +BOOLEAN
> > > > >
> > > > > +SetupMpsAsPerDeviceCapability (
> > > > >
> > > > > +  IN  UINT8                   MPS
> > > > >
> > > > > +);
> > > > >
> > > > > +
> > > > >
> > > > > +/**
> > > > >
> > > > > +  Helper routine to indicate whether the given PCI device specific
> > policy
> > > > > value
> > > > >
> > > > > +  dictates to override the Max_Read_Req_Size to a particular value, or
> > set
> > > > as
> > > > > per
> > > > >
> > > > > +  device capability.
> > > > >
> > > > > +
> > > > >
> > > > > +  @param  MRRS    Input device-specific policy should be in terms of
> > type
> > > > >
> > > > > +                  EFI_PCI_CONF_MAX_READ_REQ_SIZE
> > > > >
> > > > > +
> > > > >
> > > > > +  @retval TRUE    Setup Max_Read_Req_Size as per device capability
> > > > >
> > > > > +          FALSE   override as per device-specific platform policy
> > > > >
> > > > > +**/
> > > > >
> > > > > +BOOLEAN
> > > > >
> > > > > +SetupMrrsAsPerDeviceCapability (
> > > > >
> > > > > +  IN  UINT8                   MRRS
> > > > >
> > > > > +);
> > > > >
> > > > > +
> > > > >
> > > > > +/**
> > > > >
> > > > > +  Routine to translate the given device-specific platform policy from
> > type
> > > > >
> > > > > +  EFI_PCI_CONF_MAX_PAYLOAD_SIZE to HW-specific value, as per PCI
> > > > Base
> > > > > Specification
> > > > >
> > > > > +  Revision 4.0; for the PCI feature Max_Payload_Size.
> > > > >
> > > > > +
> > > > >
> > > > > +  @param  MPS     Input device-specific policy should be in terms of
> > type
> > > > >
> > > > > +                  EFI_PCI_CONF_MAX_PAYLOAD_SIZE
> > > > >
> > > > > +
> > > > >
> > > > > +  @retval         Range values for the Max_Payload_Size as defined in the
> > > > PCI
> > > > >
> > > > > +                  Base Specification 4.0
> > > > >
> > > > > +**/
> > > > >
> > > > > +UINT8
> > > > >
> > > > > +TranslateMpsSetupValueToPci (
> > > > >
> > > > > +  IN  UINT8                   MPS
> > > > >
> > > > > +);
> > > > >
> > > > > +
> > > > >
> > > > > +/**
> > > > >
> > > > > +  Routine to translate the given device-specific platform policy from
> > type
> > > > >
> > > > > +  EFI_PCI_CONF_MAX_READ_REQ_SIZE to HW-specific value, as per
> > PCI
> > > > > Base Specification
> > > > >
> > > > > +  Revision 4.0; for the PCI feature Max_Read_Req_Size.
> > > > >
> > > > > +
> > > > >
> > > > > +  @param  MRRS    Input device-specific policy should be in terms of
> > type
> > > > >
> > > > > +                  EFI_PCI_CONF_MAX_READ_REQ_SIZE
> > > > >
> > > > > +
> > > > >
> > > > > +  @retval         Range values for the Max_Read_Req_Size as defined in
> > the
> > > > > PCI
> > > > >
> > > > > +                  Base Specification 4.0
> > > > >
> > > > > +**/
> > > > >
> > > > > +UINT8
> > > > >
> > > > > +TranslateMrrsSetupValueToPci (
> > > > >
> > > > > +  IN  UINT8                   MRRS
> > > > >
> > > > > +);
> > > > >
> > > > > +#endif
> > > > >
> > > > > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c
> > > > > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c
> > > > > index 4969ee0f64..755423f77b 100644
> > > > > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c
> > > > > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c
> > > > > @@ -198,20 +198,7 @@ CalculateApertureIo16 (
> > > > >      //
> > > > >
> > > > >      Status = EFI_NOT_FOUND;
> > > > >
> > > > >      PciPolicy = 0;
> > > > >
> > > > > -    if (gPciPlatformProtocol != NULL) {
> > > > >
> > > > > -      Status = gPciPlatformProtocol->GetPlatformPolicy (
> > > > >
> > > > > -                                       gPciPlatformProtocol,
> > > > >
> > > > > -                                       &PciPolicy
> > > > >
> > > > > -                                       );
> > > > >
> > > > > -    }
> > > > >
> > > > > -
> > > > >
> > > > > -    if (EFI_ERROR (Status) && gPciOverrideProtocol != NULL) {
> > > > >
> > > > > -      Status = gPciOverrideProtocol->GetPlatformPolicy (
> > > > >
> > > > > -                                       gPciOverrideProtocol,
> > > > >
> > > > > -                                       &PciPolicy
> > > > >
> > > > > -                                       );
> > > > >
> > > > > -    }
> > > > >
> > > > > -
> > > > >
> > > > > +    Status = PciGetPlatformPolicy ( &PciPolicy);
> > > > >
> > > > >      if (!EFI_ERROR (Status)) {
> > > > >
> > > > >        if ((PciPolicy & EFI_RESERVE_ISA_IO_ALIAS) != 0) {
> > > > >
> > > > >          mReserveIsaAliases = TRUE;
> > > > >
> > > > > diff --git a/MdeModulePkg/MdeModulePkg.dec
> > > > > b/MdeModulePkg/MdeModulePkg.dec
> > > > > index 17beb45235..7bcbe5a3ea 100644
> > > > > --- a/MdeModulePkg/MdeModulePkg.dec
> > > > > +++ b/MdeModulePkg/MdeModulePkg.dec
> > > > > @@ -1026,6 +1026,16 @@
> > > > >    # @Prompt Enable UEFI Stack Guard.
> > > > >
> > > > >
> > > > >
> > > >
> > gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard|FALSE|BOOLEAN|0
> > > > > x30001055
> > > > >
> > > > >
> > > > >
> > > > > +  ## This PCD is to indicate the PCI Bus driver to setup other new PCI
> > > > > features.
> > > > >
> > > > > +  #  Each PCI feature is represented by its mask bit position and it
> > > > configures
> > > > >
> > > > > +  #  if that bit is set.
> > > > >
> > > > > +  #
> > > > >
> > > > > +  #   Bit 0 - if set, the PCI Bus driver programs the device's
> > > > > Max_Payload_Size.<BR>
> > > > >
> > > > > +  #   Bit 1 - if set, the PCI Bus driver programs the device's
> > > > > Max_Read_Req_Size.<BR>
> > > > >
> > > > > +  #   Bit 2 to 31 - Reserved for future use by the PCI Bus driver.<BR>
> > > > >
> > > > > +  # @Prompt The UEFI PCU Bus driver enables the new set of other PCI
> > > > > Features.
> > > > >
> > > > > +
> > > > >
> > > >
> > gEfiMdeModulePkgTokenSpaceGuid.PcdOtherPciFeatures|0x00000003|UIN
> > > > > T32|0x30001056
> > > > >
> > > > > +
> > > > >
> > > > >  [PcdsFixedAtBuild, PcdsPatchableInModule]
> > > > >
> > > > >    ## Dynamic type PCD can be registered callback function for Pcd
> > setting
> > > > > action.
> > > > >
> > > > >    #  PcdMaxPeiPcdCallBackNumberPerPcdEntry indicates the maximum
> > > > > number of callback function
> > > > >
> > > > > --
> > > > > 2.21.0.windows.1


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

View/Reply Online (#48987): https://edk2.groups.io/g/devel/message/48987
Mute This Topic: https://groups.io/mt/34264504/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub  [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-

Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH] PciBusDxe: New PCI features Max_Payload_Size, Max_Read_Req_Size
Posted by Ni, Ray 4 years, 5 months ago
> > > > 1. IsPciRootPortEmpty(): can you just check whether PciDevice-
> >ChildList is
> > > > empty by using IsListEmpty (&PciDevice->ChildList)?
> > > OK, will do the additional check.
> >
> > Can that be the only check?
> It cannot be the only check when I am parsing the list as it is going to loop
> over; or may be where exactly you want to have this check? I understand it
> can be the first check before traversing the list.

My idea is:
  BOOLEAN
  IsPciRootPortEmpty(PciIoDevice) {
    Return IsListEmpty (&PciIoDevice->ChildLIst);
  }

> 
> >
> > >
> > > > 2. Can you point to me which spec requires the MPS to be 128 for
> empty
> > > root
> > > > ports?
> > > Refer the PCI Express Base Specification Revision 5, chapter 7.5.3.4
> > > Implementation Notes section.
> > Can you please paste the specific wording that supports the logic to
> program
> > MPS to 128B for empty root ports?
> > Below wording seems to require 128B only for special OSes that don't
> support
> > PCIE.
> > " For example, if the operating system environment does not comprehend
> PCI
> > Express, firmware probably should
> > not program a non-default Max_Payload_Size for a hierarchy that supports
> Hot-
> > Plug operations"
> Yes; since the PCI Bus driver does not know what OS it is going to boot to, it
> has to assume for the worst and set it to default, or leave it to default as the
> HW default is set to 128B. Besides, the Max_Payload_Size is for the Data
> Packet size,  since the PCI RP is empty there is no point changing to any other
> value as there won't be any PCI transactions.

Agree.

> 
> >
> > >
> > > > 3. GetPciRootPortBusAssigned() is dangerous because it assumes the
> input
> > > > PciDevice points to the bridge.
> > > Good catch! Will make the right change.
> >
> > As we discussed over phone, using device path can eliminate the needs of
> > comparing bus number. Then this function is not needed.
> Yes, I am looking towards that direction.

Thanks.

> 
> >
> > >
> > > > 4. RecordPciRootPortBridges() could be simplified to just collect all
> > > PciDevice
> > > > instances who:
> > > >     a. belongs to the linked list of the root bridge
> > > >     b. is a bridge
> > > I can see if I can optimize further, but do note that I need to align the PCI
> > > feature Max_Payload_Size and Max_Read_Request_Size among all the
> child
> > > PCI devices of the Root Port (RP) in the Root Complex (RC) and since a
> single
> > > RC is known to have multiple RP I need to maintain the list of all the
> primary
> > > RP in the Root Bridge handle so that each primary RP can have its PCI
> > > configuration table to track the Max_Payload_Size and
> > > Max_Read_Request_Size that needs to be assigned to all its child PCI
> devices
> > > in the tree.
> >
> > I am not suggesting to stop collecting all root ports.
> > Can you simplify the logic of RecordPciRootPortBridges() as below?
> >   for each node in PciRootBridge.ChildList:
> >     if (!IsListEmpty (node.ChildList)) {
> >       RootPortList.add (node)
> OK, will do.

Thanks.

> 
> >
> > > > > 2. GetPciPlatformProtocol(): better to rename to InitializePciPlatform
> ().
> > > To me, the word "Initialize" would mean also installing the PCI Platform
> > > Protocol which is not the case with the PCI Bus driver; since it only fetches
> > > the existing protocol already installed by the platform...
> > I agree with your concern : )
> > But "Get" means to return the PciPlatform protocol back through function
> return
> > result.
> > How about "Locate"?
> Ok, will use this key word.

Thanks.

> 
> >
> > >
> > > > > 3. Why the type cast is needed in below code? If it is because
> > > PciPlatform2
> > > > > protocol reuses the prototype of GetPciRom defined for PciPlatform
> > > protocol,
> > > > > I suggest you define GetPciRom for PciPlatform2. Type redefinition
> > > seems a
> > > > > duplication. But below type-cast is more annoyed.
> > > > >
> > > > >     Status = mPciPlatformProtocol2->GetPciRom (
> > > > >
> > > > (EFI_PCI_PLATFORM_PROTOCOL*)mPciPlatformProtocol2,
> > > > >                                       PciIoDevice->Handle,
> > > > >                                       &PlatformOpRomBuffer,
> > > > >                                       &PlatformOpRomSize
> > > > >                                       );
> > > > >
> > > Yes, the PciPlatform2.h which I had submitted to the edk2-staging branch
> > > previously; includes the PciPlatform.h during compilation. Even I was
> thinking
> > > the same and since the new definition of the PCI Platform Protocol has to
> > > used in future; I can port the legacy definitions into the new definition
> source
> > > file itself to avoid further change in future.
> >
> > Thanks.
> >
> > >
> > > > > 4. Please run ECC tool and fix all coding style issue
> > > I thought the ECC tool is used once the changes are submitted into the
> > > Gerritt by the maintainer; it is good if I can use it offline; please let me
> know
> > > where to get this tool.
> >
> > The tool is inside BaseTools\BinWrappers\WindowsLike\Ecc.bat.
> Thanks! Will use this. By the way; I did make the code changes by referring
> the "EDK-II C Coding Style Standards Specification".

I saw several coding style issues so I asked you to run the tool.
e.g.:
1. "if (!Pointer)" should be "if (Pointer != NULL)"
2. "Function ( parameter);" should be "Function (parameter);" // no space before 1st parameter
3. "if (...) <\n> {" should be "if (...) {" // no new-line before "{"


> 
> >
> > >
> > > > > 5. I don't quite understand what *primary* PCI root port is. So I don't
> > > quite
> > > > > understand what RecordPciRootPortBridges() does.
> > > I used the word primary for the PCI Root port to indicate the first level
> Root
> > > port in the RC of the host; there can be multiple first level PCI RP in the
> Root
> > > Bridge handle and each RP can have its downstream hierarchy which in
> turn
> > > can be the PCIe-PCIe/PCI/PCI-X bridge devices and its endpoint devices.
> > > Since the RP and its downstream PCI bridges both have the same PCI
> Type 1
> > > PCI Configuration header, I have to maintain the list of first level RP of the
> > > Root Bridge handle.
> > >
> > > > >
> > > > > Thanks,
> > > > > Ray
> > > > >
> > > > > > -----Original Message-----
> > > > > > From: Javeed, Ashraf <ashraf.javeed@intel.com>
> > > > > > Sent: Monday, September 23, 2019 10:21 PM
> > > > > > To: devel@edk2.groups.io
> > > > > > Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A
> > > > > <hao.a.wu@intel.com>;
> > > > > > Ni, Ray <ray.ni@intel.com>
> > > > > > Subject: [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH] PciBusDxe:
> New
> > > PCI
> > > > > > features Max_Payload_Size, Max_Read_Req_Size
> > > > > >
> > > > > > REF: https://bugzilla.tianocore.org/show_bug.cgi?id=2194
> > > > > >
> > > > > > The EDK2 Kernel PciBusDxe driver is enhanced to enable the
> > > configuration
> > > > > > of PCI features like Max_Payload_Size and Max_Read_Req_Size.
> > > > > >
> > > > > > Max_Payload_Size:- The PCI Device Control register provides this
> > > feature
> > > > > > register field which controls the maximum data packet (TLP) size
> that a
> > > > > > PCI device should maintain as a requester. The PCI Bus driver is
> > > required
> > > > > > to maintain a highest common value supported by all the PCI
> devices in
> > > a
> > > > > > PCIe hierarchy, especially in case of isochronous applications.
> > > > > >
> > > > > > Max_Read_Req_Size:- The PCI Device Control register provides this
> > > > > feature
> > > > > > register field which controls the maximum memory read request
> size
> > > that a
> > > > > > PCI device should maintain as a requester. The PCI Bus driver is
> > > required
> > > > > > to maintain a common value, same as Max_Payload_Size, in case of
> > > > > > isochronous applications only; or else, it should maintain the user
> > > > > > requested value uniformly in a PCIe hierarchy (PCI root port and its
> > > > > > downstream devices).
> > > > > >
> > > > > > The PCI Base Specification 4 Revision 1 contains detailed information
> > > > > > about these features. The EDK2 PCI Bus driver needs to enable the
> > > > > > configuration of these features as per the PCI Base specification.
> > > > > >
> > > > > > The EDK2 PCI Bus driver also needs to take the PCI device-specific
> > > > > > platform policy into the consideration while programming these
> > > features;
> > > > > > thus the code changes to support these, is explicitly dependent on
> the
> > > > > > new PCI Platform Protocol interface definition defined in the below
> > > > > > record:-
> > > > > > https://bugzilla.tianocore.org/show_bug.cgi?id=1954
> > > > > >
> > > > > > Signed-off-by: Ashraf Javeed <ashraf.javeed@intel.com>
> > > > > > Cc: Jian J Wang <jian.j.wang@intel.com>
> > > > > > Cc: Hao A Wu <hao.a.wu@intel.com>
> > > > > > Cc: Ray Ni <ray.ni@intel.com>
> > > > > > ---
> > > > > >  MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c               |   23 ++--------
> ----
> > > > > >  MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h               |   14
> ++++++++-
> > > > > >  MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf          |    9 +++++-
> > > > > >  MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c     |  229
> > > > > >
> > > > >
> > >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > > > ++++++++++++++++++++++++++++--------------------------------------
> ----
> > > -----
> > > > > -
> > > > > >  MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c        |  139
> > > > > > ++++++++++++++++++++---------------------------------------------------
> ----
> > > ----
> > > > > ---
> > > > > >  MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c |   34
> > > > > > ++++++++++++--------
> > > > > >  MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c    | 1601
> > > > > >
> > > > >
> > >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > > >
> > > > >
> > >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > > >
> > > > >
> > >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > > >
> > > > >
> > >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > > >
> > > > >
> > >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > > >
> > > > >
> > >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > > >
> > > > >
> > >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > > >
> > > > >
> > >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > > >
> > > > >
> > >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > > >
> > > > >
> > >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > > >
> > > > >
> > >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > > >
> > > > >
> > >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > > >
> > > > >
> > >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > > >
> > > > >
> > >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > > >
> > > > >
> > >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > > >
> > > > >
> > >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > > > +++++++++
> > > > > >  MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h    |  201
> > > > > >
> > > > >
> > >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > > >
> > > > >
> > >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > > > ++
> > > > > >  MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c   |  565
> > > > > >
> > > > >
> > >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > > >
> > > > >
> > >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > > >
> > > > >
> > >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > > >
> > > > >
> > >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > > >
> > > > >
> > >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > > > +++++++++++++++++++++++++++++++++++++++++
> > > > > >  MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h   |  193
> > > > > >
> > > > >
> > >
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > > >
> > > +++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > > >  MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c   |   15
> +-----
> > > ---
> > > > > >  MdeModulePkg/MdeModulePkg.dec                         |   10 ++++++
> > > > > >  12 files changed, 2797 insertions(+), 236 deletions(-)
> > > > > >
> > > > > > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c
> > > > > > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c
> > > > > > index b020ce50ce..2503b298f4 100644
> > > > > > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c
> > > > > > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c
> > > > > > @@ -8,7 +8,7 @@
> > > > > >    PCI Root Bridges. So it means platform needs install PCI Root
> Bridge IO
> > > > > > protocol for each
> > > > > >
> > > > > >    PCI Root Bus and install PCI Host Bridge Resource Allocation
> Protocol.
> > > > > >
> > > > > >
> > > > > >
> > > > > > -Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
> > > > > >
> > > > > > +Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
> > > > > >
> > > > > >  SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > > >
> > > > > >
> > > > > >
> > > > > >  **/
> > > > > >
> > > > > > @@ -34,8 +34,6 @@ BOOLEAN                                       gFullEnumeration
> > =
> > > > > TRUE;
> > > > > >  UINT64                                        gAllOne              =
> 0xFFFFFFFFFFFFFFFFULL;
> > > > > >
> > > > > >  UINT64                                        gAllZero             = 0;
> > > > > >
> > > > > >
> > > > > >
> > > > > > -EFI_PCI_PLATFORM_PROTOCOL                     *gPciPlatformProtocol;
> > > > > >
> > > > > > -EFI_PCI_OVERRIDE_PROTOCOL                     *gPciOverrideProtocol;
> > > > > >
> > > > > >  EDKII_IOMMU_PROTOCOL                          *mIoMmuProtocol;
> > > > > >
> > > > > >
> > > > > >
> > > > > >
> > > > > >
> > > > > > @@ -266,24 +264,7 @@ PciBusDriverBindingStart (
> > > > > >    // If PCI Platform protocol is available, get it now.
> > > > > >
> > > > > >    // If the platform implements this, it must be installed before BDS
> > > phase
> > > > > >
> > > > > >    //
> > > > > >
> > > > > > -  gPciPlatformProtocol = NULL;
> > > > > >
> > > > > > -  gBS->LocateProtocol (
> > > > > >
> > > > > > -        &gEfiPciPlatformProtocolGuid,
> > > > > >
> > > > > > -        NULL,
> > > > > >
> > > > > > -        (VOID **) &gPciPlatformProtocol
> > > > > >
> > > > > > -        );
> > > > > >
> > > > > > -
> > > > > >
> > > > > > -  //
> > > > > >
> > > > > > -  // If PCI Platform protocol doesn't exist, try to Pci Override
> Protocol.
> > > > > >
> > > > > > -  //
> > > > > >
> > > > > > -  if (gPciPlatformProtocol == NULL) {
> > > > > >
> > > > > > -    gPciOverrideProtocol = NULL;
> > > > > >
> > > > > > -    gBS->LocateProtocol (
> > > > > >
> > > > > > -          &gEfiPciOverrideProtocolGuid,
> > > > > >
> > > > > > -          NULL,
> > > > > >
> > > > > > -          (VOID **) &gPciOverrideProtocol
> > > > > >
> > > > > > -          );
> > > > > >
> > > > > > -  }
> > > > > >
> > > > > > +  GetPciPlatformProtocol ();
> > > > > >
> > > > > >
> > > > > >
> > > > > >    if (mIoMmuProtocol == NULL) {
> > > > > >
> > > > > >      gBS->LocateProtocol (
> > > > > >
> > > > > > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> > > > > > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> > > > > > index 504a1b1c12..7955bf8a26 100644
> > > > > > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> > > > > > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> > > > > > @@ -27,6 +27,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > > >  #include <Protocol/PciOverride.h>
> > > > > >
> > > > > >  #include <Protocol/PciEnumerationComplete.h>
> > > > > >
> > > > > >  #include <Protocol/IoMmu.h>
> > > > > >
> > > > > > +#include <Protocol/PciPlatform2.h>
> > > > > >
> > > > > > +#include <Protocol/PciOverride2.h>
> > > > > >
> > > > > >
> > > > > >
> > > > > >  #include <Library/DebugLib.h>
> > > > > >
> > > > > >  #include <Library/UefiDriverEntryPoint.h>
> > > > > >
> > > > > > @@ -79,6 +81,7 @@ typedef enum {
> > > > > >  #include "PciPowerManagement.h"
> > > > > >
> > > > > >  #include "PciHotPlugSupport.h"
> > > > > >
> > > > > >  #include "PciLib.h"
> > > > > >
> > > > > > +#include "PciFeatureSupport.h"
> > > > > >
> > > > > >
> > > > > >
> > > > > >  #define VGABASE1  0x3B0
> > > > > >
> > > > > >  #define VGALIMIT1 0x3BB
> > > > > >
> > > > > > @@ -263,9 +266,13 @@ struct _PCI_IO_DEVICE {
> > > > > >
> > > > > >
> > > > > >    BOOLEAN                                   IsPciExp;
> > > > > >
> > > > > >    //
> > > > > >
> > > > > > -  // For SR-IOV
> > > > > >
> > > > > > +  // For PCI Express Capability List Structure
> > > > > >
> > > > > >    //
> > > > > >
> > > > > >    UINT8                                     PciExpressCapabilityOffset;
> > > > > >
> > > > > > +  PCI_CAPABILITY_PCIEXP                     PciExpStruct;
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  // For SR-IOV
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > >    UINT32                                    AriCapabilityOffset;
> > > > > >
> > > > > >    UINT32                                    SrIovCapabilityOffset;
> > > > > >
> > > > > >    UINT32                                    MrIovCapabilityOffset;
> > > > > >
> > > > > > @@ -279,6 +286,11 @@ struct _PCI_IO_DEVICE {
> > > > > >    // This field is used to support this case.
> > > > > >
> > > > > >    //
> > > > > >
> > > > > >    UINT16                                    BridgeIoAlignment;
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  // Other PCI features setup flags
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  UINT8                                     SetupMPS;
> > > > > >
> > > > > > +  UINT8                                     SetupMRRS;
> > > > > >
> > > > > >  };
> > > > > >
> > > > > >
> > > > > >
> > > > > >  #define PCI_IO_DEVICE_FROM_PCI_IO_THIS(a) \
> > > > > >
> > > > > > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
> > > > > > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
> > > > > > index 05c22025b8..13768d7ded 100644
> > > > > > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
> > > > > > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
> > > > > > @@ -2,7 +2,7 @@
> > > > > >  #  The PCI bus driver will probe all PCI devices and allocate MMIO
> and
> > > IO
> > > > > > space for these devices.
> > > > > >
> > > > > >  #  Please use PCD feature flag PcdPciBusHotplugDeviceSupport to
> > > enable
> > > > > > hot plug supporting.
> > > > > >
> > > > > >  #
> > > > > >
> > > > > > -#  Copyright (c) 2006 - 2018, Intel Corporation. All rights
> reserved.<BR>
> > > > > >
> > > > > > +#  Copyright (c) 2006 - 2019, Intel Corporation. All rights
> reserved.<BR>
> > > > > >
> > > > > >  #
> > > > > >
> > > > > >  #  SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > > >
> > > > > >  #
> > > > > >
> > > > > > @@ -57,6 +57,10 @@
> > > > > >    PciCommand.h
> > > > > >
> > > > > >    PciIo.h
> > > > > >
> > > > > >    PciBus.h
> > > > > >
> > > > > > +  PciFeatureSupport.c
> > > > > >
> > > > > > +  PciFeatureSupport.h
> > > > > >
> > > > > > +  PciPlatformSupport.c
> > > > > >
> > > > > > +  PciPlatformSupport.h
> > > > > >
> > > > > >
> > > > > >
> > > > > >  [Packages]
> > > > > >
> > > > > >    MdePkg/MdePkg.dec
> > > > > >
> > > > > > @@ -91,6 +95,8 @@
> > > > > >    gEfiLoadFile2ProtocolGuid                       ## SOMETIMES_PRODUCES
> > > > > >
> > > > > >    gEdkiiIoMmuProtocolGuid                         ##
> SOMETIMES_CONSUMES
> > > > > >
> > > > > >    gEfiLoadedImageDevicePathProtocolGuid           ## CONSUMES
> > > > > >
> > > > > > +  gEfiPciPlatformProtocol2Guid                     ##
> SOMETIMES_CONSUMES
> > > > > >
> > > > > > +  gEfiPciOverrideProtocol2Guid                     ##
> SOMETIMES_CONSUMES
> > > > > >
> > > > > >
> > > > > >
> > > > > >  [FeaturePcd]
> > > > > >
> > > > > >
> gEfiMdeModulePkgTokenSpaceGuid.PcdPciBusHotplugDeviceSupport
> > > > > ##
> > > > > > CONSUMES
> > > > > >
> > > > > > @@ -104,6 +110,7 @@
> > > > > >    gEfiMdeModulePkgTokenSpaceGuid.PcdAriSupport                  ##
> > > > > CONSUMES
> > > > > >
> > > > > >    gEfiMdeModulePkgTokenSpaceGuid.PcdMrIovSupport                ##
> > > > > > CONSUMES
> > > > > >
> > > > > >
> gEfiMdeModulePkgTokenSpaceGuid.PcdPciDisableBusEnumeration
> > > ##
> > > > > > SOMETIMES_CONSUMES
> > > > > >
> > > > > > +  gEfiMdeModulePkgTokenSpaceGuid.PcdOtherPciFeatures
> > > ##
> > > > > > CONSUMES
> > > > > >
> > > > > >
> > > > > >
> > > > > >  [UserExtensions.TianoCore."ExtraFiles"]
> > > > > >
> > > > > >    PciBusDxeExtra.uni
> > > > > >
> > > > > > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
> > > > > > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
> > > > > > index b7832c6970..0f76ab1cd5 100644
> > > > > > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
> > > > > > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
> > > > > > @@ -170,6 +170,8 @@ DestroyRootBridgeByHandle (
> > > > > >
> > > > > >
> > > > > >      if (Temp->Handle == Controller) {
> > > > > >
> > > > > >
> > > > > >
> > > > > > +      DestroyRootBridgePciFeaturesConfigCompletionList ( Temp);
> > > > > >
> > > > > > +
> > > > > >
> > > > > >        RemoveEntryList (CurrentLink);
> > > > > >
> > > > > >
> > > > > >
> > > > > >        DestroyPciDeviceTree (Temp);
> > > > > >
> > > > > > @@ -208,8 +210,6 @@ RegisterPciDevice (
> > > > > >    )
> > > > > >
> > > > > >  {
> > > > > >
> > > > > >    EFI_STATUS          Status;
> > > > > >
> > > > > > -  VOID                *PlatformOpRomBuffer;
> > > > > >
> > > > > > -  UINTN               PlatformOpRomSize;
> > > > > >
> > > > > >    EFI_PCI_IO_PROTOCOL *PciIo;
> > > > > >
> > > > > >    UINT8               Data8;
> > > > > >
> > > > > >    BOOLEAN             HasEfiImage;
> > > > > >
> > > > > > @@ -244,49 +244,13 @@ RegisterPciDevice (
> > > > > >      //
> > > > > >
> > > > > >      // Get the OpRom provided by platform
> > > > > >
> > > > > >      //
> > > > > >
> > > > > > -    if (gPciPlatformProtocol != NULL) {
> > > > > >
> > > > > > -      Status = gPciPlatformProtocol->GetPciRom (
> > > > > >
> > > > > > -                                       gPciPlatformProtocol,
> > > > > >
> > > > > > -                                       PciIoDevice->Handle,
> > > > > >
> > > > > > -                                       &PlatformOpRomBuffer,
> > > > > >
> > > > > > -                                       &PlatformOpRomSize
> > > > > >
> > > > > > -                                       );
> > > > > >
> > > > > > -      if (!EFI_ERROR (Status)) {
> > > > > >
> > > > > > -        PciIoDevice->EmbeddedRom    = FALSE;
> > > > > >
> > > > > > -        PciIoDevice->RomSize        = (UINT32) PlatformOpRomSize;
> > > > > >
> > > > > > -        PciIoDevice->PciIo.RomSize  = PlatformOpRomSize;
> > > > > >
> > > > > > -        PciIoDevice->PciIo.RomImage = PlatformOpRomBuffer;
> > > > > >
> > > > > > -        //
> > > > > >
> > > > > > -        // For OpROM read from gPciPlatformProtocol:
> > > > > >
> > > > > > -        // Add the Rom Image to internal database for later PCI light
> > > > > > enumeration
> > > > > >
> > > > > > -        //
> > > > > >
> > > > > > -        PciRomAddImageMapping (
> > > > > >
> > > > > > -          NULL,
> > > > > >
> > > > > > -          PciIoDevice->PciRootBridgeIo->SegmentNumber,
> > > > > >
> > > > > > -          PciIoDevice->BusNumber,
> > > > > >
> > > > > > -          PciIoDevice->DeviceNumber,
> > > > > >
> > > > > > -          PciIoDevice->FunctionNumber,
> > > > > >
> > > > > > -          PciIoDevice->PciIo.RomImage,
> > > > > >
> > > > > > -          PciIoDevice->PciIo.RomSize
> > > > > >
> > > > > > -          );
> > > > > >
> > > > > > -      }
> > > > > >
> > > > > > -    } else if (gPciOverrideProtocol != NULL) {
> > > > > >
> > > > > > -      Status = gPciOverrideProtocol->GetPciRom (
> > > > > >
> > > > > > -                                       gPciOverrideProtocol,
> > > > > >
> > > > > > -                                       PciIoDevice->Handle,
> > > > > >
> > > > > > -                                       &PlatformOpRomBuffer,
> > > > > >
> > > > > > -                                       &PlatformOpRomSize
> > > > > >
> > > > > > -                                       );
> > > > > >
> > > > > > -      if (!EFI_ERROR (Status)) {
> > > > > >
> > > > > > -        PciIoDevice->EmbeddedRom    = FALSE;
> > > > > >
> > > > > > -        PciIoDevice->RomSize        = (UINT32) PlatformOpRomSize;
> > > > > >
> > > > > > -        PciIoDevice->PciIo.RomSize  = PlatformOpRomSize;
> > > > > >
> > > > > > -        PciIoDevice->PciIo.RomImage = PlatformOpRomBuffer;
> > > > > >
> > > > > > -        //
> > > > > >
> > > > > > -        // For OpROM read from gPciOverrideProtocol:
> > > > > >
> > > > > > -        // Add the Rom Image to internal database for later PCI light
> > > > > > enumeration
> > > > > >
> > > > > > -        //
> > > > > >
> > > > > > -        PciRomAddImageMapping (
> > > > > >
> > > > > > +    Status = GetPlatformPciOptionRom ( Controller, PciIoDevice);
> > > > > >
> > > > > > +    if (!EFI_ERROR (Status)) {
> > > > > >
> > > > > > +      //
> > > > > >
> > > > > > +      // For OpROM read from the PCI Platform Protocol:
> > > > > >
> > > > > > +      // Add the Rom Image to internal database for later PCI light
> > > > > > enumeration
> > > > > >
> > > > > > +      //
> > > > > >
> > > > > > +      PciRomAddImageMapping (
> > > > > >
> > > > > >            NULL,
> > > > > >
> > > > > >            PciIoDevice->PciRootBridgeIo->SegmentNumber,
> > > > > >
> > > > > >            PciIoDevice->BusNumber,
> > > > > >
> > > > > > @@ -294,8 +258,7 @@ RegisterPciDevice (
> > > > > >            PciIoDevice->FunctionNumber,
> > > > > >
> > > > > >            PciIoDevice->PciIo.RomImage,
> > > > > >
> > > > > >            PciIoDevice->PciIo.RomSize
> > > > > >
> > > > > > -          );
> > > > > >
> > > > > > -      }
> > > > > >
> > > > > > +        );
> > > > > >
> > > > > >      }
> > > > > >
> > > > > >    }
> > > > > >
> > > > > >
> > > > > >
> > > > > > @@ -597,7 +560,7 @@ DeRegisterPciDevice (
> > > > > >  }
> > > > > >
> > > > > >
> > > > > >
> > > > > >  /**
> > > > > >
> > > > > > -  Start to manage the PCI device on the specified root bridge or PCI-
> PCI
> > > > > > Bridge.
> > > > > >
> > > > > > +  Start the PCI root Ports or PCI-PCI Bridge only.
> > > > > >
> > > > > >
> > > > > >
> > > > > >    @param Controller          The root bridge handle.
> > > > > >
> > > > > >    @param RootBridge          A pointer to the PCI_IO_DEVICE.
> > > > > >
> > > > > > @@ -612,7 +575,82 @@ DeRegisterPciDevice (
> > > > > >
> > > > > >
> > > > > >  **/
> > > > > >
> > > > > >  EFI_STATUS
> > > > > >
> > > > > > -StartPciDevicesOnBridge (
> > > > > >
> > > > > > +StartPciRootPortsOnBridge (
> > > > > >
> > > > > > +  IN EFI_HANDLE                          Controller,
> > > > > >
> > > > > > +  IN PCI_IO_DEVICE                       *RootBridge
> > > > > >
> > > > > > +  )
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +{
> > > > > >
> > > > > > +  PCI_IO_DEVICE             *PciIoDevice;
> > > > > >
> > > > > > +  EFI_STATUS                Status;
> > > > > >
> > > > > > +  LIST_ENTRY                *CurrentLink;
> > > > > >
> > > > > > +  UINT64                    Supports;
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  PciIoDevice = NULL;
> > > > > >
> > > > > > +  CurrentLink = RootBridge->ChildList.ForwardLink;
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  while (CurrentLink != NULL && CurrentLink != &RootBridge-
> >ChildList)
> > > {
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +    PciIoDevice = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +    //
> > > > > >
> > > > > > +    // check if the device has been assigned with required resource
> > > > > >
> > > > > > +    // and registered
> > > > > >
> > > > > > +    //
> > > > > >
> > > > > > +    if (!PciIoDevice->Registered && !PciIoDevice->Allocated) {
> > > > > >
> > > > > > +      return EFI_NOT_READY;
> > > > > >
> > > > > > +    }
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +    if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {
> > > > > >
> > > > > > +      Status = StartPciRootPortsOnBridge (
> > > > > >
> > > > > > +                 Controller,
> > > > > >
> > > > > > +                 PciIoDevice
> > > > > >
> > > > > > +                 );
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +      PciIoDevice->PciIo.Attributes (
> > > > > >
> > > > > > +                           &(PciIoDevice->PciIo),
> > > > > >
> > > > > > +                           EfiPciIoAttributeOperationSupported,
> > > > > >
> > > > > > +                           0,
> > > > > >
> > > > > > +                           &Supports
> > > > > >
> > > > > > +                         );
> > > > > >
> > > > > > +      Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;
> > > > > >
> > > > > > +      PciIoDevice->PciIo.Attributes (
> > > > > >
> > > > > > +                           &(PciIoDevice->PciIo),
> > > > > >
> > > > > > +                           EfiPciIoAttributeOperationEnable,
> > > > > >
> > > > > > +                           Supports,
> > > > > >
> > > > > > +                           NULL
> > > > > >
> > > > > > +                         );
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +    }
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +    CurrentLink = CurrentLink->ForwardLink;
> > > > > >
> > > > > > +  }
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  if (PciIoDevice == NULL) {
> > > > > >
> > > > > > +    return EFI_NOT_FOUND;
> > > > > >
> > > > > > +  } else {
> > > > > >
> > > > > > +    return EFI_SUCCESS;
> > > > > >
> > > > > > +  }
> > > > > >
> > > > > > +}
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +/**
> > > > > >
> > > > > > +  Register to manage the PCI device on the specified root bridge or
> > > PCI-PCI
> > > > > > Bridge.
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @param Controller          The root bridge handle.
> > > > > >
> > > > > > +  @param RootBridge          A pointer to the PCI_IO_DEVICE.
> > > > > >
> > > > > > +  @param RemainingDevicePath A pointer to the
> > > > > > EFI_DEVICE_PATH_PROTOCOL.
> > > > > >
> > > > > > +  @param NumberOfChildren    Children number.
> > > > > >
> > > > > > +  @param ChildHandleBuffer   A pointer to the child handle buffer.
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @retval EFI_NOT_READY   Device is not allocated.
> > > > > >
> > > > > > +  @retval EFI_UNSUPPORTED Device only support PCI-PCI bridge.
> > > > > >
> > > > > > +  @retval EFI_NOT_FOUND   Can not find the specific device.
> > > > > >
> > > > > > +  @retval EFI_SUCCESS     Success to start Pci devices on bridge.
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +**/
> > > > > >
> > > > > > +EFI_STATUS
> > > > > >
> > > > > > +RegisterPciDevicesOnBridge (
> > > > > >
> > > > > >    IN EFI_HANDLE                          Controller,
> > > > > >
> > > > > >    IN PCI_IO_DEVICE                       *RootBridge,
> > > > > >
> > > > > >    IN EFI_DEVICE_PATH_PROTOCOL            *RemainingDevicePath,
> > > > > >
> > > > > > @@ -626,7 +664,6 @@ StartPciDevicesOnBridge (
> > > > > >    EFI_DEVICE_PATH_PROTOCOL  *CurrentDevicePath;
> > > > > >
> > > > > >    EFI_STATUS                Status;
> > > > > >
> > > > > >    LIST_ENTRY                *CurrentLink;
> > > > > >
> > > > > > -  UINT64                    Supports;
> > > > > >
> > > > > >
> > > > > >
> > > > > >    PciIoDevice = NULL;
> > > > > >
> > > > > >    CurrentLink = RootBridge->ChildList.ForwardLink;
> > > > > >
> > > > > > @@ -681,7 +718,7 @@ StartPciDevicesOnBridge (
> > > > > >        // If it is a PPB
> > > > > >
> > > > > >        //
> > > > > >
> > > > > >        if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {
> > > > > >
> > > > > > -        Status = StartPciDevicesOnBridge (
> > > > > >
> > > > > > +        Status = RegisterPciDevicesOnBridge (
> > > > > >
> > > > > >                     Controller,
> > > > > >
> > > > > >                     PciIoDevice,
> > > > > >
> > > > > >                     CurrentDevicePath,
> > > > > >
> > > > > > @@ -689,20 +726,6 @@ StartPciDevicesOnBridge (
> > > > > >                     ChildHandleBuffer
> > > > > >
> > > > > >                     );
> > > > > >
> > > > > >
> > > > > >
> > > > > > -        PciIoDevice->PciIo.Attributes (
> > > > > >
> > > > > > -                             &(PciIoDevice->PciIo),
> > > > > >
> > > > > > -                             EfiPciIoAttributeOperationSupported,
> > > > > >
> > > > > > -                             0,
> > > > > >
> > > > > > -                             &Supports
> > > > > >
> > > > > > -                             );
> > > > > >
> > > > > > -        Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;
> > > > > >
> > > > > > -        PciIoDevice->PciIo.Attributes (
> > > > > >
> > > > > > -                             &(PciIoDevice->PciIo),
> > > > > >
> > > > > > -                             EfiPciIoAttributeOperationEnable,
> > > > > >
> > > > > > -                             Supports,
> > > > > >
> > > > > > -                             NULL
> > > > > >
> > > > > > -                             );
> > > > > >
> > > > > > -
> > > > > >
> > > > > >          return Status;
> > > > > >
> > > > > >        } else {
> > > > > >
> > > > > >
> > > > > >
> > > > > > @@ -733,28 +756,13 @@ StartPciDevicesOnBridge (
> > > > > >        }
> > > > > >
> > > > > >
> > > > > >
> > > > > >        if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {
> > > > > >
> > > > > > -        Status = StartPciDevicesOnBridge (
> > > > > >
> > > > > > +        Status = RegisterPciDevicesOnBridge (
> > > > > >
> > > > > >                     Controller,
> > > > > >
> > > > > >                     PciIoDevice,
> > > > > >
> > > > > >                     RemainingDevicePath,
> > > > > >
> > > > > >                     NumberOfChildren,
> > > > > >
> > > > > >                     ChildHandleBuffer
> > > > > >
> > > > > >                     );
> > > > > >
> > > > > > -
> > > > > >
> > > > > > -        PciIoDevice->PciIo.Attributes (
> > > > > >
> > > > > > -                             &(PciIoDevice->PciIo),
> > > > > >
> > > > > > -                             EfiPciIoAttributeOperationSupported,
> > > > > >
> > > > > > -                             0,
> > > > > >
> > > > > > -                             &Supports
> > > > > >
> > > > > > -                             );
> > > > > >
> > > > > > -        Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;
> > > > > >
> > > > > > -        PciIoDevice->PciIo.Attributes (
> > > > > >
> > > > > > -                             &(PciIoDevice->PciIo),
> > > > > >
> > > > > > -                             EfiPciIoAttributeOperationEnable,
> > > > > >
> > > > > > -                             Supports,
> > > > > >
> > > > > > -                             NULL
> > > > > >
> > > > > > -                             );
> > > > > >
> > > > > > -
> > > > > >
> > > > > >        }
> > > > > >
> > > > > >
> > > > > >
> > > > > >        CurrentLink = CurrentLink->ForwardLink;
> > > > > >
> > > > > > @@ -768,6 +776,65 @@ StartPciDevicesOnBridge (
> > > > > >    }
> > > > > >
> > > > > >  }
> > > > > >
> > > > > >
> > > > > >
> > > > > > +/**
> > > > > >
> > > > > > +  Start to manage the PCI device on the specified root bridge or
> PCI-PCI
> > > > > > Bridge.
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @param Controller          The root bridge handle.
> > > > > >
> > > > > > +  @param RootBridge          A pointer to the PCI_IO_DEVICE.
> > > > > >
> > > > > > +  @param RemainingDevicePath A pointer to the
> > > > > > EFI_DEVICE_PATH_PROTOCOL.
> > > > > >
> > > > > > +  @param NumberOfChildren    Children number.
> > > > > >
> > > > > > +  @param ChildHandleBuffer   A pointer to the child handle buffer.
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @retval EFI_NOT_READY   Device is not allocated.
> > > > > >
> > > > > > +  @retval EFI_UNSUPPORTED Device only support PCI-PCI bridge.
> > > > > >
> > > > > > +  @retval EFI_NOT_FOUND   Can not find the specific device.
> > > > > >
> > > > > > +  @retval EFI_SUCCESS     Success to start Pci devices on bridge.
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +**/
> > > > > >
> > > > > > +EFI_STATUS
> > > > > >
> > > > > > +StartPciDevicesOnBridge (
> > > > > >
> > > > > > +  IN EFI_HANDLE                          Controller,
> > > > > >
> > > > > > +  IN PCI_IO_DEVICE                       *RootBridge,
> > > > > >
> > > > > > +  IN EFI_DEVICE_PATH_PROTOCOL            *RemainingDevicePath,
> > > > > >
> > > > > > +  IN OUT UINT8                           *NumberOfChildren,
> > > > > >
> > > > > > +  IN OUT EFI_HANDLE                      *ChildHandleBuffer
> > > > > >
> > > > > > +  )
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +{
> > > > > >
> > > > > > +  EFI_STATUS                Status;
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  // first register all the PCI devices
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  Status = RegisterPciDevicesOnBridge (
> > > > > >
> > > > > > +             Controller,
> > > > > >
> > > > > > +             RootBridge,
> > > > > >
> > > > > > +             RemainingDevicePath,
> > > > > >
> > > > > > +             NumberOfChildren,
> > > > > >
> > > > > > +             ChildHandleBuffer
> > > > > >
> > > > > > +             );
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  if (EFI_ERROR (Status) == EFI_NOT_FOUND) {
> > > > > >
> > > > > > +    return Status;
> > > > > >
> > > > > > +  } else {
> > > > > >
> > > > > > +    if ( CheckOtherPciFeaturesPcd ()) {
> > > > > >
> > > > > > +      //
> > > > > >
> > > > > > +      // the late configuration of PCI features
> > > > > >
> > > > > > +      //
> > > > > >
> > > > > > +      Status = EnumerateOtherPciFeatures (
> > > > > >
> > > > > > +                  RootBridge
> > > > > >
> > > > > > +                );
> > > > > >
> > > > > > +    }
> > > > > >
> > > > > > +    //
> > > > > >
> > > > > > +    // finally start those PCI bridge port devices only
> > > > > >
> > > > > > +    //
> > > > > >
> > > > > > +    return StartPciRootPortsOnBridge (
> > > > > >
> > > > > > +            Controller,
> > > > > >
> > > > > > +            RootBridge
> > > > > >
> > > > > > +            );
> > > > > >
> > > > > > +  }
> > > > > >
> > > > > > +}
> > > > > >
> > > > > > +
> > > > > >
> > > > > >  /**
> > > > > >
> > > > > >    Start to manage all the PCI devices it found previously under
> > > > > >
> > > > > >    the entire host bridge.
> > > > > >
> > > > > > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c
> > > > > > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c
> > > > > > index 8db1ebf8ec..0a56668380 100644
> > > > > > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c
> > > > > > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c
> > > > > > @@ -1003,7 +1003,7 @@ PciHostBridgeAdjustAllocation (
> > > > > >      Status = RejectPciDevice (PciResNode->PciDev);
> > > > > >
> > > > > >      if (Status == EFI_SUCCESS) {
> > > > > >
> > > > > >        DEBUG ((
> > > > > >
> > > > > > -        EFI_D_ERROR,
> > > > > >
> > > > > > +        DEBUG_ERROR,
> > > > > >
> > > > > >          "PciBus: [%02x|%02x|%02x] was rejected due to resource
> > > > > > confliction.\n",
> > > > > >
> > > > > >          PciResNode->PciDev->BusNumber, PciResNode->PciDev-
> > > > > > >DeviceNumber, PciResNode->PciDev->FunctionNumber
> > > > > >
> > > > > >          ));
> > > > > >
> > > > > > @@ -1746,7 +1746,7 @@ NotifyPhase (
> > > > > >
> > > > > >
> > > > > >    HostBridgeHandle  = NULL;
> > > > > >
> > > > > >    RootBridgeHandle  = NULL;
> > > > > >
> > > > > > -  if (gPciPlatformProtocol != NULL) {
> > > > > >
> > > > > > +  if ( CheckPciPlatformProtocolInstall()) {
> > > > > >
> > > > > >      //
> > > > > >
> > > > > >      // Get Host Bridge Handle.
> > > > > >
> > > > > >      //
> > > > > >
> > > > > > @@ -1770,42 +1770,11 @@ NotifyPhase (
> > > > > >      //
> > > > > >
> > > > > >      // Call PlatformPci::PlatformNotify() if the protocol is present.
> > > > > >
> > > > > >      //
> > > > > >
> > > > > > -    gPciPlatformProtocol->PlatformNotify (
> > > > > >
> > > > > > -                            gPciPlatformProtocol,
> > > > > >
> > > > > > -                            HostBridgeHandle,
> > > > > >
> > > > > > -                            Phase,
> > > > > >
> > > > > > -                            ChipsetEntry
> > > > > >
> > > > > > -                            );
> > > > > >
> > > > > > -  } else if (gPciOverrideProtocol != NULL){
> > > > > >
> > > > > > -    //
> > > > > >
> > > > > > -    // Get Host Bridge Handle.
> > > > > >
> > > > > > -    //
> > > > > >
> > > > > > -    PciResAlloc->GetNextRootBridge (PciResAlloc,
> &RootBridgeHandle);
> > > > > >
> > > > > > -
> > > > > >
> > > > > > -    //
> > > > > >
> > > > > > -    // Get the rootbridge Io protocol to find the host bridge handle
> > > > > >
> > > > > > -    //
> > > > > >
> > > > > > -    Status = gBS->HandleProtocol (
> > > > > >
> > > > > > -                    RootBridgeHandle,
> > > > > >
> > > > > > -                    &gEfiPciRootBridgeIoProtocolGuid,
> > > > > >
> > > > > > -                    (VOID **) &PciRootBridgeIo
> > > > > >
> > > > > > -                    );
> > > > > >
> > > > > > -
> > > > > >
> > > > > > -    if (EFI_ERROR (Status)) {
> > > > > >
> > > > > > -      return EFI_NOT_FOUND;
> > > > > >
> > > > > > -    }
> > > > > >
> > > > > > -
> > > > > >
> > > > > > -    HostBridgeHandle = PciRootBridgeIo->ParentHandle;
> > > > > >
> > > > > > -
> > > > > >
> > > > > > -    //
> > > > > >
> > > > > > -    // Call PlatformPci::PhaseNotify() if the protocol is present.
> > > > > >
> > > > > > -    //
> > > > > >
> > > > > > -    gPciOverrideProtocol->PlatformNotify (
> > > > > >
> > > > > > -                            gPciOverrideProtocol,
> > > > > >
> > > > > > -                            HostBridgeHandle,
> > > > > >
> > > > > > -                            Phase,
> > > > > >
> > > > > > -                            ChipsetEntry
> > > > > >
> > > > > > -                            );
> > > > > >
> > > > > > +    PciPlatformNotifyPhase (
> > > > > >
> > > > > > +        HostBridgeHandle,
> > > > > >
> > > > > > +        Phase,
> > > > > >
> > > > > > +        ChipsetEntry
> > > > > >
> > > > > > +        );
> > > > > >
> > > > > >    }
> > > > > >
> > > > > >
> > > > > >
> > > > > >    Status = PciResAlloc->NotifyPhase (
> > > > > >
> > > > > > @@ -1813,27 +1782,15 @@ NotifyPhase (
> > > > > >                            Phase
> > > > > >
> > > > > >                            );
> > > > > >
> > > > > >
> > > > > >
> > > > > > -  if (gPciPlatformProtocol != NULL) {
> > > > > >
> > > > > > +  if ( CheckPciPlatformProtocolInstall()) {
> > > > > >
> > > > > >      //
> > > > > >
> > > > > >      // Call PlatformPci::PlatformNotify() if the protocol is present.
> > > > > >
> > > > > >      //
> > > > > >
> > > > > > -    gPciPlatformProtocol->PlatformNotify (
> > > > > >
> > > > > > -                            gPciPlatformProtocol,
> > > > > >
> > > > > > -                            HostBridgeHandle,
> > > > > >
> > > > > > -                            Phase,
> > > > > >
> > > > > > -                            ChipsetExit
> > > > > >
> > > > > > -                            );
> > > > > >
> > > > > > -
> > > > > >
> > > > > > -  } else if (gPciOverrideProtocol != NULL) {
> > > > > >
> > > > > > -    //
> > > > > >
> > > > > > -    // Call PlatformPci::PhaseNotify() if the protocol is present.
> > > > > >
> > > > > > -    //
> > > > > >
> > > > > > -    gPciOverrideProtocol->PlatformNotify (
> > > > > >
> > > > > > -                            gPciOverrideProtocol,
> > > > > >
> > > > > > -                            HostBridgeHandle,
> > > > > >
> > > > > > -                            Phase,
> > > > > >
> > > > > > -                            ChipsetExit
> > > > > >
> > > > > > -                            );
> > > > > >
> > > > > > +    PciPlatformNotifyPhase (
> > > > > >
> > > > > > +        HostBridgeHandle,
> > > > > >
> > > > > > +        Phase,
> > > > > >
> > > > > > +        ChipsetExit
> > > > > >
> > > > > > +        );
> > > > > >
> > > > > >    }
> > > > > >
> > > > > >
> > > > > >
> > > > > >    return Status;
> > > > > >
> > > > > > @@ -1914,31 +1871,16 @@ PreprocessController (
> > > > > >    RootBridgePciAddress.Bus              = Bus;
> > > > > >
> > > > > >    RootBridgePciAddress.ExtendedRegister = 0;
> > > > > >
> > > > > >
> > > > > >
> > > > > > -  if (gPciPlatformProtocol != NULL) {
> > > > > >
> > > > > > -    //
> > > > > >
> > > > > > -    // Call PlatformPci::PrepController() if the protocol is present.
> > > > > >
> > > > > > -    //
> > > > > >
> > > > > > -    gPciPlatformProtocol->PlatformPrepController (
> > > > > >
> > > > > > -                            gPciPlatformProtocol,
> > > > > >
> > > > > > -                            HostBridgeHandle,
> > > > > >
> > > > > > -                            RootBridgeHandle,
> > > > > >
> > > > > > -                            RootBridgePciAddress,
> > > > > >
> > > > > > -                            Phase,
> > > > > >
> > > > > > -                            ChipsetEntry
> > > > > >
> > > > > > -                            );
> > > > > >
> > > > > > -  } else if (gPciOverrideProtocol != NULL) {
> > > > > >
> > > > > > -    //
> > > > > >
> > > > > > -    // Call PlatformPci::PrepController() if the protocol is present.
> > > > > >
> > > > > > -    //
> > > > > >
> > > > > > -    gPciOverrideProtocol->PlatformPrepController (
> > > > > >
> > > > > > -                            gPciOverrideProtocol,
> > > > > >
> > > > > > -                            HostBridgeHandle,
> > > > > >
> > > > > > -                            RootBridgeHandle,
> > > > > >
> > > > > > -                            RootBridgePciAddress,
> > > > > >
> > > > > > -                            Phase,
> > > > > >
> > > > > > -                            ChipsetEntry
> > > > > >
> > > > > > -                            );
> > > > > >
> > > > > > -  }
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  // Call PlatformPci::PrepController() if the protocol is present.
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  PciPlatformPreprocessController (
> > > > > >
> > > > > > +      HostBridgeHandle,
> > > > > >
> > > > > > +      RootBridgeHandle,
> > > > > >
> > > > > > +      RootBridgePciAddress,
> > > > > >
> > > > > > +      Phase,
> > > > > >
> > > > > > +      ChipsetEntry
> > > > > >
> > > > > > +    );
> > > > > >
> > > > > >
> > > > > >
> > > > > >    Status = PciResAlloc->PreprocessController (
> > > > > >
> > > > > >                            PciResAlloc,
> > > > > >
> > > > > > @@ -1947,31 +1889,16 @@ PreprocessController (
> > > > > >                            Phase
> > > > > >
> > > > > >                            );
> > > > > >
> > > > > >
> > > > > >
> > > > > > -  if (gPciPlatformProtocol != NULL) {
> > > > > >
> > > > > > -    //
> > > > > >
> > > > > > -    // Call PlatformPci::PrepController() if the protocol is present.
> > > > > >
> > > > > > -    //
> > > > > >
> > > > > > -    gPciPlatformProtocol->PlatformPrepController (
> > > > > >
> > > > > > -                            gPciPlatformProtocol,
> > > > > >
> > > > > > -                            HostBridgeHandle,
> > > > > >
> > > > > > -                            RootBridgeHandle,
> > > > > >
> > > > > > -                            RootBridgePciAddress,
> > > > > >
> > > > > > -                            Phase,
> > > > > >
> > > > > > -                            ChipsetExit
> > > > > >
> > > > > > -                            );
> > > > > >
> > > > > > -  } else if (gPciOverrideProtocol != NULL) {
> > > > > >
> > > > > > -    //
> > > > > >
> > > > > > -    // Call PlatformPci::PrepController() if the protocol is present.
> > > > > >
> > > > > > -    //
> > > > > >
> > > > > > -    gPciOverrideProtocol->PlatformPrepController (
> > > > > >
> > > > > > -                            gPciOverrideProtocol,
> > > > > >
> > > > > > -                            HostBridgeHandle,
> > > > > >
> > > > > > -                            RootBridgeHandle,
> > > > > >
> > > > > > -                            RootBridgePciAddress,
> > > > > >
> > > > > > -                            Phase,
> > > > > >
> > > > > > -                            ChipsetExit
> > > > > >
> > > > > > -                            );
> > > > > >
> > > > > > -  }
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  // Call PlatformPci::PrepController() if the protocol is present.
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  PciPlatformPreprocessController (
> > > > > >
> > > > > > +      HostBridgeHandle,
> > > > > >
> > > > > > +      RootBridgeHandle,
> > > > > >
> > > > > > +      RootBridgePciAddress,
> > > > > >
> > > > > > +      Phase,
> > > > > >
> > > > > > +      ChipsetExit
> > > > > >
> > > > > > +    );
> > > > > >
> > > > > >
> > > > > >
> > > > > >    return EFI_SUCCESS;
> > > > > >
> > > > > >  }
> > > > > >
> > > > > > diff --git
> > > a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
> > > > > > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
> > > > > > index c7eafff593..2343702154 100644
> > > > > > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
> > > > > > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
> > > > > > @@ -230,7 +230,7 @@ PciSearchDevice (
> > > > > >    PciIoDevice = NULL;
> > > > > >
> > > > > >
> > > > > >
> > > > > >    DEBUG ((
> > > > > >
> > > > > > -    EFI_D_INFO,
> > > > > >
> > > > > > +    DEBUG_INFO,
> > > > > >
> > > > > >      "PciBus: Discovered %s @ [%02x|%02x|%02x]\n",
> > > > > >
> > > > > >      IS_PCI_BRIDGE (Pci) ?     L"PPB" :
> > > > > >
> > > > > >      IS_CARDBUS_BRIDGE (Pci) ? L"P2C" :
> > > > > >
> > > > > > @@ -397,7 +397,7 @@ DumpPpbPaddingResource (
> > > > > >
> > > > > >
> > > > > >      if ((Type != PciBarTypeUnknown) && ((ResourceType ==
> > > > > > PciBarTypeUnknown) || (ResourceType == Type))) {
> > > > > >
> > > > > >        DEBUG ((
> > > > > >
> > > > > > -        EFI_D_INFO,
> > > > > >
> > > > > > +        DEBUG_INFO,
> > > > > >
> > > > > >          "   Padding: Type = %s; Alignment = 0x%lx;\tLength = 0x%lx\n",
> > > > > >
> > > > > >          mBarTypeStr[Type], Descriptor->AddrRangeMax, Descriptor-
> > > >AddrLen
> > > > > >
> > > > > >          ));
> > > > > >
> > > > > > @@ -424,7 +424,7 @@ DumpPciBars (
> > > > > >      }
> > > > > >
> > > > > >
> > > > > >
> > > > > >      DEBUG ((
> > > > > >
> > > > > > -      EFI_D_INFO,
> > > > > >
> > > > > > +      DEBUG_INFO,
> > > > > >
> > > > > >        "   BAR[%d]: Type = %s; Alignment = 0x%lx;\tLength =
> 0x%lx;\tOffset
> > > =
> > > > > > 0x%02x\n",
> > > > > >
> > > > > >        Index, mBarTypeStr[MIN (PciIoDevice->PciBar[Index].BarType,
> > > > > > PciBarTypeMaxType)],
> > > > > >
> > > > > >        PciIoDevice->PciBar[Index].Alignment, PciIoDevice-
> > > > > > >PciBar[Index].Length, PciIoDevice->PciBar[Index].Offset
> > > > > >
> > > > > > @@ -437,13 +437,13 @@ DumpPciBars (
> > > > > >      }
> > > > > >
> > > > > >
> > > > > >
> > > > > >      DEBUG ((
> > > > > >
> > > > > > -      EFI_D_INFO,
> > > > > >
> > > > > > +      DEBUG_INFO,
> > > > > >
> > > > > >        " VFBAR[%d]: Type = %s; Alignment = 0x%lx;\tLength =
> > > 0x%lx;\tOffset =
> > > > > > 0x%02x\n",
> > > > > >
> > > > > >        Index, mBarTypeStr[MIN (PciIoDevice->VfPciBar[Index].BarType,
> > > > > > PciBarTypeMaxType)],
> > > > > >
> > > > > >        PciIoDevice->VfPciBar[Index].Alignment, PciIoDevice-
> > > > > > >VfPciBar[Index].Length, PciIoDevice->VfPciBar[Index].Offset
> > > > > >
> > > > > >        ));
> > > > > >
> > > > > >    }
> > > > > >
> > > > > > -  DEBUG ((EFI_D_INFO, "\n"));
> > > > > >
> > > > > > +  DEBUG ((DEBUG_INFO, "\n"));
> > > > > >
> > > > > >  }
> > > > > >
> > > > > >
> > > > > >
> > > > > >  /**
> > > > > >
> > > > > > @@ -1903,7 +1903,7 @@ PciParseBar (
> > > > > >        // Fix the length to support some special 64 bit BAR
> > > > > >
> > > > > >        //
> > > > > >
> > > > > >        if (Value == 0) {
> > > > > >
> > > > > > -        DEBUG ((EFI_D_INFO, "[PciBus]BAR probing for upper 32bit of
> > > MEM64
> > > > > > BAR returns 0, change to 0xFFFFFFFF.\n"));
> > > > > >
> > > > > > +        DEBUG ((DEBUG_INFO, "[PciBus]BAR probing for upper 32bit
> of
> > > > > MEM64
> > > > > > BAR returns 0, change to 0xFFFFFFFF.\n"));
> > > > > >
> > > > > >          Value = (UINT32) -1;
> > > > > >
> > > > > >        } else {
> > > > > >
> > > > > >          Value |= ((UINT32)(-1) << HighBitSet32 (Value));
> > > > > >
> > > > > > @@ -2153,7 +2153,17 @@ CreatePciIoDevice (
> > > > > >               NULL
> > > > > >
> > > > > >               );
> > > > > >
> > > > > >    if (!EFI_ERROR (Status)) {
> > > > > >
> > > > > > -    PciIoDevice->IsPciExp = TRUE;
> > > > > >
> > > > > > +  PciIoDevice->IsPciExp = TRUE;
> > > > > >
> > > > > > +    //
> > > > > >
> > > > > > +    // read the PCI device's entire PCI Express Capability structure
> > > > > >
> > > > > > +    //
> > > > > >
> > > > > > +    PciIo->Pci.Read (
> > > > > >
> > > > > > +                  PciIo,
> > > > > >
> > > > > > +                  EfiPciIoWidthUint8,
> > > > > >
> > > > > > +                  PciIoDevice->PciExpressCapabilityOffset,
> > > > > >
> > > > > > +                  sizeof (PCI_CAPABILITY_PCIEXP) / sizeof (UINT8),
> > > > > >
> > > > > > +                  &PciIoDevice->PciExpStruct
> > > > > >
> > > > > > +                );
> > > > > >
> > > > > >    }
> > > > > >
> > > > > >
> > > > > >
> > > > > >    if (PcdGetBool (PcdAriSupport)) {
> > > > > >
> > > > > > @@ -2206,7 +2216,7 @@ CreatePciIoDevice (
> > > > > >                                &Data32
> > > > > >
> > > > > >                                );
> > > > > >
> > > > > >            DEBUG ((
> > > > > >
> > > > > > -            EFI_D_INFO,
> > > > > >
> > > > > > +            DEBUG_INFO,
> > > > > >
> > > > > >              " ARI: forwarding enabled for PPB[%02x:%02x:%02x]\n",
> > > > > >
> > > > > >              Bridge->BusNumber,
> > > > > >
> > > > > >              Bridge->DeviceNumber,
> > > > > >
> > > > > > @@ -2215,7 +2225,7 @@ CreatePciIoDevice (
> > > > > >          }
> > > > > >
> > > > > >        }
> > > > > >
> > > > > >
> > > > > >
> > > > > > -      DEBUG ((EFI_D_INFO, " ARI: CapOffset = 0x%x\n", PciIoDevice-
> > > > > > >AriCapabilityOffset));
> > > > > >
> > > > > > +      DEBUG ((DEBUG_INFO, " ARI: CapOffset = 0x%x\n",
> PciIoDevice-
> > > > > > >AriCapabilityOffset));
> > > > > >
> > > > > >      }
> > > > > >
> > > > > >    }
> > > > > >
> > > > > >
> > > > > >
> > > > > > @@ -2325,12 +2335,12 @@ CreatePciIoDevice (
> > > > > >        PciIoDevice->ReservedBusNum =
> (UINT16)(EFI_PCI_BUS_OF_RID
> > > > > (LastVF)
> > > > > > - Bus + 1);
> > > > > >
> > > > > >
> > > > > >
> > > > > >        DEBUG ((
> > > > > >
> > > > > > -        EFI_D_INFO,
> > > > > >
> > > > > > +        DEBUG_INFO,
> > > > > >
> > > > > >          " SR-IOV: SupportedPageSize = 0x%x; SystemPageSize = 0x%x;
> > > > > > FirstVFOffset = 0x%x;\n",
> > > > > >
> > > > > >          SupportedPageSize, PciIoDevice->SystemPageSize >> 12,
> > > FirstVFOffset
> > > > > >
> > > > > >          ));
> > > > > >
> > > > > >        DEBUG ((
> > > > > >
> > > > > > -        EFI_D_INFO,
> > > > > >
> > > > > > +        DEBUG_INFO,
> > > > > >
> > > > > >          "         InitialVFs = 0x%x; ReservedBusNum = 0x%x; CapOffset =
> > > 0x%x\n",
> > > > > >
> > > > > >          PciIoDevice->InitialVFs, PciIoDevice->ReservedBusNum,
> > > PciIoDevice-
> > > > > > >SrIovCapabilityOffset
> > > > > >
> > > > > >          ));
> > > > > >
> > > > > > @@ -2345,7 +2355,7 @@ CreatePciIoDevice (
> > > > > >                 NULL
> > > > > >
> > > > > >                 );
> > > > > >
> > > > > >      if (!EFI_ERROR (Status)) {
> > > > > >
> > > > > > -      DEBUG ((EFI_D_INFO, " MR-IOV: CapOffset = 0x%x\n",
> PciIoDevice-
> > > > > > >MrIovCapabilityOffset));
> > > > > >
> > > > > > +      DEBUG ((DEBUG_INFO, " MR-IOV: CapOffset = 0x%x\n",
> > > PciIoDevice-
> > > > > > >MrIovCapabilityOffset));
> > > > > >
> > > > > >      }
> > > > > >
> > > > > >    }
> > > > > >
> > > > > >
> > > > > >
> > > > > > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> > > > > > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> > > > > > new file mode 100644
> > > > > > index 0000000000..0819da6536
> > > > > > --- /dev/null
> > > > > > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> > > > > > @@ -0,0 +1,1601 @@
> > > > > > +/** @file
> > > > > >
> > > > > > +  PCI standard feature support functions implementation for PCI
> Bus
> > > > > > module..
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> > > > > >
> > > > > > +SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +**/
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +#include "PciFeatureSupport.h"
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +/**
> > > > > >
> > > > > > +  A gobal pointer to PRIMARY_ROOT_PORT_NODE buffer to track
> all
> > > the
> > > > > > primary physical
> > > > > >
> > > > > > +  PCI Root Ports (PCI Controllers) for a given PCI Root Bridge
> instance
> > > while
> > > > > >
> > > > > > +  enumerating to configure the PCI features
> > > > > >
> > > > > > +**/
> > > > > >
> > > > > > +PRIMARY_ROOT_PORT_NODE                      *mPrimaryRootPortList;
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +/**
> > > > > >
> > > > > > +  A gobal pointer to
> OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > > > > buffer
> > > > > > all the PCI
> > > > > >
> > > > > > +  Feature configuration Table nodes to pair against each of the
> > > > > > PRIMARY_ROOT_PORT_NODE
> > > > > >
> > > > > > +  buffer nodes. Each node of these is used to align all the PCI
> devices
> > > > > > originating
> > > > > >
> > > > > > +  from the PCI Root Port devices of a PCI Root Bridge instance
> > > > > >
> > > > > > +**/
> > > > > >
> > > > > > +OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > > > > > *mPciFeaturesConfigurationTableInstances;
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +/**
> > > > > >
> > > > > > +  A global pointer to
> > > PCI_FEATURE_CONFIGURATION_COMPLETION_LIST,
> > > > > > which stores all
> > > > > >
> > > > > > +  the PCI Root Bridge instances that are enumerated for the other
> PCI
> > > > > > features,
> > > > > >
> > > > > > +  like MaxPayloadSize & MaxReadReqSize; during the the Start()
> > > interface
> > > > > of
> > > > > > the
> > > > > >
> > > > > > +  driver binding protocol. The records pointed by this pointer would
> be
> > > > > > destroyed
> > > > > >
> > > > > > +  when the DXE core invokes the Stop() interface.
> > > > > >
> > > > > > +**/
> > > > > >
> > > > > > +PCI_FEATURE_CONFIGURATION_COMPLETION_LIST
> > > > > > *mPciFeaturesConfigurationCompletionList = NULL;
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +/**
> > > > > >
> > > > > > +  Main routine to indicate platform selection of any of the other PCI
> > > > > features
> > > > > >
> > > > > > +  to be configured by this driver
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @retval TRUE    platform has selected the other PCI features to be
> > > > > > configured
> > > > > >
> > > > > > +          FALSE   platform has not selected any of the other PCI
> features
> > > > > >
> > > > > > +**/
> > > > > >
> > > > > > +BOOLEAN
> > > > > >
> > > > > > +CheckOtherPciFeaturesPcd (
> > > > > >
> > > > > > +  )
> > > > > >
> > > > > > +{
> > > > > >
> > > > > > +  return PcdGet32 ( PcdOtherPciFeatures) ? TRUE : FALSE;
> > > > > >
> > > > > > +}
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +/**
> > > > > >
> > > > > > +  Main routine to indicate whether the platform has selected the
> > > > > > Max_Payload_Size
> > > > > >
> > > > > > +  PCI feature to be configured by this driver
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @retval TRUE    platform has selected the Max_Payload_Size to
> be
> > > > > > configured
> > > > > >
> > > > > > +          FALSE   platform has not selected this feature
> > > > > >
> > > > > > +**/
> > > > > >
> > > > > > +BOOLEAN
> > > > > >
> > > > > > +SetupMaxPayloadSize (
> > > > > >
> > > > > > +  )
> > > > > >
> > > > > > +{
> > > > > >
> > > > > > +  return (PcdGet32 ( PcdOtherPciFeatures) &
> > > > > > PCI_FEATURE_SUPPORT_FLAG_MPS) ? TRUE : FALSE;
> > > > > >
> > > > > > +}
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +/**
> > > > > >
> > > > > > +  Main routine to indicate whether the platform has selected the
> > > > > > Max_Read_Req_Size
> > > > > >
> > > > > > +  PCI feature to be configured by this driver
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @retval TRUE    platform has selected the Max_Read_Req_Size to
> be
> > > > > > configured
> > > > > >
> > > > > > +          FALSE   platform has not selected this feature
> > > > > >
> > > > > > +**/
> > > > > >
> > > > > > +BOOLEAN
> > > > > >
> > > > > > +SetupMaxReadReqSize (
> > > > > >
> > > > > > +  )
> > > > > >
> > > > > > +{
> > > > > >
> > > > > > +  return (PcdGet32 ( PcdOtherPciFeatures) &
> > > > > > PCI_FEATURE_SUPPORT_FLAG_MRRS) ? TRUE : FALSE;
> > > > > >
> > > > > > +}
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +/**
> > > > > >
> > > > > > +  Helper routine which determines whether the given PCI Root
> Bridge
> > > > > > instance
> > > > > >
> > > > > > +  record already exist. This routine shall help avoid duplicate record
> > > > > creation
> > > > > >
> > > > > > +  in case of re-enumeration of PCI configuation features.
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @param  RootBridge              A pointer to the PCI_IO_DEVICE for
> the
> > > Root
> > > > > > Bridge
> > > > > >
> > > > > > +  @param  PciFeatureConfigRecord  A pointer to a pointer for type
> > > > > >
> > > > > > +
> PCI_FEATURE_CONFIGURATION_COMPLETION_LIST
> > > > > >
> > > > > > +                                  record, Use to return the specific record.
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @retval TRUE                    Record already exist
> > > > > >
> > > > > > +          FALSE                   Record does not exist for the given PCI Root
> > > Bridge
> > > > > >
> > > > > > +**/
> > > > > >
> > > > > > +BOOLEAN
> > > > > >
> > > > > > +CheckPciFeatureConfigurationRecordExist (
> > > > > >
> > > > > > +  IN  PCI_IO_DEVICE                             *RootBridge,
> > > > > >
> > > > > > +  OUT PCI_FEATURE_CONFIGURATION_COMPLETION_LIST
> > > > > > **PciFeatureConfigRecord
> > > > > >
> > > > > > +  )
> > > > > >
> > > > > > +{
> > > > > >
> > > > > > +  LIST_ENTRY                                  *Link;
> > > > > >
> > > > > > +  PCI_FEATURE_CONFIGURATION_COMPLETION_LIST   *Temp;
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  if ( mPciFeaturesConfigurationCompletionList) {
> > > > > >
> > > > > > +    Link = &mPciFeaturesConfigurationCompletionList-
> >RootBridgeLink;
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +    do {
> > > > > >
> > > > > > +      Temp =
> > > > > > PCI_FEATURE_CONFIGURATION_COMPLETION_LIST_FROM_LINK
> > > (Link);
> > > > > >
> > > > > > +      if ( Temp->RootBridgeHandle == RootBridge->Handle) {
> > > > > >
> > > > > > +        *PciFeatureConfigRecord = Temp;
> > > > > >
> > > > > > +        return TRUE;
> > > > > >
> > > > > > +      }
> > > > > >
> > > > > > +      Link = Link->ForwardLink;
> > > > > >
> > > > > > +    } while (Link != &mPciFeaturesConfigurationCompletionList-
> > > > > > >RootBridgeLink);
> > > > > >
> > > > > > +  }
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  // not found on the PCI feature configuration completion list
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  *PciFeatureConfigRecord = NULL;
> > > > > >
> > > > > > +  return FALSE;
> > > > > >
> > > > > > +}
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +/**
> > > > > >
> > > > > > +  This routine is primarily to avoid multiple configuration of PCI
> features
> > > > > >
> > > > > > +  to the same PCI Root Bridge due to EDK2 core's ConnectController
> > > calls
> > > > > on
> > > > > >
> > > > > > +  all the EFI handles. This routine also provide re-enumeration of
> the
> > > PCI
> > > > > >
> > > > > > +  features on the same PCI Root Bridge based on the policy of
> > > > > > ReEnumeratePciFeatureConfiguration
> > > > > >
> > > > > > +  of the PCI_FEATURE_CONFIGURATION_COMPLETION_LIST.
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @param  RootBridge              A pointer to the PCI_IO_DEVICE for
> the
> > > Root
> > > > > > Bridge
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @retval TRUE                    PCI Feature configuration required for the
> PCI
> > > > > >
> > > > > > +                                  Root Bridge
> > > > > >
> > > > > > +          FALSE                   PCI Feature configuration is not required to be
> > > > > >
> > > > > > +                                  re-enumerated for the PCI Root Bridge
> > > > > >
> > > > > > +**/
> > > > > >
> > > > > > +BOOLEAN
> > > > > >
> > > > > > +CheckPciFeaturesConfigurationRequired (
> > > > > >
> > > > > > +  IN PCI_IO_DEVICE          *RootBridge
> > > > > >
> > > > > > +  )
> > > > > >
> > > > > > +{
> > > > > >
> > > > > > +  LIST_ENTRY                                  *Link;
> > > > > >
> > > > > > +  PCI_FEATURE_CONFIGURATION_COMPLETION_LIST   *Temp;
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  if ( mPciFeaturesConfigurationCompletionList) {
> > > > > >
> > > > > > +    Link = &mPciFeaturesConfigurationCompletionList-
> >RootBridgeLink;
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +    do {
> > > > > >
> > > > > > +      Temp =
> > > > > > PCI_FEATURE_CONFIGURATION_COMPLETION_LIST_FROM_LINK
> > > (Link);
> > > > > >
> > > > > > +      if ( Temp->RootBridgeHandle == RootBridge->Handle) {
> > > > > >
> > > > > > +        return Temp->ReEnumeratePciFeatureConfiguration;
> > > > > >
> > > > > > +      }
> > > > > >
> > > > > > +      Link = Link->ForwardLink;
> > > > > >
> > > > > > +    } while (Link != &mPciFeaturesConfigurationCompletionList-
> > > > > > >RootBridgeLink);
> > > > > >
> > > > > > +  }
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  // not found on the PCI feature configuration completion list,
> return
> > > as
> > > > > > required
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  return TRUE;
> > > > > >
> > > > > > +}
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +/**
> > > > > >
> > > > > > +  This routine finds the duplicate record if exist and assigns the re-
> > > > > > enumeration
> > > > > >
> > > > > > +  requirement flag, as passed as input. It creates new record for
> the
> > > PCI
> > > > > > Root
> > > > > >
> > > > > > +  Bridge and appends the list after updating its re-enumeration flag.
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @param  RootBridge            A pointer to PCI_IO_DEVICE of the
> Root
> > > > > Bridge
> > > > > >
> > > > > > +  @param  ReEnumerationRequired A BOOLEAN for recording the
> re-
> > > > > > enumeration requirement
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @retval EFI_SUCCESS           new record inserted into the list or
> > > updated
> > > > > the
> > > > > >
> > > > > > +                                existing record
> > > > > >
> > > > > > +          EFI_INVALID_PARAMETER Unexpected error as
> > > > > > CheckPciFeatureConfigurationRecordExist
> > > > > >
> > > > > > +                                reports as record exist but does not return its
> pointer
> > > > > >
> > > > > > +          EFI_OUT_OF_RESOURCES  Not able to create PCI features
> > > > > configuratin
> > > > > > complete
> > > > > >
> > > > > > +                                record for the RootBridge
> > > > > >
> > > > > > +**/
> > > > > >
> > > > > > +EFI_STATUS
> > > > > >
> > > > > > +AddRootBridgeInPciFeaturesConfigCompletionList (
> > > > > >
> > > > > > +  IN PCI_IO_DEVICE          *RootBridge,
> > > > > >
> > > > > > +  IN BOOLEAN                ReEnumerationRequired
> > > > > >
> > > > > > +  )
> > > > > >
> > > > > > +{
> > > > > >
> > > > > > +  PCI_FEATURE_CONFIGURATION_COMPLETION_LIST   *Temp;
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  if ( CheckPciFeatureConfigurationRecordExist ( RootBridge,
> &Temp))
> > > {
> > > > > >
> > > > > > +    //
> > > > > >
> > > > > > +    // this PCI Root Bridge record already exist; it may have been re-
> > > > > > enumerated
> > > > > >
> > > > > > +    // hence just update its enumeration required flag again to exit
> > > > > >
> > > > > > +    //
> > > > > >
> > > > > > +    if ( Temp) {
> > > > > >
> > > > > > +      Temp->ReEnumeratePciFeatureConfiguration  =
> > > > > > ReEnumerationRequired;
> > > > > >
> > > > > > +      return EFI_SUCCESS;
> > > > > >
> > > > > > +    } else {
> > > > > >
> > > > > > +      //
> > > > > >
> > > > > > +      // PCI feature configuration complete record reported as exist
> and
> > > no
> > > > > >
> > > > > > +      // record pointer returned
> > > > > >
> > > > > > +      //
> > > > > >
> > > > > > +      return EFI_INVALID_PARAMETER;
> > > > > >
> > > > > > +    }
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  } else {
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +    Temp = AllocateZeroPool ( sizeof
> > > > > > ( PCI_FEATURE_CONFIGURATION_COMPLETION_LIST));
> > > > > >
> > > > > > +    if ( !Temp) {
> > > > > >
> > > > > > +      return EFI_OUT_OF_RESOURCES;
> > > > > >
> > > > > > +    }
> > > > > >
> > > > > > +    Temp->Signature                           =
> > > > > > PCI_FEATURE_CONFIGURATION_SIGNATURE;
> > > > > >
> > > > > > +    Temp->RootBridgeHandle                    = RootBridge->Handle;
> > > > > >
> > > > > > +    Temp->ReEnumeratePciFeatureConfiguration  =
> > > > > ReEnumerationRequired;
> > > > > >
> > > > > > +    if ( mPciFeaturesConfigurationCompletionList) {
> > > > > >
> > > > > > +      InsertTailList ( &mPciFeaturesConfigurationCompletionList-
> > > > > > >RootBridgeLink,
> > > > > >
> > > > > > +                       &Temp->RootBridgeLink);
> > > > > >
> > > > > > +    } else {
> > > > > >
> > > > > > +      //
> > > > > >
> > > > > > +      // init the very first node of the Root Bridge
> > > > > >
> > > > > > +      //
> > > > > >
> > > > > > +      mPciFeaturesConfigurationCompletionList = Temp;
> > > > > >
> > > > > > +      InitializeListHead ( &mPciFeaturesConfigurationCompletionList-
> > > > > > >RootBridgeLink);
> > > > > >
> > > > > > +    }
> > > > > >
> > > > > > +  }
> > > > > >
> > > > > > +  return EFI_SUCCESS;
> > > > > >
> > > > > > +}
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +/**
> > > > > >
> > > > > > +  Free up memory alloted for the primary physical PCI Root ports of
> the
> > > > > PCI
> > > > > > Root
> > > > > >
> > > > > > +  Bridge instance. Free up all the nodes of type
> > > > > > PRIMARY_ROOT_PORT_NODE.
> > > > > >
> > > > > > +**/
> > > > > >
> > > > > > +VOID
> > > > > >
> > > > > > +DestroyPrimaryRootPortNodes ()
> > > > > >
> > > > > > +{
> > > > > >
> > > > > > +  LIST_ENTRY                *Link;
> > > > > >
> > > > > > +  PRIMARY_ROOT_PORT_NODE    *Temp;
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  if ( mPrimaryRootPortList) {
> > > > > >
> > > > > > +    Link = &mPrimaryRootPortList->NeighborRootPort;
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +    if ( IsListEmpty ( Link)) {
> > > > > >
> > > > > > +      FreePool ( mPrimaryRootPortList);
> > > > > >
> > > > > > +    } else {
> > > > > >
> > > > > > +      do {
> > > > > >
> > > > > > +        if ( Link->ForwardLink != &mPrimaryRootPortList-
> > > >NeighborRootPort)
> > > > > {
> > > > > >
> > > > > > +          Link = Link->ForwardLink;
> > > > > >
> > > > > > +        }
> > > > > >
> > > > > > +        Temp = PRIMARY_ROOT_PORT_NODE_FROM_LINK ( Link);
> > > > > >
> > > > > > +        Link = RemoveEntryList ( Link);
> > > > > >
> > > > > > +        FreePool ( Temp);
> > > > > >
> > > > > > +      } while ( !IsListEmpty ( Link));
> > > > > >
> > > > > > +      FreePool ( mPrimaryRootPortList);
> > > > > >
> > > > > > +    }
> > > > > >
> > > > > > +    mPrimaryRootPortList = NULL;
> > > > > >
> > > > > > +  }
> > > > > >
> > > > > > +}
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +/**
> > > > > >
> > > > > > +  Free up the memory allocated for temporarily maintaining the PCI
> > > > > feature
> > > > > >
> > > > > > +  configuration table for all the nodes of the primary PCI Root port.
> > > > > >
> > > > > > +  Free up memory alloted for
> > > > > > OTHER_PCI_FEATURES_CONFIGURATION_TABLE.
> > > > > >
> > > > > > +**/
> > > > > >
> > > > > > +VOID
> > > > > >
> > > > > > +ErasePciFeaturesConfigurationTable (
> > > > > >
> > > > > > +  )
> > > > > >
> > > > > > +{
> > > > > >
> > > > > > +  if ( mPciFeaturesConfigurationTableInstances) {
> > > > > >
> > > > > > +    FreePool ( mPciFeaturesConfigurationTableInstances);
> > > > > >
> > > > > > +  }
> > > > > >
> > > > > > +  mPciFeaturesConfigurationTableInstances = NULL;
> > > > > >
> > > > > > +}
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +/**
> > > > > >
> > > > > > +  Routine meant for initializing any global variables used. It primarily
> > > cleans
> > > > > >
> > > > > > +  up the internal data structure memory allocated for the previous
> PCI
> > > > > Root
> > > > > > Bridge
> > > > > >
> > > > > > +  instance. This should be the first routine to call for any virtual PCI
> > > Root
> > > > > >
> > > > > > +  Bridge instance.
> > > > > >
> > > > > > +**/
> > > > > >
> > > > > > +VOID
> > > > > >
> > > > > > +SetupPciFeaturesConfigurationDefaults ()
> > > > > >
> > > > > > +{
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  // delete the primary root port list
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  if (mPrimaryRootPortList) {
> > > > > >
> > > > > > +    DestroyPrimaryRootPortNodes ();
> > > > > >
> > > > > > +  }
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  if ( mPciFeaturesConfigurationTableInstances) {
> > > > > >
> > > > > > +    ErasePciFeaturesConfigurationTable ();
> > > > > >
> > > > > > +  }
> > > > > >
> > > > > > +}
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +/**
> > > > > >
> > > > > > +  Helper routine to determine whether the PCI device is a physical
> root
> > > > > port
> > > > > >
> > > > > > +  recorded in the list.
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @param  PciDevice                       A pointer to the PCI_IO_DEVICE.
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @retval TRUE                            The PCI device instance is a primary
> > > > > >
> > > > > > +                                          primary physical PCI Root Port
> > > > > >
> > > > > > +          FALSE                           Not a primary physical PCI Root port
> > > > > >
> > > > > > +**/
> > > > > >
> > > > > > +BOOLEAN
> > > > > >
> > > > > > +CheckRootBridgePrimaryPort (
> > > > > >
> > > > > > +  IN PCI_IO_DEVICE          *PciDevice
> > > > > >
> > > > > > +  )
> > > > > >
> > > > > > +{
> > > > > >
> > > > > > +  LIST_ENTRY                *Link;
> > > > > >
> > > > > > +  PRIMARY_ROOT_PORT_NODE    *Temp;
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  if ( !mPrimaryRootPortList) {
> > > > > >
> > > > > > +    return FALSE;
> > > > > >
> > > > > > +  }
> > > > > >
> > > > > > +  Link = &mPrimaryRootPortList->NeighborRootPort;
> > > > > >
> > > > > > +  do {
> > > > > >
> > > > > > +    Temp = PRIMARY_ROOT_PORT_NODE_FROM_LINK ( Link);
> > > > > >
> > > > > > +    if ( Temp->RootBridgeHandle == PciDevice->Parent->Handle
> > > > > >
> > > > > > +        && Temp->RootPortHandle == PciDevice->Handle) {
> > > > > >
> > > > > > +      //
> > > > > >
> > > > > > +      // the given PCI device is the primary root port of the Root
> Bridge
> > > > > > controller
> > > > > >
> > > > > > +      //
> > > > > >
> > > > > > +      return TRUE;
> > > > > >
> > > > > > +    }
> > > > > >
> > > > > > +    Link = Link->ForwardLink;
> > > > > >
> > > > > > +  } while ( Link != &mPrimaryRootPortList->NeighborRootPort);
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  // the given PCI device is not the primary root port of the Bridge
> > > > > controller
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  return FALSE;
> > > > > >
> > > > > > +}
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +/**
> > > > > >
> > > > > > +  Main routine to determine the child PCI devices of a physical PCI
> > > bridge
> > > > > > device
> > > > > >
> > > > > > +  and group them under a common internal PCI features
> Configuration
> > > > > table.
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @param  PciDevice                       A pointer to the PCI_IO_DEVICE.
> > > > > >
> > > > > > +  @param  PciFeaturesConfigTable          A pointer to a pointer to
> the
> > > > > >
> > > > > > +
> > OTHER_PCI_FEATURES_CONFIGURATION_TABLE.
> > > > > >
> > > > > > +                                          Returns NULL in case of RCiEP or the PCI
> > > > > >
> > > > > > +                                          device does match with any of the physical
> > > > > >
> > > > > > +                                          Root ports, or it does not belong to any
> > > > > >
> > > > > > +                                          Root port's PCU bus range (not a child)
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @retval EFI_SUCCESS                     able to determine the PCI feature
> > > > > >
> > > > > > +                                          configuration table. For RCiEP since
> > > > > >
> > > > > > +                                          since it is not prepared.
> > > > > >
> > > > > > +          EFI_NOT_FOUND                   the PCI feature configuration table
> > > does
> > > > > >
> > > > > > +                                          not exist as the PCI physical Bridge device
> > > > > >
> > > > > > +                                          is not found for this device's parent
> > > > > >
> > > > > > +                                          Root Bridge instance
> > > > > >
> > > > > > +**/
> > > > > >
> > > > > > +EFI_STATUS
> > > > > >
> > > > > > +GetPciFeaturesConfigurationTable (
> > > > > >
> > > > > > +  IN  PCI_IO_DEVICE                           *PciDevice,
> > > > > >
> > > > > > +  OUT OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > > > > > **PciFeaturesConfigTable
> > > > > >
> > > > > > +  )
> > > > > >
> > > > > > +{
> > > > > >
> > > > > > +  LIST_ENTRY                *Link;
> > > > > >
> > > > > > +  PRIMARY_ROOT_PORT_NODE    *Temp;
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  if ( !mPrimaryRootPortList) {
> > > > > >
> > > > > > +    *PciFeaturesConfigTable = NULL;
> > > > > >
> > > > > > +    return EFI_NOT_FOUND;
> > > > > >
> > > > > > +  }
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  // The PCI features configuration table is not built for RCiEP,
> return
> > > NULL
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  if ( PciDevice->PciExpStruct.Capability.Bits.DevicePortType == \
> > > > > >
> > > > > > +
> > > PCIE_DEVICE_PORT_TYPE_ROOT_COMPLEX_INTEGRATED_ENDPOINT)
> > > > > > {
> > > > > >
> > > > > > +    *PciFeaturesConfigTable = NULL;
> > > > > >
> > > > > > +    return EFI_SUCCESS;
> > > > > >
> > > > > > +  }
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  Link = &mPrimaryRootPortList->NeighborRootPort;
> > > > > >
> > > > > > +  do {
> > > > > >
> > > > > > +    Temp = PRIMARY_ROOT_PORT_NODE_FROM_LINK ( Link);
> > > > > >
> > > > > > +    if ( Temp->RootBridgeHandle == PciDevice->Parent->Handle
> > > > > >
> > > > > > +        && Temp->RootPortHandle == PciDevice->Handle) {
> > > > > >
> > > > > > +      //
> > > > > >
> > > > > > +      // the given PCI device is the primary root port of the Root
> Bridge
> > > > > > controller
> > > > > >
> > > > > > +      //
> > > > > >
> > > > > > +      *PciFeaturesConfigTable = Temp-
> > > > > >OtherPciFeaturesConfigurationTable;
> > > > > >
> > > > > > +      return EFI_SUCCESS;
> > > > > >
> > > > > > +    } else {
> > > > > >
> > > > > > +      //
> > > > > >
> > > > > > +      // check this PCI device belongs to the primary root port of the
> root
> > > > > > bridge
> > > > > >
> > > > > > +      //
> > > > > >
> > > > > > +      if ( PciDevice->BusNumber >= Temp->SecondaryBusStart
> > > > > >
> > > > > > +          && PciDevice->BusNumber <= Temp->SecondaryBusEnd) {
> > > > > >
> > > > > > +        *PciFeaturesConfigTable = Temp-
> > > > > >OtherPciFeaturesConfigurationTable;
> > > > > >
> > > > > > +        return EFI_SUCCESS;
> > > > > >
> > > > > > +      }
> > > > > >
> > > > > > +    }
> > > > > >
> > > > > > +    Link = Link->ForwardLink;
> > > > > >
> > > > > > +  } while ( Link != &mPrimaryRootPortList->NeighborRootPort);
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  // the PCI device must be RCiEP, does not belong to any primary
> root
> > > > > port
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  *PciFeaturesConfigTable = NULL;
> > > > > >
> > > > > > +  return EFI_SUCCESS;
> > > > > >
> > > > > > +}
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +/**
> > > > > >
> > > > > > +  The helper routine to retrieve the PCI bus numbers from the PCI
> > > Bridge
> > > > > or
> > > > > > Root
> > > > > >
> > > > > > +  port device. Assumes the input PCI device has the PCI Type 1
> > > > > configuration
> > > > > > header.
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @param  PciDevice                       A pointer to the PCI_IO_DEVICE.
> > > > > >
> > > > > > +  @param  PrimaryBusNumber                A pointer to return the PCI
> > > Priamry
> > > > > >
> > > > > > +                                          Bus number.
> > > > > >
> > > > > > +  @param  SecondaryBusNumber              A pointer to return the PCI
> > > > > > Secondary
> > > > > >
> > > > > > +                                          Bus number.
> > > > > >
> > > > > > +  @param  SubordinateBusNumber            A pointer to return the
> PCI
> > > > > > Subordinate
> > > > > >
> > > > > > +                                          Bus number.
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @retval EFI_SUCCESS           The data was read from the PCI device.
> > > > > >
> > > > > > +  @retval EFI_UNSUPPORTED       The address range specified by
> Offset,
> > > > > > Width, and Count is not
> > > > > >
> > > > > > +                                valid for the PCI configuration header of the PCI
> > device.
> > > > > >
> > > > > > +  @retval EFI_INVALID_PARAMETER input parameters provided to
> the
> > > > > read
> > > > > > operation were invalid.
> > > > > >
> > > > > > +**/
> > > > > >
> > > > > > +EFI_STATUS
> > > > > >
> > > > > > +GetPciRootPortBusAssigned (
> > > > > >
> > > > > > +  IN  PCI_IO_DEVICE                           *PciDevice,
> > > > > >
> > > > > > +  OUT UINT8                                   *PrimaryBusNumber,
> > > > > >
> > > > > > +  OUT UINT8                                   *SecondaryBusNumber,
> > > > > >
> > > > > > +  OUT UINT8                                   *SubordinateBusNumber
> > > > > >
> > > > > > +  )
> > > > > >
> > > > > > +{
> > > > > >
> > > > > > +  EFI_STATUS                                  Status;
> > > > > >
> > > > > > +  UINT32                                      RootPortBusAssigned;
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  Status = PciDevice->PciIo.Pci.Read (
> > > > > >
> > > > > > +                                  &PciDevice->PciIo,
> > > > > >
> > > > > > +                                  EfiPciIoWidthUint32,
> > > > > >
> > > > > > +                                  PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET,
> > > > > >
> > > > > > +                                  1,
> > > > > >
> > > > > > +                                  &RootPortBusAssigned
> > > > > >
> > > > > > +                                );
> > > > > >
> > > > > > +  if ( !EFI_ERROR(Status)) {
> > > > > >
> > > > > > +    if ( PrimaryBusNumber) {
> > > > > >
> > > > > > +      *PrimaryBusNumber = (UINT8) (0xFF & RootPortBusAssigned);
> > > > > >
> > > > > > +    }
> > > > > >
> > > > > > +    if ( SecondaryBusNumber) {
> > > > > >
> > > > > > +      *SecondaryBusNumber = (UINT8)(0xFF &
> (RootPortBusAssigned >>
> > > 8));
> > > > > >
> > > > > > +    }
> > > > > >
> > > > > > +    if ( SubordinateBusNumber) {
> > > > > >
> > > > > > +      *SubordinateBusNumber = (UINT8)(0xFF &
> > > (RootPortBusAssigned >>
> > > > > > 16));
> > > > > >
> > > > > > +    }
> > > > > >
> > > > > > +  }
> > > > > >
> > > > > > +  return Status;
> > > > > >
> > > > > > +}
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +/**
> > > > > >
> > > > > > +  This routine determines the existance of the child PCI device for
> the
> > > > > given
> > > > > >
> > > > > > +  PCI Root / Bridge Port device. Always assumes the input PCI
> device is
> > > the
> > > > > > bridge
> > > > > >
> > > > > > +  or PCI-PCI Bridge device. This routine should not be used with PCI
> > > > > > endpoint device.
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @param  PciDevice                       A pointer to the PCI_IO_DEVICE.
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @retval TRUE                            child device exist
> > > > > >
> > > > > > +          FALSE                           no child device
> > > > > >
> > > > > > +**/
> > > > > >
> > > > > > +BOOLEAN
> > > > > >
> > > > > > +IsPciRootPortEmpty (
> > > > > >
> > > > > > +  IN  PCI_IO_DEVICE                           *PciDevice
> > > > > >
> > > > > > +  )
> > > > > >
> > > > > > +{
> > > > > >
> > > > > > +  UINT8                                       SecBus,
> > > > > >
> > > > > > +                                              SubBus;
> > > > > >
> > > > > > +  EFI_STATUS                                  Status;
> > > > > >
> > > > > > +  LIST_ENTRY                                  *Link;
> > > > > >
> > > > > > +  PCI_IO_DEVICE                               *NextPciDevice;
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  // check secondary & suboridinate bus numbers for its endpoint
> > > device
> > > > > >
> > > > > > +  // existance
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  Status = GetPciRootPortBusAssigned ( PciDevice, NULL, &SecBus,
> > > > > > &SubBus);
> > > > > >
> > > > > > +  if ( !EFI_ERROR( Status)) {
> > > > > >
> > > > > > +    Link = PciDevice->ChildList.ForwardLink;
> > > > > >
> > > > > > +    if ( IsListEmpty ( Link)) {
> > > > > >
> > > > > > +      //
> > > > > >
> > > > > > +      // return as PCI Root port empty
> > > > > >
> > > > > > +      //
> > > > > >
> > > > > > +      DEBUG (( DEBUG_INFO, "RP empty,"));
> > > > > >
> > > > > > +      return TRUE;
> > > > > >
> > > > > > +    }
> > > > > >
> > > > > > +    do {
> > > > > >
> > > > > > +      NextPciDevice = PCI_IO_DEVICE_FROM_LINK ( Link);
> > > > > >
> > > > > > +      DEBUG (( DEBUG_INFO, "dev@%x", NextPciDevice-
> >BusNumber));
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +      if ( NextPciDevice->BusNumber >= SecBus
> > > > > >
> > > > > > +          && NextPciDevice->BusNumber <= SubBus) {
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +        return FALSE;
> > > > > >
> > > > > > +      }
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +      Link = Link->ForwardLink;
> > > > > >
> > > > > > +    } while ( Link != &PciDevice->ChildList);
> > > > > >
> > > > > > +  } else {
> > > > > >
> > > > > > +    SecBus = SubBus = 0;
> > > > > >
> > > > > > +    DEBUG (( DEBUG_ERROR, "unable to retrieve root port's bus
> range
> > > > > > assigned!!!"));
> > > > > >
> > > > > > +  }
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  // return as PCI Root port empty
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  return TRUE;
> > > > > >
> > > > > > +}
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +/**
> > > > > >
> > > > > > +  The main routine which process the PCI feature
> Max_Payload_Size as
> > > > > per
> > > > > > the
> > > > > >
> > > > > > +  device-specific platform policy, as well as in complaince with the
> PCI
> > > Base
> > > > > >
> > > > > > +  specification Revision 4, that aligns the value for the entire PCI
> > > heirarchy
> > > > > >
> > > > > > +  starting from its physical PCI Root port / Bridge device.
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @param PciDevice                      A pointer to the PCI_IO_DEVICE.
> > > > > >
> > > > > > +  @param PciConfigPhase                 for the PCI feature configuration
> > > phases:
> > > > > >
> > > > > > +                                        PciFeatureGetDevicePolicy &
> > > PciFeatureSetupPhase
> > > > > >
> > > > > > +  @param PciFeaturesConfigurationTable  pointer to
> > > > > > OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @retval EFI_SUCCESS                   processing of PCI feature
> > > > > > Max_Payload_Size
> > > > > >
> > > > > > +                                        is successful.
> > > > > >
> > > > > > +**/
> > > > > >
> > > > > > +EFI_STATUS
> > > > > >
> > > > > > +ProcessMaxPayloadSize (
> > > > > >
> > > > > > +  IN  PCI_IO_DEVICE                           *PciDevice,
> > > > > >
> > > > > > +  IN  PCI_FEATURE_CONFIGURATION_PHASE         PciConfigPhase,
> > > > > >
> > > > > > +  IN  OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > > > > > *PciFeaturesConfigurationTable
> > > > > >
> > > > > > +  )
> > > > > >
> > > > > > +{
> > > > > >
> > > > > > +  PCI_REG_PCIE_DEVICE_CAPABILITY          PciDeviceCap;
> > > > > >
> > > > > > +  UINT8                                   MpsValue;
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  PciDeviceCap.Uint32 = PciDevice-
> > > >PciExpStruct.DeviceCapability.Uint32;
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  if ( PciConfigPhase == PciFeatureGetDevicePolicy) {
> > > > > >
> > > > > > +    if ( SetupMpsAsPerDeviceCapability ( PciDevice->SetupMPS))
> > > > > >
> > > > > > +    {
> > > > > >
> > > > > > +      MpsValue = (UINT8)PciDeviceCap.Bits.MaxPayloadSize;
> > > > > >
> > > > > > +      //
> > > > > >
> > > > > > +      // no change to PCI Root ports without any endpoint device
> > > > > >
> > > > > > +      //
> > > > > >
> > > > > > +      if ( IS_PCI_BRIDGE ( &PciDevice->Pci) &&
> > > > > > PciDeviceCap.Bits.MaxPayloadSize) {
> > > > > >
> > > > > > +        if ( IsPciRootPortEmpty ( PciDevice)) {
> > > > > >
> > > > > > +          MpsValue = PCIE_MAX_PAYLOAD_SIZE_128B;
> > > > > >
> > > > > > +          DEBUG (( DEBUG_INFO, "(reset RP MPS to min.)"));
> > > > > >
> > > > > > +        }
> > > > > >
> > > > > > +      }
> > > > > >
> > > > > > +    } else {
> > > > > >
> > > > > > +      MpsValue = TranslateMpsSetupValueToPci ( PciDevice-
> > > >SetupMPS);
> > > > > >
> > > > > > +    }
> > > > > >
> > > > > > +    //
> > > > > >
> > > > > > +    // discard device policy override request if greater than PCI
> device
> > > > > > capability
> > > > > >
> > > > > > +    //
> > > > > >
> > > > > > +    PciDevice->SetupMPS =
> > > > > MIN( (UINT8)PciDeviceCap.Bits.MaxPayloadSize,
> > > > > > MpsValue);
> > > > > >
> > > > > > +  }
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  // align the MPS of the tree to the HCF with this device
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  if ( PciFeaturesConfigurationTable) {
> > > > > >
> > > > > > +    MpsValue = PciFeaturesConfigurationTable->Max_Payload_Size;
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +    MpsValue = MIN ( PciDevice->SetupMPS, MpsValue);
> > > > > >
> > > > > > +    PciDevice->SetupMPS = MIN ( PciDevice->SetupMPS,
> MpsValue);
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +    if ( MpsValue != PciFeaturesConfigurationTable-
> >Max_Payload_Size)
> > > {
> > > > > >
> > > > > > +      DEBUG (( DEBUG_INFO, "reset MPS of the tree to %d,",
> > > MpsValue));
> > > > > >
> > > > > > +      PciFeaturesConfigurationTable->Max_Payload_Size =
> MpsValue;
> > > > > >
> > > > > > +    }
> > > > > >
> > > > > > +  }
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  DEBUG (( DEBUG_INFO,
> > > > > >
> > > > > > +      "Max_Payload_Size: %d [DevCap:%d],",
> > > > > >
> > > > > > +      PciDevice->SetupMPS, PciDeviceCap.Bits.MaxPayloadSize
> > > > > >
> > > > > > +  ));
> > > > > >
> > > > > > +  return EFI_SUCCESS;
> > > > > >
> > > > > > +}
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +/**
> > > > > >
> > > > > > +  The main routine which process the PCI feature
> Max_Read_Req_Size
> > > as
> > > > > > per the
> > > > > >
> > > > > > +  device-specific platform policy, as well as in complaince with the
> PCI
> > > Base
> > > > > >
> > > > > > +  specification Revision 4, that aligns the value for the entire PCI
> > > heirarchy
> > > > > >
> > > > > > +  starting from its physical PCI Root port / Bridge device.
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @param PciDevice                      A pointer to the PCI_IO_DEVICE.
> > > > > >
> > > > > > +  @param PciConfigPhase                 for the PCI feature configuration
> > > phases:
> > > > > >
> > > > > > +                                        PciFeatureGetDevicePolicy &
> > > PciFeatureSetupPhase
> > > > > >
> > > > > > +  @param PciFeaturesConfigurationTable  pointer to
> > > > > > OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @retval EFI_SUCCESS                   processing of PCI feature
> > > > > > Max_Read_Req_Size
> > > > > >
> > > > > > +                                        is successful.
> > > > > >
> > > > > > +**/
> > > > > >
> > > > > > +EFI_STATUS
> > > > > >
> > > > > > +ProcessMaxReadReqSize (
> > > > > >
> > > > > > +  IN  PCI_IO_DEVICE                           *PciDevice,
> > > > > >
> > > > > > +  IN  PCI_FEATURE_CONFIGURATION_PHASE         PciConfigPhase,
> > > > > >
> > > > > > +  IN  OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > > > > > *PciFeaturesConfigurationTable
> > > > > >
> > > > > > +  )
> > > > > >
> > > > > > +{
> > > > > >
> > > > > > +  PCI_REG_PCIE_DEVICE_CAPABILITY  PciDeviceCap;
> > > > > >
> > > > > > +  UINT8                           MrrsValue;
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  PciDeviceCap.Uint32 = PciDevice-
> > > >PciExpStruct.DeviceCapability.Uint32;
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  if ( PciConfigPhase == PciFeatureGetDevicePolicy) {
> > > > > >
> > > > > > +    if ( SetupMrrsAsPerDeviceCapability ( PciDevice->SetupMRRS))
> > > > > >
> > > > > > +    {
> > > > > >
> > > > > > +      //
> > > > > >
> > > > > > +      // The maximum read request size is not the data packet size of
> the
> > > > > TLP,
> > > > > >
> > > > > > +      // but the memory read request size, and set to the function as
> a
> > > > > > requestor
> > > > > >
> > > > > > +      // to not exceed this limit.
> > > > > >
> > > > > > +      // However, for the PCI device capable of isochronous traffic;
> this
> > > > > > memory read
> > > > > >
> > > > > > +      // request size should not extend beyond the
> Max_Payload_Size.
> > > Thus,
> > > > > > in case if
> > > > > >
> > > > > > +      // device policy return by platform indicates to set as per device
> > > > > > capability
> > > > > >
> > > > > > +      // than set as per Max_Payload_Size configuration value
> > > > > >
> > > > > > +      //
> > > > > >
> > > > > > +      if ( SetupMaxPayloadSize()) {
> > > > > >
> > > > > > +        MrrsValue = PciDevice->SetupMPS;
> > > > > >
> > > > > > +      } else {
> > > > > >
> > > > > > +        //
> > > > > >
> > > > > > +        // in case this driver is not required to configure the
> > > > > Max_Payload_Size
> > > > > >
> > > > > > +        // than consider programming HCF of the device capability's
> > > > > > Max_Payload_Size
> > > > > >
> > > > > > +        // in this PCI hierarchy; thus making this an implementation
> > > specific
> > > > > > feature
> > > > > >
> > > > > > +        // which the platform should avoid. For better results, the
> > > platform
> > > > > > should
> > > > > >
> > > > > > +        // make both the Max_Payload_Size &
> Max_Read_Request_Size
> > > to
> > > > > be
> > > > > > configured
> > > > > >
> > > > > > +        // by this driver
> > > > > >
> > > > > > +        //
> > > > > >
> > > > > > +        MrrsValue = (UINT8)PciDeviceCap.Bits.MaxPayloadSize;
> > > > > >
> > > > > > +      }
> > > > > >
> > > > > > +    } else {
> > > > > >
> > > > > > +      //
> > > > > >
> > > > > > +      // override as per platform based device policy
> > > > > >
> > > > > > +      //
> > > > > >
> > > > > > +      MrrsValue = TranslateMrrsSetupValueToPci ( PciDevice-
> > > >SetupMRRS);
> > > > > >
> > > > > > +      //
> > > > > >
> > > > > > +      // align this device's Max_Read_Request_Size value to the
> entire
> > > PCI
> > > > > > tree
> > > > > >
> > > > > > +      //
> > > > > >
> > > > > > +      if ( PciFeaturesConfigurationTable) {
> > > > > >
> > > > > > +        if ( !PciFeaturesConfigurationTable-
> > > >Lock_Max_Read_Request_Size)
> > > > > {
> > > > > >
> > > > > > +          PciFeaturesConfigurationTable-
> >Lock_Max_Read_Request_Size
> > > =
> > > > > > TRUE;
> > > > > >
> > > > > > +          PciFeaturesConfigurationTable->Max_Read_Request_Size =
> > > > > > MrrsValue;
> > > > > >
> > > > > > +        } else {
> > > > > >
> > > > > > +          //
> > > > > >
> > > > > > +          // in case of another user enforced value of MRRS within the
> > > same
> > > > > > tree,
> > > > > >
> > > > > > +          // pick the smallest between the locked value and this value;
> to
> > > set
> > > > > >
> > > > > > +          // across entire PCI tree nodes
> > > > > >
> > > > > > +          //
> > > > > >
> > > > > > +          MrrsValue = MIN (
> > > > > >
> > > > > > +                        MrrsValue,
> > > > > >
> > > > > > +                        PciFeaturesConfigurationTable-
> >Max_Read_Request_Size
> > > > > >
> > > > > > +                        );
> > > > > >
> > > > > > +          PciFeaturesConfigurationTable->Max_Read_Request_Size =
> > > > > > MrrsValue;
> > > > > >
> > > > > > +        }
> > > > > >
> > > > > > +      }
> > > > > >
> > > > > > +    }
> > > > > >
> > > > > > +    //
> > > > > >
> > > > > > +    // align this device's Max_Read_Request_Size to derived
> > > configuration
> > > > > > value
> > > > > >
> > > > > > +    //
> > > > > >
> > > > > > +    PciDevice->SetupMRRS = MrrsValue;
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  }
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  // align the Max_Read_Request_Size of the PCI tree based on 3
> > > > > conditions:
> > > > > >
> > > > > > +  // first, if user defines MRRS for any one PCI device in the tree
> than
> > > align
> > > > > >
> > > > > > +  // all the devices in the PCI tree.
> > > > > >
> > > > > > +  // second, if user override is not define for this PCI tree than
> setup
> > > the
> > > > > > MRRS
> > > > > >
> > > > > > +  // based on MPS value of the tree to meet the criteria for the
> > > > > isochronous
> > > > > >
> > > > > > +  // traffic.
> > > > > >
> > > > > > +  // third, if no user override, or platform firmware policy has not
> > > selected
> > > > > >
> > > > > > +  // this PCI bus driver to configure the MPS; than configure the
> MRRS
> > > to a
> > > > > >
> > > > > > +  // highest common value of PCI device capability for the MPS
> found
> > > > > among
> > > > > > all
> > > > > >
> > > > > > +  // the PCI devices in this tree
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  if ( PciFeaturesConfigurationTable) {
> > > > > >
> > > > > > +    if ( PciFeaturesConfigurationTable-
> >Lock_Max_Read_Request_Size)
> > > {
> > > > > >
> > > > > > +      PciDevice->SetupMRRS = PciFeaturesConfigurationTable-
> > > > > > >Max_Read_Request_Size;
> > > > > >
> > > > > > +    } else {
> > > > > >
> > > > > > +      if ( SetupMaxPayloadSize()) {
> > > > > >
> > > > > > +        PciDevice->SetupMRRS = PciDevice->SetupMPS;
> > > > > >
> > > > > > +      } else {
> > > > > >
> > > > > > +        PciDevice->SetupMRRS = MIN (
> > > > > >
> > > > > > +                                PciDevice->SetupMRRS,
> > > > > >
> > > > > > +                                PciFeaturesConfigurationTable-
> > > > > >Max_Read_Request_Size
> > > > > >
> > > > > > +                                );
> > > > > >
> > > > > > +      }
> > > > > >
> > > > > > +      PciFeaturesConfigurationTable->Max_Read_Request_Size =
> > > > > PciDevice-
> > > > > > >SetupMRRS;
> > > > > >
> > > > > > +    }
> > > > > >
> > > > > > +  }
> > > > > >
> > > > > > +  DEBUG (( DEBUG_INFO, "Max_Read_Request_Size: %d\n",
> > > PciDevice-
> > > > > > >SetupMRRS));
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  return EFI_SUCCESS;
> > > > > >
> > > > > > +}
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +/**
> > > > > >
> > > > > > +  Overrides the PCI Device Control register MaxPayloadSize register
> > > field;
> > > > > if
> > > > > >
> > > > > > +  the hardware value is different than the intended value.
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @param  PciDevice             A pointer to the PCI_IO_DEVICE
> instance.
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @retval EFI_SUCCESS           The data was read from or written to
> the
> > > PCI
> > > > > > device.
> > > > > >
> > > > > > +  @retval EFI_UNSUPPORTED       The address range specified by
> Offset,
> > > > > > Width, and Count is not
> > > > > >
> > > > > > +                                valid for the PCI configuration header of the PCI
> > > > controller.
> > > > > >
> > > > > > +  @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is
> invalid.
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +**/
> > > > > >
> > > > > > +EFI_STATUS
> > > > > >
> > > > > > +OverrideMaxPayloadSize (
> > > > > >
> > > > > > +  IN PCI_IO_DEVICE          *PciDevice
> > > > > >
> > > > > > +  )
> > > > > >
> > > > > > +{
> > > > > >
> > > > > > +  PCI_REG_PCIE_DEVICE_CONTROL PcieDev;
> > > > > >
> > > > > > +  UINT32                      Offset;
> > > > > >
> > > > > > +  EFI_STATUS                  Status;
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  PcieDev.Uint16 = 0;
> > > > > >
> > > > > > +  Offset = PciDevice->PciExpressCapabilityOffset +
> > > > > >
> > > > > > +               OFFSET_OF (PCI_CAPABILITY_PCIEXP, DeviceControl);
> > > > > >
> > > > > > +  Status = PciDevice->PciIo.Pci.Read (
> > > > > >
> > > > > > +                                  &PciDevice->PciIo,
> > > > > >
> > > > > > +                                  EfiPciIoWidthUint16,
> > > > > >
> > > > > > +                                  Offset,
> > > > > >
> > > > > > +                                  1,
> > > > > >
> > > > > > +                                  &PcieDev.Uint16
> > > > > >
> > > > > > +                                );
> > > > > >
> > > > > > +  if ( EFI_ERROR(Status)){
> > > > > >
> > > > > > +    DEBUG (( DEBUG_ERROR, "Unexpected DeviceControl register
> > > (0x%x)
> > > > > > read error!",
> > > > > >
> > > > > > +        Offset
> > > > > >
> > > > > > +    ));
> > > > > >
> > > > > > +    return Status;
> > > > > >
> > > > > > +  }
> > > > > >
> > > > > > +  if ( PcieDev.Bits.MaxPayloadSize != PciDevice->SetupMPS) {
> > > > > >
> > > > > > +    PcieDev.Bits.MaxPayloadSize = PciDevice->SetupMPS;
> > > > > >
> > > > > > +    DEBUG (( DEBUG_INFO, "Max_Payload_Size=%d,", PciDevice-
> > > > > > >SetupMPS));
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +    Status = PciDevice->PciIo.Pci.Write (
> > > > > >
> > > > > > +                                    &PciDevice->PciIo,
> > > > > >
> > > > > > +                                    EfiPciIoWidthUint16,
> > > > > >
> > > > > > +                                    Offset,
> > > > > >
> > > > > > +                                    1,
> > > > > >
> > > > > > +                                    &PcieDev.Uint16
> > > > > >
> > > > > > +                                  );
> > > > > >
> > > > > > +    if ( !EFI_ERROR(Status)) {
> > > > > >
> > > > > > +      PciDevice->PciExpStruct.DeviceControl.Uint16 = PcieDev.Uint16;
> > > > > >
> > > > > > +    } else {
> > > > > >
> > > > > > +      DEBUG (( DEBUG_ERROR, "Unexpected DeviceControl register
> > > (0x%x)
> > > > > > write error!",
> > > > > >
> > > > > > +          Offset
> > > > > >
> > > > > > +      ));
> > > > > >
> > > > > > +    }
> > > > > >
> > > > > > +  } else {
> > > > > >
> > > > > > +    DEBUG (( DEBUG_INFO, "No write of Max_Payload_Size=%d,",
> > > > > PciDevice-
> > > > > > >SetupMPS));
> > > > > >
> > > > > > +  }
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  return Status;
> > > > > >
> > > > > > +}
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +/**
> > > > > >
> > > > > > +  Overrides the PCI Device Control register MaxPayloadSize register
> > > field;
> > > > > if
> > > > > >
> > > > > > +  the hardware value is different than the intended value.
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @param  PciDevice             A pointer to the PCI_IO_DEVICE
> instance.
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @retval EFI_SUCCESS           The data was read from or written to
> the
> > > PCI
> > > > > > controller.
> > > > > >
> > > > > > +  @retval EFI_UNSUPPORTED       The address range specified by
> Offset,
> > > > > > Width, and Count is not
> > > > > >
> > > > > > +                                valid for the PCI configuration header of the PCI
> > > > controller.
> > > > > >
> > > > > > +  @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is
> invalid.
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +**/
> > > > > >
> > > > > > +EFI_STATUS
> > > > > >
> > > > > > +OverrideMaxReadReqSize (
> > > > > >
> > > > > > +  IN PCI_IO_DEVICE          *PciDevice
> > > > > >
> > > > > > +  )
> > > > > >
> > > > > > +{
> > > > > >
> > > > > > +  PCI_REG_PCIE_DEVICE_CONTROL PcieDev;
> > > > > >
> > > > > > +  UINT32                      Offset;
> > > > > >
> > > > > > +  EFI_STATUS                  Status;
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  PcieDev.Uint16 = 0;
> > > > > >
> > > > > > +  Offset = PciDevice->PciExpressCapabilityOffset +
> > > > > >
> > > > > > +               OFFSET_OF (PCI_CAPABILITY_PCIEXP, DeviceControl);
> > > > > >
> > > > > > +  Status = PciDevice->PciIo.Pci.Read (
> > > > > >
> > > > > > +                                  &PciDevice->PciIo,
> > > > > >
> > > > > > +                                  EfiPciIoWidthUint16,
> > > > > >
> > > > > > +                                  Offset,
> > > > > >
> > > > > > +                                  1,
> > > > > >
> > > > > > +                                  &PcieDev.Uint16
> > > > > >
> > > > > > +                                );
> > > > > >
> > > > > > +  if ( EFI_ERROR(Status)){
> > > > > >
> > > > > > +    DEBUG (( DEBUG_ERROR, "Unexpected DeviceControl register
> > > (0x%x)
> > > > > > read error!",
> > > > > >
> > > > > > +        Offset
> > > > > >
> > > > > > +    ));
> > > > > >
> > > > > > +    return Status;
> > > > > >
> > > > > > +  }
> > > > > >
> > > > > > +  if ( PcieDev.Bits.MaxReadRequestSize != PciDevice->SetupMRRS)
> {
> > > > > >
> > > > > > +    PcieDev.Bits.MaxReadRequestSize = PciDevice->SetupMRRS;
> > > > > >
> > > > > > +    DEBUG (( DEBUG_INFO, "Max_Read_Request_Size: %d\n",
> > > PciDevice-
> > > > > > >SetupMRRS));
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +    Status = PciDevice->PciIo.Pci.Write (
> > > > > >
> > > > > > +                                    &PciDevice->PciIo,
> > > > > >
> > > > > > +                                    EfiPciIoWidthUint16,
> > > > > >
> > > > > > +                                    Offset,
> > > > > >
> > > > > > +                                    1,
> > > > > >
> > > > > > +                                    &PcieDev.Uint16
> > > > > >
> > > > > > +                                  );
> > > > > >
> > > > > > +    if ( !EFI_ERROR(Status)) {
> > > > > >
> > > > > > +      PciDevice->PciExpStruct.DeviceControl.Uint16 = PcieDev.Uint16;
> > > > > >
> > > > > > +    } else {
> > > > > >
> > > > > > +      DEBUG (( DEBUG_ERROR, "Unexpected DeviceControl register
> > > (0x%x)
> > > > > > write error!",
> > > > > >
> > > > > > +          Offset
> > > > > >
> > > > > > +      ));
> > > > > >
> > > > > > +    }
> > > > > >
> > > > > > +  } else {
> > > > > >
> > > > > > +    DEBUG (( DEBUG_INFO, "No write of
> > > Max_Read_Request_Size=%d\n",
> > > > > > PciDevice->SetupMRRS));
> > > > > >
> > > > > > +  }
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  return Status;
> > > > > >
> > > > > > +}
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +/**
> > > > > >
> > > > > > +  helper routine to dump the PCIe Device Port Type
> > > > > >
> > > > > > +**/
> > > > > >
> > > > > > +VOID
> > > > > >
> > > > > > +DumpDevicePortType (
> > > > > >
> > > > > > +  IN  UINT8   DevicePortType
> > > > > >
> > > > > > +  )
> > > > > >
> > > > > > +{
> > > > > >
> > > > > > +  switch ( DevicePortType){
> > > > > >
> > > > > > +    case PCIE_DEVICE_PORT_TYPE_PCIE_ENDPOINT:
> > > > > >
> > > > > > +      DEBUG (( DEBUG_INFO, "PCIe endpoint found\n"));
> > > > > >
> > > > > > +      break;
> > > > > >
> > > > > > +    case PCIE_DEVICE_PORT_TYPE_LEGACY_PCIE_ENDPOINT:
> > > > > >
> > > > > > +      DEBUG (( DEBUG_INFO, "legacy PCI endpoint found\n"));
> > > > > >
> > > > > > +      break;
> > > > > >
> > > > > > +    case PCIE_DEVICE_PORT_TYPE_ROOT_PORT:
> > > > > >
> > > > > > +      DEBUG (( DEBUG_INFO, "PCIe Root Port found\n"));
> > > > > >
> > > > > > +      break;
> > > > > >
> > > > > > +    case PCIE_DEVICE_PORT_TYPE_UPSTREAM_PORT:
> > > > > >
> > > > > > +      DEBUG (( DEBUG_INFO, "PCI switch upstream port found\n"));
> > > > > >
> > > > > > +      break;
> > > > > >
> > > > > > +    case PCIE_DEVICE_PORT_TYPE_DOWNSTREAM_PORT:
> > > > > >
> > > > > > +      DEBUG (( DEBUG_INFO, "PCI switch downstream port
> found\n"));
> > > > > >
> > > > > > +      break;
> > > > > >
> > > > > > +    case PCIE_DEVICE_PORT_TYPE_PCIE_TO_PCI_BRIDGE:
> > > > > >
> > > > > > +      DEBUG (( DEBUG_INFO, "PCIe-PCI bridge found\n"));
> > > > > >
> > > > > > +      break;
> > > > > >
> > > > > > +    case PCIE_DEVICE_PORT_TYPE_PCI_TO_PCIE_BRIDGE:
> > > > > >
> > > > > > +      DEBUG (( DEBUG_INFO, "PCI-PCIe bridge found\n"));
> > > > > >
> > > > > > +      break;
> > > > > >
> > > > > > +    case
> > > > > >
> PCIE_DEVICE_PORT_TYPE_ROOT_COMPLEX_INTEGRATED_ENDPOINT:
> > > > > >
> > > > > > +      DEBUG (( DEBUG_INFO, "RCiEP found\n"));
> > > > > >
> > > > > > +      break;
> > > > > >
> > > > > > +    case
> > > PCIE_DEVICE_PORT_TYPE_ROOT_COMPLEX_EVENT_COLLECTOR:
> > > > > >
> > > > > > +      DEBUG (( DEBUG_INFO, "RC Event Collector found\n"));
> > > > > >
> > > > > > +      break;
> > > > > >
> > > > > > +  }
> > > > > >
> > > > > > +}
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +/**
> > > > > >
> > > > > > +   Process each PCI device as per the pltaform and device-specific
> > > policy.
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @param RootBridge             A pointer to the PCI_IO_DEVICE.
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @retval EFI_SUCCESS           processing each PCI feature as per
> policy
> > > > > > defined
> > > > > >
> > > > > > +                                was successful.
> > > > > >
> > > > > > + **/
> > > > > >
> > > > > > +EFI_STATUS
> > > > > >
> > > > > > +SetupDevicePciFeatures (
> > > > > >
> > > > > > +  IN  PCI_IO_DEVICE                   *PciDevice,
> > > > > >
> > > > > > +  IN  PCI_FEATURE_CONFIGURATION_PHASE PciConfigPhase
> > > > > >
> > > > > > +  )
> > > > > >
> > > > > > +{
> > > > > >
> > > > > > +  EFI_STATUS                              Status;
> > > > > >
> > > > > > +  PCI_REG_PCIE_CAPABILITY                 PcieCap;
> > > > > >
> > > > > > +  OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > > > > > *OtherPciFeaturesConfigTable;
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  PcieCap.Uint16 = PciDevice->PciExpStruct.Capability.Uint16;
> > > > > >
> > > > > > +  DumpDevicePortType ( (UINT8)PcieCap.Bits.DevicePortType);
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  OtherPciFeaturesConfigTable = NULL;
> > > > > >
> > > > > > +  Status = GetPciFeaturesConfigurationTable ( PciDevice,
> > > > > > &OtherPciFeaturesConfigTable);
> > > > > >
> > > > > > +  if ( EFI_ERROR( Status)) {
> > > > > >
> > > > > > +    DEBUG ((
> > > > > >
> > > > > > +        EFI_D_WARN, "No primary root port found in these root
> bridge
> > > > > > nodes!\n"
> > > > > >
> > > > > > +    ));
> > > > > >
> > > > > > +  } else if ( !OtherPciFeaturesConfigTable) {
> > > > > >
> > > > > > +    DEBUG ((
> > > > > >
> > > > > > +        DEBUG_INFO, "No PCI features config. table for this
> device!\n"
> > > > > >
> > > > > > +    ));
> > > > > >
> > > > > > +  } else {
> > > > > >
> > > > > > +    DEBUG ((
> > > > > >
> > > > > > +        DEBUG_INFO, "using PCI features config. table ID: %d\n",
> > > > > >
> > > > > > +        OtherPciFeaturesConfigTable->ID
> > > > > >
> > > > > > +    ));
> > > > > >
> > > > > > +  }
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  if ( PciConfigPhase == PciFeatureGetDevicePolicy) {
> > > > > >
> > > > > > +    Status = GetPciDevicePlatformPolicy ( PciDevice);
> > > > > >
> > > > > > +    if ( EFI_ERROR(Status)) {
> > > > > >
> > > > > > +      DEBUG ((
> > > > > >
> > > > > > +          DEBUG_ERROR, "Error in obtaining PCI device policy!!!\n"
> > > > > >
> > > > > > +      ));
> > > > > >
> > > > > > +    }
> > > > > >
> > > > > > +  }
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  if ( SetupMaxPayloadSize ()) {
> > > > > >
> > > > > > +    Status = ProcessMaxPayloadSize (
> > > > > >
> > > > > > +              PciDevice,
> > > > > >
> > > > > > +              PciConfigPhase,
> > > > > >
> > > > > > +              OtherPciFeaturesConfigTable
> > > > > >
> > > > > > +              );
> > > > > >
> > > > > > +  }
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  // implementation specific rule:- the MRRS of any PCI device
> should
> > > be
> > > > > > processed
> > > > > >
> > > > > > +  // only after the MPS is processed for that device
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  if ( SetupMaxReadReqSize ()) {
> > > > > >
> > > > > > +    Status = ProcessMaxReadReqSize (
> > > > > >
> > > > > > +              PciDevice,
> > > > > >
> > > > > > +              PciConfigPhase,
> > > > > >
> > > > > > +              OtherPciFeaturesConfigTable
> > > > > >
> > > > > > +              );
> > > > > >
> > > > > > +  }
> > > > > >
> > > > > > +  return Status;
> > > > > >
> > > > > > +}
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +/**
> > > > > >
> > > > > > +  Traverse all the nodes from the root bridge or PCI-PCI bridge
> instance,
> > > to
> > > > > >
> > > > > > +  configure the PCI features as per the device-specific platform
> policy,
> > > and
> > > > > >
> > > > > > +  as per the device capability, as applicable.
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @param RootBridge             A pointer to the PCI_IO_DEVICE.
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @retval EFI_SUCCESS           Traversing all the nodes of the root
> bridge
> > > > > >
> > > > > > +                                instances were successfull.
> > > > > >
> > > > > > +**/
> > > > > >
> > > > > > +EFI_STATUS
> > > > > >
> > > > > > +SetupPciFeatures (
> > > > > >
> > > > > > +  IN  PCI_IO_DEVICE                   *RootBridge,
> > > > > >
> > > > > > +  IN  PCI_FEATURE_CONFIGURATION_PHASE PciConfigPhase
> > > > > >
> > > > > > +  )
> > > > > >
> > > > > > +{
> > > > > >
> > > > > > +  EFI_STATUS           Status;
> > > > > >
> > > > > > +  LIST_ENTRY           *Link;
> > > > > >
> > > > > > +  PCI_IO_DEVICE        *Device;
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  for ( Link = RootBridge->ChildList.ForwardLink
> > > > > >
> > > > > > +      ; Link != &RootBridge->ChildList
> > > > > >
> > > > > > +      ; Link = Link->ForwardLink
> > > > > >
> > > > > > +  ) {
> > > > > >
> > > > > > +    Device = PCI_IO_DEVICE_FROM_LINK (Link);
> > > > > >
> > > > > > +    if (IS_PCI_BRIDGE (&Device->Pci)) {
> > > > > >
> > > > > > +      DEBUG ((
> > > > > >
> > > > > > +          DEBUG_INFO, "::Bridge [%02x|%02x|%02x] -",
> > > > > >
> > > > > > +          Device->BusNumber, Device->DeviceNumber, Device-
> > > > > > >FunctionNumber
> > > > > >
> > > > > > +      ));
> > > > > >
> > > > > > +      if (Device->IsPciExp) {
> > > > > >
> > > > > > +        Status = SetupDevicePciFeatures ( Device, PciConfigPhase);
> > > > > >
> > > > > > +      } else {
> > > > > >
> > > > > > +        DEBUG (( DEBUG_INFO, "Not a PCIe capable device!\n"));
> > > > > >
> > > > > > +        //
> > > > > >
> > > > > > +        // PCI Bridge which does not have PCI Express Capability
> structure
> > > > > >
> > > > > > +        // cannot process this kind of PCI Bridge device
> > > > > >
> > > > > > +        //
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +      }
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +      SetupPciFeatures ( Device, PciConfigPhase);
> > > > > >
> > > > > > +    } else {
> > > > > >
> > > > > > +      DEBUG ((
> > > > > >
> > > > > > +          DEBUG_INFO, "::Device [%02x|%02x|%02x] -",
> > > > > >
> > > > > > +          Device->BusNumber, Device->DeviceNumber, Device-
> > > > > > >FunctionNumber
> > > > > >
> > > > > > +      ));
> > > > > >
> > > > > > +      if (Device->IsPciExp) {
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +        Status = SetupDevicePciFeatures ( Device, PciConfigPhase);
> > > > > >
> > > > > > +      } else {
> > > > > >
> > > > > > +        DEBUG (( DEBUG_INFO, "Not a PCIe capable device!\n"));
> > > > > >
> > > > > > +        //
> > > > > >
> > > > > > +        // PCI Device which does not have PCI Express Capability
> structure
> > > > > >
> > > > > > +        // cannot process this kind of PCI device
> > > > > >
> > > > > > +        //
> > > > > >
> > > > > > +      }
> > > > > >
> > > > > > +    }
> > > > > >
> > > > > > +  }
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  return EFI_SUCCESS;
> > > > > >
> > > > > > +}
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +/**
> > > > > >
> > > > > > +  Program the PCI device, to override the PCI features as per the
> policy,
> > > > > >
> > > > > > +  resolved from previous traverse.
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @param RootBridge             A pointer to the PCI_IO_DEVICE.
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @retval EFI_SUCCESS           The other PCI features configuration
> > > during
> > > > > > enumeration
> > > > > >
> > > > > > +                                of all the nodes of the PCI root bridge instance
> were
> > > > > >
> > > > > > +                                programmed in PCI-compliance pattern along with
> the
> > > > > >
> > > > > > +                                device-specific policy, as applicable.
> > > > > >
> > > > > > +  @retval EFI_UNSUPPORTED       One of the override operation
> maong
> > > the
> > > > > > nodes of
> > > > > >
> > > > > > +                                the PCI hierarchy resulted in a incompatible
> address
> > > > > >
> > > > > > +                                range.
> > > > > >
> > > > > > +  @retval EFI_INVALID_PARAMETER The override operation is
> > > performed
> > > > > > with invalid input
> > > > > >
> > > > > > +                                parameters.
> > > > > >
> > > > > > +**/
> > > > > >
> > > > > > +EFI_STATUS
> > > > > >
> > > > > > +ProgramDevicePciFeatures (
> > > > > >
> > > > > > +  IN PCI_IO_DEVICE          *PciDevice
> > > > > >
> > > > > > +  )
> > > > > >
> > > > > > +{
> > > > > >
> > > > > > +  EFI_STATUS           Status;
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  if ( SetupMaxPayloadSize ()) {
> > > > > >
> > > > > > +    Status = OverrideMaxPayloadSize (PciDevice);
> > > > > >
> > > > > > +  }
> > > > > >
> > > > > > +  if ( SetupMaxReadReqSize ()) {
> > > > > >
> > > > > > +    Status = OverrideMaxReadReqSize (PciDevice);
> > > > > >
> > > > > > +  }
> > > > > >
> > > > > > +  return Status;
> > > > > >
> > > > > > +}
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +/**
> > > > > >
> > > > > > +  Program all the nodes of the specified root bridge or PCI-PCI
> Bridge,
> > > to
> > > > > >
> > > > > > +  override the PCI features.
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @param RootBridge             A pointer to the PCI_IO_DEVICE.
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @retval EFI_SUCCESS           The other PCI features configuration
> > > during
> > > > > > enumeration
> > > > > >
> > > > > > +                                of all the nodes of the PCI root bridge instance
> were
> > > > > >
> > > > > > +                                programmed in PCI-compliance pattern along with
> the
> > > > > >
> > > > > > +                                device-specific policy, as applicable.
> > > > > >
> > > > > > +  @retval EFI_UNSUPPORTED       One of the override operation
> maong
> > > the
> > > > > > nodes of
> > > > > >
> > > > > > +                                the PCI hierarchy resulted in a incompatible
> address
> > > > > >
> > > > > > +                                range.
> > > > > >
> > > > > > +  @retval EFI_INVALID_PARAMETER The override operation is
> > > performed
> > > > > > with invalid input
> > > > > >
> > > > > > +                                parameters.
> > > > > >
> > > > > > +**/
> > > > > >
> > > > > > +EFI_STATUS
> > > > > >
> > > > > > +ProgramPciFeatures (
> > > > > >
> > > > > > +  IN PCI_IO_DEVICE          *RootBridge
> > > > > >
> > > > > > +  )
> > > > > >
> > > > > > +{
> > > > > >
> > > > > > +  EFI_STATUS           Status;
> > > > > >
> > > > > > +  LIST_ENTRY           *Link;
> > > > > >
> > > > > > +  PCI_IO_DEVICE        *Device;
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  for ( Link = RootBridge->ChildList.ForwardLink
> > > > > >
> > > > > > +      ; Link != &RootBridge->ChildList
> > > > > >
> > > > > > +      ; Link = Link->ForwardLink
> > > > > >
> > > > > > +  ) {
> > > > > >
> > > > > > +    Device = PCI_IO_DEVICE_FROM_LINK (Link);
> > > > > >
> > > > > > +    if (IS_PCI_BRIDGE (&Device->Pci)) {
> > > > > >
> > > > > > +      DEBUG ((
> > > > > >
> > > > > > +          DEBUG_INFO, "::Bridge [%02x|%02x|%02x] -",
> > > > > >
> > > > > > +          Device->BusNumber, Device->DeviceNumber, Device-
> > > > > > >FunctionNumber
> > > > > >
> > > > > > +      ));
> > > > > >
> > > > > > +      if (Device->IsPciExp) {
> > > > > >
> > > > > > +        DEBUG (( DEBUG_INFO, "ready to override!\n"));
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +        Status = ProgramDevicePciFeatures ( Device);
> > > > > >
> > > > > > +      } else {
> > > > > >
> > > > > > +        DEBUG (( DEBUG_INFO, "skipped!\n"));
> > > > > >
> > > > > > +        //
> > > > > >
> > > > > > +        // PCI Bridge which does not have PCI Express Capability
> structure
> > > > > >
> > > > > > +        // cannot process this kind of PCI Bridge device
> > > > > >
> > > > > > +        //
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +      }
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +      Status = ProgramPciFeatures ( Device);
> > > > > >
> > > > > > +    } else {
> > > > > >
> > > > > > +      DEBUG ((
> > > > > >
> > > > > > +          DEBUG_INFO, "::Device [%02x|%02x|%02x] -",
> > > > > >
> > > > > > +          Device->BusNumber, Device->DeviceNumber, Device-
> > > > > > >FunctionNumber
> > > > > >
> > > > > > +      ));
> > > > > >
> > > > > > +      if (Device->IsPciExp) {
> > > > > >
> > > > > > +        DEBUG (( DEBUG_INFO, "ready to override!\n"));
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +        Status = ProgramDevicePciFeatures ( Device);
> > > > > >
> > > > > > +      } else {
> > > > > >
> > > > > > +        DEBUG (( DEBUG_INFO, "skipped!\n"));
> > > > > >
> > > > > > +        //
> > > > > >
> > > > > > +        // PCI Device which does not have PCI Express Capability
> structure
> > > > > >
> > > > > > +        // cannot process this kind of PCI device
> > > > > >
> > > > > > +        //
> > > > > >
> > > > > > +      }
> > > > > >
> > > > > > +    }
> > > > > >
> > > > > > +  }
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  return Status;
> > > > > >
> > > > > > +}
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +/**
> > > > > >
> > > > > > +  Create a node of type PRIMARY_ROOT_PORT_NODE for the
> given
> > > PCI
> > > > > > device, and
> > > > > >
> > > > > > +  assigns EFI handles of its Root Bridge and its own, along with its
> PCI
> > > Bus
> > > > > >
> > > > > > +  range for the secondary and subordinate bus range.
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @param  RootBridge          A pointer to the PCI_IO_DEVICE for its
> PCI
> > > Root
> > > > > > Bridge
> > > > > >
> > > > > > +  @param  Device              A pointer to the PCI_IO_DEVICE for the
> PCI
> > > > > > controller
> > > > > >
> > > > > > +  @param  RootPortSecBus      PCI controller's Secondary Bus
> number
> > > > > >
> > > > > > +  @param  RootPortSubBus      PCI controller's Subordinate Bus
> number
> > > > > >
> > > > > > +  @param  PrimaryRootPortNode A pointer to the
> > > > > > PRIMARY_ROOT_PORT_NODE to return
> > > > > >
> > > > > > +                              the newly created node for the PCI controller. In
> > > > > >
> > > > > > +                              case of error nothing is return in this.
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @retval EFI_SUCCESS           new node of
> > > PRIMARY_ROOT_PORT_NODE is
> > > > > > returned for
> > > > > >
> > > > > > +                                the PCI controller
> > > > > >
> > > > > > +          EFI_OUT_OF_RESOURCES  unable to create the node for the
> PCI
> > > > > > controller
> > > > > >
> > > > > > +          EFI_INVALID_PARAMETER unable to store the node as the
> input
> > > > > > buffer is
> > > > > >
> > > > > > +                                not empty (*PrimaryRootPortNode)
> > > > > >
> > > > > > +**/
> > > > > >
> > > > > > +EFI_STATUS
> > > > > >
> > > > > > +CreatePrimaryPciRootPortNode (
> > > > > >
> > > > > > +  IN  PCI_IO_DEVICE           *RootBridge,
> > > > > >
> > > > > > +  IN  PCI_IO_DEVICE           *Device,
> > > > > >
> > > > > > +  IN  UINT8                   RootPortSecBus,
> > > > > >
> > > > > > +  IN  UINT8                   RootPortSubBus,
> > > > > >
> > > > > > +  OUT PRIMARY_ROOT_PORT_NODE  **PrimaryRootPortNode
> > > > > >
> > > > > > +  )
> > > > > >
> > > > > > +{
> > > > > >
> > > > > > +  PRIMARY_ROOT_PORT_NODE      *RootPortNode = NULL;
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  if ( !*PrimaryRootPortNode) {
> > > > > >
> > > > > > +    RootPortNode                    = AllocateZeroPool ( sizeof
> > > > > > (PRIMARY_ROOT_PORT_NODE));
> > > > > >
> > > > > > +    if ( RootPortNode == NULL) {
> > > > > >
> > > > > > +      return EFI_OUT_OF_RESOURCES;
> > > > > >
> > > > > > +    }
> > > > > >
> > > > > > +    RootPortNode->Signature         = PCI_ROOT_PORT_SIGNATURE;
> > > > > >
> > > > > > +    RootPortNode->RootBridgeHandle  = RootBridge->Handle;
> > > > > >
> > > > > > +    RootPortNode->RootPortHandle    = Device->Handle;
> > > > > >
> > > > > > +    RootPortNode->SecondaryBusStart = RootPortSecBus;
> > > > > >
> > > > > > +    RootPortNode->SecondaryBusEnd   = RootPortSubBus;
> > > > > >
> > > > > > +    InitializeListHead ( &RootPortNode->NeighborRootPort);
> > > > > >
> > > > > > +    *PrimaryRootPortNode = RootPortNode;
> > > > > >
> > > > > > +    return EFI_SUCCESS;
> > > > > >
> > > > > > +  } else {
> > > > > >
> > > > > > +    return EFI_INVALID_PARAMETER;
> > > > > >
> > > > > > +  }
> > > > > >
> > > > > > +}
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +/**
> > > > > >
> > > > > > +  Checks to report whether the input PCI controller's secondary /
> > > > > > subordinate
> > > > > >
> > > > > > +  bus numbers are within the recorded list of other PCI controllers
> > > (root
> > > > > > ports).
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @param  RootPortNode      A pointer to the first node of
> > > > > > PRIMARY_ROOT_PORT_NODE
> > > > > >
> > > > > > +  @param  RootPortSecBus    PCI secondary bus number of the PCI
> > > > > controller
> > > > > > found
> > > > > >
> > > > > > +  @param  RootPortSubBus    PCI subordinate bus number of the
> PCI
> > > Root
> > > > > > Port found
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @retval TRUE              A child PCI Root port found
> > > > > >
> > > > > > +          FALSE             A new PCI controller found
> > > > > >
> > > > > > +**/
> > > > > >
> > > > > > +BOOLEAN
> > > > > >
> > > > > > +CheckChildRootPort (
> > > > > >
> > > > > > +  IN      PRIMARY_ROOT_PORT_NODE  *RootPortNode,
> > > > > >
> > > > > > +  IN      UINT8                   RootPortSecBus,
> > > > > >
> > > > > > +  IN      UINT8                   RootPortSubBus
> > > > > >
> > > > > > +)
> > > > > >
> > > > > > +{
> > > > > >
> > > > > > +  LIST_ENTRY              *Link;
> > > > > >
> > > > > > +  PRIMARY_ROOT_PORT_NODE  *Temp;
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  if ( !RootPortNode) {
> > > > > >
> > > > > > +    return FALSE;
> > > > > >
> > > > > > +  }
> > > > > >
> > > > > > +  Link = &RootPortNode->NeighborRootPort;
> > > > > >
> > > > > > +  do {
> > > > > >
> > > > > > +    Temp = PRIMARY_ROOT_PORT_NODE_FROM_LINK ( Link);
> > > > > >
> > > > > > +    if ( RootPortSecBus >= Temp->SecondaryBusStart
> > > > > >
> > > > > > +        && RootPortSubBus <= Temp->SecondaryBusEnd) {
> > > > > >
> > > > > > +      //
> > > > > >
> > > > > > +      // given root port's secondary & subordinate within its primary
> > > ports
> > > > > >
> > > > > > +      // hence return as child port
> > > > > >
> > > > > > +      //
> > > > > >
> > > > > > +      return TRUE;
> > > > > >
> > > > > > +    }
> > > > > >
> > > > > > +    Link = Link->ForwardLink;
> > > > > >
> > > > > > +  } while (Link != &RootPortNode->NeighborRootPort);
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  // the given root port's secondary / subordinate bus numbers do
> not
> > > > > > belong to
> > > > > >
> > > > > > +  // any existing primary root port's bus range hence consider
> another
> > > > > > primary
> > > > > >
> > > > > > +  // root port of the root bridge controller
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  return FALSE;
> > > > > >
> > > > > > +}
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +/**
> > > > > >
> > > > > > +  Create the vector of PCI Feature configuration table as per the
> > > number
> > > > > of
> > > > > >
> > > > > > +  the PCI Root Ports given, assigns default value to the PCI features
> > > > > > supported
> > > > > >
> > > > > > +  and assign its address to the global variable
> > > > > > "mPciFeaturesConfigurationTableInstances".
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @param  NumberOfRootPorts   An input arguement of UINTN to
> > > indicate
> > > > > > number of
> > > > > >
> > > > > > +                              primary PCI physical Root Bridge devices found
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @retval EFI_OUT_OF_RESOURCES  unable to allocate buffer to
> store
> > > PCI
> > > > > > feature
> > > > > >
> > > > > > +                                configuration table for all the physical PCI root
> > > > > >
> > > > > > +                                ports given
> > > > > >
> > > > > > +          EFI_SUCCESS           PCI Feature COnfiguration table created for
> all
> > > > > >
> > > > > > +                                the PCI Rooot ports reported
> > > > > >
> > > > > > + */
> > > > > >
> > > > > > +EFI_STATUS
> > > > > >
> > > > > > +CreatePciFeaturesConfigurationTableInstances (
> > > > > >
> > > > > > +  IN  UINTN NumberOfRootPorts
> > > > > >
> > > > > > +  )
> > > > > >
> > > > > > +{
> > > > > >
> > > > > > +  OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > > > > > *PciRootBridgePortFeatures = NULL;
> > > > > >
> > > > > > +  UINTN                                     Instances;
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  PciRootBridgePortFeatures = AllocateZeroPool (
> > > > > >
> > > > > > +                                sizeof
> > > ( OTHER_PCI_FEATURES_CONFIGURATION_TABLE)
> > > > > *
> > > > > > NumberOfRootPorts
> > > > > >
> > > > > > +                                );
> > > > > >
> > > > > > +  if ( !PciRootBridgePortFeatures) {
> > > > > >
> > > > > > +    return EFI_OUT_OF_RESOURCES;
> > > > > >
> > > > > > +  }
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  for ( Instances = 0; Instances < NumberOfRootPorts; Instances++)
> {
> > > > > >
> > > > > > +    PciRootBridgePortFeatures [Instances].ID                    = Instances +
> 1;
> > > > > >
> > > > > > +    PciRootBridgePortFeatures [Instances].Max_Payload_Size      =
> > > > > > PCIE_MAX_PAYLOAD_SIZE_4096B;
> > > > > >
> > > > > > +    PciRootBridgePortFeatures
> [Instances].Max_Read_Request_Size =
> > > > > > PCIE_MAX_READ_REQ_SIZE_4096B;
> > > > > >
> > > > > > +    PciRootBridgePortFeatures
> > > [Instances].Lock_Max_Read_Request_Size
> > > > > =
> > > > > > FALSE;
> > > > > >
> > > > > > +  }
> > > > > >
> > > > > > +  mPciFeaturesConfigurationTableInstances =
> > > PciRootBridgePortFeatures;
> > > > > >
> > > > > > +  return EFI_SUCCESS;
> > > > > >
> > > > > > +}
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +/**
> > > > > >
> > > > > > +  This routine pairs the each PCI Root Port node with one of the PCI
> > > > > Feature
> > > > > >
> > > > > > +  Configuration Table node. Each physical PCI Root Port has its own
> PCI
> > > > > > feature
> > > > > >
> > > > > > +  configuration table which will used for aligning all its downstream
> > > > > > components.
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @param  NumberOfRootPorts     inputs the number of physical
> PCI
> > > root
> > > > > > ports
> > > > > >
> > > > > > +                                found on the Root bridge instance
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @retval EFI_INVALID_PARAMETER if the primary PCI root ports
> list is
> > > > > > vacant when
> > > > > >
> > > > > > +                                there is one or more PCI Root port indicated as per
> > > > > >
> > > > > > +                                input parameter
> > > > > >
> > > > > > +          EFI_UNSUPPORTED       The PCI Root Port nodes not paired
> > > equally
> > > > > with
> > > > > >
> > > > > > +                                the PCI Configuration Table nodes
> > > > > >
> > > > > > +          EFI_SUCCESS           each PCI feature configuration node is
> paired
> > > > > > equally
> > > > > >
> > > > > > +                                with each PCI Root port in the list
> > > > > >
> > > > > > +**/
> > > > > >
> > > > > > +EFI_STATUS
> > > > > >
> > > > > > +AssignPciFeaturesConfigurationTable (
> > > > > >
> > > > > > +  IN  UINTN NumberOfRootPorts
> > > > > >
> > > > > > +  )
> > > > > >
> > > > > > +{
> > > > > >
> > > > > > +  UINTN                       Instances;
> > > > > >
> > > > > > +  LIST_ENTRY                  *Link;
> > > > > >
> > > > > > +  PRIMARY_ROOT_PORT_NODE      *Temp;
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  if ( !mPrimaryRootPortList
> > > > > >
> > > > > > +      && NumberOfRootPorts) {
> > > > > >
> > > > > > +    DEBUG ((
> > > > > >
> > > > > > +        DEBUG_ERROR,
> > > > > >
> > > > > > +        "Critical error! no internal table setup for %d PCI Root ports \n",
> > > > > >
> > > > > > +        NumberOfRootPorts
> > > > > >
> > > > > > +    ));
> > > > > >
> > > > > > +    return EFI_INVALID_PARAMETER;
> > > > > >
> > > > > > +  }
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  if ( NumberOfRootPorts) {
> > > > > >
> > > > > > +    Link = &mPrimaryRootPortList->NeighborRootPort;
> > > > > >
> > > > > > +    for ( Instances = 0
> > > > > >
> > > > > > +        ; (Instances < NumberOfRootPorts)
> > > > > >
> > > > > > +        ; Instances++
> > > > > >
> > > > > > +    ) {
> > > > > >
> > > > > > +      Temp = PRIMARY_ROOT_PORT_NODE_FROM_LINK ( Link);
> > > > > >
> > > > > > +      Temp->OtherPciFeaturesConfigurationTable =
> > > > > > &mPciFeaturesConfigurationTableInstances [Instances];
> > > > > >
> > > > > > +      DEBUG ((
> > > > > >
> > > > > > +          DEBUG_INFO,
> > > > > >
> > > > > > +          "Assigned to %dth primary root port\n",
> > > > > >
> > > > > > +          Instances
> > > > > >
> > > > > > +      ));
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +      Link = Link->ForwardLink;
> > > > > >
> > > > > > +    }
> > > > > >
> > > > > > +    if ( Link != &mPrimaryRootPortList->NeighborRootPort) {
> > > > > >
> > > > > > +      DEBUG ((
> > > > > >
> > > > > > +          DEBUG_ERROR,
> > > > > >
> > > > > > +          "Error!! PCI Root Port list is not properly matched with Config.,
> > > Table
> > > > > > list \n"
> > > > > >
> > > > > > +      ));
> > > > > >
> > > > > > +      return EFI_UNSUPPORTED;
> > > > > >
> > > > > > +    }
> > > > > >
> > > > > > +  }
> > > > > >
> > > > > > +  return  EFI_SUCCESS;
> > > > > >
> > > > > > +}
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +/**
> > > > > >
> > > > > > +  Prepare each PCI Controller (Root Port) with its own PCI Feature
> > > > > > configuration
> > > > > >
> > > > > > +  table node that can be used for tracking to align all PCI nodes in its
> > > > > > hierarchy.
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @param  PrimaryRootPorts      A pointer to
> > > PRIMARY_ROOT_PORT_NODE
> > > > > >
> > > > > > +  @param  NumberOfRootPorts     Total number of pysical primary
> PCI
> > > > > Root
> > > > > > ports
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @retval EFI_OUT_OF_RESOURCES  unable to allocate buffer to
> store
> > > PCI
> > > > > > feature
> > > > > >
> > > > > > +                                configuration table for all the physical PCI root
> > > > > >
> > > > > > +                                ports given
> > > > > >
> > > > > > +          EFI_INVALID_PARAMETER if the primary PCI root ports list is
> > > vacant
> > > > > > when
> > > > > >
> > > > > > +                                there is one or more PCI Root port indicated as per
> > > > > >
> > > > > > +                                input parameter
> > > > > >
> > > > > > +          EFI_UNSUPPORTED       The PCI Root Port nodes not paired
> > > equally
> > > > > with
> > > > > >
> > > > > > +                                the PCI Configuration Table nodes
> > > > > >
> > > > > > +          EFI_SUCCESS           each PCI feature configuration node is
> paired
> > > > > > equally
> > > > > >
> > > > > > +                                with each PCI Root port in the list
> > > > > >
> > > > > > +**/
> > > > > >
> > > > > > +EFI_STATUS
> > > > > >
> > > > > > +PreparePciControllerConfigurationTable (
> > > > > >
> > > > > > +  IN  PRIMARY_ROOT_PORT_NODE    *PrimaryRootPorts,
> > > > > >
> > > > > > +  IN  UINTN                     NumberOfRootPorts
> > > > > >
> > > > > > +  )
> > > > > >
> > > > > > +{
> > > > > >
> > > > > > +  EFI_STATUS                    Status;
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  mPrimaryRootPortList = PrimaryRootPorts;
> > > > > >
> > > > > > +  DEBUG ((
> > > > > >
> > > > > > +      DEBUG_INFO, "Number of primary Root Ports found on this
> bridge
> > > > > > = %d\n",
> > > > > >
> > > > > > +      NumberOfRootPorts
> > > > > >
> > > > > > +  ));
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  Status = CreatePciFeaturesConfigurationTableInstances
> > > > > > ( NumberOfRootPorts);
> > > > > >
> > > > > > +  if ( EFI_ERROR(Status)) {
> > > > > >
> > > > > > +    DEBUG ((
> > > > > >
> > > > > > +        DEBUG_ERROR, "Unexpected memory node creation error for
> PCI
> > > > > > features!\n"
> > > > > >
> > > > > > +    ));
> > > > > >
> > > > > > +  } else {
> > > > > >
> > > > > > +    //
> > > > > >
> > > > > > +    // align the primary root port nodes list with the PCI Feature
> > > > > configuration
> > > > > >
> > > > > > +    // table. Note that the PCI Feature configuration table is not
> > > maintain
> > > > > for
> > > > > >
> > > > > > +    // the RCiEP devices
> > > > > >
> > > > > > +    //
> > > > > >
> > > > > > +    Status = AssignPciFeaturesConfigurationTable
> > > ( NumberOfRootPorts);
> > > > > >
> > > > > > +  }
> > > > > >
> > > > > > +  return Status;
> > > > > >
> > > > > > +}
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +/**
> > > > > >
> > > > > > +  Scan all the nodes of the RootBridge to identify and create a
> separate
> > > list
> > > > > >
> > > > > > +  of all primary physical PCI root ports and link each with its own
> > > instance
> > > > > of
> > > > > >
> > > > > > +  the PCI Feature Configuration Table.
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @param  RootBridge    A pointer to the PCI_IO_DEVICE of the PCI
> > > Root
> > > > > > Bridge
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @retval EFI_OUT_OF_RESOURCES  unable to allocate buffer to
> store
> > > PCI
> > > > > > feature
> > > > > >
> > > > > > +                                configuration table for all the physical PCI root
> > > > > >
> > > > > > +                                ports given
> > > > > >
> > > > > > +          EFI_NOT_FOUND         No PCI Bridge device found
> > > > > >
> > > > > > +          EFI_SUCCESS           PCI Feature COnfiguration table created for
> all
> > > > > >
> > > > > > +                                the PCI Rooot ports found
> > > > > >
> > > > > > +          EFI_INVALID_PARAMETER invalid parameter passed to the
> > > routine
> > > > > > which
> > > > > >
> > > > > > +                                creates the PCI controller node for the primary
> > > > > >
> > > > > > +                                Root post list
> > > > > >
> > > > > > +**/
> > > > > >
> > > > > > +EFI_STATUS
> > > > > >
> > > > > > +RecordPciRootPortBridges (
> > > > > >
> > > > > > +  IN  PCI_IO_DEVICE           *RootBridge
> > > > > >
> > > > > > +  )
> > > > > >
> > > > > > +{
> > > > > >
> > > > > > +  EFI_STATUS              Status = EFI_NOT_FOUND;
> > > > > >
> > > > > > +  LIST_ENTRY              *Link;
> > > > > >
> > > > > > +  PCI_IO_DEVICE           *Device;
> > > > > >
> > > > > > +  UINTN                   NumberOfRootPorts;
> > > > > >
> > > > > > +  PRIMARY_ROOT_PORT_NODE  *PrimaryRootPorts,
> > > > > >
> > > > > > +                          *TempNode;
> > > > > >
> > > > > > +  UINT8                   RootPortSecBus,
> > > > > >
> > > > > > +                          RootPortSubBus;
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  DEBUG ((
> > > > > >
> > > > > > +      DEBUG_INFO, "<<********** RecordPciRootPortBridges -
> start
> > > > > > *************>>\n"
> > > > > >
> > > > > > +  ));
> > > > > >
> > > > > > +  NumberOfRootPorts = 0;
> > > > > >
> > > > > > +  PrimaryRootPorts = NULL;
> > > > > >
> > > > > > +  for ( Link = RootBridge->ChildList.ForwardLink
> > > > > >
> > > > > > +      ; Link != &RootBridge->ChildList
> > > > > >
> > > > > > +      ; Link = Link->ForwardLink
> > > > > >
> > > > > > +  ) {
> > > > > >
> > > > > > +    Device = PCI_IO_DEVICE_FROM_LINK (Link);
> > > > > >
> > > > > > +    if (IS_PCI_BRIDGE (&Device->Pci)) {
> > > > > >
> > > > > > +      Status = GetPciRootPortBusAssigned (
> > > > > >
> > > > > > +                  Device,
> > > > > >
> > > > > > +                  NULL,
> > > > > >
> > > > > > +                  &RootPortSecBus,
> > > > > >
> > > > > > +                  &RootPortSubBus
> > > > > >
> > > > > > +                  );
> > > > > >
> > > > > > +      if ( !EFI_ERROR(Status)) {
> > > > > >
> > > > > > +        DEBUG ((
> > > > > >
> > > > > > +            DEBUG_INFO, "::Device [%02x|%02x|%02x] - SecBus=0x%x,
> > > > > > SubBus=0x%x\n",
> > > > > >
> > > > > > +            Device->BusNumber, Device->DeviceNumber, Device-
> > > > > > >FunctionNumber,
> > > > > >
> > > > > > +            RootPortSecBus, RootPortSubBus
> > > > > >
> > > > > > +        ));
> > > > > >
> > > > > > +      } else {
> > > > > >
> > > > > > +        DEBUG ((
> > > > > >
> > > > > > +            DEBUG_ERROR, "Unexpected read error [0x%lx]::Device
> > > > > > [%02x|%02x|%02x]\n",
> > > > > >
> > > > > > +            Status, Device->BusNumber, Device->DeviceNumber,
> Device-
> > > > > > >FunctionNumber
> > > > > >
> > > > > > +        ));
> > > > > >
> > > > > > +        RootPortSecBus = RootPortSubBus = 0;
> > > > > >
> > > > > > +        continue;
> > > > > >
> > > > > > +      }
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +      if ( !PrimaryRootPorts) {
> > > > > >
> > > > > > +        NumberOfRootPorts++;
> > > > > >
> > > > > > +        Status = CreatePrimaryPciRootPortNode (
> > > > > >
> > > > > > +                    RootBridge,
> > > > > >
> > > > > > +                    Device,
> > > > > >
> > > > > > +                    RootPortSecBus,
> > > > > >
> > > > > > +                    RootPortSubBus,
> > > > > >
> > > > > > +                    &PrimaryRootPorts
> > > > > >
> > > > > > +                    );
> > > > > >
> > > > > > +        if ( EFI_ERROR(Status)) {
> > > > > >
> > > > > > +          //
> > > > > >
> > > > > > +          // abort mission to scan for all primary roots ports of a bridge
> > > > > >
> > > > > > +          // controller if error encountered for very first PCI primary
> root
> > > port
> > > > > >
> > > > > > +          //
> > > > > >
> > > > > > +          DEBUG ((
> > > > > >
> > > > > > +              DEBUG_ERROR, "Unexpected node creation error
> > > [0x%lx]::Device
> > > > > > [%02x|%02x|%02x]\n",
> > > > > >
> > > > > > +              Status, Device->BusNumber, Device->DeviceNumber,
> Device-
> > > > > > >FunctionNumber
> > > > > >
> > > > > > +          ));
> > > > > >
> > > > > > +          return Status;
> > > > > >
> > > > > > +        }
> > > > > >
> > > > > > +        DEBUG ((
> > > > > >
> > > > > > +            DEBUG_INFO, "first primary root port found::Device
> > > > > > [%02x|%02x|%02x]\n",
> > > > > >
> > > > > > +            Device->BusNumber, Device->DeviceNumber, Device-
> > > > > > >FunctionNumber
> > > > > >
> > > > > > +        ));
> > > > > >
> > > > > > +      } else {
> > > > > >
> > > > > > +        if ( !CheckChildRootPort ( PrimaryRootPorts, RootPortSecBus,
> > > > > > RootPortSubBus)) {
> > > > > >
> > > > > > +          NumberOfRootPorts++;
> > > > > >
> > > > > > +          TempNode = NULL;
> > > > > >
> > > > > > +          Status = CreatePrimaryPciRootPortNode (
> > > > > >
> > > > > > +                      RootBridge,
> > > > > >
> > > > > > +                      Device,
> > > > > >
> > > > > > +                      RootPortSecBus,
> > > > > >
> > > > > > +                      RootPortSubBus,
> > > > > >
> > > > > > +                      &TempNode
> > > > > >
> > > > > > +                      );
> > > > > >
> > > > > > +          if ( !EFI_ERROR(Status)) {
> > > > > >
> > > > > > +            //
> > > > > >
> > > > > > +            // another primary root port found on the same bridge
> > > controller
> > > > > >
> > > > > > +            // insert in the node list
> > > > > >
> > > > > > +            //
> > > > > >
> > > > > > +            InsertTailList ( &PrimaryRootPorts->NeighborRootPort,
> > > > > &TempNode-
> > > > > > >NeighborRootPort);
> > > > > >
> > > > > > +            DEBUG ((
> > > > > >
> > > > > > +                DEBUG_INFO, "next primary root port found::Device
> > > > > > [%02x|%02x|%02x]\n",
> > > > > >
> > > > > > +                Device->BusNumber, Device->DeviceNumber, Device-
> > > > > > >FunctionNumber
> > > > > >
> > > > > > +            ));
> > > > > >
> > > > > > +          } else {
> > > > > >
> > > > > > +            DEBUG ((
> > > > > >
> > > > > > +                DEBUG_ERROR, "Unexpected node creation error
> > > [0x%lx]::Device
> > > > > > [%02x|%02x|%02x]\n",
> > > > > >
> > > > > > +                Status, Device->BusNumber, Device->DeviceNumber,
> Device-
> > > > > > >FunctionNumber
> > > > > >
> > > > > > +            ));
> > > > > >
> > > > > > +          }
> > > > > >
> > > > > > +        }
> > > > > >
> > > > > > +      }
> > > > > >
> > > > > > +    }
> > > > > >
> > > > > > +  }
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  // prepare the PCI root port and its feature configuration table list
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  if ( NumberOfRootPorts) {
> > > > > >
> > > > > > +    Status = PreparePciControllerConfigurationTable (
> > > > > >
> > > > > > +                PrimaryRootPorts,
> > > > > >
> > > > > > +                NumberOfRootPorts
> > > > > >
> > > > > > +              );
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  } else {
> > > > > >
> > > > > > +    DEBUG ((
> > > > > >
> > > > > > +        DEBUG_INFO, "No PCI Root port found on this bridge!\n"
> > > > > >
> > > > > > +    ));
> > > > > >
> > > > > > +  }
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  DEBUG ((
> > > > > >
> > > > > > +      DEBUG_INFO, "<<********** RecordPciRootPortBridges -
> end
> > > > > > **********>>\n"
> > > > > >
> > > > > > +  ));
> > > > > >
> > > > > > +  return Status;
> > > > > >
> > > > > > +}
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +/**
> > > > > >
> > > > > > +  Enumerate all the nodes of the specified root bridge or PCI-PCI
> > > Bridge, to
> > > > > >
> > > > > > +  configure the other PCI features.
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @param RootBridge          A pointer to the PCI_IO_DEVICE.
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @retval EFI_SUCCESS           The other PCI features configuration
> > > during
> > > > > > enumeration
> > > > > >
> > > > > > +                                of all the nodes of the PCI root bridge instance
> were
> > > > > >
> > > > > > +                                programmed in PCI-compliance pattern along with
> the
> > > > > >
> > > > > > +                                device-specific policy, as applicable.
> > > > > >
> > > > > > +  @retval EFI_UNSUPPORTED       One of the override operation
> maong
> > > the
> > > > > > nodes of
> > > > > >
> > > > > > +                                the PCI hierarchy resulted in a incompatible
> address
> > > > > >
> > > > > > +                                range.
> > > > > >
> > > > > > +  @retval EFI_INVALID_PARAMETER The override operation is
> > > performed
> > > > > > with invalid input
> > > > > >
> > > > > > +                                parameters.
> > > > > >
> > > > > > +**/
> > > > > >
> > > > > > +EFI_STATUS
> > > > > >
> > > > > > +EnumerateOtherPciFeatures (
> > > > > >
> > > > > > +  IN PCI_IO_DEVICE          *RootBridge
> > > > > >
> > > > > > +  )
> > > > > >
> > > > > > +{
> > > > > >
> > > > > > +  EFI_STATUS            Status;
> > > > > >
> > > > > > +  CHAR16                *Str;
> > > > > >
> > > > > > +  UINTN                 OtherPciFeatureConfigPhase;
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  // check on PCI features configuration is complete and re-
> > > enumeration is
> > > > > > required
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  if ( !CheckPciFeaturesConfigurationRequired ( RootBridge)) {
> > > > > >
> > > > > > +    return EFI_ALREADY_STARTED;
> > > > > >
> > > > > > +  }
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  Str = ConvertDevicePathToText (
> > > > > >
> > > > > > +          DevicePathFromHandle (RootBridge->Handle),
> > > > > >
> > > > > > +          FALSE,
> > > > > >
> > > > > > +          FALSE
> > > > > >
> > > > > > +        );
> > > > > >
> > > > > > +  DEBUG ((DEBUG_INFO, "Enumerating PCI features for Root
> > > Bridge %s\n",
> > > > > > Str != NULL ? Str : L""));
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  for ( OtherPciFeatureConfigPhase = PciFeatureRootBridgeScan
> > > > > >
> > > > > > +      ; OtherPciFeatureConfigPhase <=
> > > PciFeatureConfigurationComplete
> > > > > >
> > > > > > +      ; OtherPciFeatureConfigPhase++
> > > > > >
> > > > > > +      ) {
> > > > > >
> > > > > > +    switch ( OtherPciFeatureConfigPhase){
> > > > > >
> > > > > > +      case  PciFeatureRootBridgeScan:
> > > > > >
> > > > > > +        SetupPciFeaturesConfigurationDefaults ();
> > > > > >
> > > > > > +        //
> > > > > >
> > > > > > +        //first scan the entire root bridge heirarchy for the primary PCI
> > > root
> > > > > > ports
> > > > > >
> > > > > > +        //
> > > > > >
> > > > > > +        RecordPciRootPortBridges ( RootBridge);
> > > > > >
> > > > > > +        break;
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +      case  PciFeatureGetDevicePolicy:
> > > > > >
> > > > > > +      case  PciFeatureSetupPhase:
> > > > > >
> > > > > > +        DEBUG ((
> > > > > >
> > > > > > +            DEBUG_INFO, "<<********** SetupPciFeatures - start
> > > > > > **********>>\n"
> > > > > >
> > > > > > +        ));
> > > > > >
> > > > > > +        //
> > > > > >
> > > > > > +        // enumerate the other PCI features
> > > > > >
> > > > > > +        //
> > > > > >
> > > > > > +        Status = SetupPciFeatures ( RootBridge,
> > > OtherPciFeatureConfigPhase);
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +        DEBUG ((
> > > > > >
> > > > > > +            DEBUG_INFO, "<<********** SetupPciFeatures - end
> > > > > > **********>>\n"
> > > > > >
> > > > > > +        ));
> > > > > >
> > > > > > +        break;
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +      case  PciFeatureConfigurationPhase:
> > > > > >
> > > > > > +        //
> > > > > >
> > > > > > +        // override the PCI features as per enumeration phase
> > > > > >
> > > > > > +        //
> > > > > >
> > > > > > +        DEBUG ((DEBUG_INFO, "PCI features override for Root
> > > Bridge %s\n",
> > > > > > Str != NULL ? Str : L""));
> > > > > >
> > > > > > +        DEBUG ((
> > > > > >
> > > > > > +            DEBUG_INFO, "<<********** ProgramPciFeatures - start
> > > > > > **********>>\n"
> > > > > >
> > > > > > +        ));
> > > > > >
> > > > > > +        Status = ProgramPciFeatures ( RootBridge);
> > > > > >
> > > > > > +        DEBUG ((
> > > > > >
> > > > > > +            DEBUG_INFO, "<<********** ProgramPciFeatures - end
> > > > > > **********>>\n"
> > > > > >
> > > > > > +        ));
> > > > > >
> > > > > > +        break;
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +      case  PciFeatureConfigurationComplete:
> > > > > >
> > > > > > +        //
> > > > > >
> > > > > > +        // clean up the temporary resource nodes created for this root
> > > bridge
> > > > > >
> > > > > > +        //
> > > > > >
> > > > > > +        DestroyPrimaryRootPortNodes ();
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +        ErasePciFeaturesConfigurationTable ();
> > > > > >
> > > > > > +    }
> > > > > >
> > > > > > +  }
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  if (Str != NULL) {
> > > > > >
> > > > > > +    FreePool (Str);
> > > > > >
> > > > > > +  }
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  // mark this root bridge as PCI features configuration complete,
> and
> > > no
> > > > > > new
> > > > > >
> > > > > > +  // enumeration is required
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  AddRootBridgeInPciFeaturesConfigCompletionList ( RootBridge,
> > > FALSE);
> > > > > >
> > > > > > +  return Status;
> > > > > >
> > > > > > +}
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +/**
> > > > > >
> > > > > > +  This routine is invoked from the Stop () interface for the EFI
> handle of
> > > > > the
> > > > > >
> > > > > > +  RootBridge. Free up its node of type
> > > > > > PCI_FEATURE_CONFIGURATION_COMPLETION_LIST.
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @param  RootBridge      A pointer to the PCI_IO_DEVICE
> > > > > >
> > > > > > +**/
> > > > > >
> > > > > > +VOID
> > > > > >
> > > > > > +DestroyRootBridgePciFeaturesConfigCompletionList (
> > > > > >
> > > > > > +  IN PCI_IO_DEVICE          *RootBridge
> > > > > >
> > > > > > +  )
> > > > > >
> > > > > > +{
> > > > > >
> > > > > > +  LIST_ENTRY                                  *Link;
> > > > > >
> > > > > > +  PCI_FEATURE_CONFIGURATION_COMPLETION_LIST   *Temp;
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  if ( mPciFeaturesConfigurationCompletionList) {
> > > > > >
> > > > > > +    Link = &mPciFeaturesConfigurationCompletionList-
> >RootBridgeLink;
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +    do {
> > > > > >
> > > > > > +      Temp =
> > > > > > PCI_FEATURE_CONFIGURATION_COMPLETION_LIST_FROM_LINK
> > > (Link);
> > > > > >
> > > > > > +      if ( Temp->RootBridgeHandle == RootBridge->Handle) {
> > > > > >
> > > > > > +        RemoveEntryList ( Link);
> > > > > >
> > > > > > +        FreePool ( Temp);
> > > > > >
> > > > > > +        return;
> > > > > >
> > > > > > +      }
> > > > > >
> > > > > > +      Link = Link->ForwardLink;
> > > > > >
> > > > > > +    } while (Link != &mPciFeaturesConfigurationCompletionList-
> > > > > > >RootBridgeLink);
> > > > > >
> > > > > > +  }
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  // not found on the PCI feature configuration completion list,
> return
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  return;
> > > > > >
> > > > > > +}
> > > > > >
> > > > > > diff --git
> a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> > > > > > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> > > > > > new file mode 100644
> > > > > > index 0000000000..9f225fa993
> > > > > > --- /dev/null
> > > > > > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> > > > > > @@ -0,0 +1,201 @@
> > > > > > +/** @file
> > > > > >
> > > > > > +  PCI standard feature support functions implementation for PCI
> Bus
> > > > > > module..
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> > > > > >
> > > > > > +SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +**/
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +#ifndef _EFI_PCI_FEATURES_SUPPORT_H_
> > > > > >
> > > > > > +#define _EFI_PCI_FEATURES_SUPPORT_H_
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +#include "PciBus.h"
> > > > > >
> > > > > > +#include "PciPlatformSupport.h"
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +//
> > > > > >
> > > > > > +// Macro definitions for the PCI Features support PCD
> > > > > >
> > > > > > +//
> > > > > >
> > > > > > +#define PCI_FEATURE_SUPPORT_FLAG_MPS  BIT0
> > > > > >
> > > > > > +#define PCI_FEATURE_SUPPORT_FLAG_MRRS BIT1
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +//
> > > > > >
> > > > > > +// defines the data structure to hold the details of the PCI Root
> port
> > > > > devices
> > > > > >
> > > > > > +//
> > > > > >
> > > > > > +typedef struct _PRIMARY_ROOT_PORT_NODE
> > > > > > PRIMARY_ROOT_PORT_NODE;
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +//
> > > > > >
> > > > > > +// defines the data structure to hold the configuration data for the
> > > other
> > > > > > PCI
> > > > > >
> > > > > > +// features
> > > > > >
> > > > > > +//
> > > > > >
> > > > > > +typedef struct _OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > > > > > OTHER_PCI_FEATURES_CONFIGURATION_TABLE;
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +//
> > > > > >
> > > > > > +// Defines for the PCI features configuration completion and re-
> > > > > > enumeration list
> > > > > >
> > > > > > +//
> > > > > >
> > > > > > +typedef struct
> _PCI_FEATURE_CONFIGURATION_COMPLETION_LIST
> > > > > > PCI_FEATURE_CONFIGURATION_COMPLETION_LIST;
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +//
> > > > > >
> > > > > > +// Signature value for the PCI Root Port node
> > > > > >
> > > > > > +//
> > > > > >
> > > > > > +#define PCI_ROOT_PORT_SIGNATURE               SIGNATURE_32 ('p',
> 'c',
> > > 'i',
> > > > > 'p')
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +//
> > > > > >
> > > > > > +// Definitions of the PCI Root Port data structure members
> > > > > >
> > > > > > +//
> > > > > >
> > > > > > +struct _PRIMARY_ROOT_PORT_NODE {
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  // Signature header
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  UINT32                                    Signature;
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  // linked list pointers to next node
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  LIST_ENTRY                                NeighborRootPort;
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  // EFI handle of the parent Root Bridge instance
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  EFI_HANDLE                                RootBridgeHandle;
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  // EFI handle of the PCI controller
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  EFI_HANDLE                                RootPortHandle;
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  // PCI Secondary bus value of the PCI controller
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  UINT8                                     SecondaryBusStart;
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  // PCI Subordinate bus value of the PCI controller
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  UINT8                                     SecondaryBusEnd;
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  // pointer to the corresponding PCI feature configuration Table
> node
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > > > > > *OtherPciFeaturesConfigurationTable;
> > > > > >
> > > > > > +};
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +#define PRIMARY_ROOT_PORT_NODE_FROM_LINK(a) \
> > > > > >
> > > > > > +  CR (a, PRIMARY_ROOT_PORT_NODE, NeighborRootPort,
> > > > > > PCI_ROOT_PORT_SIGNATURE)
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +//
> > > > > >
> > > > > > +// Definition of the PCI Feature configuration Table members
> > > > > >
> > > > > > +//
> > > > > >
> > > > > > +struct _OTHER_PCI_FEATURES_CONFIGURATION_TABLE {
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  // Configuration Table ID
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  UINTN                                     ID;
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  // to configure the PCI feature Maximum payload size to maintain
> the
> > > > > data
> > > > > > packet
> > > > > >
> > > > > > +  // size among all the PCI devices in the PCI hierarchy
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  UINT8                                     Max_Payload_Size;
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  // to configure the PCI feature maximum read request size to
> > > maintain
> > > > > the
> > > > > > memory
> > > > > >
> > > > > > +  // requester size among all the PCI devices in the PCI hierarchy
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  UINT8                                     Max_Read_Request_Size;
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  // lock the Max_Read_Request_Size for the entire PCI tree of a
> root
> > > port
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  BOOLEAN                                   Lock_Max_Read_Request_Size;
> > > > > >
> > > > > > +};
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +//
> > > > > >
> > > > > > +// PCI feature configuration node signature value
> > > > > >
> > > > > > +//
> > > > > >
> > > > > > +#define PCI_FEATURE_CONFIGURATION_SIGNATURE
> > > > > > SIGNATURE_32 ('p', 'c', 'i', 'f')
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +struct _PCI_FEATURE_CONFIGURATION_COMPLETION_LIST {
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  // Signature header
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  UINT32                                    Signature;
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  // link to next Root Bridge whose PCI Feature configuration is
> > > complete
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  LIST_ENTRY                                RootBridgeLink;
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  // EFI handle of the Root Bridge whose PCI feature configuration
> is
> > > > > > complete
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  EFI_HANDLE                                RootBridgeHandle;
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  // indication for complete re-enumeration of the PCI feature
> > > > > configuration
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  BOOLEAN                                   ReEnumeratePciFeatureConfiguration;
> > > > > >
> > > > > > +};
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +#define
> > > > > > PCI_FEATURE_CONFIGURATION_COMPLETION_LIST_FROM_LINK(a)
> \
> > > > > >
> > > > > > +  CR (a, PCI_FEATURE_CONFIGURATION_COMPLETION_LIST,
> > > > > > RootBridgeLink, PCI_FEATURE_CONFIGURATION_SIGNATURE)
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +//
> > > > > >
> > > > > > +// Declaration of the internal sub-phases within the PCI Feature
> > > > > > enumeration
> > > > > >
> > > > > > +//
> > > > > >
> > > > > > +typedef enum {
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  // initial phase in configuring the other PCI features to record the
> > > primary
> > > > > >
> > > > > > +  // root ports
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  PciFeatureRootBridgeScan,
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  // get the PCI device-specific platform policies and align with
> device
> > > > > > capabilities
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  PciFeatureGetDevicePolicy,
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  // align all PCI nodes in the PCI heirarchical tree
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  PciFeatureSetupPhase,
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  // finally override to complete configuration of the PCI feature
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  PciFeatureConfigurationPhase,
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  // PCI feature configuration complete
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  PciFeatureConfigurationComplete
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +}PCI_FEATURE_CONFIGURATION_PHASE;
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +/**
> > > > > >
> > > > > > +  Main routine to indicate platform selection of any of the other PCI
> > > > > features
> > > > > >
> > > > > > +  to be configured by this driver
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @retval TRUE    platform has selected the other PCI features to be
> > > > > > configured
> > > > > >
> > > > > > +          FALSE   platform has not selected any of the other PCI
> features
> > > > > >
> > > > > > +**/
> > > > > >
> > > > > > +BOOLEAN
> > > > > >
> > > > > > +CheckOtherPciFeaturesPcd (
> > > > > >
> > > > > > +  );
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +/**
> > > > > >
> > > > > > +  Enumerate all the nodes of the specified root bridge or PCI-PCI
> > > Bridge, to
> > > > > >
> > > > > > +  configure the other PCI features.
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @param RootBridge          A pointer to the PCI_IO_DEVICE.
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @retval EFI_SUCCESS           The other PCI features configuration
> > > during
> > > > > > enumeration
> > > > > >
> > > > > > +                                of all the nodes of the PCI root bridge instance
> were
> > > > > >
> > > > > > +                                programmed in PCI-compliance pattern along with
> the
> > > > > >
> > > > > > +                                device-specific policy, as applicable.
> > > > > >
> > > > > > +  @retval EFI_UNSUPPORTED       One of the override operation
> maong
> > > the
> > > > > > nodes of
> > > > > >
> > > > > > +                                the PCI hierarchy resulted in a incompatible
> address
> > > > > >
> > > > > > +                                range.
> > > > > >
> > > > > > +  @retval EFI_INVALID_PARAMETER The override operation is
> > > performed
> > > > > > with invalid input
> > > > > >
> > > > > > +                                parameters.
> > > > > >
> > > > > > +**/
> > > > > >
> > > > > > +EFI_STATUS
> > > > > >
> > > > > > +EnumerateOtherPciFeatures (
> > > > > >
> > > > > > +  IN PCI_IO_DEVICE           *RootBridge
> > > > > >
> > > > > > +  );
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +/**
> > > > > >
> > > > > > +  This routine is invoked from the Stop () interface for the EFI
> handle of
> > > > > the
> > > > > >
> > > > > > +  RootBridge. Free up its node of type
> > > > > > PCI_FEATURE_CONFIGURATION_COMPLETION_LIST.
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @param  RootBridge      A pointer to the PCI_IO_DEVICE
> > > > > >
> > > > > > +**/
> > > > > >
> > > > > > +VOID
> > > > > >
> > > > > > +DestroyRootBridgePciFeaturesConfigCompletionList (
> > > > > >
> > > > > > +  IN PCI_IO_DEVICE          *RootBridge
> > > > > >
> > > > > > +  );
> > > > > >
> > > > > > +#endif
> > > > > >
> > > > > > diff --git
> a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> > > > > > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> > > > > > new file mode 100644
> > > > > > index 0000000000..d94037d69a
> > > > > > --- /dev/null
> > > > > > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> > > > > > @@ -0,0 +1,565 @@
> > > > > > +/** @file
> > > > > >
> > > > > > +  This file encapsulate the usage of PCI Platform Protocol
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  This file define the necessary hooks used to obtain the platform
> > > > > >
> > > > > > +  level data and policies which could be used in the PCI
> Enumeration
> > > > > phases
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> > > > > >
> > > > > > +SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +**/
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +#include "PciPlatformSupport.h"
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +EFI_PCI_PLATFORM_PROTOCOL                     *mPciPlatformProtocol;
> > > > > >
> > > > > > +EFI_PCI_OVERRIDE_PROTOCOL                     *mPciOverrideProtocol;
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +EFI_PCI_PLATFORM_PROTOCOL2
> *mPciPlatformProtocol2;
> > > > > >
> > > > > > +EFI_PCI_OVERRIDE_PROTOCOL2                    *mPciOverrideProtocol2;
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +/**
> > > > > >
> > > > > > +  This function retrieves the PCI Platform Protocol published by
> > > platform
> > > > > > driver
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +**/
> > > > > >
> > > > > > +VOID
> > > > > >
> > > > > > +GetPciPlatformProtocol (
> > > > > >
> > > > > > +  )
> > > > > >
> > > > > > +{
> > > > > >
> > > > > > +  mPciPlatformProtocol2 = NULL;
> > > > > >
> > > > > > +  gBS->LocateProtocol (
> > > > > >
> > > > > > +      &gEfiPciPlatformProtocol2Guid,
> > > > > >
> > > > > > +      NULL,
> > > > > >
> > > > > > +      (VOID **) &mPciPlatformProtocol2
> > > > > >
> > > > > > +  );
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  // If PCI Platform protocol doesn't exist, try to get Pci Override
> > > Protocol.
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  if (mPciPlatformProtocol2 == NULL) {
> > > > > >
> > > > > > +    mPciOverrideProtocol2 = NULL;
> > > > > >
> > > > > > +    gBS->LocateProtocol (
> > > > > >
> > > > > > +        &gEfiPciOverrideProtocol2Guid,
> > > > > >
> > > > > > +        NULL,
> > > > > >
> > > > > > +        (VOID **) &mPciOverrideProtocol2
> > > > > >
> > > > > > +    );
> > > > > >
> > > > > > +  }
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  // fetch the old PCI Platform Protocols if new are not installed
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  if (mPciOverrideProtocol2 == NULL) {
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +    mPciPlatformProtocol = NULL;
> > > > > >
> > > > > > +    gBS->LocateProtocol (
> > > > > >
> > > > > > +        &gEfiPciPlatformProtocolGuid,
> > > > > >
> > > > > > +        NULL,
> > > > > >
> > > > > > +        (VOID **) &mPciPlatformProtocol
> > > > > >
> > > > > > +    );
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +    //
> > > > > >
> > > > > > +    // If PCI Platform protocol doesn't exist, try to  get Pci Override
> > > Protocol.
> > > > > >
> > > > > > +    //
> > > > > >
> > > > > > +    if (mPciPlatformProtocol == NULL) {
> > > > > >
> > > > > > +      mPciOverrideProtocol = NULL;
> > > > > >
> > > > > > +      gBS->LocateProtocol (
> > > > > >
> > > > > > +          &gEfiPciOverrideProtocolGuid,
> > > > > >
> > > > > > +          NULL,
> > > > > >
> > > > > > +          (VOID **) &mPciOverrideProtocol
> > > > > >
> > > > > > +      );
> > > > > >
> > > > > > +    }
> > > > > >
> > > > > > +  }
> > > > > >
> > > > > > +}
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +/**
> > > > > >
> > > > > > +  This function indicates the presence of PCI Platform driver
> > > > > >
> > > > > > +  @retval     TRUE or FALSE
> > > > > >
> > > > > > +**/
> > > > > >
> > > > > > +BOOLEAN
> > > > > >
> > > > > > +CheckPciPlatformProtocolInstall (
> > > > > >
> > > > > > +  )
> > > > > >
> > > > > > +{
> > > > > >
> > > > > > +  if (mPciPlatformProtocol2 != NULL) {
> > > > > >
> > > > > > +    return TRUE;
> > > > > >
> > > > > > +  } else if (mPciOverrideProtocol2 != NULL) {
> > > > > >
> > > > > > +    return TRUE;
> > > > > >
> > > > > > +  } else {
> > > > > >
> > > > > > +    if (mPciPlatformProtocol != NULL) {
> > > > > >
> > > > > > +      return TRUE;
> > > > > >
> > > > > > +    } else if (mPciOverrideProtocol != NULL){
> > > > > >
> > > > > > +      return TRUE;
> > > > > >
> > > > > > +    }
> > > > > >
> > > > > > +  }
> > > > > >
> > > > > > +  return FALSE;
> > > > > >
> > > > > > +}
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +/**
> > > > > >
> > > > > > +  Provides the hooks from the PCI bus driver to every PCI controller
> > > > > > (device/function) at various
> > > > > >
> > > > > > +  stages of the PCI enumeration process that allow the host bridge
> > > driver
> > > > > to
> > > > > > preinitialize individual
> > > > > >
> > > > > > +  PCI controllers before enumeration.
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  This function is called during the PCI enumeration process. No
> specific
> > > > > > action is expected from this
> > > > > >
> > > > > > +  member function. It allows the host bridge driver to preinitialize
> > > > > individual
> > > > > > PCI controllers before
> > > > > >
> > > > > > +  enumeration.
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @param[in] HostBridgeHandle     The associated PCI host bridge
> > > handle.
> > > > > >
> > > > > > +  @param[in] RootBridgeHandle     The associated PCI root bridge
> > > handle.
> > > > > >
> > > > > > +  @param[in] RootBridgePciAddress The address of the PCI device
> on
> > > the
> > > > > > PCI bus.
> > > > > >
> > > > > > +  @param[in] Phase          The phase of the PCI controller
> enumeration.
> > > > > >
> > > > > > +  @param[in] ExecPhase      Defines the execution phase of the PCI
> > > chipset
> > > > > > driver.
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @retval    Status         returns the status from the PCI Platform
> > > protocol as
> > > > > is
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +**/
> > > > > >
> > > > > > +EFI_STATUS
> > > > > >
> > > > > > +PciPlatformPreprocessController (
> > > > > >
> > > > > > +  IN EFI_HANDLE                                    HostBridgeHandle,
> > > > > >
> > > > > > +  IN EFI_HANDLE                                    RootBridgeHandle,
> > > > > >
> > > > > > +  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS
> > > > > > RootBridgePciAddress,
> > > > > >
> > > > > > +  IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE
> Phase,
> > > > > >
> > > > > > +  IN EFI_PCI_EXECUTION_PHASE                       ExecPhase
> > > > > >
> > > > > > +  )
> > > > > >
> > > > > > +{
> > > > > >
> > > > > > +  EFI_STATUS  Status;
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  if (mPciPlatformProtocol2 != NULL) {
> > > > > >
> > > > > > +    //
> > > > > >
> > > > > > +    // Call PlatformPci::PrepController() if the protocol is present.
> > > > > >
> > > > > > +    //
> > > > > >
> > > > > > +    Status = mPciPlatformProtocol2->PlatformPrepController (
> > > > > >
> > > > > > +
> > > > > > (EFI_PCI_PLATFORM_PROTOCOL*)mPciPlatformProtocol2,
> > > > > >
> > > > > > +                                      HostBridgeHandle,
> > > > > >
> > > > > > +                                      RootBridgeHandle,
> > > > > >
> > > > > > +                                      RootBridgePciAddress,
> > > > > >
> > > > > > +                                      Phase,
> > > > > >
> > > > > > +                                      ExecPhase
> > > > > >
> > > > > > +                                    );
> > > > > >
> > > > > > +  } else if (mPciOverrideProtocol2 != NULL) {
> > > > > >
> > > > > > +    //
> > > > > >
> > > > > > +    // Call PlatformPci::PrepController() if the protocol is present.
> > > > > >
> > > > > > +    //
> > > > > >
> > > > > > +    Status = mPciOverrideProtocol2->PlatformPrepController (
> > > > > >
> > > > > > +
> > > > > > (EFI_PCI_PLATFORM_PROTOCOL*)mPciOverrideProtocol2,
> > > > > >
> > > > > > +                                      HostBridgeHandle,
> > > > > >
> > > > > > +                                      RootBridgeHandle,
> > > > > >
> > > > > > +                                      RootBridgePciAddress,
> > > > > >
> > > > > > +                                      Phase,
> > > > > >
> > > > > > +                                      ExecPhase
> > > > > >
> > > > > > +                                    );
> > > > > >
> > > > > > +  } else {
> > > > > >
> > > > > > +    if (mPciPlatformProtocol != NULL) {
> > > > > >
> > > > > > +      //
> > > > > >
> > > > > > +      // Call PlatformPci::PrepController() if the protocol is present.
> > > > > >
> > > > > > +      //
> > > > > >
> > > > > > +      Status = mPciPlatformProtocol->PlatformPrepController (
> > > > > >
> > > > > > +                                      mPciPlatformProtocol,
> > > > > >
> > > > > > +                                      HostBridgeHandle,
> > > > > >
> > > > > > +                                      RootBridgeHandle,
> > > > > >
> > > > > > +                                      RootBridgePciAddress,
> > > > > >
> > > > > > +                                      Phase,
> > > > > >
> > > > > > +                                      ExecPhase
> > > > > >
> > > > > > +                                    );
> > > > > >
> > > > > > +    } else if (mPciOverrideProtocol != NULL) {
> > > > > >
> > > > > > +      //
> > > > > >
> > > > > > +      // Call PlatformPci::PrepController() if the protocol is present.
> > > > > >
> > > > > > +      //
> > > > > >
> > > > > > +      Status = mPciOverrideProtocol->PlatformPrepController (
> > > > > >
> > > > > > +                                      mPciOverrideProtocol,
> > > > > >
> > > > > > +                                      HostBridgeHandle,
> > > > > >
> > > > > > +                                      RootBridgeHandle,
> > > > > >
> > > > > > +                                      RootBridgePciAddress,
> > > > > >
> > > > > > +                                      Phase,
> > > > > >
> > > > > > +                                      ExecPhase
> > > > > >
> > > > > > +                                    );
> > > > > >
> > > > > > +    } else {
> > > > > >
> > > > > > +      //
> > > > > >
> > > > > > +      // return PCI Platform Protocol not found
> > > > > >
> > > > > > +      //
> > > > > >
> > > > > > +      return EFI_NOT_FOUND;
> > > > > >
> > > > > > +    }
> > > > > >
> > > > > > +  }
> > > > > >
> > > > > > +  return Status;
> > > > > >
> > > > > > +}
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +/**
> > > > > >
> > > > > > +  This function notifies the PCI Platform driver about the PCI host
> > > bridge
> > > > > > resource
> > > > > >
> > > > > > +  allocation phase and PCI execution phase.
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @param[in]  HostBridge     The handle of the host bridge
> controller.
> > > > > >
> > > > > > +  @param[in]  Phase          The phase of the PCI bus enumeration.
> > > > > >
> > > > > > +  @param[in]  ExecPhase      Defines the execution phase of the PCI
> > > > > chipset
> > > > > > driver.
> > > > > >
> > > > > > +  @retval     Status          returns the status from the PCI Platform
> > > protocol
> > > > > as
> > > > > > is
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +**/
> > > > > >
> > > > > > +EFI_STATUS
> > > > > >
> > > > > > +PciPlatformNotifyPhase (
> > > > > >
> > > > > > +  IN  EFI_HANDLE                                      HostBridgeHandle,
> > > > > >
> > > > > > +  IN  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE
> Phase,
> > > > > >
> > > > > > +  IN  EFI_PCI_EXECUTION_PHASE                         ExecPhase
> > > > > >
> > > > > > +  )
> > > > > >
> > > > > > +{
> > > > > >
> > > > > > +  EFI_STATUS  Status;
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  if ( mPciPlatformProtocol2 != NULL) {
> > > > > >
> > > > > > +    Status = mPciPlatformProtocol2->PlatformNotify (
> > > > > >
> > > > > > +
> > > > > > (EFI_PCI_PLATFORM_PROTOCOL*)mPciPlatformProtocol2,
> > > > > >
> > > > > > +                                      HostBridgeHandle,
> > > > > >
> > > > > > +                                      Phase,
> > > > > >
> > > > > > +                                      ExecPhase
> > > > > >
> > > > > > +                                    );
> > > > > >
> > > > > > +  } else if ( mPciOverrideProtocol2 != NULL) {
> > > > > >
> > > > > > +    Status = mPciOverrideProtocol2->PlatformNotify (
> > > > > >
> > > > > > +
> > > > > > (EFI_PCI_PLATFORM_PROTOCOL*)mPciOverrideProtocol2,
> > > > > >
> > > > > > +                                      HostBridgeHandle,
> > > > > >
> > > > > > +                                      Phase,
> > > > > >
> > > > > > +                                      ExecPhase
> > > > > >
> > > > > > +                                    );
> > > > > >
> > > > > > +  } else {
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +    if ( mPciPlatformProtocol != NULL) {
> > > > > >
> > > > > > +      Status = mPciPlatformProtocol->PlatformNotify (
> > > > > >
> > > > > > +                                      mPciPlatformProtocol,
> > > > > >
> > > > > > +                                      HostBridgeHandle,
> > > > > >
> > > > > > +                                      Phase,
> > > > > >
> > > > > > +                                      ExecPhase
> > > > > >
> > > > > > +                                    );
> > > > > >
> > > > > > +    } else if ( mPciOverrideProtocol != NULL){
> > > > > >
> > > > > > +      Status = mPciOverrideProtocol->PlatformNotify (
> > > > > >
> > > > > > +                                      mPciOverrideProtocol,
> > > > > >
> > > > > > +                                      HostBridgeHandle,
> > > > > >
> > > > > > +                                      Phase,
> > > > > >
> > > > > > +                                      ExecPhase
> > > > > >
> > > > > > +                                    );
> > > > > >
> > > > > > +    } else {
> > > > > >
> > > > > > +      //
> > > > > >
> > > > > > +      // return PCI Platform Protocol not found
> > > > > >
> > > > > > +      //
> > > > > >
> > > > > > +      return EFI_NOT_FOUND;
> > > > > >
> > > > > > +    }
> > > > > >
> > > > > > +  }
> > > > > >
> > > > > > +  return Status;
> > > > > >
> > > > > > +}
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +/**
> > > > > >
> > > > > > +  This function retrieves the PCI platform policy.
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @param  PciPolicy     pointer to the legacy
> > > EFI_PCI_PLATFORM_POLICY
> > > > > >
> > > > > > +  @retval Status        returns the status from the PCI Platform
> protocol
> > > as is
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +**/
> > > > > >
> > > > > > +EFI_STATUS
> > > > > >
> > > > > > +PciGetPlatformPolicy (
> > > > > >
> > > > > > +  OUT EFI_PCI_PLATFORM_POLICY *PciPolicy
> > > > > >
> > > > > > +  )
> > > > > >
> > > > > > +{
> > > > > >
> > > > > > +  EFI_STATUS  Status;
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  if ( mPciPlatformProtocol2 != NULL) {
> > > > > >
> > > > > > +      Status = mPciPlatformProtocol2->GetPlatformPolicy (
> > > > > >
> > > > > > +
> > > > > > (EFI_PCI_PLATFORM_PROTOCOL*)mPciPlatformProtocol2,
> > > > > >
> > > > > > +                                        PciPolicy
> > > > > >
> > > > > > +                                      );
> > > > > >
> > > > > > +  } else if ( mPciOverrideProtocol2 != NULL) {
> > > > > >
> > > > > > +      Status = mPciOverrideProtocol2->GetPlatformPolicy (
> > > > > >
> > > > > > +
> > > > > > (EFI_PCI_PLATFORM_PROTOCOL*)mPciOverrideProtocol2,
> > > > > >
> > > > > > +                                        PciPolicy
> > > > > >
> > > > > > +                                      );
> > > > > >
> > > > > > +  } else {
> > > > > >
> > > > > > +    if ( mPciPlatformProtocol != NULL) {
> > > > > >
> > > > > > +      Status = mPciPlatformProtocol->GetPlatformPolicy (
> > > > > >
> > > > > > +                                      mPciPlatformProtocol,
> > > > > >
> > > > > > +                                      PciPolicy
> > > > > >
> > > > > > +                                    );
> > > > > >
> > > > > > +    }
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +    if ( mPciOverrideProtocol != NULL) {
> > > > > >
> > > > > > +      Status = mPciOverrideProtocol->GetPlatformPolicy (
> > > > > >
> > > > > > +                                      mPciOverrideProtocol,
> > > > > >
> > > > > > +                                      PciPolicy
> > > > > >
> > > > > > +                                    );
> > > > > >
> > > > > > +    } else {
> > > > > >
> > > > > > +      //
> > > > > >
> > > > > > +      // return PCI Platform Protocol not found
> > > > > >
> > > > > > +      //
> > > > > >
> > > > > > +      return EFI_NOT_FOUND;
> > > > > >
> > > > > > +    }
> > > > > >
> > > > > > +  }
> > > > > >
> > > > > > +  return Status;
> > > > > >
> > > > > > +}
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +/**
> > > > > >
> > > > > > +  This function retrieves the Option ROM image and size from the
> > > Platform.
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  It uses the PCI_IO_DEVICE internal fields are used to store
> OpROM
> > > > > > image/size
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @param Controller     An EFI handle for the PCI bus controller.
> > > > > >
> > > > > > +  @param PciIoDevice    A PCI_IO_DEVICE pointer to the PCI IO
> device
> > > to
> > > > > be
> > > > > > registered.
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @retval EFI_SUCCESS            The option ROM was available for this
> > > device
> > > > > > and loaded into memory.
> > > > > >
> > > > > > +  @retval EFI_NOT_FOUND          No option ROM was available for
> this
> > > > > device.
> > > > > >
> > > > > > +  @retval EFI_OUT_OF_RESOURCES   No memory was available to
> load
> > > the
> > > > > > option ROM.
> > > > > >
> > > > > > +  @retval EFI_DEVICE_ERROR       An error occurred in obtaining the
> > > option
> > > > > > ROM.
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +**/
> > > > > >
> > > > > > +EFI_STATUS
> > > > > >
> > > > > > +GetPlatformPciOptionRom (
> > > > > >
> > > > > > +  IN  EFI_HANDLE                    Controller,
> > > > > >
> > > > > > +  IN  PCI_IO_DEVICE                 *PciIoDevice
> > > > > >
> > > > > > +  )
> > > > > >
> > > > > > +{
> > > > > >
> > > > > > +  EFI_STATUS  Status;
> > > > > >
> > > > > > +  VOID        *PlatformOpRomBuffer;
> > > > > >
> > > > > > +  UINTN       PlatformOpRomSize;
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  if (mPciPlatformProtocol2 != NULL) {
> > > > > >
> > > > > > +    Status = mPciPlatformProtocol2->GetPciRom (
> > > > > >
> > > > > > +
> > > > > > (EFI_PCI_PLATFORM_PROTOCOL*)mPciPlatformProtocol2,
> > > > > >
> > > > > > +                                      PciIoDevice->Handle,
> > > > > >
> > > > > > +                                      &PlatformOpRomBuffer,
> > > > > >
> > > > > > +                                      &PlatformOpRomSize
> > > > > >
> > > > > > +                                      );
> > > > > >
> > > > > > +  } else if (mPciOverrideProtocol2 != NULL) {
> > > > > >
> > > > > > +    Status = mPciOverrideProtocol2->GetPciRom (
> > > > > >
> > > > > > +
> > > > > > (EFI_PCI_PLATFORM_PROTOCOL*)mPciOverrideProtocol2,
> > > > > >
> > > > > > +                                      PciIoDevice->Handle,
> > > > > >
> > > > > > +                                      &PlatformOpRomBuffer,
> > > > > >
> > > > > > +                                      &PlatformOpRomSize
> > > > > >
> > > > > > +                                      );
> > > > > >
> > > > > > +  } else {
> > > > > >
> > > > > > +    if (mPciPlatformProtocol != NULL) {
> > > > > >
> > > > > > +      Status = mPciPlatformProtocol->GetPciRom (
> > > > > >
> > > > > > +                                      mPciPlatformProtocol,
> > > > > >
> > > > > > +                                      PciIoDevice->Handle,
> > > > > >
> > > > > > +                                      &PlatformOpRomBuffer,
> > > > > >
> > > > > > +                                      &PlatformOpRomSize
> > > > > >
> > > > > > +                                      );
> > > > > >
> > > > > > +    } else if (mPciOverrideProtocol != NULL) {
> > > > > >
> > > > > > +      Status = mPciOverrideProtocol->GetPciRom (
> > > > > >
> > > > > > +                                        mPciOverrideProtocol,
> > > > > >
> > > > > > +                                        PciIoDevice->Handle,
> > > > > >
> > > > > > +                                        &PlatformOpRomBuffer,
> > > > > >
> > > > > > +                                        &PlatformOpRomSize
> > > > > >
> > > > > > +                                        );
> > > > > >
> > > > > > +    } else {
> > > > > >
> > > > > > +      //
> > > > > >
> > > > > > +      // return PCI Platform Protocol not found
> > > > > >
> > > > > > +      //
> > > > > >
> > > > > > +      return EFI_NOT_FOUND;
> > > > > >
> > > > > > +    }
> > > > > >
> > > > > > +  }
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  if (!EFI_ERROR (Status)) {
> > > > > >
> > > > > > +    PciIoDevice->EmbeddedRom    = FALSE;
> > > > > >
> > > > > > +    PciIoDevice->RomSize        = (UINT32)PlatformOpRomSize;
> > > > > >
> > > > > > +    PciIoDevice->PciIo.RomSize  = PlatformOpRomSize;
> > > > > >
> > > > > > +    PciIoDevice->PciIo.RomImage = PlatformOpRomBuffer;
> > > > > >
> > > > > > +  }
> > > > > >
> > > > > > +  return Status;
> > > > > >
> > > > > > +}
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +/**
> > > > > >
> > > > > > +  Helper routine to indicate whether the given PCI device specific
> > > policy
> > > > > > value
> > > > > >
> > > > > > +  dictates to override the Max_Payload_Size to a particular value,
> or
> > > set as
> > > > > > per
> > > > > >
> > > > > > +  device capability.
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @param  MPS     Input device-specific policy should be in terms of
> > > type
> > > > > >
> > > > > > +                  EFI_PCI_CONF_MAX_PAYLOAD_SIZE
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @retval TRUE    Setup Max_Payload_Size as per device capability
> > > > > >
> > > > > > +          FALSE   override as per device-specific platform policy
> > > > > >
> > > > > > +**/
> > > > > >
> > > > > > +BOOLEAN
> > > > > >
> > > > > > +SetupMpsAsPerDeviceCapability (
> > > > > >
> > > > > > +  IN  UINT8                   MPS
> > > > > >
> > > > > > +)
> > > > > >
> > > > > > +{
> > > > > >
> > > > > > +  if ( MPS == EFI_PCI_CONF_MAX_PAYLOAD_SIZE_AUTO) {
> > > > > >
> > > > > > +    return TRUE;
> > > > > >
> > > > > > +  } else {
> > > > > >
> > > > > > +    return FALSE;
> > > > > >
> > > > > > +  }
> > > > > >
> > > > > > +}
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +/**
> > > > > >
> > > > > > +  Helper routine to indicate whether the given PCI device specific
> > > policy
> > > > > > value
> > > > > >
> > > > > > +  dictates to override the Max_Read_Req_Size to a particular value,
> or
> > > set
> > > > > as
> > > > > > per
> > > > > >
> > > > > > +  device capability.
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @param  MRRS    Input device-specific policy should be in terms
> of
> > > type
> > > > > >
> > > > > > +                  EFI_PCI_CONF_MAX_READ_REQ_SIZE
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @retval TRUE    Setup Max_Read_Req_Size as per device
> capability
> > > > > >
> > > > > > +          FALSE   override as per device-specific platform policy
> > > > > >
> > > > > > +**/
> > > > > >
> > > > > > +BOOLEAN
> > > > > >
> > > > > > +SetupMrrsAsPerDeviceCapability (
> > > > > >
> > > > > > +  IN  UINT8                   MRRS
> > > > > >
> > > > > > +)
> > > > > >
> > > > > > +{
> > > > > >
> > > > > > +  if ( MRRS == EFI_PCI_CONF_MAX_READ_REQ_SIZE_AUTO) {
> > > > > >
> > > > > > +    return TRUE;
> > > > > >
> > > > > > +  } else {
> > > > > >
> > > > > > +    return FALSE;
> > > > > >
> > > > > > +  }
> > > > > >
> > > > > > +}
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +/**
> > > > > >
> > > > > > +  Routine to translate the given device-specific platform policy from
> > > type
> > > > > >
> > > > > > +  EFI_PCI_CONF_MAX_PAYLOAD_SIZE to HW-specific value, as per
> PCI
> > > > > Base
> > > > > > Specification
> > > > > >
> > > > > > +  Revision 4.0; for the PCI feature Max_Payload_Size.
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @param  MPS     Input device-specific policy should be in terms of
> > > type
> > > > > >
> > > > > > +                  EFI_PCI_CONF_MAX_PAYLOAD_SIZE
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @retval         Range values for the Max_Payload_Size as defined in
> the
> > > > > PCI
> > > > > >
> > > > > > +                  Base Specification 4.0
> > > > > >
> > > > > > +**/
> > > > > >
> > > > > > +UINT8
> > > > > >
> > > > > > +TranslateMpsSetupValueToPci (
> > > > > >
> > > > > > +  IN  UINT8                   MPS
> > > > > >
> > > > > > +)
> > > > > >
> > > > > > +{
> > > > > >
> > > > > > +  switch (MPS) {
> > > > > >
> > > > > > +    case EFI_PCI_CONF_MAX_PAYLOAD_SIZE_128B:
> > > > > >
> > > > > > +      return PCIE_MAX_PAYLOAD_SIZE_128B;
> > > > > >
> > > > > > +    case EFI_PCI_CONF_MAX_PAYLOAD_SIZE_256B:
> > > > > >
> > > > > > +      return PCIE_MAX_PAYLOAD_SIZE_256B;
> > > > > >
> > > > > > +    case EFI_PCI_CONF_MAX_PAYLOAD_SIZE_512B:
> > > > > >
> > > > > > +      return PCIE_MAX_PAYLOAD_SIZE_512B;
> > > > > >
> > > > > > +    case EFI_PCI_CONF_MAX_PAYLOAD_SIZE_1024B:
> > > > > >
> > > > > > +      return PCIE_MAX_PAYLOAD_SIZE_1024B;
> > > > > >
> > > > > > +    case EFI_PCI_CONF_MAX_PAYLOAD_SIZE_2048B:
> > > > > >
> > > > > > +      return PCIE_MAX_PAYLOAD_SIZE_2048B;
> > > > > >
> > > > > > +    case EFI_PCI_CONF_MAX_PAYLOAD_SIZE_4096B:
> > > > > >
> > > > > > +      return PCIE_MAX_PAYLOAD_SIZE_4096B;
> > > > > >
> > > > > > +    default:
> > > > > >
> > > > > > +      return PCIE_MAX_PAYLOAD_SIZE_128B;
> > > > > >
> > > > > > +  }
> > > > > >
> > > > > > +}
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +/**
> > > > > >
> > > > > > +  Routine to translate the given device-specific platform policy from
> > > type
> > > > > >
> > > > > > +  EFI_PCI_CONF_MAX_READ_REQ_SIZE to HW-specific value, as
> per
> > > PCI
> > > > > > Base Specification
> > > > > >
> > > > > > +  Revision 4.0; for the PCI feature Max_Read_Req_Size.
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @param  MRRS    Input device-specific policy should be in terms
> of
> > > type
> > > > > >
> > > > > > +                  EFI_PCI_CONF_MAX_READ_REQ_SIZE
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @retval         Range values for the Max_Read_Req_Size as defined
> in
> > > the
> > > > > > PCI
> > > > > >
> > > > > > +                  Base Specification 4.0
> > > > > >
> > > > > > +**/
> > > > > >
> > > > > > +UINT8
> > > > > >
> > > > > > +TranslateMrrsSetupValueToPci (
> > > > > >
> > > > > > +  IN  UINT8                   MRRS
> > > > > >
> > > > > > +)
> > > > > >
> > > > > > +{
> > > > > >
> > > > > > +  switch (MRRS) {
> > > > > >
> > > > > > +    case EFI_PCI_CONF_MAX_READ_REQ_SIZE_128B:
> > > > > >
> > > > > > +      return PCIE_MAX_READ_REQ_SIZE_128B;
> > > > > >
> > > > > > +    case EFI_PCI_CONF_MAX_READ_REQ_SIZE_256B:
> > > > > >
> > > > > > +      return PCIE_MAX_READ_REQ_SIZE_256B;
> > > > > >
> > > > > > +    case EFI_PCI_CONF_MAX_READ_REQ_SIZE_512B:
> > > > > >
> > > > > > +      return PCIE_MAX_READ_REQ_SIZE_512B;
> > > > > >
> > > > > > +    case EFI_PCI_CONF_MAX_READ_REQ_SIZE_1024B:
> > > > > >
> > > > > > +      return PCIE_MAX_READ_REQ_SIZE_1024B;
> > > > > >
> > > > > > +    case EFI_PCI_CONF_MAX_READ_REQ_SIZE_2048B:
> > > > > >
> > > > > > +      return PCIE_MAX_READ_REQ_SIZE_2048B;
> > > > > >
> > > > > > +    case EFI_PCI_CONF_MAX_READ_REQ_SIZE_4096B:
> > > > > >
> > > > > > +      return PCIE_MAX_READ_REQ_SIZE_4096B;
> > > > > >
> > > > > > +    default:
> > > > > >
> > > > > > +      return PCIE_MAX_READ_REQ_SIZE_128B;
> > > > > >
> > > > > > +  }
> > > > > >
> > > > > > +}
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +/**
> > > > > >
> > > > > > +  Generic routine to setup the PCI features as per its
> predetermined
> > > > > > defaults.
> > > > > >
> > > > > > +**/
> > > > > >
> > > > > > +VOID
> > > > > >
> > > > > > +SetupDefaultsDevicePlatformPolicy (
> > > > > >
> > > > > > +  IN  PCI_IO_DEVICE               *PciDevice
> > > > > >
> > > > > > +  )
> > > > > >
> > > > > > +{
> > > > > >
> > > > > > +  PciDevice->SetupMPS =
> EFI_PCI_CONF_MAX_PAYLOAD_SIZE_AUTO;
> > > > > >
> > > > > > +  PciDevice->SetupMRRS =
> > > EFI_PCI_CONF_MAX_READ_REQ_SIZE_AUTO;
> > > > > >
> > > > > > +}
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +/**
> > > > > >
> > > > > > +  Intermediate routine to either get the PCI device specific
> platform
> > > > > policies
> > > > > >
> > > > > > +  through the PCI Platform Protocol, or its alias the PCI Override
> > > Protocol.
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @param  PciIoDevice         A pointer to PCI_IO_DEVICE
> > > > > >
> > > > > > +  @param  PciPlatformProtocol A pointer to
> > > > > > EFI_PCI_PLATFORM_PROTOCOL2
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @retval EFI_STATUS          The direct status from the PCI Platform
> > > Protocol
> > > > > >
> > > > > > +  @retval EFI_SUCCESS         if on returning predetermined PCI
> features
> > > > > > defaults,
> > > > > >
> > > > > > +                              for the case when protocol returns as
> > > EFI_UNSUPPORTED
> > > > > >
> > > > > > +                              to indicate PCI device exist and it has no platform
> > > > > >
> > > > > > +                              policy defined.
> > > > > >
> > > > > > +**/
> > > > > >
> > > > > > +EFI_STATUS
> > > > > >
> > > > > > +GetPciDevicePlatformPolicyEx (
> > > > > >
> > > > > > +  IN  PCI_IO_DEVICE               *PciIoDevice,
> > > > > >
> > > > > > +  IN  EFI_PCI_PLATFORM_PROTOCOL2  *PciPlatformProtocol
> > > > > >
> > > > > > +  )
> > > > > >
> > > > > > +{
> > > > > >
> > > > > > +  EFI_PCI_PLATFORM_EXTENDED_POLICY
> PciPlatformExtendedPolicy;
> > > > > >
> > > > > > +  EFI_STATUS                        Status;
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  ZeroMem ( &PciPlatformExtendedPolicy, sizeof
> > > > > > (EFI_PCI_PLATFORM_EXTENDED_POLICY));
> > > > > >
> > > > > > +  Status = PciPlatformProtocol->GetDevicePolicy (
> > > > > >
> > > > > > +                                  PciPlatformProtocol,
> > > > > >
> > > > > > +                                  PciIoDevice->Handle,
> > > > > >
> > > > > > +                                  &PciPlatformExtendedPolicy
> > > > > >
> > > > > > +                                  );
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  // platform chipset policies are returned for this PCI device
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  if (!EFI_ERROR(Status)) {
> > > > > >
> > > > > > +    PciIoDevice->SetupMPS =
> PciPlatformExtendedPolicy.DeviceCtlMPS;
> > > > > >
> > > > > > +    PciIoDevice->SetupMRRS =
> > > PciPlatformExtendedPolicy.DeviceCtlMRRS;
> > > > > >
> > > > > > +  }
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  // platform chipset policies are not provided for this PCI device
> > > > > >
> > > > > > +  //
> > > > > >
> > > > > > +  if (EFI_ERROR(Status) == EFI_UNSUPPORTED) {
> > > > > >
> > > > > > +    //
> > > > > >
> > > > > > +    // let the enumeration happen as per the PCI standard way
> > > > > >
> > > > > > +    //
> > > > > >
> > > > > > +    SetupDefaultsDevicePlatformPolicy ( PciIoDevice);
> > > > > >
> > > > > > +    return EFI_SUCCESS;
> > > > > >
> > > > > > +  }
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  return Status;
> > > > > >
> > > > > > +}
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +/**
> > > > > >
> > > > > > +  Gets the PCI device-specific platform policy from the PCI Platform
> > > > > Protocol.
> > > > > >
> > > > > > +  If no PCI Platform protocol is published than setup the PCI feature
> to
> > > > > > predetermined
> > > > > >
> > > > > > +  defaults, in order to align all the PCI devices in the PCI hierarchy,
> as
> > > > > > applicable.
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @param  PciDevice     A pointer to PCI_IO_DEVICE
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @retval EFI_STATUS    The direct status from the PCI Platform
> > > Protocol
> > > > > >
> > > > > > +  @retval EFI_SUCCESS   On return of predetermined PCI features
> > > defaults,
> > > > > > for
> > > > > >
> > > > > > +                        the case when protocol returns as EFI_UNSUPPORTED
> to
> > > > > >
> > > > > > +                        indicate PCI device exist and it has no platform policy
> > > > > >
> > > > > > +                        defined. Also, on returns when no PCI Platform
> Protocol
> > > > > >
> > > > > > +                        exist.
> > > > > >
> > > > > > +**/
> > > > > >
> > > > > > +EFI_STATUS
> > > > > >
> > > > > > +GetPciDevicePlatformPolicy (
> > > > > >
> > > > > > +  IN PCI_IO_DEVICE          *PciDevice
> > > > > >
> > > > > > +  )
> > > > > >
> > > > > > +{
> > > > > >
> > > > > > +  if ( mPciPlatformProtocol2 != NULL) {
> > > > > >
> > > > > > +    return GetPciDevicePlatformPolicyEx ( PciDevice,
> > > > > mPciPlatformProtocol2);
> > > > > >
> > > > > > +  } else if (mPciOverrideProtocol2 != NULL) {
> > > > > >
> > > > > > +    return GetPciDevicePlatformPolicyEx ( PciDevice,
> > > > > mPciOverrideProtocol2);
> > > > > >
> > > > > > +  } else {
> > > > > >
> > > > > > +    //
> > > > > >
> > > > > > +    // new PCI Platform Protocol 2 is not installed; let the
> enumeration
> > > > > > happen
> > > > > >
> > > > > > +    // as per PCI standard way
> > > > > >
> > > > > > +    //
> > > > > >
> > > > > > +    SetupDefaultsDevicePlatformPolicy ( PciDevice);
> > > > > >
> > > > > > +    return EFI_SUCCESS;
> > > > > >
> > > > > > +  }
> > > > > >
> > > > > > +}
> > > > > >
> > > > > > diff --git
> a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
> > > > > > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
> > > > > > new file mode 100644
> > > > > > index 0000000000..d54e46b950
> > > > > > --- /dev/null
> > > > > > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
> > > > > > @@ -0,0 +1,193 @@
> > > > > > +/** @file
> > > > > >
> > > > > > +  This file encapsulate the usage of PCI Platform Protocol
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  This file define the necessary hooks used to obtain the platform
> > > > > >
> > > > > > +  level data and policies which could be used in the PCI
> Enumeration
> > > > > phases
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> > > > > >
> > > > > > +SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +**/
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +#ifndef _EFI_PCI_PLATFORM_SUPPORT_H_
> > > > > >
> > > > > > +#define _EFI_PCI_PLATFORM_SUPPORT_H_
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +#include "PciBus.h"
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +/**
> > > > > >
> > > > > > +  This function retrieves the PCI Platform Protocol published by
> > > platform
> > > > > > driver
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +**/
> > > > > >
> > > > > > +VOID
> > > > > >
> > > > > > +GetPciPlatformProtocol (
> > > > > >
> > > > > > +  );
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +/**
> > > > > >
> > > > > > +  This function indicates the presence of PCI Platform driver
> > > > > >
> > > > > > +  @retval     TRUE or FALSE
> > > > > >
> > > > > > +**/
> > > > > >
> > > > > > +BOOLEAN
> > > > > >
> > > > > > +CheckPciPlatformProtocolInstall (
> > > > > >
> > > > > > +  );
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +/**
> > > > > >
> > > > > > +  Provides the hooks from the PCI bus driver to every PCI controller
> > > > > > (device/function) at various
> > > > > >
> > > > > > +  stages of the PCI enumeration process that allow the host bridge
> > > driver
> > > > > to
> > > > > > preinitialize individual
> > > > > >
> > > > > > +  PCI controllers before enumeration.
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  This function is called during the PCI enumeration process. No
> specific
> > > > > > action is expected from this
> > > > > >
> > > > > > +  member function. It allows the host bridge driver to preinitialize
> > > > > individual
> > > > > > PCI controllers before
> > > > > >
> > > > > > +  enumeration.
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @param[in] HostBridgeHandle     The associated PCI host bridge
> > > handle.
> > > > > >
> > > > > > +  @param[in] RootBridgeHandle     The associated PCI root bridge
> > > handle.
> > > > > >
> > > > > > +  @param[in] RootBridgePciAddress The address of the PCI device
> on
> > > the
> > > > > > PCI bus.
> > > > > >
> > > > > > +  @param[in] Phase          The phase of the PCI controller
> enumeration.
> > > > > >
> > > > > > +  @param[in] ExecPhase      Defines the execution phase of the PCI
> > > chipset
> > > > > > driver.
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @retval    Status         returns the status from the PCI Platform
> > > protocol as
> > > > > is
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +**/
> > > > > >
> > > > > > +EFI_STATUS
> > > > > >
> > > > > > +PciPlatformPreprocessController (
> > > > > >
> > > > > > +  IN EFI_HANDLE                                    HostBridgeHandle,
> > > > > >
> > > > > > +  IN EFI_HANDLE                                    RootBridgeHandle,
> > > > > >
> > > > > > +  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS
> > > > > > RootBridgePciAddress,
> > > > > >
> > > > > > +  IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE
> Phase,
> > > > > >
> > > > > > +  IN EFI_PCI_EXECUTION_PHASE                       ExecPhase
> > > > > >
> > > > > > +  );
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +/**
> > > > > >
> > > > > > +  This function notifies the PCI Platform driver about the PCI host
> > > bridge
> > > > > > resource
> > > > > >
> > > > > > +  allocation phase and PCI execution phase.
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @param[in]  HostBridge     The handle of the host bridge
> controller.
> > > > > >
> > > > > > +  @param[in]  Phase          The phase of the PCI bus enumeration.
> > > > > >
> > > > > > +  @param[in]  ExecPhase      Defines the execution phase of the PCI
> > > > > chipset
> > > > > > driver.
> > > > > >
> > > > > > +  @retval     Status          returns the status from the PCI Platform
> > > protocol
> > > > > as
> > > > > > is
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +**/
> > > > > >
> > > > > > +EFI_STATUS
> > > > > >
> > > > > > +PciPlatformNotifyPhase (
> > > > > >
> > > > > > +  IN  EFI_HANDLE                                      HostBridgeHandle,
> > > > > >
> > > > > > +  IN  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE
> Phase,
> > > > > >
> > > > > > +  IN  EFI_PCI_EXECUTION_PHASE                         ExecPhase
> > > > > >
> > > > > > +  );
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +/**
> > > > > >
> > > > > > +  This function retrieves the PCI platform policy.
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @param  PciPolicy     pointer to the legacy
> > > EFI_PCI_PLATFORM_POLICY
> > > > > >
> > > > > > +  @retval Status        returns the status from the PCI Platform
> protocol
> > > as is
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +**/
> > > > > >
> > > > > > +EFI_STATUS
> > > > > >
> > > > > > +PciGetPlatformPolicy (
> > > > > >
> > > > > > +  OUT EFI_PCI_PLATFORM_POLICY *PciPolicy
> > > > > >
> > > > > > +  );
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +/**
> > > > > >
> > > > > > +  This function retrieves the Option ROM image and size from the
> > > Platform.
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  It uses the PCI_IO_DEVICE internal fields are used to store
> OpROM
> > > > > > image/size
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @param Controller     An EFI handle for the PCI bus controller.
> > > > > >
> > > > > > +  @param PciIoDevice    A PCI_IO_DEVICE pointer to the PCI IO
> device
> > > to
> > > > > be
> > > > > > registered.
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @retval EFI_SUCCESS            The option ROM was available for this
> > > device
> > > > > > and loaded into memory.
> > > > > >
> > > > > > +  @retval EFI_NOT_FOUND          No option ROM was available for
> this
> > > > > device.
> > > > > >
> > > > > > +  @retval EFI_OUT_OF_RESOURCES   No memory was available to
> load
> > > the
> > > > > > option ROM.
> > > > > >
> > > > > > +  @retval EFI_DEVICE_ERROR       An error occurred in obtaining the
> > > option
> > > > > > ROM.
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +**/
> > > > > >
> > > > > > +EFI_STATUS
> > > > > >
> > > > > > +GetPlatformPciOptionRom (
> > > > > >
> > > > > > +  IN  EFI_HANDLE                    Controller,
> > > > > >
> > > > > > +  IN  PCI_IO_DEVICE                 *PciIoDevice
> > > > > >
> > > > > > +  );
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +/**
> > > > > >
> > > > > > +  Gets the PCI device-specific platform policy from the PCI Platform
> > > > > Protocol.
> > > > > >
> > > > > > +  If no PCI Platform protocol is published than setup the PCI feature
> to
> > > > > > predetermined
> > > > > >
> > > > > > +  defaults, in order to align all the PCI devices in the PCI hierarchy,
> as
> > > > > > applicable.
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @param  PciDevice     A pointer to PCI_IO_DEVICE
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @retval EFI_STATUS    The direct status from the PCI Platform
> > > Protocol
> > > > > >
> > > > > > +  @retval EFI_SUCCESS   On return of predetermined PCI features
> > > defaults,
> > > > > > for
> > > > > >
> > > > > > +                        the case when protocol returns as EFI_UNSUPPORTED
> to
> > > > > >
> > > > > > +                        indicate PCI device exist and it has no platform policy
> > > > > >
> > > > > > +                        defined. Also, on returns when no PCI Platform
> Protocol
> > > > > >
> > > > > > +                        exist.
> > > > > >
> > > > > > +**/
> > > > > >
> > > > > > +EFI_STATUS
> > > > > >
> > > > > > +GetPciDevicePlatformPolicy (
> > > > > >
> > > > > > +  IN PCI_IO_DEVICE          *PciDevice
> > > > > >
> > > > > > +  );
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +/**
> > > > > >
> > > > > > +  Helper routine to indicate whether the given PCI device specific
> > > policy
> > > > > > value
> > > > > >
> > > > > > +  dictates to override the Max_Payload_Size to a particular value,
> or
> > > set as
> > > > > > per
> > > > > >
> > > > > > +  device capability.
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @param  MPS     Input device-specific policy should be in terms of
> > > type
> > > > > >
> > > > > > +                  EFI_PCI_CONF_MAX_PAYLOAD_SIZE
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @retval TRUE    Setup Max_Payload_Size as per device capability
> > > > > >
> > > > > > +          FALSE   override as per device-specific platform policy
> > > > > >
> > > > > > +**/
> > > > > >
> > > > > > +BOOLEAN
> > > > > >
> > > > > > +SetupMpsAsPerDeviceCapability (
> > > > > >
> > > > > > +  IN  UINT8                   MPS
> > > > > >
> > > > > > +);
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +/**
> > > > > >
> > > > > > +  Helper routine to indicate whether the given PCI device specific
> > > policy
> > > > > > value
> > > > > >
> > > > > > +  dictates to override the Max_Read_Req_Size to a particular value,
> or
> > > set
> > > > > as
> > > > > > per
> > > > > >
> > > > > > +  device capability.
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @param  MRRS    Input device-specific policy should be in terms
> of
> > > type
> > > > > >
> > > > > > +                  EFI_PCI_CONF_MAX_READ_REQ_SIZE
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @retval TRUE    Setup Max_Read_Req_Size as per device
> capability
> > > > > >
> > > > > > +          FALSE   override as per device-specific platform policy
> > > > > >
> > > > > > +**/
> > > > > >
> > > > > > +BOOLEAN
> > > > > >
> > > > > > +SetupMrrsAsPerDeviceCapability (
> > > > > >
> > > > > > +  IN  UINT8                   MRRS
> > > > > >
> > > > > > +);
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +/**
> > > > > >
> > > > > > +  Routine to translate the given device-specific platform policy from
> > > type
> > > > > >
> > > > > > +  EFI_PCI_CONF_MAX_PAYLOAD_SIZE to HW-specific value, as per
> PCI
> > > > > Base
> > > > > > Specification
> > > > > >
> > > > > > +  Revision 4.0; for the PCI feature Max_Payload_Size.
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @param  MPS     Input device-specific policy should be in terms of
> > > type
> > > > > >
> > > > > > +                  EFI_PCI_CONF_MAX_PAYLOAD_SIZE
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @retval         Range values for the Max_Payload_Size as defined in
> the
> > > > > PCI
> > > > > >
> > > > > > +                  Base Specification 4.0
> > > > > >
> > > > > > +**/
> > > > > >
> > > > > > +UINT8
> > > > > >
> > > > > > +TranslateMpsSetupValueToPci (
> > > > > >
> > > > > > +  IN  UINT8                   MPS
> > > > > >
> > > > > > +);
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +/**
> > > > > >
> > > > > > +  Routine to translate the given device-specific platform policy from
> > > type
> > > > > >
> > > > > > +  EFI_PCI_CONF_MAX_READ_REQ_SIZE to HW-specific value, as
> per
> > > PCI
> > > > > > Base Specification
> > > > > >
> > > > > > +  Revision 4.0; for the PCI feature Max_Read_Req_Size.
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @param  MRRS    Input device-specific policy should be in terms
> of
> > > type
> > > > > >
> > > > > > +                  EFI_PCI_CONF_MAX_READ_REQ_SIZE
> > > > > >
> > > > > > +
> > > > > >
> > > > > > +  @retval         Range values for the Max_Read_Req_Size as defined
> in
> > > the
> > > > > > PCI
> > > > > >
> > > > > > +                  Base Specification 4.0
> > > > > >
> > > > > > +**/
> > > > > >
> > > > > > +UINT8
> > > > > >
> > > > > > +TranslateMrrsSetupValueToPci (
> > > > > >
> > > > > > +  IN  UINT8                   MRRS
> > > > > >
> > > > > > +);
> > > > > >
> > > > > > +#endif
> > > > > >
> > > > > > diff --git
> a/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c
> > > > > > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c
> > > > > > index 4969ee0f64..755423f77b 100644
> > > > > > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c
> > > > > > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c
> > > > > > @@ -198,20 +198,7 @@ CalculateApertureIo16 (
> > > > > >      //
> > > > > >
> > > > > >      Status = EFI_NOT_FOUND;
> > > > > >
> > > > > >      PciPolicy = 0;
> > > > > >
> > > > > > -    if (gPciPlatformProtocol != NULL) {
> > > > > >
> > > > > > -      Status = gPciPlatformProtocol->GetPlatformPolicy (
> > > > > >
> > > > > > -                                       gPciPlatformProtocol,
> > > > > >
> > > > > > -                                       &PciPolicy
> > > > > >
> > > > > > -                                       );
> > > > > >
> > > > > > -    }
> > > > > >
> > > > > > -
> > > > > >
> > > > > > -    if (EFI_ERROR (Status) && gPciOverrideProtocol != NULL) {
> > > > > >
> > > > > > -      Status = gPciOverrideProtocol->GetPlatformPolicy (
> > > > > >
> > > > > > -                                       gPciOverrideProtocol,
> > > > > >
> > > > > > -                                       &PciPolicy
> > > > > >
> > > > > > -                                       );
> > > > > >
> > > > > > -    }
> > > > > >
> > > > > > -
> > > > > >
> > > > > > +    Status = PciGetPlatformPolicy ( &PciPolicy);
> > > > > >
> > > > > >      if (!EFI_ERROR (Status)) {
> > > > > >
> > > > > >        if ((PciPolicy & EFI_RESERVE_ISA_IO_ALIAS) != 0) {
> > > > > >
> > > > > >          mReserveIsaAliases = TRUE;
> > > > > >
> > > > > > diff --git a/MdeModulePkg/MdeModulePkg.dec
> > > > > > b/MdeModulePkg/MdeModulePkg.dec
> > > > > > index 17beb45235..7bcbe5a3ea 100644
> > > > > > --- a/MdeModulePkg/MdeModulePkg.dec
> > > > > > +++ b/MdeModulePkg/MdeModulePkg.dec
> > > > > > @@ -1026,6 +1026,16 @@
> > > > > >    # @Prompt Enable UEFI Stack Guard.
> > > > > >
> > > > > >
> > > > > >
> > > > >
> > >
> gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard|FALSE|BOOLEAN|0
> > > > > > x30001055
> > > > > >
> > > > > >
> > > > > >
> > > > > > +  ## This PCD is to indicate the PCI Bus driver to setup other new
> PCI
> > > > > > features.
> > > > > >
> > > > > > +  #  Each PCI feature is represented by its mask bit position and it
> > > > > configures
> > > > > >
> > > > > > +  #  if that bit is set.
> > > > > >
> > > > > > +  #
> > > > > >
> > > > > > +  #   Bit 0 - if set, the PCI Bus driver programs the device's
> > > > > > Max_Payload_Size.<BR>
> > > > > >
> > > > > > +  #   Bit 1 - if set, the PCI Bus driver programs the device's
> > > > > > Max_Read_Req_Size.<BR>
> > > > > >
> > > > > > +  #   Bit 2 to 31 - Reserved for future use by the PCI Bus driver.<BR>
> > > > > >
> > > > > > +  # @Prompt The UEFI PCU Bus driver enables the new set of other
> PCI
> > > > > > Features.
> > > > > >
> > > > > > +
> > > > > >
> > > > >
> > >
> gEfiMdeModulePkgTokenSpaceGuid.PcdOtherPciFeatures|0x00000003|UIN
> > > > > > T32|0x30001056
> > > > > >
> > > > > > +
> > > > > >
> > > > > >  [PcdsFixedAtBuild, PcdsPatchableInModule]
> > > > > >
> > > > > >    ## Dynamic type PCD can be registered callback function for Pcd
> > > setting
> > > > > > action.
> > > > > >
> > > > > >    #  PcdMaxPeiPcdCallBackNumberPerPcdEntry indicates the
> maximum
> > > > > > number of callback function
> > > > > >
> > > > > > --
> > > > > > 2.21.0.windows.1


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

View/Reply Online (#48994): https://edk2.groups.io/g/devel/message/48994
Mute This Topic: https://groups.io/mt/34264504/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub  [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-

Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH] PciBusDxe: New PCI features Max_Payload_Size, Max_Read_Req_Size
Posted by Javeed, Ashraf 4 years, 5 months ago

> -----Original Message-----
> From: Ni, Ray <ray.ni@intel.com>
> Sent: Tuesday, October 15, 2019 3:19 PM
> To: Javeed, Ashraf <ashraf.javeed@intel.com>; 'devel@edk2.groups.io'
> <devel@edk2.groups.io>
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>
> Subject: RE: [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH] PciBusDxe: New PCI
> features Max_Payload_Size, Max_Read_Req_Size
> 
> > > > > 1. IsPciRootPortEmpty(): can you just check whether PciDevice-
> > >ChildList is
> > > > > empty by using IsListEmpty (&PciDevice->ChildList)?
> > > > OK, will do the additional check.
> > >
> > > Can that be the only check?
> > It cannot be the only check when I am parsing the list as it is going to loop
> > over; or may be where exactly you want to have this check? I understand it
> > can be the first check before traversing the list.
> 
> My idea is:
>   BOOLEAN
>   IsPciRootPortEmpty(PciIoDevice) {
>     Return IsListEmpty (&PciIoDevice->ChildLIst);
>   }
> 
OK, got it, will do. Thanks!

> >
> > >
> > > >
> > > > > 2. Can you point to me which spec requires the MPS to be 128 for
> > empty
> > > > root
> > > > > ports?
> > > > Refer the PCI Express Base Specification Revision 5, chapter 7.5.3.4
> > > > Implementation Notes section.
> > > Can you please paste the specific wording that supports the logic to
> > program
> > > MPS to 128B for empty root ports?
> > > Below wording seems to require 128B only for special OSes that don't
> > support
> > > PCIE.
> > > " For example, if the operating system environment does not comprehend
> > PCI
> > > Express, firmware probably should
> > > not program a non-default Max_Payload_Size for a hierarchy that supports
> > Hot-
> > > Plug operations"
> > Yes; since the PCI Bus driver does not know what OS it is going to boot to, it
> > has to assume for the worst and set it to default, or leave it to default as the
> > HW default is set to 128B. Besides, the Max_Payload_Size is for the Data
> > Packet size,  since the PCI RP is empty there is no point changing to any other
> > value as there won't be any PCI transactions.
> 
> Agree.
> 
> >
> > >
> > > >
> > > > > 3. GetPciRootPortBusAssigned() is dangerous because it assumes the
> > input
> > > > > PciDevice points to the bridge.
> > > > Good catch! Will make the right change.
> > >
> > > As we discussed over phone, using device path can eliminate the needs of
> > > comparing bus number. Then this function is not needed.
> > Yes, I am looking towards that direction.
> 
> Thanks.
> 
> >
> > >
> > > >
> > > > > 4. RecordPciRootPortBridges() could be simplified to just collect all
> > > > PciDevice
> > > > > instances who:
> > > > >     a. belongs to the linked list of the root bridge
> > > > >     b. is a bridge
> > > > I can see if I can optimize further, but do note that I need to align the PCI
> > > > feature Max_Payload_Size and Max_Read_Request_Size among all the
> > child
> > > > PCI devices of the Root Port (RP) in the Root Complex (RC) and since a
> > single
> > > > RC is known to have multiple RP I need to maintain the list of all the
> > primary
> > > > RP in the Root Bridge handle so that each primary RP can have its PCI
> > > > configuration table to track the Max_Payload_Size and
> > > > Max_Read_Request_Size that needs to be assigned to all its child PCI
> > devices
> > > > in the tree.
> > >
> > > I am not suggesting to stop collecting all root ports.
> > > Can you simplify the logic of RecordPciRootPortBridges() as below?
> > >   for each node in PciRootBridge.ChildList:
> > >     if (!IsListEmpty (node.ChildList)) {
> > >       RootPortList.add (node)
> > OK, will do.
> 
> Thanks.
> 
> >
> > >
> > > > > > 2. GetPciPlatformProtocol(): better to rename to InitializePciPlatform
> > ().
> > > > To me, the word "Initialize" would mean also installing the PCI Platform
> > > > Protocol which is not the case with the PCI Bus driver; since it only fetches
> > > > the existing protocol already installed by the platform...
> > > I agree with your concern : )
> > > But "Get" means to return the PciPlatform protocol back through function
> > return
> > > result.
> > > How about "Locate"?
> > Ok, will use this key word.
> 
> Thanks.
> 
> >
> > >
> > > >
> > > > > > 3. Why the type cast is needed in below code? If it is because
> > > > PciPlatform2
> > > > > > protocol reuses the prototype of GetPciRom defined for PciPlatform
> > > > protocol,
> > > > > > I suggest you define GetPciRom for PciPlatform2. Type redefinition
> > > > seems a
> > > > > > duplication. But below type-cast is more annoyed.
> > > > > >
> > > > > >     Status = mPciPlatformProtocol2->GetPciRom (
> > > > > >
> > > > > (EFI_PCI_PLATFORM_PROTOCOL*)mPciPlatformProtocol2,
> > > > > >                                       PciIoDevice->Handle,
> > > > > >                                       &PlatformOpRomBuffer,
> > > > > >                                       &PlatformOpRomSize
> > > > > >                                       );
> > > > > >
> > > > Yes, the PciPlatform2.h which I had submitted to the edk2-staging branch
> > > > previously; includes the PciPlatform.h during compilation. Even I was
> > thinking
> > > > the same and since the new definition of the PCI Platform Protocol has to
> > > > used in future; I can port the legacy definitions into the new definition
> > source
> > > > file itself to avoid further change in future.
> > >
> > > Thanks.
> > >
> > > >
> > > > > > 4. Please run ECC tool and fix all coding style issue
> > > > I thought the ECC tool is used once the changes are submitted into the
> > > > Gerritt by the maintainer; it is good if I can use it offline; please let me
> > know
> > > > where to get this tool.
> > >
> > > The tool is inside BaseTools\BinWrappers\WindowsLike\Ecc.bat.
> > Thanks! Will use this. By the way; I did make the code changes by referring
> > the "EDK-II C Coding Style Standards Specification".
> 
> I saw several coding style issues so I asked you to run the tool.
> e.g.:
> 1. "if (!Pointer)" should be "if (Pointer != NULL)"
I agree with this; since it was defined in many other places I thought this is the standard here. I shall make the suggested changes to my new code added.

> 2. "Function ( parameter);" should be "Function (parameter);" // no space before
> 1st parameter
OK, will adopt to this. I had done as per the Server platform firmware style as I understand.
 
> 3. "if (...) <\n> {" should be "if (...) {" // no new-line before "{"
OK, will fix this, along with the ECC tool requirements.

> 
> 
> >
> > >
> > > >
> > > > > > 5. I don't quite understand what *primary* PCI root port is. So I don't
> > > > quite
> > > > > > understand what RecordPciRootPortBridges() does.
> > > > I used the word primary for the PCI Root port to indicate the first level
> > Root
> > > > port in the RC of the host; there can be multiple first level PCI RP in the
> > Root
> > > > Bridge handle and each RP can have its downstream hierarchy which in
> > turn
> > > > can be the PCIe-PCIe/PCI/PCI-X bridge devices and its endpoint devices.
> > > > Since the RP and its downstream PCI bridges both have the same PCI
> > Type 1
> > > > PCI Configuration header, I have to maintain the list of first level RP of the
> > > > Root Bridge handle.
> > > >
> > > > > >
> > > > > > Thanks,
> > > > > > Ray
> > > > > >
> > > > > > > -----Original Message-----
> > > > > > > From: Javeed, Ashraf <ashraf.javeed@intel.com>
> > > > > > > Sent: Monday, September 23, 2019 10:21 PM
> > > > > > > To: devel@edk2.groups.io
> > > > > > > Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A
> > > > > > <hao.a.wu@intel.com>;
> > > > > > > Ni, Ray <ray.ni@intel.com>
> > > > > > > Subject: [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH] PciBusDxe:
> > New
> > > > PCI
> > > > > > > features Max_Payload_Size, Max_Read_Req_Size
> > > > > > >
> > > > > > > REF: https://bugzilla.tianocore.org/show_bug.cgi?id=2194
> > > > > > >
> > > > > > > The EDK2 Kernel PciBusDxe driver is enhanced to enable the
> > > > configuration
> > > > > > > of PCI features like Max_Payload_Size and Max_Read_Req_Size.
> > > > > > >
> > > > > > > Max_Payload_Size:- The PCI Device Control register provides this
> > > > feature
> > > > > > > register field which controls the maximum data packet (TLP) size
> > that a
> > > > > > > PCI device should maintain as a requester. The PCI Bus driver is
> > > > required
> > > > > > > to maintain a highest common value supported by all the PCI
> > devices in
> > > > a
> > > > > > > PCIe hierarchy, especially in case of isochronous applications.
> > > > > > >
> > > > > > > Max_Read_Req_Size:- The PCI Device Control register provides this
> > > > > > feature
> > > > > > > register field which controls the maximum memory read request
> > size
> > > > that a
> > > > > > > PCI device should maintain as a requester. The PCI Bus driver is
> > > > required
> > > > > > > to maintain a common value, same as Max_Payload_Size, in case of
> > > > > > > isochronous applications only; or else, it should maintain the user
> > > > > > > requested value uniformly in a PCIe hierarchy (PCI root port and its
> > > > > > > downstream devices).
> > > > > > >
> > > > > > > The PCI Base Specification 4 Revision 1 contains detailed information
> > > > > > > about these features. The EDK2 PCI Bus driver needs to enable the
> > > > > > > configuration of these features as per the PCI Base specification.
> > > > > > >
> > > > > > > The EDK2 PCI Bus driver also needs to take the PCI device-specific
> > > > > > > platform policy into the consideration while programming these
> > > > features;
> > > > > > > thus the code changes to support these, is explicitly dependent on
> > the
> > > > > > > new PCI Platform Protocol interface definition defined in the below
> > > > > > > record:-
> > > > > > > https://bugzilla.tianocore.org/show_bug.cgi?id=1954
> > > > > > >
> > > > > > > Signed-off-by: Ashraf Javeed <ashraf.javeed@intel.com>
> > > > > > > Cc: Jian J Wang <jian.j.wang@intel.com>
> > > > > > > Cc: Hao A Wu <hao.a.wu@intel.com>
> > > > > > > Cc: Ray Ni <ray.ni@intel.com>
> > > > > > > ---
> > > > > > >  MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c               |   23 ++--------
> > ----
> > > > > > >  MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h               |   14
> > ++++++++-
> > > > > > >  MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf          |    9 +++++-
> > > > > > >  MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c     |  229
> > > > > > >
> > > > > >
> > > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > > > > ++++++++++++++++++++++++++++--------------------------------------
> > ----
> > > > -----
> > > > > > -
> > > > > > >  MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c        |  139
> > > > > > > ++++++++++++++++++++---------------------------------------------------
> > ----
> > > > ----
> > > > > > ---
> > > > > > >  MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c |   34
> > > > > > > ++++++++++++--------
> > > > > > >  MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c    | 1601
> > > > > > >
> > > > > >
> > > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > > > >
> > > > > >
> > > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > > > >
> > > > > >
> > > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > > > >
> > > > > >
> > > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > > > >
> > > > > >
> > > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > > > >
> > > > > >
> > > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > > > >
> > > > > >
> > > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > > > >
> > > > > >
> > > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > > > >
> > > > > >
> > > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > > > >
> > > > > >
> > > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > > > >
> > > > > >
> > > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > > > >
> > > > > >
> > > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > > > >
> > > > > >
> > > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > > > >
> > > > > >
> > > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > > > >
> > > > > >
> > > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > > > >
> > > > > >
> > > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > > > > +++++++++
> > > > > > >  MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h    |  201
> > > > > > >
> > > > > >
> > > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > > > >
> > > > > >
> > > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > > > > ++
> > > > > > >  MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c   |  565
> > > > > > >
> > > > > >
> > > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > > > >
> > > > > >
> > > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > > > >
> > > > > >
> > > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > > > >
> > > > > >
> > > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > > > >
> > > > > >
> > > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > > > > +++++++++++++++++++++++++++++++++++++++++
> > > > > > >  MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h   |  193
> > > > > > >
> > > > > >
> > > >
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > > > >
> > > > +++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > > > > >  MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c   |   15
> > +-----
> > > > ---
> > > > > > >  MdeModulePkg/MdeModulePkg.dec                         |   10 ++++++
> > > > > > >  12 files changed, 2797 insertions(+), 236 deletions(-)
> > > > > > >
> > > > > > > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c
> > > > > > > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c
> > > > > > > index b020ce50ce..2503b298f4 100644
> > > > > > > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c
> > > > > > > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c
> > > > > > > @@ -8,7 +8,7 @@
> > > > > > >    PCI Root Bridges. So it means platform needs install PCI Root
> > Bridge IO
> > > > > > > protocol for each
> > > > > > >
> > > > > > >    PCI Root Bus and install PCI Host Bridge Resource Allocation
> > Protocol.
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > > -Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
> > > > > > >
> > > > > > > +Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
> > > > > > >
> > > > > > >  SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > >  **/
> > > > > > >
> > > > > > > @@ -34,8 +34,6 @@ BOOLEAN
> gFullEnumeration
> > > =
> > > > > > TRUE;
> > > > > > >  UINT64                                        gAllOne              =
> > 0xFFFFFFFFFFFFFFFFULL;
> > > > > > >
> > > > > > >  UINT64                                        gAllZero             = 0;
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > > -EFI_PCI_PLATFORM_PROTOCOL                     *gPciPlatformProtocol;
> > > > > > >
> > > > > > > -EFI_PCI_OVERRIDE_PROTOCOL                     *gPciOverrideProtocol;
> > > > > > >
> > > > > > >  EDKII_IOMMU_PROTOCOL                          *mIoMmuProtocol;
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > > @@ -266,24 +264,7 @@ PciBusDriverBindingStart (
> > > > > > >    // If PCI Platform protocol is available, get it now.
> > > > > > >
> > > > > > >    // If the platform implements this, it must be installed before BDS
> > > > phase
> > > > > > >
> > > > > > >    //
> > > > > > >
> > > > > > > -  gPciPlatformProtocol = NULL;
> > > > > > >
> > > > > > > -  gBS->LocateProtocol (
> > > > > > >
> > > > > > > -        &gEfiPciPlatformProtocolGuid,
> > > > > > >
> > > > > > > -        NULL,
> > > > > > >
> > > > > > > -        (VOID **) &gPciPlatformProtocol
> > > > > > >
> > > > > > > -        );
> > > > > > >
> > > > > > > -
> > > > > > >
> > > > > > > -  //
> > > > > > >
> > > > > > > -  // If PCI Platform protocol doesn't exist, try to Pci Override
> > Protocol.
> > > > > > >
> > > > > > > -  //
> > > > > > >
> > > > > > > -  if (gPciPlatformProtocol == NULL) {
> > > > > > >
> > > > > > > -    gPciOverrideProtocol = NULL;
> > > > > > >
> > > > > > > -    gBS->LocateProtocol (
> > > > > > >
> > > > > > > -          &gEfiPciOverrideProtocolGuid,
> > > > > > >
> > > > > > > -          NULL,
> > > > > > >
> > > > > > > -          (VOID **) &gPciOverrideProtocol
> > > > > > >
> > > > > > > -          );
> > > > > > >
> > > > > > > -  }
> > > > > > >
> > > > > > > +  GetPciPlatformProtocol ();
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > >    if (mIoMmuProtocol == NULL) {
> > > > > > >
> > > > > > >      gBS->LocateProtocol (
> > > > > > >
> > > > > > > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> > > > > > > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> > > > > > > index 504a1b1c12..7955bf8a26 100644
> > > > > > > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> > > > > > > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> > > > > > > @@ -27,6 +27,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > > > >  #include <Protocol/PciOverride.h>
> > > > > > >
> > > > > > >  #include <Protocol/PciEnumerationComplete.h>
> > > > > > >
> > > > > > >  #include <Protocol/IoMmu.h>
> > > > > > >
> > > > > > > +#include <Protocol/PciPlatform2.h>
> > > > > > >
> > > > > > > +#include <Protocol/PciOverride2.h>
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > >  #include <Library/DebugLib.h>
> > > > > > >
> > > > > > >  #include <Library/UefiDriverEntryPoint.h>
> > > > > > >
> > > > > > > @@ -79,6 +81,7 @@ typedef enum {
> > > > > > >  #include "PciPowerManagement.h"
> > > > > > >
> > > > > > >  #include "PciHotPlugSupport.h"
> > > > > > >
> > > > > > >  #include "PciLib.h"
> > > > > > >
> > > > > > > +#include "PciFeatureSupport.h"
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > >  #define VGABASE1  0x3B0
> > > > > > >
> > > > > > >  #define VGALIMIT1 0x3BB
> > > > > > >
> > > > > > > @@ -263,9 +266,13 @@ struct _PCI_IO_DEVICE {
> > > > > > >
> > > > > > >
> > > > > > >    BOOLEAN                                   IsPciExp;
> > > > > > >
> > > > > > >    //
> > > > > > >
> > > > > > > -  // For SR-IOV
> > > > > > >
> > > > > > > +  // For PCI Express Capability List Structure
> > > > > > >
> > > > > > >    //
> > > > > > >
> > > > > > >    UINT8                                     PciExpressCapabilityOffset;
> > > > > > >
> > > > > > > +  PCI_CAPABILITY_PCIEXP                     PciExpStruct;
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  // For SR-IOV
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > >    UINT32                                    AriCapabilityOffset;
> > > > > > >
> > > > > > >    UINT32                                    SrIovCapabilityOffset;
> > > > > > >
> > > > > > >    UINT32                                    MrIovCapabilityOffset;
> > > > > > >
> > > > > > > @@ -279,6 +286,11 @@ struct _PCI_IO_DEVICE {
> > > > > > >    // This field is used to support this case.
> > > > > > >
> > > > > > >    //
> > > > > > >
> > > > > > >    UINT16                                    BridgeIoAlignment;
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  // Other PCI features setup flags
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  UINT8                                     SetupMPS;
> > > > > > >
> > > > > > > +  UINT8                                     SetupMRRS;
> > > > > > >
> > > > > > >  };
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > >  #define PCI_IO_DEVICE_FROM_PCI_IO_THIS(a) \
> > > > > > >
> > > > > > > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
> > > > > > > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
> > > > > > > index 05c22025b8..13768d7ded 100644
> > > > > > > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
> > > > > > > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
> > > > > > > @@ -2,7 +2,7 @@
> > > > > > >  #  The PCI bus driver will probe all PCI devices and allocate MMIO
> > and
> > > > IO
> > > > > > > space for these devices.
> > > > > > >
> > > > > > >  #  Please use PCD feature flag PcdPciBusHotplugDeviceSupport to
> > > > enable
> > > > > > > hot plug supporting.
> > > > > > >
> > > > > > >  #
> > > > > > >
> > > > > > > -#  Copyright (c) 2006 - 2018, Intel Corporation. All rights
> > reserved.<BR>
> > > > > > >
> > > > > > > +#  Copyright (c) 2006 - 2019, Intel Corporation. All rights
> > reserved.<BR>
> > > > > > >
> > > > > > >  #
> > > > > > >
> > > > > > >  #  SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > > > >
> > > > > > >  #
> > > > > > >
> > > > > > > @@ -57,6 +57,10 @@
> > > > > > >    PciCommand.h
> > > > > > >
> > > > > > >    PciIo.h
> > > > > > >
> > > > > > >    PciBus.h
> > > > > > >
> > > > > > > +  PciFeatureSupport.c
> > > > > > >
> > > > > > > +  PciFeatureSupport.h
> > > > > > >
> > > > > > > +  PciPlatformSupport.c
> > > > > > >
> > > > > > > +  PciPlatformSupport.h
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > >  [Packages]
> > > > > > >
> > > > > > >    MdePkg/MdePkg.dec
> > > > > > >
> > > > > > > @@ -91,6 +95,8 @@
> > > > > > >    gEfiLoadFile2ProtocolGuid                       ## SOMETIMES_PRODUCES
> > > > > > >
> > > > > > >    gEdkiiIoMmuProtocolGuid                         ##
> > SOMETIMES_CONSUMES
> > > > > > >
> > > > > > >    gEfiLoadedImageDevicePathProtocolGuid           ## CONSUMES
> > > > > > >
> > > > > > > +  gEfiPciPlatformProtocol2Guid                     ##
> > SOMETIMES_CONSUMES
> > > > > > >
> > > > > > > +  gEfiPciOverrideProtocol2Guid                     ##
> > SOMETIMES_CONSUMES
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > >  [FeaturePcd]
> > > > > > >
> > > > > > >
> > gEfiMdeModulePkgTokenSpaceGuid.PcdPciBusHotplugDeviceSupport
> > > > > > ##
> > > > > > > CONSUMES
> > > > > > >
> > > > > > > @@ -104,6 +110,7 @@
> > > > > > >    gEfiMdeModulePkgTokenSpaceGuid.PcdAriSupport                  ##
> > > > > > CONSUMES
> > > > > > >
> > > > > > >    gEfiMdeModulePkgTokenSpaceGuid.PcdMrIovSupport                ##
> > > > > > > CONSUMES
> > > > > > >
> > > > > > >
> > gEfiMdeModulePkgTokenSpaceGuid.PcdPciDisableBusEnumeration
> > > > ##
> > > > > > > SOMETIMES_CONSUMES
> > > > > > >
> > > > > > > +  gEfiMdeModulePkgTokenSpaceGuid.PcdOtherPciFeatures
> > > > ##
> > > > > > > CONSUMES
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > >  [UserExtensions.TianoCore."ExtraFiles"]
> > > > > > >
> > > > > > >    PciBusDxeExtra.uni
> > > > > > >
> > > > > > > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
> > > > > > > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
> > > > > > > index b7832c6970..0f76ab1cd5 100644
> > > > > > > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
> > > > > > > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
> > > > > > > @@ -170,6 +170,8 @@ DestroyRootBridgeByHandle (
> > > > > > >
> > > > > > >
> > > > > > >      if (Temp->Handle == Controller) {
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > > +      DestroyRootBridgePciFeaturesConfigCompletionList ( Temp);
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > >        RemoveEntryList (CurrentLink);
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > >        DestroyPciDeviceTree (Temp);
> > > > > > >
> > > > > > > @@ -208,8 +210,6 @@ RegisterPciDevice (
> > > > > > >    )
> > > > > > >
> > > > > > >  {
> > > > > > >
> > > > > > >    EFI_STATUS          Status;
> > > > > > >
> > > > > > > -  VOID                *PlatformOpRomBuffer;
> > > > > > >
> > > > > > > -  UINTN               PlatformOpRomSize;
> > > > > > >
> > > > > > >    EFI_PCI_IO_PROTOCOL *PciIo;
> > > > > > >
> > > > > > >    UINT8               Data8;
> > > > > > >
> > > > > > >    BOOLEAN             HasEfiImage;
> > > > > > >
> > > > > > > @@ -244,49 +244,13 @@ RegisterPciDevice (
> > > > > > >      //
> > > > > > >
> > > > > > >      // Get the OpRom provided by platform
> > > > > > >
> > > > > > >      //
> > > > > > >
> > > > > > > -    if (gPciPlatformProtocol != NULL) {
> > > > > > >
> > > > > > > -      Status = gPciPlatformProtocol->GetPciRom (
> > > > > > >
> > > > > > > -                                       gPciPlatformProtocol,
> > > > > > >
> > > > > > > -                                       PciIoDevice->Handle,
> > > > > > >
> > > > > > > -                                       &PlatformOpRomBuffer,
> > > > > > >
> > > > > > > -                                       &PlatformOpRomSize
> > > > > > >
> > > > > > > -                                       );
> > > > > > >
> > > > > > > -      if (!EFI_ERROR (Status)) {
> > > > > > >
> > > > > > > -        PciIoDevice->EmbeddedRom    = FALSE;
> > > > > > >
> > > > > > > -        PciIoDevice->RomSize        = (UINT32) PlatformOpRomSize;
> > > > > > >
> > > > > > > -        PciIoDevice->PciIo.RomSize  = PlatformOpRomSize;
> > > > > > >
> > > > > > > -        PciIoDevice->PciIo.RomImage = PlatformOpRomBuffer;
> > > > > > >
> > > > > > > -        //
> > > > > > >
> > > > > > > -        // For OpROM read from gPciPlatformProtocol:
> > > > > > >
> > > > > > > -        // Add the Rom Image to internal database for later PCI light
> > > > > > > enumeration
> > > > > > >
> > > > > > > -        //
> > > > > > >
> > > > > > > -        PciRomAddImageMapping (
> > > > > > >
> > > > > > > -          NULL,
> > > > > > >
> > > > > > > -          PciIoDevice->PciRootBridgeIo->SegmentNumber,
> > > > > > >
> > > > > > > -          PciIoDevice->BusNumber,
> > > > > > >
> > > > > > > -          PciIoDevice->DeviceNumber,
> > > > > > >
> > > > > > > -          PciIoDevice->FunctionNumber,
> > > > > > >
> > > > > > > -          PciIoDevice->PciIo.RomImage,
> > > > > > >
> > > > > > > -          PciIoDevice->PciIo.RomSize
> > > > > > >
> > > > > > > -          );
> > > > > > >
> > > > > > > -      }
> > > > > > >
> > > > > > > -    } else if (gPciOverrideProtocol != NULL) {
> > > > > > >
> > > > > > > -      Status = gPciOverrideProtocol->GetPciRom (
> > > > > > >
> > > > > > > -                                       gPciOverrideProtocol,
> > > > > > >
> > > > > > > -                                       PciIoDevice->Handle,
> > > > > > >
> > > > > > > -                                       &PlatformOpRomBuffer,
> > > > > > >
> > > > > > > -                                       &PlatformOpRomSize
> > > > > > >
> > > > > > > -                                       );
> > > > > > >
> > > > > > > -      if (!EFI_ERROR (Status)) {
> > > > > > >
> > > > > > > -        PciIoDevice->EmbeddedRom    = FALSE;
> > > > > > >
> > > > > > > -        PciIoDevice->RomSize        = (UINT32) PlatformOpRomSize;
> > > > > > >
> > > > > > > -        PciIoDevice->PciIo.RomSize  = PlatformOpRomSize;
> > > > > > >
> > > > > > > -        PciIoDevice->PciIo.RomImage = PlatformOpRomBuffer;
> > > > > > >
> > > > > > > -        //
> > > > > > >
> > > > > > > -        // For OpROM read from gPciOverrideProtocol:
> > > > > > >
> > > > > > > -        // Add the Rom Image to internal database for later PCI light
> > > > > > > enumeration
> > > > > > >
> > > > > > > -        //
> > > > > > >
> > > > > > > -        PciRomAddImageMapping (
> > > > > > >
> > > > > > > +    Status = GetPlatformPciOptionRom ( Controller, PciIoDevice);
> > > > > > >
> > > > > > > +    if (!EFI_ERROR (Status)) {
> > > > > > >
> > > > > > > +      //
> > > > > > >
> > > > > > > +      // For OpROM read from the PCI Platform Protocol:
> > > > > > >
> > > > > > > +      // Add the Rom Image to internal database for later PCI light
> > > > > > > enumeration
> > > > > > >
> > > > > > > +      //
> > > > > > >
> > > > > > > +      PciRomAddImageMapping (
> > > > > > >
> > > > > > >            NULL,
> > > > > > >
> > > > > > >            PciIoDevice->PciRootBridgeIo->SegmentNumber,
> > > > > > >
> > > > > > >            PciIoDevice->BusNumber,
> > > > > > >
> > > > > > > @@ -294,8 +258,7 @@ RegisterPciDevice (
> > > > > > >            PciIoDevice->FunctionNumber,
> > > > > > >
> > > > > > >            PciIoDevice->PciIo.RomImage,
> > > > > > >
> > > > > > >            PciIoDevice->PciIo.RomSize
> > > > > > >
> > > > > > > -          );
> > > > > > >
> > > > > > > -      }
> > > > > > >
> > > > > > > +        );
> > > > > > >
> > > > > > >      }
> > > > > > >
> > > > > > >    }
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > > @@ -597,7 +560,7 @@ DeRegisterPciDevice (
> > > > > > >  }
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > >  /**
> > > > > > >
> > > > > > > -  Start to manage the PCI device on the specified root bridge or PCI-
> > PCI
> > > > > > > Bridge.
> > > > > > >
> > > > > > > +  Start the PCI root Ports or PCI-PCI Bridge only.
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > >    @param Controller          The root bridge handle.
> > > > > > >
> > > > > > >    @param RootBridge          A pointer to the PCI_IO_DEVICE.
> > > > > > >
> > > > > > > @@ -612,7 +575,82 @@ DeRegisterPciDevice (
> > > > > > >
> > > > > > >
> > > > > > >  **/
> > > > > > >
> > > > > > >  EFI_STATUS
> > > > > > >
> > > > > > > -StartPciDevicesOnBridge (
> > > > > > >
> > > > > > > +StartPciRootPortsOnBridge (
> > > > > > >
> > > > > > > +  IN EFI_HANDLE                          Controller,
> > > > > > >
> > > > > > > +  IN PCI_IO_DEVICE                       *RootBridge
> > > > > > >
> > > > > > > +  )
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +{
> > > > > > >
> > > > > > > +  PCI_IO_DEVICE             *PciIoDevice;
> > > > > > >
> > > > > > > +  EFI_STATUS                Status;
> > > > > > >
> > > > > > > +  LIST_ENTRY                *CurrentLink;
> > > > > > >
> > > > > > > +  UINT64                    Supports;
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  PciIoDevice = NULL;
> > > > > > >
> > > > > > > +  CurrentLink = RootBridge->ChildList.ForwardLink;
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  while (CurrentLink != NULL && CurrentLink != &RootBridge-
> > >ChildList)
> > > > {
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +    PciIoDevice = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +    //
> > > > > > >
> > > > > > > +    // check if the device has been assigned with required resource
> > > > > > >
> > > > > > > +    // and registered
> > > > > > >
> > > > > > > +    //
> > > > > > >
> > > > > > > +    if (!PciIoDevice->Registered && !PciIoDevice->Allocated) {
> > > > > > >
> > > > > > > +      return EFI_NOT_READY;
> > > > > > >
> > > > > > > +    }
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +    if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {
> > > > > > >
> > > > > > > +      Status = StartPciRootPortsOnBridge (
> > > > > > >
> > > > > > > +                 Controller,
> > > > > > >
> > > > > > > +                 PciIoDevice
> > > > > > >
> > > > > > > +                 );
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +      PciIoDevice->PciIo.Attributes (
> > > > > > >
> > > > > > > +                           &(PciIoDevice->PciIo),
> > > > > > >
> > > > > > > +                           EfiPciIoAttributeOperationSupported,
> > > > > > >
> > > > > > > +                           0,
> > > > > > >
> > > > > > > +                           &Supports
> > > > > > >
> > > > > > > +                         );
> > > > > > >
> > > > > > > +      Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;
> > > > > > >
> > > > > > > +      PciIoDevice->PciIo.Attributes (
> > > > > > >
> > > > > > > +                           &(PciIoDevice->PciIo),
> > > > > > >
> > > > > > > +                           EfiPciIoAttributeOperationEnable,
> > > > > > >
> > > > > > > +                           Supports,
> > > > > > >
> > > > > > > +                           NULL
> > > > > > >
> > > > > > > +                         );
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +    }
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +    CurrentLink = CurrentLink->ForwardLink;
> > > > > > >
> > > > > > > +  }
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  if (PciIoDevice == NULL) {
> > > > > > >
> > > > > > > +    return EFI_NOT_FOUND;
> > > > > > >
> > > > > > > +  } else {
> > > > > > >
> > > > > > > +    return EFI_SUCCESS;
> > > > > > >
> > > > > > > +  }
> > > > > > >
> > > > > > > +}
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +/**
> > > > > > >
> > > > > > > +  Register to manage the PCI device on the specified root bridge or
> > > > PCI-PCI
> > > > > > > Bridge.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @param Controller          The root bridge handle.
> > > > > > >
> > > > > > > +  @param RootBridge          A pointer to the PCI_IO_DEVICE.
> > > > > > >
> > > > > > > +  @param RemainingDevicePath A pointer to the
> > > > > > > EFI_DEVICE_PATH_PROTOCOL.
> > > > > > >
> > > > > > > +  @param NumberOfChildren    Children number.
> > > > > > >
> > > > > > > +  @param ChildHandleBuffer   A pointer to the child handle buffer.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @retval EFI_NOT_READY   Device is not allocated.
> > > > > > >
> > > > > > > +  @retval EFI_UNSUPPORTED Device only support PCI-PCI bridge.
> > > > > > >
> > > > > > > +  @retval EFI_NOT_FOUND   Can not find the specific device.
> > > > > > >
> > > > > > > +  @retval EFI_SUCCESS     Success to start Pci devices on bridge.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +**/
> > > > > > >
> > > > > > > +EFI_STATUS
> > > > > > >
> > > > > > > +RegisterPciDevicesOnBridge (
> > > > > > >
> > > > > > >    IN EFI_HANDLE                          Controller,
> > > > > > >
> > > > > > >    IN PCI_IO_DEVICE                       *RootBridge,
> > > > > > >
> > > > > > >    IN EFI_DEVICE_PATH_PROTOCOL            *RemainingDevicePath,
> > > > > > >
> > > > > > > @@ -626,7 +664,6 @@ StartPciDevicesOnBridge (
> > > > > > >    EFI_DEVICE_PATH_PROTOCOL  *CurrentDevicePath;
> > > > > > >
> > > > > > >    EFI_STATUS                Status;
> > > > > > >
> > > > > > >    LIST_ENTRY                *CurrentLink;
> > > > > > >
> > > > > > > -  UINT64                    Supports;
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > >    PciIoDevice = NULL;
> > > > > > >
> > > > > > >    CurrentLink = RootBridge->ChildList.ForwardLink;
> > > > > > >
> > > > > > > @@ -681,7 +718,7 @@ StartPciDevicesOnBridge (
> > > > > > >        // If it is a PPB
> > > > > > >
> > > > > > >        //
> > > > > > >
> > > > > > >        if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {
> > > > > > >
> > > > > > > -        Status = StartPciDevicesOnBridge (
> > > > > > >
> > > > > > > +        Status = RegisterPciDevicesOnBridge (
> > > > > > >
> > > > > > >                     Controller,
> > > > > > >
> > > > > > >                     PciIoDevice,
> > > > > > >
> > > > > > >                     CurrentDevicePath,
> > > > > > >
> > > > > > > @@ -689,20 +726,6 @@ StartPciDevicesOnBridge (
> > > > > > >                     ChildHandleBuffer
> > > > > > >
> > > > > > >                     );
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > > -        PciIoDevice->PciIo.Attributes (
> > > > > > >
> > > > > > > -                             &(PciIoDevice->PciIo),
> > > > > > >
> > > > > > > -                             EfiPciIoAttributeOperationSupported,
> > > > > > >
> > > > > > > -                             0,
> > > > > > >
> > > > > > > -                             &Supports
> > > > > > >
> > > > > > > -                             );
> > > > > > >
> > > > > > > -        Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;
> > > > > > >
> > > > > > > -        PciIoDevice->PciIo.Attributes (
> > > > > > >
> > > > > > > -                             &(PciIoDevice->PciIo),
> > > > > > >
> > > > > > > -                             EfiPciIoAttributeOperationEnable,
> > > > > > >
> > > > > > > -                             Supports,
> > > > > > >
> > > > > > > -                             NULL
> > > > > > >
> > > > > > > -                             );
> > > > > > >
> > > > > > > -
> > > > > > >
> > > > > > >          return Status;
> > > > > > >
> > > > > > >        } else {
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > > @@ -733,28 +756,13 @@ StartPciDevicesOnBridge (
> > > > > > >        }
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > >        if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {
> > > > > > >
> > > > > > > -        Status = StartPciDevicesOnBridge (
> > > > > > >
> > > > > > > +        Status = RegisterPciDevicesOnBridge (
> > > > > > >
> > > > > > >                     Controller,
> > > > > > >
> > > > > > >                     PciIoDevice,
> > > > > > >
> > > > > > >                     RemainingDevicePath,
> > > > > > >
> > > > > > >                     NumberOfChildren,
> > > > > > >
> > > > > > >                     ChildHandleBuffer
> > > > > > >
> > > > > > >                     );
> > > > > > >
> > > > > > > -
> > > > > > >
> > > > > > > -        PciIoDevice->PciIo.Attributes (
> > > > > > >
> > > > > > > -                             &(PciIoDevice->PciIo),
> > > > > > >
> > > > > > > -                             EfiPciIoAttributeOperationSupported,
> > > > > > >
> > > > > > > -                             0,
> > > > > > >
> > > > > > > -                             &Supports
> > > > > > >
> > > > > > > -                             );
> > > > > > >
> > > > > > > -        Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;
> > > > > > >
> > > > > > > -        PciIoDevice->PciIo.Attributes (
> > > > > > >
> > > > > > > -                             &(PciIoDevice->PciIo),
> > > > > > >
> > > > > > > -                             EfiPciIoAttributeOperationEnable,
> > > > > > >
> > > > > > > -                             Supports,
> > > > > > >
> > > > > > > -                             NULL
> > > > > > >
> > > > > > > -                             );
> > > > > > >
> > > > > > > -
> > > > > > >
> > > > > > >        }
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > >        CurrentLink = CurrentLink->ForwardLink;
> > > > > > >
> > > > > > > @@ -768,6 +776,65 @@ StartPciDevicesOnBridge (
> > > > > > >    }
> > > > > > >
> > > > > > >  }
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > > +/**
> > > > > > >
> > > > > > > +  Start to manage the PCI device on the specified root bridge or
> > PCI-PCI
> > > > > > > Bridge.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @param Controller          The root bridge handle.
> > > > > > >
> > > > > > > +  @param RootBridge          A pointer to the PCI_IO_DEVICE.
> > > > > > >
> > > > > > > +  @param RemainingDevicePath A pointer to the
> > > > > > > EFI_DEVICE_PATH_PROTOCOL.
> > > > > > >
> > > > > > > +  @param NumberOfChildren    Children number.
> > > > > > >
> > > > > > > +  @param ChildHandleBuffer   A pointer to the child handle buffer.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @retval EFI_NOT_READY   Device is not allocated.
> > > > > > >
> > > > > > > +  @retval EFI_UNSUPPORTED Device only support PCI-PCI bridge.
> > > > > > >
> > > > > > > +  @retval EFI_NOT_FOUND   Can not find the specific device.
> > > > > > >
> > > > > > > +  @retval EFI_SUCCESS     Success to start Pci devices on bridge.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +**/
> > > > > > >
> > > > > > > +EFI_STATUS
> > > > > > >
> > > > > > > +StartPciDevicesOnBridge (
> > > > > > >
> > > > > > > +  IN EFI_HANDLE                          Controller,
> > > > > > >
> > > > > > > +  IN PCI_IO_DEVICE                       *RootBridge,
> > > > > > >
> > > > > > > +  IN EFI_DEVICE_PATH_PROTOCOL            *RemainingDevicePath,
> > > > > > >
> > > > > > > +  IN OUT UINT8                           *NumberOfChildren,
> > > > > > >
> > > > > > > +  IN OUT EFI_HANDLE                      *ChildHandleBuffer
> > > > > > >
> > > > > > > +  )
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +{
> > > > > > >
> > > > > > > +  EFI_STATUS                Status;
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  // first register all the PCI devices
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  Status = RegisterPciDevicesOnBridge (
> > > > > > >
> > > > > > > +             Controller,
> > > > > > >
> > > > > > > +             RootBridge,
> > > > > > >
> > > > > > > +             RemainingDevicePath,
> > > > > > >
> > > > > > > +             NumberOfChildren,
> > > > > > >
> > > > > > > +             ChildHandleBuffer
> > > > > > >
> > > > > > > +             );
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  if (EFI_ERROR (Status) == EFI_NOT_FOUND) {
> > > > > > >
> > > > > > > +    return Status;
> > > > > > >
> > > > > > > +  } else {
> > > > > > >
> > > > > > > +    if ( CheckOtherPciFeaturesPcd ()) {
> > > > > > >
> > > > > > > +      //
> > > > > > >
> > > > > > > +      // the late configuration of PCI features
> > > > > > >
> > > > > > > +      //
> > > > > > >
> > > > > > > +      Status = EnumerateOtherPciFeatures (
> > > > > > >
> > > > > > > +                  RootBridge
> > > > > > >
> > > > > > > +                );
> > > > > > >
> > > > > > > +    }
> > > > > > >
> > > > > > > +    //
> > > > > > >
> > > > > > > +    // finally start those PCI bridge port devices only
> > > > > > >
> > > > > > > +    //
> > > > > > >
> > > > > > > +    return StartPciRootPortsOnBridge (
> > > > > > >
> > > > > > > +            Controller,
> > > > > > >
> > > > > > > +            RootBridge
> > > > > > >
> > > > > > > +            );
> > > > > > >
> > > > > > > +  }
> > > > > > >
> > > > > > > +}
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > >  /**
> > > > > > >
> > > > > > >    Start to manage all the PCI devices it found previously under
> > > > > > >
> > > > > > >    the entire host bridge.
> > > > > > >
> > > > > > > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c
> > > > > > > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c
> > > > > > > index 8db1ebf8ec..0a56668380 100644
> > > > > > > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c
> > > > > > > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c
> > > > > > > @@ -1003,7 +1003,7 @@ PciHostBridgeAdjustAllocation (
> > > > > > >      Status = RejectPciDevice (PciResNode->PciDev);
> > > > > > >
> > > > > > >      if (Status == EFI_SUCCESS) {
> > > > > > >
> > > > > > >        DEBUG ((
> > > > > > >
> > > > > > > -        EFI_D_ERROR,
> > > > > > >
> > > > > > > +        DEBUG_ERROR,
> > > > > > >
> > > > > > >          "PciBus: [%02x|%02x|%02x] was rejected due to resource
> > > > > > > confliction.\n",
> > > > > > >
> > > > > > >          PciResNode->PciDev->BusNumber, PciResNode->PciDev-
> > > > > > > >DeviceNumber, PciResNode->PciDev->FunctionNumber
> > > > > > >
> > > > > > >          ));
> > > > > > >
> > > > > > > @@ -1746,7 +1746,7 @@ NotifyPhase (
> > > > > > >
> > > > > > >
> > > > > > >    HostBridgeHandle  = NULL;
> > > > > > >
> > > > > > >    RootBridgeHandle  = NULL;
> > > > > > >
> > > > > > > -  if (gPciPlatformProtocol != NULL) {
> > > > > > >
> > > > > > > +  if ( CheckPciPlatformProtocolInstall()) {
> > > > > > >
> > > > > > >      //
> > > > > > >
> > > > > > >      // Get Host Bridge Handle.
> > > > > > >
> > > > > > >      //
> > > > > > >
> > > > > > > @@ -1770,42 +1770,11 @@ NotifyPhase (
> > > > > > >      //
> > > > > > >
> > > > > > >      // Call PlatformPci::PlatformNotify() if the protocol is present.
> > > > > > >
> > > > > > >      //
> > > > > > >
> > > > > > > -    gPciPlatformProtocol->PlatformNotify (
> > > > > > >
> > > > > > > -                            gPciPlatformProtocol,
> > > > > > >
> > > > > > > -                            HostBridgeHandle,
> > > > > > >
> > > > > > > -                            Phase,
> > > > > > >
> > > > > > > -                            ChipsetEntry
> > > > > > >
> > > > > > > -                            );
> > > > > > >
> > > > > > > -  } else if (gPciOverrideProtocol != NULL){
> > > > > > >
> > > > > > > -    //
> > > > > > >
> > > > > > > -    // Get Host Bridge Handle.
> > > > > > >
> > > > > > > -    //
> > > > > > >
> > > > > > > -    PciResAlloc->GetNextRootBridge (PciResAlloc,
> > &RootBridgeHandle);
> > > > > > >
> > > > > > > -
> > > > > > >
> > > > > > > -    //
> > > > > > >
> > > > > > > -    // Get the rootbridge Io protocol to find the host bridge handle
> > > > > > >
> > > > > > > -    //
> > > > > > >
> > > > > > > -    Status = gBS->HandleProtocol (
> > > > > > >
> > > > > > > -                    RootBridgeHandle,
> > > > > > >
> > > > > > > -                    &gEfiPciRootBridgeIoProtocolGuid,
> > > > > > >
> > > > > > > -                    (VOID **) &PciRootBridgeIo
> > > > > > >
> > > > > > > -                    );
> > > > > > >
> > > > > > > -
> > > > > > >
> > > > > > > -    if (EFI_ERROR (Status)) {
> > > > > > >
> > > > > > > -      return EFI_NOT_FOUND;
> > > > > > >
> > > > > > > -    }
> > > > > > >
> > > > > > > -
> > > > > > >
> > > > > > > -    HostBridgeHandle = PciRootBridgeIo->ParentHandle;
> > > > > > >
> > > > > > > -
> > > > > > >
> > > > > > > -    //
> > > > > > >
> > > > > > > -    // Call PlatformPci::PhaseNotify() if the protocol is present.
> > > > > > >
> > > > > > > -    //
> > > > > > >
> > > > > > > -    gPciOverrideProtocol->PlatformNotify (
> > > > > > >
> > > > > > > -                            gPciOverrideProtocol,
> > > > > > >
> > > > > > > -                            HostBridgeHandle,
> > > > > > >
> > > > > > > -                            Phase,
> > > > > > >
> > > > > > > -                            ChipsetEntry
> > > > > > >
> > > > > > > -                            );
> > > > > > >
> > > > > > > +    PciPlatformNotifyPhase (
> > > > > > >
> > > > > > > +        HostBridgeHandle,
> > > > > > >
> > > > > > > +        Phase,
> > > > > > >
> > > > > > > +        ChipsetEntry
> > > > > > >
> > > > > > > +        );
> > > > > > >
> > > > > > >    }
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > >    Status = PciResAlloc->NotifyPhase (
> > > > > > >
> > > > > > > @@ -1813,27 +1782,15 @@ NotifyPhase (
> > > > > > >                            Phase
> > > > > > >
> > > > > > >                            );
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > > -  if (gPciPlatformProtocol != NULL) {
> > > > > > >
> > > > > > > +  if ( CheckPciPlatformProtocolInstall()) {
> > > > > > >
> > > > > > >      //
> > > > > > >
> > > > > > >      // Call PlatformPci::PlatformNotify() if the protocol is present.
> > > > > > >
> > > > > > >      //
> > > > > > >
> > > > > > > -    gPciPlatformProtocol->PlatformNotify (
> > > > > > >
> > > > > > > -                            gPciPlatformProtocol,
> > > > > > >
> > > > > > > -                            HostBridgeHandle,
> > > > > > >
> > > > > > > -                            Phase,
> > > > > > >
> > > > > > > -                            ChipsetExit
> > > > > > >
> > > > > > > -                            );
> > > > > > >
> > > > > > > -
> > > > > > >
> > > > > > > -  } else if (gPciOverrideProtocol != NULL) {
> > > > > > >
> > > > > > > -    //
> > > > > > >
> > > > > > > -    // Call PlatformPci::PhaseNotify() if the protocol is present.
> > > > > > >
> > > > > > > -    //
> > > > > > >
> > > > > > > -    gPciOverrideProtocol->PlatformNotify (
> > > > > > >
> > > > > > > -                            gPciOverrideProtocol,
> > > > > > >
> > > > > > > -                            HostBridgeHandle,
> > > > > > >
> > > > > > > -                            Phase,
> > > > > > >
> > > > > > > -                            ChipsetExit
> > > > > > >
> > > > > > > -                            );
> > > > > > >
> > > > > > > +    PciPlatformNotifyPhase (
> > > > > > >
> > > > > > > +        HostBridgeHandle,
> > > > > > >
> > > > > > > +        Phase,
> > > > > > >
> > > > > > > +        ChipsetExit
> > > > > > >
> > > > > > > +        );
> > > > > > >
> > > > > > >    }
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > >    return Status;
> > > > > > >
> > > > > > > @@ -1914,31 +1871,16 @@ PreprocessController (
> > > > > > >    RootBridgePciAddress.Bus              = Bus;
> > > > > > >
> > > > > > >    RootBridgePciAddress.ExtendedRegister = 0;
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > > -  if (gPciPlatformProtocol != NULL) {
> > > > > > >
> > > > > > > -    //
> > > > > > >
> > > > > > > -    // Call PlatformPci::PrepController() if the protocol is present.
> > > > > > >
> > > > > > > -    //
> > > > > > >
> > > > > > > -    gPciPlatformProtocol->PlatformPrepController (
> > > > > > >
> > > > > > > -                            gPciPlatformProtocol,
> > > > > > >
> > > > > > > -                            HostBridgeHandle,
> > > > > > >
> > > > > > > -                            RootBridgeHandle,
> > > > > > >
> > > > > > > -                            RootBridgePciAddress,
> > > > > > >
> > > > > > > -                            Phase,
> > > > > > >
> > > > > > > -                            ChipsetEntry
> > > > > > >
> > > > > > > -                            );
> > > > > > >
> > > > > > > -  } else if (gPciOverrideProtocol != NULL) {
> > > > > > >
> > > > > > > -    //
> > > > > > >
> > > > > > > -    // Call PlatformPci::PrepController() if the protocol is present.
> > > > > > >
> > > > > > > -    //
> > > > > > >
> > > > > > > -    gPciOverrideProtocol->PlatformPrepController (
> > > > > > >
> > > > > > > -                            gPciOverrideProtocol,
> > > > > > >
> > > > > > > -                            HostBridgeHandle,
> > > > > > >
> > > > > > > -                            RootBridgeHandle,
> > > > > > >
> > > > > > > -                            RootBridgePciAddress,
> > > > > > >
> > > > > > > -                            Phase,
> > > > > > >
> > > > > > > -                            ChipsetEntry
> > > > > > >
> > > > > > > -                            );
> > > > > > >
> > > > > > > -  }
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  // Call PlatformPci::PrepController() if the protocol is present.
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  PciPlatformPreprocessController (
> > > > > > >
> > > > > > > +      HostBridgeHandle,
> > > > > > >
> > > > > > > +      RootBridgeHandle,
> > > > > > >
> > > > > > > +      RootBridgePciAddress,
> > > > > > >
> > > > > > > +      Phase,
> > > > > > >
> > > > > > > +      ChipsetEntry
> > > > > > >
> > > > > > > +    );
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > >    Status = PciResAlloc->PreprocessController (
> > > > > > >
> > > > > > >                            PciResAlloc,
> > > > > > >
> > > > > > > @@ -1947,31 +1889,16 @@ PreprocessController (
> > > > > > >                            Phase
> > > > > > >
> > > > > > >                            );
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > > -  if (gPciPlatformProtocol != NULL) {
> > > > > > >
> > > > > > > -    //
> > > > > > >
> > > > > > > -    // Call PlatformPci::PrepController() if the protocol is present.
> > > > > > >
> > > > > > > -    //
> > > > > > >
> > > > > > > -    gPciPlatformProtocol->PlatformPrepController (
> > > > > > >
> > > > > > > -                            gPciPlatformProtocol,
> > > > > > >
> > > > > > > -                            HostBridgeHandle,
> > > > > > >
> > > > > > > -                            RootBridgeHandle,
> > > > > > >
> > > > > > > -                            RootBridgePciAddress,
> > > > > > >
> > > > > > > -                            Phase,
> > > > > > >
> > > > > > > -                            ChipsetExit
> > > > > > >
> > > > > > > -                            );
> > > > > > >
> > > > > > > -  } else if (gPciOverrideProtocol != NULL) {
> > > > > > >
> > > > > > > -    //
> > > > > > >
> > > > > > > -    // Call PlatformPci::PrepController() if the protocol is present.
> > > > > > >
> > > > > > > -    //
> > > > > > >
> > > > > > > -    gPciOverrideProtocol->PlatformPrepController (
> > > > > > >
> > > > > > > -                            gPciOverrideProtocol,
> > > > > > >
> > > > > > > -                            HostBridgeHandle,
> > > > > > >
> > > > > > > -                            RootBridgeHandle,
> > > > > > >
> > > > > > > -                            RootBridgePciAddress,
> > > > > > >
> > > > > > > -                            Phase,
> > > > > > >
> > > > > > > -                            ChipsetExit
> > > > > > >
> > > > > > > -                            );
> > > > > > >
> > > > > > > -  }
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  // Call PlatformPci::PrepController() if the protocol is present.
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  PciPlatformPreprocessController (
> > > > > > >
> > > > > > > +      HostBridgeHandle,
> > > > > > >
> > > > > > > +      RootBridgeHandle,
> > > > > > >
> > > > > > > +      RootBridgePciAddress,
> > > > > > >
> > > > > > > +      Phase,
> > > > > > >
> > > > > > > +      ChipsetExit
> > > > > > >
> > > > > > > +    );
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > >    return EFI_SUCCESS;
> > > > > > >
> > > > > > >  }
> > > > > > >
> > > > > > > diff --git
> > > > a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
> > > > > > > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
> > > > > > > index c7eafff593..2343702154 100644
> > > > > > > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
> > > > > > > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
> > > > > > > @@ -230,7 +230,7 @@ PciSearchDevice (
> > > > > > >    PciIoDevice = NULL;
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > >    DEBUG ((
> > > > > > >
> > > > > > > -    EFI_D_INFO,
> > > > > > >
> > > > > > > +    DEBUG_INFO,
> > > > > > >
> > > > > > >      "PciBus: Discovered %s @ [%02x|%02x|%02x]\n",
> > > > > > >
> > > > > > >      IS_PCI_BRIDGE (Pci) ?     L"PPB" :
> > > > > > >
> > > > > > >      IS_CARDBUS_BRIDGE (Pci) ? L"P2C" :
> > > > > > >
> > > > > > > @@ -397,7 +397,7 @@ DumpPpbPaddingResource (
> > > > > > >
> > > > > > >
> > > > > > >      if ((Type != PciBarTypeUnknown) && ((ResourceType ==
> > > > > > > PciBarTypeUnknown) || (ResourceType == Type))) {
> > > > > > >
> > > > > > >        DEBUG ((
> > > > > > >
> > > > > > > -        EFI_D_INFO,
> > > > > > >
> > > > > > > +        DEBUG_INFO,
> > > > > > >
> > > > > > >          "   Padding: Type = %s; Alignment = 0x%lx;\tLength = 0x%lx\n",
> > > > > > >
> > > > > > >          mBarTypeStr[Type], Descriptor->AddrRangeMax, Descriptor-
> > > > >AddrLen
> > > > > > >
> > > > > > >          ));
> > > > > > >
> > > > > > > @@ -424,7 +424,7 @@ DumpPciBars (
> > > > > > >      }
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > >      DEBUG ((
> > > > > > >
> > > > > > > -      EFI_D_INFO,
> > > > > > >
> > > > > > > +      DEBUG_INFO,
> > > > > > >
> > > > > > >        "   BAR[%d]: Type = %s; Alignment = 0x%lx;\tLength =
> > 0x%lx;\tOffset
> > > > =
> > > > > > > 0x%02x\n",
> > > > > > >
> > > > > > >        Index, mBarTypeStr[MIN (PciIoDevice->PciBar[Index].BarType,
> > > > > > > PciBarTypeMaxType)],
> > > > > > >
> > > > > > >        PciIoDevice->PciBar[Index].Alignment, PciIoDevice-
> > > > > > > >PciBar[Index].Length, PciIoDevice->PciBar[Index].Offset
> > > > > > >
> > > > > > > @@ -437,13 +437,13 @@ DumpPciBars (
> > > > > > >      }
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > >      DEBUG ((
> > > > > > >
> > > > > > > -      EFI_D_INFO,
> > > > > > >
> > > > > > > +      DEBUG_INFO,
> > > > > > >
> > > > > > >        " VFBAR[%d]: Type = %s; Alignment = 0x%lx;\tLength =
> > > > 0x%lx;\tOffset =
> > > > > > > 0x%02x\n",
> > > > > > >
> > > > > > >        Index, mBarTypeStr[MIN (PciIoDevice->VfPciBar[Index].BarType,
> > > > > > > PciBarTypeMaxType)],
> > > > > > >
> > > > > > >        PciIoDevice->VfPciBar[Index].Alignment, PciIoDevice-
> > > > > > > >VfPciBar[Index].Length, PciIoDevice->VfPciBar[Index].Offset
> > > > > > >
> > > > > > >        ));
> > > > > > >
> > > > > > >    }
> > > > > > >
> > > > > > > -  DEBUG ((EFI_D_INFO, "\n"));
> > > > > > >
> > > > > > > +  DEBUG ((DEBUG_INFO, "\n"));
> > > > > > >
> > > > > > >  }
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > >  /**
> > > > > > >
> > > > > > > @@ -1903,7 +1903,7 @@ PciParseBar (
> > > > > > >        // Fix the length to support some special 64 bit BAR
> > > > > > >
> > > > > > >        //
> > > > > > >
> > > > > > >        if (Value == 0) {
> > > > > > >
> > > > > > > -        DEBUG ((EFI_D_INFO, "[PciBus]BAR probing for upper 32bit of
> > > > MEM64
> > > > > > > BAR returns 0, change to 0xFFFFFFFF.\n"));
> > > > > > >
> > > > > > > +        DEBUG ((DEBUG_INFO, "[PciBus]BAR probing for upper 32bit
> > of
> > > > > > MEM64
> > > > > > > BAR returns 0, change to 0xFFFFFFFF.\n"));
> > > > > > >
> > > > > > >          Value = (UINT32) -1;
> > > > > > >
> > > > > > >        } else {
> > > > > > >
> > > > > > >          Value |= ((UINT32)(-1) << HighBitSet32 (Value));
> > > > > > >
> > > > > > > @@ -2153,7 +2153,17 @@ CreatePciIoDevice (
> > > > > > >               NULL
> > > > > > >
> > > > > > >               );
> > > > > > >
> > > > > > >    if (!EFI_ERROR (Status)) {
> > > > > > >
> > > > > > > -    PciIoDevice->IsPciExp = TRUE;
> > > > > > >
> > > > > > > +  PciIoDevice->IsPciExp = TRUE;
> > > > > > >
> > > > > > > +    //
> > > > > > >
> > > > > > > +    // read the PCI device's entire PCI Express Capability structure
> > > > > > >
> > > > > > > +    //
> > > > > > >
> > > > > > > +    PciIo->Pci.Read (
> > > > > > >
> > > > > > > +                  PciIo,
> > > > > > >
> > > > > > > +                  EfiPciIoWidthUint8,
> > > > > > >
> > > > > > > +                  PciIoDevice->PciExpressCapabilityOffset,
> > > > > > >
> > > > > > > +                  sizeof (PCI_CAPABILITY_PCIEXP) / sizeof (UINT8),
> > > > > > >
> > > > > > > +                  &PciIoDevice->PciExpStruct
> > > > > > >
> > > > > > > +                );
> > > > > > >
> > > > > > >    }
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > >    if (PcdGetBool (PcdAriSupport)) {
> > > > > > >
> > > > > > > @@ -2206,7 +2216,7 @@ CreatePciIoDevice (
> > > > > > >                                &Data32
> > > > > > >
> > > > > > >                                );
> > > > > > >
> > > > > > >            DEBUG ((
> > > > > > >
> > > > > > > -            EFI_D_INFO,
> > > > > > >
> > > > > > > +            DEBUG_INFO,
> > > > > > >
> > > > > > >              " ARI: forwarding enabled for PPB[%02x:%02x:%02x]\n",
> > > > > > >
> > > > > > >              Bridge->BusNumber,
> > > > > > >
> > > > > > >              Bridge->DeviceNumber,
> > > > > > >
> > > > > > > @@ -2215,7 +2225,7 @@ CreatePciIoDevice (
> > > > > > >          }
> > > > > > >
> > > > > > >        }
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > > -      DEBUG ((EFI_D_INFO, " ARI: CapOffset = 0x%x\n", PciIoDevice-
> > > > > > > >AriCapabilityOffset));
> > > > > > >
> > > > > > > +      DEBUG ((DEBUG_INFO, " ARI: CapOffset = 0x%x\n",
> > PciIoDevice-
> > > > > > > >AriCapabilityOffset));
> > > > > > >
> > > > > > >      }
> > > > > > >
> > > > > > >    }
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > > @@ -2325,12 +2335,12 @@ CreatePciIoDevice (
> > > > > > >        PciIoDevice->ReservedBusNum =
> > (UINT16)(EFI_PCI_BUS_OF_RID
> > > > > > (LastVF)
> > > > > > > - Bus + 1);
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > >        DEBUG ((
> > > > > > >
> > > > > > > -        EFI_D_INFO,
> > > > > > >
> > > > > > > +        DEBUG_INFO,
> > > > > > >
> > > > > > >          " SR-IOV: SupportedPageSize = 0x%x; SystemPageSize = 0x%x;
> > > > > > > FirstVFOffset = 0x%x;\n",
> > > > > > >
> > > > > > >          SupportedPageSize, PciIoDevice->SystemPageSize >> 12,
> > > > FirstVFOffset
> > > > > > >
> > > > > > >          ));
> > > > > > >
> > > > > > >        DEBUG ((
> > > > > > >
> > > > > > > -        EFI_D_INFO,
> > > > > > >
> > > > > > > +        DEBUG_INFO,
> > > > > > >
> > > > > > >          "         InitialVFs = 0x%x; ReservedBusNum = 0x%x; CapOffset =
> > > > 0x%x\n",
> > > > > > >
> > > > > > >          PciIoDevice->InitialVFs, PciIoDevice->ReservedBusNum,
> > > > PciIoDevice-
> > > > > > > >SrIovCapabilityOffset
> > > > > > >
> > > > > > >          ));
> > > > > > >
> > > > > > > @@ -2345,7 +2355,7 @@ CreatePciIoDevice (
> > > > > > >                 NULL
> > > > > > >
> > > > > > >                 );
> > > > > > >
> > > > > > >      if (!EFI_ERROR (Status)) {
> > > > > > >
> > > > > > > -      DEBUG ((EFI_D_INFO, " MR-IOV: CapOffset = 0x%x\n",
> > PciIoDevice-
> > > > > > > >MrIovCapabilityOffset));
> > > > > > >
> > > > > > > +      DEBUG ((DEBUG_INFO, " MR-IOV: CapOffset = 0x%x\n",
> > > > PciIoDevice-
> > > > > > > >MrIovCapabilityOffset));
> > > > > > >
> > > > > > >      }
> > > > > > >
> > > > > > >    }
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> > > > > > > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> > > > > > > new file mode 100644
> > > > > > > index 0000000000..0819da6536
> > > > > > > --- /dev/null
> > > > > > > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> > > > > > > @@ -0,0 +1,1601 @@
> > > > > > > +/** @file
> > > > > > >
> > > > > > > +  PCI standard feature support functions implementation for PCI
> > Bus
> > > > > > > module..
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> > > > > > >
> > > > > > > +SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +**/
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +#include "PciFeatureSupport.h"
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +/**
> > > > > > >
> > > > > > > +  A gobal pointer to PRIMARY_ROOT_PORT_NODE buffer to track
> > all
> > > > the
> > > > > > > primary physical
> > > > > > >
> > > > > > > +  PCI Root Ports (PCI Controllers) for a given PCI Root Bridge
> > instance
> > > > while
> > > > > > >
> > > > > > > +  enumerating to configure the PCI features
> > > > > > >
> > > > > > > +**/
> > > > > > >
> > > > > > > +PRIMARY_ROOT_PORT_NODE                      *mPrimaryRootPortList;
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +/**
> > > > > > >
> > > > > > > +  A gobal pointer to
> > OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > > > > > buffer
> > > > > > > all the PCI
> > > > > > >
> > > > > > > +  Feature configuration Table nodes to pair against each of the
> > > > > > > PRIMARY_ROOT_PORT_NODE
> > > > > > >
> > > > > > > +  buffer nodes. Each node of these is used to align all the PCI
> > devices
> > > > > > > originating
> > > > > > >
> > > > > > > +  from the PCI Root Port devices of a PCI Root Bridge instance
> > > > > > >
> > > > > > > +**/
> > > > > > >
> > > > > > > +OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > > > > > > *mPciFeaturesConfigurationTableInstances;
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +/**
> > > > > > >
> > > > > > > +  A global pointer to
> > > > PCI_FEATURE_CONFIGURATION_COMPLETION_LIST,
> > > > > > > which stores all
> > > > > > >
> > > > > > > +  the PCI Root Bridge instances that are enumerated for the other
> > PCI
> > > > > > > features,
> > > > > > >
> > > > > > > +  like MaxPayloadSize & MaxReadReqSize; during the the Start()
> > > > interface
> > > > > > of
> > > > > > > the
> > > > > > >
> > > > > > > +  driver binding protocol. The records pointed by this pointer would
> > be
> > > > > > > destroyed
> > > > > > >
> > > > > > > +  when the DXE core invokes the Stop() interface.
> > > > > > >
> > > > > > > +**/
> > > > > > >
> > > > > > > +PCI_FEATURE_CONFIGURATION_COMPLETION_LIST
> > > > > > > *mPciFeaturesConfigurationCompletionList = NULL;
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +/**
> > > > > > >
> > > > > > > +  Main routine to indicate platform selection of any of the other PCI
> > > > > > features
> > > > > > >
> > > > > > > +  to be configured by this driver
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @retval TRUE    platform has selected the other PCI features to be
> > > > > > > configured
> > > > > > >
> > > > > > > +          FALSE   platform has not selected any of the other PCI
> > features
> > > > > > >
> > > > > > > +**/
> > > > > > >
> > > > > > > +BOOLEAN
> > > > > > >
> > > > > > > +CheckOtherPciFeaturesPcd (
> > > > > > >
> > > > > > > +  )
> > > > > > >
> > > > > > > +{
> > > > > > >
> > > > > > > +  return PcdGet32 ( PcdOtherPciFeatures) ? TRUE : FALSE;
> > > > > > >
> > > > > > > +}
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +/**
> > > > > > >
> > > > > > > +  Main routine to indicate whether the platform has selected the
> > > > > > > Max_Payload_Size
> > > > > > >
> > > > > > > +  PCI feature to be configured by this driver
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @retval TRUE    platform has selected the Max_Payload_Size to
> > be
> > > > > > > configured
> > > > > > >
> > > > > > > +          FALSE   platform has not selected this feature
> > > > > > >
> > > > > > > +**/
> > > > > > >
> > > > > > > +BOOLEAN
> > > > > > >
> > > > > > > +SetupMaxPayloadSize (
> > > > > > >
> > > > > > > +  )
> > > > > > >
> > > > > > > +{
> > > > > > >
> > > > > > > +  return (PcdGet32 ( PcdOtherPciFeatures) &
> > > > > > > PCI_FEATURE_SUPPORT_FLAG_MPS) ? TRUE : FALSE;
> > > > > > >
> > > > > > > +}
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +/**
> > > > > > >
> > > > > > > +  Main routine to indicate whether the platform has selected the
> > > > > > > Max_Read_Req_Size
> > > > > > >
> > > > > > > +  PCI feature to be configured by this driver
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @retval TRUE    platform has selected the Max_Read_Req_Size to
> > be
> > > > > > > configured
> > > > > > >
> > > > > > > +          FALSE   platform has not selected this feature
> > > > > > >
> > > > > > > +**/
> > > > > > >
> > > > > > > +BOOLEAN
> > > > > > >
> > > > > > > +SetupMaxReadReqSize (
> > > > > > >
> > > > > > > +  )
> > > > > > >
> > > > > > > +{
> > > > > > >
> > > > > > > +  return (PcdGet32 ( PcdOtherPciFeatures) &
> > > > > > > PCI_FEATURE_SUPPORT_FLAG_MRRS) ? TRUE : FALSE;
> > > > > > >
> > > > > > > +}
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +/**
> > > > > > >
> > > > > > > +  Helper routine which determines whether the given PCI Root
> > Bridge
> > > > > > > instance
> > > > > > >
> > > > > > > +  record already exist. This routine shall help avoid duplicate record
> > > > > > creation
> > > > > > >
> > > > > > > +  in case of re-enumeration of PCI configuation features.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @param  RootBridge              A pointer to the PCI_IO_DEVICE for
> > the
> > > > Root
> > > > > > > Bridge
> > > > > > >
> > > > > > > +  @param  PciFeatureConfigRecord  A pointer to a pointer for type
> > > > > > >
> > > > > > > +
> > PCI_FEATURE_CONFIGURATION_COMPLETION_LIST
> > > > > > >
> > > > > > > +                                  record, Use to return the specific record.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @retval TRUE                    Record already exist
> > > > > > >
> > > > > > > +          FALSE                   Record does not exist for the given PCI Root
> > > > Bridge
> > > > > > >
> > > > > > > +**/
> > > > > > >
> > > > > > > +BOOLEAN
> > > > > > >
> > > > > > > +CheckPciFeatureConfigurationRecordExist (
> > > > > > >
> > > > > > > +  IN  PCI_IO_DEVICE                             *RootBridge,
> > > > > > >
> > > > > > > +  OUT PCI_FEATURE_CONFIGURATION_COMPLETION_LIST
> > > > > > > **PciFeatureConfigRecord
> > > > > > >
> > > > > > > +  )
> > > > > > >
> > > > > > > +{
> > > > > > >
> > > > > > > +  LIST_ENTRY                                  *Link;
> > > > > > >
> > > > > > > +  PCI_FEATURE_CONFIGURATION_COMPLETION_LIST   *Temp;
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  if ( mPciFeaturesConfigurationCompletionList) {
> > > > > > >
> > > > > > > +    Link = &mPciFeaturesConfigurationCompletionList-
> > >RootBridgeLink;
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +    do {
> > > > > > >
> > > > > > > +      Temp =
> > > > > > > PCI_FEATURE_CONFIGURATION_COMPLETION_LIST_FROM_LINK
> > > > (Link);
> > > > > > >
> > > > > > > +      if ( Temp->RootBridgeHandle == RootBridge->Handle) {
> > > > > > >
> > > > > > > +        *PciFeatureConfigRecord = Temp;
> > > > > > >
> > > > > > > +        return TRUE;
> > > > > > >
> > > > > > > +      }
> > > > > > >
> > > > > > > +      Link = Link->ForwardLink;
> > > > > > >
> > > > > > > +    } while (Link != &mPciFeaturesConfigurationCompletionList-
> > > > > > > >RootBridgeLink);
> > > > > > >
> > > > > > > +  }
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  // not found on the PCI feature configuration completion list
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  *PciFeatureConfigRecord = NULL;
> > > > > > >
> > > > > > > +  return FALSE;
> > > > > > >
> > > > > > > +}
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +/**
> > > > > > >
> > > > > > > +  This routine is primarily to avoid multiple configuration of PCI
> > features
> > > > > > >
> > > > > > > +  to the same PCI Root Bridge due to EDK2 core's ConnectController
> > > > calls
> > > > > > on
> > > > > > >
> > > > > > > +  all the EFI handles. This routine also provide re-enumeration of
> > the
> > > > PCI
> > > > > > >
> > > > > > > +  features on the same PCI Root Bridge based on the policy of
> > > > > > > ReEnumeratePciFeatureConfiguration
> > > > > > >
> > > > > > > +  of the PCI_FEATURE_CONFIGURATION_COMPLETION_LIST.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @param  RootBridge              A pointer to the PCI_IO_DEVICE for
> > the
> > > > Root
> > > > > > > Bridge
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @retval TRUE                    PCI Feature configuration required for the
> > PCI
> > > > > > >
> > > > > > > +                                  Root Bridge
> > > > > > >
> > > > > > > +          FALSE                   PCI Feature configuration is not required to be
> > > > > > >
> > > > > > > +                                  re-enumerated for the PCI Root Bridge
> > > > > > >
> > > > > > > +**/
> > > > > > >
> > > > > > > +BOOLEAN
> > > > > > >
> > > > > > > +CheckPciFeaturesConfigurationRequired (
> > > > > > >
> > > > > > > +  IN PCI_IO_DEVICE          *RootBridge
> > > > > > >
> > > > > > > +  )
> > > > > > >
> > > > > > > +{
> > > > > > >
> > > > > > > +  LIST_ENTRY                                  *Link;
> > > > > > >
> > > > > > > +  PCI_FEATURE_CONFIGURATION_COMPLETION_LIST   *Temp;
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  if ( mPciFeaturesConfigurationCompletionList) {
> > > > > > >
> > > > > > > +    Link = &mPciFeaturesConfigurationCompletionList-
> > >RootBridgeLink;
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +    do {
> > > > > > >
> > > > > > > +      Temp =
> > > > > > > PCI_FEATURE_CONFIGURATION_COMPLETION_LIST_FROM_LINK
> > > > (Link);
> > > > > > >
> > > > > > > +      if ( Temp->RootBridgeHandle == RootBridge->Handle) {
> > > > > > >
> > > > > > > +        return Temp->ReEnumeratePciFeatureConfiguration;
> > > > > > >
> > > > > > > +      }
> > > > > > >
> > > > > > > +      Link = Link->ForwardLink;
> > > > > > >
> > > > > > > +    } while (Link != &mPciFeaturesConfigurationCompletionList-
> > > > > > > >RootBridgeLink);
> > > > > > >
> > > > > > > +  }
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  // not found on the PCI feature configuration completion list,
> > return
> > > > as
> > > > > > > required
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  return TRUE;
> > > > > > >
> > > > > > > +}
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +/**
> > > > > > >
> > > > > > > +  This routine finds the duplicate record if exist and assigns the re-
> > > > > > > enumeration
> > > > > > >
> > > > > > > +  requirement flag, as passed as input. It creates new record for
> > the
> > > > PCI
> > > > > > > Root
> > > > > > >
> > > > > > > +  Bridge and appends the list after updating its re-enumeration flag.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @param  RootBridge            A pointer to PCI_IO_DEVICE of the
> > Root
> > > > > > Bridge
> > > > > > >
> > > > > > > +  @param  ReEnumerationRequired A BOOLEAN for recording the
> > re-
> > > > > > > enumeration requirement
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @retval EFI_SUCCESS           new record inserted into the list or
> > > > updated
> > > > > > the
> > > > > > >
> > > > > > > +                                existing record
> > > > > > >
> > > > > > > +          EFI_INVALID_PARAMETER Unexpected error as
> > > > > > > CheckPciFeatureConfigurationRecordExist
> > > > > > >
> > > > > > > +                                reports as record exist but does not return its
> > pointer
> > > > > > >
> > > > > > > +          EFI_OUT_OF_RESOURCES  Not able to create PCI features
> > > > > > configuratin
> > > > > > > complete
> > > > > > >
> > > > > > > +                                record for the RootBridge
> > > > > > >
> > > > > > > +**/
> > > > > > >
> > > > > > > +EFI_STATUS
> > > > > > >
> > > > > > > +AddRootBridgeInPciFeaturesConfigCompletionList (
> > > > > > >
> > > > > > > +  IN PCI_IO_DEVICE          *RootBridge,
> > > > > > >
> > > > > > > +  IN BOOLEAN                ReEnumerationRequired
> > > > > > >
> > > > > > > +  )
> > > > > > >
> > > > > > > +{
> > > > > > >
> > > > > > > +  PCI_FEATURE_CONFIGURATION_COMPLETION_LIST   *Temp;
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  if ( CheckPciFeatureConfigurationRecordExist ( RootBridge,
> > &Temp))
> > > > {
> > > > > > >
> > > > > > > +    //
> > > > > > >
> > > > > > > +    // this PCI Root Bridge record already exist; it may have been re-
> > > > > > > enumerated
> > > > > > >
> > > > > > > +    // hence just update its enumeration required flag again to exit
> > > > > > >
> > > > > > > +    //
> > > > > > >
> > > > > > > +    if ( Temp) {
> > > > > > >
> > > > > > > +      Temp->ReEnumeratePciFeatureConfiguration  =
> > > > > > > ReEnumerationRequired;
> > > > > > >
> > > > > > > +      return EFI_SUCCESS;
> > > > > > >
> > > > > > > +    } else {
> > > > > > >
> > > > > > > +      //
> > > > > > >
> > > > > > > +      // PCI feature configuration complete record reported as exist
> > and
> > > > no
> > > > > > >
> > > > > > > +      // record pointer returned
> > > > > > >
> > > > > > > +      //
> > > > > > >
> > > > > > > +      return EFI_INVALID_PARAMETER;
> > > > > > >
> > > > > > > +    }
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  } else {
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +    Temp = AllocateZeroPool ( sizeof
> > > > > > > ( PCI_FEATURE_CONFIGURATION_COMPLETION_LIST));
> > > > > > >
> > > > > > > +    if ( !Temp) {
> > > > > > >
> > > > > > > +      return EFI_OUT_OF_RESOURCES;
> > > > > > >
> > > > > > > +    }
> > > > > > >
> > > > > > > +    Temp->Signature                           =
> > > > > > > PCI_FEATURE_CONFIGURATION_SIGNATURE;
> > > > > > >
> > > > > > > +    Temp->RootBridgeHandle                    = RootBridge->Handle;
> > > > > > >
> > > > > > > +    Temp->ReEnumeratePciFeatureConfiguration  =
> > > > > > ReEnumerationRequired;
> > > > > > >
> > > > > > > +    if ( mPciFeaturesConfigurationCompletionList) {
> > > > > > >
> > > > > > > +      InsertTailList ( &mPciFeaturesConfigurationCompletionList-
> > > > > > > >RootBridgeLink,
> > > > > > >
> > > > > > > +                       &Temp->RootBridgeLink);
> > > > > > >
> > > > > > > +    } else {
> > > > > > >
> > > > > > > +      //
> > > > > > >
> > > > > > > +      // init the very first node of the Root Bridge
> > > > > > >
> > > > > > > +      //
> > > > > > >
> > > > > > > +      mPciFeaturesConfigurationCompletionList = Temp;
> > > > > > >
> > > > > > > +      InitializeListHead ( &mPciFeaturesConfigurationCompletionList-
> > > > > > > >RootBridgeLink);
> > > > > > >
> > > > > > > +    }
> > > > > > >
> > > > > > > +  }
> > > > > > >
> > > > > > > +  return EFI_SUCCESS;
> > > > > > >
> > > > > > > +}
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +/**
> > > > > > >
> > > > > > > +  Free up memory alloted for the primary physical PCI Root ports of
> > the
> > > > > > PCI
> > > > > > > Root
> > > > > > >
> > > > > > > +  Bridge instance. Free up all the nodes of type
> > > > > > > PRIMARY_ROOT_PORT_NODE.
> > > > > > >
> > > > > > > +**/
> > > > > > >
> > > > > > > +VOID
> > > > > > >
> > > > > > > +DestroyPrimaryRootPortNodes ()
> > > > > > >
> > > > > > > +{
> > > > > > >
> > > > > > > +  LIST_ENTRY                *Link;
> > > > > > >
> > > > > > > +  PRIMARY_ROOT_PORT_NODE    *Temp;
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  if ( mPrimaryRootPortList) {
> > > > > > >
> > > > > > > +    Link = &mPrimaryRootPortList->NeighborRootPort;
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +    if ( IsListEmpty ( Link)) {
> > > > > > >
> > > > > > > +      FreePool ( mPrimaryRootPortList);
> > > > > > >
> > > > > > > +    } else {
> > > > > > >
> > > > > > > +      do {
> > > > > > >
> > > > > > > +        if ( Link->ForwardLink != &mPrimaryRootPortList-
> > > > >NeighborRootPort)
> > > > > > {
> > > > > > >
> > > > > > > +          Link = Link->ForwardLink;
> > > > > > >
> > > > > > > +        }
> > > > > > >
> > > > > > > +        Temp = PRIMARY_ROOT_PORT_NODE_FROM_LINK ( Link);
> > > > > > >
> > > > > > > +        Link = RemoveEntryList ( Link);
> > > > > > >
> > > > > > > +        FreePool ( Temp);
> > > > > > >
> > > > > > > +      } while ( !IsListEmpty ( Link));
> > > > > > >
> > > > > > > +      FreePool ( mPrimaryRootPortList);
> > > > > > >
> > > > > > > +    }
> > > > > > >
> > > > > > > +    mPrimaryRootPortList = NULL;
> > > > > > >
> > > > > > > +  }
> > > > > > >
> > > > > > > +}
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +/**
> > > > > > >
> > > > > > > +  Free up the memory allocated for temporarily maintaining the PCI
> > > > > > feature
> > > > > > >
> > > > > > > +  configuration table for all the nodes of the primary PCI Root port.
> > > > > > >
> > > > > > > +  Free up memory alloted for
> > > > > > > OTHER_PCI_FEATURES_CONFIGURATION_TABLE.
> > > > > > >
> > > > > > > +**/
> > > > > > >
> > > > > > > +VOID
> > > > > > >
> > > > > > > +ErasePciFeaturesConfigurationTable (
> > > > > > >
> > > > > > > +  )
> > > > > > >
> > > > > > > +{
> > > > > > >
> > > > > > > +  if ( mPciFeaturesConfigurationTableInstances) {
> > > > > > >
> > > > > > > +    FreePool ( mPciFeaturesConfigurationTableInstances);
> > > > > > >
> > > > > > > +  }
> > > > > > >
> > > > > > > +  mPciFeaturesConfigurationTableInstances = NULL;
> > > > > > >
> > > > > > > +}
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +/**
> > > > > > >
> > > > > > > +  Routine meant for initializing any global variables used. It primarily
> > > > cleans
> > > > > > >
> > > > > > > +  up the internal data structure memory allocated for the previous
> > PCI
> > > > > > Root
> > > > > > > Bridge
> > > > > > >
> > > > > > > +  instance. This should be the first routine to call for any virtual PCI
> > > > Root
> > > > > > >
> > > > > > > +  Bridge instance.
> > > > > > >
> > > > > > > +**/
> > > > > > >
> > > > > > > +VOID
> > > > > > >
> > > > > > > +SetupPciFeaturesConfigurationDefaults ()
> > > > > > >
> > > > > > > +{
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  // delete the primary root port list
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  if (mPrimaryRootPortList) {
> > > > > > >
> > > > > > > +    DestroyPrimaryRootPortNodes ();
> > > > > > >
> > > > > > > +  }
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  if ( mPciFeaturesConfigurationTableInstances) {
> > > > > > >
> > > > > > > +    ErasePciFeaturesConfigurationTable ();
> > > > > > >
> > > > > > > +  }
> > > > > > >
> > > > > > > +}
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +/**
> > > > > > >
> > > > > > > +  Helper routine to determine whether the PCI device is a physical
> > root
> > > > > > port
> > > > > > >
> > > > > > > +  recorded in the list.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @param  PciDevice                       A pointer to the PCI_IO_DEVICE.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @retval TRUE                            The PCI device instance is a primary
> > > > > > >
> > > > > > > +                                          primary physical PCI Root Port
> > > > > > >
> > > > > > > +          FALSE                           Not a primary physical PCI Root port
> > > > > > >
> > > > > > > +**/
> > > > > > >
> > > > > > > +BOOLEAN
> > > > > > >
> > > > > > > +CheckRootBridgePrimaryPort (
> > > > > > >
> > > > > > > +  IN PCI_IO_DEVICE          *PciDevice
> > > > > > >
> > > > > > > +  )
> > > > > > >
> > > > > > > +{
> > > > > > >
> > > > > > > +  LIST_ENTRY                *Link;
> > > > > > >
> > > > > > > +  PRIMARY_ROOT_PORT_NODE    *Temp;
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  if ( !mPrimaryRootPortList) {
> > > > > > >
> > > > > > > +    return FALSE;
> > > > > > >
> > > > > > > +  }
> > > > > > >
> > > > > > > +  Link = &mPrimaryRootPortList->NeighborRootPort;
> > > > > > >
> > > > > > > +  do {
> > > > > > >
> > > > > > > +    Temp = PRIMARY_ROOT_PORT_NODE_FROM_LINK ( Link);
> > > > > > >
> > > > > > > +    if ( Temp->RootBridgeHandle == PciDevice->Parent->Handle
> > > > > > >
> > > > > > > +        && Temp->RootPortHandle == PciDevice->Handle) {
> > > > > > >
> > > > > > > +      //
> > > > > > >
> > > > > > > +      // the given PCI device is the primary root port of the Root
> > Bridge
> > > > > > > controller
> > > > > > >
> > > > > > > +      //
> > > > > > >
> > > > > > > +      return TRUE;
> > > > > > >
> > > > > > > +    }
> > > > > > >
> > > > > > > +    Link = Link->ForwardLink;
> > > > > > >
> > > > > > > +  } while ( Link != &mPrimaryRootPortList->NeighborRootPort);
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  // the given PCI device is not the primary root port of the Bridge
> > > > > > controller
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  return FALSE;
> > > > > > >
> > > > > > > +}
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +/**
> > > > > > >
> > > > > > > +  Main routine to determine the child PCI devices of a physical PCI
> > > > bridge
> > > > > > > device
> > > > > > >
> > > > > > > +  and group them under a common internal PCI features
> > Configuration
> > > > > > table.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @param  PciDevice                       A pointer to the PCI_IO_DEVICE.
> > > > > > >
> > > > > > > +  @param  PciFeaturesConfigTable          A pointer to a pointer to
> > the
> > > > > > >
> > > > > > > +
> > > OTHER_PCI_FEATURES_CONFIGURATION_TABLE.
> > > > > > >
> > > > > > > +                                          Returns NULL in case of RCiEP or the PCI
> > > > > > >
> > > > > > > +                                          device does match with any of the physical
> > > > > > >
> > > > > > > +                                          Root ports, or it does not belong to any
> > > > > > >
> > > > > > > +                                          Root port's PCU bus range (not a child)
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @retval EFI_SUCCESS                     able to determine the PCI feature
> > > > > > >
> > > > > > > +                                          configuration table. For RCiEP since
> > > > > > >
> > > > > > > +                                          since it is not prepared.
> > > > > > >
> > > > > > > +          EFI_NOT_FOUND                   the PCI feature configuration table
> > > > does
> > > > > > >
> > > > > > > +                                          not exist as the PCI physical Bridge device
> > > > > > >
> > > > > > > +                                          is not found for this device's parent
> > > > > > >
> > > > > > > +                                          Root Bridge instance
> > > > > > >
> > > > > > > +**/
> > > > > > >
> > > > > > > +EFI_STATUS
> > > > > > >
> > > > > > > +GetPciFeaturesConfigurationTable (
> > > > > > >
> > > > > > > +  IN  PCI_IO_DEVICE                           *PciDevice,
> > > > > > >
> > > > > > > +  OUT OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > > > > > > **PciFeaturesConfigTable
> > > > > > >
> > > > > > > +  )
> > > > > > >
> > > > > > > +{
> > > > > > >
> > > > > > > +  LIST_ENTRY                *Link;
> > > > > > >
> > > > > > > +  PRIMARY_ROOT_PORT_NODE    *Temp;
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  if ( !mPrimaryRootPortList) {
> > > > > > >
> > > > > > > +    *PciFeaturesConfigTable = NULL;
> > > > > > >
> > > > > > > +    return EFI_NOT_FOUND;
> > > > > > >
> > > > > > > +  }
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  // The PCI features configuration table is not built for RCiEP,
> > return
> > > > NULL
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  if ( PciDevice->PciExpStruct.Capability.Bits.DevicePortType == \
> > > > > > >
> > > > > > > +
> > > > PCIE_DEVICE_PORT_TYPE_ROOT_COMPLEX_INTEGRATED_ENDPOINT)
> > > > > > > {
> > > > > > >
> > > > > > > +    *PciFeaturesConfigTable = NULL;
> > > > > > >
> > > > > > > +    return EFI_SUCCESS;
> > > > > > >
> > > > > > > +  }
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  Link = &mPrimaryRootPortList->NeighborRootPort;
> > > > > > >
> > > > > > > +  do {
> > > > > > >
> > > > > > > +    Temp = PRIMARY_ROOT_PORT_NODE_FROM_LINK ( Link);
> > > > > > >
> > > > > > > +    if ( Temp->RootBridgeHandle == PciDevice->Parent->Handle
> > > > > > >
> > > > > > > +        && Temp->RootPortHandle == PciDevice->Handle) {
> > > > > > >
> > > > > > > +      //
> > > > > > >
> > > > > > > +      // the given PCI device is the primary root port of the Root
> > Bridge
> > > > > > > controller
> > > > > > >
> > > > > > > +      //
> > > > > > >
> > > > > > > +      *PciFeaturesConfigTable = Temp-
> > > > > > >OtherPciFeaturesConfigurationTable;
> > > > > > >
> > > > > > > +      return EFI_SUCCESS;
> > > > > > >
> > > > > > > +    } else {
> > > > > > >
> > > > > > > +      //
> > > > > > >
> > > > > > > +      // check this PCI device belongs to the primary root port of the
> > root
> > > > > > > bridge
> > > > > > >
> > > > > > > +      //
> > > > > > >
> > > > > > > +      if ( PciDevice->BusNumber >= Temp->SecondaryBusStart
> > > > > > >
> > > > > > > +          && PciDevice->BusNumber <= Temp->SecondaryBusEnd) {
> > > > > > >
> > > > > > > +        *PciFeaturesConfigTable = Temp-
> > > > > > >OtherPciFeaturesConfigurationTable;
> > > > > > >
> > > > > > > +        return EFI_SUCCESS;
> > > > > > >
> > > > > > > +      }
> > > > > > >
> > > > > > > +    }
> > > > > > >
> > > > > > > +    Link = Link->ForwardLink;
> > > > > > >
> > > > > > > +  } while ( Link != &mPrimaryRootPortList->NeighborRootPort);
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  // the PCI device must be RCiEP, does not belong to any primary
> > root
> > > > > > port
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  *PciFeaturesConfigTable = NULL;
> > > > > > >
> > > > > > > +  return EFI_SUCCESS;
> > > > > > >
> > > > > > > +}
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +/**
> > > > > > >
> > > > > > > +  The helper routine to retrieve the PCI bus numbers from the PCI
> > > > Bridge
> > > > > > or
> > > > > > > Root
> > > > > > >
> > > > > > > +  port device. Assumes the input PCI device has the PCI Type 1
> > > > > > configuration
> > > > > > > header.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @param  PciDevice                       A pointer to the PCI_IO_DEVICE.
> > > > > > >
> > > > > > > +  @param  PrimaryBusNumber                A pointer to return the PCI
> > > > Priamry
> > > > > > >
> > > > > > > +                                          Bus number.
> > > > > > >
> > > > > > > +  @param  SecondaryBusNumber              A pointer to return the PCI
> > > > > > > Secondary
> > > > > > >
> > > > > > > +                                          Bus number.
> > > > > > >
> > > > > > > +  @param  SubordinateBusNumber            A pointer to return the
> > PCI
> > > > > > > Subordinate
> > > > > > >
> > > > > > > +                                          Bus number.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @retval EFI_SUCCESS           The data was read from the PCI device.
> > > > > > >
> > > > > > > +  @retval EFI_UNSUPPORTED       The address range specified by
> > Offset,
> > > > > > > Width, and Count is not
> > > > > > >
> > > > > > > +                                valid for the PCI configuration header of the PCI
> > > device.
> > > > > > >
> > > > > > > +  @retval EFI_INVALID_PARAMETER input parameters provided to
> > the
> > > > > > read
> > > > > > > operation were invalid.
> > > > > > >
> > > > > > > +**/
> > > > > > >
> > > > > > > +EFI_STATUS
> > > > > > >
> > > > > > > +GetPciRootPortBusAssigned (
> > > > > > >
> > > > > > > +  IN  PCI_IO_DEVICE                           *PciDevice,
> > > > > > >
> > > > > > > +  OUT UINT8                                   *PrimaryBusNumber,
> > > > > > >
> > > > > > > +  OUT UINT8                                   *SecondaryBusNumber,
> > > > > > >
> > > > > > > +  OUT UINT8                                   *SubordinateBusNumber
> > > > > > >
> > > > > > > +  )
> > > > > > >
> > > > > > > +{
> > > > > > >
> > > > > > > +  EFI_STATUS                                  Status;
> > > > > > >
> > > > > > > +  UINT32                                      RootPortBusAssigned;
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  Status = PciDevice->PciIo.Pci.Read (
> > > > > > >
> > > > > > > +                                  &PciDevice->PciIo,
> > > > > > >
> > > > > > > +                                  EfiPciIoWidthUint32,
> > > > > > >
> > > > > > > +                                  PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET,
> > > > > > >
> > > > > > > +                                  1,
> > > > > > >
> > > > > > > +                                  &RootPortBusAssigned
> > > > > > >
> > > > > > > +                                );
> > > > > > >
> > > > > > > +  if ( !EFI_ERROR(Status)) {
> > > > > > >
> > > > > > > +    if ( PrimaryBusNumber) {
> > > > > > >
> > > > > > > +      *PrimaryBusNumber = (UINT8) (0xFF & RootPortBusAssigned);
> > > > > > >
> > > > > > > +    }
> > > > > > >
> > > > > > > +    if ( SecondaryBusNumber) {
> > > > > > >
> > > > > > > +      *SecondaryBusNumber = (UINT8)(0xFF &
> > (RootPortBusAssigned >>
> > > > 8));
> > > > > > >
> > > > > > > +    }
> > > > > > >
> > > > > > > +    if ( SubordinateBusNumber) {
> > > > > > >
> > > > > > > +      *SubordinateBusNumber = (UINT8)(0xFF &
> > > > (RootPortBusAssigned >>
> > > > > > > 16));
> > > > > > >
> > > > > > > +    }
> > > > > > >
> > > > > > > +  }
> > > > > > >
> > > > > > > +  return Status;
> > > > > > >
> > > > > > > +}
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +/**
> > > > > > >
> > > > > > > +  This routine determines the existance of the child PCI device for
> > the
> > > > > > given
> > > > > > >
> > > > > > > +  PCI Root / Bridge Port device. Always assumes the input PCI
> > device is
> > > > the
> > > > > > > bridge
> > > > > > >
> > > > > > > +  or PCI-PCI Bridge device. This routine should not be used with PCI
> > > > > > > endpoint device.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @param  PciDevice                       A pointer to the PCI_IO_DEVICE.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @retval TRUE                            child device exist
> > > > > > >
> > > > > > > +          FALSE                           no child device
> > > > > > >
> > > > > > > +**/
> > > > > > >
> > > > > > > +BOOLEAN
> > > > > > >
> > > > > > > +IsPciRootPortEmpty (
> > > > > > >
> > > > > > > +  IN  PCI_IO_DEVICE                           *PciDevice
> > > > > > >
> > > > > > > +  )
> > > > > > >
> > > > > > > +{
> > > > > > >
> > > > > > > +  UINT8                                       SecBus,
> > > > > > >
> > > > > > > +                                              SubBus;
> > > > > > >
> > > > > > > +  EFI_STATUS                                  Status;
> > > > > > >
> > > > > > > +  LIST_ENTRY                                  *Link;
> > > > > > >
> > > > > > > +  PCI_IO_DEVICE                               *NextPciDevice;
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  // check secondary & suboridinate bus numbers for its endpoint
> > > > device
> > > > > > >
> > > > > > > +  // existance
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  Status = GetPciRootPortBusAssigned ( PciDevice, NULL, &SecBus,
> > > > > > > &SubBus);
> > > > > > >
> > > > > > > +  if ( !EFI_ERROR( Status)) {
> > > > > > >
> > > > > > > +    Link = PciDevice->ChildList.ForwardLink;
> > > > > > >
> > > > > > > +    if ( IsListEmpty ( Link)) {
> > > > > > >
> > > > > > > +      //
> > > > > > >
> > > > > > > +      // return as PCI Root port empty
> > > > > > >
> > > > > > > +      //
> > > > > > >
> > > > > > > +      DEBUG (( DEBUG_INFO, "RP empty,"));
> > > > > > >
> > > > > > > +      return TRUE;
> > > > > > >
> > > > > > > +    }
> > > > > > >
> > > > > > > +    do {
> > > > > > >
> > > > > > > +      NextPciDevice = PCI_IO_DEVICE_FROM_LINK ( Link);
> > > > > > >
> > > > > > > +      DEBUG (( DEBUG_INFO, "dev@%x", NextPciDevice-
> > >BusNumber));
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +      if ( NextPciDevice->BusNumber >= SecBus
> > > > > > >
> > > > > > > +          && NextPciDevice->BusNumber <= SubBus) {
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +        return FALSE;
> > > > > > >
> > > > > > > +      }
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +      Link = Link->ForwardLink;
> > > > > > >
> > > > > > > +    } while ( Link != &PciDevice->ChildList);
> > > > > > >
> > > > > > > +  } else {
> > > > > > >
> > > > > > > +    SecBus = SubBus = 0;
> > > > > > >
> > > > > > > +    DEBUG (( DEBUG_ERROR, "unable to retrieve root port's bus
> > range
> > > > > > > assigned!!!"));
> > > > > > >
> > > > > > > +  }
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  // return as PCI Root port empty
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  return TRUE;
> > > > > > >
> > > > > > > +}
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +/**
> > > > > > >
> > > > > > > +  The main routine which process the PCI feature
> > Max_Payload_Size as
> > > > > > per
> > > > > > > the
> > > > > > >
> > > > > > > +  device-specific platform policy, as well as in complaince with the
> > PCI
> > > > Base
> > > > > > >
> > > > > > > +  specification Revision 4, that aligns the value for the entire PCI
> > > > heirarchy
> > > > > > >
> > > > > > > +  starting from its physical PCI Root port / Bridge device.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @param PciDevice                      A pointer to the PCI_IO_DEVICE.
> > > > > > >
> > > > > > > +  @param PciConfigPhase                 for the PCI feature configuration
> > > > phases:
> > > > > > >
> > > > > > > +                                        PciFeatureGetDevicePolicy &
> > > > PciFeatureSetupPhase
> > > > > > >
> > > > > > > +  @param PciFeaturesConfigurationTable  pointer to
> > > > > > > OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @retval EFI_SUCCESS                   processing of PCI feature
> > > > > > > Max_Payload_Size
> > > > > > >
> > > > > > > +                                        is successful.
> > > > > > >
> > > > > > > +**/
> > > > > > >
> > > > > > > +EFI_STATUS
> > > > > > >
> > > > > > > +ProcessMaxPayloadSize (
> > > > > > >
> > > > > > > +  IN  PCI_IO_DEVICE                           *PciDevice,
> > > > > > >
> > > > > > > +  IN  PCI_FEATURE_CONFIGURATION_PHASE         PciConfigPhase,
> > > > > > >
> > > > > > > +  IN  OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > > > > > > *PciFeaturesConfigurationTable
> > > > > > >
> > > > > > > +  )
> > > > > > >
> > > > > > > +{
> > > > > > >
> > > > > > > +  PCI_REG_PCIE_DEVICE_CAPABILITY          PciDeviceCap;
> > > > > > >
> > > > > > > +  UINT8                                   MpsValue;
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  PciDeviceCap.Uint32 = PciDevice-
> > > > >PciExpStruct.DeviceCapability.Uint32;
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  if ( PciConfigPhase == PciFeatureGetDevicePolicy) {
> > > > > > >
> > > > > > > +    if ( SetupMpsAsPerDeviceCapability ( PciDevice->SetupMPS))
> > > > > > >
> > > > > > > +    {
> > > > > > >
> > > > > > > +      MpsValue = (UINT8)PciDeviceCap.Bits.MaxPayloadSize;
> > > > > > >
> > > > > > > +      //
> > > > > > >
> > > > > > > +      // no change to PCI Root ports without any endpoint device
> > > > > > >
> > > > > > > +      //
> > > > > > >
> > > > > > > +      if ( IS_PCI_BRIDGE ( &PciDevice->Pci) &&
> > > > > > > PciDeviceCap.Bits.MaxPayloadSize) {
> > > > > > >
> > > > > > > +        if ( IsPciRootPortEmpty ( PciDevice)) {
> > > > > > >
> > > > > > > +          MpsValue = PCIE_MAX_PAYLOAD_SIZE_128B;
> > > > > > >
> > > > > > > +          DEBUG (( DEBUG_INFO, "(reset RP MPS to min.)"));
> > > > > > >
> > > > > > > +        }
> > > > > > >
> > > > > > > +      }
> > > > > > >
> > > > > > > +    } else {
> > > > > > >
> > > > > > > +      MpsValue = TranslateMpsSetupValueToPci ( PciDevice-
> > > > >SetupMPS);
> > > > > > >
> > > > > > > +    }
> > > > > > >
> > > > > > > +    //
> > > > > > >
> > > > > > > +    // discard device policy override request if greater than PCI
> > device
> > > > > > > capability
> > > > > > >
> > > > > > > +    //
> > > > > > >
> > > > > > > +    PciDevice->SetupMPS =
> > > > > > MIN( (UINT8)PciDeviceCap.Bits.MaxPayloadSize,
> > > > > > > MpsValue);
> > > > > > >
> > > > > > > +  }
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  // align the MPS of the tree to the HCF with this device
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  if ( PciFeaturesConfigurationTable) {
> > > > > > >
> > > > > > > +    MpsValue = PciFeaturesConfigurationTable->Max_Payload_Size;
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +    MpsValue = MIN ( PciDevice->SetupMPS, MpsValue);
> > > > > > >
> > > > > > > +    PciDevice->SetupMPS = MIN ( PciDevice->SetupMPS,
> > MpsValue);
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +    if ( MpsValue != PciFeaturesConfigurationTable-
> > >Max_Payload_Size)
> > > > {
> > > > > > >
> > > > > > > +      DEBUG (( DEBUG_INFO, "reset MPS of the tree to %d,",
> > > > MpsValue));
> > > > > > >
> > > > > > > +      PciFeaturesConfigurationTable->Max_Payload_Size =
> > MpsValue;
> > > > > > >
> > > > > > > +    }
> > > > > > >
> > > > > > > +  }
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  DEBUG (( DEBUG_INFO,
> > > > > > >
> > > > > > > +      "Max_Payload_Size: %d [DevCap:%d],",
> > > > > > >
> > > > > > > +      PciDevice->SetupMPS, PciDeviceCap.Bits.MaxPayloadSize
> > > > > > >
> > > > > > > +  ));
> > > > > > >
> > > > > > > +  return EFI_SUCCESS;
> > > > > > >
> > > > > > > +}
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +/**
> > > > > > >
> > > > > > > +  The main routine which process the PCI feature
> > Max_Read_Req_Size
> > > > as
> > > > > > > per the
> > > > > > >
> > > > > > > +  device-specific platform policy, as well as in complaince with the
> > PCI
> > > > Base
> > > > > > >
> > > > > > > +  specification Revision 4, that aligns the value for the entire PCI
> > > > heirarchy
> > > > > > >
> > > > > > > +  starting from its physical PCI Root port / Bridge device.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @param PciDevice                      A pointer to the PCI_IO_DEVICE.
> > > > > > >
> > > > > > > +  @param PciConfigPhase                 for the PCI feature configuration
> > > > phases:
> > > > > > >
> > > > > > > +                                        PciFeatureGetDevicePolicy &
> > > > PciFeatureSetupPhase
> > > > > > >
> > > > > > > +  @param PciFeaturesConfigurationTable  pointer to
> > > > > > > OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @retval EFI_SUCCESS                   processing of PCI feature
> > > > > > > Max_Read_Req_Size
> > > > > > >
> > > > > > > +                                        is successful.
> > > > > > >
> > > > > > > +**/
> > > > > > >
> > > > > > > +EFI_STATUS
> > > > > > >
> > > > > > > +ProcessMaxReadReqSize (
> > > > > > >
> > > > > > > +  IN  PCI_IO_DEVICE                           *PciDevice,
> > > > > > >
> > > > > > > +  IN  PCI_FEATURE_CONFIGURATION_PHASE         PciConfigPhase,
> > > > > > >
> > > > > > > +  IN  OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > > > > > > *PciFeaturesConfigurationTable
> > > > > > >
> > > > > > > +  )
> > > > > > >
> > > > > > > +{
> > > > > > >
> > > > > > > +  PCI_REG_PCIE_DEVICE_CAPABILITY  PciDeviceCap;
> > > > > > >
> > > > > > > +  UINT8                           MrrsValue;
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  PciDeviceCap.Uint32 = PciDevice-
> > > > >PciExpStruct.DeviceCapability.Uint32;
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  if ( PciConfigPhase == PciFeatureGetDevicePolicy) {
> > > > > > >
> > > > > > > +    if ( SetupMrrsAsPerDeviceCapability ( PciDevice->SetupMRRS))
> > > > > > >
> > > > > > > +    {
> > > > > > >
> > > > > > > +      //
> > > > > > >
> > > > > > > +      // The maximum read request size is not the data packet size of
> > the
> > > > > > TLP,
> > > > > > >
> > > > > > > +      // but the memory read request size, and set to the function as
> > a
> > > > > > > requestor
> > > > > > >
> > > > > > > +      // to not exceed this limit.
> > > > > > >
> > > > > > > +      // However, for the PCI device capable of isochronous traffic;
> > this
> > > > > > > memory read
> > > > > > >
> > > > > > > +      // request size should not extend beyond the
> > Max_Payload_Size.
> > > > Thus,
> > > > > > > in case if
> > > > > > >
> > > > > > > +      // device policy return by platform indicates to set as per device
> > > > > > > capability
> > > > > > >
> > > > > > > +      // than set as per Max_Payload_Size configuration value
> > > > > > >
> > > > > > > +      //
> > > > > > >
> > > > > > > +      if ( SetupMaxPayloadSize()) {
> > > > > > >
> > > > > > > +        MrrsValue = PciDevice->SetupMPS;
> > > > > > >
> > > > > > > +      } else {
> > > > > > >
> > > > > > > +        //
> > > > > > >
> > > > > > > +        // in case this driver is not required to configure the
> > > > > > Max_Payload_Size
> > > > > > >
> > > > > > > +        // than consider programming HCF of the device capability's
> > > > > > > Max_Payload_Size
> > > > > > >
> > > > > > > +        // in this PCI hierarchy; thus making this an implementation
> > > > specific
> > > > > > > feature
> > > > > > >
> > > > > > > +        // which the platform should avoid. For better results, the
> > > > platform
> > > > > > > should
> > > > > > >
> > > > > > > +        // make both the Max_Payload_Size &
> > Max_Read_Request_Size
> > > > to
> > > > > > be
> > > > > > > configured
> > > > > > >
> > > > > > > +        // by this driver
> > > > > > >
> > > > > > > +        //
> > > > > > >
> > > > > > > +        MrrsValue = (UINT8)PciDeviceCap.Bits.MaxPayloadSize;
> > > > > > >
> > > > > > > +      }
> > > > > > >
> > > > > > > +    } else {
> > > > > > >
> > > > > > > +      //
> > > > > > >
> > > > > > > +      // override as per platform based device policy
> > > > > > >
> > > > > > > +      //
> > > > > > >
> > > > > > > +      MrrsValue = TranslateMrrsSetupValueToPci ( PciDevice-
> > > > >SetupMRRS);
> > > > > > >
> > > > > > > +      //
> > > > > > >
> > > > > > > +      // align this device's Max_Read_Request_Size value to the
> > entire
> > > > PCI
> > > > > > > tree
> > > > > > >
> > > > > > > +      //
> > > > > > >
> > > > > > > +      if ( PciFeaturesConfigurationTable) {
> > > > > > >
> > > > > > > +        if ( !PciFeaturesConfigurationTable-
> > > > >Lock_Max_Read_Request_Size)
> > > > > > {
> > > > > > >
> > > > > > > +          PciFeaturesConfigurationTable-
> > >Lock_Max_Read_Request_Size
> > > > =
> > > > > > > TRUE;
> > > > > > >
> > > > > > > +          PciFeaturesConfigurationTable->Max_Read_Request_Size =
> > > > > > > MrrsValue;
> > > > > > >
> > > > > > > +        } else {
> > > > > > >
> > > > > > > +          //
> > > > > > >
> > > > > > > +          // in case of another user enforced value of MRRS within the
> > > > same
> > > > > > > tree,
> > > > > > >
> > > > > > > +          // pick the smallest between the locked value and this value;
> > to
> > > > set
> > > > > > >
> > > > > > > +          // across entire PCI tree nodes
> > > > > > >
> > > > > > > +          //
> > > > > > >
> > > > > > > +          MrrsValue = MIN (
> > > > > > >
> > > > > > > +                        MrrsValue,
> > > > > > >
> > > > > > > +                        PciFeaturesConfigurationTable-
> > >Max_Read_Request_Size
> > > > > > >
> > > > > > > +                        );
> > > > > > >
> > > > > > > +          PciFeaturesConfigurationTable->Max_Read_Request_Size =
> > > > > > > MrrsValue;
> > > > > > >
> > > > > > > +        }
> > > > > > >
> > > > > > > +      }
> > > > > > >
> > > > > > > +    }
> > > > > > >
> > > > > > > +    //
> > > > > > >
> > > > > > > +    // align this device's Max_Read_Request_Size to derived
> > > > configuration
> > > > > > > value
> > > > > > >
> > > > > > > +    //
> > > > > > >
> > > > > > > +    PciDevice->SetupMRRS = MrrsValue;
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  }
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  // align the Max_Read_Request_Size of the PCI tree based on 3
> > > > > > conditions:
> > > > > > >
> > > > > > > +  // first, if user defines MRRS for any one PCI device in the tree
> > than
> > > > align
> > > > > > >
> > > > > > > +  // all the devices in the PCI tree.
> > > > > > >
> > > > > > > +  // second, if user override is not define for this PCI tree than
> > setup
> > > > the
> > > > > > > MRRS
> > > > > > >
> > > > > > > +  // based on MPS value of the tree to meet the criteria for the
> > > > > > isochronous
> > > > > > >
> > > > > > > +  // traffic.
> > > > > > >
> > > > > > > +  // third, if no user override, or platform firmware policy has not
> > > > selected
> > > > > > >
> > > > > > > +  // this PCI bus driver to configure the MPS; than configure the
> > MRRS
> > > > to a
> > > > > > >
> > > > > > > +  // highest common value of PCI device capability for the MPS
> > found
> > > > > > among
> > > > > > > all
> > > > > > >
> > > > > > > +  // the PCI devices in this tree
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  if ( PciFeaturesConfigurationTable) {
> > > > > > >
> > > > > > > +    if ( PciFeaturesConfigurationTable-
> > >Lock_Max_Read_Request_Size)
> > > > {
> > > > > > >
> > > > > > > +      PciDevice->SetupMRRS = PciFeaturesConfigurationTable-
> > > > > > > >Max_Read_Request_Size;
> > > > > > >
> > > > > > > +    } else {
> > > > > > >
> > > > > > > +      if ( SetupMaxPayloadSize()) {
> > > > > > >
> > > > > > > +        PciDevice->SetupMRRS = PciDevice->SetupMPS;
> > > > > > >
> > > > > > > +      } else {
> > > > > > >
> > > > > > > +        PciDevice->SetupMRRS = MIN (
> > > > > > >
> > > > > > > +                                PciDevice->SetupMRRS,
> > > > > > >
> > > > > > > +                                PciFeaturesConfigurationTable-
> > > > > > >Max_Read_Request_Size
> > > > > > >
> > > > > > > +                                );
> > > > > > >
> > > > > > > +      }
> > > > > > >
> > > > > > > +      PciFeaturesConfigurationTable->Max_Read_Request_Size =
> > > > > > PciDevice-
> > > > > > > >SetupMRRS;
> > > > > > >
> > > > > > > +    }
> > > > > > >
> > > > > > > +  }
> > > > > > >
> > > > > > > +  DEBUG (( DEBUG_INFO, "Max_Read_Request_Size: %d\n",
> > > > PciDevice-
> > > > > > > >SetupMRRS));
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  return EFI_SUCCESS;
> > > > > > >
> > > > > > > +}
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +/**
> > > > > > >
> > > > > > > +  Overrides the PCI Device Control register MaxPayloadSize register
> > > > field;
> > > > > > if
> > > > > > >
> > > > > > > +  the hardware value is different than the intended value.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @param  PciDevice             A pointer to the PCI_IO_DEVICE
> > instance.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @retval EFI_SUCCESS           The data was read from or written to
> > the
> > > > PCI
> > > > > > > device.
> > > > > > >
> > > > > > > +  @retval EFI_UNSUPPORTED       The address range specified by
> > Offset,
> > > > > > > Width, and Count is not
> > > > > > >
> > > > > > > +                                valid for the PCI configuration header of the PCI
> > > > > controller.
> > > > > > >
> > > > > > > +  @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is
> > invalid.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +**/
> > > > > > >
> > > > > > > +EFI_STATUS
> > > > > > >
> > > > > > > +OverrideMaxPayloadSize (
> > > > > > >
> > > > > > > +  IN PCI_IO_DEVICE          *PciDevice
> > > > > > >
> > > > > > > +  )
> > > > > > >
> > > > > > > +{
> > > > > > >
> > > > > > > +  PCI_REG_PCIE_DEVICE_CONTROL PcieDev;
> > > > > > >
> > > > > > > +  UINT32                      Offset;
> > > > > > >
> > > > > > > +  EFI_STATUS                  Status;
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  PcieDev.Uint16 = 0;
> > > > > > >
> > > > > > > +  Offset = PciDevice->PciExpressCapabilityOffset +
> > > > > > >
> > > > > > > +               OFFSET_OF (PCI_CAPABILITY_PCIEXP, DeviceControl);
> > > > > > >
> > > > > > > +  Status = PciDevice->PciIo.Pci.Read (
> > > > > > >
> > > > > > > +                                  &PciDevice->PciIo,
> > > > > > >
> > > > > > > +                                  EfiPciIoWidthUint16,
> > > > > > >
> > > > > > > +                                  Offset,
> > > > > > >
> > > > > > > +                                  1,
> > > > > > >
> > > > > > > +                                  &PcieDev.Uint16
> > > > > > >
> > > > > > > +                                );
> > > > > > >
> > > > > > > +  if ( EFI_ERROR(Status)){
> > > > > > >
> > > > > > > +    DEBUG (( DEBUG_ERROR, "Unexpected DeviceControl register
> > > > (0x%x)
> > > > > > > read error!",
> > > > > > >
> > > > > > > +        Offset
> > > > > > >
> > > > > > > +    ));
> > > > > > >
> > > > > > > +    return Status;
> > > > > > >
> > > > > > > +  }
> > > > > > >
> > > > > > > +  if ( PcieDev.Bits.MaxPayloadSize != PciDevice->SetupMPS) {
> > > > > > >
> > > > > > > +    PcieDev.Bits.MaxPayloadSize = PciDevice->SetupMPS;
> > > > > > >
> > > > > > > +    DEBUG (( DEBUG_INFO, "Max_Payload_Size=%d,", PciDevice-
> > > > > > > >SetupMPS));
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +    Status = PciDevice->PciIo.Pci.Write (
> > > > > > >
> > > > > > > +                                    &PciDevice->PciIo,
> > > > > > >
> > > > > > > +                                    EfiPciIoWidthUint16,
> > > > > > >
> > > > > > > +                                    Offset,
> > > > > > >
> > > > > > > +                                    1,
> > > > > > >
> > > > > > > +                                    &PcieDev.Uint16
> > > > > > >
> > > > > > > +                                  );
> > > > > > >
> > > > > > > +    if ( !EFI_ERROR(Status)) {
> > > > > > >
> > > > > > > +      PciDevice->PciExpStruct.DeviceControl.Uint16 = PcieDev.Uint16;
> > > > > > >
> > > > > > > +    } else {
> > > > > > >
> > > > > > > +      DEBUG (( DEBUG_ERROR, "Unexpected DeviceControl register
> > > > (0x%x)
> > > > > > > write error!",
> > > > > > >
> > > > > > > +          Offset
> > > > > > >
> > > > > > > +      ));
> > > > > > >
> > > > > > > +    }
> > > > > > >
> > > > > > > +  } else {
> > > > > > >
> > > > > > > +    DEBUG (( DEBUG_INFO, "No write of Max_Payload_Size=%d,",
> > > > > > PciDevice-
> > > > > > > >SetupMPS));
> > > > > > >
> > > > > > > +  }
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  return Status;
> > > > > > >
> > > > > > > +}
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +/**
> > > > > > >
> > > > > > > +  Overrides the PCI Device Control register MaxPayloadSize register
> > > > field;
> > > > > > if
> > > > > > >
> > > > > > > +  the hardware value is different than the intended value.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @param  PciDevice             A pointer to the PCI_IO_DEVICE
> > instance.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @retval EFI_SUCCESS           The data was read from or written to
> > the
> > > > PCI
> > > > > > > controller.
> > > > > > >
> > > > > > > +  @retval EFI_UNSUPPORTED       The address range specified by
> > Offset,
> > > > > > > Width, and Count is not
> > > > > > >
> > > > > > > +                                valid for the PCI configuration header of the PCI
> > > > > controller.
> > > > > > >
> > > > > > > +  @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is
> > invalid.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +**/
> > > > > > >
> > > > > > > +EFI_STATUS
> > > > > > >
> > > > > > > +OverrideMaxReadReqSize (
> > > > > > >
> > > > > > > +  IN PCI_IO_DEVICE          *PciDevice
> > > > > > >
> > > > > > > +  )
> > > > > > >
> > > > > > > +{
> > > > > > >
> > > > > > > +  PCI_REG_PCIE_DEVICE_CONTROL PcieDev;
> > > > > > >
> > > > > > > +  UINT32                      Offset;
> > > > > > >
> > > > > > > +  EFI_STATUS                  Status;
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  PcieDev.Uint16 = 0;
> > > > > > >
> > > > > > > +  Offset = PciDevice->PciExpressCapabilityOffset +
> > > > > > >
> > > > > > > +               OFFSET_OF (PCI_CAPABILITY_PCIEXP, DeviceControl);
> > > > > > >
> > > > > > > +  Status = PciDevice->PciIo.Pci.Read (
> > > > > > >
> > > > > > > +                                  &PciDevice->PciIo,
> > > > > > >
> > > > > > > +                                  EfiPciIoWidthUint16,
> > > > > > >
> > > > > > > +                                  Offset,
> > > > > > >
> > > > > > > +                                  1,
> > > > > > >
> > > > > > > +                                  &PcieDev.Uint16
> > > > > > >
> > > > > > > +                                );
> > > > > > >
> > > > > > > +  if ( EFI_ERROR(Status)){
> > > > > > >
> > > > > > > +    DEBUG (( DEBUG_ERROR, "Unexpected DeviceControl register
> > > > (0x%x)
> > > > > > > read error!",
> > > > > > >
> > > > > > > +        Offset
> > > > > > >
> > > > > > > +    ));
> > > > > > >
> > > > > > > +    return Status;
> > > > > > >
> > > > > > > +  }
> > > > > > >
> > > > > > > +  if ( PcieDev.Bits.MaxReadRequestSize != PciDevice->SetupMRRS)
> > {
> > > > > > >
> > > > > > > +    PcieDev.Bits.MaxReadRequestSize = PciDevice->SetupMRRS;
> > > > > > >
> > > > > > > +    DEBUG (( DEBUG_INFO, "Max_Read_Request_Size: %d\n",
> > > > PciDevice-
> > > > > > > >SetupMRRS));
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +    Status = PciDevice->PciIo.Pci.Write (
> > > > > > >
> > > > > > > +                                    &PciDevice->PciIo,
> > > > > > >
> > > > > > > +                                    EfiPciIoWidthUint16,
> > > > > > >
> > > > > > > +                                    Offset,
> > > > > > >
> > > > > > > +                                    1,
> > > > > > >
> > > > > > > +                                    &PcieDev.Uint16
> > > > > > >
> > > > > > > +                                  );
> > > > > > >
> > > > > > > +    if ( !EFI_ERROR(Status)) {
> > > > > > >
> > > > > > > +      PciDevice->PciExpStruct.DeviceControl.Uint16 = PcieDev.Uint16;
> > > > > > >
> > > > > > > +    } else {
> > > > > > >
> > > > > > > +      DEBUG (( DEBUG_ERROR, "Unexpected DeviceControl register
> > > > (0x%x)
> > > > > > > write error!",
> > > > > > >
> > > > > > > +          Offset
> > > > > > >
> > > > > > > +      ));
> > > > > > >
> > > > > > > +    }
> > > > > > >
> > > > > > > +  } else {
> > > > > > >
> > > > > > > +    DEBUG (( DEBUG_INFO, "No write of
> > > > Max_Read_Request_Size=%d\n",
> > > > > > > PciDevice->SetupMRRS));
> > > > > > >
> > > > > > > +  }
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  return Status;
> > > > > > >
> > > > > > > +}
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +/**
> > > > > > >
> > > > > > > +  helper routine to dump the PCIe Device Port Type
> > > > > > >
> > > > > > > +**/
> > > > > > >
> > > > > > > +VOID
> > > > > > >
> > > > > > > +DumpDevicePortType (
> > > > > > >
> > > > > > > +  IN  UINT8   DevicePortType
> > > > > > >
> > > > > > > +  )
> > > > > > >
> > > > > > > +{
> > > > > > >
> > > > > > > +  switch ( DevicePortType){
> > > > > > >
> > > > > > > +    case PCIE_DEVICE_PORT_TYPE_PCIE_ENDPOINT:
> > > > > > >
> > > > > > > +      DEBUG (( DEBUG_INFO, "PCIe endpoint found\n"));
> > > > > > >
> > > > > > > +      break;
> > > > > > >
> > > > > > > +    case PCIE_DEVICE_PORT_TYPE_LEGACY_PCIE_ENDPOINT:
> > > > > > >
> > > > > > > +      DEBUG (( DEBUG_INFO, "legacy PCI endpoint found\n"));
> > > > > > >
> > > > > > > +      break;
> > > > > > >
> > > > > > > +    case PCIE_DEVICE_PORT_TYPE_ROOT_PORT:
> > > > > > >
> > > > > > > +      DEBUG (( DEBUG_INFO, "PCIe Root Port found\n"));
> > > > > > >
> > > > > > > +      break;
> > > > > > >
> > > > > > > +    case PCIE_DEVICE_PORT_TYPE_UPSTREAM_PORT:
> > > > > > >
> > > > > > > +      DEBUG (( DEBUG_INFO, "PCI switch upstream port found\n"));
> > > > > > >
> > > > > > > +      break;
> > > > > > >
> > > > > > > +    case PCIE_DEVICE_PORT_TYPE_DOWNSTREAM_PORT:
> > > > > > >
> > > > > > > +      DEBUG (( DEBUG_INFO, "PCI switch downstream port
> > found\n"));
> > > > > > >
> > > > > > > +      break;
> > > > > > >
> > > > > > > +    case PCIE_DEVICE_PORT_TYPE_PCIE_TO_PCI_BRIDGE:
> > > > > > >
> > > > > > > +      DEBUG (( DEBUG_INFO, "PCIe-PCI bridge found\n"));
> > > > > > >
> > > > > > > +      break;
> > > > > > >
> > > > > > > +    case PCIE_DEVICE_PORT_TYPE_PCI_TO_PCIE_BRIDGE:
> > > > > > >
> > > > > > > +      DEBUG (( DEBUG_INFO, "PCI-PCIe bridge found\n"));
> > > > > > >
> > > > > > > +      break;
> > > > > > >
> > > > > > > +    case
> > > > > > >
> > PCIE_DEVICE_PORT_TYPE_ROOT_COMPLEX_INTEGRATED_ENDPOINT:
> > > > > > >
> > > > > > > +      DEBUG (( DEBUG_INFO, "RCiEP found\n"));
> > > > > > >
> > > > > > > +      break;
> > > > > > >
> > > > > > > +    case
> > > > PCIE_DEVICE_PORT_TYPE_ROOT_COMPLEX_EVENT_COLLECTOR:
> > > > > > >
> > > > > > > +      DEBUG (( DEBUG_INFO, "RC Event Collector found\n"));
> > > > > > >
> > > > > > > +      break;
> > > > > > >
> > > > > > > +  }
> > > > > > >
> > > > > > > +}
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +/**
> > > > > > >
> > > > > > > +   Process each PCI device as per the pltaform and device-specific
> > > > policy.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @param RootBridge             A pointer to the PCI_IO_DEVICE.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @retval EFI_SUCCESS           processing each PCI feature as per
> > policy
> > > > > > > defined
> > > > > > >
> > > > > > > +                                was successful.
> > > > > > >
> > > > > > > + **/
> > > > > > >
> > > > > > > +EFI_STATUS
> > > > > > >
> > > > > > > +SetupDevicePciFeatures (
> > > > > > >
> > > > > > > +  IN  PCI_IO_DEVICE                   *PciDevice,
> > > > > > >
> > > > > > > +  IN  PCI_FEATURE_CONFIGURATION_PHASE PciConfigPhase
> > > > > > >
> > > > > > > +  )
> > > > > > >
> > > > > > > +{
> > > > > > >
> > > > > > > +  EFI_STATUS                              Status;
> > > > > > >
> > > > > > > +  PCI_REG_PCIE_CAPABILITY                 PcieCap;
> > > > > > >
> > > > > > > +  OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > > > > > > *OtherPciFeaturesConfigTable;
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  PcieCap.Uint16 = PciDevice->PciExpStruct.Capability.Uint16;
> > > > > > >
> > > > > > > +  DumpDevicePortType ( (UINT8)PcieCap.Bits.DevicePortType);
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  OtherPciFeaturesConfigTable = NULL;
> > > > > > >
> > > > > > > +  Status = GetPciFeaturesConfigurationTable ( PciDevice,
> > > > > > > &OtherPciFeaturesConfigTable);
> > > > > > >
> > > > > > > +  if ( EFI_ERROR( Status)) {
> > > > > > >
> > > > > > > +    DEBUG ((
> > > > > > >
> > > > > > > +        EFI_D_WARN, "No primary root port found in these root
> > bridge
> > > > > > > nodes!\n"
> > > > > > >
> > > > > > > +    ));
> > > > > > >
> > > > > > > +  } else if ( !OtherPciFeaturesConfigTable) {
> > > > > > >
> > > > > > > +    DEBUG ((
> > > > > > >
> > > > > > > +        DEBUG_INFO, "No PCI features config. table for this
> > device!\n"
> > > > > > >
> > > > > > > +    ));
> > > > > > >
> > > > > > > +  } else {
> > > > > > >
> > > > > > > +    DEBUG ((
> > > > > > >
> > > > > > > +        DEBUG_INFO, "using PCI features config. table ID: %d\n",
> > > > > > >
> > > > > > > +        OtherPciFeaturesConfigTable->ID
> > > > > > >
> > > > > > > +    ));
> > > > > > >
> > > > > > > +  }
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  if ( PciConfigPhase == PciFeatureGetDevicePolicy) {
> > > > > > >
> > > > > > > +    Status = GetPciDevicePlatformPolicy ( PciDevice);
> > > > > > >
> > > > > > > +    if ( EFI_ERROR(Status)) {
> > > > > > >
> > > > > > > +      DEBUG ((
> > > > > > >
> > > > > > > +          DEBUG_ERROR, "Error in obtaining PCI device policy!!!\n"
> > > > > > >
> > > > > > > +      ));
> > > > > > >
> > > > > > > +    }
> > > > > > >
> > > > > > > +  }
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  if ( SetupMaxPayloadSize ()) {
> > > > > > >
> > > > > > > +    Status = ProcessMaxPayloadSize (
> > > > > > >
> > > > > > > +              PciDevice,
> > > > > > >
> > > > > > > +              PciConfigPhase,
> > > > > > >
> > > > > > > +              OtherPciFeaturesConfigTable
> > > > > > >
> > > > > > > +              );
> > > > > > >
> > > > > > > +  }
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  // implementation specific rule:- the MRRS of any PCI device
> > should
> > > > be
> > > > > > > processed
> > > > > > >
> > > > > > > +  // only after the MPS is processed for that device
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  if ( SetupMaxReadReqSize ()) {
> > > > > > >
> > > > > > > +    Status = ProcessMaxReadReqSize (
> > > > > > >
> > > > > > > +              PciDevice,
> > > > > > >
> > > > > > > +              PciConfigPhase,
> > > > > > >
> > > > > > > +              OtherPciFeaturesConfigTable
> > > > > > >
> > > > > > > +              );
> > > > > > >
> > > > > > > +  }
> > > > > > >
> > > > > > > +  return Status;
> > > > > > >
> > > > > > > +}
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +/**
> > > > > > >
> > > > > > > +  Traverse all the nodes from the root bridge or PCI-PCI bridge
> > instance,
> > > > to
> > > > > > >
> > > > > > > +  configure the PCI features as per the device-specific platform
> > policy,
> > > > and
> > > > > > >
> > > > > > > +  as per the device capability, as applicable.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @param RootBridge             A pointer to the PCI_IO_DEVICE.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @retval EFI_SUCCESS           Traversing all the nodes of the root
> > bridge
> > > > > > >
> > > > > > > +                                instances were successfull.
> > > > > > >
> > > > > > > +**/
> > > > > > >
> > > > > > > +EFI_STATUS
> > > > > > >
> > > > > > > +SetupPciFeatures (
> > > > > > >
> > > > > > > +  IN  PCI_IO_DEVICE                   *RootBridge,
> > > > > > >
> > > > > > > +  IN  PCI_FEATURE_CONFIGURATION_PHASE PciConfigPhase
> > > > > > >
> > > > > > > +  )
> > > > > > >
> > > > > > > +{
> > > > > > >
> > > > > > > +  EFI_STATUS           Status;
> > > > > > >
> > > > > > > +  LIST_ENTRY           *Link;
> > > > > > >
> > > > > > > +  PCI_IO_DEVICE        *Device;
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  for ( Link = RootBridge->ChildList.ForwardLink
> > > > > > >
> > > > > > > +      ; Link != &RootBridge->ChildList
> > > > > > >
> > > > > > > +      ; Link = Link->ForwardLink
> > > > > > >
> > > > > > > +  ) {
> > > > > > >
> > > > > > > +    Device = PCI_IO_DEVICE_FROM_LINK (Link);
> > > > > > >
> > > > > > > +    if (IS_PCI_BRIDGE (&Device->Pci)) {
> > > > > > >
> > > > > > > +      DEBUG ((
> > > > > > >
> > > > > > > +          DEBUG_INFO, "::Bridge [%02x|%02x|%02x] -",
> > > > > > >
> > > > > > > +          Device->BusNumber, Device->DeviceNumber, Device-
> > > > > > > >FunctionNumber
> > > > > > >
> > > > > > > +      ));
> > > > > > >
> > > > > > > +      if (Device->IsPciExp) {
> > > > > > >
> > > > > > > +        Status = SetupDevicePciFeatures ( Device, PciConfigPhase);
> > > > > > >
> > > > > > > +      } else {
> > > > > > >
> > > > > > > +        DEBUG (( DEBUG_INFO, "Not a PCIe capable device!\n"));
> > > > > > >
> > > > > > > +        //
> > > > > > >
> > > > > > > +        // PCI Bridge which does not have PCI Express Capability
> > structure
> > > > > > >
> > > > > > > +        // cannot process this kind of PCI Bridge device
> > > > > > >
> > > > > > > +        //
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +      }
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +      SetupPciFeatures ( Device, PciConfigPhase);
> > > > > > >
> > > > > > > +    } else {
> > > > > > >
> > > > > > > +      DEBUG ((
> > > > > > >
> > > > > > > +          DEBUG_INFO, "::Device [%02x|%02x|%02x] -",
> > > > > > >
> > > > > > > +          Device->BusNumber, Device->DeviceNumber, Device-
> > > > > > > >FunctionNumber
> > > > > > >
> > > > > > > +      ));
> > > > > > >
> > > > > > > +      if (Device->IsPciExp) {
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +        Status = SetupDevicePciFeatures ( Device, PciConfigPhase);
> > > > > > >
> > > > > > > +      } else {
> > > > > > >
> > > > > > > +        DEBUG (( DEBUG_INFO, "Not a PCIe capable device!\n"));
> > > > > > >
> > > > > > > +        //
> > > > > > >
> > > > > > > +        // PCI Device which does not have PCI Express Capability
> > structure
> > > > > > >
> > > > > > > +        // cannot process this kind of PCI device
> > > > > > >
> > > > > > > +        //
> > > > > > >
> > > > > > > +      }
> > > > > > >
> > > > > > > +    }
> > > > > > >
> > > > > > > +  }
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  return EFI_SUCCESS;
> > > > > > >
> > > > > > > +}
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +/**
> > > > > > >
> > > > > > > +  Program the PCI device, to override the PCI features as per the
> > policy,
> > > > > > >
> > > > > > > +  resolved from previous traverse.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @param RootBridge             A pointer to the PCI_IO_DEVICE.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @retval EFI_SUCCESS           The other PCI features configuration
> > > > during
> > > > > > > enumeration
> > > > > > >
> > > > > > > +                                of all the nodes of the PCI root bridge instance
> > were
> > > > > > >
> > > > > > > +                                programmed in PCI-compliance pattern along with
> > the
> > > > > > >
> > > > > > > +                                device-specific policy, as applicable.
> > > > > > >
> > > > > > > +  @retval EFI_UNSUPPORTED       One of the override operation
> > maong
> > > > the
> > > > > > > nodes of
> > > > > > >
> > > > > > > +                                the PCI hierarchy resulted in a incompatible
> > address
> > > > > > >
> > > > > > > +                                range.
> > > > > > >
> > > > > > > +  @retval EFI_INVALID_PARAMETER The override operation is
> > > > performed
> > > > > > > with invalid input
> > > > > > >
> > > > > > > +                                parameters.
> > > > > > >
> > > > > > > +**/
> > > > > > >
> > > > > > > +EFI_STATUS
> > > > > > >
> > > > > > > +ProgramDevicePciFeatures (
> > > > > > >
> > > > > > > +  IN PCI_IO_DEVICE          *PciDevice
> > > > > > >
> > > > > > > +  )
> > > > > > >
> > > > > > > +{
> > > > > > >
> > > > > > > +  EFI_STATUS           Status;
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  if ( SetupMaxPayloadSize ()) {
> > > > > > >
> > > > > > > +    Status = OverrideMaxPayloadSize (PciDevice);
> > > > > > >
> > > > > > > +  }
> > > > > > >
> > > > > > > +  if ( SetupMaxReadReqSize ()) {
> > > > > > >
> > > > > > > +    Status = OverrideMaxReadReqSize (PciDevice);
> > > > > > >
> > > > > > > +  }
> > > > > > >
> > > > > > > +  return Status;
> > > > > > >
> > > > > > > +}
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +/**
> > > > > > >
> > > > > > > +  Program all the nodes of the specified root bridge or PCI-PCI
> > Bridge,
> > > > to
> > > > > > >
> > > > > > > +  override the PCI features.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @param RootBridge             A pointer to the PCI_IO_DEVICE.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @retval EFI_SUCCESS           The other PCI features configuration
> > > > during
> > > > > > > enumeration
> > > > > > >
> > > > > > > +                                of all the nodes of the PCI root bridge instance
> > were
> > > > > > >
> > > > > > > +                                programmed in PCI-compliance pattern along with
> > the
> > > > > > >
> > > > > > > +                                device-specific policy, as applicable.
> > > > > > >
> > > > > > > +  @retval EFI_UNSUPPORTED       One of the override operation
> > maong
> > > > the
> > > > > > > nodes of
> > > > > > >
> > > > > > > +                                the PCI hierarchy resulted in a incompatible
> > address
> > > > > > >
> > > > > > > +                                range.
> > > > > > >
> > > > > > > +  @retval EFI_INVALID_PARAMETER The override operation is
> > > > performed
> > > > > > > with invalid input
> > > > > > >
> > > > > > > +                                parameters.
> > > > > > >
> > > > > > > +**/
> > > > > > >
> > > > > > > +EFI_STATUS
> > > > > > >
> > > > > > > +ProgramPciFeatures (
> > > > > > >
> > > > > > > +  IN PCI_IO_DEVICE          *RootBridge
> > > > > > >
> > > > > > > +  )
> > > > > > >
> > > > > > > +{
> > > > > > >
> > > > > > > +  EFI_STATUS           Status;
> > > > > > >
> > > > > > > +  LIST_ENTRY           *Link;
> > > > > > >
> > > > > > > +  PCI_IO_DEVICE        *Device;
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  for ( Link = RootBridge->ChildList.ForwardLink
> > > > > > >
> > > > > > > +      ; Link != &RootBridge->ChildList
> > > > > > >
> > > > > > > +      ; Link = Link->ForwardLink
> > > > > > >
> > > > > > > +  ) {
> > > > > > >
> > > > > > > +    Device = PCI_IO_DEVICE_FROM_LINK (Link);
> > > > > > >
> > > > > > > +    if (IS_PCI_BRIDGE (&Device->Pci)) {
> > > > > > >
> > > > > > > +      DEBUG ((
> > > > > > >
> > > > > > > +          DEBUG_INFO, "::Bridge [%02x|%02x|%02x] -",
> > > > > > >
> > > > > > > +          Device->BusNumber, Device->DeviceNumber, Device-
> > > > > > > >FunctionNumber
> > > > > > >
> > > > > > > +      ));
> > > > > > >
> > > > > > > +      if (Device->IsPciExp) {
> > > > > > >
> > > > > > > +        DEBUG (( DEBUG_INFO, "ready to override!\n"));
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +        Status = ProgramDevicePciFeatures ( Device);
> > > > > > >
> > > > > > > +      } else {
> > > > > > >
> > > > > > > +        DEBUG (( DEBUG_INFO, "skipped!\n"));
> > > > > > >
> > > > > > > +        //
> > > > > > >
> > > > > > > +        // PCI Bridge which does not have PCI Express Capability
> > structure
> > > > > > >
> > > > > > > +        // cannot process this kind of PCI Bridge device
> > > > > > >
> > > > > > > +        //
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +      }
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +      Status = ProgramPciFeatures ( Device);
> > > > > > >
> > > > > > > +    } else {
> > > > > > >
> > > > > > > +      DEBUG ((
> > > > > > >
> > > > > > > +          DEBUG_INFO, "::Device [%02x|%02x|%02x] -",
> > > > > > >
> > > > > > > +          Device->BusNumber, Device->DeviceNumber, Device-
> > > > > > > >FunctionNumber
> > > > > > >
> > > > > > > +      ));
> > > > > > >
> > > > > > > +      if (Device->IsPciExp) {
> > > > > > >
> > > > > > > +        DEBUG (( DEBUG_INFO, "ready to override!\n"));
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +        Status = ProgramDevicePciFeatures ( Device);
> > > > > > >
> > > > > > > +      } else {
> > > > > > >
> > > > > > > +        DEBUG (( DEBUG_INFO, "skipped!\n"));
> > > > > > >
> > > > > > > +        //
> > > > > > >
> > > > > > > +        // PCI Device which does not have PCI Express Capability
> > structure
> > > > > > >
> > > > > > > +        // cannot process this kind of PCI device
> > > > > > >
> > > > > > > +        //
> > > > > > >
> > > > > > > +      }
> > > > > > >
> > > > > > > +    }
> > > > > > >
> > > > > > > +  }
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  return Status;
> > > > > > >
> > > > > > > +}
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +/**
> > > > > > >
> > > > > > > +  Create a node of type PRIMARY_ROOT_PORT_NODE for the
> > given
> > > > PCI
> > > > > > > device, and
> > > > > > >
> > > > > > > +  assigns EFI handles of its Root Bridge and its own, along with its
> > PCI
> > > > Bus
> > > > > > >
> > > > > > > +  range for the secondary and subordinate bus range.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @param  RootBridge          A pointer to the PCI_IO_DEVICE for its
> > PCI
> > > > Root
> > > > > > > Bridge
> > > > > > >
> > > > > > > +  @param  Device              A pointer to the PCI_IO_DEVICE for the
> > PCI
> > > > > > > controller
> > > > > > >
> > > > > > > +  @param  RootPortSecBus      PCI controller's Secondary Bus
> > number
> > > > > > >
> > > > > > > +  @param  RootPortSubBus      PCI controller's Subordinate Bus
> > number
> > > > > > >
> > > > > > > +  @param  PrimaryRootPortNode A pointer to the
> > > > > > > PRIMARY_ROOT_PORT_NODE to return
> > > > > > >
> > > > > > > +                              the newly created node for the PCI controller. In
> > > > > > >
> > > > > > > +                              case of error nothing is return in this.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @retval EFI_SUCCESS           new node of
> > > > PRIMARY_ROOT_PORT_NODE is
> > > > > > > returned for
> > > > > > >
> > > > > > > +                                the PCI controller
> > > > > > >
> > > > > > > +          EFI_OUT_OF_RESOURCES  unable to create the node for the
> > PCI
> > > > > > > controller
> > > > > > >
> > > > > > > +          EFI_INVALID_PARAMETER unable to store the node as the
> > input
> > > > > > > buffer is
> > > > > > >
> > > > > > > +                                not empty (*PrimaryRootPortNode)
> > > > > > >
> > > > > > > +**/
> > > > > > >
> > > > > > > +EFI_STATUS
> > > > > > >
> > > > > > > +CreatePrimaryPciRootPortNode (
> > > > > > >
> > > > > > > +  IN  PCI_IO_DEVICE           *RootBridge,
> > > > > > >
> > > > > > > +  IN  PCI_IO_DEVICE           *Device,
> > > > > > >
> > > > > > > +  IN  UINT8                   RootPortSecBus,
> > > > > > >
> > > > > > > +  IN  UINT8                   RootPortSubBus,
> > > > > > >
> > > > > > > +  OUT PRIMARY_ROOT_PORT_NODE  **PrimaryRootPortNode
> > > > > > >
> > > > > > > +  )
> > > > > > >
> > > > > > > +{
> > > > > > >
> > > > > > > +  PRIMARY_ROOT_PORT_NODE      *RootPortNode = NULL;
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  if ( !*PrimaryRootPortNode) {
> > > > > > >
> > > > > > > +    RootPortNode                    = AllocateZeroPool ( sizeof
> > > > > > > (PRIMARY_ROOT_PORT_NODE));
> > > > > > >
> > > > > > > +    if ( RootPortNode == NULL) {
> > > > > > >
> > > > > > > +      return EFI_OUT_OF_RESOURCES;
> > > > > > >
> > > > > > > +    }
> > > > > > >
> > > > > > > +    RootPortNode->Signature         = PCI_ROOT_PORT_SIGNATURE;
> > > > > > >
> > > > > > > +    RootPortNode->RootBridgeHandle  = RootBridge->Handle;
> > > > > > >
> > > > > > > +    RootPortNode->RootPortHandle    = Device->Handle;
> > > > > > >
> > > > > > > +    RootPortNode->SecondaryBusStart = RootPortSecBus;
> > > > > > >
> > > > > > > +    RootPortNode->SecondaryBusEnd   = RootPortSubBus;
> > > > > > >
> > > > > > > +    InitializeListHead ( &RootPortNode->NeighborRootPort);
> > > > > > >
> > > > > > > +    *PrimaryRootPortNode = RootPortNode;
> > > > > > >
> > > > > > > +    return EFI_SUCCESS;
> > > > > > >
> > > > > > > +  } else {
> > > > > > >
> > > > > > > +    return EFI_INVALID_PARAMETER;
> > > > > > >
> > > > > > > +  }
> > > > > > >
> > > > > > > +}
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +/**
> > > > > > >
> > > > > > > +  Checks to report whether the input PCI controller's secondary /
> > > > > > > subordinate
> > > > > > >
> > > > > > > +  bus numbers are within the recorded list of other PCI controllers
> > > > (root
> > > > > > > ports).
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @param  RootPortNode      A pointer to the first node of
> > > > > > > PRIMARY_ROOT_PORT_NODE
> > > > > > >
> > > > > > > +  @param  RootPortSecBus    PCI secondary bus number of the PCI
> > > > > > controller
> > > > > > > found
> > > > > > >
> > > > > > > +  @param  RootPortSubBus    PCI subordinate bus number of the
> > PCI
> > > > Root
> > > > > > > Port found
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @retval TRUE              A child PCI Root port found
> > > > > > >
> > > > > > > +          FALSE             A new PCI controller found
> > > > > > >
> > > > > > > +**/
> > > > > > >
> > > > > > > +BOOLEAN
> > > > > > >
> > > > > > > +CheckChildRootPort (
> > > > > > >
> > > > > > > +  IN      PRIMARY_ROOT_PORT_NODE  *RootPortNode,
> > > > > > >
> > > > > > > +  IN      UINT8                   RootPortSecBus,
> > > > > > >
> > > > > > > +  IN      UINT8                   RootPortSubBus
> > > > > > >
> > > > > > > +)
> > > > > > >
> > > > > > > +{
> > > > > > >
> > > > > > > +  LIST_ENTRY              *Link;
> > > > > > >
> > > > > > > +  PRIMARY_ROOT_PORT_NODE  *Temp;
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  if ( !RootPortNode) {
> > > > > > >
> > > > > > > +    return FALSE;
> > > > > > >
> > > > > > > +  }
> > > > > > >
> > > > > > > +  Link = &RootPortNode->NeighborRootPort;
> > > > > > >
> > > > > > > +  do {
> > > > > > >
> > > > > > > +    Temp = PRIMARY_ROOT_PORT_NODE_FROM_LINK ( Link);
> > > > > > >
> > > > > > > +    if ( RootPortSecBus >= Temp->SecondaryBusStart
> > > > > > >
> > > > > > > +        && RootPortSubBus <= Temp->SecondaryBusEnd) {
> > > > > > >
> > > > > > > +      //
> > > > > > >
> > > > > > > +      // given root port's secondary & subordinate within its primary
> > > > ports
> > > > > > >
> > > > > > > +      // hence return as child port
> > > > > > >
> > > > > > > +      //
> > > > > > >
> > > > > > > +      return TRUE;
> > > > > > >
> > > > > > > +    }
> > > > > > >
> > > > > > > +    Link = Link->ForwardLink;
> > > > > > >
> > > > > > > +  } while (Link != &RootPortNode->NeighborRootPort);
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  // the given root port's secondary / subordinate bus numbers do
> > not
> > > > > > > belong to
> > > > > > >
> > > > > > > +  // any existing primary root port's bus range hence consider
> > another
> > > > > > > primary
> > > > > > >
> > > > > > > +  // root port of the root bridge controller
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  return FALSE;
> > > > > > >
> > > > > > > +}
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +/**
> > > > > > >
> > > > > > > +  Create the vector of PCI Feature configuration table as per the
> > > > number
> > > > > > of
> > > > > > >
> > > > > > > +  the PCI Root Ports given, assigns default value to the PCI features
> > > > > > > supported
> > > > > > >
> > > > > > > +  and assign its address to the global variable
> > > > > > > "mPciFeaturesConfigurationTableInstances".
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @param  NumberOfRootPorts   An input arguement of UINTN to
> > > > indicate
> > > > > > > number of
> > > > > > >
> > > > > > > +                              primary PCI physical Root Bridge devices found
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @retval EFI_OUT_OF_RESOURCES  unable to allocate buffer to
> > store
> > > > PCI
> > > > > > > feature
> > > > > > >
> > > > > > > +                                configuration table for all the physical PCI root
> > > > > > >
> > > > > > > +                                ports given
> > > > > > >
> > > > > > > +          EFI_SUCCESS           PCI Feature COnfiguration table created for
> > all
> > > > > > >
> > > > > > > +                                the PCI Rooot ports reported
> > > > > > >
> > > > > > > + */
> > > > > > >
> > > > > > > +EFI_STATUS
> > > > > > >
> > > > > > > +CreatePciFeaturesConfigurationTableInstances (
> > > > > > >
> > > > > > > +  IN  UINTN NumberOfRootPorts
> > > > > > >
> > > > > > > +  )
> > > > > > >
> > > > > > > +{
> > > > > > >
> > > > > > > +  OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > > > > > > *PciRootBridgePortFeatures = NULL;
> > > > > > >
> > > > > > > +  UINTN                                     Instances;
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  PciRootBridgePortFeatures = AllocateZeroPool (
> > > > > > >
> > > > > > > +                                sizeof
> > > > ( OTHER_PCI_FEATURES_CONFIGURATION_TABLE)
> > > > > > *
> > > > > > > NumberOfRootPorts
> > > > > > >
> > > > > > > +                                );
> > > > > > >
> > > > > > > +  if ( !PciRootBridgePortFeatures) {
> > > > > > >
> > > > > > > +    return EFI_OUT_OF_RESOURCES;
> > > > > > >
> > > > > > > +  }
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  for ( Instances = 0; Instances < NumberOfRootPorts; Instances++)
> > {
> > > > > > >
> > > > > > > +    PciRootBridgePortFeatures [Instances].ID                    = Instances +
> > 1;
> > > > > > >
> > > > > > > +    PciRootBridgePortFeatures [Instances].Max_Payload_Size      =
> > > > > > > PCIE_MAX_PAYLOAD_SIZE_4096B;
> > > > > > >
> > > > > > > +    PciRootBridgePortFeatures
> > [Instances].Max_Read_Request_Size =
> > > > > > > PCIE_MAX_READ_REQ_SIZE_4096B;
> > > > > > >
> > > > > > > +    PciRootBridgePortFeatures
> > > > [Instances].Lock_Max_Read_Request_Size
> > > > > > =
> > > > > > > FALSE;
> > > > > > >
> > > > > > > +  }
> > > > > > >
> > > > > > > +  mPciFeaturesConfigurationTableInstances =
> > > > PciRootBridgePortFeatures;
> > > > > > >
> > > > > > > +  return EFI_SUCCESS;
> > > > > > >
> > > > > > > +}
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +/**
> > > > > > >
> > > > > > > +  This routine pairs the each PCI Root Port node with one of the PCI
> > > > > > Feature
> > > > > > >
> > > > > > > +  Configuration Table node. Each physical PCI Root Port has its own
> > PCI
> > > > > > > feature
> > > > > > >
> > > > > > > +  configuration table which will used for aligning all its downstream
> > > > > > > components.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @param  NumberOfRootPorts     inputs the number of physical
> > PCI
> > > > root
> > > > > > > ports
> > > > > > >
> > > > > > > +                                found on the Root bridge instance
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @retval EFI_INVALID_PARAMETER if the primary PCI root ports
> > list is
> > > > > > > vacant when
> > > > > > >
> > > > > > > +                                there is one or more PCI Root port indicated as per
> > > > > > >
> > > > > > > +                                input parameter
> > > > > > >
> > > > > > > +          EFI_UNSUPPORTED       The PCI Root Port nodes not paired
> > > > equally
> > > > > > with
> > > > > > >
> > > > > > > +                                the PCI Configuration Table nodes
> > > > > > >
> > > > > > > +          EFI_SUCCESS           each PCI feature configuration node is
> > paired
> > > > > > > equally
> > > > > > >
> > > > > > > +                                with each PCI Root port in the list
> > > > > > >
> > > > > > > +**/
> > > > > > >
> > > > > > > +EFI_STATUS
> > > > > > >
> > > > > > > +AssignPciFeaturesConfigurationTable (
> > > > > > >
> > > > > > > +  IN  UINTN NumberOfRootPorts
> > > > > > >
> > > > > > > +  )
> > > > > > >
> > > > > > > +{
> > > > > > >
> > > > > > > +  UINTN                       Instances;
> > > > > > >
> > > > > > > +  LIST_ENTRY                  *Link;
> > > > > > >
> > > > > > > +  PRIMARY_ROOT_PORT_NODE      *Temp;
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  if ( !mPrimaryRootPortList
> > > > > > >
> > > > > > > +      && NumberOfRootPorts) {
> > > > > > >
> > > > > > > +    DEBUG ((
> > > > > > >
> > > > > > > +        DEBUG_ERROR,
> > > > > > >
> > > > > > > +        "Critical error! no internal table setup for %d PCI Root ports \n",
> > > > > > >
> > > > > > > +        NumberOfRootPorts
> > > > > > >
> > > > > > > +    ));
> > > > > > >
> > > > > > > +    return EFI_INVALID_PARAMETER;
> > > > > > >
> > > > > > > +  }
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  if ( NumberOfRootPorts) {
> > > > > > >
> > > > > > > +    Link = &mPrimaryRootPortList->NeighborRootPort;
> > > > > > >
> > > > > > > +    for ( Instances = 0
> > > > > > >
> > > > > > > +        ; (Instances < NumberOfRootPorts)
> > > > > > >
> > > > > > > +        ; Instances++
> > > > > > >
> > > > > > > +    ) {
> > > > > > >
> > > > > > > +      Temp = PRIMARY_ROOT_PORT_NODE_FROM_LINK ( Link);
> > > > > > >
> > > > > > > +      Temp->OtherPciFeaturesConfigurationTable =
> > > > > > > &mPciFeaturesConfigurationTableInstances [Instances];
> > > > > > >
> > > > > > > +      DEBUG ((
> > > > > > >
> > > > > > > +          DEBUG_INFO,
> > > > > > >
> > > > > > > +          "Assigned to %dth primary root port\n",
> > > > > > >
> > > > > > > +          Instances
> > > > > > >
> > > > > > > +      ));
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +      Link = Link->ForwardLink;
> > > > > > >
> > > > > > > +    }
> > > > > > >
> > > > > > > +    if ( Link != &mPrimaryRootPortList->NeighborRootPort) {
> > > > > > >
> > > > > > > +      DEBUG ((
> > > > > > >
> > > > > > > +          DEBUG_ERROR,
> > > > > > >
> > > > > > > +          "Error!! PCI Root Port list is not properly matched with Config.,
> > > > Table
> > > > > > > list \n"
> > > > > > >
> > > > > > > +      ));
> > > > > > >
> > > > > > > +      return EFI_UNSUPPORTED;
> > > > > > >
> > > > > > > +    }
> > > > > > >
> > > > > > > +  }
> > > > > > >
> > > > > > > +  return  EFI_SUCCESS;
> > > > > > >
> > > > > > > +}
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +/**
> > > > > > >
> > > > > > > +  Prepare each PCI Controller (Root Port) with its own PCI Feature
> > > > > > > configuration
> > > > > > >
> > > > > > > +  table node that can be used for tracking to align all PCI nodes in its
> > > > > > > hierarchy.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @param  PrimaryRootPorts      A pointer to
> > > > PRIMARY_ROOT_PORT_NODE
> > > > > > >
> > > > > > > +  @param  NumberOfRootPorts     Total number of pysical primary
> > PCI
> > > > > > Root
> > > > > > > ports
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @retval EFI_OUT_OF_RESOURCES  unable to allocate buffer to
> > store
> > > > PCI
> > > > > > > feature
> > > > > > >
> > > > > > > +                                configuration table for all the physical PCI root
> > > > > > >
> > > > > > > +                                ports given
> > > > > > >
> > > > > > > +          EFI_INVALID_PARAMETER if the primary PCI root ports list is
> > > > vacant
> > > > > > > when
> > > > > > >
> > > > > > > +                                there is one or more PCI Root port indicated as per
> > > > > > >
> > > > > > > +                                input parameter
> > > > > > >
> > > > > > > +          EFI_UNSUPPORTED       The PCI Root Port nodes not paired
> > > > equally
> > > > > > with
> > > > > > >
> > > > > > > +                                the PCI Configuration Table nodes
> > > > > > >
> > > > > > > +          EFI_SUCCESS           each PCI feature configuration node is
> > paired
> > > > > > > equally
> > > > > > >
> > > > > > > +                                with each PCI Root port in the list
> > > > > > >
> > > > > > > +**/
> > > > > > >
> > > > > > > +EFI_STATUS
> > > > > > >
> > > > > > > +PreparePciControllerConfigurationTable (
> > > > > > >
> > > > > > > +  IN  PRIMARY_ROOT_PORT_NODE    *PrimaryRootPorts,
> > > > > > >
> > > > > > > +  IN  UINTN                     NumberOfRootPorts
> > > > > > >
> > > > > > > +  )
> > > > > > >
> > > > > > > +{
> > > > > > >
> > > > > > > +  EFI_STATUS                    Status;
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  mPrimaryRootPortList = PrimaryRootPorts;
> > > > > > >
> > > > > > > +  DEBUG ((
> > > > > > >
> > > > > > > +      DEBUG_INFO, "Number of primary Root Ports found on this
> > bridge
> > > > > > > = %d\n",
> > > > > > >
> > > > > > > +      NumberOfRootPorts
> > > > > > >
> > > > > > > +  ));
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  Status = CreatePciFeaturesConfigurationTableInstances
> > > > > > > ( NumberOfRootPorts);
> > > > > > >
> > > > > > > +  if ( EFI_ERROR(Status)) {
> > > > > > >
> > > > > > > +    DEBUG ((
> > > > > > >
> > > > > > > +        DEBUG_ERROR, "Unexpected memory node creation error for
> > PCI
> > > > > > > features!\n"
> > > > > > >
> > > > > > > +    ));
> > > > > > >
> > > > > > > +  } else {
> > > > > > >
> > > > > > > +    //
> > > > > > >
> > > > > > > +    // align the primary root port nodes list with the PCI Feature
> > > > > > configuration
> > > > > > >
> > > > > > > +    // table. Note that the PCI Feature configuration table is not
> > > > maintain
> > > > > > for
> > > > > > >
> > > > > > > +    // the RCiEP devices
> > > > > > >
> > > > > > > +    //
> > > > > > >
> > > > > > > +    Status = AssignPciFeaturesConfigurationTable
> > > > ( NumberOfRootPorts);
> > > > > > >
> > > > > > > +  }
> > > > > > >
> > > > > > > +  return Status;
> > > > > > >
> > > > > > > +}
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +/**
> > > > > > >
> > > > > > > +  Scan all the nodes of the RootBridge to identify and create a
> > separate
> > > > list
> > > > > > >
> > > > > > > +  of all primary physical PCI root ports and link each with its own
> > > > instance
> > > > > > of
> > > > > > >
> > > > > > > +  the PCI Feature Configuration Table.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @param  RootBridge    A pointer to the PCI_IO_DEVICE of the PCI
> > > > Root
> > > > > > > Bridge
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @retval EFI_OUT_OF_RESOURCES  unable to allocate buffer to
> > store
> > > > PCI
> > > > > > > feature
> > > > > > >
> > > > > > > +                                configuration table for all the physical PCI root
> > > > > > >
> > > > > > > +                                ports given
> > > > > > >
> > > > > > > +          EFI_NOT_FOUND         No PCI Bridge device found
> > > > > > >
> > > > > > > +          EFI_SUCCESS           PCI Feature COnfiguration table created for
> > all
> > > > > > >
> > > > > > > +                                the PCI Rooot ports found
> > > > > > >
> > > > > > > +          EFI_INVALID_PARAMETER invalid parameter passed to the
> > > > routine
> > > > > > > which
> > > > > > >
> > > > > > > +                                creates the PCI controller node for the primary
> > > > > > >
> > > > > > > +                                Root post list
> > > > > > >
> > > > > > > +**/
> > > > > > >
> > > > > > > +EFI_STATUS
> > > > > > >
> > > > > > > +RecordPciRootPortBridges (
> > > > > > >
> > > > > > > +  IN  PCI_IO_DEVICE           *RootBridge
> > > > > > >
> > > > > > > +  )
> > > > > > >
> > > > > > > +{
> > > > > > >
> > > > > > > +  EFI_STATUS              Status = EFI_NOT_FOUND;
> > > > > > >
> > > > > > > +  LIST_ENTRY              *Link;
> > > > > > >
> > > > > > > +  PCI_IO_DEVICE           *Device;
> > > > > > >
> > > > > > > +  UINTN                   NumberOfRootPorts;
> > > > > > >
> > > > > > > +  PRIMARY_ROOT_PORT_NODE  *PrimaryRootPorts,
> > > > > > >
> > > > > > > +                          *TempNode;
> > > > > > >
> > > > > > > +  UINT8                   RootPortSecBus,
> > > > > > >
> > > > > > > +                          RootPortSubBus;
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  DEBUG ((
> > > > > > >
> > > > > > > +      DEBUG_INFO, "<<********** RecordPciRootPortBridges -
> > start
> > > > > > > *************>>\n"
> > > > > > >
> > > > > > > +  ));
> > > > > > >
> > > > > > > +  NumberOfRootPorts = 0;
> > > > > > >
> > > > > > > +  PrimaryRootPorts = NULL;
> > > > > > >
> > > > > > > +  for ( Link = RootBridge->ChildList.ForwardLink
> > > > > > >
> > > > > > > +      ; Link != &RootBridge->ChildList
> > > > > > >
> > > > > > > +      ; Link = Link->ForwardLink
> > > > > > >
> > > > > > > +  ) {
> > > > > > >
> > > > > > > +    Device = PCI_IO_DEVICE_FROM_LINK (Link);
> > > > > > >
> > > > > > > +    if (IS_PCI_BRIDGE (&Device->Pci)) {
> > > > > > >
> > > > > > > +      Status = GetPciRootPortBusAssigned (
> > > > > > >
> > > > > > > +                  Device,
> > > > > > >
> > > > > > > +                  NULL,
> > > > > > >
> > > > > > > +                  &RootPortSecBus,
> > > > > > >
> > > > > > > +                  &RootPortSubBus
> > > > > > >
> > > > > > > +                  );
> > > > > > >
> > > > > > > +      if ( !EFI_ERROR(Status)) {
> > > > > > >
> > > > > > > +        DEBUG ((
> > > > > > >
> > > > > > > +            DEBUG_INFO, "::Device [%02x|%02x|%02x] - SecBus=0x%x,
> > > > > > > SubBus=0x%x\n",
> > > > > > >
> > > > > > > +            Device->BusNumber, Device->DeviceNumber, Device-
> > > > > > > >FunctionNumber,
> > > > > > >
> > > > > > > +            RootPortSecBus, RootPortSubBus
> > > > > > >
> > > > > > > +        ));
> > > > > > >
> > > > > > > +      } else {
> > > > > > >
> > > > > > > +        DEBUG ((
> > > > > > >
> > > > > > > +            DEBUG_ERROR, "Unexpected read error [0x%lx]::Device
> > > > > > > [%02x|%02x|%02x]\n",
> > > > > > >
> > > > > > > +            Status, Device->BusNumber, Device->DeviceNumber,
> > Device-
> > > > > > > >FunctionNumber
> > > > > > >
> > > > > > > +        ));
> > > > > > >
> > > > > > > +        RootPortSecBus = RootPortSubBus = 0;
> > > > > > >
> > > > > > > +        continue;
> > > > > > >
> > > > > > > +      }
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +      if ( !PrimaryRootPorts) {
> > > > > > >
> > > > > > > +        NumberOfRootPorts++;
> > > > > > >
> > > > > > > +        Status = CreatePrimaryPciRootPortNode (
> > > > > > >
> > > > > > > +                    RootBridge,
> > > > > > >
> > > > > > > +                    Device,
> > > > > > >
> > > > > > > +                    RootPortSecBus,
> > > > > > >
> > > > > > > +                    RootPortSubBus,
> > > > > > >
> > > > > > > +                    &PrimaryRootPorts
> > > > > > >
> > > > > > > +                    );
> > > > > > >
> > > > > > > +        if ( EFI_ERROR(Status)) {
> > > > > > >
> > > > > > > +          //
> > > > > > >
> > > > > > > +          // abort mission to scan for all primary roots ports of a bridge
> > > > > > >
> > > > > > > +          // controller if error encountered for very first PCI primary
> > root
> > > > port
> > > > > > >
> > > > > > > +          //
> > > > > > >
> > > > > > > +          DEBUG ((
> > > > > > >
> > > > > > > +              DEBUG_ERROR, "Unexpected node creation error
> > > > [0x%lx]::Device
> > > > > > > [%02x|%02x|%02x]\n",
> > > > > > >
> > > > > > > +              Status, Device->BusNumber, Device->DeviceNumber,
> > Device-
> > > > > > > >FunctionNumber
> > > > > > >
> > > > > > > +          ));
> > > > > > >
> > > > > > > +          return Status;
> > > > > > >
> > > > > > > +        }
> > > > > > >
> > > > > > > +        DEBUG ((
> > > > > > >
> > > > > > > +            DEBUG_INFO, "first primary root port found::Device
> > > > > > > [%02x|%02x|%02x]\n",
> > > > > > >
> > > > > > > +            Device->BusNumber, Device->DeviceNumber, Device-
> > > > > > > >FunctionNumber
> > > > > > >
> > > > > > > +        ));
> > > > > > >
> > > > > > > +      } else {
> > > > > > >
> > > > > > > +        if ( !CheckChildRootPort ( PrimaryRootPorts, RootPortSecBus,
> > > > > > > RootPortSubBus)) {
> > > > > > >
> > > > > > > +          NumberOfRootPorts++;
> > > > > > >
> > > > > > > +          TempNode = NULL;
> > > > > > >
> > > > > > > +          Status = CreatePrimaryPciRootPortNode (
> > > > > > >
> > > > > > > +                      RootBridge,
> > > > > > >
> > > > > > > +                      Device,
> > > > > > >
> > > > > > > +                      RootPortSecBus,
> > > > > > >
> > > > > > > +                      RootPortSubBus,
> > > > > > >
> > > > > > > +                      &TempNode
> > > > > > >
> > > > > > > +                      );
> > > > > > >
> > > > > > > +          if ( !EFI_ERROR(Status)) {
> > > > > > >
> > > > > > > +            //
> > > > > > >
> > > > > > > +            // another primary root port found on the same bridge
> > > > controller
> > > > > > >
> > > > > > > +            // insert in the node list
> > > > > > >
> > > > > > > +            //
> > > > > > >
> > > > > > > +            InsertTailList ( &PrimaryRootPorts->NeighborRootPort,
> > > > > > &TempNode-
> > > > > > > >NeighborRootPort);
> > > > > > >
> > > > > > > +            DEBUG ((
> > > > > > >
> > > > > > > +                DEBUG_INFO, "next primary root port found::Device
> > > > > > > [%02x|%02x|%02x]\n",
> > > > > > >
> > > > > > > +                Device->BusNumber, Device->DeviceNumber, Device-
> > > > > > > >FunctionNumber
> > > > > > >
> > > > > > > +            ));
> > > > > > >
> > > > > > > +          } else {
> > > > > > >
> > > > > > > +            DEBUG ((
> > > > > > >
> > > > > > > +                DEBUG_ERROR, "Unexpected node creation error
> > > > [0x%lx]::Device
> > > > > > > [%02x|%02x|%02x]\n",
> > > > > > >
> > > > > > > +                Status, Device->BusNumber, Device->DeviceNumber,
> > Device-
> > > > > > > >FunctionNumber
> > > > > > >
> > > > > > > +            ));
> > > > > > >
> > > > > > > +          }
> > > > > > >
> > > > > > > +        }
> > > > > > >
> > > > > > > +      }
> > > > > > >
> > > > > > > +    }
> > > > > > >
> > > > > > > +  }
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  // prepare the PCI root port and its feature configuration table list
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  if ( NumberOfRootPorts) {
> > > > > > >
> > > > > > > +    Status = PreparePciControllerConfigurationTable (
> > > > > > >
> > > > > > > +                PrimaryRootPorts,
> > > > > > >
> > > > > > > +                NumberOfRootPorts
> > > > > > >
> > > > > > > +              );
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  } else {
> > > > > > >
> > > > > > > +    DEBUG ((
> > > > > > >
> > > > > > > +        DEBUG_INFO, "No PCI Root port found on this bridge!\n"
> > > > > > >
> > > > > > > +    ));
> > > > > > >
> > > > > > > +  }
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  DEBUG ((
> > > > > > >
> > > > > > > +      DEBUG_INFO, "<<********** RecordPciRootPortBridges -
> > end
> > > > > > > **********>>\n"
> > > > > > >
> > > > > > > +  ));
> > > > > > >
> > > > > > > +  return Status;
> > > > > > >
> > > > > > > +}
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +/**
> > > > > > >
> > > > > > > +  Enumerate all the nodes of the specified root bridge or PCI-PCI
> > > > Bridge, to
> > > > > > >
> > > > > > > +  configure the other PCI features.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @param RootBridge          A pointer to the PCI_IO_DEVICE.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @retval EFI_SUCCESS           The other PCI features configuration
> > > > during
> > > > > > > enumeration
> > > > > > >
> > > > > > > +                                of all the nodes of the PCI root bridge instance
> > were
> > > > > > >
> > > > > > > +                                programmed in PCI-compliance pattern along with
> > the
> > > > > > >
> > > > > > > +                                device-specific policy, as applicable.
> > > > > > >
> > > > > > > +  @retval EFI_UNSUPPORTED       One of the override operation
> > maong
> > > > the
> > > > > > > nodes of
> > > > > > >
> > > > > > > +                                the PCI hierarchy resulted in a incompatible
> > address
> > > > > > >
> > > > > > > +                                range.
> > > > > > >
> > > > > > > +  @retval EFI_INVALID_PARAMETER The override operation is
> > > > performed
> > > > > > > with invalid input
> > > > > > >
> > > > > > > +                                parameters.
> > > > > > >
> > > > > > > +**/
> > > > > > >
> > > > > > > +EFI_STATUS
> > > > > > >
> > > > > > > +EnumerateOtherPciFeatures (
> > > > > > >
> > > > > > > +  IN PCI_IO_DEVICE          *RootBridge
> > > > > > >
> > > > > > > +  )
> > > > > > >
> > > > > > > +{
> > > > > > >
> > > > > > > +  EFI_STATUS            Status;
> > > > > > >
> > > > > > > +  CHAR16                *Str;
> > > > > > >
> > > > > > > +  UINTN                 OtherPciFeatureConfigPhase;
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  // check on PCI features configuration is complete and re-
> > > > enumeration is
> > > > > > > required
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  if ( !CheckPciFeaturesConfigurationRequired ( RootBridge)) {
> > > > > > >
> > > > > > > +    return EFI_ALREADY_STARTED;
> > > > > > >
> > > > > > > +  }
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  Str = ConvertDevicePathToText (
> > > > > > >
> > > > > > > +          DevicePathFromHandle (RootBridge->Handle),
> > > > > > >
> > > > > > > +          FALSE,
> > > > > > >
> > > > > > > +          FALSE
> > > > > > >
> > > > > > > +        );
> > > > > > >
> > > > > > > +  DEBUG ((DEBUG_INFO, "Enumerating PCI features for Root
> > > > Bridge %s\n",
> > > > > > > Str != NULL ? Str : L""));
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  for ( OtherPciFeatureConfigPhase = PciFeatureRootBridgeScan
> > > > > > >
> > > > > > > +      ; OtherPciFeatureConfigPhase <=
> > > > PciFeatureConfigurationComplete
> > > > > > >
> > > > > > > +      ; OtherPciFeatureConfigPhase++
> > > > > > >
> > > > > > > +      ) {
> > > > > > >
> > > > > > > +    switch ( OtherPciFeatureConfigPhase){
> > > > > > >
> > > > > > > +      case  PciFeatureRootBridgeScan:
> > > > > > >
> > > > > > > +        SetupPciFeaturesConfigurationDefaults ();
> > > > > > >
> > > > > > > +        //
> > > > > > >
> > > > > > > +        //first scan the entire root bridge heirarchy for the primary PCI
> > > > root
> > > > > > > ports
> > > > > > >
> > > > > > > +        //
> > > > > > >
> > > > > > > +        RecordPciRootPortBridges ( RootBridge);
> > > > > > >
> > > > > > > +        break;
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +      case  PciFeatureGetDevicePolicy:
> > > > > > >
> > > > > > > +      case  PciFeatureSetupPhase:
> > > > > > >
> > > > > > > +        DEBUG ((
> > > > > > >
> > > > > > > +            DEBUG_INFO, "<<********** SetupPciFeatures - start
> > > > > > > **********>>\n"
> > > > > > >
> > > > > > > +        ));
> > > > > > >
> > > > > > > +        //
> > > > > > >
> > > > > > > +        // enumerate the other PCI features
> > > > > > >
> > > > > > > +        //
> > > > > > >
> > > > > > > +        Status = SetupPciFeatures ( RootBridge,
> > > > OtherPciFeatureConfigPhase);
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +        DEBUG ((
> > > > > > >
> > > > > > > +            DEBUG_INFO, "<<********** SetupPciFeatures - end
> > > > > > > **********>>\n"
> > > > > > >
> > > > > > > +        ));
> > > > > > >
> > > > > > > +        break;
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +      case  PciFeatureConfigurationPhase:
> > > > > > >
> > > > > > > +        //
> > > > > > >
> > > > > > > +        // override the PCI features as per enumeration phase
> > > > > > >
> > > > > > > +        //
> > > > > > >
> > > > > > > +        DEBUG ((DEBUG_INFO, "PCI features override for Root
> > > > Bridge %s\n",
> > > > > > > Str != NULL ? Str : L""));
> > > > > > >
> > > > > > > +        DEBUG ((
> > > > > > >
> > > > > > > +            DEBUG_INFO, "<<********** ProgramPciFeatures - start
> > > > > > > **********>>\n"
> > > > > > >
> > > > > > > +        ));
> > > > > > >
> > > > > > > +        Status = ProgramPciFeatures ( RootBridge);
> > > > > > >
> > > > > > > +        DEBUG ((
> > > > > > >
> > > > > > > +            DEBUG_INFO, "<<********** ProgramPciFeatures - end
> > > > > > > **********>>\n"
> > > > > > >
> > > > > > > +        ));
> > > > > > >
> > > > > > > +        break;
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +      case  PciFeatureConfigurationComplete:
> > > > > > >
> > > > > > > +        //
> > > > > > >
> > > > > > > +        // clean up the temporary resource nodes created for this root
> > > > bridge
> > > > > > >
> > > > > > > +        //
> > > > > > >
> > > > > > > +        DestroyPrimaryRootPortNodes ();
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +        ErasePciFeaturesConfigurationTable ();
> > > > > > >
> > > > > > > +    }
> > > > > > >
> > > > > > > +  }
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  if (Str != NULL) {
> > > > > > >
> > > > > > > +    FreePool (Str);
> > > > > > >
> > > > > > > +  }
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  // mark this root bridge as PCI features configuration complete,
> > and
> > > > no
> > > > > > > new
> > > > > > >
> > > > > > > +  // enumeration is required
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  AddRootBridgeInPciFeaturesConfigCompletionList ( RootBridge,
> > > > FALSE);
> > > > > > >
> > > > > > > +  return Status;
> > > > > > >
> > > > > > > +}
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +/**
> > > > > > >
> > > > > > > +  This routine is invoked from the Stop () interface for the EFI
> > handle of
> > > > > > the
> > > > > > >
> > > > > > > +  RootBridge. Free up its node of type
> > > > > > > PCI_FEATURE_CONFIGURATION_COMPLETION_LIST.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @param  RootBridge      A pointer to the PCI_IO_DEVICE
> > > > > > >
> > > > > > > +**/
> > > > > > >
> > > > > > > +VOID
> > > > > > >
> > > > > > > +DestroyRootBridgePciFeaturesConfigCompletionList (
> > > > > > >
> > > > > > > +  IN PCI_IO_DEVICE          *RootBridge
> > > > > > >
> > > > > > > +  )
> > > > > > >
> > > > > > > +{
> > > > > > >
> > > > > > > +  LIST_ENTRY                                  *Link;
> > > > > > >
> > > > > > > +  PCI_FEATURE_CONFIGURATION_COMPLETION_LIST   *Temp;
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  if ( mPciFeaturesConfigurationCompletionList) {
> > > > > > >
> > > > > > > +    Link = &mPciFeaturesConfigurationCompletionList-
> > >RootBridgeLink;
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +    do {
> > > > > > >
> > > > > > > +      Temp =
> > > > > > > PCI_FEATURE_CONFIGURATION_COMPLETION_LIST_FROM_LINK
> > > > (Link);
> > > > > > >
> > > > > > > +      if ( Temp->RootBridgeHandle == RootBridge->Handle) {
> > > > > > >
> > > > > > > +        RemoveEntryList ( Link);
> > > > > > >
> > > > > > > +        FreePool ( Temp);
> > > > > > >
> > > > > > > +        return;
> > > > > > >
> > > > > > > +      }
> > > > > > >
> > > > > > > +      Link = Link->ForwardLink;
> > > > > > >
> > > > > > > +    } while (Link != &mPciFeaturesConfigurationCompletionList-
> > > > > > > >RootBridgeLink);
> > > > > > >
> > > > > > > +  }
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  // not found on the PCI feature configuration completion list,
> > return
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  return;
> > > > > > >
> > > > > > > +}
> > > > > > >
> > > > > > > diff --git
> > a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> > > > > > > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> > > > > > > new file mode 100644
> > > > > > > index 0000000000..9f225fa993
> > > > > > > --- /dev/null
> > > > > > > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> > > > > > > @@ -0,0 +1,201 @@
> > > > > > > +/** @file
> > > > > > >
> > > > > > > +  PCI standard feature support functions implementation for PCI
> > Bus
> > > > > > > module..
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> > > > > > >
> > > > > > > +SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +**/
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +#ifndef _EFI_PCI_FEATURES_SUPPORT_H_
> > > > > > >
> > > > > > > +#define _EFI_PCI_FEATURES_SUPPORT_H_
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +#include "PciBus.h"
> > > > > > >
> > > > > > > +#include "PciPlatformSupport.h"
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +//
> > > > > > >
> > > > > > > +// Macro definitions for the PCI Features support PCD
> > > > > > >
> > > > > > > +//
> > > > > > >
> > > > > > > +#define PCI_FEATURE_SUPPORT_FLAG_MPS  BIT0
> > > > > > >
> > > > > > > +#define PCI_FEATURE_SUPPORT_FLAG_MRRS BIT1
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +//
> > > > > > >
> > > > > > > +// defines the data structure to hold the details of the PCI Root
> > port
> > > > > > devices
> > > > > > >
> > > > > > > +//
> > > > > > >
> > > > > > > +typedef struct _PRIMARY_ROOT_PORT_NODE
> > > > > > > PRIMARY_ROOT_PORT_NODE;
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +//
> > > > > > >
> > > > > > > +// defines the data structure to hold the configuration data for the
> > > > other
> > > > > > > PCI
> > > > > > >
> > > > > > > +// features
> > > > > > >
> > > > > > > +//
> > > > > > >
> > > > > > > +typedef struct _OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > > > > > > OTHER_PCI_FEATURES_CONFIGURATION_TABLE;
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +//
> > > > > > >
> > > > > > > +// Defines for the PCI features configuration completion and re-
> > > > > > > enumeration list
> > > > > > >
> > > > > > > +//
> > > > > > >
> > > > > > > +typedef struct
> > _PCI_FEATURE_CONFIGURATION_COMPLETION_LIST
> > > > > > > PCI_FEATURE_CONFIGURATION_COMPLETION_LIST;
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +//
> > > > > > >
> > > > > > > +// Signature value for the PCI Root Port node
> > > > > > >
> > > > > > > +//
> > > > > > >
> > > > > > > +#define PCI_ROOT_PORT_SIGNATURE               SIGNATURE_32 ('p',
> > 'c',
> > > > 'i',
> > > > > > 'p')
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +//
> > > > > > >
> > > > > > > +// Definitions of the PCI Root Port data structure members
> > > > > > >
> > > > > > > +//
> > > > > > >
> > > > > > > +struct _PRIMARY_ROOT_PORT_NODE {
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  // Signature header
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  UINT32                                    Signature;
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  // linked list pointers to next node
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  LIST_ENTRY                                NeighborRootPort;
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  // EFI handle of the parent Root Bridge instance
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  EFI_HANDLE                                RootBridgeHandle;
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  // EFI handle of the PCI controller
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  EFI_HANDLE                                RootPortHandle;
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  // PCI Secondary bus value of the PCI controller
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  UINT8                                     SecondaryBusStart;
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  // PCI Subordinate bus value of the PCI controller
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  UINT8                                     SecondaryBusEnd;
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  // pointer to the corresponding PCI feature configuration Table
> > node
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > > > > > > *OtherPciFeaturesConfigurationTable;
> > > > > > >
> > > > > > > +};
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +#define PRIMARY_ROOT_PORT_NODE_FROM_LINK(a) \
> > > > > > >
> > > > > > > +  CR (a, PRIMARY_ROOT_PORT_NODE, NeighborRootPort,
> > > > > > > PCI_ROOT_PORT_SIGNATURE)
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +//
> > > > > > >
> > > > > > > +// Definition of the PCI Feature configuration Table members
> > > > > > >
> > > > > > > +//
> > > > > > >
> > > > > > > +struct _OTHER_PCI_FEATURES_CONFIGURATION_TABLE {
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  // Configuration Table ID
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  UINTN                                     ID;
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  // to configure the PCI feature Maximum payload size to maintain
> > the
> > > > > > data
> > > > > > > packet
> > > > > > >
> > > > > > > +  // size among all the PCI devices in the PCI hierarchy
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  UINT8                                     Max_Payload_Size;
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  // to configure the PCI feature maximum read request size to
> > > > maintain
> > > > > > the
> > > > > > > memory
> > > > > > >
> > > > > > > +  // requester size among all the PCI devices in the PCI hierarchy
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  UINT8                                     Max_Read_Request_Size;
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  // lock the Max_Read_Request_Size for the entire PCI tree of a
> > root
> > > > port
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  BOOLEAN                                   Lock_Max_Read_Request_Size;
> > > > > > >
> > > > > > > +};
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +//
> > > > > > >
> > > > > > > +// PCI feature configuration node signature value
> > > > > > >
> > > > > > > +//
> > > > > > >
> > > > > > > +#define PCI_FEATURE_CONFIGURATION_SIGNATURE
> > > > > > > SIGNATURE_32 ('p', 'c', 'i', 'f')
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +struct _PCI_FEATURE_CONFIGURATION_COMPLETION_LIST {
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  // Signature header
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  UINT32                                    Signature;
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  // link to next Root Bridge whose PCI Feature configuration is
> > > > complete
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  LIST_ENTRY                                RootBridgeLink;
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  // EFI handle of the Root Bridge whose PCI feature configuration
> > is
> > > > > > > complete
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  EFI_HANDLE                                RootBridgeHandle;
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  // indication for complete re-enumeration of the PCI feature
> > > > > > configuration
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  BOOLEAN
> ReEnumeratePciFeatureConfiguration;
> > > > > > >
> > > > > > > +};
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +#define
> > > > > > > PCI_FEATURE_CONFIGURATION_COMPLETION_LIST_FROM_LINK(a)
> > \
> > > > > > >
> > > > > > > +  CR (a, PCI_FEATURE_CONFIGURATION_COMPLETION_LIST,
> > > > > > > RootBridgeLink, PCI_FEATURE_CONFIGURATION_SIGNATURE)
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +//
> > > > > > >
> > > > > > > +// Declaration of the internal sub-phases within the PCI Feature
> > > > > > > enumeration
> > > > > > >
> > > > > > > +//
> > > > > > >
> > > > > > > +typedef enum {
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  // initial phase in configuring the other PCI features to record the
> > > > primary
> > > > > > >
> > > > > > > +  // root ports
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  PciFeatureRootBridgeScan,
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  // get the PCI device-specific platform policies and align with
> > device
> > > > > > > capabilities
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  PciFeatureGetDevicePolicy,
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  // align all PCI nodes in the PCI heirarchical tree
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  PciFeatureSetupPhase,
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  // finally override to complete configuration of the PCI feature
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  PciFeatureConfigurationPhase,
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  // PCI feature configuration complete
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  PciFeatureConfigurationComplete
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +}PCI_FEATURE_CONFIGURATION_PHASE;
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +/**
> > > > > > >
> > > > > > > +  Main routine to indicate platform selection of any of the other PCI
> > > > > > features
> > > > > > >
> > > > > > > +  to be configured by this driver
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @retval TRUE    platform has selected the other PCI features to be
> > > > > > > configured
> > > > > > >
> > > > > > > +          FALSE   platform has not selected any of the other PCI
> > features
> > > > > > >
> > > > > > > +**/
> > > > > > >
> > > > > > > +BOOLEAN
> > > > > > >
> > > > > > > +CheckOtherPciFeaturesPcd (
> > > > > > >
> > > > > > > +  );
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +/**
> > > > > > >
> > > > > > > +  Enumerate all the nodes of the specified root bridge or PCI-PCI
> > > > Bridge, to
> > > > > > >
> > > > > > > +  configure the other PCI features.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @param RootBridge          A pointer to the PCI_IO_DEVICE.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @retval EFI_SUCCESS           The other PCI features configuration
> > > > during
> > > > > > > enumeration
> > > > > > >
> > > > > > > +                                of all the nodes of the PCI root bridge instance
> > were
> > > > > > >
> > > > > > > +                                programmed in PCI-compliance pattern along with
> > the
> > > > > > >
> > > > > > > +                                device-specific policy, as applicable.
> > > > > > >
> > > > > > > +  @retval EFI_UNSUPPORTED       One of the override operation
> > maong
> > > > the
> > > > > > > nodes of
> > > > > > >
> > > > > > > +                                the PCI hierarchy resulted in a incompatible
> > address
> > > > > > >
> > > > > > > +                                range.
> > > > > > >
> > > > > > > +  @retval EFI_INVALID_PARAMETER The override operation is
> > > > performed
> > > > > > > with invalid input
> > > > > > >
> > > > > > > +                                parameters.
> > > > > > >
> > > > > > > +**/
> > > > > > >
> > > > > > > +EFI_STATUS
> > > > > > >
> > > > > > > +EnumerateOtherPciFeatures (
> > > > > > >
> > > > > > > +  IN PCI_IO_DEVICE           *RootBridge
> > > > > > >
> > > > > > > +  );
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +/**
> > > > > > >
> > > > > > > +  This routine is invoked from the Stop () interface for the EFI
> > handle of
> > > > > > the
> > > > > > >
> > > > > > > +  RootBridge. Free up its node of type
> > > > > > > PCI_FEATURE_CONFIGURATION_COMPLETION_LIST.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @param  RootBridge      A pointer to the PCI_IO_DEVICE
> > > > > > >
> > > > > > > +**/
> > > > > > >
> > > > > > > +VOID
> > > > > > >
> > > > > > > +DestroyRootBridgePciFeaturesConfigCompletionList (
> > > > > > >
> > > > > > > +  IN PCI_IO_DEVICE          *RootBridge
> > > > > > >
> > > > > > > +  );
> > > > > > >
> > > > > > > +#endif
> > > > > > >
> > > > > > > diff --git
> > a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> > > > > > > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> > > > > > > new file mode 100644
> > > > > > > index 0000000000..d94037d69a
> > > > > > > --- /dev/null
> > > > > > > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> > > > > > > @@ -0,0 +1,565 @@
> > > > > > > +/** @file
> > > > > > >
> > > > > > > +  This file encapsulate the usage of PCI Platform Protocol
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  This file define the necessary hooks used to obtain the platform
> > > > > > >
> > > > > > > +  level data and policies which could be used in the PCI
> > Enumeration
> > > > > > phases
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> > > > > > >
> > > > > > > +SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +**/
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +#include "PciPlatformSupport.h"
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +EFI_PCI_PLATFORM_PROTOCOL                     *mPciPlatformProtocol;
> > > > > > >
> > > > > > > +EFI_PCI_OVERRIDE_PROTOCOL                     *mPciOverrideProtocol;
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +EFI_PCI_PLATFORM_PROTOCOL2
> > *mPciPlatformProtocol2;
> > > > > > >
> > > > > > > +EFI_PCI_OVERRIDE_PROTOCOL2
> *mPciOverrideProtocol2;
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +/**
> > > > > > >
> > > > > > > +  This function retrieves the PCI Platform Protocol published by
> > > > platform
> > > > > > > driver
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +**/
> > > > > > >
> > > > > > > +VOID
> > > > > > >
> > > > > > > +GetPciPlatformProtocol (
> > > > > > >
> > > > > > > +  )
> > > > > > >
> > > > > > > +{
> > > > > > >
> > > > > > > +  mPciPlatformProtocol2 = NULL;
> > > > > > >
> > > > > > > +  gBS->LocateProtocol (
> > > > > > >
> > > > > > > +      &gEfiPciPlatformProtocol2Guid,
> > > > > > >
> > > > > > > +      NULL,
> > > > > > >
> > > > > > > +      (VOID **) &mPciPlatformProtocol2
> > > > > > >
> > > > > > > +  );
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  // If PCI Platform protocol doesn't exist, try to get Pci Override
> > > > Protocol.
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  if (mPciPlatformProtocol2 == NULL) {
> > > > > > >
> > > > > > > +    mPciOverrideProtocol2 = NULL;
> > > > > > >
> > > > > > > +    gBS->LocateProtocol (
> > > > > > >
> > > > > > > +        &gEfiPciOverrideProtocol2Guid,
> > > > > > >
> > > > > > > +        NULL,
> > > > > > >
> > > > > > > +        (VOID **) &mPciOverrideProtocol2
> > > > > > >
> > > > > > > +    );
> > > > > > >
> > > > > > > +  }
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  // fetch the old PCI Platform Protocols if new are not installed
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  if (mPciOverrideProtocol2 == NULL) {
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +    mPciPlatformProtocol = NULL;
> > > > > > >
> > > > > > > +    gBS->LocateProtocol (
> > > > > > >
> > > > > > > +        &gEfiPciPlatformProtocolGuid,
> > > > > > >
> > > > > > > +        NULL,
> > > > > > >
> > > > > > > +        (VOID **) &mPciPlatformProtocol
> > > > > > >
> > > > > > > +    );
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +    //
> > > > > > >
> > > > > > > +    // If PCI Platform protocol doesn't exist, try to  get Pci Override
> > > > Protocol.
> > > > > > >
> > > > > > > +    //
> > > > > > >
> > > > > > > +    if (mPciPlatformProtocol == NULL) {
> > > > > > >
> > > > > > > +      mPciOverrideProtocol = NULL;
> > > > > > >
> > > > > > > +      gBS->LocateProtocol (
> > > > > > >
> > > > > > > +          &gEfiPciOverrideProtocolGuid,
> > > > > > >
> > > > > > > +          NULL,
> > > > > > >
> > > > > > > +          (VOID **) &mPciOverrideProtocol
> > > > > > >
> > > > > > > +      );
> > > > > > >
> > > > > > > +    }
> > > > > > >
> > > > > > > +  }
> > > > > > >
> > > > > > > +}
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +/**
> > > > > > >
> > > > > > > +  This function indicates the presence of PCI Platform driver
> > > > > > >
> > > > > > > +  @retval     TRUE or FALSE
> > > > > > >
> > > > > > > +**/
> > > > > > >
> > > > > > > +BOOLEAN
> > > > > > >
> > > > > > > +CheckPciPlatformProtocolInstall (
> > > > > > >
> > > > > > > +  )
> > > > > > >
> > > > > > > +{
> > > > > > >
> > > > > > > +  if (mPciPlatformProtocol2 != NULL) {
> > > > > > >
> > > > > > > +    return TRUE;
> > > > > > >
> > > > > > > +  } else if (mPciOverrideProtocol2 != NULL) {
> > > > > > >
> > > > > > > +    return TRUE;
> > > > > > >
> > > > > > > +  } else {
> > > > > > >
> > > > > > > +    if (mPciPlatformProtocol != NULL) {
> > > > > > >
> > > > > > > +      return TRUE;
> > > > > > >
> > > > > > > +    } else if (mPciOverrideProtocol != NULL){
> > > > > > >
> > > > > > > +      return TRUE;
> > > > > > >
> > > > > > > +    }
> > > > > > >
> > > > > > > +  }
> > > > > > >
> > > > > > > +  return FALSE;
> > > > > > >
> > > > > > > +}
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +/**
> > > > > > >
> > > > > > > +  Provides the hooks from the PCI bus driver to every PCI controller
> > > > > > > (device/function) at various
> > > > > > >
> > > > > > > +  stages of the PCI enumeration process that allow the host bridge
> > > > driver
> > > > > > to
> > > > > > > preinitialize individual
> > > > > > >
> > > > > > > +  PCI controllers before enumeration.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  This function is called during the PCI enumeration process. No
> > specific
> > > > > > > action is expected from this
> > > > > > >
> > > > > > > +  member function. It allows the host bridge driver to preinitialize
> > > > > > individual
> > > > > > > PCI controllers before
> > > > > > >
> > > > > > > +  enumeration.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @param[in] HostBridgeHandle     The associated PCI host bridge
> > > > handle.
> > > > > > >
> > > > > > > +  @param[in] RootBridgeHandle     The associated PCI root bridge
> > > > handle.
> > > > > > >
> > > > > > > +  @param[in] RootBridgePciAddress The address of the PCI device
> > on
> > > > the
> > > > > > > PCI bus.
> > > > > > >
> > > > > > > +  @param[in] Phase          The phase of the PCI controller
> > enumeration.
> > > > > > >
> > > > > > > +  @param[in] ExecPhase      Defines the execution phase of the PCI
> > > > chipset
> > > > > > > driver.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @retval    Status         returns the status from the PCI Platform
> > > > protocol as
> > > > > > is
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +**/
> > > > > > >
> > > > > > > +EFI_STATUS
> > > > > > >
> > > > > > > +PciPlatformPreprocessController (
> > > > > > >
> > > > > > > +  IN EFI_HANDLE                                    HostBridgeHandle,
> > > > > > >
> > > > > > > +  IN EFI_HANDLE                                    RootBridgeHandle,
> > > > > > >
> > > > > > > +  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS
> > > > > > > RootBridgePciAddress,
> > > > > > >
> > > > > > > +  IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE
> > Phase,
> > > > > > >
> > > > > > > +  IN EFI_PCI_EXECUTION_PHASE                       ExecPhase
> > > > > > >
> > > > > > > +  )
> > > > > > >
> > > > > > > +{
> > > > > > >
> > > > > > > +  EFI_STATUS  Status;
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  if (mPciPlatformProtocol2 != NULL) {
> > > > > > >
> > > > > > > +    //
> > > > > > >
> > > > > > > +    // Call PlatformPci::PrepController() if the protocol is present.
> > > > > > >
> > > > > > > +    //
> > > > > > >
> > > > > > > +    Status = mPciPlatformProtocol2->PlatformPrepController (
> > > > > > >
> > > > > > > +
> > > > > > > (EFI_PCI_PLATFORM_PROTOCOL*)mPciPlatformProtocol2,
> > > > > > >
> > > > > > > +                                      HostBridgeHandle,
> > > > > > >
> > > > > > > +                                      RootBridgeHandle,
> > > > > > >
> > > > > > > +                                      RootBridgePciAddress,
> > > > > > >
> > > > > > > +                                      Phase,
> > > > > > >
> > > > > > > +                                      ExecPhase
> > > > > > >
> > > > > > > +                                    );
> > > > > > >
> > > > > > > +  } else if (mPciOverrideProtocol2 != NULL) {
> > > > > > >
> > > > > > > +    //
> > > > > > >
> > > > > > > +    // Call PlatformPci::PrepController() if the protocol is present.
> > > > > > >
> > > > > > > +    //
> > > > > > >
> > > > > > > +    Status = mPciOverrideProtocol2->PlatformPrepController (
> > > > > > >
> > > > > > > +
> > > > > > > (EFI_PCI_PLATFORM_PROTOCOL*)mPciOverrideProtocol2,
> > > > > > >
> > > > > > > +                                      HostBridgeHandle,
> > > > > > >
> > > > > > > +                                      RootBridgeHandle,
> > > > > > >
> > > > > > > +                                      RootBridgePciAddress,
> > > > > > >
> > > > > > > +                                      Phase,
> > > > > > >
> > > > > > > +                                      ExecPhase
> > > > > > >
> > > > > > > +                                    );
> > > > > > >
> > > > > > > +  } else {
> > > > > > >
> > > > > > > +    if (mPciPlatformProtocol != NULL) {
> > > > > > >
> > > > > > > +      //
> > > > > > >
> > > > > > > +      // Call PlatformPci::PrepController() if the protocol is present.
> > > > > > >
> > > > > > > +      //
> > > > > > >
> > > > > > > +      Status = mPciPlatformProtocol->PlatformPrepController (
> > > > > > >
> > > > > > > +                                      mPciPlatformProtocol,
> > > > > > >
> > > > > > > +                                      HostBridgeHandle,
> > > > > > >
> > > > > > > +                                      RootBridgeHandle,
> > > > > > >
> > > > > > > +                                      RootBridgePciAddress,
> > > > > > >
> > > > > > > +                                      Phase,
> > > > > > >
> > > > > > > +                                      ExecPhase
> > > > > > >
> > > > > > > +                                    );
> > > > > > >
> > > > > > > +    } else if (mPciOverrideProtocol != NULL) {
> > > > > > >
> > > > > > > +      //
> > > > > > >
> > > > > > > +      // Call PlatformPci::PrepController() if the protocol is present.
> > > > > > >
> > > > > > > +      //
> > > > > > >
> > > > > > > +      Status = mPciOverrideProtocol->PlatformPrepController (
> > > > > > >
> > > > > > > +                                      mPciOverrideProtocol,
> > > > > > >
> > > > > > > +                                      HostBridgeHandle,
> > > > > > >
> > > > > > > +                                      RootBridgeHandle,
> > > > > > >
> > > > > > > +                                      RootBridgePciAddress,
> > > > > > >
> > > > > > > +                                      Phase,
> > > > > > >
> > > > > > > +                                      ExecPhase
> > > > > > >
> > > > > > > +                                    );
> > > > > > >
> > > > > > > +    } else {
> > > > > > >
> > > > > > > +      //
> > > > > > >
> > > > > > > +      // return PCI Platform Protocol not found
> > > > > > >
> > > > > > > +      //
> > > > > > >
> > > > > > > +      return EFI_NOT_FOUND;
> > > > > > >
> > > > > > > +    }
> > > > > > >
> > > > > > > +  }
> > > > > > >
> > > > > > > +  return Status;
> > > > > > >
> > > > > > > +}
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +/**
> > > > > > >
> > > > > > > +  This function notifies the PCI Platform driver about the PCI host
> > > > bridge
> > > > > > > resource
> > > > > > >
> > > > > > > +  allocation phase and PCI execution phase.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @param[in]  HostBridge     The handle of the host bridge
> > controller.
> > > > > > >
> > > > > > > +  @param[in]  Phase          The phase of the PCI bus enumeration.
> > > > > > >
> > > > > > > +  @param[in]  ExecPhase      Defines the execution phase of the PCI
> > > > > > chipset
> > > > > > > driver.
> > > > > > >
> > > > > > > +  @retval     Status          returns the status from the PCI Platform
> > > > protocol
> > > > > > as
> > > > > > > is
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +**/
> > > > > > >
> > > > > > > +EFI_STATUS
> > > > > > >
> > > > > > > +PciPlatformNotifyPhase (
> > > > > > >
> > > > > > > +  IN  EFI_HANDLE                                      HostBridgeHandle,
> > > > > > >
> > > > > > > +  IN  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE
> > Phase,
> > > > > > >
> > > > > > > +  IN  EFI_PCI_EXECUTION_PHASE                         ExecPhase
> > > > > > >
> > > > > > > +  )
> > > > > > >
> > > > > > > +{
> > > > > > >
> > > > > > > +  EFI_STATUS  Status;
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  if ( mPciPlatformProtocol2 != NULL) {
> > > > > > >
> > > > > > > +    Status = mPciPlatformProtocol2->PlatformNotify (
> > > > > > >
> > > > > > > +
> > > > > > > (EFI_PCI_PLATFORM_PROTOCOL*)mPciPlatformProtocol2,
> > > > > > >
> > > > > > > +                                      HostBridgeHandle,
> > > > > > >
> > > > > > > +                                      Phase,
> > > > > > >
> > > > > > > +                                      ExecPhase
> > > > > > >
> > > > > > > +                                    );
> > > > > > >
> > > > > > > +  } else if ( mPciOverrideProtocol2 != NULL) {
> > > > > > >
> > > > > > > +    Status = mPciOverrideProtocol2->PlatformNotify (
> > > > > > >
> > > > > > > +
> > > > > > > (EFI_PCI_PLATFORM_PROTOCOL*)mPciOverrideProtocol2,
> > > > > > >
> > > > > > > +                                      HostBridgeHandle,
> > > > > > >
> > > > > > > +                                      Phase,
> > > > > > >
> > > > > > > +                                      ExecPhase
> > > > > > >
> > > > > > > +                                    );
> > > > > > >
> > > > > > > +  } else {
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +    if ( mPciPlatformProtocol != NULL) {
> > > > > > >
> > > > > > > +      Status = mPciPlatformProtocol->PlatformNotify (
> > > > > > >
> > > > > > > +                                      mPciPlatformProtocol,
> > > > > > >
> > > > > > > +                                      HostBridgeHandle,
> > > > > > >
> > > > > > > +                                      Phase,
> > > > > > >
> > > > > > > +                                      ExecPhase
> > > > > > >
> > > > > > > +                                    );
> > > > > > >
> > > > > > > +    } else if ( mPciOverrideProtocol != NULL){
> > > > > > >
> > > > > > > +      Status = mPciOverrideProtocol->PlatformNotify (
> > > > > > >
> > > > > > > +                                      mPciOverrideProtocol,
> > > > > > >
> > > > > > > +                                      HostBridgeHandle,
> > > > > > >
> > > > > > > +                                      Phase,
> > > > > > >
> > > > > > > +                                      ExecPhase
> > > > > > >
> > > > > > > +                                    );
> > > > > > >
> > > > > > > +    } else {
> > > > > > >
> > > > > > > +      //
> > > > > > >
> > > > > > > +      // return PCI Platform Protocol not found
> > > > > > >
> > > > > > > +      //
> > > > > > >
> > > > > > > +      return EFI_NOT_FOUND;
> > > > > > >
> > > > > > > +    }
> > > > > > >
> > > > > > > +  }
> > > > > > >
> > > > > > > +  return Status;
> > > > > > >
> > > > > > > +}
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +/**
> > > > > > >
> > > > > > > +  This function retrieves the PCI platform policy.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @param  PciPolicy     pointer to the legacy
> > > > EFI_PCI_PLATFORM_POLICY
> > > > > > >
> > > > > > > +  @retval Status        returns the status from the PCI Platform
> > protocol
> > > > as is
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +**/
> > > > > > >
> > > > > > > +EFI_STATUS
> > > > > > >
> > > > > > > +PciGetPlatformPolicy (
> > > > > > >
> > > > > > > +  OUT EFI_PCI_PLATFORM_POLICY *PciPolicy
> > > > > > >
> > > > > > > +  )
> > > > > > >
> > > > > > > +{
> > > > > > >
> > > > > > > +  EFI_STATUS  Status;
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  if ( mPciPlatformProtocol2 != NULL) {
> > > > > > >
> > > > > > > +      Status = mPciPlatformProtocol2->GetPlatformPolicy (
> > > > > > >
> > > > > > > +
> > > > > > > (EFI_PCI_PLATFORM_PROTOCOL*)mPciPlatformProtocol2,
> > > > > > >
> > > > > > > +                                        PciPolicy
> > > > > > >
> > > > > > > +                                      );
> > > > > > >
> > > > > > > +  } else if ( mPciOverrideProtocol2 != NULL) {
> > > > > > >
> > > > > > > +      Status = mPciOverrideProtocol2->GetPlatformPolicy (
> > > > > > >
> > > > > > > +
> > > > > > > (EFI_PCI_PLATFORM_PROTOCOL*)mPciOverrideProtocol2,
> > > > > > >
> > > > > > > +                                        PciPolicy
> > > > > > >
> > > > > > > +                                      );
> > > > > > >
> > > > > > > +  } else {
> > > > > > >
> > > > > > > +    if ( mPciPlatformProtocol != NULL) {
> > > > > > >
> > > > > > > +      Status = mPciPlatformProtocol->GetPlatformPolicy (
> > > > > > >
> > > > > > > +                                      mPciPlatformProtocol,
> > > > > > >
> > > > > > > +                                      PciPolicy
> > > > > > >
> > > > > > > +                                    );
> > > > > > >
> > > > > > > +    }
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +    if ( mPciOverrideProtocol != NULL) {
> > > > > > >
> > > > > > > +      Status = mPciOverrideProtocol->GetPlatformPolicy (
> > > > > > >
> > > > > > > +                                      mPciOverrideProtocol,
> > > > > > >
> > > > > > > +                                      PciPolicy
> > > > > > >
> > > > > > > +                                    );
> > > > > > >
> > > > > > > +    } else {
> > > > > > >
> > > > > > > +      //
> > > > > > >
> > > > > > > +      // return PCI Platform Protocol not found
> > > > > > >
> > > > > > > +      //
> > > > > > >
> > > > > > > +      return EFI_NOT_FOUND;
> > > > > > >
> > > > > > > +    }
> > > > > > >
> > > > > > > +  }
> > > > > > >
> > > > > > > +  return Status;
> > > > > > >
> > > > > > > +}
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +/**
> > > > > > >
> > > > > > > +  This function retrieves the Option ROM image and size from the
> > > > Platform.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  It uses the PCI_IO_DEVICE internal fields are used to store
> > OpROM
> > > > > > > image/size
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @param Controller     An EFI handle for the PCI bus controller.
> > > > > > >
> > > > > > > +  @param PciIoDevice    A PCI_IO_DEVICE pointer to the PCI IO
> > device
> > > > to
> > > > > > be
> > > > > > > registered.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @retval EFI_SUCCESS            The option ROM was available for this
> > > > device
> > > > > > > and loaded into memory.
> > > > > > >
> > > > > > > +  @retval EFI_NOT_FOUND          No option ROM was available for
> > this
> > > > > > device.
> > > > > > >
> > > > > > > +  @retval EFI_OUT_OF_RESOURCES   No memory was available to
> > load
> > > > the
> > > > > > > option ROM.
> > > > > > >
> > > > > > > +  @retval EFI_DEVICE_ERROR       An error occurred in obtaining the
> > > > option
> > > > > > > ROM.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +**/
> > > > > > >
> > > > > > > +EFI_STATUS
> > > > > > >
> > > > > > > +GetPlatformPciOptionRom (
> > > > > > >
> > > > > > > +  IN  EFI_HANDLE                    Controller,
> > > > > > >
> > > > > > > +  IN  PCI_IO_DEVICE                 *PciIoDevice
> > > > > > >
> > > > > > > +  )
> > > > > > >
> > > > > > > +{
> > > > > > >
> > > > > > > +  EFI_STATUS  Status;
> > > > > > >
> > > > > > > +  VOID        *PlatformOpRomBuffer;
> > > > > > >
> > > > > > > +  UINTN       PlatformOpRomSize;
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  if (mPciPlatformProtocol2 != NULL) {
> > > > > > >
> > > > > > > +    Status = mPciPlatformProtocol2->GetPciRom (
> > > > > > >
> > > > > > > +
> > > > > > > (EFI_PCI_PLATFORM_PROTOCOL*)mPciPlatformProtocol2,
> > > > > > >
> > > > > > > +                                      PciIoDevice->Handle,
> > > > > > >
> > > > > > > +                                      &PlatformOpRomBuffer,
> > > > > > >
> > > > > > > +                                      &PlatformOpRomSize
> > > > > > >
> > > > > > > +                                      );
> > > > > > >
> > > > > > > +  } else if (mPciOverrideProtocol2 != NULL) {
> > > > > > >
> > > > > > > +    Status = mPciOverrideProtocol2->GetPciRom (
> > > > > > >
> > > > > > > +
> > > > > > > (EFI_PCI_PLATFORM_PROTOCOL*)mPciOverrideProtocol2,
> > > > > > >
> > > > > > > +                                      PciIoDevice->Handle,
> > > > > > >
> > > > > > > +                                      &PlatformOpRomBuffer,
> > > > > > >
> > > > > > > +                                      &PlatformOpRomSize
> > > > > > >
> > > > > > > +                                      );
> > > > > > >
> > > > > > > +  } else {
> > > > > > >
> > > > > > > +    if (mPciPlatformProtocol != NULL) {
> > > > > > >
> > > > > > > +      Status = mPciPlatformProtocol->GetPciRom (
> > > > > > >
> > > > > > > +                                      mPciPlatformProtocol,
> > > > > > >
> > > > > > > +                                      PciIoDevice->Handle,
> > > > > > >
> > > > > > > +                                      &PlatformOpRomBuffer,
> > > > > > >
> > > > > > > +                                      &PlatformOpRomSize
> > > > > > >
> > > > > > > +                                      );
> > > > > > >
> > > > > > > +    } else if (mPciOverrideProtocol != NULL) {
> > > > > > >
> > > > > > > +      Status = mPciOverrideProtocol->GetPciRom (
> > > > > > >
> > > > > > > +                                        mPciOverrideProtocol,
> > > > > > >
> > > > > > > +                                        PciIoDevice->Handle,
> > > > > > >
> > > > > > > +                                        &PlatformOpRomBuffer,
> > > > > > >
> > > > > > > +                                        &PlatformOpRomSize
> > > > > > >
> > > > > > > +                                        );
> > > > > > >
> > > > > > > +    } else {
> > > > > > >
> > > > > > > +      //
> > > > > > >
> > > > > > > +      // return PCI Platform Protocol not found
> > > > > > >
> > > > > > > +      //
> > > > > > >
> > > > > > > +      return EFI_NOT_FOUND;
> > > > > > >
> > > > > > > +    }
> > > > > > >
> > > > > > > +  }
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  if (!EFI_ERROR (Status)) {
> > > > > > >
> > > > > > > +    PciIoDevice->EmbeddedRom    = FALSE;
> > > > > > >
> > > > > > > +    PciIoDevice->RomSize        = (UINT32)PlatformOpRomSize;
> > > > > > >
> > > > > > > +    PciIoDevice->PciIo.RomSize  = PlatformOpRomSize;
> > > > > > >
> > > > > > > +    PciIoDevice->PciIo.RomImage = PlatformOpRomBuffer;
> > > > > > >
> > > > > > > +  }
> > > > > > >
> > > > > > > +  return Status;
> > > > > > >
> > > > > > > +}
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +/**
> > > > > > >
> > > > > > > +  Helper routine to indicate whether the given PCI device specific
> > > > policy
> > > > > > > value
> > > > > > >
> > > > > > > +  dictates to override the Max_Payload_Size to a particular value,
> > or
> > > > set as
> > > > > > > per
> > > > > > >
> > > > > > > +  device capability.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @param  MPS     Input device-specific policy should be in terms of
> > > > type
> > > > > > >
> > > > > > > +                  EFI_PCI_CONF_MAX_PAYLOAD_SIZE
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @retval TRUE    Setup Max_Payload_Size as per device capability
> > > > > > >
> > > > > > > +          FALSE   override as per device-specific platform policy
> > > > > > >
> > > > > > > +**/
> > > > > > >
> > > > > > > +BOOLEAN
> > > > > > >
> > > > > > > +SetupMpsAsPerDeviceCapability (
> > > > > > >
> > > > > > > +  IN  UINT8                   MPS
> > > > > > >
> > > > > > > +)
> > > > > > >
> > > > > > > +{
> > > > > > >
> > > > > > > +  if ( MPS == EFI_PCI_CONF_MAX_PAYLOAD_SIZE_AUTO) {
> > > > > > >
> > > > > > > +    return TRUE;
> > > > > > >
> > > > > > > +  } else {
> > > > > > >
> > > > > > > +    return FALSE;
> > > > > > >
> > > > > > > +  }
> > > > > > >
> > > > > > > +}
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +/**
> > > > > > >
> > > > > > > +  Helper routine to indicate whether the given PCI device specific
> > > > policy
> > > > > > > value
> > > > > > >
> > > > > > > +  dictates to override the Max_Read_Req_Size to a particular value,
> > or
> > > > set
> > > > > > as
> > > > > > > per
> > > > > > >
> > > > > > > +  device capability.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @param  MRRS    Input device-specific policy should be in terms
> > of
> > > > type
> > > > > > >
> > > > > > > +                  EFI_PCI_CONF_MAX_READ_REQ_SIZE
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @retval TRUE    Setup Max_Read_Req_Size as per device
> > capability
> > > > > > >
> > > > > > > +          FALSE   override as per device-specific platform policy
> > > > > > >
> > > > > > > +**/
> > > > > > >
> > > > > > > +BOOLEAN
> > > > > > >
> > > > > > > +SetupMrrsAsPerDeviceCapability (
> > > > > > >
> > > > > > > +  IN  UINT8                   MRRS
> > > > > > >
> > > > > > > +)
> > > > > > >
> > > > > > > +{
> > > > > > >
> > > > > > > +  if ( MRRS == EFI_PCI_CONF_MAX_READ_REQ_SIZE_AUTO) {
> > > > > > >
> > > > > > > +    return TRUE;
> > > > > > >
> > > > > > > +  } else {
> > > > > > >
> > > > > > > +    return FALSE;
> > > > > > >
> > > > > > > +  }
> > > > > > >
> > > > > > > +}
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +/**
> > > > > > >
> > > > > > > +  Routine to translate the given device-specific platform policy from
> > > > type
> > > > > > >
> > > > > > > +  EFI_PCI_CONF_MAX_PAYLOAD_SIZE to HW-specific value, as per
> > PCI
> > > > > > Base
> > > > > > > Specification
> > > > > > >
> > > > > > > +  Revision 4.0; for the PCI feature Max_Payload_Size.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @param  MPS     Input device-specific policy should be in terms of
> > > > type
> > > > > > >
> > > > > > > +                  EFI_PCI_CONF_MAX_PAYLOAD_SIZE
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @retval         Range values for the Max_Payload_Size as defined in
> > the
> > > > > > PCI
> > > > > > >
> > > > > > > +                  Base Specification 4.0
> > > > > > >
> > > > > > > +**/
> > > > > > >
> > > > > > > +UINT8
> > > > > > >
> > > > > > > +TranslateMpsSetupValueToPci (
> > > > > > >
> > > > > > > +  IN  UINT8                   MPS
> > > > > > >
> > > > > > > +)
> > > > > > >
> > > > > > > +{
> > > > > > >
> > > > > > > +  switch (MPS) {
> > > > > > >
> > > > > > > +    case EFI_PCI_CONF_MAX_PAYLOAD_SIZE_128B:
> > > > > > >
> > > > > > > +      return PCIE_MAX_PAYLOAD_SIZE_128B;
> > > > > > >
> > > > > > > +    case EFI_PCI_CONF_MAX_PAYLOAD_SIZE_256B:
> > > > > > >
> > > > > > > +      return PCIE_MAX_PAYLOAD_SIZE_256B;
> > > > > > >
> > > > > > > +    case EFI_PCI_CONF_MAX_PAYLOAD_SIZE_512B:
> > > > > > >
> > > > > > > +      return PCIE_MAX_PAYLOAD_SIZE_512B;
> > > > > > >
> > > > > > > +    case EFI_PCI_CONF_MAX_PAYLOAD_SIZE_1024B:
> > > > > > >
> > > > > > > +      return PCIE_MAX_PAYLOAD_SIZE_1024B;
> > > > > > >
> > > > > > > +    case EFI_PCI_CONF_MAX_PAYLOAD_SIZE_2048B:
> > > > > > >
> > > > > > > +      return PCIE_MAX_PAYLOAD_SIZE_2048B;
> > > > > > >
> > > > > > > +    case EFI_PCI_CONF_MAX_PAYLOAD_SIZE_4096B:
> > > > > > >
> > > > > > > +      return PCIE_MAX_PAYLOAD_SIZE_4096B;
> > > > > > >
> > > > > > > +    default:
> > > > > > >
> > > > > > > +      return PCIE_MAX_PAYLOAD_SIZE_128B;
> > > > > > >
> > > > > > > +  }
> > > > > > >
> > > > > > > +}
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +/**
> > > > > > >
> > > > > > > +  Routine to translate the given device-specific platform policy from
> > > > type
> > > > > > >
> > > > > > > +  EFI_PCI_CONF_MAX_READ_REQ_SIZE to HW-specific value, as
> > per
> > > > PCI
> > > > > > > Base Specification
> > > > > > >
> > > > > > > +  Revision 4.0; for the PCI feature Max_Read_Req_Size.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @param  MRRS    Input device-specific policy should be in terms
> > of
> > > > type
> > > > > > >
> > > > > > > +                  EFI_PCI_CONF_MAX_READ_REQ_SIZE
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @retval         Range values for the Max_Read_Req_Size as defined
> > in
> > > > the
> > > > > > > PCI
> > > > > > >
> > > > > > > +                  Base Specification 4.0
> > > > > > >
> > > > > > > +**/
> > > > > > >
> > > > > > > +UINT8
> > > > > > >
> > > > > > > +TranslateMrrsSetupValueToPci (
> > > > > > >
> > > > > > > +  IN  UINT8                   MRRS
> > > > > > >
> > > > > > > +)
> > > > > > >
> > > > > > > +{
> > > > > > >
> > > > > > > +  switch (MRRS) {
> > > > > > >
> > > > > > > +    case EFI_PCI_CONF_MAX_READ_REQ_SIZE_128B:
> > > > > > >
> > > > > > > +      return PCIE_MAX_READ_REQ_SIZE_128B;
> > > > > > >
> > > > > > > +    case EFI_PCI_CONF_MAX_READ_REQ_SIZE_256B:
> > > > > > >
> > > > > > > +      return PCIE_MAX_READ_REQ_SIZE_256B;
> > > > > > >
> > > > > > > +    case EFI_PCI_CONF_MAX_READ_REQ_SIZE_512B:
> > > > > > >
> > > > > > > +      return PCIE_MAX_READ_REQ_SIZE_512B;
> > > > > > >
> > > > > > > +    case EFI_PCI_CONF_MAX_READ_REQ_SIZE_1024B:
> > > > > > >
> > > > > > > +      return PCIE_MAX_READ_REQ_SIZE_1024B;
> > > > > > >
> > > > > > > +    case EFI_PCI_CONF_MAX_READ_REQ_SIZE_2048B:
> > > > > > >
> > > > > > > +      return PCIE_MAX_READ_REQ_SIZE_2048B;
> > > > > > >
> > > > > > > +    case EFI_PCI_CONF_MAX_READ_REQ_SIZE_4096B:
> > > > > > >
> > > > > > > +      return PCIE_MAX_READ_REQ_SIZE_4096B;
> > > > > > >
> > > > > > > +    default:
> > > > > > >
> > > > > > > +      return PCIE_MAX_READ_REQ_SIZE_128B;
> > > > > > >
> > > > > > > +  }
> > > > > > >
> > > > > > > +}
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +/**
> > > > > > >
> > > > > > > +  Generic routine to setup the PCI features as per its
> > predetermined
> > > > > > > defaults.
> > > > > > >
> > > > > > > +**/
> > > > > > >
> > > > > > > +VOID
> > > > > > >
> > > > > > > +SetupDefaultsDevicePlatformPolicy (
> > > > > > >
> > > > > > > +  IN  PCI_IO_DEVICE               *PciDevice
> > > > > > >
> > > > > > > +  )
> > > > > > >
> > > > > > > +{
> > > > > > >
> > > > > > > +  PciDevice->SetupMPS =
> > EFI_PCI_CONF_MAX_PAYLOAD_SIZE_AUTO;
> > > > > > >
> > > > > > > +  PciDevice->SetupMRRS =
> > > > EFI_PCI_CONF_MAX_READ_REQ_SIZE_AUTO;
> > > > > > >
> > > > > > > +}
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +/**
> > > > > > >
> > > > > > > +  Intermediate routine to either get the PCI device specific
> > platform
> > > > > > policies
> > > > > > >
> > > > > > > +  through the PCI Platform Protocol, or its alias the PCI Override
> > > > Protocol.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @param  PciIoDevice         A pointer to PCI_IO_DEVICE
> > > > > > >
> > > > > > > +  @param  PciPlatformProtocol A pointer to
> > > > > > > EFI_PCI_PLATFORM_PROTOCOL2
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @retval EFI_STATUS          The direct status from the PCI Platform
> > > > Protocol
> > > > > > >
> > > > > > > +  @retval EFI_SUCCESS         if on returning predetermined PCI
> > features
> > > > > > > defaults,
> > > > > > >
> > > > > > > +                              for the case when protocol returns as
> > > > EFI_UNSUPPORTED
> > > > > > >
> > > > > > > +                              to indicate PCI device exist and it has no platform
> > > > > > >
> > > > > > > +                              policy defined.
> > > > > > >
> > > > > > > +**/
> > > > > > >
> > > > > > > +EFI_STATUS
> > > > > > >
> > > > > > > +GetPciDevicePlatformPolicyEx (
> > > > > > >
> > > > > > > +  IN  PCI_IO_DEVICE               *PciIoDevice,
> > > > > > >
> > > > > > > +  IN  EFI_PCI_PLATFORM_PROTOCOL2  *PciPlatformProtocol
> > > > > > >
> > > > > > > +  )
> > > > > > >
> > > > > > > +{
> > > > > > >
> > > > > > > +  EFI_PCI_PLATFORM_EXTENDED_POLICY
> > PciPlatformExtendedPolicy;
> > > > > > >
> > > > > > > +  EFI_STATUS                        Status;
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  ZeroMem ( &PciPlatformExtendedPolicy, sizeof
> > > > > > > (EFI_PCI_PLATFORM_EXTENDED_POLICY));
> > > > > > >
> > > > > > > +  Status = PciPlatformProtocol->GetDevicePolicy (
> > > > > > >
> > > > > > > +                                  PciPlatformProtocol,
> > > > > > >
> > > > > > > +                                  PciIoDevice->Handle,
> > > > > > >
> > > > > > > +                                  &PciPlatformExtendedPolicy
> > > > > > >
> > > > > > > +                                  );
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  // platform chipset policies are returned for this PCI device
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  if (!EFI_ERROR(Status)) {
> > > > > > >
> > > > > > > +    PciIoDevice->SetupMPS =
> > PciPlatformExtendedPolicy.DeviceCtlMPS;
> > > > > > >
> > > > > > > +    PciIoDevice->SetupMRRS =
> > > > PciPlatformExtendedPolicy.DeviceCtlMRRS;
> > > > > > >
> > > > > > > +  }
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  // platform chipset policies are not provided for this PCI device
> > > > > > >
> > > > > > > +  //
> > > > > > >
> > > > > > > +  if (EFI_ERROR(Status) == EFI_UNSUPPORTED) {
> > > > > > >
> > > > > > > +    //
> > > > > > >
> > > > > > > +    // let the enumeration happen as per the PCI standard way
> > > > > > >
> > > > > > > +    //
> > > > > > >
> > > > > > > +    SetupDefaultsDevicePlatformPolicy ( PciIoDevice);
> > > > > > >
> > > > > > > +    return EFI_SUCCESS;
> > > > > > >
> > > > > > > +  }
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  return Status;
> > > > > > >
> > > > > > > +}
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +/**
> > > > > > >
> > > > > > > +  Gets the PCI device-specific platform policy from the PCI Platform
> > > > > > Protocol.
> > > > > > >
> > > > > > > +  If no PCI Platform protocol is published than setup the PCI feature
> > to
> > > > > > > predetermined
> > > > > > >
> > > > > > > +  defaults, in order to align all the PCI devices in the PCI hierarchy,
> > as
> > > > > > > applicable.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @param  PciDevice     A pointer to PCI_IO_DEVICE
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @retval EFI_STATUS    The direct status from the PCI Platform
> > > > Protocol
> > > > > > >
> > > > > > > +  @retval EFI_SUCCESS   On return of predetermined PCI features
> > > > defaults,
> > > > > > > for
> > > > > > >
> > > > > > > +                        the case when protocol returns as EFI_UNSUPPORTED
> > to
> > > > > > >
> > > > > > > +                        indicate PCI device exist and it has no platform policy
> > > > > > >
> > > > > > > +                        defined. Also, on returns when no PCI Platform
> > Protocol
> > > > > > >
> > > > > > > +                        exist.
> > > > > > >
> > > > > > > +**/
> > > > > > >
> > > > > > > +EFI_STATUS
> > > > > > >
> > > > > > > +GetPciDevicePlatformPolicy (
> > > > > > >
> > > > > > > +  IN PCI_IO_DEVICE          *PciDevice
> > > > > > >
> > > > > > > +  )
> > > > > > >
> > > > > > > +{
> > > > > > >
> > > > > > > +  if ( mPciPlatformProtocol2 != NULL) {
> > > > > > >
> > > > > > > +    return GetPciDevicePlatformPolicyEx ( PciDevice,
> > > > > > mPciPlatformProtocol2);
> > > > > > >
> > > > > > > +  } else if (mPciOverrideProtocol2 != NULL) {
> > > > > > >
> > > > > > > +    return GetPciDevicePlatformPolicyEx ( PciDevice,
> > > > > > mPciOverrideProtocol2);
> > > > > > >
> > > > > > > +  } else {
> > > > > > >
> > > > > > > +    //
> > > > > > >
> > > > > > > +    // new PCI Platform Protocol 2 is not installed; let the
> > enumeration
> > > > > > > happen
> > > > > > >
> > > > > > > +    // as per PCI standard way
> > > > > > >
> > > > > > > +    //
> > > > > > >
> > > > > > > +    SetupDefaultsDevicePlatformPolicy ( PciDevice);
> > > > > > >
> > > > > > > +    return EFI_SUCCESS;
> > > > > > >
> > > > > > > +  }
> > > > > > >
> > > > > > > +}
> > > > > > >
> > > > > > > diff --git
> > a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
> > > > > > > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
> > > > > > > new file mode 100644
> > > > > > > index 0000000000..d54e46b950
> > > > > > > --- /dev/null
> > > > > > > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
> > > > > > > @@ -0,0 +1,193 @@
> > > > > > > +/** @file
> > > > > > >
> > > > > > > +  This file encapsulate the usage of PCI Platform Protocol
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  This file define the necessary hooks used to obtain the platform
> > > > > > >
> > > > > > > +  level data and policies which could be used in the PCI
> > Enumeration
> > > > > > phases
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> > > > > > >
> > > > > > > +SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +**/
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +#ifndef _EFI_PCI_PLATFORM_SUPPORT_H_
> > > > > > >
> > > > > > > +#define _EFI_PCI_PLATFORM_SUPPORT_H_
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +#include "PciBus.h"
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +/**
> > > > > > >
> > > > > > > +  This function retrieves the PCI Platform Protocol published by
> > > > platform
> > > > > > > driver
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +**/
> > > > > > >
> > > > > > > +VOID
> > > > > > >
> > > > > > > +GetPciPlatformProtocol (
> > > > > > >
> > > > > > > +  );
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +/**
> > > > > > >
> > > > > > > +  This function indicates the presence of PCI Platform driver
> > > > > > >
> > > > > > > +  @retval     TRUE or FALSE
> > > > > > >
> > > > > > > +**/
> > > > > > >
> > > > > > > +BOOLEAN
> > > > > > >
> > > > > > > +CheckPciPlatformProtocolInstall (
> > > > > > >
> > > > > > > +  );
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +/**
> > > > > > >
> > > > > > > +  Provides the hooks from the PCI bus driver to every PCI controller
> > > > > > > (device/function) at various
> > > > > > >
> > > > > > > +  stages of the PCI enumeration process that allow the host bridge
> > > > driver
> > > > > > to
> > > > > > > preinitialize individual
> > > > > > >
> > > > > > > +  PCI controllers before enumeration.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  This function is called during the PCI enumeration process. No
> > specific
> > > > > > > action is expected from this
> > > > > > >
> > > > > > > +  member function. It allows the host bridge driver to preinitialize
> > > > > > individual
> > > > > > > PCI controllers before
> > > > > > >
> > > > > > > +  enumeration.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @param[in] HostBridgeHandle     The associated PCI host bridge
> > > > handle.
> > > > > > >
> > > > > > > +  @param[in] RootBridgeHandle     The associated PCI root bridge
> > > > handle.
> > > > > > >
> > > > > > > +  @param[in] RootBridgePciAddress The address of the PCI device
> > on
> > > > the
> > > > > > > PCI bus.
> > > > > > >
> > > > > > > +  @param[in] Phase          The phase of the PCI controller
> > enumeration.
> > > > > > >
> > > > > > > +  @param[in] ExecPhase      Defines the execution phase of the PCI
> > > > chipset
> > > > > > > driver.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @retval    Status         returns the status from the PCI Platform
> > > > protocol as
> > > > > > is
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +**/
> > > > > > >
> > > > > > > +EFI_STATUS
> > > > > > >
> > > > > > > +PciPlatformPreprocessController (
> > > > > > >
> > > > > > > +  IN EFI_HANDLE                                    HostBridgeHandle,
> > > > > > >
> > > > > > > +  IN EFI_HANDLE                                    RootBridgeHandle,
> > > > > > >
> > > > > > > +  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS
> > > > > > > RootBridgePciAddress,
> > > > > > >
> > > > > > > +  IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE
> > Phase,
> > > > > > >
> > > > > > > +  IN EFI_PCI_EXECUTION_PHASE                       ExecPhase
> > > > > > >
> > > > > > > +  );
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +/**
> > > > > > >
> > > > > > > +  This function notifies the PCI Platform driver about the PCI host
> > > > bridge
> > > > > > > resource
> > > > > > >
> > > > > > > +  allocation phase and PCI execution phase.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @param[in]  HostBridge     The handle of the host bridge
> > controller.
> > > > > > >
> > > > > > > +  @param[in]  Phase          The phase of the PCI bus enumeration.
> > > > > > >
> > > > > > > +  @param[in]  ExecPhase      Defines the execution phase of the PCI
> > > > > > chipset
> > > > > > > driver.
> > > > > > >
> > > > > > > +  @retval     Status          returns the status from the PCI Platform
> > > > protocol
> > > > > > as
> > > > > > > is
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +**/
> > > > > > >
> > > > > > > +EFI_STATUS
> > > > > > >
> > > > > > > +PciPlatformNotifyPhase (
> > > > > > >
> > > > > > > +  IN  EFI_HANDLE                                      HostBridgeHandle,
> > > > > > >
> > > > > > > +  IN  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE
> > Phase,
> > > > > > >
> > > > > > > +  IN  EFI_PCI_EXECUTION_PHASE                         ExecPhase
> > > > > > >
> > > > > > > +  );
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +/**
> > > > > > >
> > > > > > > +  This function retrieves the PCI platform policy.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @param  PciPolicy     pointer to the legacy
> > > > EFI_PCI_PLATFORM_POLICY
> > > > > > >
> > > > > > > +  @retval Status        returns the status from the PCI Platform
> > protocol
> > > > as is
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +**/
> > > > > > >
> > > > > > > +EFI_STATUS
> > > > > > >
> > > > > > > +PciGetPlatformPolicy (
> > > > > > >
> > > > > > > +  OUT EFI_PCI_PLATFORM_POLICY *PciPolicy
> > > > > > >
> > > > > > > +  );
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +/**
> > > > > > >
> > > > > > > +  This function retrieves the Option ROM image and size from the
> > > > Platform.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  It uses the PCI_IO_DEVICE internal fields are used to store
> > OpROM
> > > > > > > image/size
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @param Controller     An EFI handle for the PCI bus controller.
> > > > > > >
> > > > > > > +  @param PciIoDevice    A PCI_IO_DEVICE pointer to the PCI IO
> > device
> > > > to
> > > > > > be
> > > > > > > registered.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @retval EFI_SUCCESS            The option ROM was available for this
> > > > device
> > > > > > > and loaded into memory.
> > > > > > >
> > > > > > > +  @retval EFI_NOT_FOUND          No option ROM was available for
> > this
> > > > > > device.
> > > > > > >
> > > > > > > +  @retval EFI_OUT_OF_RESOURCES   No memory was available to
> > load
> > > > the
> > > > > > > option ROM.
> > > > > > >
> > > > > > > +  @retval EFI_DEVICE_ERROR       An error occurred in obtaining the
> > > > option
> > > > > > > ROM.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +**/
> > > > > > >
> > > > > > > +EFI_STATUS
> > > > > > >
> > > > > > > +GetPlatformPciOptionRom (
> > > > > > >
> > > > > > > +  IN  EFI_HANDLE                    Controller,
> > > > > > >
> > > > > > > +  IN  PCI_IO_DEVICE                 *PciIoDevice
> > > > > > >
> > > > > > > +  );
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +/**
> > > > > > >
> > > > > > > +  Gets the PCI device-specific platform policy from the PCI Platform
> > > > > > Protocol.
> > > > > > >
> > > > > > > +  If no PCI Platform protocol is published than setup the PCI feature
> > to
> > > > > > > predetermined
> > > > > > >
> > > > > > > +  defaults, in order to align all the PCI devices in the PCI hierarchy,
> > as
> > > > > > > applicable.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @param  PciDevice     A pointer to PCI_IO_DEVICE
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @retval EFI_STATUS    The direct status from the PCI Platform
> > > > Protocol
> > > > > > >
> > > > > > > +  @retval EFI_SUCCESS   On return of predetermined PCI features
> > > > defaults,
> > > > > > > for
> > > > > > >
> > > > > > > +                        the case when protocol returns as EFI_UNSUPPORTED
> > to
> > > > > > >
> > > > > > > +                        indicate PCI device exist and it has no platform policy
> > > > > > >
> > > > > > > +                        defined. Also, on returns when no PCI Platform
> > Protocol
> > > > > > >
> > > > > > > +                        exist.
> > > > > > >
> > > > > > > +**/
> > > > > > >
> > > > > > > +EFI_STATUS
> > > > > > >
> > > > > > > +GetPciDevicePlatformPolicy (
> > > > > > >
> > > > > > > +  IN PCI_IO_DEVICE          *PciDevice
> > > > > > >
> > > > > > > +  );
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +/**
> > > > > > >
> > > > > > > +  Helper routine to indicate whether the given PCI device specific
> > > > policy
> > > > > > > value
> > > > > > >
> > > > > > > +  dictates to override the Max_Payload_Size to a particular value,
> > or
> > > > set as
> > > > > > > per
> > > > > > >
> > > > > > > +  device capability.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @param  MPS     Input device-specific policy should be in terms of
> > > > type
> > > > > > >
> > > > > > > +                  EFI_PCI_CONF_MAX_PAYLOAD_SIZE
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @retval TRUE    Setup Max_Payload_Size as per device capability
> > > > > > >
> > > > > > > +          FALSE   override as per device-specific platform policy
> > > > > > >
> > > > > > > +**/
> > > > > > >
> > > > > > > +BOOLEAN
> > > > > > >
> > > > > > > +SetupMpsAsPerDeviceCapability (
> > > > > > >
> > > > > > > +  IN  UINT8                   MPS
> > > > > > >
> > > > > > > +);
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +/**
> > > > > > >
> > > > > > > +  Helper routine to indicate whether the given PCI device specific
> > > > policy
> > > > > > > value
> > > > > > >
> > > > > > > +  dictates to override the Max_Read_Req_Size to a particular value,
> > or
> > > > set
> > > > > > as
> > > > > > > per
> > > > > > >
> > > > > > > +  device capability.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @param  MRRS    Input device-specific policy should be in terms
> > of
> > > > type
> > > > > > >
> > > > > > > +                  EFI_PCI_CONF_MAX_READ_REQ_SIZE
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @retval TRUE    Setup Max_Read_Req_Size as per device
> > capability
> > > > > > >
> > > > > > > +          FALSE   override as per device-specific platform policy
> > > > > > >
> > > > > > > +**/
> > > > > > >
> > > > > > > +BOOLEAN
> > > > > > >
> > > > > > > +SetupMrrsAsPerDeviceCapability (
> > > > > > >
> > > > > > > +  IN  UINT8                   MRRS
> > > > > > >
> > > > > > > +);
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +/**
> > > > > > >
> > > > > > > +  Routine to translate the given device-specific platform policy from
> > > > type
> > > > > > >
> > > > > > > +  EFI_PCI_CONF_MAX_PAYLOAD_SIZE to HW-specific value, as per
> > PCI
> > > > > > Base
> > > > > > > Specification
> > > > > > >
> > > > > > > +  Revision 4.0; for the PCI feature Max_Payload_Size.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @param  MPS     Input device-specific policy should be in terms of
> > > > type
> > > > > > >
> > > > > > > +                  EFI_PCI_CONF_MAX_PAYLOAD_SIZE
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @retval         Range values for the Max_Payload_Size as defined in
> > the
> > > > > > PCI
> > > > > > >
> > > > > > > +                  Base Specification 4.0
> > > > > > >
> > > > > > > +**/
> > > > > > >
> > > > > > > +UINT8
> > > > > > >
> > > > > > > +TranslateMpsSetupValueToPci (
> > > > > > >
> > > > > > > +  IN  UINT8                   MPS
> > > > > > >
> > > > > > > +);
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +/**
> > > > > > >
> > > > > > > +  Routine to translate the given device-specific platform policy from
> > > > type
> > > > > > >
> > > > > > > +  EFI_PCI_CONF_MAX_READ_REQ_SIZE to HW-specific value, as
> > per
> > > > PCI
> > > > > > > Base Specification
> > > > > > >
> > > > > > > +  Revision 4.0; for the PCI feature Max_Read_Req_Size.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @param  MRRS    Input device-specific policy should be in terms
> > of
> > > > type
> > > > > > >
> > > > > > > +                  EFI_PCI_CONF_MAX_READ_REQ_SIZE
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > > +  @retval         Range values for the Max_Read_Req_Size as defined
> > in
> > > > the
> > > > > > > PCI
> > > > > > >
> > > > > > > +                  Base Specification 4.0
> > > > > > >
> > > > > > > +**/
> > > > > > >
> > > > > > > +UINT8
> > > > > > >
> > > > > > > +TranslateMrrsSetupValueToPci (
> > > > > > >
> > > > > > > +  IN  UINT8                   MRRS
> > > > > > >
> > > > > > > +);
> > > > > > >
> > > > > > > +#endif
> > > > > > >
> > > > > > > diff --git
> > a/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c
> > > > > > > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c
> > > > > > > index 4969ee0f64..755423f77b 100644
> > > > > > > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c
> > > > > > > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c
> > > > > > > @@ -198,20 +198,7 @@ CalculateApertureIo16 (
> > > > > > >      //
> > > > > > >
> > > > > > >      Status = EFI_NOT_FOUND;
> > > > > > >
> > > > > > >      PciPolicy = 0;
> > > > > > >
> > > > > > > -    if (gPciPlatformProtocol != NULL) {
> > > > > > >
> > > > > > > -      Status = gPciPlatformProtocol->GetPlatformPolicy (
> > > > > > >
> > > > > > > -                                       gPciPlatformProtocol,
> > > > > > >
> > > > > > > -                                       &PciPolicy
> > > > > > >
> > > > > > > -                                       );
> > > > > > >
> > > > > > > -    }
> > > > > > >
> > > > > > > -
> > > > > > >
> > > > > > > -    if (EFI_ERROR (Status) && gPciOverrideProtocol != NULL) {
> > > > > > >
> > > > > > > -      Status = gPciOverrideProtocol->GetPlatformPolicy (
> > > > > > >
> > > > > > > -                                       gPciOverrideProtocol,
> > > > > > >
> > > > > > > -                                       &PciPolicy
> > > > > > >
> > > > > > > -                                       );
> > > > > > >
> > > > > > > -    }
> > > > > > >
> > > > > > > -
> > > > > > >
> > > > > > > +    Status = PciGetPlatformPolicy ( &PciPolicy);
> > > > > > >
> > > > > > >      if (!EFI_ERROR (Status)) {
> > > > > > >
> > > > > > >        if ((PciPolicy & EFI_RESERVE_ISA_IO_ALIAS) != 0) {
> > > > > > >
> > > > > > >          mReserveIsaAliases = TRUE;
> > > > > > >
> > > > > > > diff --git a/MdeModulePkg/MdeModulePkg.dec
> > > > > > > b/MdeModulePkg/MdeModulePkg.dec
> > > > > > > index 17beb45235..7bcbe5a3ea 100644
> > > > > > > --- a/MdeModulePkg/MdeModulePkg.dec
> > > > > > > +++ b/MdeModulePkg/MdeModulePkg.dec
> > > > > > > @@ -1026,6 +1026,16 @@
> > > > > > >    # @Prompt Enable UEFI Stack Guard.
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > >
> > > >
> > gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard|FALSE|BOOLEAN|0
> > > > > > > x30001055
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > > +  ## This PCD is to indicate the PCI Bus driver to setup other new
> > PCI
> > > > > > > features.
> > > > > > >
> > > > > > > +  #  Each PCI feature is represented by its mask bit position and it
> > > > > > configures
> > > > > > >
> > > > > > > +  #  if that bit is set.
> > > > > > >
> > > > > > > +  #
> > > > > > >
> > > > > > > +  #   Bit 0 - if set, the PCI Bus driver programs the device's
> > > > > > > Max_Payload_Size.<BR>
> > > > > > >
> > > > > > > +  #   Bit 1 - if set, the PCI Bus driver programs the device's
> > > > > > > Max_Read_Req_Size.<BR>
> > > > > > >
> > > > > > > +  #   Bit 2 to 31 - Reserved for future use by the PCI Bus driver.<BR>
> > > > > > >
> > > > > > > +  # @Prompt The UEFI PCU Bus driver enables the new set of other
> > PCI
> > > > > > > Features.
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > >
> > > >
> > gEfiMdeModulePkgTokenSpaceGuid.PcdOtherPciFeatures|0x00000003|UIN
> > > > > > > T32|0x30001056
> > > > > > >
> > > > > > > +
> > > > > > >
> > > > > > >  [PcdsFixedAtBuild, PcdsPatchableInModule]
> > > > > > >
> > > > > > >    ## Dynamic type PCD can be registered callback function for Pcd
> > > > setting
> > > > > > > action.
> > > > > > >
> > > > > > >    #  PcdMaxPeiPcdCallBackNumberPerPcdEntry indicates the
> > maximum
> > > > > > > number of callback function
> > > > > > >
> > > > > > > --
> > > > > > > 2.21.0.windows.1


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

View/Reply Online (#48995): https://edk2.groups.io/g/devel/message/48995
Mute This Topic: https://groups.io/mt/34264504/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub  [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-