MdeModulePkg/NonDiscoverablePciDeviceDxe: expose unique B/D/F identifiers
authorArd Biesheuvel <ard.biesheuvel@linaro.org>
Wed, 10 Oct 2018 08:34:50 +0000 (10:34 +0200)
committerArd Biesheuvel <ard.biesheuvel@linaro.org>
Wed, 10 Oct 2018 09:14:29 +0000 (11:14 +0200)
Currently, the implementation of EFI_PCI_IO_PROTOCOL::GetLocation()
in NonDiscoverablePciDeviceDxe returns the same set of dummy values
for each instance of the NON_DISCOVERABLE_DEVICE protocol that it
attaches itself to. However, this turns out to be causing problems
in cases where software (such as the ARM Compliance Test Suite [ACS])
attempts to use these values to uniquely identify controllers, since
the collisions create ambiguity in this regard.

So let's modify GetLocation() to return an arbitrary bus/device tuple
on segment 0xff instead. This is guaranteed not to clash with other
non-discoverable PCI devices, and highly unlikely to clash with real
PCIe devices.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Tested-by: Marcin Wojtas <mw@semihalf.com>
Reviewed-by: Star Zeng <star.zeng@intel.com>
MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.c
MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c
MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.h

index 3e9ff66..2483c72 100644 (file)
@@ -16,6 +16,9 @@
 \r
 #include <Protocol/DriverBinding.h>\r
 \r
 \r
 #include <Protocol/DriverBinding.h>\r
 \r
+#define MAX_NON_DISCOVERABLE_PCI_DEVICE_ID   (32 * 256)\r
+\r
+STATIC UINTN               mUniqueIdCounter = 0;\r
 EFI_CPU_ARCH_PROTOCOL      *mCpu;\r
 \r
 //\r
 EFI_CPU_ARCH_PROTOCOL      *mCpu;\r
 \r
 //\r
@@ -141,6 +144,11 @@ NonDiscoverablePciDeviceStart (
   NON_DISCOVERABLE_PCI_DEVICE   *Dev;\r
   EFI_STATUS                    Status;\r
 \r
   NON_DISCOVERABLE_PCI_DEVICE   *Dev;\r
   EFI_STATUS                    Status;\r
 \r
+  ASSERT (mUniqueIdCounter < MAX_NON_DISCOVERABLE_PCI_DEVICE_ID);\r
+  if (mUniqueIdCounter >= MAX_NON_DISCOVERABLE_PCI_DEVICE_ID) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
   Dev = AllocateZeroPool (sizeof *Dev);\r
   if (Dev == NULL) {\r
     return EFI_OUT_OF_RESOURCES;\r
   Dev = AllocateZeroPool (sizeof *Dev);\r
   if (Dev == NULL) {\r
     return EFI_OUT_OF_RESOURCES;\r
@@ -167,6 +175,8 @@ NonDiscoverablePciDeviceStart (
     goto CloseProtocol;\r
   }\r
 \r
     goto CloseProtocol;\r
   }\r
 \r
+  Dev->UniqueId = mUniqueIdCounter++;\r
+\r
   return EFI_SUCCESS;\r
 \r
 CloseProtocol:\r
   return EFI_SUCCESS;\r
 \r
 CloseProtocol:\r
index 0e42ae4..58cb5d8 100644 (file)
@@ -1181,6 +1181,8 @@ PciIoGetLocation (
   OUT  UINTN                *FunctionNumber\r
   )\r
 {\r
   OUT  UINTN                *FunctionNumber\r
   )\r
 {\r
+  NON_DISCOVERABLE_PCI_DEVICE         *Dev;\r
+\r
   if (SegmentNumber == NULL ||\r
       BusNumber == NULL ||\r
       DeviceNumber == NULL ||\r
   if (SegmentNumber == NULL ||\r
       BusNumber == NULL ||\r
       DeviceNumber == NULL ||\r
@@ -1188,9 +1190,11 @@ PciIoGetLocation (
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  *SegmentNumber  = 0;\r
-  *BusNumber      = 0xff;\r
-  *DeviceNumber   = 0;\r
+  Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This);\r
+\r
+  *SegmentNumber  = 0xff;\r
+  *BusNumber      = Dev->UniqueId >> 5;\r
+  *DeviceNumber   = Dev->UniqueId & 0x1f;\r
   *FunctionNumber = 0;\r
 \r
   return EFI_SUCCESS;\r
   *FunctionNumber = 0;\r
 \r
   return EFI_SUCCESS;\r
index e641189..5b4c57f 100644 (file)
@@ -100,6 +100,12 @@ typedef struct {
   // on behalf of this device\r
   //\r
   LIST_ENTRY                UncachedAllocationList;\r
   // on behalf of this device\r
   //\r
   LIST_ENTRY                UncachedAllocationList;\r
+  //\r
+  // Unique ID for this device instance: needed so that we can report unique\r
+  // segment/bus/device number for each device instance. Note that this number\r
+  // may change when disconnecting/reconnecting the driver.\r
+  //\r
+  UINTN                     UniqueId;\r
 } NON_DISCOVERABLE_PCI_DEVICE;\r
 \r
 /**\r
 } NON_DISCOVERABLE_PCI_DEVICE;\r
 \r
 /**\r