References:-
https://bugzilla.tianocore.org/show_bug.cgi?id=1954
https://bugzilla.tianocore.org/show_bug.cgi?id=2194
https://bugzilla.tianocore.org/show_bug.cgi?id=2313
https://bugzilla.tianocore.org/show_bug.cgi?id=2499
https://bugzilla.tianocore.org/show_bug.cgi?id=2500
This code change represents the preparation of common code setup for the
new PCI Express features initialization, utilizing the new PCI Express
Platform / Override Protocol.
The new set of source files are as follows:-
new file: /PciFeatureSupport.c
new file: /PciFeatureSupport.h
new file: /PciPlatformSupport.c
new file: /PciPlatformSupport.h
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 | 6 +++++-
MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h | 12 ++++++++++--
MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf | 9 ++++++++-
MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c | 12 +++++++++++-
MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c | 891 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h | 226 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c | 302 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
8 files changed, 1540 insertions(+), 5 deletions(-)
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c
index b020ce5..714101c 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 - 2020, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -284,6 +284,10 @@ PciBusDriverBindingStart (
(VOID **) &gPciOverrideProtocol
);
}
+ //
+ // get the PCI Express Protocol or the PCI Express Override Protocol
+ //
+ GetPciExpressProtocol ();
if (mIoMmuProtocol == NULL) {
gBS->LocateProtocol (
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
index 504a1b1..225229d 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
@@ -1,7 +1,7 @@
/** @file
Header files and data structures needed by PCI Bus module.
-Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2020, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -42,6 +42,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <IndustryStandard/Pci.h>
#include <IndustryStandard/PeImage.h>
#include <IndustryStandard/Acpi.h>
+#include <Protocol/PciExpressOverride.h>
+#include <Protocol/PciExpressPlatform.h>
typedef struct _PCI_IO_DEVICE PCI_IO_DEVICE;
typedef struct _PCI_BAR PCI_BAR;
@@ -79,6 +81,8 @@ typedef enum {
#include "PciPowerManagement.h"
#include "PciHotPlugSupport.h"
#include "PciLib.h"
+#include "PciPlatformSupport.h"
+#include "PciFeatureSupport.h"
#define VGABASE1 0x3B0
#define VGALIMIT1 0x3BB
@@ -263,9 +267,13 @@ struct _PCI_IO_DEVICE {
BOOLEAN IsPciExp;
//
- // For SR-IOV
+ // For PCI Express Capability List Structure
//
UINT8 PciExpressCapabilityOffset;
+ PCI_CAPABILITY_PCIEXP PciExpressCapabilityStructure;
+ //
+ // For SR-IOV
+ //
UINT32 AriCapabilityOffset;
UINT32 SrIovCapabilityOffset;
UINT32 MrIovCapabilityOffset;
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
index 05c2202..f06b411 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 - 2020, 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,9 @@
gEfiLoadFile2ProtocolGuid ## SOMETIMES_PRODUCES
gEdkiiIoMmuProtocolGuid ## SOMETIMES_CONSUMES
gEfiLoadedImageDevicePathProtocolGuid ## CONSUMES
+ gEfiPciExpressPlatformProtocolGuid ## SOMETIMES_CONSUMES
+ gEfiPciExpressOverrideProtocolGuid ## SOMETIMES_CONSUMES
+
[FeaturePcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdPciBusHotplugDeviceSupport ## CONSUMES
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
index c7eafff..c9e52ea 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
@@ -1,7 +1,7 @@
/** @file
PCI emumeration support functions implementation for PCI Bus module.
-Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2020, Intel Corporation. All rights reserved.<BR>
(C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -2154,6 +2154,16 @@ CreatePciIoDevice (
);
if (!EFI_ERROR (Status)) {
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->PciExpressCapabilityStructure
+ );
}
if (PcdGetBool (PcdAriSupport)) {
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
new file mode 100644
index 0000000..3980a8e
--- /dev/null
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
@@ -0,0 +1,891 @@
+/** @file
+ PCI standard feature support functions implementation for PCI Bus module..
+
+Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "PciBus.h"
+#include "PciFeatureSupport.h"
+
+/**
+ Hold the current instance of Root Bridge IO protocol Handle
+**/
+EFI_HANDLE mRootBridgeHandle;
+
+/**
+ A gobal pointer to BRIDGE_DEVICE_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
+**/
+LIST_ENTRY mRootBridgeDeviceList;
+
+/**
+ global list to indicate the supported PCI Express features of this driver, it
+ is expected to be overridden based on the platform request
+**/
+EFI_PCI_EXPRESS_PLATFORM_POLICY mPciExpressPlatformPolicy = {
+ //
+ // support for PCI Express feature - Max. Payload Size
+ //
+ FALSE,
+ //
+ // support for PCI Express feature - Max. Read Request Size
+ //
+ FALSE,
+ //
+ // support for PCI Express feature - Extended Tag
+ //
+ FALSE,
+ //
+ // support for PCI Express feature - Relax Order
+ //
+ FALSE,
+ //
+ // support for PCI Express feature - No-Snoop
+ //
+ FALSE,
+ //
+ // support for PCI Express feature - ASPM state
+ //
+ FALSE,
+ //
+ // support for PCI Express feature - Common Clock Configuration
+ //
+ FALSE,
+ //
+ // support for PCI Express feature - Extended Sync
+ //
+ FALSE,
+ //
+ // support for PCI Express feature - Atomic Op
+ //
+ FALSE,
+ //
+ // support for PCI Express feature - LTR
+ //
+ FALSE,
+ //
+ // support for PCI Express feature - PTM
+ //
+ FALSE,
+ //
+ // support for PCI Express feature - Completion Timeout
+ //
+ FALSE,
+ //
+ // support for PCI Express feature - Clock Power Management
+ //
+ FALSE,
+ //
+ // support for PCI Express feature - L1 PM Substates
+ //
+ FALSE
+};
+
+//
+// indicates the driver has completed query to platform on the list of supported
+// PCI features to be configured
+//
+BOOLEAN mPciExpressGetPlatformPolicyComplete = FALSE;
+
+//
+// PCI Express feature initialization phase handle routines
+//
+PCI_EXPRESS_FEATURE_INITIALIZATION_POINT mPciExpressFeatureInitializationList[] = {
+ //
+ // vacant entry, shall be replaced with actual entry when the PCI Express
+ // feature are added.
+ //
+ { 0, 0, NULL}
+};
+
+/**
+ Routine to serially dispatch the designated the PCI Express feature specific
+ functions defined for each of the configuration phase. The order for each phase
+ would be based entirely on the table mPciExpressFeatureInitializationList.
+
+ @param PciDevice pointer to PCI_IO_DEVICE to identify device
+ @param PciExFeatureConfigPhase input configuration phase
+ @param PciExpressFeatureConfiguration used pointer to void to accomodate any PCI
+ Express feature specific data type
+ @retval EFI_STATUS output only from feature specific function
+ defined in the table mPciExpressFeatureInitializationList
+**/
+EFI_STATUS
+DispatchPciExpressInitializationFunctions (
+ IN PCI_IO_DEVICE *PciDevice,
+ IN PCI_EXPRESS_FEATURE_CONFIGURATION_PHASE PciExFeatureConfigPhase,
+ IN VOID *PciExpressFeatureConfiguration
+ )
+{
+ UINTN idx;
+ EFI_STATUS Status;
+ UINT8 *PciExpressPolicy;
+
+ for (
+ idx = 0, PciExpressPolicy = (UINT8*)&mPciExpressPlatformPolicy
+ ; idx < sizeof (mPciExpressFeatureInitializationList) / sizeof (PCI_EXPRESS_FEATURE_INITIALIZATION_POINT)
+ ; idx++
+ ){
+ if (
+ //
+ // match the configuration phase
+ //
+ mPciExpressFeatureInitializationList[idx].PciExpressFeatureConfigurationPhase == PciExFeatureConfigPhase
+ //
+ // check whether the PCI Express features is enabled
+ //
+ && PciExpressPolicy[mPciExpressFeatureInitializationList[idx].PciExpressFeatureId] == TRUE
+ ) {
+ Status = mPciExpressFeatureInitializationList[idx].PciExpressFeatureConfigurationRoutine (
+ PciDevice,
+ PciExpressFeatureConfiguration
+ );
+ }
+ }
+ return Status;
+}
+
+/**
+ 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
+CheckPciExpressFeatureList (
+ )
+{
+ UINTN length;
+ UINT8 *list;
+
+ for (
+ length = 0, list = (UINT8*)&mPciExpressPlatformPolicy
+ ; length < sizeof (EFI_PCI_EXPRESS_PLATFORM_POLICY)
+ ; length++
+ ) {
+ if (list[length]) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/**
+ helper routine to wipe out the global PCI Express feature list
+**/
+VOID
+NegatePciExpressFeatureList (
+ )
+{
+ UINTN length;
+ UINT8 *list;
+
+ for (
+ length = 0, list = (UINT8*)&mPciExpressPlatformPolicy
+ ; length < sizeof (EFI_PCI_EXPRESS_PLATFORM_POLICY)
+ ; length++
+ ) {
+ if (list[length]) {
+ list[length] = FALSE;
+ }
+ }
+}
+
+/**
+ Main routine to indicate whether the PCI Express feature initialization is
+ required or not
+
+ @retval TRUE PCI Express feature initialization required
+ FALSE PCI Express feature not required
+**/
+BOOLEAN
+IsPciExpressFeatureConfigurationRequired (
+ )
+{
+ EFI_STATUS Status;
+
+ if (mPciExpressGetPlatformPolicyComplete) {
+ return CheckPciExpressFeatureList ();
+ }
+ //
+ // initialize the PCI Express feature data members
+ //
+ InitializeListHead (&mRootBridgeDeviceList);
+ //
+ // check the platform to configure the PCI Express features
+ //
+ mPciExpressGetPlatformPolicyComplete = TRUE;
+
+ Status = PciExpressPlatformGetPolicy ();
+ if (EFI_ERROR (Status)) {
+ //
+ // fail to obtain the PCI Express feature configuration from platform,
+ // negate the list to avoid any unwanted configuration
+ //
+ NegatePciExpressFeatureList ();
+ return FALSE;
+ }
+ //
+ // PCI Express feature configuration list is ready from platform
+ //
+ return TRUE;
+}
+
+
+/**
+ Indicates whether the set of PCI Express features selected by platform requires
+ extended setup, that has additional resources that would be allocated to align
+ all the devices in the PCI tree, and free the resources later.
+
+ @retval TRUE PCI Express feature requires extended setup
+ FALSE PCI Express feature does not require extended setup
+**/
+BOOLEAN
+IsPciExpressFeatureExtendedSetupRequired (
+ )
+{
+ UINTN idx;
+ UINT8 *PciExpressPolicy;
+ //
+ // return TRUE only for those features which are required to be aligned with
+ // common values among all the devices in the PCI tree
+ //
+ for (
+ idx = 0, PciExpressPolicy = (UINT8*)&mPciExpressPlatformPolicy
+ ; idx < sizeof (mPciExpressFeatureInitializationList) / sizeof (PCI_EXPRESS_FEATURE_INITIALIZATION_POINT)
+ ; idx++
+ ){
+ if (
+ //
+ // match the configuration phase to extended setup phase
+ //
+ mPciExpressFeatureInitializationList[idx].PciExpressFeatureConfigurationPhase == PciExpressFeatureEntendedSetupPhase
+ //
+ // check whether the PCI Express features is enabled
+ //
+ && PciExpressPolicy[mPciExpressFeatureInitializationList[idx].PciExpressFeatureId] == TRUE
+ ) {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+/**
+ Helper routine to determine the existence of previously enumerated PCI device
+
+ @retval TRUE PCI device exist
+ FALSE does not exist
+**/
+BOOLEAN
+DeviceExist (
+ PCI_IO_DEVICE *PciDevice
+ )
+{
+ EFI_PCI_IO_PROTOCOL *PciIoProtocol = &PciDevice->PciIo;
+ UINT16 VendorId = 0xFFFF;
+
+ PciIoProtocol->Pci.Read (
+ PciIoProtocol,
+ EfiPciIoWidthUint16,
+ PCI_VENDOR_ID_OFFSET,
+ 1,
+ &VendorId
+ );
+ if (VendorId == 0 || VendorId == 0xFFFF) {
+ return FALSE;
+ } else {
+ return TRUE;
+ }
+}
+
+/**
+ Free up memory alloted for the primary physical PCI Root ports of the PCI Root
+ Bridge instance. Free up all the nodes of type BRIDGE_DEVICE_NODE.
+**/
+VOID
+DestroyRootBridgeDeviceNodes ()
+{
+ LIST_ENTRY *Link;
+ BRIDGE_DEVICE_NODE *Temp;
+
+ Link = mRootBridgeDeviceList.ForwardLink;
+ while (Link != NULL && Link != &mRootBridgeDeviceList) {
+ Temp = ROOT_BRIDGE_DEVICE_NODE_FROM_LINK (Link);
+ Link = RemoveEntryList (Link);
+ FreePool (Temp->PciExFeaturesConfigurationTable);
+ FreePool (Temp);
+ }
+}
+
+/**
+ Main routine to determine the child PCI devices of a 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
+ PCI_EXPRESS_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 PCI 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_DEVICE_ERROR the PCI device has invalid EFI device
+ path
+**/
+EFI_STATUS
+GetPciExpressFeaturesConfigurationTable (
+ IN PCI_IO_DEVICE *PciDevice,
+ OUT PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE **PciFeaturesConfigTable
+ )
+{
+ LIST_ENTRY *Link;
+ BRIDGE_DEVICE_NODE *Temp;
+ BOOLEAN NodeMatch;
+ EFI_DEVICE_PATH_PROTOCOL *RootPortPath;
+ EFI_DEVICE_PATH_PROTOCOL *PciDevicePath;
+
+ if (IsListEmpty (&mRootBridgeDeviceList)) {
+ //
+ // no populated PCI primary root ports to parse and match the PCI features
+ // configuration table
+ //
+ *PciFeaturesConfigTable = NULL;
+ return EFI_SUCCESS;
+ }
+
+ //
+ // The PCI features configuration table is not built for RCiEP, return NULL
+ //
+ if (PciDevice->PciExpressCapabilityStructure.Capability.Bits.DevicePortType == \
+ PCIE_DEVICE_PORT_TYPE_ROOT_COMPLEX_INTEGRATED_ENDPOINT) {
+ *PciFeaturesConfigTable = NULL;
+ return EFI_SUCCESS;
+ }
+
+ if (IsDevicePathEnd (PciDevice->DevicePath)){
+ //
+ // the given PCI device does not have a valid device path
+ //
+ *PciFeaturesConfigTable = NULL;
+ return EFI_DEVICE_ERROR;
+ }
+
+
+ Link = mRootBridgeDeviceList.ForwardLink;
+ do {
+ Temp = ROOT_BRIDGE_DEVICE_NODE_FROM_LINK (Link);
+ RootPortPath = Temp->RootBridgeDevicePath;
+ PciDevicePath = PciDevice->DevicePath;
+ NodeMatch = FALSE;
+ //
+ // match the device path from the list of primary Root Ports with the given
+ // device; the initial nodes matching in sequence indicate that the given PCI
+ // device belongs to that PCI tree from the root port
+ //
+ if (IsDevicePathEnd (RootPortPath)) {
+ //
+ // critical error as no device path available in root
+ //
+ *PciFeaturesConfigTable = NULL;
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (EfiCompareDevicePath (RootPortPath, PciDevicePath)) {
+ //
+ // the given PCI device is the primary root port itself
+ //
+ *PciFeaturesConfigTable = Temp->PciExFeaturesConfigurationTable;
+ return EFI_SUCCESS;
+ }
+ //
+ // check this PCI device belongs to the primary root port of the root bridge
+ // any child PCI device will have the same initial device path nodes as
+ // its parent root port
+ //
+ while (!IsDevicePathEnd (RootPortPath)){
+
+ if (DevicePathNodeLength (RootPortPath) != DevicePathNodeLength (PciDevicePath)) {
+ //
+ // break to check the next primary root port nodes as does not match
+ //
+ NodeMatch = FALSE;
+ break;
+ }
+ if (CompareMem (RootPortPath, PciDevicePath, DevicePathNodeLength (RootPortPath)) != 0) {
+ //
+ // node does not match, break to check next node
+ //
+ NodeMatch = FALSE;
+ break;
+ }
+ NodeMatch = TRUE;
+ //
+ // advance to next node
+ //
+ RootPortPath = NextDevicePathNode (RootPortPath);
+ PciDevicePath = NextDevicePathNode (PciDevicePath);
+ }
+
+ if (NodeMatch == TRUE) {
+ //
+ // device belongs to primary root port, return its PCI feature configuration
+ // table
+ //
+ *PciFeaturesConfigTable = Temp->PciExFeaturesConfigurationTable;
+ return EFI_SUCCESS;
+ }
+
+ //
+ // advance to next Root port node
+ //
+ Link = Link->ForwardLink;
+ } while (Link != &mRootBridgeDeviceList && Link != NULL);
+ //
+ // the PCI device must be RCiEP, does not belong to any primary root port
+ //
+ *PciFeaturesConfigTable = NULL;
+ return EFI_SUCCESS;
+}
+
+/**
+ 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;
+ }
+}
+
+/**
+ Setup each PCI device as per the pltaform's device-specific policy, in accordance
+ with PCI Express Base specification.
+
+ @param RootBridge A pointer to the PCI_IO_DEVICE.
+
+ @retval EFI_SUCCESS processing each PCI feature as per policy defined
+ was successful.
+ **/
+EFI_STATUS
+SetupDevicePciExpressFeatures (
+ IN PCI_IO_DEVICE *PciDevice,
+ IN PCI_EXPRESS_FEATURE_CONFIGURATION_PHASE PciConfigPhase
+ )
+{
+ EFI_STATUS Status;
+ PCI_REG_PCIE_CAPABILITY PcieCap;
+ PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE *PciExpressFeaturesConfigTable;
+
+ PciExpressFeaturesConfigTable = NULL;
+ Status = GetPciExpressFeaturesConfigurationTable (PciDevice, &PciExpressFeaturesConfigTable);
+
+ if (PciConfigPhase == PciExpressFeatureSetupPhase) {
+ DEBUG_CODE (
+ if (EFI_ERROR( Status)) {
+ DEBUG ((
+ DEBUG_WARN,
+ "[Cfg group: 0 {error in dev path}]"
+ ));
+ } else if (PciExpressFeaturesConfigTable == NULL) {
+ DEBUG ((
+ DEBUG_INFO,
+ "[Cfg group: 0]"
+ ));
+ } else {
+ DEBUG ((
+ DEBUG_INFO,
+ "[Cfg group: %d]",
+ PciExpressFeaturesConfigTable->ID
+ ));
+ }
+ PcieCap.Uint16 = PciDevice->PciExpressCapabilityStructure.Capability.Uint16;
+ DumpDevicePortType ((UINT8)PcieCap.Bits.DevicePortType);
+ );
+
+ //
+ // get the device-specific platform policy for the PCI Express features
+ //
+ Status = PciExpressPlatformGetDevicePolicy (PciDevice);
+ if (EFI_ERROR(Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "Error in obtaining PCI device policy!!!\n"
+ ));
+ }
+ }
+
+ DEBUG ((DEBUG_INFO, "["));
+
+ Status = DispatchPciExpressInitializationFunctions (
+ PciDevice,
+ PciConfigPhase,
+ PciExpressFeaturesConfigTable
+ );
+
+ DEBUG ((DEBUG_INFO, "]\n"));
+ return Status;
+}
+
+/**
+ Create and append a node of type BRIDGE_DEVICE_NODE in the list for the primary
+ Root Port so that all its child PCI devices can be identified against the PCI
+ features configuration table group ID, of type PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE.
+
+ @param BridgePort A pointer to the PCI_IO_DEVICE
+ @param PortNumber A UINTN value to identify the PCI feature configuration
+ table group
+
+ @retval EFI_SUCCESS success in adding a node of BRIDGE_DEVICE_NODE
+ to the list
+ EFI_OUT_OF_RESOURCES unable to get memory for creating the node
+**/
+EFI_STATUS
+CreatePciRootBridgeDeviceNode (
+ IN PCI_IO_DEVICE *BridgePort,
+ IN UINTN PortNumber
+ )
+{
+ BRIDGE_DEVICE_NODE *RootBridgeNode = NULL;
+ PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE *PciConfigTable = NULL;
+
+ RootBridgeNode = AllocateZeroPool (sizeof (BRIDGE_DEVICE_NODE));
+ if (RootBridgeNode == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ RootBridgeNode->Signature = PCI_ROOT_BRIDGE_DEVICE_SIGNATURE;
+ RootBridgeNode->RootBridgeDevicePath = BridgePort->DevicePath;
+ PciConfigTable = AllocateZeroPool (
+ sizeof (PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE)
+ );
+ if (PciConfigTable) {
+ PciConfigTable->ID = PortNumber;
+ }
+
+ RootBridgeNode->PciExFeaturesConfigurationTable = PciConfigTable;
+
+ InsertTailList (&mRootBridgeDeviceList, &RootBridgeNode->NextRootBridgeDevice);
+
+ if (PciConfigTable == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ 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
+CreatePciRootBridgeDeviceList (
+ IN PCI_IO_DEVICE *RootBridge
+ )
+{
+ EFI_STATUS Status = EFI_NOT_FOUND;
+ LIST_ENTRY *Link;
+ PCI_IO_DEVICE *Device;
+ UINTN BridgeDeviceCount;
+
+ BridgeDeviceCount = 0;
+ for ( Link = RootBridge->ChildList.ForwardLink
+ ; Link != &RootBridge->ChildList
+ ; Link = Link->ForwardLink
+ ) {
+ Device = PCI_IO_DEVICE_FROM_LINK (Link);
+ if (!DeviceExist (Device)) {
+ continue;
+ }
+ if (IS_PCI_BRIDGE (&Device->Pci)) {
+ BridgeDeviceCount++;
+ DEBUG ((
+ DEBUG_INFO,
+ "#%d ::Bridge [%02x|%02x|%02x]",
+ BridgeDeviceCount, Device->BusNumber, Device->DeviceNumber, Device->FunctionNumber
+ ));
+ //
+ // create a list of bridge devices if that is connected to any other device
+ //
+ if (!IsListEmpty (&Device->ChildList)) {
+ DEBUG ((
+ DEBUG_INFO,
+ "- has downstream device!\n"
+ ));
+ Status = CreatePciRootBridgeDeviceNode (Device, BridgeDeviceCount);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "PCI configuration table allocation failure for #%d ::Bridge [%02x|%02x|%02x]\n",
+ BridgeDeviceCount, Device->BusNumber, Device->DeviceNumber, Device->FunctionNumber
+ ));
+ }
+ } else {
+ DEBUG ((
+ DEBUG_INFO,
+ "- no downstream device!\n"
+ ));
+ }
+ }
+ }
+
+ return Status;
+}
+
+/**
+ Initialize the device's PCI Express features, in a staged manner
+ @param PciDevice A pointer to the PCI_IO_DEVICE.
+
+ @retval EFI_SUCCESS initializing all the nodes of the root bridge
+ instances were successfull.
+**/
+EFI_STATUS
+InitializeDevicePciExpressFeatures (
+ IN PCI_IO_DEVICE *PciDevice,
+ IN PCI_EXPRESS_FEATURE_CONFIGURATION_PHASE PciConfigPhase
+ )
+{
+ EFI_STATUS Status;
+
+ switch (PciConfigPhase) {
+ case PciExpressFeatureSetupPhase:
+ case PciExpressFeatureEntendedSetupPhase:
+ case PciExpressFeatureProgramPhase:
+ Status = SetupDevicePciExpressFeatures (PciDevice, PciConfigPhase);
+ break;
+ case PciExpressFeatureEndPhase:
+ Status = PciExpressPlatformNotifyDeviceState (PciDevice);
+ break;
+ }
+ return Status;
+}
+
+/**
+ Traverse all the nodes from the root bridge or PCI-PCI bridge instance, to
+ configure the PCI Express features as per the PCI Express Base Secification
+ by considering its device-specific platform policy, and its 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
+InitializePciExpressFeatures (
+ IN PCI_IO_DEVICE *RootBridge,
+ IN PCI_EXPRESS_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 (!DeviceExist (Device)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "::Device [%02x|%02x|%02x] - does not exist!!!\n",
+ Device->BusNumber, Device->DeviceNumber, Device->FunctionNumber
+ ));
+ continue;
+ }
+ if (IS_PCI_BRIDGE (&Device->Pci)) {
+ DEBUG ((
+ DEBUG_INFO,
+ "::Bridge [%02x|%02x|%02x] -",
+ Device->BusNumber, Device->DeviceNumber, Device->FunctionNumber
+ ));
+ if (Device->IsPciExp) {
+ Status = InitializeDevicePciExpressFeatures (
+ 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
+ //
+ }
+
+ InitializePciExpressFeatures (Device, PciConfigPhase);
+ } else {
+ DEBUG ((
+ DEBUG_INFO,
+ "::Device [%02x|%02x|%02x] -",
+ Device->BusNumber, Device->DeviceNumber, Device->FunctionNumber
+ ));
+ if (Device->IsPciExp) {
+ Status = InitializeDevicePciExpressFeatures (
+ 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;
+}
+
+/**
+ 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
+EnumeratePciExpressFeatures (
+ IN EFI_HANDLE Controller,
+ IN PCI_IO_DEVICE *RootBridge
+ )
+{
+ EFI_STATUS Status;
+ UINTN PciExpressFeatureConfigPhase;
+
+ if (!IsPciExpressFeatureConfigurationRequired ()) {
+ //
+ // exit as agreement is not reached with platform to configure the PCI
+ // Express features
+ //
+ return EFI_SUCCESS;
+ }
+ mRootBridgeHandle = Controller;
+
+ DEBUG_CODE (
+ CHAR16 *Str;
+ Str = ConvertDevicePathToText (
+ DevicePathFromHandle (RootBridge->Handle),
+ FALSE,
+ FALSE
+ );
+ DEBUG ((
+ DEBUG_INFO,
+ "Enumerating PCI features for Root Bridge %s\n",
+ Str != NULL ? Str : L""
+ ));
+
+ if (Str != NULL) {
+ FreePool (Str);
+ }
+ );
+
+ for ( PciExpressFeatureConfigPhase = PciExpressFeaturePreProcessPhase
+ ; PciExpressFeatureConfigPhase <= PciExpressFeatureEndPhase
+ ; PciExpressFeatureConfigPhase++
+ ) {
+ DEBUG ((
+ DEBUG_INFO,
+ "<<********** Phase [%d]**********>>\n",
+ PciExpressFeatureConfigPhase
+ ));
+ if (PciExpressFeatureConfigPhase == PciExpressFeaturePreProcessPhase) {
+ //
+ // create a list of root bridge devices (root ports) of the root complex
+ // if extra setup phase required
+ //
+ if (IsPciExpressFeatureExtendedSetupRequired ()) {
+ CreatePciRootBridgeDeviceList (RootBridge);
+ }
+ continue;
+ }
+ if (PciExpressFeatureConfigPhase == PciExpressFeatureEntendedSetupPhase) {
+ if (!IsPciExpressFeatureExtendedSetupRequired ()) {
+ //
+ // since the PCI Express features require no extra initialization steps
+ // skip this phase
+ //
+ continue;
+ }
+ }
+ //
+ // setup the PCI Express features
+ //
+ Status = InitializePciExpressFeatures (RootBridge, PciExpressFeatureConfigPhase);
+
+ if (PciExpressFeatureConfigPhase == PciExpressFeatureEndPhase) {
+ //
+ // clean up the temporary resource nodes created for this root bridge
+ //
+ if (IsPciExpressFeatureExtendedSetupRequired ()) {
+ DestroyRootBridgeDeviceNodes ();
+ }
+ }
+ }
+
+ return Status;
+}
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
new file mode 100644
index 0000000..2eff8aa
--- /dev/null
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
@@ -0,0 +1,226 @@
+/** @file
+ PCI standard feature support functions implementation for PCI Bus module..
+
+Copyright (c) 2020, 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_
+
+extern EFI_HANDLE mRootBridgeHandle;
+extern EFI_PCI_EXPRESS_PLATFORM_POLICY mPciExpressPlatformPolicy;
+//
+// defines the data structure to hold the details of the PCI Root port devices
+//
+typedef struct _BRIDGE_DEVICE_NODE BRIDGE_DEVICE_NODE;
+
+//
+// defines the data structure to hold the configuration data for the other PCI
+// features
+//
+typedef struct _PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE;
+
+//
+// define the data type for the PCI feature policy support
+//
+typedef struct _PCI_FEATURE_POLICY PCI_FEATURE_POLICY;
+
+//
+// Signature value for the PCI Root Port node
+//
+#define PCI_ROOT_BRIDGE_DEVICE_SIGNATURE SIGNATURE_32 ('p', 'c', 'i', 'p')
+
+//
+// Definitions of the PCI Root Port data structure members
+//
+struct _BRIDGE_DEVICE_NODE {
+ //
+ // Signature header
+ //
+ UINT32 Signature;
+ //
+ // linked list pointers to next node
+ //
+ LIST_ENTRY NextRootBridgeDevice;
+ //
+ // pointer to PCI_IO_DEVICE of the primary PCI Controller device
+ //
+ EFI_DEVICE_PATH_PROTOCOL *RootBridgeDevicePath;
+ //
+ // pointer to the corresponding PCI Express feature configuration Table node
+ // all the child PCI devices of the controller are aligned based on this table
+ //
+ PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE *PciExFeaturesConfigurationTable;
+};
+
+#define ROOT_BRIDGE_DEVICE_NODE_FROM_LINK(a) \
+ CR (a, BRIDGE_DEVICE_NODE, NextRootBridgeDevice, PCI_ROOT_BRIDGE_DEVICE_SIGNATURE)
+
+//
+// Definition of the PCI Feature configuration Table members
+//
+struct _PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE {
+ //
+ // Configuration Table ID
+ //
+ UINTN ID;
+};
+
+//
+// Declaration of the internal sub-phases during enumeration to configure the PCI
+// Express features
+//
+typedef enum {
+ //
+ // preprocessing applicable only to few PCI Express features to bind all devices
+ // under the common root bridge device (root port), that would be useful to align
+ // all devices with a common value. This would be optional phase based on the
+ // type of the PCI Express feature to be programmed based on platform policy
+ //
+ PciExpressFeaturePreProcessPhase,
+
+ //
+ // mandatory phase to setup the PCI Express feature to its applicable attribute,
+ // based on its device-specific platform policies, matching with its device capabilities
+ //
+ PciExpressFeatureSetupPhase,
+
+ //
+ // optional phase primarily to align all devices, specially required when PCI
+ // switch is present in the hierarchy, applicable to certain few PCI Express
+ // features only
+ //
+ PciExpressFeatureEntendedSetupPhase,
+
+ //
+ // mandatory programming phase to complete the configuration of the PCI Express
+ // features
+ //
+ PciExpressFeatureProgramPhase,
+
+ //
+ // optional phase to clean up temporary buffers, like those that were prepared
+ // during the preprocessing phase above
+ //
+ PciExpressFeatureEndPhase
+
+}PCI_EXPRESS_FEATURE_CONFIGURATION_PHASE;
+
+//
+// declaration for the data type to harbor the PCI feature policies
+//
+struct _PCI_FEATURE_POLICY {
+ //
+ // if set, it indicates the feature should be enabled
+ // if clear, it indicates the feature should be disabled
+ //
+ UINT8 Act : 1;
+ //
+ // this field will be specific to feature, it can be implementation specific
+ // or it can be reserved and remain unused
+ //
+ UINT8 Support : 6;
+ //
+ // if set indicates override the feature policy defined by the members above
+ // if clear it indicates that this feature policy should be ignored completely
+ // this means the above two members should not be used
+ //
+ UINT8 Override : 1;
+};
+
+//
+// Declaration of the PCI Express features unique Id
+//
+typedef enum {
+ //
+ // support for PCI Express feature - Max. Payload Size
+ //
+ PciExpressMps,
+ //
+ // support for PCI Express feature - Max. Read Request Size
+ //
+ PciExpressMrrs,
+ //
+ // support for PCI Express feature - Extended Tag
+ //
+ PciExpressExtTag,
+ //
+ // support for PCI Express feature - Relax Order
+ //
+ PciExpressRelaxOrder,
+ //
+ // support for PCI Express feature - No-Snoop
+ //
+ PciExpressNoSnoop,
+ //
+ // support for PCI Express feature - ASPM state
+ //
+ PciExpressAspm,
+ //
+ // support for PCI Express feature - Common Clock Configuration
+ //
+ PciExpressCcc,
+ //
+ // support for PCI Express feature - Extended Sync
+ //
+ PciExpressExtSync,
+ //
+ // support for PCI Express feature - Atomic Op
+ //
+ PciExpressAtomicOp,
+ //
+ // support for PCI Express feature - LTR
+ //
+ PciExpressLtr,
+ //
+ // support for PCI Express feature - PTM
+ //
+ PciExpressPtm,
+ //
+ // support for PCI Express feature - Completion Timeout
+ //
+ PciExpressCto,
+ //
+ // support for PCI Express feature - Clock Power Management
+ //
+ PciExpressCpm,
+ //
+ // support for PCI Express feature - L1 PM Substates
+ //
+ PciExpressL1PmSubstates
+
+} PCI_EXPRESS_FEATURE_ID;
+
+//
+// PCI Express feature configuration routine during initialization phases
+//
+typedef
+EFI_STATUS
+(*PCI_EXPRESS_FEATURE_CONFIGURATION_ROUTINE) (
+ IN PCI_IO_DEVICE *PciDevice,
+ IN VOID *PciExpressFeatureConfiguration
+ );
+
+//
+// data type for the PCI Express feature initialization phases
+//
+typedef struct {
+ //
+ // Pci Express feature configuration phase
+ //
+ PCI_EXPRESS_FEATURE_CONFIGURATION_PHASE PciExpressFeatureConfigurationPhase;
+ //
+ // PCI Express feature Id
+ //
+ PCI_EXPRESS_FEATURE_ID PciExpressFeatureId;
+ //
+ // PCI Express feature configuration routine
+ //
+ PCI_EXPRESS_FEATURE_CONFIGURATION_ROUTINE PciExpressFeatureConfigurationRoutine;
+
+}PCI_EXPRESS_FEATURE_INITIALIZATION_POINT;
+
+
+#endif
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
new file mode 100644
index 0000000..31c675d
--- /dev/null
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
@@ -0,0 +1,302 @@
+/** @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) 2020, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "PciBus.h"
+
+
+EFI_PCI_EXPRESS_PLATFORM_PROTOCOL *mPciExPlatformProtocol;
+EFI_PCI_EXPRESS_OVERRIDE_PROTOCOL *mPciExOverrideProtocol;
+
+
+/**
+ This function retrieves the PCI Express Platform Protocols published by platform
+ @retval EFI_STATUS direct return status from the LocateProtocol ()
+ boot service for the PCI Express Override Protocol
+ EFI_SUCCESS The PCI Express Platform Protocol is found
+**/
+EFI_STATUS
+GetPciExpressProtocol (
+ )
+{
+ EFI_STATUS Status;
+
+ if (mPciExPlatformProtocol) {
+ //
+ // the PCI Express Platform Protocol is already initialized
+ //
+ return EFI_SUCCESS;
+ }
+ if (mPciExOverrideProtocol) {
+ //
+ // the PCI Express Override Protocol is already initialized
+ //
+ return EFI_SUCCESS;
+ }
+ //
+ // locate the PCI Express Platform Protocol
+ //
+ Status = gBS->LocateProtocol (
+ &gEfiPciExpressPlatformProtocolGuid,
+ NULL,
+ (VOID **) &mPciExPlatformProtocol
+ );
+ if (!EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // If PCI Express Platform protocol doesn't exist, try to get the Pci Express
+ // Override Protocol.
+ //
+ return gBS->LocateProtocol (
+ &gEfiPciExpressOverrideProtocolGuid,
+ NULL,
+ (VOID **) &mPciExOverrideProtocol
+ );
+}
+
+/**
+ This function indicates that the platform has published the PCI Express Platform
+ Protocol (or PCI Express Override Protocol) to indicate that this driver can
+ initialize the PCI Express features.
+ @retval TRUE or FALSE
+**/
+BOOLEAN
+IsPciExpressProtocolPresent (
+ )
+{
+ if (
+ mPciExPlatformProtocol == NULL
+ && mPciExOverrideProtocol == NULL
+ ) {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+
+/**
+ Generic routine to setup the PCI features as per its predetermined defaults.
+**/
+VOID
+SetupDefaultPciExpressDevicePolicy (
+ IN PCI_IO_DEVICE *PciDevice
+ )
+{
+
+}
+
+/**
+ initialize the device policy data members
+**/
+VOID
+InitializeDevicePolicyData (
+ IN EFI_PCI_EXPRESS_DEVICE_POLICY *PciExpressDevicePolicy
+ )
+{
+ UINTN length;
+ UINT8 *PciExpressPolicy;
+ UINT8 *PciExDevicePolicy;
+
+
+ ZeroMem (PciExpressDevicePolicy, sizeof (EFI_PCI_EXPRESS_DEVICE_POLICY));
+
+ for (
+ length = 0
+ , PciExpressPolicy = (UINT8*)&mPciExpressPlatformPolicy
+ , PciExDevicePolicy = (UINT8*)PciExpressDevicePolicy
+ ; length < sizeof (EFI_PCI_EXPRESS_PLATFORM_POLICY)
+ ; length++
+ ) {
+ if (!PciExpressPolicy[length]) {
+ PciExDevicePolicy[length] = EFI_PCI_EXPRESS_NOT_APPLICABLE;
+ }
+ }
+}
+
+/**
+ Intermediate routine to either get the PCI device specific platform policies
+ through the PCI Platform Protocol, or its alias the PCI Override Protocol.
+
+ @param PciDevice A pointer to PCI_IO_DEVICE
+ @param PciPlatformProtocol A pointer to EFI_PCI_EXPRESS_PLATFORM_PROTOCOL
+
+ @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
+GetPciExpressDevicePolicy (
+ IN PCI_IO_DEVICE *PciDevice,
+ IN EFI_PCI_EXPRESS_PLATFORM_PROTOCOL *PciPlatformProtocol
+ )
+{
+ EFI_PCI_EXPRESS_DEVICE_POLICY PciExpressDevicePolicy;
+ EFI_STATUS Status;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress;
+
+ PciAddress.Bus = PciDevice->BusNumber;
+ PciAddress.Device = PciDevice->DeviceNumber;
+ PciAddress.Function = PciDevice->FunctionNumber;
+ PciAddress.Register = 0;
+ PciAddress.ExtendedRegister = 0;
+
+ InitializeDevicePolicyData (&PciExpressDevicePolicy);
+ Status = PciPlatformProtocol->GetDevicePolicy (
+ PciPlatformProtocol,
+ mRootBridgeHandle,
+ PciAddress,
+ sizeof (EFI_PCI_EXPRESS_DEVICE_POLICY),
+ &PciExpressDevicePolicy
+ );
+ if (!EFI_ERROR(Status)) {
+ //
+ // platform chipset policies are returned for this PCI device
+ //
+
+
+ DEBUG ((
+ DEBUG_INFO,
+ "[device policy: platform]"
+ ));
+ return Status;
+ } else if (Status == EFI_UNSUPPORTED) {
+ //
+ // platform chipset policies are not provided for this PCI device
+ // let the enumeration happen as per the PCI standard way
+ //
+ SetupDefaultPciExpressDevicePolicy (PciDevice);
+ DEBUG ((
+ DEBUG_INFO,
+ "[device policy: default]"
+ ));
+ return EFI_SUCCESS;
+ }
+ DEBUG ((
+ DEBUG_ERROR,
+ "[device policy: none (error)]"
+ ));
+ return Status;
+}
+
+/**
+ Gets the PCI device-specific platform policy from the PCI Express 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
+PciExpressPlatformGetDevicePolicy (
+ IN PCI_IO_DEVICE *PciDevice
+ )
+{
+ if (mPciExPlatformProtocol != NULL) {
+ return GetPciExpressDevicePolicy (PciDevice, mPciExPlatformProtocol);
+ } else if (mPciExOverrideProtocol != NULL) {
+ return GetPciExpressDevicePolicy (PciDevice, mPciExOverrideProtocol);
+ } else {
+ //
+ // no protocol found, platform does not require the PCI Express initialization
+ //
+ return EFI_UNSUPPORTED;
+ }
+}
+
+/**
+ This function gets the platform requirement to initialize the list of PCI Express
+ features from the protocol definition supported.
+ This function should be called after the LocatePciPlatformProtocol.
+ @retval EFI_SUCCESS return by platform to acknowledge the list of
+ PCI Express feature to be configured
+ (in mPciExpressPlatformPolicy)
+ EFI_INVALID_PARAMETER platform does not support the protocol arguements
+ passed
+ EFI_UNSUPPORTED platform did not published the protocol
+**/
+EFI_STATUS
+PciExpressPlatformGetPolicy (
+ )
+{
+ EFI_STATUS Status;
+
+ if (mPciExPlatformProtocol) {
+ Status = mPciExPlatformProtocol->GetPolicy (
+ mPciExPlatformProtocol,
+ sizeof (EFI_PCI_EXPRESS_PLATFORM_POLICY),
+ &mPciExpressPlatformPolicy
+ );
+ } else if (mPciExOverrideProtocol) {
+ Status = mPciExOverrideProtocol->GetPolicy (
+ mPciExOverrideProtocol,
+ sizeof (EFI_PCI_EXPRESS_PLATFORM_POLICY),
+ &mPciExpressPlatformPolicy
+ );
+ } else {
+ //
+ // no protocol found, platform does not require the PCI Express initialization
+ //
+ return EFI_UNSUPPORTED;
+ }
+ return Status;
+}
+
+
+/**
+ Notifies the platform about the current PCI Express state of the device.
+
+ @param PciDevice A pointer to PCI_IO_DEVICE
+ @param PciExDeviceConfiguration Pointer to EFI_PCI_EXPRESS_DEVICE_CONFIGURATION.
+ Used to pass the current state of device to
+ platform.
+
+ @retval EFI_STATUS The direct status from the PCI Express Platform Protocol
+ @retval EFI_UNSUPPORTED returns when the PCI Express Platform Protocol or its
+ alias PCI Express OVerride Protocol is not present.
+**/
+EFI_STATUS
+PciExpressPlatformNotifyDeviceState (
+ IN PCI_IO_DEVICE *PciDevice
+ )
+{
+ EFI_PCI_EXPRESS_DEVICE_CONFIGURATION PciExDeviceConfiguration;
+
+
+ if (mPciExPlatformProtocol != NULL) {
+ return mPciExPlatformProtocol->NotifyDeviceState (
+ mPciExPlatformProtocol,
+ PciDevice->Handle,
+ sizeof (EFI_PCI_EXPRESS_DEVICE_CONFIGURATION),
+ &PciExDeviceConfiguration
+ );
+ } else if (mPciExOverrideProtocol != NULL) {
+ return mPciExOverrideProtocol->NotifyDeviceState (
+ mPciExOverrideProtocol,
+ PciDevice->Handle,
+ sizeof (EFI_PCI_EXPRESS_DEVICE_CONFIGURATION),
+ &PciExDeviceConfiguration
+ );
+ } else {
+ //
+ // unexpected error
+ //
+ return EFI_UNSUPPORTED;
+ }
+}
+
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
new file mode 100644
index 0000000..4283b81
--- /dev/null
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
@@ -0,0 +1,87 @@
+/** @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) 2020, 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_
+
+
+/**
+ This function retrieves the PCI Express Platform Protocols published by platform
+ @retval EFI_STATUS direct return status from the LocateProtocol ()
+ boot service for the PCI Express Override Protocol
+ EFI_SUCCESS The PCI Express Platform Protocol is found
+**/
+EFI_STATUS
+GetPciExpressProtocol (
+ );
+
+/**
+ This function indicates that the platform has published the PCI Express Platform
+ Protocol (or PCI Express Override Protocol) to indicate that this driver can
+ initialize the PCI Express features.
+ @retval TRUE or FALSE
+**/
+BOOLEAN
+IsPciExpressProtocolPresent (
+ );
+
+/**
+ This function gets the platform requirement to initialize the list of PCI Express
+ features from the protocol definition supported.
+ This function should be called after the LocatePciPlatformProtocol.
+ @retval EFI_SUCCESS return by platform to acknowledge the list of
+ PCI Express feature to be configured
+ (in mPciExpressPlatformPolicy)
+ EFI_INVALID_PARAMETER platform does not support the protocol arguements
+ passed
+ EFI_UNSUPPORTED platform did not published the protocol
+**/
+EFI_STATUS
+PciExpressPlatformGetPolicy (
+ );
+
+/**
+ 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
+PciExpressPlatformGetDevicePolicy (
+ IN PCI_IO_DEVICE *PciDevice
+ );
+
+/**
+ Notifies the platform about the current PCI Express state of the device.
+
+ @param PciDevice A pointer to PCI_IO_DEVICE
+ @param PciExDeviceConfiguration Pointer to EFI_PCI_EXPRESS_DEVICE_CONFIGURATION.
+ Used to pass the current state of device to
+ platform.
+
+ @retval EFI_STATUS The direct status from the PCI Express Platform Protocol
+ @retval EFI_UNSUPPORTED returns when the PCI Express Platform Protocol or its
+ alias PCI Express OVerride Protocol is not present.
+**/
+EFI_STATUS
+PciExpressPlatformNotifyDeviceState (
+ IN PCI_IO_DEVICE *PciDevice
+ );
+#endif
--
2.21.0.windows.1
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#54064): https://edk2.groups.io/g/devel/message/54064
Mute This Topic: https://groups.io/mt/71063071/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-
© 2016 - 2024 Red Hat, Inc.