This patch can also be viewed in the following repo:- https://github.com/ashrafj/edk2-staging/commit/9d9f47b271f2c8fe7f7fa2a72bc98db3c28b3312
Thanks Ashraf > -----Original Message----- > From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Javeed, > Ashraf > Sent: Saturday, February 8, 2020 1:35 AM > To: devel@edk2.groups.io > Cc: Wang, Jian J <jian.j.w...@intel.com>; Wu, Hao A <hao.a...@intel.com>; > Ni, Ray <ray...@intel.com> > Subject: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 01/12] > MdeModulePkg/PciBusDxe: Setup for PCI Express features > > 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.jav...@intel.com> > Cc: Jian J Wang <jian.j.w...@intel.com> > Cc: Hao A Wu <hao.a...@intel.com> > Cc: Ray Ni <ray...@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].PciExpressFeatureConfigurationRoutin > e ( > + 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 (#54076): https://edk2.groups.io/g/devel/message/54076 Mute This Topic: https://groups.io/mt/71063360/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-