From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mga06.intel.com (mga06.intel.com [134.134.136.31]) by mx.groups.io with SMTP id smtpd.web12.10665.1581106622624107826 for ; Fri, 07 Feb 2020 12:17:02 -0800 Authentication-Results: mx.groups.io; dkim=missing; spf=pass (domain: intel.com, ip: 134.134.136.31, mailfrom: ashraf.javeed@intel.com) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga004.jf.intel.com ([10.7.209.38]) by orsmga104.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 07 Feb 2020 12:17:01 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.70,414,1574150400"; d="scan'208";a="379500971" Received: from fmsmsx103.amr.corp.intel.com ([10.18.124.201]) by orsmga004.jf.intel.com with ESMTP; 07 Feb 2020 12:17:01 -0800 Received: from fmsmsx118.amr.corp.intel.com (10.18.116.18) by FMSMSX103.amr.corp.intel.com (10.18.124.201) with Microsoft SMTP Server (TLS) id 14.3.439.0; Fri, 7 Feb 2020 12:17:00 -0800 Received: from bgsmsx153.gar.corp.intel.com (10.224.23.4) by fmsmsx118.amr.corp.intel.com (10.18.116.18) with Microsoft SMTP Server (TLS) id 14.3.439.0; Fri, 7 Feb 2020 12:16:59 -0800 Received: from bgsmsx101.gar.corp.intel.com ([169.254.1.155]) by BGSMSX153.gar.corp.intel.com ([169.254.2.95]) with mapi id 14.03.0439.000; Sat, 8 Feb 2020 01:46:57 +0530 From: "Javeed, Ashraf" To: "devel@edk2.groups.io" , "Javeed, Ashraf" CC: "Wang, Jian J" , "Wu, Hao A" , "Ni, Ray" Subject: Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 01/12] MdeModulePkg/PciBusDxe: Setup for PCI Express features Thread-Topic: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 01/12] MdeModulePkg/PciBusDxe: Setup for PCI Express features Thread-Index: AQHV3fIMf9YTCUzmnk+VcR6U2vCJ+qgQKrMg Date: Fri, 7 Feb 2020 20:16:56 +0000 Message-ID: <95C5C2B113DE604FB208120C742E9824579AAF65@BGSMSX101.gar.corp.intel.com> References: <20200207200447.10536-1-ashraf.javeed@intel.com> <15F1377EA7D1AA4F.7869@groups.io> In-Reply-To: <15F1377EA7D1AA4F.7869@groups.io> Accept-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-titus-metadata-40: eyJDYXRlZ29yeUxhYmVscyI6IiIsIk1ldGFkYXRhIjp7Im5zIjoiaHR0cDpcL1wvd3d3LnRpdHVzLmNvbVwvbnNcL0ludGVsMyIsImlkIjoiY2ZhZDhjNTMtYTFlZC00MjIxLTk0OGMtNmE2MDU5NDk5NzJkIiwicHJvcHMiOlt7Im4iOiJDVFBDbGFzc2lmaWNhdGlvbiIsInZhbHMiOlt7InZhbHVlIjoiQ1RQX05UIn1dfV19LCJTdWJqZWN0TGFiZWxzIjpbXSwiVE1DVmVyc2lvbiI6IjE3LjEwLjE4MDQuNDkiLCJUcnVzdGVkTGFiZWxIYXNoIjoiNjFFZ2JQNllpdXB2WlRISzlGMTdCdml0UzFGazFBd0VCVXZSWW5vaUM2YjVDSGE0Y0VmcmZKXC9MTGpyamtPTlEifQ== x-ctpclassification: CTP_NT dlp-product: dlpe-windows dlp-version: 11.2.0.6 dlp-reaction: no-action x-originating-ip: [10.223.10.10] MIME-Version: 1.0 Return-Path: ashraf.javeed@intel.com Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable This patch can also be viewed in the following repo:- https://github.com/ashrafj/edk2-staging/commit/9d9f47b271f2c8fe7f7fa2a72bc= 98db3c28b3312 Thanks Ashraf > -----Original Message----- > From: 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 ; Wu, Hao A = ; > Ni, Ray > Subject: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 01/12] > MdeModulePkg/PciBusDxe: Setup for PCI Express features >=20 > References:- > https://bugzilla.tianocore.org/show_bug.cgi?id=3D1954 > https://bugzilla.tianocore.org/show_bug.cgi?id=3D2194 > https://bugzilla.tianocore.org/show_bug.cgi?id=3D2313 > https://bugzilla.tianocore.org/show_bug.cgi?id=3D2499 > https://bugzilla.tianocore.org/show_bug.cgi?id=3D2500 >=20 > 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 >=20 > Signed-off-by: Ashraf Javeed > Cc: Jian J Wang > Cc: Hao A Wu > Cc: Ray Ni > --- > 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(-) >=20 > 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= . >=20 > -Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
> +Copyright (c) 2006 - 2020, Intel Corporation. All rights reserved.
> SPDX-License-Identifier: BSD-2-Clause-Patent >=20 > **/ > @@ -284,6 +284,10 @@ PciBusDriverBindingStart ( > (VOID **) &gPciOverrideProtocol > ); > } > + // > + // get the PCI Express Protocol or the PCI Express Override Protocol > + // > + GetPciExpressProtocol (); >=20 > if (mIoMmuProtocol =3D=3D 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. >=20 > -Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
> +Copyright (c) 2006 - 2020, Intel Corporation. All rights reserved.
> SPDX-License-Identifier: BSD-2-Clause-Patent >=20 > **/ > @@ -42,6 +42,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent > #include > #include > #include > +#include > +#include >=20 > 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" >=20 > #define VGABASE1 0x3B0 > #define VGALIMIT1 0x3BB > @@ -263,9 +267,13 @@ struct _PCI_IO_DEVICE { >=20 > BOOLEAN IsPciExp; > // > - // For SR-IOV > + // For PCI Express Capability List Structure > // > UINT8 PciExpressCapabilityOffset; > + PCI_CAPABILITY_PCIEXP PciExpressCapabilityStructu= re; > + // > + // 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. > +# Copyright (c) 2006 - 2020, Intel Corporation. All rights reserved. > # > # 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 >=20 > [Packages] > MdePkg/MdePkg.dec > @@ -91,6 +95,9 @@ > gEfiLoadFile2ProtocolGuid ## SOMETIMES_PRODUCES > gEdkiiIoMmuProtocolGuid ## SOMETIMES_CONSUMES > gEfiLoadedImageDevicePathProtocolGuid ## CONSUMES > + gEfiPciExpressPlatformProtocolGuid ## SOMETIMES_C= ONSUMES > + gEfiPciExpressOverrideProtocolGuid ## SOMETIMES_C= ONSUMES > + >=20 > [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. >=20 > -Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
> +Copyright (c) 2006 - 2020, Intel Corporation. All rights reserved.
> (C) Copyright 2015 Hewlett Packard Enterprise Development LP
> SPDX-License-Identifier: BSD-2-Clause-Patent >=20 > @@ -2154,6 +2154,16 @@ CreatePciIoDevice ( > ); > if (!EFI_ERROR (Status)) { > PciIoDevice->IsPciExp =3D 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 > + ); > } >=20 > 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 mod= ule.. > + > +Copyright (c) 2020, Intel Corporation. All rights reserved.
> +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 dri= ver, it > + is expected to be overridden based on the platform request > +**/ > +EFI_PCI_EXPRESS_PLATFORM_POLICY mPciExpressPlatformPolicy = =3D { > + // > + // 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 =3D FALSE; > + > +// > +// PCI Express feature initialization phase handle routines > +// > +PCI_EXPRESS_FEATURE_INITIALIZATION_POINT > mPciExpressFeatureInitializationList[] =3D { > + // > + // vacant entry, shall be replaced with actual entry when the PCI E= xpress > + // feature are added. > + // > + { 0, 0, NULL} > +}; > + > +/** > + Routine to serially dispatch the designated the PCI Express feature s= pecific > + functions defined for each of the configuration phase. The order for = each > phase > + would be based entirely on the table mPciExpressFeatureInitialization= List. > + > + @param PciDevice pointer to PCI_IO_DEVICE to i= dentify 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 spec= ific function > + defined in the table mPciExpr= essFeatureInitializationList > +**/ > +EFI_STATUS > +DispatchPciExpressInitializationFunctions ( > + IN PCI_IO_DEVICE *PciDevice, > + IN PCI_EXPRESS_FEATURE_CONFIGURATION_PHASE > PciExFeatureConfigPhase, > + IN VOID *PciExpressFeatureConfigu= ration > + ) > +{ > + UINTN idx; > + EFI_STATUS Status; > + UINT8 *PciExpressPolicy; > + > + for ( > + idx =3D 0, PciExpressPolicy =3D (UINT8*)&mPciExpressPlatformPolic= y > + ; idx < sizeof (mPciExpressFeatureInitializationList) / sizeof > (PCI_EXPRESS_FEATURE_INITIALIZATION_POINT) > + ; idx++ > + ){ > + if ( > + // > + // match the configuration phase > + // > + > mPciExpressFeatureInitializationList[idx].PciExpressFeatureConfiguration= Phase > =3D=3D PciExFeatureConfigPhase > + // > + // check whether the PCI Express features is enabled > + // > + && > PciExpressPolicy[mPciExpressFeatureInitializationList[idx].PciExpressFea= tureId] > =3D=3D TRUE > + ) { > + Status =3D > mPciExpressFeatureInitializationList[idx].PciExpressFeatureConfiguration= Routin > e ( > + PciDevice, > + PciExpressF= eatureConfiguration > + ); > + } > + } > + return Status; > +} > + > +/** > + Main routine to indicate platform selection of any of the other PCI f= eatures > + to be configured by this driver > + > + @retval TRUE platform has selected the other PCI features to be co= nfigured > + FALSE platform has not selected any of the other PCI featur= es > +**/ > +BOOLEAN > +CheckPciExpressFeatureList ( > + ) > +{ > + UINTN length; > + UINT8 *list; > + > + for ( > + length =3D 0, list =3D (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 =3D 0, list =3D (UINT8*)&mPciExpressPlatformPolicy > + ; length < sizeof (EFI_PCI_EXPRESS_PLATFORM_POLICY) > + ; length++ > + ) { > + if (list[length]) { > + list[length] =3D FALSE; > + } > + } > +} > + > +/** > + Main routine to indicate whether the PCI Express feature initializati= on 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 =3D TRUE; > + > + Status =3D PciExpressPlatformGetPolicy (); > + if (EFI_ERROR (Status)) { > + // > + // fail to obtain the PCI Express feature configuration from platfo= rm, > + // 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 platfor= m > 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 align= ed with > + // common values among all the devices in the PCI tree > + // > + for ( > + idx =3D 0, PciExpressPolicy =3D (UINT8*)&mPciExpressPlatformPolic= y > + ; idx < sizeof (mPciExpressFeatureInitializationList) / sizeof > (PCI_EXPRESS_FEATURE_INITIALIZATION_POINT) > + ; idx++ > + ){ > + if ( > + // > + // match the configuration phase to extended setup phase > + // > + > mPciExpressFeatureInitializationList[idx].PciExpressFeatureConfiguration= Phase > =3D=3D PciExpressFeatureEntendedSetupPhase > + // > + // check whether the PCI Express features is enabled > + // > + && > PciExpressPolicy[mPciExpressFeatureInitializationList[idx].PciExpressFea= tureId] > =3D=3D 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 =3D &PciDevice->PciIo; > + UINT16 VendorId =3D 0xFFFF; > + > + PciIoProtocol->Pci.Read ( > + PciIoProtocol, > + EfiPciIoWidthUint16, > + PCI_VENDOR_ID_OFFSET, > + 1, > + &VendorId > + ); > + if (VendorId =3D=3D 0 || VendorId =3D=3D 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 =3D mRootBridgeDeviceList.ForwardLink; > + while (Link !=3D NULL && Link !=3D &mRootBridgeDeviceList) { > + Temp =3D ROOT_BRIDGE_DEVICE_NODE_FROM_LINK (Link); > + Link =3D RemoveEntryList (Link); > + FreePool (Temp->PciExFeaturesConfigurationTable); > + FreePool (Temp); > + } > +} > + > +/** > + Main routine to determine the child PCI devices of a PCI bridge devic= e > + and group them under a common internal PCI features Configuration tab= le. > + > + @param PciDevice A pointer to the PCI_IO_DEVIC= E. > + @param PciFeaturesConfigTable A pointer to a pointer to the > + PCI_EXPRESS_FEATURES_CONFIGUR= ATION_TABLE. > + Returns NULL in case of RCiEP= or the PCI > + device does match with any of= the physical > + Root ports, or it does not be= long to any > + Root port's PCI bus range (no= t a child) > + > + @retval EFI_SUCCESS able to determine the PCI fea= ture > + configuration table. For RCiE= P since > + since it is not prepared. > + EFI_DEVICE_ERROR the PCI device has invalid EF= I 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 f= eatures > + // configuration table > + // > + *PciFeaturesConfigTable =3D NULL; > + return EFI_SUCCESS; > + } > + > + // > + // The PCI features configuration table is not built for RCiEP, retur= n NULL > + // > + if (PciDevice->PciExpressCapabilityStructure.Capability.Bits.DevicePo= rtType =3D=3D > \ > + PCIE_DEVICE_PORT_TYPE_ROOT_COMPLEX_INTEGRATED_ENDPOINT) { > + *PciFeaturesConfigTable =3D NULL; > + return EFI_SUCCESS; > + } > + > + if (IsDevicePathEnd (PciDevice->DevicePath)){ > + // > + // the given PCI device does not have a valid device path > + // > + *PciFeaturesConfigTable =3D NULL; > + return EFI_DEVICE_ERROR; > + } > + > + > + Link =3D mRootBridgeDeviceList.ForwardLink; > + do { > + Temp =3D ROOT_BRIDGE_DEVICE_NODE_FROM_LINK (Link); > + RootPortPath =3D Temp->RootBridgeDevicePath; > + PciDevicePath =3D PciDevice->DevicePath; > + NodeMatch =3D FALSE; > + // > + // match the device path from the list of primary Root Ports with t= he 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 =3D NULL; > + return EFI_DEVICE_ERROR; > + } > + > + if (EfiCompareDevicePath (RootPortPath, PciDevicePath)) { > + // > + // the given PCI device is the primary root port itself > + // > + *PciFeaturesConfigTable =3D Temp->PciExFeaturesConfigurationTable= ; > + return EFI_SUCCESS; > + } > + // > + // check this PCI device belongs to the primary root port of the ro= ot bridge > + // any child PCI device will have the same initial device path node= s as > + // its parent root port > + // > + while (!IsDevicePathEnd (RootPortPath)){ > + > + if (DevicePathNodeLength (RootPortPath) !=3D DevicePathNodeLength > (PciDevicePath)) { > + // > + // break to check the next primary root port nodes as does not = match > + // > + NodeMatch =3D FALSE; > + break; > + } > + if (CompareMem (RootPortPath, PciDevicePath, DevicePathNodeLength > (RootPortPath)) !=3D 0) { > + // > + // node does not match, break to check next node > + // > + NodeMatch =3D FALSE; > + break; > + } > + NodeMatch =3D TRUE; > + // > + // advance to next node > + // > + RootPortPath =3D NextDevicePathNode (RootPortPath); > + PciDevicePath =3D NextDevicePathNode (PciDevicePath); > + } > + > + if (NodeMatch =3D=3D TRUE) { > + // > + // device belongs to primary root port, return its PCI feature co= nfiguration > + // table > + // > + *PciFeaturesConfigTable =3D Temp->PciExFeaturesConfigurationTable= ; > + return EFI_SUCCESS; > + } > + > + // > + // advance to next Root port node > + // > + Link =3D Link->ForwardLink; > + } while (Link !=3D &mRootBridgeDeviceList && Link !=3D NULL); > + // > + // the PCI device must be RCiEP, does not belong to any primary root = port > + // > + *PciFeaturesConfigTable =3D 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 poli= cy 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 =3D NULL; > + Status =3D GetPciExpressFeaturesConfigurationTable (PciDevice, > &PciExpressFeaturesConfigTable); > + > + if (PciConfigPhase =3D=3D PciExpressFeatureSetupPhase) { > + DEBUG_CODE ( > + if (EFI_ERROR( Status)) { > + DEBUG (( > + DEBUG_WARN, > + "[Cfg group: 0 {error in dev path}]" > + )); > + } else if (PciExpressFeaturesConfigTable =3D=3D NULL) { > + DEBUG (( > + DEBUG_INFO, > + "[Cfg group: 0]" > + )); > + } else { > + DEBUG (( > + DEBUG_INFO, > + "[Cfg group: %d]", > + PciExpressFeaturesConfigTable->ID > + )); > + } > + PcieCap.Uint16 =3D PciDevice- > >PciExpressCapabilityStructure.Capability.Uint16; > + DumpDevicePortType ((UINT8)PcieCap.Bits.DevicePortType); > + ); > + > + // > + // get the device-specific platform policy for the PCI Express feat= ures > + // > + Status =3D PciExpressPlatformGetDevicePolicy (PciDevice); > + if (EFI_ERROR(Status)) { > + DEBUG (( > + DEBUG_ERROR, > + "Error in obtaining PCI device policy!!!\n" > + )); > + } > + } > + > + DEBUG ((DEBUG_INFO, "[")); > + > + Status =3D DispatchPciExpressInitializationFunctions ( > + PciDevice, > + PciConfigPhase, > + PciExpressFeaturesConfigTable > + ); > + > + DEBUG ((DEBUG_INFO, "]\n")); > + return Status; > +} > + > +/** > + Create and append a node of type BRIDGE_DEVICE_NODE in the list for t= he > 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 n= ode > +**/ > +EFI_STATUS > +CreatePciRootBridgeDeviceNode ( > + IN PCI_IO_DEVICE *BridgePort, > + IN UINTN PortNumber > + ) > +{ > + BRIDGE_DEVICE_NODE *RootBridgeNode =3D NULL; > + PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE *PciConfigTable =3D NULL; > + > + RootBridgeNode =3D AllocateZeroPool (sizeof (BRIDGE_DEVICE_NODE)); > + if (RootBridgeNode =3D=3D NULL) { > + return EFI_OUT_OF_RESOURCES; > + } > + RootBridgeNode->Signature =3D > PCI_ROOT_BRIDGE_DEVICE_SIGNATURE; > + RootBridgeNode->RootBridgeDevicePath =3D BridgePort->DeviceP= ath; > + PciConfigTable =3D AllocateZeroPool ( > + sizeof (PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE) > + ); > + if (PciConfigTable) { > + PciConfigTable->ID =3D PortNumber; > + } > + > + RootBridgeNode->PciExFeaturesConfigurationTable =3D PciConfigTable; > + > + InsertTailList (&mRootBridgeDeviceList, &RootBridgeNode- > >NextRootBridgeDevice); > + > + if (PciConfigTable =3D=3D NULL) { > + return EFI_OUT_OF_RESOURCES; > + } > + return EFI_SUCCESS; > +} > + > +/** > + Scan all the nodes of the RootBridge to identify and create a separat= e list > + of all primary physical PCI root ports and link each with its own ins= tance 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 physica= l 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 =3D EFI_NOT_FOUND; > + LIST_ENTRY *Link; > + PCI_IO_DEVICE *Device; > + UINTN BridgeDeviceCount; > + > + BridgeDeviceCount =3D 0; > + for ( Link =3D RootBridge->ChildList.ForwardLink > + ; Link !=3D &RootBridge->ChildList > + ; Link =3D Link->ForwardLink > + ) { > + Device =3D 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, Dev= ice- > >FunctionNumber > + )); > + // > + // create a list of bridge devices if that is connected to any ot= her device > + // > + if (!IsListEmpty (&Device->ChildList)) { > + DEBUG (( > + DEBUG_INFO, > + "- has downstream device!\n" > + )); > + Status =3D CreatePciRootBridgeDeviceNode (Device, BridgeDeviceC= ount); > + if (EFI_ERROR (Status)) { > + DEBUG (( > + DEBUG_ERROR, > + "PCI configuration table allocation failure for #%d ::Bridg= e > [%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 =3D SetupDevicePciExpressFeatures (PciDevice, PciConfigPha= se); > + break; > + case PciExpressFeatureEndPhase: > + Status =3D PciExpressPlatformNotifyDeviceState (PciDevice); > + break; > + } > + return Status; > +} > + > +/** > + Traverse all the nodes from the root bridge or PCI-PCI bridge instanc= e, to > + configure the PCI Express features as per the PCI Express Base Secifi= cation > + by considering its device-specific platform policy, and its device ca= pability, > + as applicable. > + > + @param RootBridge A pointer to the PCI_IO_DEVICE. > + > + @retval EFI_SUCCESS Traversing all the nodes of the root br= idge > + 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 =3D RootBridge->ChildList.ForwardLink > + ; Link !=3D &RootBridge->ChildList > + ; Link =3D Link->ForwardLink > + ) { > + Device =3D 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 =3D InitializeDevicePciExpressFeatures ( > + Device, > + PciConfigPhase > + ); > + } else { > + DEBUG (( > + DEBUG_INFO, > + "Not a PCIe capable device!\n" > + )); > + // > + // PCI Bridge which does not have PCI Express Capability struct= ure > + // 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 =3D InitializeDevicePciExpressFeatures ( > + Device, > + PciConfigPhase > + ); > + } else { > + DEBUG (( > + DEBUG_INFO, > + "Not a PCIe capable device!\n" > + )); > + // > + // PCI Device which does not have PCI Express Capability struct= ure > + // cannot process this kind of PCI device > + // > + } > + } > + } > + > + return EFI_SUCCESS; > +} > + > +/** > + Enumerate all the nodes of the specified root bridge or PCI-PCI Bridg= e, to > + configure the other PCI features. > + > + @param RootBridge A pointer to the PCI_IO_DEVICE. > + > + @retval EFI_SUCCESS The other PCI features configuration du= ring > enumeration > + of all the nodes of the PCI root bridge= instance were > + programmed in PCI-compliance pattern al= ong 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 incompa= tible address > + range. > + @retval EFI_INVALID_PARAMETER The override operation is performed wit= h > 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 =3D Controller; > + > + DEBUG_CODE ( > + CHAR16 *Str; > + Str =3D ConvertDevicePathToText ( > + DevicePathFromHandle (RootBridge->Handle), > + FALSE, > + FALSE > + ); > + DEBUG (( > + DEBUG_INFO, > + "Enumerating PCI features for Root Bridge %s\n", > + Str !=3D NULL ? Str : L"" > + )); > + > + if (Str !=3D NULL) { > + FreePool (Str); > + } > + ); > + > + for ( PciExpressFeatureConfigPhase =3D PciExpressFeaturePreProcessPha= se > + ; PciExpressFeatureConfigPhase <=3D PciExpressFeatureEndPhase > + ; PciExpressFeatureConfigPhase++ > + ) { > + DEBUG (( > + DEBUG_INFO, > + "<<********** Phase [%d]**********>>\n", > + PciExpressFeatureConfigPhase > + )); > + if (PciExpressFeatureConfigPhase =3D=3D PciExpressFeaturePreProcess= Phase) { > + // > + // 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 =3D=3D PciExpressFeatureEntendedSe= tupPhase) > { > + if (!IsPciExpressFeatureExtendedSetupRequired ()) { > + // > + // since the PCI Express features require no extra initializati= on steps > + // skip this phase > + // > + continue; > + } > + } > + // > + // setup the PCI Express features > + // > + Status =3D InitializePciExpressFeatures (RootBridge, > PciExpressFeatureConfigPhase); > + > + if (PciExpressFeatureConfigPhase =3D=3D PciExpressFeatureEndPhase) = { > + // > + // clean up the temporary resource nodes created for this root br= idge > + // > + 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 mod= ule.. > + > +Copyright (c) 2020, Intel Corporation. All rights reserved.
> +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 ot= her 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 Tab= le node > + // all the child PCI devices of the controller are aligned based on t= his 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 configu= re 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 use= ful to > align > + // all devices with a common value. This would be optional phase base= d 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 P= CI > 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 s= pecific > + // or it can be reserved and remain unused > + // > + UINT8 Support : 6; > + // > + // if set indicates override the feature policy defined by the member= s above > + // if clear it indicates that this feature policy should be ignored c= ompletely > + // 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 phas= es > +// > +typedef > +EFI_STATUS > +(*PCI_EXPRESS_FEATURE_CONFIGURATION_ROUTINE) ( > + IN PCI_IO_DEVICE *PciDevice, > + IN VOID *PciExpressFeatureConfigu= ration > + ); > + > +// > +// 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 ph= ases > + > +Copyright (c) 2020, Intel Corporation. All rights reserved.
> +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 LocateProto= col () > + boot service for the PCI Express Override= Protocol > + EFI_SUCCESS The PCI Express Platform Protocol is foun= d > +**/ > +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 =3D 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 Expre= ss > Platform > + Protocol (or PCI Express Override Protocol) to indicate that this dri= ver can > + initialize the PCI Express features. > + @retval TRUE or FALSE > +**/ > +BOOLEAN > +IsPciExpressProtocolPresent ( > + ) > +{ > + if ( > + mPciExPlatformProtocol =3D=3D NULL > + && mPciExOverrideProtocol =3D=3D NULL > + ) { > + return FALSE; > + } > + return TRUE; > +} > + > + > +/** > + Generic routine to setup the PCI features as per its predetermined de= faults. > +**/ > +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 =3D 0 > + , PciExpressPolicy =3D (UINT8*)&mPciExpressPlatformPolicy > + , PciExDevicePolicy =3D (UINT8*)PciExpressDevicePolicy > + ; length < sizeof (EFI_PCI_EXPRESS_PLATFORM_POLICY) > + ; length++ > + ) { > + if (!PciExpressPolicy[length]) { > + PciExDevicePolicy[length] =3D EFI_PCI_EXPRESS_NOT_APPLICABLE; > + } > + } > +} > + > +/** > + Intermediate routine to either get the PCI device specific platform p= olicies > + through the PCI Platform Protocol, or its alias the PCI Override Prot= ocol. > + > + @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 P= rotocol > + @retval EFI_SUCCESS if on returning predetermined PCI feature= s defaults, > + for the case when protocol returns as EFI= _UNSUPPORTED > + to indicate PCI device exist and it has n= o 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 =3D PciDevice->BusNumber; > + PciAddress.Device =3D PciDevice->DeviceNumber; > + PciAddress.Function =3D PciDevice->FunctionNumber; > + PciAddress.Register =3D 0; > + PciAddress.ExtendedRegister =3D 0; > + > + InitializeDevicePolicyData (&PciExpressDevicePolicy); > + Status =3D 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 =3D=3D 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 Pla= tform > Protocol. > + If no PCI Platform protocol is published than setup the PCI feature t= o > 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 Protoco= l > + @retval EFI_SUCCESS On return of predetermined PCI features default= s, for > + the case when protocol returns as EFI_UNSUPPORT= ED to > + indicate PCI device exist and it has no platfor= m policy > + defined. Also, on returns when no PCI Platform = Protocol > + exist. > +**/ > +EFI_STATUS > +PciExpressPlatformGetDevicePolicy ( > + IN PCI_IO_DEVICE *PciDevice > + ) > +{ > + if (mPciExPlatformProtocol !=3D NULL) { > + return GetPciExpressDevicePolicy (PciDevice, mPciExPlatformProtocol= ); > + } else if (mPciExOverrideProtocol !=3D NULL) { > + return GetPciExpressDevicePolicy (PciDevice, mPciExOverrideProtocol= ); > + } else { > + // > + // no protocol found, platform does not require the PCI Express ini= tialization > + // > + 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 l= ist 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 =3D mPciExPlatformProtocol->GetPolicy ( > + mPciExPlatformProtocol, > + sizeof (EFI_PCI_EXPRESS_PLATFORM_= POLICY), > + &mPciExpressPlatformPolicy > + ); > + } else if (mPciExOverrideProtocol) { > + Status =3D mPciExOverrideProtocol->GetPolicy ( > + mPciExOverrideProtocol, > + sizeof (EFI_PCI_EXPRESS_PLATFORM_= POLICY), > + &mPciExpressPlatformPolicy > + ); > + } else { > + // > + // no protocol found, platform does not require the PCI Express ini= tialization > + // > + return EFI_UNSUPPORTED; > + } > + return Status; > +} > + > + > +/** > + Notifies the platform about the current PCI Express state of the devi= ce. > + > + @param PciDevice A pointer to PCI_IO_DEVICE > + @param PciExDeviceConfiguration Pointer to > EFI_PCI_EXPRESS_DEVICE_CONFIGURATION. > + Used to pass the current state of d= evice to > + platform. > + > + @retval EFI_STATUS The direct status from the PCI Express Plat= form > Protocol > + @retval EFI_UNSUPPORTED returns when the PCI Express Platform Proto= col > 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 !=3D NULL) { > + return mPciExPlatformProtocol->NotifyDeviceState ( > + mPciExPlatformProtocol, > + PciDevice->Handle, > + sizeof (EFI_PCI_EXPRESS_DEVICE_CONF= IGURATION), > + &PciExDeviceConfiguration > + ); > + } else if (mPciExOverrideProtocol !=3D NULL) { > + return mPciExOverrideProtocol->NotifyDeviceState ( > + mPciExOverrideProtocol, > + PciDevice->Handle, > + sizeof (EFI_PCI_EXPRESS_DEVICE_CONF= IGURATION), > + &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 ph= ases > + > +Copyright (c) 2020, Intel Corporation. All rights reserved.
> +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 LocateProto= col () > + boot service for the PCI Express Override= Protocol > + EFI_SUCCESS The PCI Express Platform Protocol is foun= d > +**/ > +EFI_STATUS > +GetPciExpressProtocol ( > + ); > + > +/** > + This function indicates that the platform has published the PCI Expre= ss > Platform > + Protocol (or PCI Express Override Protocol) to indicate that this dri= ver 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 l= ist 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 Pr= otocol. > + If no PCI Platform protocol is published than setup the PCI feature t= o > 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 Protoco= l > + @retval EFI_SUCCESS On return of predetermined PCI features default= s, for > + the case when protocol returns as EFI_UNSUPPORT= ED to > + indicate PCI device exist and it has no platfor= m 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 devi= ce. > + > + @param PciDevice A pointer to PCI_IO_DEVICE > + @param PciExDeviceConfiguration Pointer to > EFI_PCI_EXPRESS_DEVICE_CONFIGURATION. > + Used to pass the current state of d= evice to > + platform. > + > + @retval EFI_STATUS The direct status from the PCI Express Plat= form > Protocol > + @retval EFI_UNSUPPORTED returns when the PCI Express Platform Proto= col > or its > + alias PCI Express OVerride Protocol is not = present. > +**/ > +EFI_STATUS > +PciExpressPlatformNotifyDeviceState ( > + IN PCI_IO_DEVICE *PciDevice > + ); > +#endif > -- > 2.21.0.windows.1 >=20 >=20 >=20