From nobody Tue Nov 26 14:42:51 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+54064+1787277+3901457@groups.io; helo=web01.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+54064+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 1581105962176355.4729925580584; Fri, 7 Feb 2020 12:06:02 -0800 (PST) Return-Path: X-Received: by 127.0.0.2 with SMTP id GtHeYY1788612xqei5M7Hzwn; Fri, 07 Feb 2020 12:06:01 -0800 X-Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by mx.groups.io with SMTP id smtpd.web09.10520.1581105960932621955 for ; Fri, 07 Feb 2020 12:06:01 -0800 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-Received: from fmsmga007.fm.intel.com ([10.253.24.52]) by fmsmga103.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 07 Feb 2020 12:06:00 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.70,414,1574150400"; d="scan'208";a="225644120" X-Received: from unknown (HELO PIDSBABIOS005.gar.corp.intel.com) ([10.223.9.183]) by fmsmga007.fm.intel.com with ESMTP; 07 Feb 2020 12:05:56 -0800 From: "Javeed, Ashraf" To: devel@edk2.groups.io Cc: Jian J Wang , Hao A Wu , Ray Ni Subject: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 01/12] MdeModulePkg/PciBusDxe: Setup for PCI Express features Date: Sat, 8 Feb 2020 01:34:36 +0530 Message-Id: <20200207200447.10536-2-ashraf.javeed@intel.com> In-Reply-To: <20200207200447.10536-1-ashraf.javeed@intel.com> References: <20200207200447.10536-1-ashraf.javeed@intel.com> MIME-Version: 1.0 Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,ashraf.javeed@intel.com X-Gm-Message-State: fPPcftBL08GqP63nnfoi8rh2x1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1581105961; bh=Q7noTEk8O4Dm9afAUvFtHmTZhYtZs5jH0d2AG/1mig4=; h=Cc:Date:From:Reply-To:Subject:To; b=mdITvY/s/xaL238mtP93B5a0bfBspCmpTKVPCj6YIzMAK29T2hhUfLwlmdIBoS3b8eb LYKmN/jwvTRCiJNBXEQ3rNL0JRk1qkWeT78olYMpDknwc3W+ZHyG/PTT3BxY+o5+2A5G7 C0nPzXLpbem5wA2AFJuEm0EZuevJO05atko= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Type: text/plain; charset="utf-8" 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 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 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(-) 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 PciExpressCapabilityStructure; + // + // For SR-IOV + // UINT32 AriCapabilityOffset; UINT32 SrIovCapabilityOffset; UINT32 MrIovCapabilityOffset; diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf b/MdeModulePkg/Bu= s/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_CONS= UMES + gEfiPciExpressOverrideProtocolGuid ## SOMETIMES_CONS= UMES + =20 [FeaturePcd] gEfiMdeModulePkgTokenSpaceGuid.PcdPciBusHotplugDeviceSupport ## CON= SUMES diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c b/MdeMod= ulePkg/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/MdeModule= Pkg/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.
+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 ph= ysical + PCI Root Ports (PCI Controllers) for a given PCI Root Bridge instance wh= ile + 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 =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 sup= ported +// PCI features to be configured +// +BOOLEAN mPciExpressGetPlatformPolicyComplete =3D FALSE; + +// +// PCI Express feature initialization phase handle routines +// +PCI_EXPRESS_FEATURE_INITIALIZATION_POINT mPciExpressFeatureInitialization= List[] =3D { + // + // vacant entry, shall be replaced with actual entry when the PCI Expr= ess + // feature are added. + // + { 0, 0, NULL} +}; + +/** + Routine to serially dispatch the designated the PCI Express feature spec= ific + functions defined for each of the configuration phase. The order for eac= h phase + would be based entirely on the table mPciExpressFeatureInitializationLis= t. + + @param PciDevice pointer to PCI_IO_DEVICE to iden= tify device + @param PciExFeatureConfigPhase input configuration phase + @param PciExpressFeatureConfiguration used pointer to void to accomoda= te any PCI + Express feature specific data ty= pe + @retval EFI_STATUS output only from feature specifi= c function + defined in the table mPciExpress= FeatureInitializationList +**/ +EFI_STATUS +DispatchPciExpressInitializationFunctions ( + IN PCI_IO_DEVICE *PciDevice, + IN PCI_EXPRESS_FEATURE_CONFIGURATION_PHASE PciExFeatureConfigPhase, + IN VOID *PciExpressFeatureConfigurat= ion + ) +{ + UINTN idx; + EFI_STATUS Status; + UINT8 *PciExpressPolicy; + + for ( + idx =3D 0, PciExpressPolicy =3D (UINT8*)&mPciExpressPlatformPolicy + ; idx < sizeof (mPciExpressFeatureInitializationList) / sizeof (PCI_= EXPRESS_FEATURE_INITIALIZATION_POINT) + ; idx++ + ){ + if ( + // + // match the configuration phase + // + mPciExpressFeatureInitializationList[idx].PciExpressFeatureConfigu= rationPhase =3D=3D PciExFeatureConfigPhase + // + // check whether the PCI Express features is enabled + // + && PciExpressPolicy[mPciExpressFeatureInitializationList[idx].PciE= xpressFeatureId] =3D=3D TRUE + ) { + Status =3D mPciExpressFeatureInitializationList[idx].PciExpressFeat= ureConfigurationRoutine ( + PciDevice, + PciExpressFeat= ureConfiguration + ); + } + } + return Status; +} + +/** + Main routine to indicate platform selection of any of the other PCI feat= ures + to be configured by this driver + + @retval TRUE platform has selected the other PCI features to be confi= gured + FALSE platform has not selected any of the other PCI features +**/ +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 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 =3D TRUE; + + Status =3D 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 r= equires + 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 =3D 0, PciExpressPolicy =3D (UINT8*)&mPciExpressPlatformPolicy + ; idx < sizeof (mPciExpressFeatureInitializationList) / sizeof (PCI_= EXPRESS_FEATURE_INITIALIZATION_POINT) + ; idx++ + ){ + if ( + // + // match the configuration phase to extended setup phase + // + mPciExpressFeatureInitializationList[idx].PciExpressFeatureConfigu= rationPhase =3D=3D PciExpressFeatureEntendedSetupPhase + // + // check whether the PCI Express features is enabled + // + && PciExpressPolicy[mPciExpressFeatureInitializationList[idx].PciE= xpressFeatureId] =3D=3D TRUE + ) { + return TRUE; + } + } + + return FALSE; +} + +/** + Helper routine to determine the existence of previously enumerated PCI de= vice + + @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 PC= I 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 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_CONFIGURATI= ON_TABLE. + Returns NULL in case of RCiEP or= the PCI + device does match with any of th= e physical + Root ports, or it does not belon= g to any + Root port's PCI bus range (not a= child) + + @retval EFI_SUCCESS able to determine the PCI feature + configuration table. For RCiEP s= ince + since it is not prepared. + EFI_DEVICE_ERROR the PCI device has invalid EFI d= evice + 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 feat= ures + // configuration table + // + *PciFeaturesConfigTable =3D NULL; + return EFI_SUCCESS; + } + + // + // The PCI features configuration table is not built for RCiEP, return N= ULL + // + if (PciDevice->PciExpressCapabilityStructure.Capability.Bits.DevicePortT= ype =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 the = given + // device; the initial nodes matching in sequence indicate that the gi= ven 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 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) !=3D DevicePathNodeLength (P= ciDevicePath)) { + // + // break to check the next primary root port nodes as does not mat= ch + // + NodeMatch =3D FALSE; + break; + } + if (CompareMem (RootPortPath, PciDevicePath, DevicePathNodeLength (R= ootPortPath)) !=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 confi= guration + // 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 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 =3D NULL; + Status =3D GetPciExpressFeaturesConfigurationTable (PciDevice, &PciExpre= ssFeaturesConfigTable); + + 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.Capabili= ty.Uint16; + DumpDevicePortType ((UINT8)PcieCap.Bits.DevicePortType); + ); + + // + // get the device-specific platform policy for the PCI Express features + // + 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 the = primary + Root Port so that all its child PCI devices can be identified against th= e PCI + features configuration table group ID, of type PCI_EXPRESS_FEATURES_CONF= IGURATION_TABLE. + + @param BridgePort A pointer to the PCI_IO_DEVICE + @param PortNumber A UINTN value to identify the PCI feature configura= tion + 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 =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->DevicePath; + PciConfigTable =3D AllocateZeroPool ( + sizeof (PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE) + ); + if (PciConfigTable) { + PciConfigTable->ID =3D PortNumber; + } + + RootBridgeNode->PciExFeaturesConfigurationTable =3D PciConfigTable; + + InsertTailList (&mRootBridgeDeviceList, &RootBridgeNode->NextRootBridgeD= evice); + + 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 separate l= ist + of all primary physical PCI root ports and link each with its own instan= ce of + the PCI Feature Configuration Table. + + @param RootBridge A pointer to the PCI_IO_DEVICE of the PCI Root Bri= dge + + @retval EFI_OUT_OF_RESOURCES unable to allocate buffer to store PCI fea= ture + configuration table for all the physical P= CI root + ports given + EFI_NOT_FOUND No PCI Bridge device found + EFI_SUCCESS PCI Feature COnfiguration table created fo= r all + the PCI Rooot ports found + EFI_INVALID_PARAMETER invalid parameter passed to the routine wh= ich + creates the PCI controller node for the pr= imary + 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, 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 =3D CreatePciRootBridgeDeviceNode (Device, BridgeDeviceCoun= t); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "PCI configuration table allocation failure for #%d ::Bridge [= %02x|%02x|%02x]\n", + BridgeDeviceCount, Device->BusNumber, Device->DeviceNumber, De= vice->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 bri= dge + 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, PciConfigPhase); + break; + case PciExpressFeatureEndPhase: + Status =3D 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 Secificat= ion + by considering its device-specific platform policy, and its device capab= ility, + 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 =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 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 =3D 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 durin= g enumeration + of all the nodes of the PCI root bridge in= stance were + programmed in PCI-compliance pattern along= with the + device-specific policy, as applicable. + @retval EFI_UNSUPPORTED One of the override operation maong the no= des of + the PCI hierarchy resulted in a incompatib= le address + range. + @retval EFI_INVALID_PARAMETER The override operation is performed with i= nvalid 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 PciExpressFeaturePreProcessPhase + ; PciExpressFeatureConfigPhase <=3D PciExpressFeatureEndPhase + ; PciExpressFeatureConfigPhase++ + ) { + DEBUG (( + DEBUG_INFO, + "<<********** Phase [%d]**********>>\n", + PciExpressFeatureConfigPhase + )); + if (PciExpressFeatureConfigPhase =3D=3D PciExpressFeaturePreProcessPha= se) { + // + // create a list of root bridge devices (root ports) of the root com= plex + // if extra setup phase required + // + if (IsPciExpressFeatureExtendedSetupRequired ()) { + CreatePciRootBridgeDeviceList (RootBridge); + } + continue; + } + if (PciExpressFeatureConfigPhase =3D=3D PciExpressFeatureEntendedSetup= Phase) { + if (!IsPciExpressFeatureExtendedSetupRequired ()) { + // + // since the PCI Express features require no extra initialization = steps + // skip this phase + // + continue; + } + } + // + // setup the PCI Express features + // + Status =3D InitializePciExpressFeatures (RootBridge, PciExpressFeature= ConfigPhase); + + if (PciExpressFeatureConfigPhase =3D=3D 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/MdeModule= Pkg/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.
+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 mPciExpressPlatformPol= icy; +// +// defines the data structure to hold the details of the PCI Root port dev= ices +// +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_FEAT= URES_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 *PciExFeaturesConfigurationTab= le; +}; + +#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 o= n the + // type of the PCI Express feature to be programmed based on platform po= licy + // + PciExpressFeaturePreProcessPhase, + + // + // mandatory phase to setup the PCI Express feature to its applicable at= tribute, + // based on its device-specific platform policies, matching with its dev= ice capabilities + // + PciExpressFeatureSetupPhase, + + // + // optional phase primarily to align all devices, specially required whe= n PCI + // switch is present in the hierarchy, applicable to certain few PCI Exp= ress + // 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 pr= epared + // 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 spec= ific + // or it can be reserved and remain unused + // + UINT8 Support : 6; + // + // if set indicates override the feature policy defined by the members a= bove + // if clear it indicates that this feature policy should be ignored comp= letely + // 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 *PciExpressFeatureConfigurat= ion + ); + +// +// data type for the PCI Express feature initialization phases +// +typedef struct { + // + // Pci Express feature configuration phase + // + PCI_EXPRESS_FEATURE_CONFIGURATION_PHASE PciExpressFeatureConfiguration= Phase; + // + // PCI Express feature Id + // + PCI_EXPRESS_FEATURE_ID PciExpressFeatureId; + // + // PCI Express feature configuration routine + // + PCI_EXPRESS_FEATURE_CONFIGURATION_ROUTINE PciExpressFeatureConfiguration= Routine; + +}PCI_EXPRESS_FEATURE_INITIALIZATION_POINT; + + +#endif diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c b/MdeModul= ePkg/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.
+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 Pr= otocol + 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 =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 Ex= press + // 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 =3D=3D NULL + && mPciExOverrideProtocol =3D=3D NULL + ) { + return FALSE; + } + return TRUE; +} + + +/** + Generic routine to setup the PCI features as per its predetermined defau= lts. +**/ +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 poli= cies + through the PCI Platform Protocol, or its alias the PCI Override Protoco= l. + + @param PciDevice A pointer to PCI_IO_DEVICE + @param PciPlatformProtocol A pointer to EFI_PCI_EXPRESS_PLATFORM_PROTOC= OL + + @retval EFI_STATUS The direct status from the PCI Platform Prot= ocol + @retval EFI_SUCCESS if on returning predetermined PCI features d= efaults, + for the case when protocol returns as EFI_UN= SUPPORTED + to indicate PCI device exist and it has no p= latform + 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 Platfo= rm Protocol. + If no PCI Platform protocol is published than setup the PCI feature to p= redetermined + 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 p= olicy + defined. Also, on returns when no PCI Platform Pro= tocol + 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 initia= lization + // + return EFI_UNSUPPORTED; + } +} + +/** + This function gets the platform requirement to initialize the list of PC= I 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 arg= uements + 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_POL= ICY), + &mPciExpressPlatformPolicy + ); + } else if (mPciExOverrideProtocol) { + Status =3D mPciExOverrideProtocol->GetPolicy ( + mPciExOverrideProtocol, + sizeof (EFI_PCI_EXPRESS_PLATFORM_POL= ICY), + &mPciExpressPlatformPolicy + ); + } else { + // + // no protocol found, platform does not require the PCI Express initia= lization + // + 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_CONF= IGURATION. + Used to pass the current state of devi= ce to + platform. + + @retval EFI_STATUS The direct status from the PCI Express Platfor= m Protocol + @retval EFI_UNSUPPORTED returns when the PCI Express Platform Protocol= or its + alias PCI Express OVerride Protocol is not pre= sent. +**/ +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_CONFIGU= RATION), + &PciExDeviceConfiguration + ); + } else if (mPciExOverrideProtocol !=3D NULL) { + return mPciExOverrideProtocol->NotifyDeviceState ( + mPciExOverrideProtocol, + PciDevice->Handle, + sizeof (EFI_PCI_EXPRESS_DEVICE_CONFIGU= RATION), + &PciExDeviceConfiguration + ); + } else { + // + // unexpected error + // + return EFI_UNSUPPORTED; + } +} + diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h b/MdeModul= ePkg/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.
+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 Pr= otocol + 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 PC= I 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 arg= uements + passed + EFI_UNSUPPORTED platform did not published the protocol +**/ +EFI_STATUS +PciExpressPlatformGetPolicy ( + ); + +/** + Gets the PCI device-specific platform policy from the PCI Platform Proto= col. + If no PCI Platform protocol is published than setup the PCI feature to p= redetermined + 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 p= olicy + defined. Also, on returns when no PCI Platform Pro= tocol + 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_CONF= IGURATION. + Used to pass the current state of devi= ce to + platform. + + @retval EFI_STATUS The direct status from the PCI Express Platfor= m Protocol + @retval EFI_UNSUPPORTED returns when the PCI Express Platform Protocol= or its + alias PCI Express OVerride Protocol is not pre= sent. +**/ +EFI_STATUS +PciExpressPlatformNotifyDeviceState ( + IN PCI_IO_DEVICE *PciDevice + ); +#endif --=20 2.21.0.windows.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#54064): https://edk2.groups.io/g/devel/message/54064 Mute This Topic: https://groups.io/mt/71063071/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-