OvmfPkg/PciHostBridgeLibScan: create from PciHostBridgeLib

Create an almost verbatim copy of the
"OvmfPkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf" library instance.

The new PciHostBridgeLibScan instance will ultimately duplicate a
negligible amount of code from the original, and will be used by the Bhyve
and OvmfXen platforms.

List the new driver in "Maintainers.txt", in the "OvmfPkg: bhyve-related
modules" and "OvmfPkg: Xen-related modules" sections.

This patch should be reviewed with "git show --find-copies-harder".

Cc: Anthony Perard <anthony.perard@citrix.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Julien Grall <julien@xen.org>
Cc: Peter Grehan <grehan@freebsd.org>
Cc: Philippe Mathieu-Daudé <philmd@redhat.com>
Cc: Rebecca Cran <rebecca@bsdio.com>
Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=2122
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Message-Id: <20210526201446.12554-30-lersek@redhat.com>
Reviewed-by: Ard Biesheuvel <ardb@kernel.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
This commit is contained in:
Laszlo Ersek 2021-05-26 22:14:32 +02:00 committed by mergify[bot]
parent 32fef03563
commit e120c962f5
5 changed files with 675 additions and 0 deletions

View File

@ -426,6 +426,7 @@ F: OvmfPkg/Include/Library/BhyveFwCtlLib.h
F: OvmfPkg/Library/AcpiTimerLib/BaseAcpiTimerLibBhyve.c
F: OvmfPkg/Library/AcpiTimerLib/BaseAcpiTimerLibBhyve.inf
F: OvmfPkg/Library/BhyveFwCtlLib/
F: OvmfPkg/Library/PciHostBridgeLibScan/
F: OvmfPkg/Library/PlatformBootManagerLibBhyve/
F: OvmfPkg/Library/ResetSystemLib/BaseResetShutdownBhyve.c
F: OvmfPkg/Library/ResetSystemLib/BaseResetSystemLibBhyve.inf
@ -484,6 +485,7 @@ F: OvmfPkg/Include/Library/XenPlatformLib.h
F: OvmfPkg/Include/Protocol/XenBus.h
F: OvmfPkg/Include/Protocol/XenIo.h
F: OvmfPkg/Library/PciHostBridgeLib/XenSupport.c
F: OvmfPkg/Library/PciHostBridgeLibScan/
F: OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c
F: OvmfPkg/Library/XenConsoleSerialPortLib/
F: OvmfPkg/Library/XenHypercallLib/

View File

