Extend parameter list of PciHostBridgeUtilityGetRootBridges() with BusMin/ BusMax, so that the utility function could be compatible with ArmVirtPkg who uses mutable bus range [BusMin, BusMax] insteand of [0, PCI_MAX_BUS]. BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3059 Cc: Jordan Justen <jordan.l.justen@intel.com> Cc: Laszlo Ersek <lersek@redhat.com> Cc: Ard Biesheuvel <ard.biesheuvel@arm.com> Signed-off-by: Jiahui Cen <cenjiahui@huawei.com> Message-Id: <20210119011302.10908-10-cenjiahui@huawei.com> [lersek@redhat.com: fix logging of UINTN values BusMin, BusMax] [lersek@redhat.com: keep zeroing of (*Count) centralized] [lersek@redhat.com: fix typos in ExtraRootBridges comment] Reviewed-by: Laszlo Ersek <lersek@redhat.com>
		
			
				
	
	
		
			461 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			461 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  Provide common utility functions to PciHostBridgeLib instances in
 | 
						|
  ArmVirtPkg and OvmfPkg.
 | 
						|
 | 
						|
  Copyright (C) 2016, Red Hat, Inc.
 | 
						|
  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
 | 
						|
  Copyright (c) 2020, Huawei Corporation. All rights reserved.<BR>
 | 
						|
 | 
						|
  SPDX-License-Identifier: BSD-2-Clause-Patent
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
#include <IndustryStandard/Acpi10.h>
 | 
						|
#include <IndustryStandard/Pci.h>
 | 
						|
#include <Library/BaseMemoryLib.h>
 | 
						|
#include <Library/DebugLib.h>
 | 
						|
#include <Library/DevicePathLib.h>
 | 
						|
#include <Library/MemoryAllocationLib.h>
 | 
						|
#include <Library/PciHostBridgeUtilityLib.h>
 | 
						|
#include <Library/PciLib.h>
 | 
						|
#include <Library/QemuFwCfgLib.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 *mPciHostBridgeUtilityLibAcpiAddressSpaceTypeStr[] = {
 | 
						|
  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
 | 
						|
    }
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Utility function to initialize a PCI_ROOT_BRIDGE structure.
 | 
						|
 | 
						|
  @param[in]  Supports               Supported attributes.
 | 
						|
 | 
						|
  @param[in]  Attributes             Initial attributes.
 | 
						|
 | 
						|
  @param[in]  AllocAttributes        Allocation attributes.
 | 
						|
 | 
						|
  @param[in]  DmaAbove4G             DMA above 4GB memory.
 | 
						|
 | 
						|
  @param[in]  NoExtendedConfigSpace  No Extended Config Space.
 | 
						|
 | 
						|
  @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
 | 
						|
EFIAPI
 | 
						|
