MdeModulePkg/PciBus: Shadow option ROM after BARs are programmed
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=1376 Today's implementation reuses the 32bit MMIO resource requested by all PCI devices MMIO BARs when shadowing the option ROM. Take a simple example, a system has only one PCI device. It requires 8MB 32bit MMIO and contains a 4MB option ROM. Today's implementation only requests 8MB (max of 4M and 8M) 32bit MMIO from PciHostBridgeResourceAllocation protocol. Let's assume the MMIO range [3GB, 3GB+8MB) is allocated. The 3GB base address is firstly programmed to the option ROM BAR for option ROM shadow. Then the option ROM decoding is turned off and 3GB base address is programmed to the 32bit MMIO BAR. It doesn't cause issues when the device doesn't request too much MMIO. But when the device contains a 64bit MMIO BAR which requests 4GB MMIO and a 4MB option ROM. Let's assume [3GB, 3GB+8MB) 32bit MMIO range is allocated for the option ROM. When the option ROM is being shadowed, 64bit MMIO BAR is programmed to value 0, which means [0, 4GB) MMIO is given to the 64bit BAR. The range overlaps with the option ROM range which may cause the device malfunction (e.g.: option ROM cannot be read out) when the device has two separate decoders: one for MMIO BAR, the other for option ROM. The patch requests dedicated MEM32 resource for Option ROMs and moves the Option ROM shadow logic after all MMIO BARs are programmed. The MMIO BAR setting to 0 when shadowing Option ROM is also skipped because the MMIO BAR already contains the correct value. Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Reviewed-by: Hao Wu <hao.a.wu@intel.com>
This commit is contained in:
@@ -24,6 +24,7 @@ CHAR16 *mBarTypeStr[] = {
|
||||
L"PMem32",
|
||||
L" Mem64",
|
||||
L"PMem64",
|
||||
L" OpRom",
|
||||
L" Io",
|
||||
L" Mem",
|
||||
L"Unknow"
|
||||
@@ -425,15 +426,9 @@ PciHostBridgeResourceAllocator (
|
||||
PCI_RESOURCE_NODE PMem32Pool;
|
||||
PCI_RESOURCE_NODE Mem64Pool;
|
||||
PCI_RESOURCE_NODE PMem64Pool;
|
||||
BOOLEAN ReAllocate;
|
||||
EFI_DEVICE_HANDLE_EXTENDED_DATA_PAYLOAD HandleExtendedData;
|
||||
EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA_PAYLOAD AllocFailExtendedData;
|
||||
|
||||
//
|
||||
// Reallocate flag
|
||||
//
|
||||
ReAllocate = FALSE;
|
||||
|
||||
//
|
||||
// It may try several times if the resource allocation fails
|
||||
//
|
||||
@@ -514,6 +509,17 @@ PciHostBridgeResourceAllocator (
|
||||
PciResUsageTypical
|
||||
);
|
||||
|
||||
//
|
||||
// Get the max ROM size that the root bridge can process
|
||||
// Insert to resource map so that there will be dedicate MEM32 resource range for Option ROM.
|
||||
// All devices' Option ROM share the same MEM32 resource.
|
||||
//
|
||||
MaxOptionRomSize = GetMaxOptionRomSize (RootBridgeDev);
|
||||
RootBridgeDev->PciBar[0].BarType = PciBarTypeOpRom;
|
||||
RootBridgeDev->PciBar[0].Length = MaxOptionRomSize;
|
||||
RootBridgeDev->PciBar[0].Alignment = MaxOptionRomSize - 1;
|
||||
GetResourceFromDevice (RootBridgeDev, IoBridge, Mem32Bridge, PMem32Bridge, Mem64Bridge, PMem64Bridge);
|
||||
|
||||
//
|
||||
// Create resourcemap by going through all the devices subject to this root bridge
|
||||
//
|
||||
@@ -526,38 +532,6 @@ PciHostBridgeResourceAllocator (
|
||||
PMem64Bridge
|
||||
);
|
||||
|
||||
//
|
||||
// Get the max ROM size that the root bridge can process
|
||||
//
|
||||
RootBridgeDev->RomSize = Mem32Bridge->Length;
|
||||
|
||||
//
|
||||
// Skip to enlarge the resource request during realloction
|
||||
//
|
||||
if (!ReAllocate) {
|
||||
//
|
||||
// Get Max Option Rom size for current root bridge
|
||||
//
|
||||
MaxOptionRomSize = GetMaxOptionRomSize (RootBridgeDev);
|
||||
|
||||
//
|
||||
// Enlarger the mem32 resource to accomdate the option rom
|
||||
// if the mem32 resource is not enough to hold the rom
|
||||
//
|
||||
if (MaxOptionRomSize > Mem32Bridge->Length) {
|
||||
|
||||
Mem32Bridge->Length = MaxOptionRomSize;
|
||||
RootBridgeDev->RomSize = MaxOptionRomSize;
|
||||
|
||||
//
|
||||
// Alignment should be adjusted as well
|
||||
//
|
||||
if (Mem32Bridge->Alignment < MaxOptionRomSize - 1) {
|
||||
Mem32Bridge->Alignment = MaxOptionRomSize - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Based on the all the resource tree, construct ACPI resource node to
|
||||
// submit the resource aperture to pci host bridge protocol
|
||||
@@ -760,8 +734,6 @@ PciHostBridgeResourceAllocator (
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
ReAllocate = TRUE;
|
||||
}
|
||||
}
|
||||
//
|
||||
@@ -828,11 +800,6 @@ PciHostBridgeResourceAllocator (
|
||||
&PMem64Base
|
||||
);
|
||||
|
||||
//
|
||||
// Process option rom for this root bridge
|
||||
//
|
||||
ProcessOptionRom (RootBridgeDev, Mem32Base, RootBridgeDev->RomSize);
|
||||
|
||||
//
|
||||
// Create the entire system resource map from the information collected by
|
||||
// enumerator. Several resource tree was created
|
||||
@@ -889,6 +856,20 @@ PciHostBridgeResourceAllocator (
|
||||
PMem64Bridge
|
||||
);
|
||||
|
||||
//
|
||||
// Process Option ROM for this root bridge after all BARs are programmed.
|
||||
// The PPB's MEM32 RANGE BAR is re-programmed to the Option ROM BAR Base in order to
|
||||
// shadow the Option ROM of the devices under the PPB.
|
||||
// After the shadow, Option ROM BAR decoding is turned off and the PPB's MEM32 RANGE
|
||||
// BAR is restored back to the original value.
|
||||
// The original value is programmed by ProgramResource() above.
|
||||
//
|
||||
DEBUG ((
|
||||
DEBUG_INFO, "Process Option ROM: BAR Base/Length = %lx/%lx\n",
|
||||
RootBridgeDev->PciBar[0].BaseAddress, RootBridgeDev->PciBar[0].Length
|
||||
));
|
||||
ProcessOptionRom (RootBridgeDev, RootBridgeDev->PciBar[0].BaseAddress, RootBridgeDev->PciBar[0].Length);
|
||||
|
||||
IoBridge ->PciDev->PciBar[IoBridge ->Bar].BaseAddress = IoBase;
|
||||
Mem32Bridge ->PciDev->PciBar[Mem32Bridge ->Bar].BaseAddress = Mem32Base;
|
||||
PMem32Bridge->PciDev->PciBar[PMem32Bridge->Bar].BaseAddress = PMem32Base;
|
||||
|
Reference in New Issue
Block a user