]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c
MdeModulePkg/PciBusDxe: make OPROM BAR degradation configurable
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / PciBusDxe / PciResourceSupport.c
index cca365370faf9a9ffaa727e0316b08e9f011b7f5..e93134613b488aad1b8c4fa5069500760769d562 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   PCI resouces support functions implemntation for PCI Bus module.\r
 \r
-Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>\r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
 which accompanies this distribution.  The full text of the license may be found at\r
@@ -14,6 +14,13 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 \r
 #include "PciBus.h"\r
 \r
+//\r
+// The default policy for the PCI bus driver is NOT to reserve I/O ranges for both ISA aliases and VGA aliases.\r
+//\r
+BOOLEAN mReserveIsaAliases = FALSE;\r
+BOOLEAN mReserveVgaAliases = FALSE;\r
+BOOLEAN mPolicyDetermined  = FALSE;\r
+\r
 /**\r
   The function is used to skip VGA range.\r
 \r
@@ -188,63 +195,61 @@ CalculateApertureIo16 (
   LIST_ENTRY              *CurrentLink;\r
   PCI_RESOURCE_NODE       *Node;\r
   UINT64                  Offset;\r
-  BOOLEAN                 IsaEnable;\r
-  BOOLEAN                 VGAEnable;\r
   EFI_PCI_PLATFORM_POLICY PciPolicy;\r
+  UINT64                  PaddingAperture;\r
 \r
-  //\r
-  // Always assume there is ISA device and VGA device on the platform\r
-  // will be customized later\r
-  //\r
-  IsaEnable = FALSE;\r
-  VGAEnable = FALSE;\r
+  if (!mPolicyDetermined) {\r
+    //\r
+    // Check PciPlatform policy\r
+    //\r
+    Status = EFI_NOT_FOUND;\r
+    PciPolicy = 0;\r
+    if (gPciPlatformProtocol != NULL) {\r
+      Status = gPciPlatformProtocol->GetPlatformPolicy (\r
+                                       gPciPlatformProtocol,\r
+                                       &PciPolicy\r
+                                       );\r
+    }\r
 \r
-  //\r
-  // Check PciPlatform policy\r
-  //\r
-  if (gPciPlatformProtocol != NULL) {\r
-    Status = gPciPlatformProtocol->GetPlatformPolicy (\r
-                                     gPciPlatformProtocol,\r
-                                     &PciPolicy\r
-                                     );\r
-    if (!EFI_ERROR (Status)) {\r
-      if ((PciPolicy & EFI_RESERVE_ISA_IO_ALIAS) != 0) {\r
-        IsaEnable = TRUE;\r
-      }\r
-      if ((PciPolicy & EFI_RESERVE_VGA_IO_ALIAS) != 0) {\r
-        VGAEnable = TRUE;\r
-      }\r
+    if (EFI_ERROR (Status) && gPciOverrideProtocol != NULL) {\r
+      Status = gPciOverrideProtocol->GetPlatformPolicy (\r
+                                       gPciOverrideProtocol,\r
+                                       &PciPolicy\r
+                                       );\r
     }\r
-  } else if (gPciOverrideProtocol != NULL) {\r
-    Status = gPciOverrideProtocol->GetPlatformPolicy (\r
-                                     gPciOverrideProtocol,\r
-                                     &PciPolicy\r
-                                     );\r
+\r
     if (!EFI_ERROR (Status)) {\r
       if ((PciPolicy & EFI_RESERVE_ISA_IO_ALIAS) != 0) {\r
-        IsaEnable = TRUE;\r
+        mReserveIsaAliases = TRUE;\r
       }\r
       if ((PciPolicy & EFI_RESERVE_VGA_IO_ALIAS) != 0) {\r
-        VGAEnable = TRUE;\r
+        mReserveVgaAliases = TRUE;\r
       }\r
     }\r
+    mPolicyDetermined = TRUE;\r
   }\r
 \r
-  Aperture = 0;\r
+  Aperture        = 0;\r
+  PaddingAperture = 0;\r
 \r
   if (Bridge == NULL) {\r
     return ;\r
   }\r
 \r
-  CurrentLink = Bridge->ChildList.ForwardLink;\r
-\r
   //\r
   // Assume the bridge is aligned\r
   //\r
-  while (CurrentLink != &Bridge->ChildList) {\r
+  for ( CurrentLink = GetFirstNode (&Bridge->ChildList)\r
+      ; !IsNull (&Bridge->ChildList, CurrentLink)\r
+      ; CurrentLink = GetNextNode (&Bridge->ChildList, CurrentLink)\r
+      ) {\r
 \r
     Node = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
-\r
+    if (Node->ResourceUsage == PciResUsagePadding) {\r
+      ASSERT (PaddingAperture == 0);\r
+      PaddingAperture = Node->Length;\r
+      continue;\r
+    }\r
     //\r
     // Consider the aperture alignment\r
     //\r
@@ -261,13 +266,13 @@ CalculateApertureIo16 (
     // If both of them are enabled, then the IO resource would\r
     // become too limited to meet the requirement of most of devices.\r
     //\r
-    if (IsaEnable || VGAEnable) {\r
+    if (mReserveIsaAliases || mReserveVgaAliases) {\r
       if (!IS_PCI_BRIDGE (&(Node->PciDev->Pci)) && !IS_CARDBUS_BRIDGE (&(Node->PciDev->Pci))) {\r
         //\r
         // Check if there is need to support ISA/VGA decoding\r
         // If so, we need to avoid isa/vga aliasing range\r
         //\r
-        if (IsaEnable) {\r
+        if (mReserveIsaAliases) {\r
           SkipIsaAliasAperture (\r
             &Aperture,\r
             Node->Length\r
@@ -276,7 +281,7 @@ CalculateApertureIo16 (
           if (Offset != 0) {\r
             Aperture = Aperture + (Node->Alignment + 1) - Offset;\r
           }\r
-        } else if (VGAEnable) {\r
+        } else if (mReserveVgaAliases) {\r
           SkipVGAAperture (\r
             &Aperture,\r
             Node->Length\r
@@ -295,13 +300,10 @@ CalculateApertureIo16 (
     // Increment aperture by the length of node\r
     //\r
     Aperture += Node->Length;\r
-\r
-    CurrentLink = CurrentLink->ForwardLink;\r
   }\r
 \r
   //\r
-  // At last, adjust the aperture with the bridge's\r
-  // alignment\r
+  // Adjust the aperture with the bridge's alignment\r
   //\r
   Offset = Aperture & (Bridge->Alignment);\r
 \r
@@ -321,6 +323,12 @@ CalculateApertureIo16 (
       Bridge->Alignment = Node->Alignment;\r
     }\r
   }\r
+\r
+  //\r
+  // Hotplug controller needs padding resources.\r
+  // Use the larger one between the padding resource and actual occupied resource.\r
+  //\r
+  Bridge->Length = MAX (Bridge->Length, PaddingAperture);\r
 }\r
 \r
 /**\r
@@ -338,10 +346,11 @@ CalculateResourceAperture (
   UINT64            Aperture;\r
   LIST_ENTRY        *CurrentLink;\r
   PCI_RESOURCE_NODE *Node;\r
-\r
+  UINT64            PaddingAperture;\r
   UINT64            Offset;\r
 \r
-  Aperture = 0;\r
+  Aperture        = 0;\r
+  PaddingAperture = 0;\r
 \r
   if (Bridge == NULL) {\r
     return ;\r
@@ -353,14 +362,20 @@ CalculateResourceAperture (
     return ;\r
   }\r
 \r
-  CurrentLink = Bridge->ChildList.ForwardLink;\r
-\r
   //\r
   // Assume the bridge is aligned\r
   //\r
-  while (CurrentLink != &Bridge->ChildList) {\r
+  for ( CurrentLink = GetFirstNode (&Bridge->ChildList)\r
+      ; !IsNull (&Bridge->ChildList, CurrentLink)\r
+      ; CurrentLink = GetNextNode (&Bridge->ChildList, CurrentLink)\r
+      ) {\r
 \r
     Node = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
+    if (Node->ResourceUsage == PciResUsagePadding) {\r
+      ASSERT (PaddingAperture == 0);\r
+      PaddingAperture = Node->Length;\r
+      continue;\r
+    }\r
 \r
     //\r
     // Apply padding resource if available\r
@@ -383,11 +398,6 @@ CalculateResourceAperture (
     // Increment aperture by the length of node\r
     //\r
     Aperture += Node->Length;\r
-\r
-    //\r
-    // Consider the aperture alignment\r
-    //\r
-    CurrentLink = CurrentLink->ForwardLink;\r
   }\r
 \r
   //\r
@@ -409,7 +419,7 @@ CalculateResourceAperture (
   }\r
 \r
   //\r
-  // At last, adjust the bridge's alignment to the first child's alignment\r
+  // Adjust the bridge's alignment to the first child's alignment\r
   // if the bridge has at least one child\r
   //\r
   CurrentLink = Bridge->ChildList.ForwardLink;\r
@@ -419,6 +429,12 @@ CalculateResourceAperture (
       Bridge->Alignment = Node->Alignment;\r
     }\r
   }\r
+\r
+  //\r
+  // Hotplug controller needs padding resources.\r
+  // Use the larger one between the padding resource and actual occupied resource.\r
+  //\r
+  Bridge->Length = MAX (Bridge->Length, PaddingAperture);\r
 }\r
 \r
 /**\r
@@ -726,17 +742,6 @@ CreateVfResourceNode (
 {\r
   PCI_RESOURCE_NODE *Node;\r
 \r
-  DEBUG ((\r
-    EFI_D_INFO,\r
-    "PCI-IOV B%x.D%x.F%x - VfResource (Bar - 0x%x) (Type - 0x%x) (Length - 0x%x)\n",\r
-    (UINTN)PciDev->BusNumber,\r
-    (UINTN)PciDev->DeviceNumber,\r
-    (UINTN)PciDev->FunctionNumber,\r
-    (UINTN)Bar,\r
-    (UINTN)ResType,\r
-    (UINTN)Length\r
-    ));\r
-\r
   Node = CreateResourceNode (PciDev, Length, Alignment, Bar, ResType, ResUsage);\r
   if (Node == NULL) {\r
     return Node;\r
@@ -1047,50 +1052,56 @@ DegradeResource (
   IN PCI_RESOURCE_NODE *PMem64Node\r
   )\r
 {\r
-  PCI_IO_DEVICE        *Temp;\r
+  PCI_IO_DEVICE        *PciIoDevice;\r
   LIST_ENTRY           *ChildDeviceLink;\r
   LIST_ENTRY           *ChildNodeLink;\r
   LIST_ENTRY           *NextChildNodeLink;\r
-  PCI_RESOURCE_NODE    *TempNode;\r
+  PCI_RESOURCE_NODE    *ResourceNode;\r
 \r
-  //\r
-  // If any child device has both option ROM and 64-bit BAR, degrade its PMEM64/MEM64\r
-  // requests in case that if a legacy option ROM image can not access 64-bit resources.\r
-  //\r
-  ChildDeviceLink = Bridge->ChildList.ForwardLink;\r
-  while (ChildDeviceLink != NULL && ChildDeviceLink != &Bridge->ChildList) {\r
-    Temp = PCI_IO_DEVICE_FROM_LINK (ChildDeviceLink);\r
-    if (Temp->RomSize != 0) {\r
-      if (!IsListEmpty (&Mem64Node->ChildList)) {      \r
-        ChildNodeLink = Mem64Node->ChildList.ForwardLink;\r
-        while (ChildNodeLink != &Mem64Node->ChildList) {\r
-          TempNode = RESOURCE_NODE_FROM_LINK (ChildNodeLink);\r
-          NextChildNodeLink = ChildNodeLink->ForwardLink;\r
-\r
-          if (TempNode->PciDev == Temp) {\r
-            RemoveEntryList (ChildNodeLink);\r
-            InsertResourceNode (Mem32Node, TempNode);\r
+  if (FeaturePcdGet (PcdPciDegradeResourceForOptionRom)) {\r
+    //\r
+    // If any child device has both option ROM and 64-bit BAR, degrade its PMEM64/MEM64\r
+    // requests in case that if a legacy option ROM image can not access 64-bit resources.\r
+    //\r
+    ChildDeviceLink = Bridge->ChildList.ForwardLink;\r
+    while (ChildDeviceLink != NULL && ChildDeviceLink != &Bridge->ChildList) {\r
+      PciIoDevice = PCI_IO_DEVICE_FROM_LINK (ChildDeviceLink);\r
+      if (PciIoDevice->RomSize != 0) {\r
+        if (!IsListEmpty (&Mem64Node->ChildList)) {\r
+          ChildNodeLink = Mem64Node->ChildList.ForwardLink;\r
+          while (ChildNodeLink != &Mem64Node->ChildList) {\r
+            ResourceNode = RESOURCE_NODE_FROM_LINK (ChildNodeLink);\r
+            NextChildNodeLink = ChildNodeLink->ForwardLink;\r
+\r
+            if ((ResourceNode->PciDev == PciIoDevice) &&\r
+                (ResourceNode->Virtual || !PciIoDevice->PciBar[ResourceNode->Bar].BarTypeFixed)\r
+                ) {\r
+              RemoveEntryList (ChildNodeLink);\r
+              InsertResourceNode (Mem32Node, ResourceNode);\r
+            }\r
+            ChildNodeLink = NextChildNodeLink;\r
           }\r
-          ChildNodeLink = NextChildNodeLink;\r
-        }        \r
-      }\r
-\r
-      if (!IsListEmpty (&PMem64Node->ChildList)) {      \r
-        ChildNodeLink = PMem64Node->ChildList.ForwardLink;\r
-        while (ChildNodeLink != &PMem64Node->ChildList) {\r
-          TempNode = RESOURCE_NODE_FROM_LINK (ChildNodeLink);\r
-          NextChildNodeLink = ChildNodeLink->ForwardLink;\r
+        }\r
 \r
-          if (TempNode->PciDev == Temp) {\r
-            RemoveEntryList (ChildNodeLink);\r
-            InsertResourceNode (PMem32Node, TempNode);\r
+        if (!IsListEmpty (&PMem64Node->ChildList)) {\r
+          ChildNodeLink = PMem64Node->ChildList.ForwardLink;\r
+          while (ChildNodeLink != &PMem64Node->ChildList) {\r
+            ResourceNode = RESOURCE_NODE_FROM_LINK (ChildNodeLink);\r
+            NextChildNodeLink = ChildNodeLink->ForwardLink;\r
+\r
+            if ((ResourceNode->PciDev == PciIoDevice) &&\r
+                (ResourceNode->Virtual || !PciIoDevice->PciBar[ResourceNode->Bar].BarTypeFixed)\r
+                ) {\r
+              RemoveEntryList (ChildNodeLink);\r
+              InsertResourceNode (PMem32Node, ResourceNode);\r
+            }\r
+            ChildNodeLink = NextChildNodeLink;\r
           }\r
-          ChildNodeLink = NextChildNodeLink;\r
-        }        \r
-      }\r
+        }\r
 \r
+      }\r
+      ChildDeviceLink = ChildDeviceLink->ForwardLink;\r
     }\r
-    ChildDeviceLink = ChildDeviceLink->ForwardLink;\r
   }\r
 \r
   //\r
@@ -1405,17 +1416,6 @@ ProgramVfBar (
                 );\r
 \r
     Node->PciDev->VfPciBar[Node->Bar].BaseAddress = Address;\r
-\r
-    DEBUG ((\r
-      EFI_D_INFO,\r
-      "PCI-IOV B%x.D%x.F%x - VF Bar (Offset - 0x%x) 32Mem (Address - 0x%x)\n",\r
-      (UINTN)Node->PciDev->BusNumber,\r
-      (UINTN)Node->PciDev->DeviceNumber,\r
-      (UINTN)Node->PciDev->FunctionNumber,\r
-      (UINTN)(Node->PciDev->VfPciBar[Node->Bar]).Offset,\r
-      (UINTN)Address\r
-      ));\r
-\r
     break;\r
 \r
   case PciBarTypeMem64:\r
@@ -1442,17 +1442,6 @@ ProgramVfBar (
                 );\r
 \r
     Node->PciDev->VfPciBar[Node->Bar].BaseAddress = Address;\r
-\r
-    DEBUG ((\r
-      EFI_D_INFO,\r
-      "PCI-IOV B%x.D%x.F%x - VF Bar (Offset - 0x%x) 64Mem (Address - 0x%lx)\n",\r
-      (UINTN)Node->PciDev->BusNumber,\r
-      (UINTN)Node->PciDev->DeviceNumber,\r
-      (UINTN)Node->PciDev->FunctionNumber,\r
-      (UINTN)(Node->PciDev->VfPciBar[Node->Bar]).Offset,\r
-      (UINT64)Address\r
-      ));\r
-\r
     break;\r
 \r
   case PciBarTypeIo16:\r
@@ -1507,7 +1496,14 @@ ProgramPpbApperture (
 \r
   case PPB_BAR_0:\r
   case PPB_BAR_1:\r
-    PciIo->Pci.Write (\r
+    switch ((Node->PciDev->PciBar[Node->Bar]).BarType) {\r
+\r
+      case PciBarTypeIo16:\r
+      case PciBarTypeIo32:\r
+      case PciBarTypeMem32:\r
+      case PciBarTypePMem32:\r
+\r
+        PciIo->Pci.Write (\r
                  PciIo,\r
                  EfiPciIoWidthUint32,\r
                  (Node->PciDev->PciBar[Node->Bar]).Offset,\r
@@ -1515,9 +1511,40 @@ ProgramPpbApperture (
                  &Address\r
                  );\r
 \r
-    Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
-    Node->PciDev->PciBar[Node->Bar].Length      = Node->Length;\r
+        Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
+        Node->PciDev->PciBar[Node->Bar].Length      = Node->Length;\r
+        break;\r
+\r
+      case PciBarTypeMem64:\r
+      case PciBarTypePMem64:\r
+\r
+        Address32 = (UINT32) (Address & 0x00000000FFFFFFFF);\r
 \r
+        PciIo->Pci.Write (\r
+                 PciIo,\r
+                 EfiPciIoWidthUint32,\r
+                 (Node->PciDev->PciBar[Node->Bar]).Offset,\r
+                 1,\r
+                 &Address32\r
+                 );\r
+\r
+        Address32 = (UINT32) RShiftU64 (Address, 32);\r
+\r
+        PciIo->Pci.Write (\r
+                 PciIo,\r
+                 EfiPciIoWidthUint32,\r
+                 (UINT8) ((Node->PciDev->PciBar[Node->Bar]).Offset + 4),\r
+                 1,\r
+                 &Address32\r
+                 );\r
+\r
+        Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
+        Node->PciDev->PciBar[Node->Bar].Length      = Node->Length;\r
+        break;\r
+\r
+      default:\r
+        break;\r
+    }\r
     break;\r
 \r
   case PPB_IO_RANGE:\r
@@ -1729,123 +1756,6 @@ InitializeResourcePool (
   InitializeListHead (&ResourcePool->ChildList);\r
 }\r
 \r
-\r
-/**\r
-  Get all resource information for given Pci device.\r
-\r
-  @param PciDev         Pci device instance.\r
-  @param IoBridge       Io resource node.\r
-  @param Mem32Bridge    32-bit memory node.\r
-  @param PMem32Bridge   32-bit Pmemory node.\r
-  @param Mem64Bridge    64-bit memory node.\r
-  @param PMem64Bridge   64-bit PMemory node.\r
-  @param IoPool         Link list header for Io resource.\r
-  @param Mem32Pool      Link list header for 32-bit memory.\r
-  @param PMem32Pool     Link list header for 32-bit Prefetchable memory.\r
-  @param Mem64Pool      Link list header for 64-bit memory.\r
-  @param PMem64Pool     Link list header for 64-bit Prefetchable memory.\r
-\r
-**/\r
-VOID\r
-GetResourceMap (\r
-  IN PCI_IO_DEVICE      *PciDev,\r
-  IN PCI_RESOURCE_NODE  **IoBridge,\r
-  IN PCI_RESOURCE_NODE  **Mem32Bridge,\r
-  IN PCI_RESOURCE_NODE  **PMem32Bridge,\r
-  IN PCI_RESOURCE_NODE  **Mem64Bridge,\r
-  IN PCI_RESOURCE_NODE  **PMem64Bridge,\r
-  IN PCI_RESOURCE_NODE  *IoPool,\r
-  IN PCI_RESOURCE_NODE  *Mem32Pool,\r
-  IN PCI_RESOURCE_NODE  *PMem32Pool,\r
-  IN PCI_RESOURCE_NODE  *Mem64Pool,\r
-  IN PCI_RESOURCE_NODE  *PMem64Pool\r
-  )\r
-{\r
-\r
-  PCI_RESOURCE_NODE *Temp;\r
-  LIST_ENTRY        *CurrentLink;\r
-\r
-  CurrentLink = IoPool->ChildList.ForwardLink;\r
-\r
-  //\r
-  // Get Io resource map\r
-  //\r
-  while (CurrentLink != &IoPool->ChildList) {\r
-\r
-    Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
-\r
-    if (Temp->PciDev == PciDev) {\r
-      *IoBridge = Temp;\r
-    }\r
-\r
-    CurrentLink = CurrentLink->ForwardLink;\r
-  }\r
-\r
-  //\r
-  // Get Mem32 resource map\r
-  //\r
-  CurrentLink = Mem32Pool->ChildList.ForwardLink;\r
-\r
-  while (CurrentLink != &Mem32Pool->ChildList) {\r
-\r
-    Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
-\r
-    if (Temp->PciDev == PciDev) {\r
-      *Mem32Bridge = Temp;\r
-    }\r
-\r
-    CurrentLink = CurrentLink->ForwardLink;\r
-  }\r
-\r
-  //\r
-  // Get Pmem32 resource map\r
-  //\r
-  CurrentLink = PMem32Pool->ChildList.ForwardLink;\r
-\r
-  while (CurrentLink != &PMem32Pool->ChildList) {\r
-\r
-    Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
-\r
-    if (Temp->PciDev == PciDev) {\r
-      *PMem32Bridge = Temp;\r
-    }\r
-\r
-    CurrentLink = CurrentLink->ForwardLink;\r
-  }\r
-\r
-  //\r
-  // Get Mem64 resource map\r
-  //\r
-  CurrentLink = Mem64Pool->ChildList.ForwardLink;\r
-\r
-  while (CurrentLink != &Mem64Pool->ChildList) {\r
-\r
-    Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
-\r
-    if (Temp->PciDev == PciDev) {\r
-      *Mem64Bridge = Temp;\r
-    }\r
-\r
-    CurrentLink = CurrentLink->ForwardLink;\r
-  }\r
-\r
-  //\r
-  // Get Pmem64 resource map\r
-  //\r
-  CurrentLink = PMem64Pool->ChildList.ForwardLink;\r
-\r
-  while (CurrentLink != &PMem64Pool->ChildList) {\r
-\r
-    Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
-\r
-    if (Temp->PciDev == PciDev) {\r
-      *PMem64Bridge = Temp;\r
-    }\r
-\r
-    CurrentLink = CurrentLink->ForwardLink;\r
-  }\r
-}\r
-\r
 /**\r
   Destory given resource tree.\r
 \r