From: "Javeed, Ashraf" <ashraf.javeed@intel.com>
To: devel@edk2.groups.io
Cc: Jian J Wang <jian.j.wang@intel.com>,
Hao A Wu <hao.a.wu@intel.com>, Ray Ni <ray.ni@intel.com>
Subject: [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 05/12] PciBusDxe: Setup sub-phases for PCI feature enumeration
Date: Fri, 1 Nov 2019 20:39:45 +0530 [thread overview]
Message-ID: <20191101150952.3340-6-ashraf.javeed@intel.com> (raw)
In-Reply-To: <20191101150952.3340-1-ashraf.javeed@intel.com>
BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=2194
The code changes are made to setup the following internal sub-phases for
enumerating the PCI features in the late phase of the PCI Bus driver.
(1) PciFeatureRootBridgeScan - initial phase in configuring the other PCI
features to record the primary root ports
(2) PciFeatureGetDevicePolicy - get the PCI device-specific platform pol-
icies and align with device capabilities
(3) PciFeatureSetupPhase - align all PCI nodes in the PCI heirarchical
tree (if required for that PCI feature)
(4) PciFeatureConfigurationPhase - finally override to complete configu-
ration of the PCI feature
The code changes are made to support the configuration of other PCIe
features, like MPS, which require a common value to be assigned among
all the child PCI devices and its parent root port device.
Signed-off-by: Ashraf Javeed <ashraf.javeed@intel.com>
Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Hao A Wu <hao.a.wu@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
---
MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c | 859 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h | 146 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 1005 insertions(+)
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
index 8be227a..ab0e096 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
@@ -9,6 +9,23 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include "PciBus.h"
#include "PciFeatureSupport.h"
+/**
+ A gobal pointer to PRIMARY_ROOT_PORT_NODE buffer to track all the primary physical
+ PCI Root Ports (PCI Controllers) for a given PCI Root Bridge instance while
+ enumerating to configure the PCI features
+**/
+PRIMARY_ROOT_PORT_NODE *mPrimaryRootPortList;
+
+/**
+ A global pointer to PCI_FEATURE_CONFIGURATION_COMPLETION_LIST, which stores all
+ the PCI Root Bridge instances that are enumerated for the other PCI features,
+ like MaxPayloadSize & MaxReadReqSize; during the the Start() interface of the
+ driver binding protocol. The records pointed by this pointer would be destroyed
+ when the DXE core invokes the Stop() interface.
+**/
+PCI_FEATURE_CONFIGURATION_COMPLETION_LIST *mPciFeaturesConfigurationCompletionList = NULL;
+
+
/**
Main routine to indicate whether the platform has selected the Max_Payload_Size
PCI feature to be configured by this driver
@@ -175,3 +192,845 @@ SetupPtm (
{
return (PcdGet32 (PcdOtherPciFeatures) & PCI_FEATURE_SUPPORT_FLAG_PTM) ? TRUE : FALSE;
}
+
+/**
+ Helper routine to determine the existence of previously enumerated PCI device
+
+ @retval TRUE PCI device exist
+ FALSE does not exist
+**/
+BOOLEAN
+DeviceExist (
+ PCI_IO_DEVICE *PciDevice
+ )
+{
+ EFI_PCI_IO_PROTOCOL *PciIoProtocol = &PciDevice->PciIo;
+ UINT16 VendorId = 0xFFFF;
+
+ PciIoProtocol->Pci.Read (
+ PciIoProtocol,
+ EfiPciIoWidthUint16,
+ PCI_VENDOR_ID_OFFSET,
+ 1,
+ &VendorId
+ );
+ if (VendorId == 0 || VendorId == 0xFFFF) {
+ return FALSE;
+ } else {
+ return TRUE;
+ }
+}
+
+/**
+ Helper routine which determines whether the given PCI Root Bridge instance
+ record already exist. This routine shall help avoid duplicate record creation
+ in case of re-enumeration of PCI configuation features.
+
+ @param RootBridge A pointer to the PCI_IO_DEVICE for the Root Bridge
+ @param PciFeatureConfigRecord A pointer to a pointer for type
+ PCI_FEATURE_CONFIGURATION_COMPLETION_LIST
+ record, Use to return the specific record.
+
+ @retval TRUE Record already exist
+ FALSE Record does not exist for the given PCI Root Bridge
+**/
+BOOLEAN
+CheckPciFeatureConfigurationRecordExist (
+ IN PCI_IO_DEVICE *RootBridge,
+ OUT PCI_FEATURE_CONFIGURATION_COMPLETION_LIST **PciFeatureConfigRecord
+ )
+{
+ LIST_ENTRY *Link;
+ PCI_FEATURE_CONFIGURATION_COMPLETION_LIST *Temp;
+
+ if (mPciFeaturesConfigurationCompletionList) {
+ Link = &mPciFeaturesConfigurationCompletionList->RootBridgeLink;
+
+ do {
+ Temp = PCI_FEATURE_CONFIGURATION_COMPLETION_LIST_FROM_LINK (Link);
+ if (Temp->RootBridgeHandle == RootBridge->Handle) {
+ *PciFeatureConfigRecord = Temp;
+ return TRUE;
+ }
+ Link = Link->ForwardLink;
+ } while (Link != &mPciFeaturesConfigurationCompletionList->RootBridgeLink);
+ }
+ //
+ // not found on the PCI feature configuration completion list
+ //
+ *PciFeatureConfigRecord = NULL;
+ return FALSE;
+}
+
+/**
+ This routine is primarily to avoid multiple configuration of PCI features
+ to the same PCI Root Bridge due to EDK2 core's ConnectController calls on
+ all the EFI handles. This routine also provide re-enumeration of the PCI
+ features on the same PCI Root Bridge based on the policy of ReEnumeratePciFeatureConfiguration
+ of the PCI_FEATURE_CONFIGURATION_COMPLETION_LIST.
+
+ @param RootBridge A pointer to the PCI_IO_DEVICE for the Root Bridge
+
+ @retval TRUE PCI Feature configuration required for the PCI
+ Root Bridge
+ FALSE PCI Feature configuration is not required to be
+ re-enumerated for the PCI Root Bridge
+**/
+BOOLEAN
+CheckPciFeaturesConfigurationRequired (
+ IN PCI_IO_DEVICE *RootBridge
+ )
+{
+ LIST_ENTRY *Link;
+ PCI_FEATURE_CONFIGURATION_COMPLETION_LIST *Temp;
+
+ if (mPciFeaturesConfigurationCompletionList) {
+ Link = &mPciFeaturesConfigurationCompletionList->RootBridgeLink;
+
+ do {
+ Temp = PCI_FEATURE_CONFIGURATION_COMPLETION_LIST_FROM_LINK (Link);
+ if (Temp->RootBridgeHandle == RootBridge->Handle) {
+ return Temp->ReEnumeratePciFeatureConfiguration;
+ }
+ Link = Link->ForwardLink;
+ } while (Link != &mPciFeaturesConfigurationCompletionList->RootBridgeLink);
+ }
+ //
+ // not found on the PCI feature configuration completion list, return as required
+ //
+ return TRUE;
+}
+
+/**
+ This routine finds the duplicate record if exist and assigns the re-enumeration
+ requirement flag, as passed as input. It creates new record for the PCI Root
+ Bridge and appends the list after updating its re-enumeration flag.
+
+ @param RootBridge A pointer to PCI_IO_DEVICE of the Root Bridge
+ @param ReEnumerationRequired A BOOLEAN for recording the re-enumeration requirement
+
+ @retval EFI_SUCCESS new record inserted into the list or updated the
+ existing record
+ EFI_INVALID_PARAMETER Unexpected error as CheckPciFeatureConfigurationRecordExist
+ reports as record exist but does not return its pointer
+ EFI_OUT_OF_RESOURCES Not able to create PCI features configuratin complete
+ record for the RootBridge
+**/
+EFI_STATUS
+AddRootBridgeInPciFeaturesConfigCompletionList (
+ IN PCI_IO_DEVICE *RootBridge,
+ IN BOOLEAN ReEnumerationRequired
+ )
+{
+ PCI_FEATURE_CONFIGURATION_COMPLETION_LIST *Temp;
+
+ if (CheckPciFeatureConfigurationRecordExist (RootBridge, &Temp)) {
+ //
+ // this PCI Root Bridge record already exist; it may have been re-enumerated
+ // hence just update its enumeration required flag again to exit
+ //
+ if (Temp) {
+ Temp->ReEnumeratePciFeatureConfiguration = ReEnumerationRequired;
+ return EFI_SUCCESS;
+ } else {
+ //
+ // PCI feature configuration complete record reported as exist and no
+ // record pointer returned
+ //
+ return EFI_INVALID_PARAMETER;
+ }
+
+ } else {
+
+ Temp = AllocateZeroPool (sizeof (PCI_FEATURE_CONFIGURATION_COMPLETION_LIST));
+ if (Temp == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ Temp->Signature = PCI_FEATURE_CONFIGURATION_SIGNATURE;
+ Temp->RootBridgeHandle = RootBridge->Handle;
+ Temp->ReEnumeratePciFeatureConfiguration = ReEnumerationRequired;
+ if (mPciFeaturesConfigurationCompletionList) {
+ InsertTailList (
+ &mPciFeaturesConfigurationCompletionList->RootBridgeLink,
+ &Temp->RootBridgeLink
+ );
+ } else {
+ //
+ // init the very first node of the Root Bridge
+ //
+ mPciFeaturesConfigurationCompletionList = Temp;
+ InitializeListHead (&mPciFeaturesConfigurationCompletionList->RootBridgeLink);
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Free up memory alloted for the primary physical PCI Root ports of the PCI Root
+ Bridge instance. Free up all the nodes of type PRIMARY_ROOT_PORT_NODE.
+**/
+VOID
+DestroyPrimaryRootPortNodes ()
+{
+ LIST_ENTRY *Link;
+ PRIMARY_ROOT_PORT_NODE *Temp;
+
+ if (mPrimaryRootPortList) {
+ Link = &mPrimaryRootPortList->NeighborRootPort;
+
+ if (IsListEmpty (Link)) {
+ FreePool (mPrimaryRootPortList->OtherPciFeaturesConfigurationTable);
+ FreePool (mPrimaryRootPortList);
+ } else {
+ do {
+ if (Link->ForwardLink != &mPrimaryRootPortList->NeighborRootPort) {
+ Link = Link->ForwardLink;
+ }
+ Temp = PRIMARY_ROOT_PORT_NODE_FROM_LINK (Link);
+ Link = RemoveEntryList (Link);
+ FreePool (Temp->OtherPciFeaturesConfigurationTable);
+ FreePool (Temp);
+ } while (!IsListEmpty (Link));
+ FreePool (mPrimaryRootPortList->OtherPciFeaturesConfigurationTable);
+ FreePool (mPrimaryRootPortList);
+ }
+ mPrimaryRootPortList = NULL;
+ }
+}
+
+/**
+ Routine meant for initializing any global variables used. It primarily cleans
+ up the internal data structure memory allocated for the previous PCI Root Bridge
+ instance. This should be the first routine to call for any virtual PCI Root
+ Bridge instance.
+**/
+VOID
+SetupPciFeaturesConfigurationDefaults ()
+{
+ //
+ // delete the primary root port list
+ //
+ if (mPrimaryRootPortList) {
+ DestroyPrimaryRootPortNodes ();
+ }
+}
+
+/**
+ 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
+ OTHER_PCI_FEATURES_CONFIGURATION_TABLE.
+ Returns NULL in case of RCiEP or the PCI
+ device does match with any of the physical
+ Root ports, or it does not belong to any
+ Root port's PCI bus range (not a child)
+
+ @retval EFI_SUCCESS able to determine the PCI feature
+ configuration table. For RCiEP since
+ since it is not prepared.
+ EFI_DEVICE_ERROR the PCI device has invalid EFI device
+ path
+**/
+EFI_STATUS
+GetPciFeaturesConfigurationTable (
+ IN PCI_IO_DEVICE *PciDevice,
+ OUT OTHER_PCI_FEATURES_CONFIGURATION_TABLE **PciFeaturesConfigTable
+ )
+{
+ LIST_ENTRY *Link;
+ PRIMARY_ROOT_PORT_NODE *Temp;
+ BOOLEAN NodeMatch;
+ EFI_DEVICE_PATH_PROTOCOL *RootPortPath;
+ EFI_DEVICE_PATH_PROTOCOL *PciDevicePath;
+
+ if (mPrimaryRootPortList == NULL) {
+ //
+ // no populated PCI primary root ports to parse and match the PCI features
+ // configuration table
+ //
+ *PciFeaturesConfigTable = NULL;
+ return EFI_SUCCESS;
+ }
+
+
+ if (IsDevicePathEnd (PciDevice->DevicePath)){
+ //
+ // the given PCI device does not have a valid device path
+ //
+ *PciFeaturesConfigTable = NULL;
+ return EFI_DEVICE_ERROR;
+ }
+
+
+ Link = &mPrimaryRootPortList->NeighborRootPort;
+ do {
+ Temp = PRIMARY_ROOT_PORT_NODE_FROM_LINK (Link);
+ RootPortPath = Temp->RootPortDevicePath;
+ PciDevicePath = PciDevice->DevicePath;
+ NodeMatch = FALSE;
+ //
+ // match the device path from the list of primary Root Ports with the given
+ // device; the initial nodes matching in sequence indicate that the given PCI
+ // device belongs to that PCI tree from the root port
+ //
+ if (IsDevicePathEnd (RootPortPath)) {
+ //
+ // critical error as no device path available in root
+ //
+ *PciFeaturesConfigTable = NULL;
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (EfiCompareDevicePath (RootPortPath, PciDevicePath)) {
+ //
+ // the given PCI device is the primary root port itself
+ //
+ *PciFeaturesConfigTable = Temp->OtherPciFeaturesConfigurationTable;
+ return EFI_SUCCESS;
+ }
+ //
+ // check this PCI device belongs to the primary root port of the root bridge
+ // any child PCI device will have the same initial device path nodes as
+ // its parent root port
+ //
+ while (!IsDevicePathEnd (RootPortPath)){
+
+ if (DevicePathNodeLength (RootPortPath) != DevicePathNodeLength (PciDevicePath)) {
+ //
+ // break to check the next primary root port nodes as does not match
+ //
+ NodeMatch = FALSE;
+ break;
+ }
+ if (CompareMem (RootPortPath, PciDevicePath, DevicePathNodeLength (RootPortPath)) != 0) {
+ //
+ // node does not match, break to check next node
+ //
+ NodeMatch = FALSE;
+ break;
+ }
+ NodeMatch = TRUE;
+ //
+ // advance to next node
+ //
+ RootPortPath = NextDevicePathNode (RootPortPath);
+ PciDevicePath = NextDevicePathNode (PciDevicePath);
+ }
+
+ if (NodeMatch == TRUE) {
+ //
+ // device belongs to primary root port, return its PCI feature configuration
+ // table
+ //
+ *PciFeaturesConfigTable = Temp->OtherPciFeaturesConfigurationTable;
+ return EFI_SUCCESS;
+ }
+
+ //
+ // advance to next Root port node
+ //
+ Link = Link->ForwardLink;
+ } while (Link != &mPrimaryRootPortList->NeighborRootPort);
+ //
+ // the PCI device must be RCiEP, does not belong to any primary root port
+ //
+ *PciFeaturesConfigTable = NULL;
+ return EFI_SUCCESS;
+}
+
+/**
+ This routine determines the existance of the child PCI device for the given
+ PCI Root / Bridge Port device. Always assumes the input PCI device is the bridge
+ or PCI-PCI Bridge device. This routine should not be used with PCI endpoint device.
+
+ @param PciDevice A pointer to the PCI_IO_DEVICE.
+
+ @retval TRUE child device exist
+ FALSE no child device
+**/
+BOOLEAN
+IsPciRootPortEmpty (
+ IN PCI_IO_DEVICE *PciDevice
+ )
+{
+ if (IsListEmpty (&PciDevice->ChildList)){
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+/**
+ Process each PCI device as per the pltaform and device-specific policy.
+
+ @param RootBridge A pointer to the PCI_IO_DEVICE.
+
+ @retval EFI_SUCCESS processing each PCI feature as per policy defined
+ was successful.
+ **/
+EFI_STATUS
+SetupDevicePciFeatures (
+ IN PCI_IO_DEVICE *PciDevice,
+ IN PCI_FEATURE_CONFIGURATION_PHASE PciConfigPhase
+ )
+{
+ EFI_STATUS Status;
+ OTHER_PCI_FEATURES_CONFIGURATION_TABLE *OtherPciFeaturesConfigTable;
+
+ OtherPciFeaturesConfigTable = NULL;
+ Status = GetPciFeaturesConfigurationTable (PciDevice, &OtherPciFeaturesConfigTable);
+ if (EFI_ERROR( Status)) {
+ DEBUG ((
+ DEBUG_WARN, "[Cfg group: 0 {error in dev path}]"
+ ));
+ } else if (OtherPciFeaturesConfigTable == NULL) {
+ DEBUG ((
+ DEBUG_INFO, "[Cfg group: 0]"
+ ));
+ } else {
+ DEBUG ((
+ DEBUG_INFO, "[Cfg group: %d]",
+ OtherPciFeaturesConfigTable->ID
+ ));
+ }
+
+ if (PciConfigPhase == PciFeatureGetDevicePolicy) {
+ Status = GetPciDevicePlatformPolicy (PciDevice);
+ if (EFI_ERROR(Status)) {
+ DEBUG ((
+ DEBUG_ERROR, "Error in obtaining PCI device policy!!!\n"
+ ));
+ }
+ }
+
+ return Status;
+}
+
+/**
+ Traverse all the nodes from the root bridge or PCI-PCI bridge instance, to
+ configure the PCI features as per the device-specific platform policy, and
+ as per the device capability, as applicable.
+
+ @param RootBridge A pointer to the PCI_IO_DEVICE.
+
+ @retval EFI_SUCCESS Traversing all the nodes of the root bridge
+ instances were successfull.
+**/
+EFI_STATUS
+SetupPciFeatures (
+ IN PCI_IO_DEVICE *RootBridge,
+ IN PCI_FEATURE_CONFIGURATION_PHASE PciConfigPhase
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Link;
+ PCI_IO_DEVICE *Device;
+
+ for ( Link = RootBridge->ChildList.ForwardLink
+ ; Link != &RootBridge->ChildList
+ ; Link = Link->ForwardLink
+ ) {
+ Device = PCI_IO_DEVICE_FROM_LINK (Link);
+ if (!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 = SetupDevicePciFeatures (Device, PciConfigPhase);
+ } else {
+ DEBUG (( DEBUG_INFO, "Not a PCIe capable device!\n"));
+ //
+ // PCI Bridge which does not have PCI Express Capability structure
+ // cannot process this kind of PCI Bridge device
+ //
+
+ }
+
+ SetupPciFeatures (Device, PciConfigPhase);
+ } else {
+ DEBUG ((
+ DEBUG_INFO, "::Device [%02x|%02x|%02x] -",
+ Device->BusNumber, Device->DeviceNumber, Device->FunctionNumber
+ ));
+ if (Device->IsPciExp) {
+
+ Status = SetupDevicePciFeatures (Device, PciConfigPhase);
+ } else {
+ DEBUG (( DEBUG_INFO, "Not a PCIe capable device!\n"));
+ //
+ // PCI Device which does not have PCI Express Capability structure
+ // cannot process this kind of PCI device
+ //
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Program the PCI device, to override the PCI features as per the policy,
+ resolved from previous traverse.
+
+ @param RootBridge A pointer to the PCI_IO_DEVICE.
+
+ @retval EFI_SUCCESS The other PCI features configuration during enumeration
+ of all the nodes of the PCI root bridge instance were
+ programmed in PCI-compliance pattern along with the
+ device-specific policy, as applicable.
+ @retval EFI_UNSUPPORTED One of the override operation maong the nodes of
+ the PCI hierarchy resulted in a incompatible address
+ range.
+ @retval EFI_INVALID_PARAMETER The override operation is performed with invalid input
+ parameters.
+**/
+EFI_STATUS
+ProgramDevicePciFeatures (
+ IN PCI_IO_DEVICE *PciDevice
+ )
+{
+ EFI_STATUS Status;
+
+ return Status;
+}
+
+/**
+ Program all the nodes of the specified root bridge or PCI-PCI Bridge, to
+ override the PCI features.
+
+ @param RootBridge A pointer to the PCI_IO_DEVICE.
+
+ @retval EFI_SUCCESS The other PCI features configuration during enumeration
+ of all the nodes of the PCI root bridge instance were
+ programmed in PCI-compliance pattern along with the
+ device-specific policy, as applicable.
+ @retval EFI_UNSUPPORTED One of the override operation maong the nodes of
+ the PCI hierarchy resulted in a incompatible address
+ range.
+ @retval EFI_INVALID_PARAMETER The override operation is performed with invalid input
+ parameters.
+**/
+EFI_STATUS
+ProgramPciFeatures (
+ IN PCI_IO_DEVICE *RootBridge
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Link;
+ PCI_IO_DEVICE *Device;
+
+ for ( Link = RootBridge->ChildList.ForwardLink
+ ; Link != &RootBridge->ChildList
+ ; Link = Link->ForwardLink
+ ) {
+ Device = PCI_IO_DEVICE_FROM_LINK (Link);
+ if (!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) {
+ DEBUG (( DEBUG_INFO, "ready to override!\n"));
+
+ Status = ProgramDevicePciFeatures (Device);
+ } else {
+ DEBUG (( DEBUG_INFO, "skipped!\n"));
+ //
+ // PCI Bridge which does not have PCI Express Capability structure
+ // cannot process this kind of PCI Bridge device
+ //
+ }
+
+ Status = ProgramPciFeatures (Device);
+ } else {
+ DEBUG ((
+ DEBUG_INFO, "::Device [%02x|%02x|%02x] -",
+ Device->BusNumber, Device->DeviceNumber, Device->FunctionNumber
+ ));
+ if (Device->IsPciExp) {
+ DEBUG (( DEBUG_INFO, "ready to override!\n"));
+
+ Status = ProgramDevicePciFeatures (Device);
+ } else {
+ DEBUG (( DEBUG_INFO, "skipped!\n"));
+ //
+ // PCI Device which does not have PCI Express Capability structure
+ // cannot process this kind of PCI device
+ //
+ }
+ }
+ }
+
+ return Status;
+}
+
+/**
+ Create and add a node of type PRIMARY_ROOT_PORT_NODE in the list for the primary
+ Root Port so that all its child PCI devices can be identified against the PCI
+ features configuration table group ID, of type OTHER_PCI_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 PRIMARY_ROOT_PORT_NODE
+ to the list
+ EFI_OUT_OF_RESOURCES unable to get memory for creating the node
+**/
+EFI_STATUS
+AddPrimaryRootPortNode (
+ IN PCI_IO_DEVICE *BridgePort,
+ IN UINTN PortNumber
+ )
+{
+ PRIMARY_ROOT_PORT_NODE *RootPortNode = NULL;
+ OTHER_PCI_FEATURES_CONFIGURATION_TABLE *PciConfigTable = NULL;
+
+ RootPortNode = AllocateZeroPool (sizeof (PRIMARY_ROOT_PORT_NODE));
+ if (RootPortNode == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ RootPortNode->Signature = PCI_ROOT_PORT_SIGNATURE;
+ RootPortNode->RootPortDevicePath = BridgePort->DevicePath;
+ PciConfigTable = AllocateZeroPool (
+ sizeof (OTHER_PCI_FEATURES_CONFIGURATION_TABLE)
+ );
+ if (PciConfigTable) {
+ PciConfigTable->ID = PortNumber;
+ }
+ RootPortNode->OtherPciFeaturesConfigurationTable = PciConfigTable;
+
+ if (mPrimaryRootPortList != NULL) {
+ InsertTailList (&mPrimaryRootPortList->NeighborRootPort, &RootPortNode->NeighborRootPort);
+ } else {
+ InitializeListHead (&RootPortNode->NeighborRootPort);
+ mPrimaryRootPortList = RootPortNode;
+ }
+
+ if (PciConfigTable == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Scan all the nodes of the RootBridge to identify and create a separate list
+ of all primary physical PCI root ports and link each with its own instance of
+ the PCI Feature Configuration Table.
+
+ @param RootBridge A pointer to the PCI_IO_DEVICE of the PCI Root Bridge
+
+ @retval EFI_OUT_OF_RESOURCES unable to allocate buffer to store PCI feature
+ configuration table for all the physical PCI root
+ ports given
+ EFI_NOT_FOUND No PCI Bridge device found
+ EFI_SUCCESS PCI Feature COnfiguration table created for all
+ the PCI Rooot ports found
+ EFI_INVALID_PARAMETER invalid parameter passed to the routine which
+ creates the PCI controller node for the primary
+ Root post list
+**/
+EFI_STATUS
+RecordPciRootPortBridges (
+ IN PCI_IO_DEVICE *RootBridge
+ )
+{
+ EFI_STATUS Status = EFI_NOT_FOUND;
+ LIST_ENTRY *Link;
+ PCI_IO_DEVICE *Device;
+ UINTN NumberOfRootPorts;
+
+ DEBUG ((
+ DEBUG_INFO, "<<********** RecordPciRootPortBridges -start *************>>\n"
+ ));
+ NumberOfRootPorts = 0;
+ for ( Link = RootBridge->ChildList.ForwardLink
+ ; Link != &RootBridge->ChildList
+ ; Link = Link->ForwardLink
+ ) {
+ Device = PCI_IO_DEVICE_FROM_LINK (Link);
+ if (!DeviceExist (Device)) {
+ continue;
+ }
+ if (IS_PCI_BRIDGE (&Device->Pci)) {
+ NumberOfRootPorts++;
+ DEBUG ((
+ DEBUG_INFO, "#%d ::Bridge [%02x|%02x|%02x]",
+ NumberOfRootPorts, Device->BusNumber, Device->DeviceNumber, Device->FunctionNumber
+ ));
+ //
+ // create a primary root port list if that port is connected
+ //
+ if (!IsListEmpty (&Device->ChildList)) {
+ DEBUG ((
+ DEBUG_INFO, "- has downstream device!\n"
+ ));
+ Status = AddPrimaryRootPortNode (Device, NumberOfRootPorts);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR, "PCI configuration table allocation failure for #%d ::Bridge [%02x|%02x|%02x]\n",
+ NumberOfRootPorts, Device->BusNumber, Device->DeviceNumber, Device->FunctionNumber
+ ));
+ }
+ } else {
+ DEBUG ((
+ DEBUG_INFO, "- no downstream device!\n"
+ ));
+ }
+ }
+ }
+ DEBUG ((
+ DEBUG_INFO, "<<********** RecordPciRootPortBridges - end **********>>\n"
+ ));
+ return Status;
+}
+
+/**
+ Enumerate all the nodes of the specified root bridge or PCI-PCI Bridge, to
+ configure the other PCI features.
+
+ @param RootBridge A pointer to the PCI_IO_DEVICE.
+
+ @retval EFI_SUCCESS The other PCI features configuration during enumeration
+ of all the nodes of the PCI root bridge instance were
+ programmed in PCI-compliance pattern along with the
+ device-specific policy, as applicable.
+ @retval EFI_UNSUPPORTED One of the override operation maong the nodes of
+ the PCI hierarchy resulted in a incompatible address
+ range.
+ @retval EFI_INVALID_PARAMETER The override operation is performed with invalid input
+ parameters.
+**/
+EFI_STATUS
+EnumerateOtherPciFeatures (
+ IN PCI_IO_DEVICE *RootBridge
+ )
+{
+ EFI_STATUS Status;
+ CHAR16 *Str;
+ UINTN OtherPciFeatureConfigPhase;
+
+ //
+ // check on PCI features configuration is complete and re-enumeration is required
+ //
+ if (!CheckPciFeaturesConfigurationRequired (RootBridge)) {
+ return EFI_ALREADY_STARTED;
+ }
+
+ Str = ConvertDevicePathToText (
+ DevicePathFromHandle (RootBridge->Handle),
+ FALSE,
+ FALSE
+ );
+ DEBUG ((DEBUG_INFO, "Enumerating PCI features for Root Bridge %s\n", Str != NULL ? Str : L""));
+
+ for ( OtherPciFeatureConfigPhase = PciFeatureRootBridgeScan
+ ; OtherPciFeatureConfigPhase <= PciFeatureConfigurationComplete
+ ; OtherPciFeatureConfigPhase++
+ ) {
+ switch (OtherPciFeatureConfigPhase){
+ case PciFeatureRootBridgeScan:
+ SetupPciFeaturesConfigurationDefaults ();
+ //
+ //first scan the entire root bridge heirarchy for the primary PCI root ports
+ //
+ RecordPciRootPortBridges (RootBridge);
+ break;
+
+ case PciFeatureGetDevicePolicy:
+ case PciFeatureSetupPhase:
+ DEBUG ((
+ DEBUG_INFO, "<<********** SetupPciFeatures - start **********>>\n"
+ ));
+ //
+ // enumerate the other PCI features
+ //
+ Status = SetupPciFeatures (RootBridge, OtherPciFeatureConfigPhase);
+
+ DEBUG ((
+ DEBUG_INFO, "<<********** SetupPciFeatures - end **********>>\n"
+ ));
+ break;
+
+ case PciFeatureConfigurationPhase:
+ //
+ // override the PCI features as per enumeration phase
+ //
+ DEBUG ((DEBUG_INFO, "PCI features override for Root Bridge %s\n", Str != NULL ? Str : L""));
+ DEBUG ((
+ DEBUG_INFO, "<<********** ProgramPciFeatures - start **********>>\n"
+ ));
+ Status = ProgramPciFeatures (RootBridge);
+ DEBUG ((
+ DEBUG_INFO, "<<********** ProgramPciFeatures - end **********>>\n"
+ ));
+ break;
+
+ case PciFeatureConfigurationComplete:
+ //
+ // clean up the temporary resource nodes created for this root bridge
+ //
+ DestroyPrimaryRootPortNodes ();
+ }
+ }
+
+ if (Str != NULL) {
+ FreePool (Str);
+ }
+ //
+ // mark this root bridge as PCI features configuration complete, and no new
+ // enumeration is required
+ //
+ AddRootBridgeInPciFeaturesConfigCompletionList (RootBridge, FALSE);
+ return Status;
+}
+
+/**
+ This routine is invoked from the Stop () interface for the EFI handle of the
+ RootBridge. Free up its node of type PCI_FEATURE_CONFIGURATION_COMPLETION_LIST.
+
+ @param RootBridge A pointer to the PCI_IO_DEVICE
+**/
+VOID
+DestroyRootBridgePciFeaturesConfigCompletionList (
+ IN PCI_IO_DEVICE *RootBridge
+ )
+{
+ LIST_ENTRY *Link;
+ PCI_FEATURE_CONFIGURATION_COMPLETION_LIST *Temp;
+
+ if (mPciFeaturesConfigurationCompletionList) {
+ Link = &mPciFeaturesConfigurationCompletionList->RootBridgeLink;
+
+ do {
+ Temp = PCI_FEATURE_CONFIGURATION_COMPLETION_LIST_FROM_LINK (Link);
+ if (Temp->RootBridgeHandle == RootBridge->Handle) {
+ RemoveEntryList (Link);
+ FreePool (Temp);
+ return;
+ }
+ Link = Link->ForwardLink;
+ } while (Link != &mPciFeaturesConfigurationCompletionList->RootBridgeLink);
+ }
+ //
+ // not found on the PCI feature configuration completion list, return
+ //
+ return;
+}
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
index d06a5e8..b06c140 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
@@ -23,4 +23,150 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#define PCI_FEATURE_SUPPORT_FLAG_CCC BIT13
#define PCI_FEATURE_SUPPORT_FLAG_ESYN BIT14
#define PCI_FEATURE_SUPPORT_FLAG_PTM BIT20
+
+//
+// defines the data structure to hold the details of the PCI Root port devices
+//
+typedef struct _PRIMARY_ROOT_PORT_NODE PRIMARY_ROOT_PORT_NODE;
+
+//
+// defines the data structure to hold the configuration data for the other PCI
+// features
+//
+typedef struct _OTHER_PCI_FEATURES_CONFIGURATION_TABLE OTHER_PCI_FEATURES_CONFIGURATION_TABLE;
+
+//
+// Defines for the PCI features configuration completion and re-enumeration list
+//
+typedef struct _PCI_FEATURE_CONFIGURATION_COMPLETION_LIST PCI_FEATURE_CONFIGURATION_COMPLETION_LIST;
+
+//
+// Signature value for the PCI Root Port node
+//
+#define PCI_ROOT_PORT_SIGNATURE SIGNATURE_32 ('p', 'c', 'i', 'p')
+
+//
+// Definitions of the PCI Root Port data structure members
+//
+struct _PRIMARY_ROOT_PORT_NODE {
+ //
+ // Signature header
+ //
+ UINT32 Signature;
+ //
+ // linked list pointers to next node
+ //
+ LIST_ENTRY NeighborRootPort;
+ //
+ // pointer to PCI_IO_DEVICE of the primary PCI Controller device
+ //
+ EFI_DEVICE_PATH_PROTOCOL *RootPortDevicePath;
+ //
+ // pointer to the corresponding PCI feature configuration Table node
+ // all the child PCI devices of the controller are aligned based on this table
+ //
+ OTHER_PCI_FEATURES_CONFIGURATION_TABLE *OtherPciFeaturesConfigurationTable;
+};
+
+#define PRIMARY_ROOT_PORT_NODE_FROM_LINK(a) \
+ CR (a, PRIMARY_ROOT_PORT_NODE, NeighborRootPort, PCI_ROOT_PORT_SIGNATURE)
+
+//
+// Definition of the PCI Feature configuration Table members
+//
+struct _OTHER_PCI_FEATURES_CONFIGURATION_TABLE {
+ //
+ // Configuration Table ID
+ //
+ UINTN ID;
+};
+
+
+//
+// PCI feature configuration node signature value
+//
+#define PCI_FEATURE_CONFIGURATION_SIGNATURE SIGNATURE_32 ('p', 'c', 'i', 'f')
+
+struct _PCI_FEATURE_CONFIGURATION_COMPLETION_LIST {
+ //
+ // Signature header
+ //
+ UINT32 Signature;
+ //
+ // link to next Root Bridge whose PCI Feature configuration is complete
+ //
+ LIST_ENTRY RootBridgeLink;
+ //
+ // EFI handle of the Root Bridge whose PCI feature configuration is complete
+ //
+ EFI_HANDLE RootBridgeHandle;
+ //
+ // indication for complete re-enumeration of the PCI feature configuration
+ //
+ BOOLEAN ReEnumeratePciFeatureConfiguration;
+};
+
+#define PCI_FEATURE_CONFIGURATION_COMPLETION_LIST_FROM_LINK(a) \
+ CR (a, PCI_FEATURE_CONFIGURATION_COMPLETION_LIST, RootBridgeLink, PCI_FEATURE_CONFIGURATION_SIGNATURE)
+
+//
+// Declaration of the internal sub-phases within the PCI Feature enumeration
+//
+typedef enum {
+ //
+ // initial phase in configuring the other PCI features to record the primary
+ // root ports
+ //
+ PciFeatureRootBridgeScan,
+ //
+ // get the PCI device-specific platform policies and align with device capabilities
+ //
+ PciFeatureGetDevicePolicy,
+ //
+ // align all PCI nodes in the PCI heirarchical tree
+ //
+ PciFeatureSetupPhase,
+ //
+ // finally override to complete configuration of the PCI feature
+ //
+ PciFeatureConfigurationPhase,
+ //
+ // PCI feature configuration complete
+ //
+ PciFeatureConfigurationComplete
+
+}PCI_FEATURE_CONFIGURATION_PHASE;
+
+
+/**
+ Enumerate all the nodes of the specified root bridge or PCI-PCI Bridge, to
+ configure the other PCI features.
+
+ @param RootBridge A pointer to the PCI_IO_DEVICE.
+
+ @retval EFI_SUCCESS The other PCI features configuration during enumeration
+ of all the nodes of the PCI root bridge instance were
+ programmed in PCI-compliance pattern along with the
+ device-specific policy, as applicable.
+ @retval EFI_UNSUPPORTED One of the override operation maong the nodes of
+ the PCI hierarchy resulted in a incompatible address
+ range.
+ @retval EFI_INVALID_PARAMETER The override operation is performed with invalid input
+ parameters.
+**/
+EFI_STATUS
+EnumerateOtherPciFeatures (
+ IN PCI_IO_DEVICE *RootBridge
+ );
+
+/**
+ This routine is invoked from the Stop () interface for the EFI handle of the
+ RootBridge. Free up its node of type PCI_FEATURE_CONFIGURATION_COMPLETION_LIST.
+
+ @param RootBridge A pointer to the PCI_IO_DEVICE
+**/
+VOID
+DestroyRootBridgePciFeaturesConfigCompletionList (
+ IN PCI_IO_DEVICE *RootBridge
+ );
#endif
--
2.21.0.windows.1
next prev parent reply other threads:[~2019-11-01 15:10 UTC|newest]
Thread overview: 51+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-11-01 15:09 [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 00/12] New PCI features - MPS, MRRS, RO, NS, CTO Javeed, Ashraf
2019-11-01 15:09 ` [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 01/12] MdeModulePkg/PciBusDxe:New PCI features separation with PCD Javeed, Ashraf
2019-11-01 15:09 ` [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 02/12] PciBusDxe: Reorganize the PCI Platform Protocol usage code Javeed, Ashraf
2019-11-01 15:09 ` [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 03/12] PciBusDxe: Separation of the PCI device registration and start Javeed, Ashraf
2019-11-01 15:09 ` [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 04/12] PciBusDxe: Inclusion of new PCI Platform Protocol 2 Javeed, Ashraf
2019-11-01 15:09 ` Javeed, Ashraf [this message]
2019-11-01 15:09 ` [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 06/12] PciBusDxe: Integration of setup for PCI feature enumeration Javeed, Ashraf
2019-11-01 15:09 ` [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 07/12] PciBusDxe: Record the PCI-Express Capability Structure Javeed, Ashraf
2019-11-01 15:09 ` [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 08/12] PciBusDxe: New PCI feature Max_Payload_Size Javeed, Ashraf
2019-11-01 15:09 ` [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 09/12] PciBusDxe: New PCI feature Max_Read_Req_Size Javeed, Ashraf
2019-11-01 15:09 ` [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 10/12] PciBusDxe: New PCI feature Relax Ordering Javeed, Ashraf
2019-11-01 15:09 ` [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 11/12] PciBusDxe: New PCI feature No-Snoop Javeed, Ashraf
2019-11-01 15:09 ` [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 12/12] PciBusDxe: New PCI feature Completion Timeout Javeed, Ashraf
[not found] ` <15D3127A726D26A6.7420@groups.io>
2019-11-13 3:22 ` [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 01/12] MdeModulePkg/PciBusDxe:New PCI features separation with PCD Javeed, Ashraf
2019-12-16 12:46 ` Ni, Ray
[not found] ` <15D3127AABF5037C.32624@groups.io>
2019-11-13 3:23 ` [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 02/12] PciBusDxe: Reorganize the PCI Platform Protocol usage code Javeed, Ashraf
2019-12-16 12:46 ` Ni, Ray
[not found] ` <15D3127A98E21087.7420@groups.io>
2019-11-13 3:25 ` [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 03/12] PciBusDxe: Separation of the PCI device registration and start Javeed, Ashraf
2019-12-17 1:38 ` Ni, Ray
2019-12-17 3:19 ` Javeed, Ashraf
2019-12-19 1:34 ` Ni, Ray
2019-12-19 4:12 ` Javeed, Ashraf
[not found] ` <15D3127AAE5DC481.32624@groups.io>
2019-11-13 3:26 ` [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 04/12] PciBusDxe: Inclusion of new PCI Platform Protocol 2 Javeed, Ashraf
[not found] ` <15D3127B934F51D3.12315@groups.io>
2019-11-13 3:27 ` [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 05/12] PciBusDxe: Setup sub-phases for PCI feature enumeration Javeed, Ashraf
2019-12-17 11:56 ` Ni, Ray
2019-12-18 7:14 ` Javeed, Ashraf
2019-12-19 5:48 ` Ni, Ray
[not found] ` <15E1AFB3EABD031C.30484@groups.io>
2020-03-05 14:12 ` Ni, Ray
2020-03-16 9:33 ` Javeed, Ashraf
2020-03-16 14:00 ` Ni, Ray
2020-03-17 7:20 ` Javeed, Ashraf
2020-03-17 15:36 ` Ni, Ray
2020-04-20 13:22 ` Javeed, Ashraf
2020-04-21 6:03 ` Javeed, Ashraf
2020-04-21 6:22 ` Javeed, Ashraf
2020-05-08 8:26 ` Ni, Ray
[not found] ` <15D3127BE430E7DA.31784@groups.io>
2019-11-13 3:28 ` [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 06/12] PciBusDxe: Integration of setup " Javeed, Ashraf
2019-12-17 11:59 ` Ni, Ray
2019-12-18 7:15 ` Javeed, Ashraf
[not found] ` <15D3127C6DFCD4A7.12315@groups.io>
2019-11-13 3:29 ` [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 07/12] PciBusDxe: Record the PCI-Express Capability Structure Javeed, Ashraf
2019-12-17 12:03 ` Ni, Ray
2019-12-18 7:32 ` Javeed, Ashraf
[not found] ` <15D3127D273722D4.32624@groups.io>
2019-11-13 3:30 ` [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 08/12] PciBusDxe: New PCI feature Max_Payload_Size Javeed, Ashraf
2019-12-18 8:38 ` Ni, Ray
2019-12-18 9:10 ` Ni, Ray
2019-12-18 14:35 ` Javeed, Ashraf
2019-12-19 2:14 ` Ni, Ray
[not found] ` <15D3127DA6E2D860.7420@groups.io>
2019-11-13 3:31 ` [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 09/12] PciBusDxe: New PCI feature Max_Read_Req_Size Javeed, Ashraf
[not found] ` <15D3127E471DF360.32624@groups.io>
2019-11-13 3:32 ` [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 10/12] PciBusDxe: New PCI feature Relax Ordering Javeed, Ashraf
[not found] ` <15D3127EB6ED8506.12315@groups.io>
2019-11-13 3:33 ` [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 11/12] PciBusDxe: New PCI feature No-Snoop Javeed, Ashraf
[not found] ` <15D3127F5541064B.31784@groups.io>
2019-11-13 3:34 ` [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 12/12] PciBusDxe: New PCI feature Completion Timeout Javeed, Ashraf
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20191101150952.3340-6-ashraf.javeed@intel.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox