]> git.proxmox.com Git - mirror_edk2.git/commitdiff
OvmfPkg/PciHotPlugInitDxe: convert to PciCapLib
authorLaszlo Ersek <lersek@redhat.com>
Fri, 4 May 2018 10:00:00 +0000 (12:00 +0200)
committerLaszlo Ersek <lersek@redhat.com>
Thu, 24 May 2018 19:22:56 +0000 (21:22 +0200)
Replace the manual capability list parsing in OvmfPkg/PciHotPlugInitDxe
with PciCapLib and PciCapPciSegmentLib API calls.

Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
OvmfPkg/PciHotPlugInitDxe/PciHotPlugInit.c
OvmfPkg/PciHotPlugInitDxe/PciHotPlugInit.inf

index 177e1a62120de3757b0cfef800e32acd47f112d7..3449796878efb5d682bdbdcc64fe075ada5abbcd 100644 (file)
@@ -14,6 +14,7 @@
 **/\r
 \r
 #include <IndustryStandard/Acpi10.h>\r
+#include <IndustryStandard/Q35MchIch9.h>\r
 #include <IndustryStandard/QemuPciBridgeCapabilities.h>\r
 \r
 #include <Library/BaseLib.h>\r
 #include <Library/DebugLib.h>\r
 #include <Library/DevicePathLib.h>\r
 #include <Library/MemoryAllocationLib.h>\r
+#include <Library/PciCapLib.h>\r
+#include <Library/PciCapPciSegmentLib.h>\r
 #include <Library/PciLib.h>\r
 #include <Library/UefiBootServicesTableLib.h>\r
 \r
 #include <Protocol/PciHotPlugInit.h>\r
 #include <Protocol/PciRootBridgeIo.h>\r
 \r
+//\r
+// TRUE if the PCI platform supports extended config space, FALSE otherwise.\r
+//\r
+STATIC BOOLEAN mPciExtConfSpaceSupported;\r
+\r
+\r
 //\r
 // The protocol interface this driver produces.\r
 //\r
@@ -248,91 +257,11 @@ HighBitSetRoundUp64 (
 }\r
 \r
 \r
-/**\r
-  Read a slice from conventional PCI config space at the given offset, then\r
-  advance the offset.\r
-\r
-  @param[in] PciAddress  The address of the PCI Device -- Bus, Device, Function\r
-                         -- in UEFI (not PciLib) encoding.\r
-\r
-  @param[in,out] Offset  On input, the offset in conventional PCI config space\r
-                         to start reading from. On output, the offset of the\r
-                         first byte that was not read.\r
-\r
-  @param[in] Size        The number of bytes to read.\r
-\r
-  @param[out] Buffer     On output, the bytes read from PCI config space are\r
-                         stored in this object.\r
-**/\r
-STATIC\r
-VOID\r
-ReadConfigSpace (\r
-  IN     CONST EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *PciAddress,\r
-  IN OUT UINT8                                             *Offset,\r
-  IN     UINT8                                             Size,\r
-  OUT    VOID                                              *Buffer\r
-  )\r
-{\r
-  PciReadBuffer (\r
-    PCI_LIB_ADDRESS (\r
-      PciAddress->Bus,\r
-      PciAddress->Device,\r
-      PciAddress->Function,\r
-      *Offset\r
-      ),\r
-    Size,\r
-    Buffer\r
-    );\r
-  *Offset += Size;\r
-}\r
-\r
-\r
-/**\r
-  Convenience wrapper macro for ReadConfigSpace().\r
-\r
-  Given the following conditions:\r
-\r
-  - HeaderField is the first field in the structure pointed-to by Struct,\r
-\r
-  - Struct->HeaderField has been populated from the conventional PCI config\r
-    space of the PCI device identified by PciAddress,\r
-\r
-  - *Offset points one past HeaderField in the conventional PCI config space of\r
-    the PCI device identified by PciAddress,\r
-\r
-  populate the rest of *Struct from conventional PCI config space, starting at\r
-  *Offset. Finally, increment *Offset so that it point one past *Struct.\r
-\r
-  @param[in] PciAddress  The address of the PCI Device -- Bus, Device, Function\r
-                         -- in UEFI (not PciLib) encoding. Type: pointer to\r
-                         CONST EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS.\r
-\r
-  @param[in,out] Offset  On input, the offset in conventional PCI config space\r
-                         to start reading from; one past Struct->HeaderField.\r
-                         On output, the offset of the first byte that was not\r
-                         read; one past *Struct. Type: pointer to UINT8.\r
-\r
-  @param[out] Struct     The structure to complete. Type: pointer to structure\r
-                         object.\r
-\r
-  @param[in] HeaderField The name of the first field in *Struct, after which\r
-                         *Struct should be populated. Type: structure member\r
-                         identifier.\r
-**/\r
-#define COMPLETE_CONFIG_SPACE_STRUCT(PciAddress, Offset, Struct, HeaderField) \\r
-          ReadConfigSpace (                                                   \\r
-            (PciAddress),                                                     \\r
-            (Offset),                                                         \\r
-            (UINT8)(sizeof *(Struct) - sizeof ((Struct)->HeaderField)),       \\r
-            &((Struct)->HeaderField) + 1                                      \\r
-            )\r
-\r
-\r
 /**\r
   Look up the QEMU-specific Resource Reservation capability in the conventional\r
   config space of a Hotplug Controller (that is, PCI Bridge).\r
 \r
-  This function performs as few config space reads as possible.\r
+  On error, the contents of ReservationHint are indeterminate.\r
 \r
   @param[in] HpcPciAddress     The address of the PCI Bridge -- Bus, Device,\r
                                Function -- in UEFI (not PciLib) encoding.\r
@@ -343,8 +272,9 @@ ReadConfigSpace (
   @retval EFI_SUCCESS    The capability has been found, ReservationHint has\r
                          been populated.\r
 \r
-  @retval EFI_NOT_FOUND  The capability is missing. The contents of\r
-                         ReservationHint are now indeterminate.\r
+  @retval EFI_NOT_FOUND  The capability is missing.\r
+\r
+  @return                Error codes from PciCapPciSegmentLib and PciCapLib.\r
 **/\r
 STATIC\r
 EFI_STATUS\r
