From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 75D0181994 for ; Thu, 5 Jan 2017 02:15:49 -0800 (PST) Received: from int-mx14.intmail.prod.int.phx2.redhat.com (int-mx14.intmail.prod.int.phx2.redhat.com [10.5.11.27]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id F37E7C057FAC; Thu, 5 Jan 2017 10:15:49 +0000 (UTC) Received: from lacos-laptop-7.usersys.redhat.com (ovpn-116-100.phx2.redhat.com [10.3.116.100]) by int-mx14.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v05AFloP028189; Thu, 5 Jan 2017 05:15:48 -0500 To: Anthony PERARD , edk2-devel@ml01.01.org, xen-devel@lists.xenproject.org References: <20161208153340.2285-1-anthony.perard@citrix.com> <20161208153340.2285-6-anthony.perard@citrix.com> From: Laszlo Ersek Message-ID: <4f7db46c-1728-076b-64eb-afba6b4864bb@redhat.com> Date: Thu, 5 Jan 2017 11:15:46 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.6.0 MIME-Version: 1.0 In-Reply-To: <20161208153340.2285-6-anthony.perard@citrix.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.27 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.32]); Thu, 05 Jan 2017 10:15:50 +0000 (UTC) Subject: Re: [PATCH RFC 05/14] OvmfPkg/Library: add XenPciHostBridgeLib X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 05 Jan 2017 10:15:49 -0000 Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 7bit On 12/08/16 16:33, Anthony PERARD wrote: > A copy of OvmfPkg/Library/PciHostBridgeLib > > Removing support for pci bus enumeration, I think, and only use scan of > already enumerated pci bus. > > Contributed-under: TianoCore Contribution Agreement 1.0 > Signed-off-by: Anthony PERARD > --- > .../Library/XenPciHostBridgeLib/XenPciHostBridge.h | 75 ++++ > .../XenPciHostBridgeLib/XenPciHostBridgeLib.c | 291 +++++++++++++ > .../XenPciHostBridgeLib/XenPciHostBridgeLib.inf | 58 +++ > OvmfPkg/Library/XenPciHostBridgeLib/XenSupport.c | 456 +++++++++++++++++++++ > 4 files changed, 880 insertions(+) > create mode 100644 OvmfPkg/Library/XenPciHostBridgeLib/XenPciHostBridge.h > create mode 100644 OvmfPkg/Library/XenPciHostBridgeLib/XenPciHostBridgeLib.c > create mode 100644 OvmfPkg/Library/XenPciHostBridgeLib/XenPciHostBridgeLib.inf > create mode 100644 OvmfPkg/Library/XenPciHostBridgeLib/XenSupport.c (1) I think the following subject line is more idiomatic: OvmfPkg: add XenPciHostBridgeLib Then, I'll practically repeat my comments for the previous patch: (2) You might want to add Citrix copyright notices to new files. (3) The Xen-related code that remains in the original PciHostBridgeLib instance should be possible to remove later; if that's the case, can you please write a subsequent patch for that too? (4) The removed functionality should be named more precisely in the commit message: - PciHostBridgeGetRootBridges(): the search for extra PCI root buses (which come from QEMU's pxb and pxb-pcie devices) is removed (hence the "etc/extra-pci-roots" fw_cfg file is no longer consulted either, which is otherwise used to speed up the search). The Xen-specific ScanForRootBridges() function call is hardwired. (5) It would be nice to hint at the reason (which is implemented in a later patch) why a separate module is a good idea here. That is, why the expected PVH2 functionality is best not added to the current PciHostBridgeLib instance. More below: > diff --git a/OvmfPkg/Library/XenPciHostBridgeLib/XenPciHostBridge.h b/OvmfPkg/Library/XenPciHostBridgeLib/XenPciHostBridge.h > new file mode 100644 > index 0000000..c23d40c > --- /dev/null > +++ b/OvmfPkg/Library/XenPciHostBridgeLib/XenPciHostBridge.h > @@ -0,0 +1,75 @@ > +/** @file > + Header file of OVMF instance of PciHostBridgeLib. > + > + Copyright (c) 2016, Intel Corporation. All rights reserved.
> + > + This program and the accompanying materials are licensed and made available > + under the terms and conditions of the BSD License which accompanies this > + distribution. The full text of the license may be found at > + http://opensource.org/licenses/bsd-license.php. > + > + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT > + WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. > + > +**/ > + > +PCI_ROOT_BRIDGE * > +ScanForRootBridges ( > + UINTN *NumberOfRootBridges > +); > + > +/** > + Initialize a PCI_ROOT_BRIDGE structure. > + > + @param[in] Supports Supported attributes. > + > + @param[in] Attributes Initial attributes. > + > + @param[in] AllocAttributes Allocation attributes. > + > + @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[in] Io IO aperture. > + > + @param[in] Mem MMIO aperture. > + > + @param[in] MemAbove4G MMIO aperture above 4G. > + > + @param[in] PMem Prefetchable MMIO aperture. > + > + @param[in] PMemAbove4G Prefetchable MMIO aperture above 4G. > + > + @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. > +**/ > +EFI_STATUS > +InitRootBridge ( > + IN UINT64 Supports, > + IN UINT64 Attributes, > + IN UINT64 AllocAttributes, > + IN UINT8 RootBusNumber, > + IN UINT8 MaxSubBusNumber, > + IN PCI_ROOT_BRIDGE_APERTURE *Io, > + IN PCI_ROOT_BRIDGE_APERTURE *Mem, > + IN PCI_ROOT_BRIDGE_APERTURE *MemAbove4G, > + IN PCI_ROOT_BRIDGE_APERTURE *PMem, > + IN PCI_ROOT_BRIDGE_APERTURE *PMemAbove4G, > + OUT PCI_ROOT_BRIDGE *RootBus > + ); > diff --git a/OvmfPkg/Library/XenPciHostBridgeLib/XenPciHostBridgeLib.c b/OvmfPkg/Library/XenPciHostBridgeLib/XenPciHostBridgeLib.c > new file mode 100644 > index 0000000..efcd830 > --- /dev/null > +++ b/OvmfPkg/Library/XenPciHostBridgeLib/XenPciHostBridgeLib.c > @@ -0,0 +1,291 @@ > +/** @file > + OVMF's instance of the PCI Host Bridge Library. > + > + Copyright (C) 2016, Red Hat, Inc. > + Copyright (c) 2016, Intel Corporation. All rights reserved.
> + > + This program and the accompanying materials are licensed and made available > + under the terms and conditions of the BSD License which accompanies this > + distribution. The full text of the license may be found at > + http://opensource.org/licenses/bsd-license.php. > + > + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT > + WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. > + > +**/ > +#include > + > +#include > +#include > + > +#include > +#include > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include "XenPciHostBridge.h" > + > + > +#pragma pack(1) > +typedef struct { > + ACPI_HID_DEVICE_PATH AcpiDevicePath; > + EFI_DEVICE_PATH_PROTOCOL EndDevicePath; > +} OVMF_PCI_ROOT_BRIDGE_DEVICE_PATH; > +#pragma pack () > + > + > +GLOBAL_REMOVE_IF_UNREFERENCED > +CHAR16 *mPciHostBridgeLibAcpiAddressSpaceTypeStr[] = { > + L"Mem", L"I/O", L"Bus" > +}; > + > + > +STATIC > +CONST > +OVMF_PCI_ROOT_BRIDGE_DEVICE_PATH mRootBridgeDevicePathTemplate = { > + { > + { > + ACPI_DEVICE_PATH, > + ACPI_DP, > + { > + (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)), > + (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8) > + } > + }, > + EISA_PNP_ID(0x0A03), // HID > + 0 // UID > + }, > + > + { > + END_DEVICE_PATH_TYPE, > + END_ENTIRE_DEVICE_PATH_SUBTYPE, > + { > + END_DEVICE_PATH_LENGTH, > + 0 > + } > + } > +}; > + > +/** > + Initialize a PCI_ROOT_BRIDGE structure. > + > + @param[in] Supports Supported attributes. > + > + @param[in] Attributes Initial attributes. > + > + @param[in] AllocAttributes Allocation attributes. > + > + @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[in] Io IO aperture. > + > + @param[in] Mem MMIO aperture. > + > + @param[in] MemAbove4G MMIO aperture above 4G. > + > + @param[in] PMem Prefetchable MMIO aperture. > + > + @param[in] PMemAbove4G Prefetchable MMIO aperture above 4G. > + > + @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. > +**/ > +EFI_STATUS > +InitRootBridge ( > + IN UINT64 Supports, > + IN UINT64 Attributes, > + IN UINT64 AllocAttributes, > + IN UINT8 RootBusNumber, > + IN UINT8 MaxSubBusNumber, > + IN PCI_ROOT_BRIDGE_APERTURE *Io, > + IN PCI_ROOT_BRIDGE_APERTURE *Mem, > + IN PCI_ROOT_BRIDGE_APERTURE *MemAbove4G, > + IN PCI_ROOT_BRIDGE_APERTURE *PMem, > + IN PCI_ROOT_BRIDGE_APERTURE *PMemAbove4G, > + OUT PCI_ROOT_BRIDGE *RootBus > + ) > +{ > + OVMF_PCI_ROOT_BRIDGE_DEVICE_PATH *DevicePath; > + > + // > + // Be safe if other fields are added to PCI_ROOT_BRIDGE later. > + // > + ZeroMem (RootBus, sizeof *RootBus); > + > + RootBus->Segment = 0; > + > + RootBus->Supports = Supports; > + RootBus->Attributes = Attributes; > + > + RootBus->DmaAbove4G = FALSE; > + > + RootBus->AllocationAttributes = AllocAttributes; > + RootBus->Bus.Base = RootBusNumber; > + RootBus->Bus.Limit = MaxSubBusNumber; > + CopyMem (&RootBus->Io, Io, sizeof (*Io)); > + CopyMem (&RootBus->Mem, Mem, sizeof (*Mem)); > + CopyMem (&RootBus->MemAbove4G, MemAbove4G, sizeof (*MemAbove4G)); > + CopyMem (&RootBus->PMem, PMem, sizeof (*PMem)); > + CopyMem (&RootBus->PMemAbove4G, PMemAbove4G, sizeof (*PMemAbove4G)); > + > + RootBus->NoExtendedConfigSpace = (PcdGet16 (PcdOvmfHostBridgePciDevId) != > + INTEL_Q35_MCH_DEVICE_ID); > + > + DevicePath = AllocateCopyPool (sizeof mRootBridgeDevicePathTemplate, > + &mRootBridgeDevicePathTemplate); > + if (DevicePath == NULL) { > + DEBUG ((EFI_D_ERROR, "%a: %r\n", __FUNCTION__, EFI_OUT_OF_RESOURCES)); > + return EFI_OUT_OF_RESOURCES; > + } > + DevicePath->AcpiDevicePath.UID = RootBusNumber; > + RootBus->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)DevicePath; > + > + DEBUG ((EFI_D_INFO, > + "%a: populated root bus %d, with room for %d subordinate bus(es)\n", > + __FUNCTION__, RootBusNumber, MaxSubBusNumber - RootBusNumber)); > + return EFI_SUCCESS; > +} > + > + > +/** > + 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 > + ) > +{ > + FreePool (RootBus->DevicePath); > +} > + > + > +/** > + 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 > + ) > +{ > + ASSERT (PcdGetBool (PcdPciDisableBusEnumeration)); > + return ScanForRootBridges (Count); > +} > + > + > +/** > + 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 > + ) > +{ > + if (Bridges == NULL && Count == 0) { > + return; > + } > + ASSERT (Bridges != NULL && Count > 0); > + > + do { > + --Count; > + UninitRootBridge (&Bridges[Count]); > + } while (Count > 0); > + > + FreePool (Bridges); > +} > + > + > +/** > + 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 > + ) > +{ > + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor; > + UINTN RootBridgeIndex; > + DEBUG ((EFI_D_ERROR, "PciHostBridge: Resource conflict happens!\n")); > + > + RootBridgeIndex = 0; > + Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration; > + while (Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR) { > + DEBUG ((EFI_D_ERROR, "RootBridge[%d]:\n", RootBridgeIndex++)); > + for (; Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR; Descriptor++) { > + ASSERT (Descriptor->ResType < > + ARRAY_SIZE (mPciHostBridgeLibAcpiAddressSpaceTypeStr) > + ); > + DEBUG ((EFI_D_ERROR, " %s: Length/Alignment = 0x%lx / 0x%lx\n", > + mPciHostBridgeLibAcpiAddressSpaceTypeStr[Descriptor->ResType], > + Descriptor->AddrLen, Descriptor->AddrRangeMax > + )); > + if (Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) { > + DEBUG ((EFI_D_ERROR, " Granularity/SpecificFlag = %ld / %02x%s\n", > + Descriptor->AddrSpaceGranularity, Descriptor->SpecificFlag, > + ((Descriptor->SpecificFlag & > + EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE > + ) != 0) ? L" (Prefetchable)" : L"" > + )); > + } > + } > + // > + // Skip the END descriptor for root bridge > + // > + ASSERT (Descriptor->Desc == ACPI_END_TAG_DESCRIPTOR); > + Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)( > + (EFI_ACPI_END_TAG_DESCRIPTOR *)Descriptor + 1 > + ); > + } > +} > diff --git a/OvmfPkg/Library/XenPciHostBridgeLib/XenPciHostBridgeLib.inf b/OvmfPkg/Library/XenPciHostBridgeLib/XenPciHostBridgeLib.inf > new file mode 100644 > index 0000000..3b8f003 > --- /dev/null > +++ b/OvmfPkg/Library/XenPciHostBridgeLib/XenPciHostBridgeLib.inf > @@ -0,0 +1,58 @@ > +## @file > +# OVMF's instance of the PCI Host Bridge Library. > +# > +# Copyright (C) 2016, Red Hat, Inc. > +# Copyright (c) 2016, Intel Corporation. All rights reserved.
> +# > +# This program and the accompanying materials are licensed and made available > +# under the terms and conditions of the BSD License which accompanies this > +# distribution. The full text of the license may be found at > +# http://opensource.org/licenses/bsd-license.php > +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR > +# IMPLIED. > +# > +# > +## > + > +[Defines] > + INF_VERSION = 0x00010005 > + BASE_NAME = XenPciHostBridgeLib > + FILE_GUID = 9F2BC05E-51EA-4AED-9A3E-7699641734E8 (6) You forgot to generate a new FILE_GUID with uuidgen. Thanks Laszlo > + 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 IPF EBC > +# > + > +[Sources] > + XenPciHostBridgeLib.c > + XenSupport.c > + XenPciHostBridge.h > + > +[Packages] > + MdeModulePkg/MdeModulePkg.dec > + MdePkg/MdePkg.dec > + OvmfPkg/OvmfPkg.dec > + > +[LibraryClasses] > + BaseMemoryLib > + DebugLib > + DevicePathLib > + MemoryAllocationLib > + PciLib > + > +[Pcd] > + gUefiOvmfPkgTokenSpaceGuid.PcdPciIoBase > + gUefiOvmfPkgTokenSpaceGuid.PcdPciIoSize > + gUefiOvmfPkgTokenSpaceGuid.PcdPciMmio32Base > + gUefiOvmfPkgTokenSpaceGuid.PcdPciMmio32Size > + gUefiOvmfPkgTokenSpaceGuid.PcdPciMmio64Base > + gUefiOvmfPkgTokenSpaceGuid.PcdPciMmio64Size > + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfHostBridgePciDevId > + gEfiMdeModulePkgTokenSpaceGuid.PcdPciDisableBusEnumeration > diff --git a/OvmfPkg/Library/XenPciHostBridgeLib/XenSupport.c b/OvmfPkg/Library/XenPciHostBridgeLib/XenSupport.c > new file mode 100644 > index 0000000..a45945f > --- /dev/null > +++ b/OvmfPkg/Library/XenPciHostBridgeLib/XenSupport.c > @@ -0,0 +1,456 @@ > +/** @file > + Scan the entire PCI bus for root bridges to support OVMF above Xen. > + > + Copyright (c) 2016, Intel Corporation. All rights reserved.
> + > + This program and the accompanying materials are licensed and made available > + under the terms and conditions of the BSD License which accompanies this > + distribution. The full text of the license may be found at > + http://opensource.org/licenses/bsd-license.php. > + > + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT > + WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. > + > +**/ > +#include > + > +#include > +#include > + > +#include > +#include > + > +#include > +#include > +#include > +#include > +#include > +#include "XenPciHostBridge.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 (); > +} > + > +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, > + IN PCI_ROOT_BRIDGE_APERTURE *PMem, > + IN PCI_ROOT_BRIDGE_APERTURE *PMemAbove4G > + > +) > +{ > + UINT32 OriginalValue; > + UINT32 Value; > + UINT32 OriginalUpperValue; > + UINT32 UpperValue; > + UINT64 Mask; > + UINTN Offset; > + UINT64 Base; > + UINT64 Length; > + UINT64 Limit; > + PCI_ROOT_BRIDGE_APERTURE *MemAperture; > + > + 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; > + > + if ((Value & BIT3) == BIT3) { > + MemAperture = PMem; > + } else { > + 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 ((Value & BIT3) == BIT3) { > + MemAperture = PMemAbove4G; > + } else { > + MemAperture = MemAbove4G; > + } > + } > + > + Limit = Base + Length - 1; > + if (Base < Limit) { > + if (MemAperture->Base > Base) { > + MemAperture->Base = Base; > + } > + if (MemAperture->Limit < Limit) { > + MemAperture->Limit = Limit; > + } > + } > + } > + } > + } > +} > + > +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, PMem, PMemAbove4G, *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; > + Io.Base = Mem.Base = MemAbove4G.Base = PMem.Base = PMemAbove4G.Base = MAX_UINT64; > + Io.Limit = Mem.Limit = MemAbove4G.Limit = PMem.Limit = PMemAbove4G.Limit = 0; > + // > + // 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 suborinate 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 > + // > + Value = Pci.Bridge.PrefetchableMemoryBase & 0x0f; > + Base = ((UINT32) Pci.Bridge.PrefetchableMemoryBase & 0xfff0) << 16; > + Limit = (((UINT32) Pci.Bridge.PrefetchableMemoryLimit & 0xfff0) > + << 16) | 0xfffff; > + MemAperture = &PMem; > + if (Value == BIT0) { > + Base |= LShiftU64 (Pci.Bridge.PrefetchableBaseUpper32, 32); > + Limit |= LShiftU64 (Pci.Bridge.PrefetchableLimitUpper32, 32); > + MemAperture = &PMemAbove4G; > + } > + 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, > + &PMem, &PMemAbove4G > + ); > + > + // > + // 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_POSITIVIE_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); > + InitRootBridge ( > + Attributes, Attributes, 0, > + (UINT8) PrimaryBus, (UINT8) SubBus, > + &Io, &Mem, &MemAbove4G, &PMem, &PMemAbove4G, > + &RootBridges[*NumberOfRootBridges] > + ); > + RootBridges[*NumberOfRootBridges].ResourceAssigned = TRUE; > + // > + // Increment the index for the next PCI Root Bridge > + // > + (*NumberOfRootBridges)++; > + } > + } > + > + return RootBridges; > +} >