public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Ojeda Leon, Nicolas" <ncoleon@amazon.com>
To: <devel@edk2.groups.io>
Cc: Nicolas Ojeda Leon <ncoleon@amazon.com>,
	Alexander Graf <graf@amazon.de>,
	Gerd Hoffmann <kraxel@redhat.com>
Subject: [PATCH v5 1/5] OvmfPkg/Library: Create base HardwareInfoLib for PCI Host Bridges
Date: Mon, 25 Apr 2022 23:43:46 +0200	[thread overview]
Message-ID: <4fb5befbbeca65d9fc1a66dbaa446b853570fe10.1650918674.git.ncoleon@amazon.com> (raw)
In-Reply-To: <cover.1650918674.git.ncoleon@amazon.com>

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>
---
Notes:
	v4:
	- Minor change in InvalidateRootBridgeAperture to always set the
	  invalid base address to MAX_UINT64, thus having a universal
	  invalid value.


 .../HardwareInfoPciHostBridgeLib.c            | 514 ++++++++++++++++++
 .../HardwareInfoPciHostBridgeLib.h            | 262 +++++++++
 .../HardwareInfoLib/HardwareInfoTypesLib.h    |  64 +++
 3 files changed, 840 insertions(+)
 create mode 100644 OvmfPkg/Library/HardwareInfoLib/HardwareInfoPciHostBridgeLib.c
 create mode 100644 OvmfPkg/Library/HardwareInfoLib/HardwareInfoPciHostBridgeLib.h
 create mode 100644 OvmfPkg/Library/HardwareInfoLib/HardwareInfoTypesLib.h

