diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
index cb44743f51..7bd8e8ba05 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
@@ -105,6 +105,7 @@
gEfiMdeModulePkgTokenSpaceGuid.PcdDisableBMEonEBS ## MU_CHANGE
gEfiMdeModulePkgTokenSpaceGuid.PcdPcieInitializeMps ## MU_CHANGE: Add support for initializing PCIe MPS
gEfiMdeModulePkgTokenSpaceGuid.PcdPciDegradeMem64toPMem64 ## CONSUMES # MU_CHANGE - MEM64 to PMEM64 conversion
+ gEfiMdeModulePkgTokenSpaceGuid.PcdPcieResizableBarMaxSize ## CONSUMES
[UserExtensions.TianoCore."ExtraFiles"]
PciBusDxeExtra.uni
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c
index 1601ee51f7..58e99211d5 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c
@@ -1827,22 +1827,59 @@ PciProgramResizableBar (
DEBUG ((
DEBUG_INFO,
- " Programs Resizable BAR register, offset: 0x%08x, number: %d\n",
+ " Program Resizable BAR registers at offset 0x%03X to %a (platform constraint 0x%lX)\n",
PciIoDevice->ResizableBarOffset,
- PciIoDevice->ResizableBarNumber
+ (ResizableBarOp == PciResizableBarMax) ? "max" :
+ (ResizableBarOp == PciResizableBarMin) ? "min" : "???",
+ LShiftU64 (SIZE_1MB, PcdGet8 (PcdPcieResizableBarMaxSize))
));
- ResizableBarNumber = MIN (PciIoDevice->ResizableBarNumber, PCI_MAX_BAR);
- PciIo = &PciIoDevice->PciIo;
- Status = PciIo->Pci.Read (
- PciIo,
- EfiPciIoWidthUint8,
- PciIoDevice->ResizableBarOffset + sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_HEADER),
- sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_ENTRY) * ResizableBarNumber,
- (VOID *)(&Entries)
- );
+ ResizableBarNumber = PciIoDevice->ResizableBarNumber;
+ if ((ResizableBarNumber == 0) || (ResizableBarNumber > PCI_MAX_BAR)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: Device %04X:%04x expose illegal Resizable BAR register (NumberOfResizableBar=%d) - ignore capability\n",
+ PciIoDevice->Pci.Hdr.VendorId,
+ PciIoDevice->Pci.Hdr.DeviceId,
+ ResizableBarNumber
+ ));
+ return EFI_DEVICE_ERROR;
+ }
+
+ PciIo = &PciIoDevice->PciIo;
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint8,
+ PciIoDevice->ResizableBarOffset + sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_HEADER),
+ sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_ENTRY) * ResizableBarNumber,
+ (VOID *)(&Entries)
+ );
ASSERT_EFI_ERROR (Status);
+ for (Index = 0; Index < PciIoDevice->ResizableBarNumber; Index++) {
+ //
+ // BAR index can be 0..5 for:
+ // 0 BAR located at offset 10h
+ // 1 BAR located at offset 14h
+ // 2 BAR located at offset 18h
+ // 3 BAR located at offset 1ch
+ // 4 BAR located at offset 20h
+ // 5 BAR located at offset 24h
+ // other illegal, do not configure anything if such entry was found.
+ //
+ if (Entries[Index].ResizableBarControl.Bits.BarIndex >= PCI_MAX_BAR ) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: Device %04X:%04x expose illegal Resizable BAR register (Entry[%d].BarIndex=%d) - ignore capability\n",
+ PciIoDevice->Pci.Hdr.VendorId,
+ PciIoDevice->Pci.Hdr.DeviceId,
+ Index,
+ Entries[Index].ResizableBarControl.Bits.BarIndex
+ ));
+ return EFI_DEVICE_ERROR;
+ }
+ }
+
for (Index = 0; Index < ResizableBarNumber; Index++) {
//
// When the bit of Capabilities Set, indicates that the Function supports
@@ -1851,18 +1888,36 @@ PciProgramResizableBar (
// Bit 0 is set: supports operating with the BAR sized to 1 MB
// Bit 1 is set: supports operating with the BAR sized to 2 MB
// Bit n is set: supports operating with the BAR sized to (2^n) MB
+ // With PcdPcieResizableBarMaxSize platform may impose limitation on the BAR size it supports.
//
Capabilities = LShiftU64 (Entries[Index].ResizableBarControl.Bits.BarSizeCapability, 28)
| Entries[Index].ResizableBarCapability.Bits.BarSizeCapability;
-
- if (ResizableBarOp == PciResizableBarMax) {
- Bit = HighBitSet64 (Capabilities);
+ Capabilities &= LShiftU64 (1, PcdGet8 (PcdPcieResizableBarMaxSize) + 1) - 1;
+ if (Capabilities == 0) {
+ //
+ // No size within the constraint, just set lowest size supported, per spec there must be something in legacy bits.
+ //
+ Bit = LowBitSet64 (Entries[Index].ResizableBarCapability.Bits.BarSizeCapability);
} else {
- ASSERT (ResizableBarOp == PciResizableBarMin);
- Bit = LowBitSet64 (Capabilities);
+ if (ResizableBarOp == PciResizableBarMax) {
+ Bit = HighBitSet64 (Capabilities);
+ } else {
+ ASSERT (ResizableBarOp == PciResizableBarMin);
+ Bit = LowBitSet64 (Capabilities);
+ }
}
- ASSERT (Bit >= 0);
+ if (Bit < 0) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: Device %04X:%04x expose illegal Resizable BAR register (Entry[%d].BarSizeCapability=%04X) - ignore entry\n",
+ PciIoDevice->Pci.Hdr.VendorId,
+ PciIoDevice->Pci.Hdr.DeviceId,
+ Index,
+ Entries[Index].ResizableBarCapability.Bits.BarSizeCapability
+ ));
+ continue;
+ }
Offset = PciIoDevice->ResizableBarOffset + sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_HEADER)
+ Index * sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_ENTRY)
@@ -1871,7 +1926,7 @@ PciProgramResizableBar (
Entries[Index].ResizableBarControl.Bits.BarSize = (UINT32)Bit;
DEBUG ((
DEBUG_INFO,
- " Resizable Bar: Offset = 0x%x, Bar Size Capability = 0x%016lx, New Bar Size = 0x%lx\n",
+ " Resizable BAR: offset = 0x%X, size capability mask = 0x%012lX, new BAR size = 0x%lX\n",
OFFSET_OF (PCI_TYPE00, Device.Bar[Entries[Index].ResizableBarControl.Bits.BarIndex]),
Capabilities,
LShiftU64 (SIZE_1MB, Bit)
diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec
index aefb8e52eb..d8e656ce2f 100644
--- a/MdeModulePkg/MdeModulePkg.dec
+++ b/MdeModulePkg/MdeModulePkg.dec
@@ -2564,6 +2564,15 @@
# @Prompt Support degrading Mem64 to PMem64 during PCI enumeration
gEfiMdeModulePkgTokenSpaceGuid.PcdPciDegradeMem64toPMem64|FALSE|BOOLEAN|0x1000002C
# MU_CHANGE End - MEM64 to PMEM64 conversion
+ ## Defines platform limit for BAR size that can be accepted in Resizable BAR Capability.
+ # BAR Capability bits specify size in MB, thus this PCD value shall be extended with +20 bits.
+ # 0 2^(0+20) = 1 MB
+ # 1 2^(1+20) = 2 MB
+ # ...
+ # 42 2^(42+20) = 4 EB
+ # 43 2^(43+20) = 8 EB
+ # @Prompt Max size to accept in PCIe Resizable BAR Capability register.
+ gEfiMdeModulePkgTokenSpaceGuid.PcdPcieResizableBarMaxSize|43|UINT8|0x10000030
[PcdsPatchableInModule]
## Specify memory size with page number for PEI code when
diff --git a/MdeModulePkg/MdeModulePkg.uni b/MdeModulePkg/MdeModulePkg.uni
index cce8426bb9..b4d33ac3c7 100644
--- a/MdeModulePkg/MdeModulePkg.uni
+++ b/MdeModulePkg/MdeModulePkg.uni
@@ -1352,3 +1352,8 @@
#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdPcieResizableBarSupport_HELP #language en-US "Indicates if the PCIe Resizable BAR Capability Supported.
\n"
"TRUE - PCIe Resizable BAR Capability is supported.
\n"
"FALSE - PCIe Resizable BAR Capability is not supported.
"
+
+#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdPcieResizableBarMaxSize_PROMPT #language en-US "Define Resizable BAR Max Size Constraint"
+#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdPcieResizableBarMaxSize_HELP #language en-US "Set platform limit for max size to pick from Resizable BAR Capability register.
\n"
+ "Decimal value 'n' is interpreted as 2^(n+20), which means 0=>1MB, 1=>2MB, 2=>4MB, 3=>8MB, etc.
\n"
+ "Maximum reasonable size to set is half of processor address with, i.e. address width - 1.
\n"