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"