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? -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