diff --git a/OvmfPkg/Library/HardwareInfoLib/HardwareInfoPciHostBridgeLib.c b/OvmfPkg/Library/HardwareInfoLib/HardwareInfoPciHostBridgeLib.c
new file mode 100644
index 0000000000..43a8d233ab
--- /dev/null
+++ b/OvmfPkg/Library/HardwareInfoLib/HardwareInfoPciHostBridgeLib.c
@@ -0,0 +1,514 @@
+/**@file
+  Hardware info library with types and accessors to parse information about
+  PCI host bridges.
+
+  Copyright 2021 Amazon.com, Inc. or its affiliates. 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 <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;
+}
diff --git a/OvmfPkg/Library/HardwareInfoLib/HardwareInfoPciHostBridgeLib.h b/OvmfPkg/Library/HardwareInfoLib/HardwareInfoPciHostBridgeLib.h
new file mode 100644
index 0000000000..397c8f8a5d
--- /dev/null
+++ b/OvmfPkg/Library/HardwareInfoLib/HardwareInfoPciHostBridgeLib.h
@@ -0,0 +1,262 @@
+/**@file
+  Hardware info library with types and accessors to parse information about
+  PCI host bridges.
+
+  Copyright 2021 Amazon.com, Inc. or its affiliates. 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.
+ **/
+
+#ifndef __HARDWARE_INFO_PCI_HOST_BRIDGE_LIB_H__
+#define __HARDWARE_INFO_PCI_HOST_BRIDGE_LIB_H__
+
+#include <Uefi/UefiBaseType.h>
+#include <Uefi/UefiSpec.h>
+#include <Library/PciHostBridgeLib.h>
+
+//
+// Host Bridge resources information
+//
+#pragma pack(1)
+typedef struct {
+  //
+  // Feature tracking, initially 0
+  //
+  UINT64    Version;
+
+  //
+  // Host bridge enabled attributes (EFI_PCI_ATTRIBUTE_*)
+  //
+  UINT64    Attributes;
+
+  union {
+    UINT64    Uint64;
+    struct {
+      UINT64    DmaAbove4G            : 1;
+      UINT64    NoExtendedConfigSpace : 1;
+      UINT64    CombineMemPMem        : 1;
+      UINT64    Reserved              : 61;
+    } Bits;
+  } Flags;
+
+  //
+  // Bus number range
+  //
+  UINT8     BusNrStart;
+  UINT8     BusNrLast;
+
+  UINT8     Padding[6];
+
+  //
+  // IO aperture
+  //
+  UINT64    IoStart;
+  UINT64    IoSize;
+
+  //
+  // 32-bit MMIO aperture
+  //
+  UINT64    MemStart;
+  UINT64    MemSize;
+
+  //
+  // 32-bit prefetchable MMIO aperture
+  //
+  UINT64    PMemStart;
+  UINT64    PMemSize;
+
+  //
+  // 64-bit MMIO aperture
+  //
+  UINT64    MemAbove4GStart;
+  UINT64    MemAbove4GSize;
+
+  //
+  // 64-bit prefetchable MMIO aperture
+  //
+  UINT64    PMemAbove4GStart;
+  UINT64    PMemAbove4GSize;
+
+  //
+  // MMIO accessible PCIe config space (ECAM)
+  //
+  UINT64    PcieConfigStart;
+  UINT64    PcieConfigSize;
+} HOST_BRIDGE_INFO;
+#pragma pack()
+
+/**
+  Extract the last MMIO address, either from high (64-bit) or low (32-bit)
+  memory used by the HostBridge's apertures.
+
+  @param[in]  HostBridge      Root bridge's resources specification
+  @param[in]  DataSize        Size in bytes of the actually filled
+                              data available in the HostBridge object
+  @param[in]  HighMem         64-bit (true) or 32-bit (false) MMIO
+                              address
+  @param[out] LastMmioAddress Pointer to last MMIO address
+
+  @retval EFI_SUCCESS               Operation succeeded
+  @retval EFI_INVALID_PARAMETER     One or more pointer parameters are
+                                    invalid
+  @retval EFI_INCOMPATIBLE_VERSION  HostBridge information belongs to
+                                    an unsupported version
+**/
+EFI_STATUS
+HardwareInfoPciHostBridgeLastMmioAddress (
+  IN CONST  HOST_BRIDGE_INFO  *HostBridge,
+  IN        UINTN             DataSize,
+  IN        BOOLEAN           HighMem,
+  OUT       UINT64            *LastMmioAddress
+  );
+
+/**
+  Interpret the HostBridge resources and extact the bus number
+  range.
+
+  @param[in]  HostBridge   Root bridge's resources specification
+  @param[in]  DataSize     Size in bytes of the actually filled
+                           data available in the HostBridge object
+  @param[out] BusNrStart   Pointer to the Bus Number range start
+  @param[out] BusNrLast    Pointer to the Bus Number range end
+
+  @retval EFI_SUCCESS               Retrieved the bus number range
+                                    without any issues.
+  @retval EFI_INVALID_PARAMETER     One of the parameters is invalid,
+                                    either NULL pointer or size 0
+  @retval EFI_INCOMPATIBLE_VERSION  HostBridge data of unsupported
+                                    version
+**/
+EFI_STATUS
+HardwareInfoPciHostBridgeGetBusNrRange (
+  IN CONST  HOST_BRIDGE_INFO  *HostBridge,
+  IN        UINTN             DataSize,
+  OUT       UINTN             *BusNrStart,
+  OUT       UINTN             *BusNrLast
+  );
+
+/**
+  Interpret the MMIO resources in HostBridge and set the apertures
+  in 32-bit space (Mem), 64-bit space (MemAbove4G), PIO (IO) and
+  ECAM (PcieConfig) accordingly.
+
+  The 2 types of apertures in each MMIO space (prefetchable and
+  non-prefetchable) may be merged into a single window, hence if both
+  types of apertures are defined while the CombineMemPMem flag is set,
+  the ranges must be contiguous.
+
+  @param[in]  HostBridge   Root bridge's resources specification
+  @param[in]  DataSize     Size in bytes of the actually filled
+                           data available in the HostBridge object
+  @param[out] Mem          Pointer to 32-bit MMIO aperture
+  @param[out] MemAbove4G   Pointer to 64-bit MMIO aperture
+  @param[out] PMem         Pointer to the 32-bit prefetchable MMIO aperture
+  @param[out] PMemAbove4G  Pointer to the 64-bit prefetchable MMIO aperture
+  @param[out] PcieConfig   Pointer to MMIO mapped PCIe config aperture (ECAM)
+
+  @retval EFI_INVALID_PARAMETER     HostBridge object is invalid
+  @retval EFI_INCOMPATIBLE_VERSION  HostBridge information belongs to
+                                    an unsupported version
+  @retval EFI_WARN_STALE_DATA       One or more valid aperture in the
+                                    HostBridge's resources were ignored
+                                    because corresponding aperture pointer
+                                    is NULL.
+  @retval EFI_SUCCESS               Operation executed cleanly, all valid
+                                    ranges were parsed into the corresponding
+                                    aperture object.
+**/
+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
+  );
+
+/**
+  Retrieve all flags and attributes of a host bridge describing the
+  resources and capabilities.
+
+  @param[in]  HostBridge            Host bridge information object
+  @param[in]  DataSize              Size in bytes of the actually filled
+                                    data available in the HostBridge object
+  @param[out] Attributes            Pointer to the host bridge's attributes
+  @param[out] DmaAbove4G            Pointer to the DMA Above 4G flag
+  @param[out] NoExtendedConfigSpace Pointer to the Extended Config Space flag
+  @param[out] CombineMemPMem        Pointer to the Combine Mem and PMem flag
+
+  @retval EFI_INVALID_PARAMETER     HostBridge object is invalid
+  @retval EFI_INCOMPATIBLE_VERSION  HostBridge information belongs to
+                                    an unsupported version
+  @retval EFI_SUCCESS               Operation executed cleanly
+**/
+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
+  );
+
+/**
+  Getter that parses information from a HOST_BRIDGE_INFO object
+  into smaller chunks of types handled by the PciHostBridgeLib.
+
+  @param[in]  HostBridge            Host bridge information object
+  @param[in]  DataSize              Size in bytes of the actually filled
+                                    data available in the HostBridge object
+  @param[out] BusNrStart            Pointer to the Bus Number range start
+  @param[out] BusNrLast             Pointer to the Bus Number range end
+  @param[out] Attributes            Pointer to the host bridge's attributes
+  @param[out] DmaAbove4G            Pointer to the DMA Above 4G flag
+  @param[out] NoExtendedConfigSpace Pointer to the Extended Config Space flag
+  @param[out] CombineMemPMem        Pointer to the Combine Mem and PMem flag
+  @param[out] Io                    Pointer to the PIO aperture object
+  @param[out] Mem                   Pointer to the 32-bit MMIO aperture object
+  @param[out] MemAbove4G            Pointer to the 64-bit MMIO aperture object
+  @param[out] PMem                  Pointer to the 32-bit prefetchable MMIO
+                                    aperture object
+  @param[out] PMemAbove4G           Pointer to the 64-bit prefetchable MMIO
+                                    aperture object
+  @param[out] PcieConfig            MMIO mapped PCIe config aperture (ECAM)
+
+  @retval EFI_SUCCESS               Whole operation succeeded
+  @retval EFI_INVALID_PARAMETER     HostBridge object and/or non-optional
+                                    output parameters are invalid
+  @retval EFI_INCOMPATIBLE_VERSION  HostBridge information provided belongs to
+                                    and unsupported version
+  @retval EFI_WARN_STALE_DATA       One or more apertures having valid ranges
+                                    in the HostBridge info were ignored because
+                                    the correspnding aperture pointer is NULL
+**/
+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
+  );
+
+#endif // __HARDWARE_INFO_PCI_HOST_BRIDGE_LIB_H__
diff --git a/OvmfPkg/Library/HardwareInfoLib/HardwareInfoTypesLib.h b/OvmfPkg/Library/HardwareInfoLib/HardwareInfoTypesLib.h
new file mode 100644
index 0000000000..84edd1c6ac
--- /dev/null
+++ b/OvmfPkg/Library/HardwareInfoLib/HardwareInfoTypesLib.h
@@ -0,0 +1,64 @@
+/**@file
+  Hardware info types' definitions.
+
+  General hardware info types to parse the binary data
+
+  Copyright 2021 Amazon.com, Inc. or its affiliates. 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.
+ **/
+
+#ifndef __HARDWARE_INFO_TYPES_LIB_H__
+#define __HARDWARE_INFO_TYPES_LIB_H__
+
+// Specific hardware types:
+#include "HardwareInfoPciHostBridgeLib.h"
+
+//
+// Hardware info types enumeration listing the supported
+// types which have an associated type definition
+//
+typedef enum {
+  HardwareInfoTypeUndefined  = 0,
+  HardwareInfoTypeHostBridge = 1,
+} HARDWARE_INFO_TYPE;
+
+//
+// Header format preceding and describing an associated hardware
+// info element
+//
+#pragma pack(1)
+typedef struct {
+  union {
+    UINT64                Uint64;
+    HARDWARE_INFO_TYPE    Value;
+  } Type;
+  UINT64    Size;
+} HARDWARE_INFO_HEADER;
+#pragma pack()
+
+//
+// Generic data structure to access any supported hardware type
+// resource definition
+//
+#pragma pack(1)
+typedef struct {
+  LIST_ENTRY              Link;
+  HARDWARE_INFO_HEADER    Header;
+  union {
+    UINT8               *Raw;
+    HOST_BRIDGE_INFO    *PciHostBridge;
+  } Data;
+} HARDWARE_INFO;
+#pragma pack()
+
+#define HARDWARE_INFO_FROM_LINK(a) \
+  BASE_CR (a, HARDWARE_INFO, Link)
+
+#endif // __HARDWARE_INFO_TYPES_LIB_H__
-- 
2.32.0




