]> git.proxmox.com Git - mirror_edk2.git/commitdiff
MdeModulePkg/PciBus: Fix a bug PPB MEM32 BAR isn't restored sometimes
authorRay Ni <ray.ni@intel.com>
Fri, 1 Feb 2019 08:51:40 +0000 (16:51 +0800)
committerRay Ni <ray.ni@intel.com>
Thu, 14 Feb 2019 06:56:57 +0000 (14:56 +0800)
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=1505

When a device under PPB contains option ROM but doesn't require 32bit
MMIO, ProgrameUpstreamBridgeForRom() cannot correctly restore the
PPB MEM32 RANGE BAR. It causes the 32bit MMIO conflict which may
cause system hangs in boot.

The root cause is when ProgrameUpstreamBridgeForRom() calls
ProgramPpbApperture() to restore the PPB MEM32 RANGE BAR, the
ProgramPpbApperture() skips to program the BAR when the resource
length is 0.

This patch fixes this issue by not calling ProgramPpbApperture().
Instead, it directly programs the PPB MEM32 RANGE BAR.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Ray Ni <ray.ni@intel.com>
Reviewed-by: Hao Wu <hao.a.wu@intel.com>
Cc: Dandan Bi <dandan.bi@intel.com>
MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c

index f5ae3d857b6b1564430d2638f056fabb67f8edac..70e45040e2efb2777f3386c59f0a620e06302d91 100644 (file)
@@ -1661,57 +1661,52 @@ ProgramUpstreamBridgeForRom (
   IN BOOLEAN         Enable\r
   )\r
 {\r
   IN BOOLEAN         Enable\r
   )\r
 {\r
-  PCI_IO_DEVICE     *Parent;\r
-  PCI_RESOURCE_NODE Node;\r
-  UINT64            Base;\r
-  UINT64            Length;\r
+  PCI_IO_DEVICE       *Parent;\r
+  EFI_PCI_IO_PROTOCOL *PciIo;\r
+  UINT16              Base;\r
+  UINT16              Limit;\r
   //\r
   // For root bridge, just return.\r
   //\r
   Parent = PciDevice->Parent;\r
   //\r
   // For root bridge, just return.\r
   //\r
   Parent = PciDevice->Parent;\r
-  ZeroMem (&Node, sizeof (Node));\r
   while (Parent != NULL) {\r
     if (!IS_PCI_BRIDGE (&Parent->Pci)) {\r
       break;\r
     }\r
 \r
   while (Parent != NULL) {\r
     if (!IS_PCI_BRIDGE (&Parent->Pci)) {\r
       break;\r
     }\r
 \r
-    Node.PciDev     = Parent;\r
-    Node.Alignment  = 0;\r
-    Node.Bar        = PPB_MEM32_RANGE;\r
-    Node.ResType    = PciBarTypeMem32;\r
-    Node.Offset     = 0;\r
+    PciIo = &Parent->PciIo;\r
 \r
     //\r
     // Program PPB to only open a single <= 16MB aperture\r
     //\r
     if (Enable) {\r
 \r
     //\r
     // Program PPB to only open a single <= 16MB aperture\r
     //\r
     if (Enable) {\r
-      //\r
-      // Save the original PPB_MEM32_RANGE BAR.\r
-      // The values will be changed by ProgramPpbApperture().\r
-      //\r
-      Base   = Parent->PciBar[Node.Bar].BaseAddress;\r
-      Length = Parent->PciBar[Node.Bar].Length;\r
-\r
       //\r
       // Only cover MMIO for Option ROM.\r
       //\r
       //\r
       // Only cover MMIO for Option ROM.\r
       //\r
-      Node.Length     = PciDevice->RomSize;\r
-      ProgramPpbApperture (OptionRomBase, &Node);\r
-\r
-      //\r
-      // Restore the original PPB_MEM32_RANGE BAR.\r
-      // So the MEM32 RANGE BAR register can be restored when disable the decoding.\r
-      //\r
-      Parent->PciBar[Node.Bar].BaseAddress = Base;\r
-      Parent->PciBar[Node.Bar].Length      = Length;\r
+      Base  = (UINT16) (OptionRomBase >> 16);\r
+      Limit = (UINT16) ((OptionRomBase + PciDevice->RomSize - 1) >> 16);\r
+      PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, OFFSET_OF (PCI_TYPE01, Bridge.MemoryBase),  1, &Base);\r
+      PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, OFFSET_OF (PCI_TYPE01, Bridge.MemoryLimit), 1, &Limit);\r
 \r
       PCI_ENABLE_COMMAND_REGISTER (Parent, EFI_PCI_COMMAND_MEMORY_SPACE);\r
     } else {\r
       //\r
       // Cover 32bit MMIO for devices below the bridge.\r
       //\r
 \r
       PCI_ENABLE_COMMAND_REGISTER (Parent, EFI_PCI_COMMAND_MEMORY_SPACE);\r
     } else {\r
       //\r
       // Cover 32bit MMIO for devices below the bridge.\r
       //\r
-      Node.Length     = Parent->PciBar[Node.Bar].Length;\r
-      ProgramPpbApperture (Parent->PciBar[Node.Bar].BaseAddress, &Node);\r
+      if (Parent->PciBar[PPB_MEM32_RANGE].Length == 0) {\r
+        //\r
+        // When devices under the bridge contains Option ROM and doesn't require 32bit MMIO.\r
+        //\r
+        Base  = (UINT16) gAllOne;\r
+        Limit = (UINT16) gAllZero;\r
+      } else {\r
+        Base  = (UINT16) ((UINT32) Parent->PciBar[PPB_MEM32_RANGE].BaseAddress >> 16);\r
+        Limit = (UINT16) ((UINT32) (Parent->PciBar[PPB_MEM32_RANGE].BaseAddress\r
+                                    + Parent->PciBar[PPB_MEM32_RANGE].Length - 1) >> 16);\r
+      }\r
+      PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, OFFSET_OF (PCI_TYPE01, Bridge.MemoryBase),  1, &Base);\r
+      PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, OFFSET_OF (PCI_TYPE01, Bridge.MemoryLimit), 1, &Limit);\r
+\r
       PCI_DISABLE_COMMAND_REGISTER (Parent, EFI_PCI_COMMAND_MEMORY_SPACE);\r
     }\r
 \r
       PCI_DISABLE_COMMAND_REGISTER (Parent, EFI_PCI_COMMAND_MEMORY_SPACE);\r
     }\r
 \r