Extend the existing IncompatiblePciDeviceSupportDxe driver to support explicit PCI BAR placement. CheckDevice() checks for a fixed-bars entry first, then falls back to the existing 64-bit-MMIO-preference descriptor.
Add FixedBars.c/.h to encapsulate fixed-BAR handling. Parse QEMU's etc/fixed-bars fw_cfg blob, reserve the specified PCI BAR address ranges in the GCD memory space map before PCI enumeration, provide fixed BAR descriptors to PciBusDxe during device discovery. Also, IncompatiblePciDeviceSupportDxe's CcProbe() call has no CcProbeLib resolution on ArmVirtQemu, which causes the build to fail. This patch adds a CcProbeLib resolution for ArmVirtQemu. Signed-off-by: Tushar Dave <[email protected]> --- ArmVirtPkg/ArmVirtQemu.dsc | 2 + ArmVirtPkg/ArmVirtQemuFvMain.fdf.inc | 1 + .../FixedBars.c | 413 ++++++++++++++++++ .../FixedBars.h | 63 +++ .../IncompatiblePciDeviceSupport.c | 114 +++-- .../IncompatiblePciDeviceSupport.inf | 8 +- 6 files changed, 570 insertions(+), 31 deletions(-) create mode 100644 OvmfPkg/IncompatiblePciDeviceSupportDxe/FixedBars.c create mode 100644 OvmfPkg/IncompatiblePciDeviceSupportDxe/FixedBars.h diff --git a/ArmVirtPkg/ArmVirtQemu.dsc b/ArmVirtPkg/ArmVirtQemu.dsc index a3f8a2d0ac..d331a3a9bd 100644 --- a/ArmVirtPkg/ArmVirtQemu.dsc +++ b/ArmVirtPkg/ArmVirtQemu.dsc @@ -67,6 +67,7 @@ !include ArmVirtPkg/ArmVirt.dsc.inc [LibraryClasses.common] + CcProbeLib|MdePkg/Library/CcProbeLibNull/CcProbeLibNull.inf ArmTransferListLib|ArmPkg/Library/ArmTransferListLib/ArmTransferListLib.inf QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgMmioDxeLib.inf @@ -392,6 +393,7 @@ # # PCI support # + OvmfPkg/IncompatiblePciDeviceSupportDxe/IncompatiblePciDeviceSupport.inf MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf # diff --git a/ArmVirtPkg/ArmVirtQemuFvMain.fdf.inc b/ArmVirtPkg/ArmVirtQemuFvMain.fdf.inc index 3fb6a1da9d..3f0b00b2e7 100644 --- a/ArmVirtPkg/ArmVirtQemuFvMain.fdf.inc +++ b/ArmVirtPkg/ArmVirtQemuFvMain.fdf.inc @@ -159,6 +159,7 @@ READ_LOCK_STATUS = TRUE # PCI support # INF UefiCpuPkg/CpuMmio2Dxe/CpuMmio2Dxe.inf + INF OvmfPkg/IncompatiblePciDeviceSupportDxe/IncompatiblePciDeviceSupport.inf INF MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf INF MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf INF OvmfPkg/PciHotPlugInitDxe/PciHotPlugInit.inf diff --git a/OvmfPkg/IncompatiblePciDeviceSupportDxe/FixedBars.c b/OvmfPkg/IncompatiblePciDeviceSupportDxe/FixedBars.c new file mode 100644 index 0000000000..f307fb285c --- /dev/null +++ b/OvmfPkg/IncompatiblePciDeviceSupportDxe/FixedBars.c @@ -0,0 +1,413 @@ +/** @file + Fixed PCI BAR placement using metadata provided by QEMU through the + "etc/fixed-bars" fw_cfg blob. + + Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.<BR> + + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include <PiDxe.h> +#include <IndustryStandard/Acpi.h> +#include <Library/BaseMemoryLib.h> +#include <Library/DebugLib.h> +#include <Library/DxeServicesTableLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/QemuFwCfgLib.h> +#include <Library/UefiBootServicesTableLib.h> + +#include "FixedBars.h" + +/* byte-for-byte identical to QEMU's structs in hw/pci/pci-fixed-bar.h */ +#pragma pack (1) + +typedef struct { + UINT32 Version; + UINT32 NumDevices; +} QEMU_FIXED_BARS_HDR; /* 8 bytes */ + +typedef struct { + UINT16 VendorId; + UINT16 DeviceId; + UINT8 DevFlags; + UINT8 RpBus; + UINT8 NumBars; + UINT8 Reserved; + CHAR8 FwPath[128]; /* qdev_get_fw_dev_path(), unused here */ +} QEMU_FIXED_BARS_DEVICE; /* 136 bytes */ + +typedef struct { + UINT8 Bar; + UINT8 Reserved[3]; + UINT32 Flags; + UINT64 Address; + UINT64 Size; +} QEMU_FIXED_BARS_BAR; /* 24 bytes */ + +#pragma pack () + +#define QEMU_FIXED_BARS_VERSION 1 +#define QEMU_FIXED_BAR_F_MEM64 BIT0 +#define QEMU_FIXED_BAR_F_PREF BIT1 +#define QEMU_FIXED_BARS_DEV_F_FIXED BIT0 + +/* + * ACPI general-flag bits (ACPI 6.x 6.4.3.5.1): + * BIT2 = _MIF (minimum address fixed) + * BIT3 = _MAF (maximum address fixed) + * Both set means AddrRangeMin carries the exact required base address. + */ +#define ACPI_ADDR_FLAG_FIXED (BIT2 | BIT3) + +/* Raw blob kept in memory; device entries point into it. */ +STATIC UINT8 *mBlobData; +STATIC QEMU_FIXED_BARS_HDR mHdr; + +/* Pre-parsed per-device index built from the blob at startup. */ +typedef struct { + UINT16 VendorId; + UINT16 DeviceId; + UINT8 DevFlags; + UINT8 RpBus; /* primary bus of the root port */ + UINT8 NumBars; + QEMU_FIXED_BARS_BAR *Bars; /* pointer into mBlobData */ +} QFBD_DEVICE; + +/* + * Per-(VendorId, DeviceId) class. FixedBarsCheckDevice() is called once per + * PCI function and once per scan pass. Different VID:DID classes must + * advance their counters independently so that one class cannot disturb + * the position of another across scan passes. + * + * Assumptions: + * - QEMU emits blob entries in the same order PciBusDxe discovers devices. + * - For identical VID:DID devices, discovery order is stable across passes. + * - The counter is maintained per VID:DID class, not globally. + */ +typedef struct { + UINT16 VendorId; + UINT16 DeviceId; + UINTN Count; /* number of devices with this VID:DID in the blob */ + UINTN CurrentIdx; /* next entry to serve; wraps at Count */ +} QFBD_DEVICE_CLASS; + +STATIC QFBD_DEVICE *mDevices; +STATIC UINTN mNumDevices; +STATIC QFBD_DEVICE_CLASS *mClasses; /* heap-allocated; mNumDevices entries max */ +STATIC UINTN mNumClasses; + +STATIC VOID +ReserveFixedBarRanges ( + VOID + ) +{ + UINTN DevIdx; + UINTN BarIdx; + UINT64 Min64; + UINT64 Max64; + UINT64 Min32; + UINT64 Max32; + UINT64 Gran; + UINT64 Base; + UINT64 Size; + EFI_STATUS Status; + + Min64 = MAX_UINT64; + Max64 = 0; + Min32 = MAX_UINT64; + Max32 = 0; + Gran = SIZE_1MB; + + for (DevIdx = 0; DevIdx < mNumDevices; DevIdx++) { + QFBD_DEVICE *Dev = &mDevices[DevIdx]; + + if (!(Dev->DevFlags & QEMU_FIXED_BARS_DEV_F_FIXED)) { + continue; + } + for (BarIdx = 0; BarIdx < Dev->NumBars; BarIdx++) { + QEMU_FIXED_BARS_BAR *Bar = &Dev->Bars[BarIdx]; + + if (Bar->Flags & QEMU_FIXED_BAR_F_MEM64) { + if (Bar->Address < Min64) { + Min64 = Bar->Address; + } + if (Bar->Address + Bar->Size > Max64) { + Max64 = Bar->Address + Bar->Size; + } + } else { + if (Bar->Address < Min32) { + Min32 = Bar->Address; + } + if (Bar->Address + Bar->Size > Max32) { + Max32 = Bar->Address + Bar->Size; + } + } + } + } + + if (Min64 < Max64) { + Base = Min64 & ~(Gran - 1); + Size = ALIGN_VALUE (Max64 - Base, Gran); + Status = gDS->AllocateMemorySpace ( + EfiGcdAllocateAddress, + EfiGcdMemoryTypeMemoryMappedIo, + 0, Size, &Base, gImageHandle, NULL + ); + DEBUG ((EFI_ERROR (Status) ? DEBUG_ERROR : DEBUG_INFO, + "QFBD: reserve 64-bit 0x%016Lx+0x%016Lx: %r\n", + Base, Size, Status)); + } + + if (Min32 < Max32) { + Base = Min32 & ~(Gran - 1); + Size = ALIGN_VALUE (Max32 - Base, Gran); + Status = gDS->AllocateMemorySpace ( + EfiGcdAllocateAddress, + EfiGcdMemoryTypeMemoryMappedIo, + 0, Size, &Base, gImageHandle, NULL + ); + DEBUG ((EFI_ERROR (Status) ? DEBUG_ERROR : DEBUG_INFO, + "QFBD: reserve 32-bit 0x%016Lx+0x%016Lx: %r\n", + Base, Size, Status)); + } +} + +/* Walk the blob once, build the mDevices[] index and the mClasses[] table. */ +STATIC VOID +InitDevices ( + IN UINTN BlobSize + ) +{ + UINT8 *Ptr = mBlobData + sizeof (QEMU_FIXED_BARS_HDR); + UINT8 *End = mBlobData + BlobSize; + UINTN DevIdx, ClassIdx; + + for (DevIdx = 0; DevIdx < mHdr.NumDevices; DevIdx++) { + QEMU_FIXED_BARS_DEVICE *Dev; + UINT8 *Next; + + if (Ptr + sizeof (QEMU_FIXED_BARS_DEVICE) > End) { + DEBUG ((DEBUG_ERROR, "QFBD: blob truncated at device %u\n", (UINT32)DevIdx)); + break; + } + + Dev = (QEMU_FIXED_BARS_DEVICE *)Ptr; + Next = Ptr + + sizeof (QEMU_FIXED_BARS_DEVICE) + + Dev->NumBars * sizeof (QEMU_FIXED_BARS_BAR); + + if (Next > End) { + DEBUG ((DEBUG_ERROR, "QFBD: blob truncated at device %u\n", (UINT32)DevIdx)); + break; + } + + mDevices[mNumDevices].VendorId = Dev->VendorId; + mDevices[mNumDevices].DeviceId = Dev->DeviceId; + mDevices[mNumDevices].DevFlags = Dev->DevFlags; + mDevices[mNumDevices].RpBus = Dev->RpBus; + mDevices[mNumDevices].NumBars = Dev->NumBars; + mDevices[mNumDevices].Bars = (QEMU_FIXED_BARS_BAR *)( + Ptr + sizeof (QEMU_FIXED_BARS_DEVICE) + ); + mNumDevices++; + + /* Find or create the class entry for this VID:DID. */ + for (ClassIdx = 0; ClassIdx < mNumClasses; ClassIdx++) { + if (mClasses[ClassIdx].VendorId == Dev->VendorId && + mClasses[ClassIdx].DeviceId == Dev->DeviceId) + { + mClasses[ClassIdx].Count++; + break; + } + } + if (ClassIdx == mNumClasses) { + mClasses[mNumClasses].VendorId = Dev->VendorId; + mClasses[mNumClasses].DeviceId = Dev->DeviceId; + mClasses[mNumClasses].Count = 1; + mClasses[mNumClasses].CurrentIdx = 0; + mNumClasses++; + } + + DEBUG ((DEBUG_INFO, + "QFBD: device %04x:%04x num_bars=%u\n", + Dev->VendorId, Dev->DeviceId, Dev->NumBars)); + + Ptr = Next; + } + + for (ClassIdx = 0; ClassIdx < mNumClasses; ClassIdx++) { + DEBUG ((DEBUG_INFO, + "QFBD: class %04x:%04x count=%u\n", + mClasses[ClassIdx].VendorId, mClasses[ClassIdx].DeviceId, + (UINT32)mClasses[ClassIdx].Count)); + } +} + +EFI_STATUS +FixedBarsCheckDevice ( + IN UINTN VendorId, + IN UINTN DeviceId, + OUT VOID **Descriptors, + OUT UINTN *DescriptorsSize + ) +{ + QFBD_DEVICE_CLASS *Class; + QFBD_DEVICE *Dev; + UINTN BarIdx, DevIdx, MatchCount, ClassIdx; + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Desc; + + *Descriptors = NULL; + *DescriptorsSize = 0; + + if (mNumClasses == 0) { + return EFI_SUCCESS; + } + + /* Look up the per-VID:DID class. */ + Class = NULL; + for (ClassIdx = 0; ClassIdx < mNumClasses; ClassIdx++) { + if (mClasses[ClassIdx].VendorId == (UINT16)VendorId && + mClasses[ClassIdx].DeviceId == (UINT16)DeviceId) + { + Class = &mClasses[ClassIdx]; + break; + } + } + if (Class == NULL) { + return EFI_SUCCESS; /* not a fixed-bar device */ + } + + /* Find the CurrentIdx-th device in mDevices[] matching this VID:DID. */ + Dev = NULL; + MatchCount = 0; + for (DevIdx = 0; DevIdx < mNumDevices; DevIdx++) { + if (mDevices[DevIdx].VendorId == (UINT16)VendorId && + mDevices[DevIdx].DeviceId == (UINT16)DeviceId) + { + if (MatchCount == Class->CurrentIdx) { + Dev = &mDevices[DevIdx]; + break; + } + MatchCount++; + } + } + if (Dev == NULL) { + return EFI_SUCCESS; + } + + /* Always advance the counter so ordering stays in sync with the blob. */ + Class->CurrentIdx++; + if (Class->CurrentIdx >= Class->Count) { + Class->CurrentIdx = 0; + } + + if (!(Dev->DevFlags & QEMU_FIXED_BARS_DEV_F_FIXED)) { + return EFI_SUCCESS; + } + + Desc = AllocateZeroPool (Dev->NumBars * sizeof (*Desc)); + if (Desc == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + *Descriptors = Desc; + *DescriptorsSize = Dev->NumBars * sizeof (*Desc); + + for (BarIdx = 0; BarIdx < Dev->NumBars; BarIdx++) { + QEMU_FIXED_BARS_BAR *Bar = &Dev->Bars[BarIdx]; + + Desc->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR; + Desc->Len = (UINT16)(sizeof (*Desc) - 3); + Desc->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM; + Desc->GenFlag = ACPI_ADDR_FLAG_FIXED; + Desc->SpecificFlag = 0; + Desc->AddrSpaceGranularity = (Bar->Flags & QEMU_FIXED_BAR_F_MEM64) ? 64 : 32; + Desc->AddrRangeMin = Bar->Address; + Desc->AddrRangeMax = Bar->Size - 1; + Desc->AddrTranslationOffset = BarIdx; + Desc->AddrLen = Bar->Size; + + DEBUG ((DEBUG_INFO, + "QFBD: %04x:%04x BAR%u -> 0x%016Lx size 0x%016Lx\n", + Dev->VendorId, Dev->DeviceId, + (UINT32)Bar->Bar, Bar->Address, Bar->Size)); + + Desc++; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +FixedBarsInit ( + OUT BOOLEAN *HasFixedBarsDevices + ) +{ + FIRMWARE_CONFIG_ITEM FwCfgItem; + UINTN FwCfgSize; + EFI_STATUS Status; + + *HasFixedBarsDevices = FALSE; + + Status = QemuFwCfgFindFile ("etc/fixed-bars", &FwCfgItem, &FwCfgSize); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "QFBD: etc/fixed-bars absent, nothing to do\n")); + return EFI_SUCCESS; + } + + if (FwCfgSize < sizeof (mHdr)) { + DEBUG ((DEBUG_ERROR, "QFBD: blob too small (%Lu bytes)\n", + (UINT64)FwCfgSize)); + return EFI_UNSUPPORTED; + } + + QemuFwCfgSelectItem (FwCfgItem); + QemuFwCfgReadBytes (sizeof (mHdr), &mHdr); + + if (mHdr.Version != QEMU_FIXED_BARS_VERSION) { + DEBUG ((DEBUG_ERROR, + "QFBD: unsupported blob version %u (expected %u)\n", + mHdr.Version, QEMU_FIXED_BARS_VERSION)); + return EFI_UNSUPPORTED; + } + + if (mHdr.NumDevices == 0) { + DEBUG ((DEBUG_INFO, "QFBD: zero devices, nothing to do\n")); + return EFI_SUCCESS; + } + + /* Read the full blob into a persistent buffer; device entries point into it. */ + mBlobData = AllocatePool (FwCfgSize); + if (mBlobData == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + QemuFwCfgSelectItem (FwCfgItem); + QemuFwCfgReadBytes (FwCfgSize, mBlobData); + CopyMem (&mHdr, mBlobData, sizeof (mHdr)); + + mDevices = AllocateZeroPool (mHdr.NumDevices * sizeof (QFBD_DEVICE)); + if (mDevices == NULL) { + FreePool (mBlobData); + return EFI_OUT_OF_RESOURCES; + } + + /* Worst case: every device has a unique VID:DID — allocate mNumDevices slots. */ + mClasses = AllocateZeroPool (mHdr.NumDevices * sizeof (QFBD_DEVICE_CLASS)); + if (mClasses == NULL) { + FreePool (mDevices); + FreePool (mBlobData); + return EFI_OUT_OF_RESOURCES; + } + + DEBUG ((DEBUG_INFO, "QFBD: %u device(s)\n", mHdr.NumDevices)); + + mNumDevices = 0; + mNumClasses = 0; + InitDevices (FwCfgSize); + ReserveFixedBarRanges (); + + *HasFixedBarsDevices = TRUE; + + return EFI_SUCCESS; +} diff --git a/OvmfPkg/IncompatiblePciDeviceSupportDxe/FixedBars.h b/OvmfPkg/IncompatiblePciDeviceSupportDxe/FixedBars.h new file mode 100644 index 0000000000..837399986e --- /dev/null +++ b/OvmfPkg/IncompatiblePciDeviceSupportDxe/FixedBars.h @@ -0,0 +1,63 @@ +/** @file + Public interface for FixedBars.c -- fixed PCI BAR placement using + metadata provided by QEMU through the "etc/fixed-bars" fw_cfg blob. + + Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.<BR> + + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef FIXED_BARS_H_ +#define FIXED_BARS_H_ + +#include <Uefi.h> + +/** + Read and parse the "etc/fixed-bars" fw_cfg blob (if present), and reserve + the fixed BAR address ranges it describes in the GCD memory space map. + + Must be called once, from the owning driver's entry point, before that + driver installs EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL. + + @param[out] HasFixedBarsDevices TRUE if the blob was present and + described at least one fixed-BAR device; + FALSE otherwise (nothing else in this + file has any effect in that case). + + @retval EFI_SUCCESS Blob absent, empty, or successfully parsed. + @retval EFI_UNSUPPORTED Blob present but malformed/wrong version. + @retval EFI_OUT_OF_RESOURCES Memory allocation failure. +**/ +EFI_STATUS +FixedBarsInit ( + OUT BOOLEAN *HasFixedBarsDevices + ); + +/** + Return the fixed-BAR ACPI address-space descriptors for one PCI function, + if it has a matching entry in the "etc/fixed-bars" blob. Returns + *Descriptors == NULL, with *DescriptorsSize == 0, when the device is not + a fixed-BAR device. + + @param[in] VendorId Device's PCI Vendor ID. + @param[in] DeviceId Device's PCI Device ID. + @param[out] Descriptors Heap-allocated array of + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR, one per + fixed BAR; caller takes ownership. NULL if no + match. + @param[out] DescriptorsSize Size in bytes of *Descriptors. + + @retval EFI_SUCCESS Always, on non-allocation-failure paths + (matches EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_ + PROTOCOL.CheckDevice()'s own contract). + @retval EFI_OUT_OF_RESOURCES Memory allocation failure. +**/ +EFI_STATUS +FixedBarsCheckDevice ( + IN UINTN VendorId, + IN UINTN DeviceId, + OUT VOID **Descriptors, + OUT UINTN *DescriptorsSize + ); + +#endif diff --git a/OvmfPkg/IncompatiblePciDeviceSupportDxe/IncompatiblePciDeviceSupport.c b/OvmfPkg/IncompatiblePciDeviceSupportDxe/IncompatiblePciDeviceSupport.c index ebf73d97db..5e40936f81 100644 --- a/OvmfPkg/IncompatiblePciDeviceSupportDxe/IncompatiblePciDeviceSupport.c +++ b/OvmfPkg/IncompatiblePciDeviceSupportDxe/IncompatiblePciDeviceSupport.c @@ -22,6 +22,8 @@ #include <Protocol/IncompatiblePciDeviceSupport.h> +#include "FixedBars.h" + // // The protocol interface this driver produces. // @@ -165,6 +167,57 @@ STATIC CONST EFI_ACPI_END_TAG_DESCRIPTOR mEndDesc = { @retval EFI_SUCCESS The function always returns EFI_SUCCESS. **/ +/** + This function copies Buffer into Configuration, then appends the + confidential-VM option ROM descriptor if applicable, and finally + appends the terminating End Tag. + + @param[in] Buffer Descriptor bytes. + @param[in] BufferSize Size in bytes of Buffer. + @param[out] Configuration As in CheckDevice(). + + @retval EFI_SUCCESS Configuration built and returned. + @retval EFI_OUT_OF_RESOURCES Memory allocation failure. +**/ +STATIC +EFI_STATUS +BuildConfiguration ( + IN CONST VOID *Buffer, + IN UINTN BufferSize, + OUT VOID **Configuration + ) +{ + UINTN Length; + UINT8 *Ptr; + + Length = BufferSize + sizeof mEndDesc; + + // + // In Td guest OptionRom is not allowed. + // + if (CcProbe ()) { + Length += sizeof mOptionRomConfiguration; + } + + *Configuration = AllocateZeroPool (Length); + if (*Configuration == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Ptr = (UINT8 *)(UINTN)*Configuration; + CopyMem (Ptr, Buffer, BufferSize); + Length = BufferSize; + + if (CcProbe ()) { + CopyMem (Ptr + Length, &mOptionRomConfiguration, sizeof mOptionRomConfiguration); + Length += sizeof mOptionRomConfiguration; + } + + CopyMem (Ptr + Length, &mEndDesc, sizeof mEndDesc); + + return EFI_SUCCESS; +} + STATIC EFI_STATUS EFIAPI @@ -178,8 +231,25 @@ CheckDevice ( OUT VOID **Configuration ) { - UINTN Length; - UINT8 *Ptr; + EFI_STATUS Status; + VOID *FixedBarsDescs; + UINTN FixedBarsDescsSize; + + // + // Dispatch hook: if this device has an entry in the "etc/fixed-bars" + // fw_cfg blob, use that instead of the hardcoded 64-bit-MMIO-preference + // descriptor below. + // + Status = FixedBarsCheckDevice (VendorId, DeviceId, &FixedBarsDescs, &FixedBarsDescsSize); + if (EFI_ERROR (Status)) { + return Status; + } + + if (FixedBarsDescs != NULL) { + Status = BuildConfiguration (FixedBarsDescs, FixedBarsDescsSize, Configuration); + FreePool (FixedBarsDescs); + return Status; + } // // Unlike the general description of this protocol member suggests, there is @@ -200,18 +270,8 @@ CheckDevice ( // the edk2 PCI Bus UEFI_DRIVER actually handles error codes; see the // UpdatePciInfo() function. // - Length = sizeof mMmio64Configuration + sizeof mEndDesc; - - // - // In Td guest OptionRom is not allowed. - // - if (CcProbe ()) { - Length += sizeof mOptionRomConfiguration; - } - - *Configuration = AllocateZeroPool (Length); - - if (*Configuration == NULL) { + Status = BuildConfiguration (&mMmio64Configuration, sizeof mMmio64Configuration, Configuration); + if (EFI_ERROR (Status)) { DEBUG (( DEBUG_WARN, "%a: 64-bit MMIO BARs may be degraded for PCI 0x%04x:0x%04x (rev %d)\n", @@ -220,21 +280,9 @@ CheckDevice ( (UINT32)DeviceId, (UINT8)RevisionId )); - return EFI_OUT_OF_RESOURCES; } - Ptr = (UINT8 *)(UINTN)*Configuration; - CopyMem (Ptr, &mMmio64Configuration, sizeof mMmio64Configuration); - Length = sizeof mMmio64Configuration; - - if (CcProbe ()) { - CopyMem (Ptr + Length, &mOptionRomConfiguration, sizeof mOptionRomConfiguration); - Length += sizeof mOptionRomConfiguration; - } - - CopyMem (Ptr + Length, &mEndDesc, sizeof mEndDesc); - - return EFI_SUCCESS; + return Status; } /** @@ -257,12 +305,18 @@ DriverInitialize ( ) { EFI_STATUS Status; + BOOLEAN HasFixedBarsDevices; + + Status = FixedBarsInit (&HasFixedBarsDevices); + if (EFI_ERROR (Status)) { + return Status; + } // - // If there is no 64-bit PCI MMIO aperture, then 64-bit MMIO BARs have to be - // allocated under 4 GB unconditionally. + // If there is no 64-bit PCI MMIO aperture and no fixed-bars devices to + // place, do not install the protocol. // - if (PcdGet64 (PcdPciMmio64Size) == 0) { + if ((PcdGet64 (PcdPciMmio64Size) == 0) && !HasFixedBarsDevices) { return EFI_UNSUPPORTED; } diff --git a/OvmfPkg/IncompatiblePciDeviceSupportDxe/IncompatiblePciDeviceSupport.inf b/OvmfPkg/IncompatiblePciDeviceSupportDxe/IncompatiblePciDeviceSupport.inf index b92662d0bb..b51f51c25e 100644 --- a/OvmfPkg/IncompatiblePciDeviceSupportDxe/IncompatiblePciDeviceSupport.inf +++ b/OvmfPkg/IncompatiblePciDeviceSupportDxe/IncompatiblePciDeviceSupport.inf @@ -18,21 +18,27 @@ [Sources] IncompatiblePciDeviceSupport.c + FixedBars.c + FixedBars.h [Packages] MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec OvmfPkg/OvmfPkg.dec [LibraryClasses] + BaseMemoryLib CcProbeLib DebugLib + DxeServicesTableLib MemoryAllocationLib PcdLib + QemuFwCfgLib UefiBootServicesTableLib UefiDriverEntryPoint [Protocols] - gEfiIncompatiblePciDeviceSupportProtocolGuid ## SOMETIMES_PRODUCES + gEfiIncompatiblePciDeviceSupportProtocolGuid ## SOMETIMES_PRODUCES [Pcd] gUefiOvmfPkgTokenSpaceGuid.PcdPciMmio64Size ## CONSUMES -- 2.34.1