@ -0,0 +1,14 @@
/** @file
Header file of OVMF instance of PciHostBridgeLib.
Copyright (C) 2021, Red Hat, Inc.
Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
PCI_ROOT_BRIDGE *
ScanForRootBridges (
UINTN *NumberOfRootBridges
);

View File

@ -0,0 +1,133 @@
/** @file
OVMF's instance of the PCI Host Bridge Library.
Copyright (C) 2016-2021, Red Hat, Inc.
Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include <IndustryStandard/Pci.h> // PCI_MAX_BUS
#include <IndustryStandard/Q35MchIch9.h> // INTEL_Q35_MCH_DEVIC...
#include <Library/BaseMemoryLib.h> // ZeroMem()
#include <Library/PcdLib.h> // PcdGet64()
#include <Library/PciHostBridgeLib.h> // PCI_ROOT_BRIDGE_APE...
#include <Library/PciHostBridgeUtilityLib.h> // PciHostBridgeUtilit...
#include <Protocol/PciHostBridgeResourceAllocation.h> // EFI_PCI_HOST_BRIDGE...
#include <Protocol/PciRootBridgeIo.h> // EFI_PCI_ATTRIBUTE_I...
#include "PciHostBridge.h"
STATIC PCI_ROOT_BRIDGE_APERTURE mNonExistAperture = { MAX_UINT64, 0 };
/**
Return all the root bridge instances in an array.
@param Count Return the count of root bridge instances.
@return All the root bridge instances in an array.
The array should be passed into PciHostBridgeFreeRootBridges()
when it's not used.
**/
PCI_ROOT_BRIDGE *
EFIAPI
PciHostBridgeGetRootBridges (
UINTN *Count
)
{
UINT64 Attributes;
UINT64 AllocationAttributes;
PCI_ROOT_BRIDGE_APERTURE Io;
PCI_ROOT_BRIDGE_APERTURE Mem;
PCI_ROOT_BRIDGE_APERTURE MemAbove4G;
if (PcdGetBool (PcdPciDisableBusEnumeration)) {
return ScanForRootBridges (Count);
}
ZeroMem (&Io, sizeof (Io));
ZeroMem (&Mem, sizeof (Mem));
ZeroMem (&MemAbove4G, sizeof (MemAbove4G));
Attributes = EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO |
EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO |
EFI_PCI_ATTRIBUTE_ISA_IO_16 |
EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO |
EFI_PCI_ATTRIBUTE_VGA_MEMORY |
EFI_PCI_ATTRIBUTE_VGA_IO_16 |
EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16;
AllocationAttributes = EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM;
if (PcdGet64 (PcdPciMmio64Size) > 0) {
AllocationAttributes |= EFI_PCI_HOST_BRIDGE_MEM64_DECODE;
MemAbove4G.Base = PcdGet64 (PcdPciMmio64Base);
MemAbove4G.Limit = PcdGet64 (PcdPciMmio64Base) +
PcdGet64 (PcdPciMmio64Size) - 1;
} else {
CopyMem (&MemAbove4G, &mNonExistAperture, sizeof (mNonExistAperture));
}
Io.Base = PcdGet64 (PcdPciIoBase);
Io.Limit = PcdGet64 (PcdPciIoBase) + (PcdGet64 (PcdPciIoSize) - 1);
Mem.Base = PcdGet64 (PcdPciMmio32Base);
Mem.Limit = PcdGet64 (PcdPciMmio32Base) + (PcdGet64 (PcdPciMmio32Size) - 1);
return PciHostBridgeUtilityGetRootBridges (
Count,
Attributes,
AllocationAttributes,
FALSE,
PcdGet16 (PcdOvmfHostBridgePciDevId) != INTEL_Q35_MCH_DEVICE_ID,
0,
PCI_MAX_BUS,
&Io,
&Mem,
&MemAbove4G,
&mNonExistAperture,
&mNonExistAperture
);
}
/**
Free the root bridge instances array returned from
PciHostBridgeGetRootBridges().
@param The root bridge instances array.
@param The count of the array.
**/
VOID
EFIAPI
PciHostBridgeFreeRootBridges (
PCI_ROOT_BRIDGE *Bridges,
UINTN Count
)
{
PciHostBridgeUtilityFreeRootBridges (Bridges, Count);
}
/**
Inform the platform that the resource conflict happens.
@param HostBridgeHandle Handle of the Host Bridge.
@param Configuration Pointer to PCI I/O and PCI memory resource
descriptors. The Configuration contains the resources
for all the root bridges. The resource for each root
bridge is terminated with END descriptor and an
additional END is appended indicating the end of the
entire resources. The resource descriptor field
values follow the description in
EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
.SubmitResources().
**/
VOID
EFIAPI
PciHostBridgeResourceConflict (
EFI_HANDLE HostBridgeHandle,
VOID *Configuration
)
{
PciHostBridgeUtilityResourceConflict (Configuration);
}

View File

