summaryrefslogtreecommitdiffstats
path: root/MdeModulePkg
diff options
context:
space:
mode:
authorRay Ni <ray.ni@intel.com>2019-02-01 16:51:40 +0800
committerRay Ni <ray.ni@intel.com>2019-02-14 14:56:57 +0800
commit0fa92d5839cddeb63a7e4583fdbca49b16599e3a (patch)
tree2b2f63e2397cc6058e36eb61214d601d37f025bf /MdeModulePkg
parentfcdfcdbfc2e5dc6a96ce550a1f46edb4007f35a9 (diff)
downloadedk2-0fa92d5839cddeb63a7e4583fdbca49b16599e3a.tar.gz
edk2-0fa92d5839cddeb63a7e4583fdbca49b16599e3a.tar.bz2
edk2-0fa92d5839cddeb63a7e4583fdbca49b16599e3a.zip
MdeModulePkg/PciBus: Fix a bug PPB MEM32 BAR isn't restored sometimes
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>
Diffstat (limited to 'MdeModulePkg')
-rw-r--r--MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c51
1 files changed, 23 insertions, 28 deletions
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c
index f5ae3d857b..70e45040e2 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c
@@ -1661,57 +1661,52 @@ ProgramUpstreamBridgeForRom (
IN BOOLEAN Enable
)
{
- PCI_IO_DEVICE *Parent;
- PCI_RESOURCE_NODE Node;
- UINT64 Base;
- UINT64 Length;
+ PCI_IO_DEVICE *Parent;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINT16 Base;
+ UINT16 Limit;
//
// For root bridge, just return.
//
Parent = PciDevice->Parent;
- ZeroMem (&Node, sizeof (Node));
while (Parent != NULL) {
if (!IS_PCI_BRIDGE (&Parent->Pci)) {
break;
}
- Node.PciDev = Parent;
- Node.Alignment = 0;
- Node.Bar = PPB_MEM32_RANGE;
- Node.ResType = PciBarTypeMem32;
- Node.Offset = 0;
+ PciIo = &Parent->PciIo;
//
// Program PPB to only open a single <= 16MB aperture
//
if (Enable) {
//
- // Save the original PPB_MEM32_RANGE BAR.
- // The values will be changed by ProgramPpbApperture().
- //
- Base = Parent->PciBar[Node.Bar].BaseAddress;
- Length = Parent->PciBar[Node.Bar].Length;
-
- //
// Only cover MMIO for Option ROM.
//
- Node.Length = PciDevice->RomSize;
- ProgramPpbApperture (OptionRomBase, &Node);
-
- //
- // Restore the original PPB_MEM32_RANGE BAR.
- // So the MEM32 RANGE BAR register can be restored when disable the decoding.
- //
- Parent->PciBar[Node.Bar].BaseAddress = Base;
- Parent->PciBar[Node.Bar].Length = Length;
+ Base = (UINT16) (OptionRomBase >> 16);
+ Limit = (UINT16) ((OptionRomBase + PciDevice->RomSize - 1) >> 16);
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, OFFSET_OF (PCI_TYPE01, Bridge.MemoryBase), 1, &Base);
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, OFFSET_OF (PCI_TYPE01, Bridge.MemoryLimit), 1, &Limit);
PCI_ENABLE_COMMAND_REGISTER (Parent, EFI_PCI_COMMAND_MEMORY_SPACE);
} else {
//
// Cover 32bit MMIO for devices below the bridge.
//
- Node.Length = Parent->PciBar[Node.Bar].Length;
- ProgramPpbApperture (Parent->PciBar[Node.Bar].BaseAddress, &Node);
+ if (Parent->PciBar[PPB_MEM32_RANGE].Length == 0) {
+ //
+ // When devices under the bridge contains Option ROM and doesn't require 32bit MMIO.
+ //
+ Base = (UINT16) gAllOne;
+ Limit = (UINT16) gAllZero;
+ } else {
+ Base = (UINT16) ((UINT32) Parent->PciBar[PPB_MEM32_RANGE].BaseAddress >> 16);
+ Limit = (UINT16) ((UINT32) (Parent->PciBar[PPB_MEM32_RANGE].BaseAddress
+ + Parent->PciBar[PPB_MEM32_RANGE].Length - 1) >> 16);
+ }
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, OFFSET_OF (PCI_TYPE01, Bridge.MemoryBase), 1, &Base);
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, OFFSET_OF (PCI_TYPE01, Bridge.MemoryLimit), 1, &Limit);
+
PCI_DISABLE_COMMAND_REGISTER (Parent, EFI_PCI_COMMAND_MEMORY_SPACE);
}