@@ -353,10 +283,12 @@ QueryReservationHint (
   OUT QEMU_PCI_BRIDGE_CAPABILITY_RESOURCE_RESERVATION   *ReservationHint\r
 )\r
 {\r
-  UINT16 PciVendorId;\r
-  UINT16 PciStatus;\r
-  UINT8  PciCapPtr;\r
-  UINT8  Offset;\r
+  UINT16       PciVendorId;\r
+  EFI_STATUS   Status;\r
+  PCI_CAP_DEV  *PciDevice;\r
+  PCI_CAP_LIST *CapList;\r
+  UINT16       VendorInstance;\r
+  PCI_CAP      *VendorCap;\r
 \r
   //\r
   // Check the vendor identifier.\r
@@ -374,108 +306,101 @@ QueryReservationHint (
   }\r
 \r
   //\r
-  // Check the Capabilities List bit in the PCI Status Register.\r
+  // Parse the capabilities lists.\r
   //\r
-  PciStatus = PciRead16 (\r
-                PCI_LIB_ADDRESS (\r
-                  HpcPciAddress->Bus,\r
-                  HpcPciAddress->Device,\r
-                  HpcPciAddress->Function,\r
-                  PCI_PRIMARY_STATUS_OFFSET\r
-                  )\r
-                );\r
-  if ((PciStatus & EFI_PCI_STATUS_CAPABILITY) == 0) {\r
-    return EFI_NOT_FOUND;\r
+  Status = PciCapPciSegmentDeviceInit (\r
+             mPciExtConfSpaceSupported ? PciCapExtended : PciCapNormal,\r
+             0, // Segment\r
+             HpcPciAddress->Bus,\r
+             HpcPciAddress->Device,\r
+             HpcPciAddress->Function,\r
+             &PciDevice\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  Status = PciCapListInit (PciDevice, &CapList);\r
+  if (EFI_ERROR (Status)) {\r
+    goto UninitPciDevice;\r
   }\r
 \r
   //\r
-  // Fetch the start of the Capabilities List.\r
-  //\r
-  PciCapPtr = PciRead8 (\r
-                PCI_LIB_ADDRESS (\r
-                  HpcPciAddress->Bus,\r
-                  HpcPciAddress->Device,\r
-                  HpcPciAddress->Function,\r
-                  PCI_CAPBILITY_POINTER_OFFSET\r
-                  )\r
-                );\r
-\r
-  //\r
-  // Scan the Capabilities List until we find the terminator element, or the\r
-  // Resource Reservation capability.\r
+  // Scan the vendor capability instances for the Resource Reservation\r
+  // capability.\r
   //\r
-  for (Offset = PciCapPtr & 0xFC;\r
-       Offset > 0;\r
-       Offset = ReservationHint->BridgeHdr.VendorHdr.Hdr.NextItemPtr & 0xFC) {\r
-    BOOLEAN EnoughRoom;\r
-\r
-    //\r
-    // Check if the Resource Reservation capability would fit into config space\r
-    // at this offset.\r
-    //\r
-    EnoughRoom = (BOOLEAN)(\r
-                   Offset <= PCI_MAX_CONFIG_OFFSET - sizeof *ReservationHint\r
-                   );\r
-\r
-    //\r
-    // Read the standard capability header so we can check the capability ID\r
-    // (if necessary) and advance to the next capability.\r
-    //\r
-    ReadConfigSpace (\r
-      HpcPciAddress,\r
-      &Offset,\r
-      (UINT8)sizeof ReservationHint->BridgeHdr.VendorHdr.Hdr,\r
-      &ReservationHint->BridgeHdr.VendorHdr.Hdr\r
-      );\r
-    if (!EnoughRoom ||\r
-        (ReservationHint->BridgeHdr.VendorHdr.Hdr.CapabilityID !=\r
-         EFI_PCI_CAPABILITY_ID_VENDOR)) {\r
-      continue;\r
+  VendorInstance = 0;\r
+  for (;;) {\r
+    UINT8 VendorLength;\r
+    UINT8 BridgeCapType;\r
+\r
+    Status = PciCapListFindCap (\r
+               CapList,\r
+               PciCapNormal,\r
+               EFI_PCI_CAPABILITY_ID_VENDOR,\r
+               VendorInstance++,\r
+               &VendorCap\r
+               );\r
+    if (EFI_ERROR (Status)) {\r
+      goto UninitCapList;\r
     }\r
 \r
     //\r
-    // Read the rest of the vendor capability header so we can check the\r
-    // capability length.\r
+    // Check the vendor capability length.\r
     //\r
-    COMPLETE_CONFIG_SPACE_STRUCT (\r
-      HpcPciAddress,\r
-      &Offset,\r
-      &ReservationHint->BridgeHdr.VendorHdr,\r
-      Hdr\r
-      );\r
-    if (ReservationHint->BridgeHdr.VendorHdr.Length !=\r
-        sizeof *ReservationHint) {\r
+    Status = PciCapRead (\r
+               PciDevice,\r
+               VendorCap,\r
+               OFFSET_OF (EFI_PCI_CAPABILITY_VENDOR_HDR, Length),\r
+               &VendorLength,\r
+               sizeof VendorLength\r
+               );\r
+    if (EFI_ERROR (Status)) {\r
+      goto UninitCapList;\r
+    }\r
+    if (VendorLength != sizeof *ReservationHint) {\r
       continue;\r
     }\r
 \r
     //\r
-    // Read the rest of the QEMU bridge capability header so we can check the\r
-    // capability type.\r
+    // Check the vendor bridge capability type.\r
     //\r
-    COMPLETE_CONFIG_SPACE_STRUCT (\r
-      HpcPciAddress,\r
-      &Offset,\r
-      &ReservationHint->BridgeHdr,\r
-      VendorHdr\r
-      );\r
-    if (ReservationHint->BridgeHdr.Type !=\r
+    Status = PciCapRead (\r
+               PciDevice,\r
+               VendorCap,\r
+               OFFSET_OF (QEMU_PCI_BRIDGE_CAPABILITY_HDR, Type),\r
+               &BridgeCapType,\r
+               sizeof BridgeCapType\r
+               );\r
+    if (EFI_ERROR (Status)) {\r
+      goto UninitCapList;\r
+    }\r
+    if (BridgeCapType ==\r
         QEMU_PCI_BRIDGE_CAPABILITY_TYPE_RESOURCE_RESERVATION) {\r
-      continue;\r
+      //\r
+      // We have a match.\r
+      //\r
+      break;\r
     }\r
-\r
-    //\r
-    // Read the body of the reservation hint.\r
-    //\r
-    COMPLETE_CONFIG_SPACE_STRUCT (\r
-      HpcPciAddress,\r
-      &Offset,\r
-      ReservationHint,\r
-      BridgeHdr\r
-      );\r
-    return EFI_SUCCESS;\r
   }\r
 \r
-  return EFI_NOT_FOUND;\r
+  //\r
+  // Populate ReservationHint.\r
+  //\r
+  Status = PciCapRead (\r
+             PciDevice,\r
+             VendorCap,\r
+             0, // SourceOffsetInCap\r
+             ReservationHint,\r
+             sizeof *ReservationHint\r
+             );\r
+\r
+UninitCapList:\r
+  PciCapListUninit (CapList);\r
+\r
+UninitPciDevice:\r
+  PciCapPciSegmentDeviceUninit (PciDevice);\r
+\r
+  return Status;\r
 }\r
 \r
 \r
@@ -870,6 +795,8 @@ DriverInitialize (
 {\r
   EFI_STATUS Status;\r
 \r
+  mPciExtConfSpaceSupported = (PcdGet16 (PcdOvmfHostBridgePciDevId) ==\r
+                               INTEL_Q35_MCH_DEVICE_ID);\r
   mPciHotPlugInit.GetRootHpcList = GetRootHpcList;\r
   mPciHotPlugInit.InitializeRootHpc = InitializeRootHpc;\r
   mPciHotPlugInit.GetResourcePadding = GetResourcePadding;\r
index 38043986eb6706af368c93b02fd1063543a1a116..cc2b60d44263781546e2680b502ec197b63b8e33 100644 (file)
@@ -35,6 +35,8 @@
   DebugLib\r
   DevicePathLib\r
   MemoryAllocationLib\r
+  PciCapLib\r
+  PciCapPciSegmentLib\r
   PciLib\r
   UefiBootServicesTableLib\r
   UefiDriverEntryPoint\r
@@ -42,5 +44,8 @@
 [Protocols]\r
   gEfiPciHotPlugInitProtocolGuid ## ALWAYS_PRODUCES\r
 \r
+[Pcd]\r
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfHostBridgePciDevId ## CONSUMES\r
+\r
 [Depex]\r
   TRUE\r