On 03/01/16 08:16, Jordan Justen wrote: > On 2016-02-26 16:23:26, Laszlo Ersek wrote: >> In this patch we import the scan for extra root buses from the >> InitializePciHostBridge() function, in file >> "OvmfPkg/PciHostBridgeDxe/PciHostBridge.c". >> >> For the time being, the InitRootBridge() and UninitRootBridge() functions >> are just placeholders. >> >> The PciHostBridgeGetRootBridges() API expects us to return the >> PCI_ROOT_BRIDGE structures in a contiguous array, instead of a linked >> list. Therefore the following bits have to be converted manually: >> >> (1) The array is allocated in advance, in a single step. >> >> (2) The calculation of the array size depends on an explicit >> multiplication, which we must check against overflow. Since more than >> 255 extra root bridges make no sense anyway, we use (1 + 255) as the >> limit on the main plus all extra root bridges. This also ensures that >> the UINTN multiplication doesn't overflow. >> >> (3) The PciHostBridgeDxe code decrements "ExtraRootBridgesLeft" to >> terminate the scanning early. Here we need track the increasing count >> of used array elements as well, so we employ "ExtraRootBridges" as a >> constant limit, and increment the new local variable "Initialized". >> >> (4) The prototypes of InitRootBridge() and UninitRootBridge() reflect that >> the PCI_ROOT_BRIDGE structure is allocated by the caller; only >> in-place initialization is necessary. >> >> Additionally, MAX_PCI_DEVICE_NUMBER is open coded as 31 (decimal) form >> "OvmfPkg/PciHostBridgeDxe/PciHostBridge.h". >> > > Do we need a different macro than PCI_MAX_DEVICE?
No, that's the one we should use. I wasn't aware of its existence in "MdePkg/Include/IndustryStandard/Pci22.h". Thanks Laszlo > > -Jordan > >> Cc: Jordan Justen <jordan.l.jus...@intel.com> >> Cc: Ruiyu Ni <ruiyu...@intel.com> >> Cc: Marcel Apfelbaum <mar...@redhat.com> >> Contributed-under: TianoCore Contribution Agreement 1.0 >> Signed-off-by: Laszlo Ersek <ler...@redhat.com> >> --- >> OvmfPkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf | 9 +- >> OvmfPkg/Library/PciHostBridgeLib/PciHostBridgeLib.c | 165 >> +++++++++++++++++++- >> 2 files changed, 172 insertions(+), 2 deletions(-) >> >> diff --git a/OvmfPkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf >> b/OvmfPkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf >> index 1f3930195a1d..b83693191261 100644 >> --- a/OvmfPkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf >> +++ b/OvmfPkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf >> @@ -34,5 +34,12 @@ [Sources] >> PciHostBridgeLib.c >> >> [Packages] >> - MdePkg/MdePkg.dec >> MdeModulePkg/MdeModulePkg.dec >> + MdePkg/MdePkg.dec >> + OvmfPkg/OvmfPkg.dec >> + >> +[LibraryClasses] >> + DebugLib >> + MemoryAllocationLib >> + PciLib >> + QemuFwCfgLib >> diff --git a/OvmfPkg/Library/PciHostBridgeLib/PciHostBridgeLib.c >> b/OvmfPkg/Library/PciHostBridgeLib/PciHostBridgeLib.c >> index 3752993f65aa..b1f7e50ce781 100644 >> --- a/OvmfPkg/Library/PciHostBridgeLib/PciHostBridgeLib.c >> +++ b/OvmfPkg/Library/PciHostBridgeLib/PciHostBridgeLib.c >> @@ -14,14 +14,77 @@ >> >> **/ >> #include <PiDxe.h> >> -#include <Library/PciHostBridgeLib.h> >> + >> +#include <IndustryStandard/Pci.h> >> + >> #include <Library/DebugLib.h> >> +#include <Library/MemoryAllocationLib.h> >> +#include <Library/PciHostBridgeLib.h> >> +#include <Library/PciLib.h> >> +#include <Library/QemuFwCfgLib.h> >> + >> +#define MAX_PCI_DEVICE_NUMBER 31 >> + >> >> GLOBAL_REMOVE_IF_UNREFERENCED >> CHAR16 *mPciHostBridgeLibAcpiAddressSpaceTypeStr[] = { >> L"Mem", L"I/O", L"Bus" >> }; >> >> + >> +/** >> + Initialize a PCI_ROOT_BRIDGE structure. >> + >> + param[in] RootBusNumber The bus number to store in RootBus. >> + >> + param[in] MaxSubBusNumber The inclusive maximum bus number that can be >> + assigned to any subordinate bus found behind >> any >> + PCI bridge hanging off this root bus. >> + >> + The caller is repsonsible for ensuring that >> + RootBusNumber <= MaxSubBusNumber. If >> + RootBusNumber equals MaxSubBusNumber, then >> the >> + root bus has no room for subordinate buses. >> + >> + param[out] RootBus The PCI_ROOT_BRIDGE structure (allocated by >> the >> + caller) that should be filled in by this >> + function. >> + >> + @retval EFI_SUCCESS Initialization successful. A device path >> + consisting of an ACPI device path node, with >> + UID = RootBusNumber, has been allocated and >> + linked into RootBus. >> + >> + @retval EFI_OUT_OF_RESOURCES Memory allocation failed. >> +**/ >> +STATIC >> +EFI_STATUS >> +InitRootBridge ( >> + IN UINT8 RootBusNumber, >> + IN UINT8 MaxSubBusNumber, >> + OUT PCI_ROOT_BRIDGE *RootBus >> + ) >> +{ >> + return EFI_OUT_OF_RESOURCES; >> +} >> + >> + >> +/** >> + Uninitialize a PCI_ROOT_BRIDGE structure set up with InitRootBridge(). >> + >> + param[in] RootBus The PCI_ROOT_BRIDGE structure, allocated by the caller >> and >> + initialized with InitRootBridge(), that should be >> + uninitialized. This function doesn't free RootBus. >> +**/ >> +STATIC >> +VOID >> +UninitRootBridge ( >> + IN PCI_ROOT_BRIDGE *RootBus >> + ) >> +{ >> +} >> + >> + >> /** >> Return all the root bridge instances in an array. >> >> @@ -37,10 +100,109 @@ PciHostBridgeGetRootBridges ( >> UINTN *Count >> ) >> { >> + EFI_STATUS Status; >> + FIRMWARE_CONFIG_ITEM FwCfgItem; >> + UINTN FwCfgSize; >> + UINT64 ExtraRootBridges; >> + PCI_ROOT_BRIDGE *Bridges; >> + UINTN Initialized; >> + UINTN LastRootBridgeNumber; >> + UINTN RootBridgeNumber; >> + >> *Count = 0; >> + >> + // >> + // QEMU provides the number of extra root buses, shortening the exhaustive >> + // search below. If there is no hint, the feature is missing. >> + // >> + Status = QemuFwCfgFindFile ("etc/extra-pci-roots", &FwCfgItem, >> &FwCfgSize); >> + if (EFI_ERROR (Status) || FwCfgSize != sizeof ExtraRootBridges) { >> + ExtraRootBridges = 0; >> + } else { >> + QemuFwCfgSelectItem (FwCfgItem); >> + QemuFwCfgReadBytes (FwCfgSize, &ExtraRootBridges); >> + >> + if (ExtraRootBridges > 255) { >> + DEBUG ((EFI_D_ERROR, "%a: invalid count of extra root buses (%Lu) " >> + "reported by QEMU\n", __FUNCTION__, ExtraRootBridges)); >> + return NULL; >> + } >> + DEBUG ((EFI_D_INFO, "%a: %Lu extra root buses reported by QEMU\n", >> + __FUNCTION__, ExtraRootBridges)); >> + } >> + >> + // >> + // Allocate the "main" root bridge, and any extra root bridges. >> + // >> + Bridges = AllocatePool ((1 + (UINTN)ExtraRootBridges) * sizeof *Bridges); >> + if (Bridges == NULL) { >> + DEBUG ((EFI_D_ERROR, "%a: %r\n", __FUNCTION__, EFI_OUT_OF_RESOURCES)); >> + return NULL; >> + } >> + Initialized = 0; >> + >> + // >> + // The "main" root bus is always there. >> + // >> + LastRootBridgeNumber = 0; >> + >> + // >> + // Scan all other root buses. If function 0 of any device on a bus >> returns a >> + // VendorId register value different from all-bits-one, then that bus is >> + // alive. >> + // >> + for (RootBridgeNumber = 1; >> + RootBridgeNumber < 256 && Initialized < ExtraRootBridges; >> + ++RootBridgeNumber) { >> + UINTN Device; >> + >> + for (Device = 0; Device <= MAX_PCI_DEVICE_NUMBER; ++Device) { >> + if (PciRead16 (PCI_LIB_ADDRESS (RootBridgeNumber, Device, 0, >> + PCI_VENDOR_ID_OFFSET)) != MAX_UINT16) { >> + break; >> + } >> + } >> + if (Device <= MAX_PCI_DEVICE_NUMBER) { >> + // >> + // Found the next root bus. We can now install the *previous* one, >> + // because now we know how big a bus number range *that* one has, for >> any >> + // subordinate buses that might exist behind PCI bridges hanging off >> it. >> + // >> + Status = InitRootBridge ((UINT8)LastRootBridgeNumber, >> + (UINT8)(RootBridgeNumber - 1), &Bridges[Initialized]); >> + if (EFI_ERROR (Status)) { >> + goto FreeBridges; >> + } >> + ++Initialized; >> + LastRootBridgeNumber = RootBridgeNumber; >> + } >> + } >> + >> + // >> + // Install the last root bus (which might be the only, ie. main, root >> bus, if >> + // we've found no extra root buses). >> + // >> + Status = InitRootBridge ((UINT8)LastRootBridgeNumber, 255, >> + &Bridges[Initialized]); >> + if (EFI_ERROR (Status)) { >> + goto FreeBridges; >> + } >> + ++Initialized; >> + >> + *Count = Initialized; >> + return Bridges; >> + >> +FreeBridges: >> + while (Initialized > 0) { >> + --Initialized; >> + UninitRootBridge (&Bridges[Initialized]); >> + } >> + >> + FreePool (Bridges); >> return NULL; >> } >> >> + >> /** >> Free the root bridge instances array returned from >> PciHostBridgeGetRootBridges(). >> @@ -58,6 +220,7 @@ PciHostBridgeFreeRootBridges ( >> return; >> } >> >> + >> /** >> Inform the platform that the resource conflict happens. >> >> -- >> 1.8.3.1 >> >> _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel