]> git.proxmox.com Git - mirror_edk2.git/commitdiff
ArmVirtPkg/FdtPciPcdProducerLib: add handling of PcdPciIoTranslation
authorArd Biesheuvel <ard.biesheuvel@linaro.org>
Wed, 24 Aug 2016 17:03:00 +0000 (19:03 +0200)
committerArd Biesheuvel <ard.biesheuvel@linaro.org>
Fri, 2 Sep 2016 20:41:01 +0000 (21:41 +0100)
Add handling of the PcdPciIoTranslation PCD, so that modules that include
this library via NULL resolution are guaranteed that it will be set before
they reference it.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Ref: https://tianocore.acgmultimedia.com/show_bug.cgi?id=65

ArmVirtPkg/Library/FdtPciPcdProducerLib/FdtPciPcdProducerLib.c
ArmVirtPkg/Library/FdtPciPcdProducerLib/FdtPciPcdProducerLib.inf

index cc60940d487cb6e3929655fac6f192308d2faf05..10b47560cb9cbee3aac82206e8434ba35664b86f 100644 (file)
 \r
 #include <Protocol/FdtClient.h>\r
 \r
+//\r
+// We expect the "ranges" property of "pci-host-ecam-generic" to consist of\r
+// records like this.\r
+//\r
+#pragma pack (1)\r
+typedef struct {\r
+  UINT32 Type;\r
+  UINT64 ChildBase;\r
+  UINT64 CpuBase;\r
+  UINT64 Size;\r
+} DTB_PCI_HOST_RANGE_RECORD;\r
+#pragma pack ()\r
+\r
+#define DTB_PCI_HOST_RANGE_RELOCATABLE  BIT31\r
+#define DTB_PCI_HOST_RANGE_PREFETCHABLE BIT30\r
+#define DTB_PCI_HOST_RANGE_ALIASED      BIT29\r
+#define DTB_PCI_HOST_RANGE_MMIO32       BIT25\r
+#define DTB_PCI_HOST_RANGE_MMIO64       (BIT25 | BIT24)\r
+#define DTB_PCI_HOST_RANGE_IO           BIT24\r
+#define DTB_PCI_HOST_RANGE_TYPEMASK     (BIT31 | BIT30 | BIT29 | BIT25 | BIT24)\r
+\r
+STATIC\r
+RETURN_STATUS\r
+GetPciIoTranslation (\r
+  IN  FDT_CLIENT_PROTOCOL *FdtClient,\r
+  IN  INT32               Node,\r
+  OUT UINT64              *IoTranslation\r
+  )\r
+{\r
+  UINT32        RecordIdx;\r
+  CONST VOID    *Prop;\r
+  UINT32        Len;\r
+  EFI_STATUS    Status;\r
+  UINT64        IoBase;\r
+\r
+  //\r
+  // Iterate over "ranges".\r
+  //\r
+  Status = FdtClient->GetNodeProperty (FdtClient, Node, "ranges", &Prop, &Len);\r
+  if (EFI_ERROR (Status) || Len == 0 ||\r
+      Len % sizeof (DTB_PCI_HOST_RANGE_RECORD) != 0) {\r
+    DEBUG ((EFI_D_ERROR, "%a: 'ranges' not found or invalid\n", __FUNCTION__));\r
+    return RETURN_PROTOCOL_ERROR;\r
+  }\r
+\r
+  for (RecordIdx = 0; RecordIdx < Len / sizeof (DTB_PCI_HOST_RANGE_RECORD);\r
+       ++RecordIdx) {\r
+    CONST DTB_PCI_HOST_RANGE_RECORD *Record;\r
+    UINT32                          Type;\r
+\r
+    Record = (CONST DTB_PCI_HOST_RANGE_RECORD *)Prop + RecordIdx;\r
+    Type = SwapBytes32 (Record->Type) & DTB_PCI_HOST_RANGE_TYPEMASK;\r
+    if (Type == DTB_PCI_HOST_RANGE_IO) {\r
+      IoBase = SwapBytes64 (Record->ChildBase);\r
+      *IoTranslation = SwapBytes64 (Record->CpuBase) - IoBase;\r
+\r
+      return RETURN_SUCCESS;\r
+    }\r
+  }\r
+  return RETURN_NOT_FOUND;\r
+}\r
+\r
 RETURN_STATUS\r
 EFIAPI\r
 FdtPciPcdProducerLibConstructor (\r
@@ -31,11 +93,21 @@ FdtPciPcdProducerLibConstructor (
   UINT64              PciExpressBaseAddress;\r
   FDT_CLIENT_PROTOCOL *FdtClient;\r
   CONST UINT64        *Reg;\r
-  UINT32              RegElemSize, RegSize;\r
+  UINT32              RegSize;\r
   EFI_STATUS          Status;\r
+  INT32               Node;\r
+  RETURN_STATUS       RetStatus;\r
+  UINT64              IoTranslation;\r
 \r
   PciExpressBaseAddress = PcdGet64 (PcdPciExpressBaseAddress);\r
   if (PciExpressBaseAddress != MAX_UINT64) {\r
+    //\r
+    // Assume that the fact that PciExpressBaseAddress has been changed from\r
+    // its default value of MAX_UINT64 implies that this code has been\r
+    // executed already, in the context of another module. That means we can\r
+    // assume that PcdPciIoTranslation has been discovered from the DT node\r
+    // as well.\r
+    //\r
     return EFI_SUCCESS;\r
   }\r
 \r
@@ -43,17 +115,33 @@ FdtPciPcdProducerLibConstructor (
                   (VOID **)&FdtClient);\r
   ASSERT_EFI_ERROR (Status);\r
 \r
-  Status = FdtClient->FindCompatibleNodeReg (FdtClient,\r
-                        "pci-host-ecam-generic", (CONST VOID **)&Reg,\r
-                        &RegElemSize, &RegSize);\r
+  PciExpressBaseAddress = 0;\r
+  Status = FdtClient->FindCompatibleNode (FdtClient, "pci-host-ecam-generic",\r
+                        &Node);\r
+\r
+  if (!EFI_ERROR (Status)) {\r
+    Status = FdtClient->GetNodeProperty (FdtClient, Node, "reg",\r
+                          (CONST VOID **)&Reg, &RegSize);\r
+\r
+    if (!EFI_ERROR (Status) && RegSize == 2 * sizeof (UINT64)) {\r
+      PciExpressBaseAddress = SwapBytes64 (*Reg);\r
 \r
-  if (EFI_ERROR (Status)) {\r
-    PciExpressBaseAddress = 0;\r
-  } else {\r
-    ASSERT (RegElemSize == sizeof (UINT64));\r
-    PciExpressBaseAddress = SwapBytes64 (*Reg);\r
+      PcdSetBool (PcdPciDisableBusEnumeration, FALSE);\r
 \r
-    PcdSetBool (PcdPciDisableBusEnumeration, FALSE);\r
+      RetStatus = GetPciIoTranslation (FdtClient, Node, &IoTranslation);\r
+      if (!RETURN_ERROR (RetStatus)) {\r
+          PcdSet64 (PcdPciIoTranslation, IoTranslation);\r
+      } else {\r
+        //\r
+        // Support for I/O BARs is not mandatory, and so it does not make sense\r
+        // to abort in the general case. So leave it up to the actual driver to\r
+        // complain about this if it wants to, and just issue a warning here.\r
+        //\r
+        DEBUG ((EFI_D_WARN,\r
+          "%a: 'pci-host-ecam-generic' device encountered with no I/O range\n",\r
+          __FUNCTION__));\r
+      }\r
+    }\r
   }\r
 \r
   PcdSet64 (PcdPciExpressBaseAddress, PciExpressBaseAddress);\r
index 1ba71abea78a6c18c132e5e929d6444c8689bd27..cd138fa1aa6e20a73f675b5309e745742fd63469 100644 (file)
@@ -26,6 +26,7 @@
   FdtPciPcdProducerLib.c\r
 \r
 [Packages]\r
+  ArmPkg/ArmPkg.dec\r
   ArmVirtPkg/ArmVirtPkg.dec\r
   MdeModulePkg/MdeModulePkg.dec\r
   MdePkg/MdePkg.dec\r
@@ -40,6 +41,7 @@
   gFdtClientProtocolGuid                                      ## CONSUMES\r
 \r
 [Pcd]\r
+  gArmTokenSpaceGuid.PcdPciIoTranslation                      ## PRODUCES\r
   gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress           ## PRODUCES\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdPciDisableBusEnumeration  ## PRODUCES\r
 \r