Amazon Development Center Germany GmbH
Krausenstr. 38
10117 Berlin
Geschaeftsfuehrung: Christian Schlaeger, Jonathan Weiss
Eingetragen am Amtsgericht Charlottenburg unter HRB 149173 B
Sitz: Berlin
Ust-ID: DE 289 237 879




  reply	other threads:[~2022-04-25 21:44 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-04-25 21:43 [PATCH v5 0/5] Handling of multiple PCI host bridges Ojeda Leon, Nicolas
2022-04-25 21:43 ` Ojeda Leon, Nicolas [this message]
2022-04-25 21:43 ` [PATCH v5 2/5] Ovmf/HardwareInfoLib: Create Pei lib to parse directly from fw-cfg Ojeda Leon, Nicolas
2022-04-25 21:43 ` [PATCH v5 3/5] Ovmf/HardwareInfoLib: Add Dxe lib to dynamically parse heterogenous data Ojeda Leon, Nicolas
2022-04-25 21:43 ` [PATCH v5 4/5] Ovmf/PlatformPei: Use host-provided GPA end if available Ojeda Leon, Nicolas
2022-04-29 10:18   ` [edk2-devel] " Gerd Hoffmann
2022-05-13  8:45     ` Ojeda Leon, Nicolas
2022-05-27 13:05       ` Ojeda Leon, Nicolas
2022-06-01  8:46         ` Gerd Hoffmann
2022-04-25 21:43 ` [PATCH v5 5/5] OvmfPkg/PciHostBridgeUtilityLib: Initialize RootBridges apertures with spec Ojeda Leon, Nicolas

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4fb5befbbeca65d9fc1a66dbaa446b853570fe10.1650918674.git.ncoleon@amazon.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox