Create the Hardware Info library base together with the specifics to describe PCI Host Bridges. The Hardware Info library is intended to be used for disclosing non-discoverable hardware information from the host to the guest in Ovmf platforms. Core functionality will provide the possibility to parse information from a generic BLOB into runtime structures. The library is conceived in a generic way so that further hardware elements can also be described using it. For such purpose the length of the BLOB is not restricted but instead regarded as a sequence of header-info elements that allow the parsing during runtime. The first type of hardware defined will be PCI host bridges, providing the possibility to define multiple and specify the resources each of them can use. This enables the guest firmware to configure PCI resources properly. Having the size of each individual element favors the reuse of a single interface to convey descriptions of an arbitrary number of heterogenous hardware elements. Furthermore, flexible access mechanisms coupled with the size will grant the possibility of interpreting them in a single run. Define the base types of the generic Hardware Info library to parse heterogeneous data. Also provide the specific changes to support PCI host bridges as the first hardware type supported by the library. Additionally, define the HOST_BRIDGE_INFO structure to describe PCI host bridges along with the functionality to parse such information into proper structures used by the PCI driver in a centralized manner and taking care of versioning. As an example and motivation, the library will be used to define multiple PCI host bridges for complex platforms that require it. The first means of transportation that will be used is going to be fw-cfg, over which a stream of bytes will be transferred and later parsed by the hardware info library. Accordingly, the PCI driver will make use of these host bridges definitions to populate the list of Root Bridges and proceed with the configuration and discovery of underlying hardware components. As mentioned before, the binary data to be parsed by the Hardware Info library should be organized as a sequence of Header-element pairs in which the header describes the type and size of the associated element that comes right after it. As an illustration, to provide inforation of 3 host bridges the data, conceptually, would look like this: Header PCI Host Bridge (type and size) # 1 PCI Host Bridge info # 1 Header PCI Host Bridge (type and size) # 2 PCI Host Bridge info # 2 Header PCI Host Bridge (type and size) # 3 PCI Host Bridge info # 3 Cc: Alexander Graf <graf@amazon.de> Cc: Gerd Hoffmann <kraxel@redhat.com> Acked-by: Gerd Hoffmann <kraxel@redhat.com> Signed-off-by: Nicolas Ojeda Leon <ncoleon@amazon.com>
		
			
				
	
	
		
			509 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			509 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/**@file
 | 
						|
  Hardware info library with types and accessors to parse information about
 | 
						|
  PCI host bridges.
 | 
						|
 | 
						|
  Copyright 2021 - 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 | 
						|
  SPDX-License-Identifier: BSD-2-Clause-Patent
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
#include <Library/DebugLib.h>
 | 
						|
 | 
						|
#include "HardwareInfoPciHostBridgeLib.h"
 | 
						|
 | 
						|
#define IS_RANGE_INVALID(Start, Size, MaxValue)  (Start >= MaxValue || Size == 0)
 | 
						|
 | 
						|
/**
 | 
						|
  Calculate the last (inclusive) address of a range.
 | 
						|
 | 
						|
  @param[in] Start  First address of the range
 | 
						|
  @param[in] Size   Size of the range
 | 
						|
  @return Last address of the range
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
UINT64
 | 
						|
GetRangeEnd (
 | 
						|
  IN  UINT64  Start,
 | 
						|
  IN  UINT64  Size,
 | 
						|
  IN  UINT64  MaxValue
 | 
						|
  )
 | 
						|
{
 | 
						|
  if (IS_RANGE_INVALID (Start, Size, MaxValue)) {
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
 | 
						|
  return Start + Size - 1;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Internal helper to update LastAddress if the Limit address
 | 
						|
  of the Mem aperture is higher than the provided value.
 | 
						|
 | 
						|
  @param[in]  Mem           Pointer to aperture whose limit is
 | 
						|
                            to be compared against accumulative
 | 
						|
                            last address.
 | 
						|
  @param[out] LastAddress   Pointer to accumulative last address
 | 
						|
                            to be updated if Limit is higher
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
VOID
 | 
						|
UpdateLastAddressIfHigher (
 | 
						|
  IN  PCI_ROOT_BRIDGE_APERTURE  *Mem,
 | 
						|
  OUT UINT64                    *LastAddress
 | 
						|
  )
 | 
						|
{
 | 
						|
  if (Mem->Limit > *LastAddress) {
 | 
						|
    *LastAddress = Mem->Limit;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
HardwareInfoPciHostBridgeLastMmioAddress (
 | 
						|
  IN CONST  HOST_BRIDGE_INFO  *HostBridge,
 | 
						|
  IN        UINTN             DataSize,
 | 
						|
  IN        BOOLEAN           HighMem,
 | 
						|
  OUT       UINT64            *LastMmioAddress
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                Status;
 | 
						|
  PCI_ROOT_BRIDGE_APERTURE  Mem;
 | 
						|
  PCI_ROOT_BRIDGE_APERTURE  MemAbove4G;
 | 
						|
  PCI_ROOT_BRIDGE_APERTURE  PMem;
 | 
						|
  PCI_ROOT_BRIDGE_APERTURE  PMemAbove4G;
 | 
						|
 | 
						|
  if (LastMmioAddress == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Set the output to the lowest possible value so that if some step fails
 | 
						|
  // the overall outcome reflects no information found
 | 
						|
  //
 | 
						|
  *LastMmioAddress = 0;
 | 
						|
 | 
						|
  Status = HardwareInfoPciHostBridgeGetApertures (
 | 
						|
             HostBridge,
 | 
						|
             DataSize,
 | 
						|
             NULL,
 | 
						|
             &Mem,
 | 
						|
             &MemAbove4G,
 | 
						|
             &PMem,
 | 
						|
             &PMemAbove4G,
 | 
						|
             NULL
 | 
						|
             );
 | 
						|
 | 
						|
  //
 | 
						|
  // Forward error to caller but ignore warnings given that, very likely,
 | 
						|
  // the host bridge will have a PIO aperture we are explicitly
 | 
						|
  // ignoring here since we care only about MMIO resources.
 | 
						|
  //
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  if (HighMem) {
 | 
						|
    UpdateLastAddressIfHigher (&MemAbove4G, LastMmioAddress);
 | 
						|
    UpdateLastAddressIfHigher (&PMemAbove4G, LastMmioAddress);
 | 
						|
  } else {
 | 
						|
    UpdateLastAddressIfHigher (&Mem, LastMmioAddress);
 | 
						|
    UpdateLastAddressIfHigher (&PMem, LastMmioAddress);
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Set the boundaries of an aperture to invalid values having
 | 
						|
  size zero and start MaxValue (yields Start > Limit which
 | 
						|
  depicts an invalid range)
 | 
						|
 | 
						|
  @param[in]  MaxValue    Max value of the aperture's range (depends
 | 
						|
                          on the data type)
 | 
						|
  @param[out] Aperture    Aperture object to invalidate
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
VOID
 | 
						|
InvalidateRootBridgeAperture (
 | 
						|
  OUT PCI_ROOT_BRIDGE_APERTURE  *Aperture
 | 
						|
  )
 | 
						|
{
 | 
						|
  if (Aperture == NULL) {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  Aperture->Base  = MAX_UINT64;
 | 
						|
  Aperture->Limit = 0;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Fill a PCI ROOT BRIDGE APERTURE with the proper values calculated
 | 
						|
  from the provided start and size.
 | 
						|
 | 
						|
  @param[in]  Start       Start address of the aperture
 | 
						|
  @param[in]  Size        Size, in bytes, of the aperture
 | 
						|
  @param[in]  MaxValue    Max value a valid address could take and which
 | 
						|
                          represents an invalid start address.
 | 
						|
  @param[out] Aperture    Pointer to the aperture to be filled
 | 
						|
 | 
						|
  @retval EFI_SUCCESS                 Aperture was filled successfully
 | 
						|
  @retval EFI_INVALID_PARAMETER       Range depicted by Start and Size is
 | 
						|
                                      valid but ignored because aperture
 | 
						|
                                      pointer is NULL
 | 
						|
  @retval EFI_WARN_BUFFER_TOO_SMALL   Aperture pointer is invalid but the
 | 
						|
                                      range also is so no harm.
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
EFI_STATUS
 | 
						|
FillHostBridgeAperture (
 | 
						|
  IN  UINT64                    Start,
 | 
						|
  IN  UINT64                    Size,
 | 
						|
  IN  UINT64                    MaxValue,
 | 
						|
  OUT PCI_ROOT_BRIDGE_APERTURE  *Aperture
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT64  End;
 | 
						|
 | 
						|
  End = GetRangeEnd (Start, Size, MaxValue);
 | 
						|
 | 
						|
  if (Aperture == NULL) {
 | 
						|
    if (!IS_RANGE_INVALID (Start, Size, MaxValue)) {
 | 
						|
      //
 | 
						|
      // Report an error to the caller since the range specified in
 | 
						|
      // the host bridge's resources is non-empty but the provided
 | 
						|
      // aperture pointer is null, thus the valid range is ignored.
 | 
						|
      //
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
 | 
						|
    return EFI_WARN_BUFFER_TOO_SMALL;
 | 
						|
  }
 | 
						|
 | 
						|
  if (IS_RANGE_INVALID (Start, Size, MaxValue)) {
 | 
						|
    //
 | 
						|
    // Fill Aperture with invalid range values to signal the
 | 
						|
    // absence of an address space (empty range)
 | 
						|
    //
 | 
						|
    InvalidateRootBridgeAperture (Aperture);
 | 
						|
  } else {
 | 
						|
    Aperture->Base  = Start;
 | 
						|
    Aperture->Limit = End;
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Merge 2 ranges (normal and prefetchable) into a single aperture
 | 
						|
  comprehending the addresses encompassed by both of them. If both
 | 
						|
  ranges are not empty they must be contiguous for correctness.
 | 
						|
 | 
						|
  @param[in]  Start       Range start address
 | 
						|
  @param[in]  Size        Range size in bytes
 | 
						|
  @param[in]  PStart      Prefetchable range start address
 | 
						|
  @param[in]  PSize       Prefetchable range size in bytes
 | 
						|
  @param[in]  MaxValue    Max value a valid address could take and which
 | 
						|
                          represents an invalid start address.
 | 
						|
  @param[out] Aperture    Pointer to the aperture to be filled
 | 
						|
 | 
						|
  @retval EFI_SUCCESS                 Aperture was filled successfully
 | 
						|
  @retval EFI_INVALID_PARAMETER       Either range depicted by Start, Size
 | 
						|
                                      or PStart, PSize or both are valid
 | 
						|
                                      but ignored because aperture pointer
 | 
						|
                                      is NULL
 | 
						|
  @retval EFI_WARN_BUFFER_TOO_SMALL   Aperture pointer is invalid but both
 | 
						|
                                      ranges are too so no harm.
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
EFI_STATUS
 | 
						|
MergeHostBridgeApertures (
 | 
						|
  IN  UINT64                    Start,
 | 
						|
  IN  UINT64                    Size,
 | 
						|
  IN  UINT64                    PStart,
 | 
						|
  IN  UINT64                    PSize,
 | 
						|
  IN  UINT64                    MaxValue,
 | 
						|
  OUT PCI_ROOT_BRIDGE_APERTURE  *Aperture
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT64  PEnd;
 | 
						|
 | 
						|
  if (Aperture == NULL) {
 | 
						|
    if (!IS_RANGE_INVALID (Start, Size, MaxValue) ||
 | 
						|
        !IS_RANGE_INVALID (PStart, PSize, MaxValue))
 | 
						|
    {
 | 
						|
      //
 | 
						|
      // Report an error to the caller since the range specified in
 | 
						|
      // the host bridge's resources is non-empty but the provided
 | 
						|
      // aperture pointer is null, thus the valid range is ignored.
 | 
						|
      //
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
 | 
						|
    return EFI_WARN_BUFFER_TOO_SMALL;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Start from an empty range (Limit < Base)
 | 
						|
  //
 | 
						|
  InvalidateRootBridgeAperture (Aperture);
 | 
						|
 | 
						|
  if (!IS_RANGE_INVALID (Start, Size, MaxValue)) {
 | 
						|
    Aperture->Base  = Start;
 | 
						|
    Aperture->Limit = Start + Size - 1;
 | 
						|
  }
 | 
						|
 | 
						|
  if (!IS_RANGE_INVALID (PStart, PSize, MaxValue)) {
 | 
						|
    PEnd = PStart + PSize - 1;
 | 
						|
 | 
						|
    if (PStart < Aperture->Base) {
 | 
						|
      Aperture->Base = PStart;
 | 
						|
    }
 | 
						|
 | 
						|
    if (PEnd > Aperture->Limit) {
 | 
						|
      Aperture->Limit = PEnd;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
HardwareInfoPciHostBridgeGetBusNrRange (
 | 
						|
  IN CONST  HOST_BRIDGE_INFO  *HostBridge,
 | 
						|
  IN        UINTN             DataSize,
 | 
						|
  OUT       UINTN             *BusNrStart,
 | 
						|
  OUT       UINTN             *BusNrLast
 | 
						|
  )
 | 
						|
{
 | 
						|
  if ((HostBridge == NULL) || (DataSize == 0) ||
 | 
						|
      (BusNrStart == NULL) || (BusNrLast == NULL))
 | 
						|
  {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // For now only version 0 is supported
 | 
						|
  //
 | 
						|
  if (HostBridge->Version != 0) {
 | 
						|
    return EFI_INCOMPATIBLE_VERSION;
 | 
						|
  }
 | 
						|
 | 
						|
  *BusNrStart = HostBridge->BusNrStart;
 | 
						|
  *BusNrLast  = HostBridge->BusNrLast;
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
HardwareInfoPciHostBridgeGetApertures (
 | 
						|
  IN CONST  HOST_BRIDGE_INFO          *HostBridge,
 | 
						|
  IN        UINTN                     DataSize,
 | 
						|
  OUT       PCI_ROOT_BRIDGE_APERTURE  *Io,
 | 
						|
  OUT       PCI_ROOT_BRIDGE_APERTURE  *Mem,
 | 
						|
  OUT       PCI_ROOT_BRIDGE_APERTURE  *MemAbove4G,
 | 
						|
  OUT       PCI_ROOT_BRIDGE_APERTURE  *PMem,
 | 
						|
  OUT       PCI_ROOT_BRIDGE_APERTURE  *PMemAbove4G,
 | 
						|
  OUT       PCI_ROOT_BRIDGE_APERTURE  *PcieConfig
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS  Status;
 | 
						|
  BOOLEAN     StickyError;
 | 
						|
 | 
						|
  StickyError = FALSE;
 | 
						|
  if ((HostBridge == NULL) || (DataSize == 0)) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // For now only version 0 is supported
 | 
						|
  //
 | 
						|
  if (HostBridge->Version != 0) {
 | 
						|
    return EFI_INCOMPATIBLE_VERSION;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = FillHostBridgeAperture (
 | 
						|
             HostBridge->IoStart,
 | 
						|
             HostBridge->IoSize,
 | 
						|
             MAX_UINT32,
 | 
						|
             Io
 | 
						|
             );
 | 
						|
  StickyError |= EFI_ERROR (Status);
 | 
						|
 | 
						|
  Status = FillHostBridgeAperture (
 | 
						|
             HostBridge->PcieConfigStart,
 | 
						|
             HostBridge->PcieConfigSize,
 | 
						|
             MAX_UINT64,
 | 
						|
             PcieConfig
 | 
						|
             );
 | 
						|
  StickyError |= EFI_ERROR (Status);
 | 
						|
 | 
						|
  if (HostBridge->Flags.Bits.CombineMemPMem) {
 | 
						|
    Status = MergeHostBridgeApertures (
 | 
						|
               HostBridge->MemStart,
 | 
						|
               HostBridge->MemSize,
 | 
						|
               HostBridge->PMemStart,
 | 
						|
               HostBridge->PMemSize,
 | 
						|
               MAX_UINT32,
 | 
						|
               Mem
 | 
						|
               );
 | 
						|
    StickyError |= EFI_ERROR (Status);
 | 
						|
 | 
						|
    Status = MergeHostBridgeApertures (
 | 
						|
               HostBridge->MemAbove4GStart,
 | 
						|
               HostBridge->MemAbove4GSize,
 | 
						|
               HostBridge->PMemAbove4GStart,
 | 
						|
               HostBridge->PMemAbove4GSize,
 | 
						|
               MAX_UINT64,
 | 
						|
               MemAbove4G
 | 
						|
               );
 | 
						|
    StickyError |= EFI_ERROR (Status);
 | 
						|
 | 
						|
    //
 | 
						|
    // Invalidate unused apertures
 | 
						|
    //
 | 
						|
    InvalidateRootBridgeAperture (PMem);
 | 
						|
    InvalidateRootBridgeAperture (PMemAbove4G);
 | 
						|
  } else {
 | 
						|
    Status = FillHostBridgeAperture (
 | 
						|
               HostBridge->MemStart,
 | 
						|
               HostBridge->MemSize,
 | 
						|
               MAX_UINT32,
 | 
						|
               Mem
 | 
						|
               );
 | 
						|
    StickyError |= EFI_ERROR (Status);
 | 
						|
 | 
						|
    Status = FillHostBridgeAperture (
 | 
						|
               HostBridge->PMemStart,
 | 
						|
               HostBridge->PMemSize,
 | 
						|
               MAX_UINT32,
 | 
						|
               PMem
 | 
						|
               );
 | 
						|
    StickyError |= EFI_ERROR (Status);
 | 
						|
 | 
						|
    Status = FillHostBridgeAperture (
 | 
						|
               HostBridge->MemAbove4GStart,
 | 
						|
               HostBridge->MemAbove4GSize,
 | 
						|
               MAX_UINT64,
 | 
						|
               MemAbove4G
 | 
						|
               );
 | 
						|
    StickyError |= EFI_ERROR (Status);
 | 
						|
 | 
						|
    Status = FillHostBridgeAperture (
 | 
						|
               HostBridge->PMemAbove4GStart,
 | 
						|
               HostBridge->PMemAbove4GSize,
 | 
						|
               MAX_UINT64,
 | 
						|
               PMem
 | 
						|
               );
 | 
						|
    StickyError |= EFI_ERROR (Status);
 | 
						|
  }
 | 
						|
 | 
						|
  if (StickyError) {
 | 
						|
    //
 | 
						|
    // If any function returned an error it is due to a valid range
 | 
						|
    // specified in the host bridge that was ignored due to a NULL
 | 
						|
    // pointer. Translate it to a warning to allow for calling with
 | 
						|
    // only a subset of the apertures.
 | 
						|
    //
 | 
						|
    return EFI_WARN_STALE_DATA;
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
HardwareInfoPciHostBridgeGetFlags (
 | 
						|
  IN CONST  HOST_BRIDGE_INFO  *HostBridge,
 | 
						|
  IN        UINTN             DataSize,
 | 
						|
  OUT       UINT64            *Attributes               OPTIONAL,
 | 
						|
  OUT       BOOLEAN           *DmaAbove4G               OPTIONAL,
 | 
						|
  OUT       BOOLEAN           *NoExtendedConfigSpace    OPTIONAL,
 | 
						|
  OUT       BOOLEAN           *CombineMemPMem           OPTIONAL
 | 
						|
  )
 | 
						|
{
 | 
						|
  if ((HostBridge == NULL) || (DataSize == 0)) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // For now only version 0 is supported
 | 
						|
  //
 | 
						|
  if (HostBridge->Version != 0) {
 | 
						|
    return EFI_INCOMPATIBLE_VERSION;
 | 
						|
  }
 | 
						|
 | 
						|
  if (Attributes) {
 | 
						|
    *Attributes = HostBridge->Attributes;
 | 
						|
  }
 | 
						|
 | 
						|
  if (DmaAbove4G) {
 | 
						|
    *DmaAbove4G = !!HostBridge->Flags.Bits.DmaAbove4G;
 | 
						|
  }
 | 
						|
 | 
						|
  if (NoExtendedConfigSpace) {
 | 
						|
    *NoExtendedConfigSpace = !!HostBridge->Flags.Bits.NoExtendedConfigSpace;
 | 
						|
  }
 | 
						|
 | 
						|
  if (CombineMemPMem) {
 | 
						|
    *CombineMemPMem = !!HostBridge->Flags.Bits.CombineMemPMem;
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
HardwareInfoPciHostBridgeGet (
 | 
						|
  IN CONST  HOST_BRIDGE_INFO          *HostBridge,
 | 
						|
  IN        UINTN                     DataSize,
 | 
						|
  OUT       UINTN                     *BusNrStart,
 | 
						|
  OUT       UINTN                     *BusNrLast,
 | 
						|
  OUT       UINT64                    *Attributes               OPTIONAL,
 | 
						|
  OUT       BOOLEAN                   *DmaAbove4G               OPTIONAL,
 | 
						|
  OUT       BOOLEAN                   *NoExtendedConfigSpace    OPTIONAL,
 | 
						|
  OUT       BOOLEAN                   *CombineMemPMem           OPTIONAL,
 | 
						|
  OUT       PCI_ROOT_BRIDGE_APERTURE  *Io                       OPTIONAL,
 | 
						|
  OUT       PCI_ROOT_BRIDGE_APERTURE  *Mem                      OPTIONAL,
 | 
						|
  OUT       PCI_ROOT_BRIDGE_APERTURE  *MemAbove4G               OPTIONAL,
 | 
						|
  OUT       PCI_ROOT_BRIDGE_APERTURE  *PMem                     OPTIONAL,
 | 
						|
  OUT       PCI_ROOT_BRIDGE_APERTURE  *PMemAbove4G              OPTIONAL,
 | 
						|
  OUT       PCI_ROOT_BRIDGE_APERTURE  *PcieConfig               OPTIONAL
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS  Status;
 | 
						|
 | 
						|
  Status = HardwareInfoPciHostBridgeGetBusNrRange (
 | 
						|
             HostBridge,
 | 
						|
             DataSize,
 | 
						|
             BusNrStart,
 | 
						|
             BusNrLast
 | 
						|
             );
 | 
						|
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = HardwareInfoPciHostBridgeGetFlags (
 | 
						|
             HostBridge,
 | 
						|
             DataSize,
 | 
						|
             Attributes,
 | 
						|
             DmaAbove4G,
 | 
						|
             NoExtendedConfigSpace,
 | 
						|
             CombineMemPMem
 | 
						|
             );
 | 
						|
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = HardwareInfoPciHostBridgeGetApertures (
 | 
						|
             HostBridge,
 | 
						|
             DataSize,
 | 
						|
             Io,
 | 
						|
             Mem,
 | 
						|
             MemAbove4G,
 | 
						|
             PMem,
 | 
						|
             PMemAbove4G,
 | 
						|
             PcieConfig
 | 
						|
             );
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 |