@ -0,0 +1,54 @@
## @file
# OVMF's instance of the PCI Host Bridge Library.
#
# Copyright (C) 2016-2021, Red Hat, Inc.
# Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
#
##
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = PciHostBridgeLibScan
FILE_GUID = c93f2411-9bf5-4894-b552-67fae0c3d291
MODULE_TYPE = DXE_DRIVER
VERSION_STRING = 1.0
LIBRARY_CLASS = PciHostBridgeLib
#
# The following information is for reference only and not required by the build
# tools.
#
# VALID_ARCHITECTURES = IA32 X64 EBC
#
[Sources]
PciHostBridge.h
PciHostBridgeLib.c
XenSupport.c
[Packages]
MdeModulePkg/MdeModulePkg.dec
MdePkg/MdePkg.dec
OvmfPkg/OvmfPkg.dec
[LibraryClasses]
BaseLib
BaseMemoryLib
DebugLib
MemoryAllocationLib
PcdLib
PciHostBridgeUtilityLib
PciLib
[Pcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdPciDisableBusEnumeration
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfHostBridgePciDevId
gUefiOvmfPkgTokenSpaceGuid.PcdPciIoBase
gUefiOvmfPkgTokenSpaceGuid.PcdPciIoSize
gUefiOvmfPkgTokenSpaceGuid.PcdPciMmio32Base
gUefiOvmfPkgTokenSpaceGuid.PcdPciMmio32Size
gUefiOvmfPkgTokenSpaceGuid.PcdPciMmio64Base
gUefiOvmfPkgTokenSpaceGuid.PcdPciMmio64Size

View File

@ -0,0 +1,472 @@
/** @file
Scan the entire PCI bus for root bridges to support OVMF above Xen.
Copyright (C) 2021, Red Hat, Inc.
Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include <IndustryStandard/Pci.h> // EFI_PCI_COMMAND_IO_SPACE
#include <IndustryStandard/Q35MchIch9.h> // INTEL_Q35_MCH_DEVICE_ID
#include <Library/BaseLib.h> // DisableInterrupts()
#include <Library/BaseMemoryLib.h> // ZeroMem()
#include <Library/DebugLib.h> // ASSERT()
#include <Library/MemoryAllocationLib.h> // ReallocatePool()
#include <Library/PcdLib.h> // PcdGet16()
#include <Library/PciHostBridgeLib.h> // PCI_ROOT_BRIDGE_APERTURE
#include <Library/PciHostBridgeUtilityLib.h> // PciHostBridgeUtilityInitRoot...
#include <Library/PciLib.h> // PciRead32()
#include <Protocol/PciRootBridgeIo.h> // EFI_PCI_ATTRIBUTE_ISA_IO
#include "PciHostBridge.h"
STATIC
VOID
PcatPciRootBridgeBarExisted (
IN UINTN Address,
OUT UINT32 *OriginalValue,
OUT UINT32 *Value
)
{
//
// Preserve the original value
//
*OriginalValue = PciRead32 (Address);
//
// Disable timer interrupt while the BAR is probed
//
DisableInterrupts ();
PciWrite32 (Address, 0xFFFFFFFF);
*Value = PciRead32 (Address);
PciWrite32 (Address, *OriginalValue);
//
// Enable interrupt
//
EnableInterrupts ();
}
#define PCI_COMMAND_DECODE ((UINT16)(EFI_PCI_COMMAND_IO_SPACE | \
EFI_PCI_COMMAND_MEMORY_SPACE))
STATIC
VOID
PcatPciRootBridgeDecodingDisable (
IN UINTN Address
)
{
UINT16 Value;
Value = PciRead16 (Address);
if (Value & PCI_COMMAND_DECODE) {
PciWrite16 (Address, Value & ~(UINT32)PCI_COMMAND_DECODE);
}
}
STATIC
VOID
PcatPciRootBridgeParseBars (
IN UINT16 Command,
IN UINTN Bus,
IN UINTN Device,
IN UINTN Function,
IN UINTN BarOffsetBase,
IN UINTN BarOffsetEnd,
IN PCI_ROOT_BRIDGE_APERTURE *Io,
IN PCI_ROOT_BRIDGE_APERTURE *Mem,
IN PCI_ROOT_BRIDGE_APERTURE *MemAbove4G
)
{
UINT32 OriginalValue;
UINT32 Value;
UINT32 OriginalUpperValue;
UINT32 UpperValue;
UINT64 Mask;
UINTN Offset;
UINT64 Base;
UINT64 Length;
UINT64 Limit;
PCI_ROOT_BRIDGE_APERTURE *MemAperture;
// Disable address decoding for every device before OVMF starts sizing it
PcatPciRootBridgeDecodingDisable (
PCI_LIB_ADDRESS (Bus, Device, Function, PCI_COMMAND_OFFSET)
);
for (Offset = BarOffsetBase; Offset < BarOffsetEnd; Offset += sizeof (UINT32)) {
PcatPciRootBridgeBarExisted (
PCI_LIB_ADDRESS (Bus, Device, Function, Offset),
&OriginalValue, &Value
);
if (Value == 0) {
continue;
}
if ((Value & BIT0) == BIT0) {
//
// IO Bar
//
if (Command & EFI_PCI_COMMAND_IO_SPACE) {
Mask = 0xfffffffc;
Base = OriginalValue & Mask;
Length = ((~(Value & Mask)) & Mask) + 0x04;
if (!(Value & 0xFFFF0000)) {
Length &= 0x0000FFFF;
}
Limit = Base + Length - 1;
if (Base < Limit) {
if (Io->Base > Base) {
Io->Base = Base;
}
if (Io->Limit < Limit) {
Io->Limit = Limit;
}
}
}
} else {
//
// Mem Bar
//
if (Command & EFI_PCI_COMMAND_MEMORY_SPACE) {
Mask = 0xfffffff0;
Base = OriginalValue & Mask;
Length = Value & Mask;
if ((Value & (BIT1 | BIT2)) == 0) {
//
// 32bit
//
Length = ((~Length) + 1) & 0xffffffff;
MemAperture = Mem;
} else {
//
// 64bit
//
Offset += 4;
PcatPciRootBridgeBarExisted (
PCI_LIB_ADDRESS (Bus, Device, Function, Offset),
&OriginalUpperValue,
&UpperValue
);
Base = Base | LShiftU64 ((UINT64) OriginalUpperValue, 32);
Length = Length | LShiftU64 ((UINT64) UpperValue, 32);
Length = (~Length) + 1;
if (Base < BASE_4GB) {
MemAperture = Mem;
} else {
MemAperture = MemAbove4G;
}
}
Limit = Base + Length - 1;
if (Base < Limit) {
if (MemAperture->Base > Base) {
MemAperture->Base = Base;
}
if (MemAperture->Limit < Limit) {
MemAperture->Limit = Limit;
}
}
}
}
}
}
STATIC PCI_ROOT_BRIDGE_APERTURE mNonExistAperture = { MAX_UINT64, 0 };
PCI_ROOT_BRIDGE *
ScanForRootBridges (
UINTN *NumberOfRootBridges
)
{
UINTN PrimaryBus;
UINTN SubBus;
UINT8 Device;
UINT8 Function;
UINTN NumberOfDevices;
UINTN Address;
PCI_TYPE01 Pci;
UINT64 Attributes;
UINT64 Base;
UINT64 Limit;
UINT64 Value;
PCI_ROOT_BRIDGE_APERTURE Io, Mem, MemAbove4G, *MemAperture;
PCI_ROOT_BRIDGE *RootBridges;
UINTN BarOffsetEnd;
*NumberOfRootBridges = 0;
RootBridges = NULL;
//
// After scanning all the PCI devices on the PCI root bridge's primary bus,
// update the Primary Bus Number for the next PCI root bridge to be this PCI
// root bridge's subordinate bus number + 1.
//
for (PrimaryBus = 0; PrimaryBus <= PCI_MAX_BUS; PrimaryBus = SubBus + 1) {
SubBus = PrimaryBus;
Attributes = 0;
ZeroMem (&Io, sizeof (Io));
ZeroMem (&Mem, sizeof (Mem));
ZeroMem (&MemAbove4G, sizeof (MemAbove4G));
Io.Base = Mem.Base = MemAbove4G.Base = MAX_UINT64;
//
// Scan all the PCI devices on the primary bus of the PCI root bridge
//
for (Device = 0, NumberOfDevices = 0; Device <= PCI_MAX_DEVICE; Device++) {
for (Function = 0; Function <= PCI_MAX_FUNC; Function++) {
//
// Compute the PCI configuration address of the PCI device to probe
//
Address = PCI_LIB_ADDRESS (PrimaryBus, Device, Function, 0);
//
// Read the Vendor ID from the PCI Configuration Header
//
if (PciRead16 (Address) == MAX_UINT16) {
if (Function == 0) {
//
// If the PCI Configuration Read fails, or a PCI device does not
// exist, then skip this entire PCI device
//
break;
} else {
//
// If PCI function != 0, VendorId == 0xFFFF, we continue to search
// PCI function.
//
continue;
}
}
//
// Read the entire PCI Configuration Header
//
PciReadBuffer (Address, sizeof (Pci), &Pci);
//
// Increment the number of PCI device found on the primary bus of the
// PCI root bridge
//
NumberOfDevices++;
//
// Look for devices with the VGA Palette Snoop enabled in the COMMAND
// register of the PCI Config Header
//
if ((Pci.Hdr.Command & EFI_PCI_COMMAND_VGA_PALETTE_SNOOP) != 0) {
Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;
Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16;
}
BarOffsetEnd = 0;
//
// PCI-PCI Bridge
//
if (IS_PCI_BRIDGE (&Pci)) {
//
// Get the Bus range that the PPB is decoding
//
if (Pci.Bridge.SubordinateBus > SubBus) {
//
// If the subordinate bus number of the PCI-PCI bridge is greater
// than the PCI root bridge's current subordinate bus number,
// then update the PCI root bridge's subordinate bus number
//
SubBus = Pci.Bridge.SubordinateBus;
}
//
// Get the I/O range that the PPB is decoding
//
Value = Pci.Bridge.IoBase & 0x0f;
Base = ((UINT32) Pci.Bridge.IoBase & 0xf0) << 8;
Limit = (((UINT32) Pci.Bridge.IoLimit & 0xf0) << 8) | 0x0fff;
if (Value == BIT0) {
Base |= ((UINT32) Pci.Bridge.IoBaseUpper16 << 16);
Limit |= ((UINT32) Pci.Bridge.IoLimitUpper16 << 16);
}
if (Base < Limit) {
if (Io.Base > Base) {
Io.Base = Base;
}
if (Io.Limit < Limit) {
Io.Limit = Limit;
}
}
//
// Get the Memory range that the PPB is decoding
//
Base = ((UINT32) Pci.Bridge.MemoryBase & 0xfff0) << 16;
Limit = (((UINT32) Pci.Bridge.MemoryLimit & 0xfff0) << 16) | 0xfffff;
if (Base < Limit) {
if (Mem.Base > Base) {
Mem.Base = Base;
}
if (Mem.Limit < Limit) {
Mem.Limit = Limit;
}
}
//
// Get the Prefetchable Memory range that the PPB is decoding
// and merge it into Memory range
//
Value = Pci.Bridge.PrefetchableMemoryBase & 0x0f;
Base = ((UINT32) Pci.Bridge.PrefetchableMemoryBase & 0xfff0) << 16;
Limit = (((UINT32) Pci.Bridge.PrefetchableMemoryLimit & 0xfff0)
<< 16) | 0xfffff;
MemAperture = &Mem;
if (Value == BIT0) {
Base |= LShiftU64 (Pci.Bridge.PrefetchableBaseUpper32, 32);
Limit |= LShiftU64 (Pci.Bridge.PrefetchableLimitUpper32, 32);
MemAperture = &MemAbove4G;
}
if (Base < Limit) {
if (MemAperture->Base > Base) {
MemAperture->Base = Base;
}
if (MemAperture->Limit < Limit) {
MemAperture->Limit = Limit;
}
}
//
// Look at the PPB Configuration for legacy decoding attributes
//
if ((Pci.Bridge.BridgeControl & EFI_PCI_BRIDGE_CONTROL_ISA)
== EFI_PCI_BRIDGE_CONTROL_ISA) {
Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO;
Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO_16;
Attributes |= EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO;
}
if ((Pci.Bridge.BridgeControl & EFI_PCI_BRIDGE_CONTROL_VGA)
== EFI_PCI_BRIDGE_CONTROL_VGA) {
Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;
Attributes |= EFI_PCI_ATTRIBUTE_VGA_MEMORY;
Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO;
if ((Pci.Bridge.BridgeControl & EFI_PCI_BRIDGE_CONTROL_VGA_16)
!= 0) {
Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16;
Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO_16;
}
}
BarOffsetEnd = OFFSET_OF (PCI_TYPE01, Bridge.Bar[2]);
} else {
//
// Parse the BARs of the PCI device to get what I/O Ranges, Memory
// Ranges, and Prefetchable Memory Ranges the device is decoding
//
if ((Pci.Hdr.HeaderType & HEADER_LAYOUT_CODE) == HEADER_TYPE_DEVICE) {
BarOffsetEnd = OFFSET_OF (PCI_TYPE00, Device.Bar[6]);
}
}
PcatPciRootBridgeParseBars (
Pci.Hdr.Command,
PrimaryBus,
Device,
Function,
OFFSET_OF (PCI_TYPE00, Device.Bar),
BarOffsetEnd,
&Io,
&Mem, &MemAbove4G
);
//
// See if the PCI device is an IDE controller
//
if (IS_CLASS2 (&Pci, PCI_CLASS_MASS_STORAGE,
PCI_CLASS_MASS_STORAGE_IDE)) {
if (Pci.Hdr.ClassCode[0] & 0x80) {
Attributes |= EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO;
Attributes |= EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO;
}
if (Pci.Hdr.ClassCode[0] & 0x01) {
Attributes |= EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO;
}
if (Pci.Hdr.ClassCode[0] & 0x04) {
Attributes |= EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO;
}
}
//
// See if the PCI device is a legacy VGA controller or
// a standard VGA controller
//
if (IS_CLASS2 (&Pci, PCI_CLASS_OLD, PCI_CLASS_OLD_VGA) ||
IS_CLASS2 (&Pci, PCI_CLASS_DISPLAY, PCI_CLASS_DISPLAY_VGA)
) {
Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;
Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16;
Attributes |= EFI_PCI_ATTRIBUTE_VGA_MEMORY;
Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO;
Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO_16;
}
//
// See if the PCI Device is a PCI - ISA or PCI - EISA
// or ISA_POSITIVE_DECODE Bridge device
//
if (Pci.Hdr.ClassCode[2] == PCI_CLASS_BRIDGE) {
if (Pci.Hdr.ClassCode[1] == PCI_CLASS_BRIDGE_ISA ||
Pci.Hdr.ClassCode[1] == PCI_CLASS_BRIDGE_EISA ||
Pci.Hdr.ClassCode[1] == PCI_CLASS_BRIDGE_ISA_PDECODE) {
Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO;
Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO_16;
Attributes |= EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO;
}
}
//
// If this device is not a multi function device, then skip the rest
// of this PCI device
//
if (Function == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {
break;
}
}
}
//
// If at least one PCI device was found on the primary bus of this PCI
// root bridge, then the PCI root bridge exists.
//
if (NumberOfDevices > 0) {
RootBridges = ReallocatePool (
(*NumberOfRootBridges) * sizeof (PCI_ROOT_BRIDGE),
(*NumberOfRootBridges + 1) * sizeof (PCI_ROOT_BRIDGE),
RootBridges
);
ASSERT (RootBridges != NULL);
PciHostBridgeUtilityInitRootBridge (
Attributes, Attributes, 0,
FALSE, PcdGet16 (PcdOvmfHostBridgePciDevId) != INTEL_Q35_MCH_DEVICE_ID,
(UINT8) PrimaryBus, (UINT8) SubBus,
&Io, &Mem, &MemAbove4G, &mNonExistAperture, &mNonExistAperture,
&RootBridges[*NumberOfRootBridges]
);
RootBridges[*NumberOfRootBridges].ResourceAssigned = TRUE;
//
// Increment the index for the next PCI Root Bridge
//
(*NumberOfRootBridges)++;
}
}
return RootBridges;
}