PciHostBridgeUtilityInitRootBridge (
 | 
						|
  IN  UINT64                   Supports,
 | 
						|
  IN  UINT64                   Attributes,
 | 
						|
  IN  UINT64                   AllocAttributes,
 | 
						|
  IN  BOOLEAN                  DmaAbove4G,
 | 
						|
  IN  BOOLEAN                  NoExtendedConfigSpace,
 | 
						|
  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 = DmaAbove4G;
 | 
						|
 | 
						|
  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 = NoExtendedConfigSpace;
 | 
						|
 | 
						|
  DevicePath = AllocateCopyPool (sizeof mRootBridgeDevicePathTemplate,
 | 
						|
                 &mRootBridgeDevicePathTemplate);
 | 
						|
  if (DevicePath == NULL) {
 | 
						|
    DEBUG ((DEBUG_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 ((DEBUG_INFO,
 | 
						|
    "%a: populated root bus %d, with room for %d subordinate bus(es)\n",
 | 
						|
    __FUNCTION__, RootBusNumber, MaxSubBusNumber - RootBusNumber));
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Utility function to uninitialize a PCI_ROOT_BRIDGE structure set up with
 | 
						|
  PciHostBridgeUtilityInitRootBridge().
 | 
						|
 | 
						|
  @param[in] RootBus  The PCI_ROOT_BRIDGE structure, allocated by the caller and
 | 
						|
                      initialized with PciHostBridgeUtilityInitRootBridge(),
 | 
						|
                      that should be uninitialized. This function doesn't free
 | 
						|
                      RootBus.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
PciHostBridgeUtilityUninitRootBridge (
 | 
						|
  IN PCI_ROOT_BRIDGE *RootBus
 | 
						|
  )
 | 
						|
{
 | 
						|
  FreePool (RootBus->DevicePath);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Utility function to return all the root bridge instances in an array.
 | 
						|
 | 
						|
  @param[out] Count                  The number of root bridge instances.
 | 
						|
 | 
						|
  @param[in]  Attributes             Initial attributes.
 | 
						|
 | 
						|
  @param[in]  AllocAttributes        Allocation attributes.
 | 
						|
 | 
						|
  @param[in]  DmaAbove4G             DMA above 4GB memory.
 | 
						|
 | 
						|
  @param[in]  NoExtendedConfigSpace  No Extended Config Space.
 | 
						|
 | 
						|
  @param[in]  BusMin                 Minimum Bus number, inclusive.
 | 
						|
 | 
						|
  @param[in]  BusMax                 Maximum Bus number, inclusive.
 | 
						|
 | 
						|
  @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.
 | 
						|
 | 
						|
  @return                            All the root bridge instances in an array.
 | 
						|
**/
 | 
						|
PCI_ROOT_BRIDGE *
 | 
						|
EFIAPI
 | 
						|
PciHostBridgeUtilityGetRootBridges (
 | 
						|
  OUT UINTN                    *Count,
 | 
						|
  IN  UINT64                   Attributes,
 | 
						|
  IN  UINT64                   AllocationAttributes,
 | 
						|
  IN  BOOLEAN                  DmaAbove4G,
 | 
						|
  IN  BOOLEAN                  NoExtendedConfigSpace,
 | 
						|
  IN  UINTN                    BusMin,
 | 
						|
  IN  UINTN                    BusMax,
 | 
						|
  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
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS           Status;
 | 
						|
  FIRMWARE_CONFIG_ITEM FwCfgItem;
 | 
						|
  UINTN                FwCfgSize;
 | 
						|
  UINT64               ExtraRootBridges;
 | 
						|
  PCI_ROOT_BRIDGE      *Bridges;
 | 
						|
  UINTN                Initialized;
 | 
						|
  UINTN                LastRootBridgeNumber;
 | 
						|
  UINTN                RootBridgeNumber;
 | 
						|
 | 
						|
  *Count = 0;
 | 
						|
 | 
						|
  if (BusMin > BusMax || BusMax > PCI_MAX_BUS) {
 | 
						|
    DEBUG ((DEBUG_ERROR, "%a: invalid bus range with BusMin %Lu and BusMax "
 | 
						|
      "%Lu\n", __FUNCTION__, (UINT64)BusMin, (UINT64)BusMax));
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // 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);
 | 
						|
 | 
						|
    //
 | 
						|
    // Validate the number of extra root bridges. As BusMax is inclusive, the
 | 
						|
    // max bus count is (BusMax - BusMin + 1). From that, the "main" root bus
 | 
						|
    // is always a given, so the max count for the "extra" root bridges is one
 | 
						|
    // less, i.e. (BusMax - BusMin). If the QEMU hint exceeds that, we have
 | 
						|
    // invalid behavior.
 | 
						|
    //
 | 
						|
    if (ExtraRootBridges > BusMax - BusMin) {
 | 
						|
      DEBUG ((DEBUG_ERROR, "%a: invalid count of extra root buses (%Lu) "
 | 
						|
        "reported by QEMU\n", __FUNCTION__, ExtraRootBridges));
 | 
						|
      return NULL;
 | 
						|
    }
 | 
						|
    DEBUG ((DEBUG_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 ((DEBUG_ERROR, "%a: %r\n", __FUNCTION__, EFI_OUT_OF_RESOURCES));
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
  Initialized = 0;
 | 
						|
 | 
						|
  //
 | 
						|
  // The "main" root bus is always there.
 | 
						|
  //
 | 
						|
  LastRootBridgeNumber = BusMin;
 | 
						|
 | 
						|
  //
 | 
						|
  // 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 = BusMin + 1;
 | 
						|
       RootBridgeNumber <= BusMax && Initialized < ExtraRootBridges;
 | 
						|
       ++RootBridgeNumber) {
 | 
						|
    UINTN Device;
 | 
						|
 | 
						|
    for (Device = 0; Device <= PCI_MAX_DEVICE; ++Device) {
 | 
						|
      if (PciRead16 (PCI_LIB_ADDRESS (RootBridgeNumber, Device, 0,
 | 
						|
                       PCI_VENDOR_ID_OFFSET)) != MAX_UINT16) {
 | 
						|
        break;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    if (Device <= PCI_MAX_DEVICE) {
 | 
						|
      //
 | 
						|
      // 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 = PciHostBridgeUtilityInitRootBridge (
 | 
						|
        Attributes,
 | 
						|
        Attributes,
 | 
						|
        AllocationAttributes,
 | 
						|
        DmaAbove4G,
 | 
						|
        NoExtendedConfigSpace,
 | 
						|
        (UINT8) LastRootBridgeNumber,
 | 
						|
        (UINT8) (RootBridgeNumber - 1),
 | 
						|
        Io,
 | 
						|
        Mem,
 | 
						|
        MemAbove4G,
 | 
						|
        PMem,
 | 
						|
        PMemAbove4G,
 | 
						|
        &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 = PciHostBridgeUtilityInitRootBridge (
 | 
						|
    Attributes,
 | 
						|
    Attributes,
 | 
						|
    AllocationAttributes,
 | 
						|
    DmaAbove4G,
 | 
						|
    NoExtendedConfigSpace,
 | 
						|
    (UINT8) LastRootBridgeNumber,
 | 
						|
    (UINT8) BusMax,
 | 
						|
    Io,
 | 
						|
    Mem,
 | 
						|
    MemAbove4G,
 | 
						|
    PMem,
 | 
						|
    PMemAbove4G,
 | 
						|
    &Bridges[Initialized]
 | 
						|
    );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto FreeBridges;
 | 
						|
  }
 | 
						|
  ++Initialized;
 | 
						|
 | 
						|
  *Count = Initialized;
 | 
						|
  return Bridges;
 | 
						|
 | 
						|
FreeBridges:
 | 
						|
  while (Initialized > 0) {
 | 
						|
    --Initialized;
 | 
						|
    PciHostBridgeUtilityUninitRootBridge (&Bridges[Initialized]);
 | 
						|
  }
 | 
						|
 | 
						|
  FreePool (Bridges);
 | 
						|
  return NULL;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Utility function to free root bridge instances array from
 | 
						|
  PciHostBridgeUtilityGetRootBridges().
 | 
						|
 | 
						|
  @param[in] Bridges  The root bridge instances array.
 | 
						|
  @param[in] Count    The count of the array.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
PciHostBridgeUtilityFreeRootBridges (
 | 
						|
  IN PCI_ROOT_BRIDGE *Bridges,
 | 
						|
  IN UINTN           Count
 | 
						|
  )
 | 
						|
{
 | 
						|
  if (Bridges == NULL && Count == 0) {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
  ASSERT (Bridges != NULL && Count > 0);
 | 
						|
 | 
						|
  do {
 | 
						|
    --Count;
 | 
						|
    PciHostBridgeUtilityUninitRootBridge (&Bridges[Count]);
 | 
						|
  } while (Count > 0);
 | 
						|
 | 
						|
  FreePool (Bridges);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Utility function to inform the platform that the resource conflict happens.
 | 
						|
 | 
						|
  @param[in] 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
 | 
						|
PciHostBridgeUtilityResourceConflict (
 | 
						|
  IN VOID  *Configuration
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;
 | 
						|
  UINTN                             RootBridgeIndex;
 | 
						|
  DEBUG ((DEBUG_ERROR, "PciHostBridge: Resource conflict happens!\n"));
 | 
						|
 | 
						|
  RootBridgeIndex = 0;
 | 
						|
  Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;
 | 
						|
  while (Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR) {
 | 
						|
    DEBUG ((DEBUG_ERROR, "RootBridge[%d]:\n", RootBridgeIndex++));
 | 
						|
    for (; Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR; Descriptor++) {
 | 
						|
      ASSERT (Descriptor->ResType <
 | 
						|
              ARRAY_SIZE (mPciHostBridgeUtilityLibAcpiAddressSpaceTypeStr)
 | 
						|
              );
 | 
						|
      DEBUG ((DEBUG_ERROR, " %s: Length/Alignment = 0x%lx / 0x%lx\n",
 | 
						|
              mPciHostBridgeUtilityLibAcpiAddressSpaceTypeStr[Descriptor->ResType],
 | 
						|
              Descriptor->AddrLen, Descriptor->AddrRangeMax
 | 
						|
              ));
 | 
						|
      if (Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) {
 | 
						|
        DEBUG ((DEBUG_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
 | 
						|
                   );
 | 
						|
  }
 | 
						|
}
 | 
						|
 |