From nobody Sun Apr 28 21:49:04 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+85872+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+85872+1787277+3901457@groups.io ARC-Seal: i=1; a=rsa-sha256; t=1642702647; cv=none; d=zohomail.com; s=zohoarc; b=Tieuqy3gOW6ADNucZ+qPvJtmIAatyKhq68JZhHC6oAbGgjqGJ5XFlnf4hXRJ8dD5XFJnHvIwcyinuLHARGd/NZeAj1ZlMUArONVdXAZDB8m5SkUAygYG4OJyGYYMvNUdccTc3af1uMHCgOVg4BZ7WIjsIERaYFQaygsygxs33BY= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1642702647; h=Content-Type:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=kjSXbEzsXqosRnoj5G6mGr0akMS1akiqWbphLNoHkUM=; b=EzmHiFANcqaNDBCTbK3YnOF67ZxnrSws5lvYWkKqJymgAJdWxYZEgy2oXFGL7Qrobg/BGbJ6vV0/3fwpoX3hPBJBhi5qN0Hs2s5rulhEfTdClCsbP7QG0w420P9xMHluVqfUM0bqjoIhT/+k6QPK4mP6IU6+XhclfcaAMi+gOc0= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+85872+1787277+3901457@groups.io Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 164270264732492.59166789121787; Thu, 20 Jan 2022 10:17:27 -0800 (PST) Return-Path: X-Received: by 127.0.0.2 with SMTP id s6o0YY1788612xRriikZc6ou; Thu, 20 Jan 2022 10:17:27 -0800 X-Received: from smtp-fw-9102.amazon.com (smtp-fw-9102.amazon.com [207.171.184.29]) by mx.groups.io with SMTP id smtpd.web12.14811.1642698720551950964 for ; Thu, 20 Jan 2022 09:12:00 -0800 X-IronPort-AV: E=Sophos;i="5.88,302,1635206400"; d="scan'208";a="188682609" X-Received: from pdx4-co-svc-p1-lb2-vlan3.amazon.com (HELO email-inbound-relay-iad-1e-98691110.us-east-1.amazon.com) ([10.25.36.214]) by smtp-border-fw-9102.sea19.amazon.com with ESMTP; 20 Jan 2022 17:11:46 +0000 X-Received: from EX13D49EUC003.ant.amazon.com (iad12-ws-svc-p26-lb9-vlan3.iad.amazon.com [10.40.163.38]) by email-inbound-relay-iad-1e-98691110.us-east-1.amazon.com (Postfix) with ESMTPS id 97EAF80394; Thu, 20 Jan 2022 17:11:44 +0000 (UTC) X-Received: from ub4014a598e6c52.ant.amazon.com (10.43.162.8) by EX13D49EUC003.ant.amazon.com (10.43.164.91) with Microsoft SMTP Server (TLS) id 15.0.1497.28; Thu, 20 Jan 2022 17:11:41 +0000 From: "Ojeda Leon, Nicolas via groups.io" To: CC: , Nicolas Ojeda Leon , Alexander Graf , Gerd Hoffmann Subject: [edk2-devel] [PATCH v2 1/8] OvmfPkg/Library: Create base HardwareInfoLib for PCI Host Bridges Date: Thu, 20 Jan 2022 18:10:14 +0100 Message-ID: In-Reply-To: References: MIME-Version: 1.0 X-Originating-IP: [10.43.162.8] X-ClientProxiedBy: EX13D12UWA004.ant.amazon.com (10.43.160.168) To EX13D49EUC003.ant.amazon.com (10.43.164.91) Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,ncoleon@amazon.com X-Gm-Message-State: 0ImAWkwiKOiH5bygNYcaYN6nx1787277AA= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1642702647; bh=QPCI2rDKebeDTP9Jnf+UixEb3DnZVO59xXN1TcU6d90=; h=CC:Content-Type:Date:From:Reply-To:Subject:To; b=nSnCTRx4U75vHJEMGGyhlt9PAU/j47YsvYujN+gcGzJ4yKnca0n0QCfKC4CWdOBZ6XM sFcDsrnvaMJLLvx7ZoF7YowiZAf1LmeQr6PMEI0FYbJcQHW7qSTQ2wEm2hQbMUl4HF2y6 0cL382zalmYcTdPQMz1KOA4tbhSL4Bdf4FI= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1642702648728100015 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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 Cc: Gerd Hoffmann Signed-off-by: Nicolas Ojeda Leon Acked-by: Gerd Hoffmann --- .../HardwareInfoPciHostBridgeLib.c | 515 ++++++++++++++++++ .../HardwareInfoPciHostBridgeLib.h | 262 +++++++++ .../HardwareInfoLib/HardwareInfoTypesLib.h | 64 +++ 3 files changed, 841 insertions(+) create mode 100644 OvmfPkg/Library/HardwareInfoLib/HardwareInfoPciHostBrid= geLib.c create mode 100644 OvmfPkg/Library/HardwareInfoLib/HardwareInfoPciHostBrid= geLib.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..ef72d4a95c --- /dev/null +++ b/OvmfPkg/Library/HardwareInfoLib/HardwareInfoPciHostBridgeLib.c @@ -0,0 +1,515 @@ +/**@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 BS= D License + which accompanies this distribution. The full text of the license may b= e 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 IMP= LIED. + **/ + +#include + +#include "HardwareInfoPciHostBridgeLib.h" + +#define IS_RANGE_INVALID(Start, Size, MaxValue) (Start >=3D MaxValue || S= ize =3D=3D 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 =3D 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 =3D=3D 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 =3D 0; + + Status =3D 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 ( + IN UINT64 MaxValue, + OUT PCI_ROOT_BRIDGE_APERTURE *Aperture + ) +{ + if (Aperture =3D=3D NULL) { + return; + } + + Aperture->Base =3D MaxValue; + Aperture->Limit =3D 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 =3D GetRangeEnd (Start, Size, MaxValue); + + if (Aperture =3D=3D 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 (MaxValue, Aperture); + } else { + Aperture->Base =3D Start; + Aperture->Limit =3D 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 =3D=3D 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 (MaxValue, Aperture); + + if (!IS_RANGE_INVALID (Start, Size, MaxValue)) { + Aperture->Base =3D Start; + Aperture->Limit =3D Start + Size - 1; + } + + if (!IS_RANGE_INVALID (PStart, PSize, MaxValue)) { + PEnd =3D PStart + PSize - 1; + + if (PStart < Aperture->Base) { + Aperture->Base =3D PStart; + } + + if (PEnd > Aperture->Limit) { + Aperture->Limit =3D PEnd; + } + } + + return EFI_SUCCESS; +} + +EFI_STATUS +HardwareInfoPciHostBridgeGetBusNrRange ( + IN CONST HOST_BRIDGE_INFO *HostBridge, + IN UINTN DataSize, + OUT UINTN *BusNrStart, + OUT UINTN *BusNrLast + ) +{ + if ((HostBridge =3D=3D NULL) || (DataSize =3D=3D 0) || + (BusNrStart =3D=3D NULL) || (BusNrLast =3D=3D NULL)) + { + return EFI_INVALID_PARAMETER; + } + + // + // For now only version 0 is supported + // + if (HostBridge->Version !=3D 0) { + return EFI_INCOMPATIBLE_VERSION; + } + + *BusNrStart =3D HostBridge->BusNrStart; + *BusNrLast =3D 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 =3D FALSE; + if ((HostBridge =3D=3D NULL) || (DataSize =3D=3D 0)) { + return EFI_INVALID_PARAMETER; + } + + // + // For now only version 0 is supported + // + if (HostBridge->Version !=3D 0) { + return EFI_INCOMPATIBLE_VERSION; + } + + Status =3D FillHostBridgeAperture ( + HostBridge->IoStart, + HostBridge->IoSize, + MAX_UINT32, + Io + ); + StickyError |=3D EFI_ERROR (Status); + + Status =3D FillHostBridgeAperture ( + HostBridge->PcieConfigStart, + HostBridge->PcieConfigSize, + MAX_UINT64, + PcieConfig + ); + StickyError |=3D EFI_ERROR (Status); + + if (HostBridge->Flags.Bits.CombineMemPMem) { + Status =3D MergeHostBridgeApertures ( + HostBridge->MemStart, + HostBridge->MemSize, + HostBridge->PMemStart, + HostBridge->PMemSize, + MAX_UINT32, + Mem + ); + StickyError |=3D EFI_ERROR (Status); + + Status =3D MergeHostBridgeApertures ( + HostBridge->MemAbove4GStart, + HostBridge->MemAbove4GSize, + HostBridge->PMemAbove4GStart, + HostBridge->PMemAbove4GSize, + MAX_UINT64, + MemAbove4G + ); + StickyError |=3D EFI_ERROR (Status); + + // + // Invalidate unused apertures + // + InvalidateRootBridgeAperture (MAX_UINT32, PMem); + InvalidateRootBridgeAperture (MAX_UINT64, PMemAbove4G); + } else { + Status =3D FillHostBridgeAperture ( + HostBridge->MemStart, + HostBridge->MemSize, + MAX_UINT32, + Mem + ); + StickyError |=3D EFI_ERROR (Status); + + Status =3D FillHostBridgeAperture ( + HostBridge->PMemStart, + HostBridge->PMemSize, + MAX_UINT32, + PMem + ); + StickyError |=3D EFI_ERROR (Status); + + Status =3D FillHostBridgeAperture ( + HostBridge->MemAbove4GStart, + HostBridge->MemAbove4GSize, + MAX_UINT64, + MemAbove4G + ); + StickyError |=3D EFI_ERROR (Status); + + Status =3D FillHostBridgeAperture ( + HostBridge->PMemAbove4GStart, + HostBridge->PMemAbove4GSize, + MAX_UINT64, + PMem + ); + StickyError |=3D 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 =3D=3D NULL) || (DataSize =3D=3D 0)) { + return EFI_INVALID_PARAMETER; + } + + // + // For now only version 0 is supported + // + if (HostBridge->Version !=3D 0) { + return EFI_INCOMPATIBLE_VERSION; + } + + if (Attributes) { + *Attributes =3D HostBridge->Attributes; + } + + if (DmaAbove4G) { + *DmaAbove4G =3D !!HostBridge->Flags.Bits.DmaAbove4G; + } + + if (NoExtendedConfigSpace) { + *NoExtendedConfigSpace =3D !!HostBridge->Flags.Bits.NoExtendedConfigSp= ace; + } + + if (CombineMemPMem) { + *CombineMemPMem =3D !!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 =3D HardwareInfoPciHostBridgeGetBusNrRange ( + HostBridge, + DataSize, + BusNrStart, + BusNrLast + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + Status =3D HardwareInfoPciHostBridgeGetFlags ( + HostBridge, + DataSize, + Attributes, + DmaAbove4G, + NoExtendedConfigSpace, + CombineMemPMem + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + Status =3D 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 BS= D License + which accompanies this distribution. The full text of the license may b= e 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 IMP= LIED. + **/ + +#ifndef __HARDWARE_INFO_PCI_HOST_BRIDGE_LIB_H__ +#define __HARDWARE_INFO_PCI_HOST_BRIDGE_LIB_H__ + +#include +#include +#include + +// +// 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 (EC= AM) + + @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 correspond= ing + 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 f= lag + @param[out] CombineMemPMem Pointer to the Combine Mem and PMem fl= ag + + @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 f= lag + @param[out] CombineMemPMem Pointer to the Combine Mem and PMem fl= ag + @param[out] Io Pointer to the PIO aperture object + @param[out] Mem Pointer to the 32-bit MMIO aperture ob= ject + @param[out] MemAbove4G Pointer to the 64-bit MMIO aperture ob= ject + @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 belong= s to + and unsupported version + @retval EFI_WARN_STALE_DATA One or more apertures having valid ran= ges + in the HostBridge info were ignored be= cause + the correspnding aperture pointer is N= ULL +**/ +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/OvmfP= kg/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 BS= D License + which accompanies this distribution. The full text of the license may b= e 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 IMP= LIED. + **/ + +#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 =3D 0, + HardwareInfoTypeHostBridge =3D 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__ --=20 2.17.1 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 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#85872): https://edk2.groups.io/g/devel/message/85872 Mute This Topic: https://groups.io/mt/88565403/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Sun Apr 28 21:49:04 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+85873+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+85873+1787277+3901457@groups.io ARC-Seal: i=1; a=rsa-sha256; t=1642702648; cv=none; d=zohomail.com; s=zohoarc; b=Wp8qatlFtfoV/XNAaP2pYa6kbbWM2HuEAxqJUdQKEaWgep1BTzWBnsyyafoqNj4fAdES0n2bfB1Jqv9BPRK3tF9QteOLiHdFykNgKRIGG+Kb/Ik5sk7M9/w+1hqlSSs/SCNA+ztkH5i7LcpXXQgdKJiEW3mSSAeGgclutvYNnDs= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1642702648; h=Content-Type:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=cUkKVdcER/Gd9l7YLzx0yYqtYkq19vGATrKXd8WTzYQ=; b=Fj6Yba5212vzpQzn58RWJ7PTeZtx/bKqL/vFf5Vpy5DuutPISwN9pbgVELbecO9OB3ZgbSFBj4Xh7L0kp0VZ9ZmDsZR4wfQ7Y0kPrbRPBPyn5OxE2xvHFrMOvMQdQxIqHocIbnQ9m3liVzv1Qj6S3nh4V2k+LjLzJeiloy+nR18= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+85873+1787277+3901457@groups.io Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1642702648011120.04650785363515; Thu, 20 Jan 2022 10:17:28 -0800 (PST) Return-Path: X-Received: by 127.0.0.2 with SMTP id q2IpYY1788612xtMeSWBGrME; Thu, 20 Jan 2022 10:17:27 -0800 X-Received: from smtp-fw-80007.amazon.com (smtp-fw-80007.amazon.com [99.78.197.218]) by mx.groups.io with SMTP id smtpd.web12.14816.1642698741432010893 for ; Thu, 20 Jan 2022 09:12:21 -0800 X-IronPort-AV: E=Sophos;i="5.88,302,1635206400"; d="scan'208";a="56749850" X-Received: from pdx4-co-svc-p1-lb2-vlan2.amazon.com (HELO email-inbound-relay-iad-1e-90d70b14.us-east-1.amazon.com) ([10.25.36.210]) by smtp-border-fw-80007.pdx80.corp.amazon.com with ESMTP; 20 Jan 2022 17:12:04 +0000 X-Received: from EX13D49EUC003.ant.amazon.com (iad12-ws-svc-p26-lb9-vlan3.iad.amazon.com [10.40.163.38]) by email-inbound-relay-iad-1e-90d70b14.us-east-1.amazon.com (Postfix) with ESMTPS id 755ADC08CF; Thu, 20 Jan 2022 17:12:02 +0000 (UTC) X-Received: from ub4014a598e6c52.ant.amazon.com (10.43.162.8) by EX13D49EUC003.ant.amazon.com (10.43.164.91) with Microsoft SMTP Server (TLS) id 15.0.1497.28; Thu, 20 Jan 2022 17:11:59 +0000 From: "Ojeda Leon, Nicolas via groups.io" To: CC: , Nicolas Ojeda Leon , Alexander Graf , Gerd Hoffmann Subject: [edk2-devel] [PATCH v2 2/8] Ovmf/HardwareInfoLib: Parse data directly from fw-cfg Date: Thu, 20 Jan 2022 18:10:15 +0100 Message-ID: <66b045d70f81c8e1a01269a13e55c5b47b7898c5.1642697671.git.ncoleon@amazon.com> In-Reply-To: References: MIME-Version: 1.0 X-Originating-IP: [10.43.162.8] X-ClientProxiedBy: EX13D12UWA004.ant.amazon.com (10.43.160.168) To EX13D49EUC003.ant.amazon.com (10.43.164.91) Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,ncoleon@amazon.com X-Gm-Message-State: GDGnc7UcqjcNWwFLa8lBjIk9x1787277AA= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1642702647; bh=bGkTD0M4LdhkSNejPyreQpa8+aXLaAZ5459GLgDqo2U=; h=CC:Content-Type:Date:From:Reply-To:Subject:To; b=PLKgx4exhCD7FuMMs2aLvox54evnkAqRkhdcE/6YxVr47n6kBS5uf2BX9FPJzFVHYSz NsD7Okf1V+n9yu/DWdbSuEmFITqqkhtvQdSzS3+aSUzh8wAQkC7C0uUXBB/HeVFitFOtH mnJhbSosrG6SlnYALiEHtsVqsz+upPu+kRs= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1642702648913100020 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Create QemuFwCfgHardwareInfoLib which extends the base HardwareInfoLib and provide fw-cfg wrappers to read hardware info elements out of a fw-cfg file. The Hardware Info library is intended to describe non-discoverable hardware information and share that from the host to the guest in Ovmf platforms. The QEMU fw-cfg extension for this library provides a first variation to parse hardware info by reading it directly from a fw-cfg file. This library offers a wrapper function to the plain QmeuFwCfgReadBytes which, specifically, parses header-data pairs out of the binary values in the file. For this purpose, the approach is incremental, reading the file block by block and outputting the values only for a specific known hardware type (e.g. PCI host bridges). One element is returned in each call until the end of the file is reached. Considering fw-cfg as the first means to transport hardware info from the host to the guest, this wrapping library offers the possibility to statically, and in steps, read a specific type of hardware info elements out of the file. This method reads one hardware element of a specific type at a time, without the need to pre-allocate memory and read the whole file or dynamically allocate memory for each new element found. As a usage example, the static approach followed by this library enables early UEFI stages to use and read hardware information supplied by the host. For instance, in early times of the PEI stage, hardware information can be parsed out from a fw-cfg file prescinding from memory services, that may not yet be available, and avoiding dynamic memory allocations. Cc: Alexander Graf Cc: Gerd Hoffmann Signed-off-by: Nicolas Ojeda Leon --- .../Library/QemuFwCfgHardwareInfoLib.h | 59 ++++++++++++ .../QemuFwCfgHardwareInfoLib.c | 89 +++++++++++++++++++ .../QemuFwCfgHardwareInfoLib.inf | 42 +++++++++ OvmfPkg/OvmfPkgX64.dsc | 1 + 4 files changed, 191 insertions(+) create mode 100644 OvmfPkg/Include/Library/QemuFwCfgHardwareInfoLib.h create mode 100644 OvmfPkg/Library/HardwareInfoLib/QemuFwCfgHardwareInfoLi= b.c create mode 100644 OvmfPkg/Library/HardwareInfoLib/QemuFwCfgHardwareInfoLi= b.inf diff --git a/OvmfPkg/Include/Library/QemuFwCfgHardwareInfoLib.h b/OvmfPkg/I= nclude/Library/QemuFwCfgHardwareInfoLib.h new file mode 100644 index 0000000000..f6c351a4e4 --- /dev/null +++ b/OvmfPkg/Include/Library/QemuFwCfgHardwareInfoLib.h @@ -0,0 +1,59 @@ +/*/@file + Qemu fw-cfg wrappers for hardware info parsing. + Provides an alternative to parse hardware information from a fw-cfg + file without relying on dynamic memory allocations. + + 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 BS= D License + which accompanies this distribution. The full text of the license may b= e 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 IMP= LIED. +**/ + +#ifndef __QEMU_FW_CFG_HARDWARE_INFO_LIB_H__ +#define __QEMU_FW_CFG_HARDWARE_INFO_LIB_H__ + +#include "../Library/HardwareInfoLib/HardwareInfoTypesLib.h" + +/** + Read, if available, the next Type element in the FwCfg file. + The FwCfg item must already be selected, this is a wrapper around + QemuFwCfgReadBytes and the Data pointer should be set to an existent + memory location with TypeSize bytes allocated for the date to be + properly written. If a Type element is found in the file which has a + size (in the header) greater than TypeSize, it is skipped. + + @param[in] Type Hardware Info Type to search for + @param[in] TypeSize Size (in bytes) of the structure intended= to + be used to dereference the data + @param[in] TotalFileSize Total size (in bytes) of the FwCfg file f= rom + which the data is read. + @param[out] Data Pointer to a memory allocated instance in= to + which the data is written to. + @param[out] DataSize Size in bytes of the actually filled + data available in the Data object after a + successful operation + @param[inout] ReadIndex Index of the next byte to be read. Increm= ented + accordingly after a read operation to ref= lect + up to date status + + @retval EFI_SUCCESS Next element found and read into Data + @retval EFI_INVALID_PARAMETER Operation failed + @retval EFI_END_OF_FILE End of the file reached, no more elements + to read. +**/ +EFI_STATUS +QemuFwCfgReadNextHardwareInfoByType ( + IN HARDWARE_INFO_TYPE Type, + IN UINTN TypeSize, + IN UINTN TotalFileSize, + OUT VOID *Data, + OUT UINTN *DataSize OPTIONAL, + IN OUT UINTN *ReadIndex + ); + +#endif // __QEMU_FW_CFG_HARDWARE_INFO_LIB_H__ diff --git a/OvmfPkg/Library/HardwareInfoLib/QemuFwCfgHardwareInfoLib.c b/O= vmfPkg/Library/HardwareInfoLib/QemuFwCfgHardwareInfoLib.c new file mode 100644 index 0000000000..059da546d1 --- /dev/null +++ b/OvmfPkg/Library/HardwareInfoLib/QemuFwCfgHardwareInfoLib.c @@ -0,0 +1,89 @@ +/*/@file + Qemu fw-cfg wrappers for hardware info parsing. + Provides an alternative to parse hardware information from a fw-cfg + file without relying on dynamic memory allocations. + + 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 BS= D License + which accompanies this distribution. The full text of the license may b= e 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 IMP= LIED. +**/ + +#include +#include + +#include + +/** + Update an optional pointer value if possible + + @param[out] DataSize Pointer to variable to be updated + @param[in] Value Value to set the pointed variable to. +**/ +STATIC +VOID +UpdateDataSize ( + OUT UINTN *DataSize, + IN UINTN Value + ) +{ + if (DataSize =3D=3D NULL) { + return; + } + + *DataSize =3D Value; +} + +EFI_STATUS +QemuFwCfgReadNextHardwareInfoByType ( + IN HARDWARE_INFO_TYPE Type, + IN UINTN TypeSize, + IN UINTN TotalFileSize, + OUT VOID *Data, + OUT UINTN *DataSize OPTIONAL, + IN OUT UINTN *ReadIndex + ) +{ + HARDWARE_INFO_HEADER Header; + + if ((Data =3D=3D NULL) || + (ReadIndex =3D=3D NULL) || + (TypeSize =3D=3D 0) || + (Type =3D=3D HardwareInfoTypeUndefined) || + (TotalFileSize =3D=3D 0)) + { + return EFI_INVALID_PARAMETER; + } + + UpdateDataSize (DataSize, 0); + + while (*ReadIndex < TotalFileSize) { + QemuFwCfgReadBytes (sizeof (Header), &Header); + *ReadIndex +=3D sizeof (Header); + + if ((Header.Type.Value =3D=3D Type) && (Header.Size <=3D TypeSize)) { + QemuFwCfgReadBytes (Header.Size, Data); + + *ReadIndex +=3D Header.Size; + UpdateDataSize (DataSize, Header.Size); + + return EFI_SUCCESS; + } + + // + // Skip the bytes corresponding to the next element as it is + // not of the expected type and/or size. The TotalFileSize + // and individual elements sizes should match so the size + // check is skipped. + // + QemuFwCfgSkipBytes (Header.Size); + *ReadIndex +=3D Header.Size; + } + + return EFI_END_OF_FILE; +} diff --git a/OvmfPkg/Library/HardwareInfoLib/QemuFwCfgHardwareInfoLib.inf b= /OvmfPkg/Library/HardwareInfoLib/QemuFwCfgHardwareInfoLib.inf new file mode 100644 index 0000000000..0a2eca3c00 --- /dev/null +++ b/OvmfPkg/Library/HardwareInfoLib/QemuFwCfgHardwareInfoLib.inf @@ -0,0 +1,42 @@ +## @file +# Hardware information library wrappers over Qemu fw-cfg functionality to= parse, +# in a static manner, non-discoverable hardware information. +# +# 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 B= SD 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 IM= PLIED. +# +## + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D QemuFwCfgHardwareInfoLib + FILE_GUID =3D 3D5011B3-9CBB-4C0B-88E8-1D758283C659 + MODULE_TYPE =3D BASE + VERSION_STRING =3D 1.0 + LIBRARY_CLASS =3D QemuFwCfgHardwareInfoLib + +# +# The following information is for reference only and not required by the = build +# tools. +# +# VALID_ARCHITECTURES =3D X64 +# + +[Sources] + QemuFwCfgHardwareInfoLib.c + HardwareInfoPciHostBridgeLib.c + +[Packages] + MdeModulePkg/MdeModulePkg.dec + MdePkg/MdePkg.dec + OvmfPkg/OvmfPkg.dec + +[LibraryClasses] + DebugLib + QemuFwCfgLib diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc index 4589adff38..fb82fd02eb 100644 --- a/OvmfPkg/OvmfPkgX64.dsc +++ b/OvmfPkg/OvmfPkgX64.dsc @@ -175,6 +175,7 @@ SecurityManagementLib|MdeModulePkg/Library/DxeSecurityManagementLib/DxeS= ecurityManagementLib.inf UefiUsbLib|MdePkg/Library/UefiUsbLib/UefiUsbLib.inf SerializeVariablesLib|OvmfPkg/Library/SerializeVariablesLib/SerializeVar= iablesLib.inf + QemuFwCfgHardwareInfoLib|OvmfPkg/Library/HardwareInfoLib/QemuFwCfgHardwa= reInfoLib.inf QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxeLib.inf QemuFwCfgSimpleParserLib|OvmfPkg/Library/QemuFwCfgSimpleParserLib/QemuFw= CfgSimpleParserLib.inf VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf --=20 2.17.1 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 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#85873): https://edk2.groups.io/g/devel/message/85873 Mute This Topic: https://groups.io/mt/88565404/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Sun Apr 28 21:49:04 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+85875+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+85875+1787277+3901457@groups.io ARC-Seal: i=1; a=rsa-sha256; t=1642702649; cv=none; d=zohomail.com; s=zohoarc; b=hkB23cLHaDqFDDrA3ckMbc7Mm8LNxYgtwkjiBq9EhmYBZgegMHa5s/iUr8WWcVPEgaPOFrq+1Mm9tquRV4EvelyiWmiXXvEPqhNw7C0egRPrTFInK7fD/9krau3tlp0XUgOyGic0QxF3B9/93+KtzfhxhaBtu527d11RfM9+E9E= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1642702649; h=Content-Type:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=li9z4vtIbZH4x9FwLaXCCXJIVbuhZIvW+xmtQMXGhTQ=; b=eWE+aBvy4ghbjpQF55/v7MiqbdtstkZdQ5EN0YBuncEBeV+WGtXPS31g55ZqE+kQ2eM7yLlUGzSR2YsXKoteGwoaiSqBNaos8X9znjrVCAAnTPp3UAttic5fbRVlksoTlCsK9u1lRqJYeFOyNw9/iW61AXb4iFVkWzmA/OsJoH8= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+85875+1787277+3901457@groups.io Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1642702649469269.8142122074547; Thu, 20 Jan 2022 10:17:29 -0800 (PST) Return-Path: X-Received: by 127.0.0.2 with SMTP id lyMNYY1788612xIzEbA2aBcD; Thu, 20 Jan 2022 10:17:29 -0800 X-Received: from smtp-fw-80006.amazon.com (smtp-fw-80006.amazon.com [99.78.197.217]) by mx.groups.io with SMTP id smtpd.web10.15136.1642698761974239638 for ; Thu, 20 Jan 2022 09:12:42 -0800 X-IronPort-AV: E=Sophos;i="5.88,302,1635206400"; d="scan'208";a="56730464" X-Received: from pdx4-co-svc-p1-lb2-vlan3.amazon.com (HELO email-inbound-relay-iad-1e-204be258.us-east-1.amazon.com) ([10.25.36.214]) by smtp-border-fw-80006.pdx80.corp.amazon.com with ESMTP; 20 Jan 2022 17:12:28 +0000 X-Received: from EX13D49EUC003.ant.amazon.com (iad12-ws-svc-p26-lb9-vlan2.iad.amazon.com [10.40.163.34]) by email-inbound-relay-iad-1e-204be258.us-east-1.amazon.com (Postfix) with ESMTPS id 6477E41597; Thu, 20 Jan 2022 17:12:26 +0000 (UTC) X-Received: from ub4014a598e6c52.ant.amazon.com (10.43.162.8) by EX13D49EUC003.ant.amazon.com (10.43.164.91) with Microsoft SMTP Server (TLS) id 15.0.1497.28; Thu, 20 Jan 2022 17:12:23 +0000 From: "Ojeda Leon, Nicolas via groups.io" To: CC: , Nicolas Ojeda Leon , Alexander Graf , Gerd Hoffmann Subject: [edk2-devel] [PATCH v2 3/8] Ovmf/HardwareInfoLib: Add core to parse heterogenous data Date: Thu, 20 Jan 2022 18:10:16 +0100 Message-ID: In-Reply-To: References: MIME-Version: 1.0 X-Originating-IP: [10.43.162.8] X-ClientProxiedBy: EX13D12UWA004.ant.amazon.com (10.43.160.168) To EX13D49EUC003.ant.amazon.com (10.43.164.91) Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,ncoleon@amazon.com X-Gm-Message-State: RgKmbtl4phLGw9iXjaJjFPeQx1787277AA= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1642702649; bh=sJ1PSRNTJpmKEhVlw7f45bzm7xPm9ZVQUxZ5muDwVoo=; h=CC:Content-Type:Date:From:Reply-To:Subject:To; b=diAVLCJ17RUaj2TaBPIYCH3AYYlfnMFDKxgZiWITpEroZDLkk5PUK7Glb7X7IV87Dtn H6T/6FnFVrFyXgmk74OHRQeetXlLSjMtA0b72lJ8gixnOcKXkU7Qmgu9vNebiB59UewLR AfbbxcoK+XVkzxHVR1bLrrCXPwTtIDDWk+A= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1642702651382100006 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Following the Hardware Info library, this commit extends the base lib and the static parsing methods to the generic, and thus the core of the library, approach, capable of parsing heterogeneous hardware information. The list-like API grants callers a flexible and common pattern to retrieve the data. Moreover, the initial source is a BLOB which generalizes the host-to-guest transmission mechanism. The Hardware Info library main objective is to provide a way to describe non-discoverable hardware so that the host can share the available resources with the guest in Ovmf platforms. This change features and embraces the main idea behind the library by providing an API that parses a BLOB into a linked list to retrieve hardware data from any source. Additionally, list-like APIs are provided so that the hardware info list can be traversed conveniently. Similarly, the capability is provided to filter results by specific hardware types. However, heterogeneous elements can be added to the list, increasing the flexibility. This way, a single source, for example a fw-cfg file, can be used to describe several instances of multiple types of hardware. This part of the Hardware Info library makes use of dynamic memory and is intended for stages in which memory services are available. A motivation example is the PciHostBridgeLib. This library, part of the PCI driver populates the list of PCI root bridges during DXE stage for future steps to discover the resources under them. The hardware info library can be used to obtain the detailed description of available host bridges, for instance in the form of a fw-cfg file, and parse that information into a dynmaic list that allows, first to verify consistency of the data, and second discover the resources availabe for each root bridge. Cc: Alexander Graf Cc: Gerd Hoffmann Signed-off-by: Nicolas Ojeda Leon --- OvmfPkg/Include/Library/HardwareInfoLib.h | 128 +++++++++ .../Library/HardwareInfoLib/HardwareInfoLib.c | 256 ++++++++++++++++++ .../HardwareInfoLib/HardwareInfoLib.inf | 43 +++ OvmfPkg/OvmfPkgX64.dsc | 1 + 4 files changed, 428 insertions(+) create mode 100644 OvmfPkg/Include/Library/HardwareInfoLib.h create mode 100644 OvmfPkg/Library/HardwareInfoLib/HardwareInfoLib.c create mode 100644 OvmfPkg/Library/HardwareInfoLib/HardwareInfoLib.inf diff --git a/OvmfPkg/Include/Library/HardwareInfoLib.h b/OvmfPkg/Include/Li= brary/HardwareInfoLib.h new file mode 100644 index 0000000000..dc7f209b09 --- /dev/null +++ b/OvmfPkg/Include/Library/HardwareInfoLib.h @@ -0,0 +1,128 @@ +/*/@file + Hardware info parsing functions. + Binary data is expected as a consecutive series of header - object pairs. + Complete library providing static Qemu fw-cfg wrappers as well as list-l= ike + interface to dynamically manipulate hardware info objects and parsing fr= om + a generic blob. + + 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 BS= D License + which accompanies this distribution. The full text of the license may b= e 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 IMP= LIED. +**/ + +#ifndef __HARDWARE_INFO_LIB_H__ +#define __HARDWARE_INFO_LIB_H__ + +#include "QemuFwCfgHardwareInfoLib.h" + +/** + Parse binary data containing resource information of multiple hardware + elements into a list of interpreted resources. + The translation is done on a copy-parse base so the blob can be freed + afterwards. + + @param[in] Blob Binary data to be parsed + @param[in] BlobSize Size (in bytes) of the binary data + @param[in] TypeFilter Optional type to filter entries. Set to + undefined to disable filtering and retrieve a= ll + @param[out] ListHead Head of the list to populate hardware informa= tion + + @retval EFI_SUCCESS Succeed. + @retval EFI_INVALID_PARAMETER Provided Blob inforation is invalid + @retval EFI_OUT_OF_RESOURCES Out of memory, list populated as far as + possible +**/ +EFI_STATUS +CreateHardwareInfoList ( + IN UINT8 *Blob, + IN UINTN BlobSize, + IN HARDWARE_INFO_TYPE TypeFilter, + OUT LIST_ENTRY *ListHead + ); + +/** + Free the dynamically allocated list of HADWARE_INFO items populated + during parsing of Blob + + @param ListHead Head of the list to be destroyed +**/ +VOID +FreeHardwareInfoList ( + IN OUT LIST_ENTRY *ListHead + ); + +/** + Retrieve the number of hardware components of a specific type + in the list. + + @param[in] ListHead Head of the hardware info list + @param[in] Type Type of hardware elements to count + @param[in] TypeSize Size (in bytes) of the structure intended to + be used to dereference the data + @return Count of elements of Type found +**/ +UINTN +GetHardwareInfoCountByType ( + IN LIST_ENTRY *ListHead, + IN HARDWARE_INFO_TYPE Type, + IN UINTN TypeSize + ); + +/** + Get the First Hardware Info entry in the list of the specified type + + @param[in] ListHead Head of the hardware info list + @param[in] Type Hardware Info Type to search for + @param[in] TypeSize Size (in bytes) of the structure intended to + be used to dereference the data + @return Link of first entry of specified type or list head if not found +**/ +LIST_ENTRY * +GetFirstHardwareInfoByType ( + IN LIST_ENTRY *ListHead, + IN HARDWARE_INFO_TYPE Type, + IN UINTN TypeSize + ); + +/** + Get the Next Hardware Info entry in the list with the specified + type, which follows the provided Node. + + @param[in] ListHead Head of the hardware info list + @param[in] Node Current, already processed, node's link + @param[in] Type Hardware Info Type to search for + @param[in] TypeSize Size (in bytes) of the structure intended to + be used to dereference the data + @return Link of next entry, after Node, of the specified type. + List head otherwise +**/ +LIST_ENTRY * +GetNextHardwareInfoByType ( + IN LIST_ENTRY *ListHead, + IN LIST_ENTRY *Node, + IN HARDWARE_INFO_TYPE Type, + IN UINTN TypeSize + ); + +/** + Assess if Node stands at the end of the doubly linked list + + @param[in] ListHead Head of the hardware info list + @param[in] Node Current Node link + + @retval TRUE Node is at the end of the list + @retval FALSE Node is not at the end of the list +**/ +BOOLEAN +EndOfHardwareInfoList ( + IN LIST_ENTRY *ListHead, + IN LIST_ENTRY *Node + ); + +#endif // __HARDWARE_INFO_LIB_H__ diff --git a/OvmfPkg/Library/HardwareInfoLib/HardwareInfoLib.c b/OvmfPkg/Li= brary/HardwareInfoLib/HardwareInfoLib.c new file mode 100644 index 0000000000..5136c55031 --- /dev/null +++ b/OvmfPkg/Library/HardwareInfoLib/HardwareInfoLib.c @@ -0,0 +1,256 @@ +/*/@file + Hardware info parsing functions. + Binary data is expected as a consecutive series of header - object pairs. + Complete library providing static Qemu fw-cfg wrappers as well as list-l= ike + interface to dynamically manipulate hardware info objects and parsing fr= om + a generic blob. + + 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 BS= D License + which accompanies this distribution. The full text of the license may b= e 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 IMP= LIED. +**/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +EFI_STATUS +CreateHardwareInfoList ( + IN UINT8 *Blob, + IN UINTN BlobSize, + IN HARDWARE_INFO_TYPE TypeFilter, + OUT LIST_ENTRY *ListHead + ) +{ + UINT8 *Index; + HARDWARE_INFO *HwComponent; + + if ((Blob =3D=3D NULL) || (BlobSize <=3D 0) || + (ListHead =3D=3D NULL)) + { + return EFI_INVALID_PARAMETER; + } + + Index =3D Blob; + while (Index < (Blob + BlobSize)) { + HwComponent =3D AllocateZeroPool (sizeof (HARDWARE_INFO)); + + if (HwComponent =3D=3D NULL) { + goto FailedAllocate; + } + + HwComponent->Header.Type.Uint64 =3D *((UINT64 *)Index); + Index +=3D sizeof (HwComponent->Header.Type); + HwComponent->Header.Size =3D *((UINT64 *)(Index)); + Index +=3D sizeof (HwComponent->Header.Size); + + // + // Check if optional TypeFilter is set, skip if the current + // object is of a different type and release the partially + // allocated object + // + if ((TypeFilter !=3D HardwareInfoTypeUndefined) && + (HwComponent->Header.Type.Value !=3D TypeFilter)) + { + FreePool (HwComponent); + Index +=3D HwComponent->Header.Size; + continue; + } + + HwComponent->Data.Raw =3D AllocateZeroPool (HwComponent->Header.Size); + if (HwComponent->Data.Raw =3D=3D NULL) { + goto FreeResources; + } + + CopyMem (HwComponent->Data.Raw, Index, HwComponent->Header.Size); + Index +=3D HwComponent->Header.Size; + + InsertTailList (ListHead, &HwComponent->Link); + } + + return EFI_SUCCESS; + +FreeResources: + // + // Clean the resources allocated in the incomplete cycle + // + FreePool (HwComponent); + +FailedAllocate: + DEBUG (( + EFI_D_ERROR, + "%a: Failed to allocate memory for hardware info\n", + __FUNCTION__ + )); + + return EFI_OUT_OF_RESOURCES; +} + +VOID +FreeHardwareInfoList ( + IN OUT LIST_ENTRY *ListHead + ) +{ + LIST_ENTRY *CurrentLink; + HARDWARE_INFO *HwComponent; + + if (IsListEmpty (ListHead)) { + return; + } + + CurrentLink =3D ListHead->ForwardLink; + while (CurrentLink !=3D NULL && CurrentLink !=3D ListHead) { + HwComponent =3D HARDWARE_INFO_FROM_LINK (CurrentLink); + + // + // Remove item from list before invalidating the pointers + // + CurrentLink =3D RemoveEntryList (CurrentLink); + + FreePool (HwComponent->Data.Raw); + FreePool (HwComponent); + } +} + +/** + Validates if the specified Node has a valid data size and is of + specified type. + The data size can be less or equal to the provided type size to be + regarded as valid and thus accessible with the typed pointer. + + For future compatibility the size is allowed to be smaller so that + different versions interpret fields differently and, particularly, + have smaller data structures. However, it cannot be larger than the + type size to avoid accessing memory out of bounds. + + @param[in] Node Hardware Info node to be validated + @param[in] TypeSize Size (in bytes) of the data type intended to be + used to dereference the data. + @retval TRUE Node is valid and can be accessed + @retval FALSE Node is not valid +/*/ +STATIC +BOOLEAN +IsHardwareInfoNodeValidByType ( + IN LIST_ENTRY *ListHead, + IN LIST_ENTRY *Link, + IN HARDWARE_INFO_TYPE Type, + IN UINTN TypeSize + ) +{ + HARDWARE_INFO *HwComponent; + + if (IsNull (ListHead, Link)) { + return FALSE; + } + + HwComponent =3D HARDWARE_INFO_FROM_LINK (Link); + + // + // Verify if the node type is the specified one and the size of + // the data allocated to the node is greater than the size of + // the type intended to dereference it in order to avoid access + // to memory out of bondaries. + // + if ((HwComponent->Header.Type.Value =3D=3D Type) && + (HwComponent->Header.Size >=3D TypeSize)) + { + return TRUE; + } + + return FALSE; +} + +UINTN +GetHardwareInfoCountByType ( + IN LIST_ENTRY *ListHead, + IN HARDWARE_INFO_TYPE Type, + IN UINTN TypeSize + ) +{ + UINTN Count; + LIST_ENTRY *Link; + + Count =3D 0; + for (Link =3D GetFirstHardwareInfoByType (ListHead, Type, TypeSize); + !IsNull (ListHead, Link); + Link =3D GetNextHardwareInfoByType (ListHead, Link, Type, TypeSize)) + { + if (IsHardwareInfoNodeValidByType (ListHead, Link, Type, TypeSize)) { + Count++; + } + } + + return Count; +} + +LIST_ENTRY * +GetFirstHardwareInfoByType ( + IN LIST_ENTRY *ListHead, + IN HARDWARE_INFO_TYPE Type, + IN UINTN TypeSize + ) +{ + LIST_ENTRY *Link; + + if (IsListEmpty (ListHead)) { + return ListHead; + } + + Link =3D GetFirstNode (ListHead); + + if (IsHardwareInfoNodeValidByType (ListHead, Link, Type, TypeSize)) { + return Link; + } + + return GetNextHardwareInfoByType (ListHead, Link, Type, TypeSize); +} + +LIST_ENTRY * +GetNextHardwareInfoByType ( + IN LIST_ENTRY *ListHead, + IN LIST_ENTRY *Node, + IN HARDWARE_INFO_TYPE Type, + IN UINTN TypeSize + ) +{ + LIST_ENTRY *Link; + + Link =3D GetNextNode (ListHead, Node); + + while (!IsNull (ListHead, Link)) { + if (IsHardwareInfoNodeValidByType (ListHead, Link, Type, TypeSize)) { + // + // Found a node of specified type and with valid size. Break and + // return the found node. + // + break; + } + + Link =3D GetNextNode (ListHead, Link); + } + + return Link; +} + +BOOLEAN +EndOfHardwareInfoList ( + IN LIST_ENTRY *ListHead, + IN LIST_ENTRY *Node + ) +{ + return IsNull (ListHead, Node); +} diff --git a/OvmfPkg/Library/HardwareInfoLib/HardwareInfoLib.inf b/OvmfPkg/= Library/HardwareInfoLib/HardwareInfoLib.inf new file mode 100644 index 0000000000..c099b072a3 --- /dev/null +++ b/OvmfPkg/Library/HardwareInfoLib/HardwareInfoLib.inf @@ -0,0 +1,43 @@ +## @file +# Hardware information library to describe non-discoverable hardware reso= urces +# +# 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 B= SD 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 IM= PLIED. +# +## + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D HardwareInfoLib + FILE_GUID =3D F60B206A-5C56-11EC-AEAC-67CB080BCFF2 + MODULE_TYPE =3D BASE + VERSION_STRING =3D 1.0 + LIBRARY_CLASS =3D HardwareInfoLib + +# +# The following information is for reference only and not required by the = build +# tools. +# +# VALID_ARCHITECTURES =3D X64 +# + +[Sources] + HardwareInfoLib.c + HardwareInfoPciHostBridgeLib.c + QemuFwCfgHardwareInfoLib.c + +[Packages] + MdeModulePkg/MdeModulePkg.dec + MdePkg/MdePkg.dec + OvmfPkg/OvmfPkg.dec + +[LibraryClasses] + BaseMemoryLib + DebugLib + MemoryAllocationLib diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc index fb82fd02eb..062e16482d 100644 --- a/OvmfPkg/OvmfPkgX64.dsc +++ b/OvmfPkg/OvmfPkgX64.dsc @@ -175,6 +175,7 @@ SecurityManagementLib|MdeModulePkg/Library/DxeSecurityManagementLib/DxeS= ecurityManagementLib.inf UefiUsbLib|MdePkg/Library/UefiUsbLib/UefiUsbLib.inf SerializeVariablesLib|OvmfPkg/Library/SerializeVariablesLib/SerializeVar= iablesLib.inf + HardwareInfoLib|OvmfPkg/Library/HardwareInfoLib/HardwareInfoLib.inf QemuFwCfgHardwareInfoLib|OvmfPkg/Library/HardwareInfoLib/QemuFwCfgHardwa= reInfoLib.inf QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxeLib.inf QemuFwCfgSimpleParserLib|OvmfPkg/Library/QemuFwCfgSimpleParserLib/QemuFw= CfgSimpleParserLib.inf --=20 2.17.1 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 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#85875): https://edk2.groups.io/g/devel/message/85875 Mute This Topic: https://groups.io/mt/88565406/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Sun Apr 28 21:49:04 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+85874+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+85874+1787277+3901457@groups.io ARC-Seal: i=1; a=rsa-sha256; t=1642702648; cv=none; d=zohomail.com; s=zohoarc; b=AS+AvXzxVM+U18KvQoimnP+JU5mQznRYVeIkYOlfmaBeq3+VkRL1dGcdhTAyeMLfZND+VHPudFaxuwAEq+toiy8CVgDJZE5cL/JKmgAd8OjN++wLQa9/ivZVdkOwiBNmV0jssZJ7MKW/ljMFGp8AmRaxDwE2wk6Tk5RneOW6Jbk= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1642702648; h=Content-Type:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=0qSBGmhoE93UfrpQSAPxpCig+3pDM5L4MNd7WIc1GQI=; b=as+8MTRyxaxDjr3fbkaCzc4iM64uP3+A9IWHPJPRYXbMZPvZMcX2UsQmfznLMf6tk+Ew3WpVVTgOmKnsh5u+voiEi19Oxh1xl9u/haRNpXS7nzjBLVXkacAwjPxQs7voAPeElEqYNcCX5uEUx74jIbyMwt+6a9QtkymhEubVKDg= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+85874+1787277+3901457@groups.io Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1642702648893717.7022405765318; Thu, 20 Jan 2022 10:17:28 -0800 (PST) Return-Path: X-Received: by 127.0.0.2 with SMTP id vJw5YY1788612x4wnK4kbhVI; Thu, 20 Jan 2022 10:17:28 -0800 X-Received: from smtp-fw-80006.amazon.com (smtp-fw-80006.amazon.com [99.78.197.217]) by mx.groups.io with SMTP id smtpd.web10.15136.1642698761974239638 for ; Thu, 20 Jan 2022 09:12:42 -0800 X-IronPort-AV: E=Sophos;i="5.88,302,1635206400"; d="scan'208";a="56730530" X-Received: from pdx4-co-svc-p1-lb2-vlan3.amazon.com (HELO email-inbound-relay-iad-1d-54a073b7.us-east-1.amazon.com) ([10.25.36.214]) by smtp-border-fw-80006.pdx80.corp.amazon.com with ESMTP; 20 Jan 2022 17:12:40 +0000 X-Received: from EX13D49EUC003.ant.amazon.com (iad12-ws-svc-p26-lb9-vlan3.iad.amazon.com [10.40.163.38]) by email-inbound-relay-iad-1d-54a073b7.us-east-1.amazon.com (Postfix) with ESMTPS id 026B990F1E; Thu, 20 Jan 2022 17:12:38 +0000 (UTC) X-Received: from ub4014a598e6c52.ant.amazon.com (10.43.162.8) by EX13D49EUC003.ant.amazon.com (10.43.164.91) with Microsoft SMTP Server (TLS) id 15.0.1497.28; Thu, 20 Jan 2022 17:12:35 +0000 From: "Ojeda Leon, Nicolas via groups.io" To: CC: , Nicolas Ojeda Leon , Alexander Graf , Gerd Hoffmann Subject: [edk2-devel] [PATCH v2 4/8] Ovmf/PlatformPei: Extend 64-bit MMIO range to fit resources Date: Thu, 20 Jan 2022 18:10:17 +0100 Message-ID: In-Reply-To: References: MIME-Version: 1.0 X-Originating-IP: [10.43.162.8] X-ClientProxiedBy: EX13D12UWA004.ant.amazon.com (10.43.160.168) To EX13D49EUC003.ant.amazon.com (10.43.164.91) Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,ncoleon@amazon.com X-Gm-Message-State: Gkz5lBD5zYMHHjgFn94Q4oFFx1787277AA= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1642702648; bh=kE1l+dGMgXz4DhN3K9pQg7OBpUVuOgnbaw9jg1+VoSg=; h=CC:Content-Type:Date:From:Reply-To:Subject:To; b=YrAA9HyBlJjghpI+41t+h1mdihzqMukyxWCTHWfc3t16gxadr+dHNivHiQyBQRBp2Og ToRPww66RA3Uq/uuKwEUlpyn2O3IZq7ZVdxHekJG2eUiFhqs81lFaMNR+bRiwdsOZHtdL 8Jq9WXaIi8UWXOkyDrDrC4Dqw8Cc0GdWJGI= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1642702651161100002 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Read the "hardware-info" item from fw-cfg to extract specifications of PCI host bridges and analyze the 64-bit apertures of them to find out if 64-bit PCI size needs to be increased in order to allocate enough address space to fit all the host bridges in a valid region. Using the static Hardware Info Lib API, read the fw-cfg file of hardware information to extract, one by one, all the host bridges. Find the last 64-bit MMIO address of each host bridge, using the HardwareInfoPciHostBridgeLib API, and compare it to an accumulate value to discover the highest address used, which corresponds to the highest value that must be covered by the 64-bit PCI MMIO window. Given that platforms with multiple host bridges may provide the PCI apertures' addresses, the PCD token used to initialize the available address space (PcdPciMmio64Size) must include those addresses for the allocation process to be able to place resources in the intended regions. Since the Pcd entry defining the 64-bit PCI MMIO size is dynamic and initialized with a platform-dependent value, it is updated to a higher value if that is required for all high memory PCI host bridge apertures to fit in the valid address space. As an example, if the PcdPciMmio64Size is initialized to 0x800000000 and the runtime calculated base address produces the value 0x800000000, the last 64-bit MMIO address a PCI host bridge may use would be 0xFFFFFFFFF. If one of the host-specified bridges defines a high memory window 0x1000000000 - 0x17FFFFFFFF (inclusive) it would be outside of the valid range defined by the Base address + PcdPciMmio64Size. Therefore, parsing the HardwwareInfo resource allows to notice the higher requirement and increase the size to 0x1000000000 so that the MMIO address space solicited by the host can be met and the range effectively extended to 0x17FFFFFFFF. Cc: Alexander Graf Cc: Gerd Hoffmann Signed-off-by: Nicolas Ojeda Leon --- OvmfPkg/PlatformPei/MemDetect.c | 110 ++++++++++++++++++++++++++++ OvmfPkg/PlatformPei/PlatformPei.inf | 1 + 2 files changed, 111 insertions(+) diff --git a/OvmfPkg/PlatformPei/MemDetect.c b/OvmfPkg/PlatformPei/MemDetec= t.c index 1bcb5a08bc..b0bdd435cb 100644 --- a/OvmfPkg/PlatformPei/MemDetect.c +++ b/OvmfPkg/PlatformPei/MemDetect.c @@ -36,6 +36,7 @@ Module Name: #include #include #include +#include =20 #include "Platform.h" #include "Cmos.h" @@ -369,6 +370,110 @@ GetSystemMemorySizeAbove4gb ( return LShiftU64 (Size, 16); } =20 +/** + Iterate over the PCI host bridges resources information optionally provi= ded + in fw-cfg. + + Find the highest address used by the PCI bridges in 64-bit MMIO space to + calculate and modify the PCI aperture size accordingly (PciMmio64Size) + + @param[in] PciMmio64Base Base address (start) of the 64-bit PCI MMIO + address space. + + @param[inout] PciMmio64Size Size of the PCI 64-bit MMIO aperture provided + as input and modified (output) if the resour= ces + indicated by fw_cfg require a larger address + space. + + @retval EFI_SUCCESS The fw_cfg host-bridges-info was found and + processed. + + @retval EFI_PROTOCOL_ERROR The host bridges information file was found, + but its size wasn't a whole multiple of + sizeof(HOST_BRIDGE_INFO). No entry was proce= ssed. + + @retval EFI_NOT_FOUND fw-cfg file with host bridges information wa= s not + found. Does not constitute an errro since th= e file + is optional and used in special cases. + + @retval EFI_UNSUPPORTED fw-cfg is unavailable + +**/ +STATIC +EFI_STATUS +ScanPci64BitApertureSize ( + IN UINT64 PciMmio64Base, + IN OUT UINT64 *PciMmio64Size + ) +{ + EFI_STATUS Status; + HOST_BRIDGE_INFO HostBridge; + FIRMWARE_CONFIG_ITEM FwCfgItem; + UINTN FwCfgSize; + UINTN FwCfgReadIndex; + UINTN ReadDataSize; + UINT64 PciEnd; + UINT64 PcdPciEnd; + UINT64 Above4GMmioEnd; + + PciEnd =3D 0; + Above4GMmioEnd =3D 0; + PcdPciEnd =3D PciMmio64Base + *PciMmio64Size - 1; + + Status =3D QemuFwCfgFindFile ("etc/hardware-info", &FwCfgItem, &FwCfgSiz= e); + if (EFI_ERROR (Status)) { + return Status; + } + + QemuFwCfgSelectItem (FwCfgItem); + + FwCfgReadIndex =3D 0; + while (FwCfgReadIndex < FwCfgSize) { + Status =3D QemuFwCfgReadNextHardwareInfoByType ( + HardwareInfoTypeHostBridge, + sizeof (HostBridge), + FwCfgSize, + &HostBridge, + &ReadDataSize, + &FwCfgReadIndex + ); + + if (Status !=3D EFI_SUCCESS) { + // + // No more data available to read in the file, break + // loop and finish process + // + break; + } + + Status =3D HardwareInfoPciHostBridgeLastMmioAddress ( + &HostBridge, + ReadDataSize, + TRUE, + &Above4GMmioEnd + ); + + if (Status !=3D EFI_SUCCESS) { + // + // Error parsing MMIO apertures and extracting last MMIO + // address, bail out and propagate error + // + return Status; + } + + if (Above4GMmioEnd > PciEnd) { + PciEnd =3D Above4GMmioEnd; + } + } + + if (PciEnd > PcdPciEnd) { + *PciMmio64Size =3D PciEnd - PciMmio64Base + 1; + *PciMmio64Size =3D ALIGN_VALUE (*PciMmio64Size, (UINT64)SIZE_1GB); + } + + return EFI_SUCCESS; +} + /** Return the highest address that DXE could possibly use, plus one. **/ @@ -515,6 +620,11 @@ GetFirstNonAddress ( // Pci64Base =3D ALIGN_VALUE (Pci64Base, GetPowerOfTwo64 (Pci64Size)); =20 + // + // Extend Pci64Size if fw_cfg Host bridges specification requires it + // + ScanPci64BitApertureSize (Pci64Base, &Pci64Size); + if (mBootMode !=3D BOOT_ON_S3_RESUME) { // // The core PciHostBridgeDxe driver will automatically add this range = to diff --git a/OvmfPkg/PlatformPei/PlatformPei.inf b/OvmfPkg/PlatformPei/Plat= formPei.inf index 8ef404168c..413b92b855 100644 --- a/OvmfPkg/PlatformPei/PlatformPei.inf +++ b/OvmfPkg/PlatformPei/PlatformPei.inf @@ -64,6 +64,7 @@ MemEncryptSevLib PcdLib VmgExitLib + QemuFwCfgHardwareInfoLib =20 [Pcd] gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvBase --=20 2.17.1 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 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#85874): https://edk2.groups.io/g/devel/message/85874 Mute This Topic: https://groups.io/mt/88565405/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Sun Apr 28 21:49:04 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+85876+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+85876+1787277+3901457@groups.io ARC-Seal: i=1; a=rsa-sha256; t=1642702650; cv=none; d=zohomail.com; s=zohoarc; b=kbpLIKroJCwxa6I6zyct5RKTFdFaCMziuA9sXL2HF4YVv4G2pNhjnz57X+g18eRaQsNCvcAfiGrOOfnoC5rHTYLPbtcCHgPsJKlpYW+tr+XYo8AIrVZkq3DcmHB02NPIRrTPiDOdxGXDR/lUyOCxnwffGFeG/LxsuhFrBuKfdpA= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1642702650; h=Content-Type:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=DnmZ3fGUSS62EieC8nVPgnDX7OPMgNZ8N9Lt1CeKq1k=; b=M0fbGugBO6kBR+m53Q+ISekEw+TanHkkIEaeUu6TzfhztLLYwWcwKlTQnEDpYmSa9hSZFdAUucjc2YH47DxPZSdJbEvgLKIFS5JEMZwtk3/LHNV06J8TdEC6BCD6MGH4a+jnzzLJhy2MJHI4Rs5d/Cd4ndTi114CSH8ROXewViE= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+85876+1787277+3901457@groups.io Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1642702650039183.95876862973034; Thu, 20 Jan 2022 10:17:30 -0800 (PST) Return-Path: X-Received: by 127.0.0.2 with SMTP id 5LhQYY1788612xL68xq91b1a; Thu, 20 Jan 2022 10:17:29 -0800 X-Received: from smtp-fw-80006.amazon.com (smtp-fw-80006.amazon.com [99.78.197.217]) by mx.groups.io with SMTP id smtpd.web09.15223.1642698773443004047 for ; Thu, 20 Jan 2022 09:12:53 -0800 X-IronPort-AV: E=Sophos;i="5.88,302,1635206400"; d="scan'208";a="56730588" X-Received: from pdx4-co-svc-p1-lb2-vlan3.amazon.com (HELO email-inbound-relay-iad-1e-fc41acad.us-east-1.amazon.com) ([10.25.36.214]) by smtp-border-fw-80006.pdx80.corp.amazon.com with ESMTP; 20 Jan 2022 17:12:53 +0000 X-Received: from EX13D49EUC003.ant.amazon.com (iad12-ws-svc-p26-lb9-vlan3.iad.amazon.com [10.40.163.38]) by email-inbound-relay-iad-1e-fc41acad.us-east-1.amazon.com (Postfix) with ESMTPS id 9C43BC0973; Thu, 20 Jan 2022 17:12:51 +0000 (UTC) X-Received: from ub4014a598e6c52.ant.amazon.com (10.43.162.8) by EX13D49EUC003.ant.amazon.com (10.43.164.91) with Microsoft SMTP Server (TLS) id 15.0.1497.28; Thu, 20 Jan 2022 17:12:48 +0000 From: "Ojeda Leon, Nicolas via groups.io" To: CC: , Nicolas Ojeda Leon , Alexander Graf , Gerd Hoffmann Subject: [edk2-devel] [PATCH v2 5/8] OvmfPkg/PciHostBridgeUtilityLib: Initialize RootBridges apertures with spec Date: Thu, 20 Jan 2022 18:10:18 +0100 Message-ID: In-Reply-To: References: MIME-Version: 1.0 X-Originating-IP: [10.43.162.8] X-ClientProxiedBy: EX13D12UWA004.ant.amazon.com (10.43.160.168) To EX13D49EUC003.ant.amazon.com (10.43.164.91) Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,ncoleon@amazon.com X-Gm-Message-State: oCUiBAErP7V2jhRSdi50MxLlx1787277AA= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1642702649; bh=TNKLriu/1FfPUfv+tZp3IsT6zNqCY5iHEu7OKUo4Cks=; h=CC:Content-Type:Date:From:Reply-To:Subject:To; b=qK3Y3ocK50Mhefaz1QOsY9ZocRvHrUlABjnT4rZEkY10tGMSuOeL2e1EdRyjp0Yzo27 vdsPo9893Xz9a1Np3Zw/AHzC2xawYo6TPW2/CrBHAjE2duEBKM5BeBepWg2u9ixNdjCXL 5A8znB6p6WTsAVOeiZVIRl7V3kzmdb9yNOQ= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1642702651511100010 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Consume the host-provided specification of PCI host bridges if available. Using the Hardware Info library, populate a list of hardware descriptors based on the content of the "hardware-info" fw-cfg file, if provided. In the affirmative case, use the resources and attributes specified by the hypervisor for each Host Bridge to create the RootBridge elements. In Ovmf platforms, the host can provide the specification of non-discoverable hardware resources like PCI host bridges. If the proper fw-cfg file is found, parse the contents provided by the host into a linked list by using the Hardware Info library. Then, using the list of PCI host bridges' descriptions, populate the PCI_ROOT_BRIDGES array with the resources and attributes specified by the host. If the file is not provided or no Host Bridge is found in it, fold back to the legacy method based on pre-defined apertures and rules. In some use cases, the host requires additional control over the hardware resources' configurations in the guest for performance and discoverability reasons. For instance, to disclose information about the PCI hierarchy to the guest so that this can profit from optimized accesses. In this case, the host can decide to describe multiple PCI Host Bridges and provide a specific set of resources (e.g. MMIO apertures) so that the guest uses the values provided. Using the provided values may entitle the guest to added performance, for example by using specific MMIO mappings that can enable peer-to-peer communication across the PCI hierarchy or by allocating memory closer to a device for faster DMA transactions. Cc: Alexander Graf Cc: Gerd Hoffmann Signed-off-by: Nicolas Ojeda Leon --- .../PciHostBridgeUtilityLib.c | 345 ++++++++++++++---- .../PciHostBridgeUtilityLib.inf | 1 + 2 files changed, 268 insertions(+), 78 deletions(-) diff --git a/OvmfPkg/Library/PciHostBridgeUtilityLib/PciHostBridgeUtilityLi= b.c b/OvmfPkg/Library/PciHostBridgeUtilityLib/PciHostBridgeUtilityLib.c index 92e1ea812f..b0e3b5e3cf 100644 --- a/OvmfPkg/Library/PciHostBridgeUtilityLib/PciHostBridgeUtilityLib.c +++ b/OvmfPkg/Library/PciHostBridgeUtilityLib/PciHostBridgeUtilityLib.c @@ -12,13 +12,16 @@ =20 #include #include +#include #include #include #include +#include #include #include #include #include +#include =20 #pragma pack(1) typedef struct { @@ -234,14 +237,29 @@ PciHostBridgeUtilityGetRootBridges ( 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; + EFI_STATUS Status; + FIRMWARE_CONFIG_ITEM FwCfgItem; + UINTN FwCfgSize; + UINT64 ExtraRootBridges; + PCI_ROOT_BRIDGE *Bridges; + UINTN Initialized; + UINTN LastRootBridgeNumber; + UINTN RootBridgeNumber; + UINTN PciHostBridgeCount; + UINT8 *HardwareInfoBlob; + LIST_ENTRY HwInfoList; + LIST_ENTRY *HwLink; + HARDWARE_INFO *HwInfo; + UINT64 HwInfoAttributes; + UINT64 HwInfoAllocationAttributes; + BOOLEAN HwInfoDmaAbove4G; + BOOLEAN HwInfoNoExtendedConfigSpace; + BOOLEAN HwInfoCombineMemPMem; + PCI_ROOT_BRIDGE_APERTURE HwInfoIo; + PCI_ROOT_BRIDGE_APERTURE HwInfoMem; + PCI_ROOT_BRIDGE_APERTURE HwInfoMemAbove4G; + PCI_ROOT_BRIDGE_APERTURE HwInfoPMem; + PCI_ROOT_BRIDGE_APERTURE HwInfoPMemAbove4G; =20 *Count =3D 0; =20 @@ -294,103 +312,266 @@ PciHostBridgeUtilityGetRootBridges ( )); } =20 + // + // Initialize the Hardware Info list head to start with an empty but val= id + // list head. + // + InitializeListHead (&HwInfoList); + HardwareInfoBlob =3D NULL; + Initialized =3D 0; + Bridges =3D NULL; + PciHostBridgeCount =3D 0; + + // + // Hypervisor can provide the specifications (resources) for one or more + // PCI host bridges. Such information comes through fw-cfg as part of + // the hardware-info file. + // + Status =3D QemuFwCfgFindFile ("etc/hardware-info", &FwCfgItem, &FwCfgSiz= e); + + if (!EFI_ERROR (Status)) { + HardwareInfoBlob =3D AllocatePool (FwCfgSize); + + if (HardwareInfoBlob =3D=3D NULL) { + DEBUG (( + DEBUG_ERROR, + "%a: Failed to allocate memory for hardware resources info\n", + __FUNCTION__ + )); + return NULL; + } + + QemuFwCfgSelectItem (FwCfgItem); + QemuFwCfgReadBytes (FwCfgSize, HardwareInfoBlob); + + // + // Create the list of hardware info devices filtering for PCI host + // bridges + // + Status =3D CreateHardwareInfoList ( + HardwareInfoBlob, + FwCfgSize, + HardwareInfoTypeHostBridge, + &HwInfoList + ); + + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "%a: Failed to create hardware info list to retrieve host " + "bridges information\n", + __FUNCTION__ + )); + + goto FreeBridges; + } + + PciHostBridgeCount =3D GetHardwareInfoCountByType ( + &HwInfoList, + HardwareInfoTypeHostBridge, + sizeof (HOST_BRIDGE_INFO) + ); + + if ((1 + ExtraRootBridges) !=3D PciHostBridgeCount) { + DEBUG (( + DEBUG_ERROR, + "%a: Invalid number of host bridges in hardware info list. " + "Expected %ld, got %ld\n", + __FUNCTION__, + (1 + ExtraRootBridges), + PciHostBridgeCount + )); + goto FreeBridges; + } + + DEBUG (( + DEBUG_INFO, + "%a: Resources for %Lu root buses found in fw-cfg\n", + __FUNCTION__, + PciHostBridgeCount + )); + } + // // Allocate the "main" root bridge, and any extra root bridges. // Bridges =3D AllocatePool ((1 + (UINTN)ExtraRootBridges) * sizeof *Bridge= s); if (Bridges =3D=3D NULL) { DEBUG ((DEBUG_ERROR, "%a: %r\n", __FUNCTION__, EFI_OUT_OF_RESOURCES)); - return NULL; + goto FreeBridges; } =20 - Initialized =3D 0; + if (!IsListEmpty (&HwInfoList)) { + // + // If Host Bridges' specification was obtained from fw-cfg, the list + // contains information to populate all root bridges in the system + // including resources and attributes. + // + HwLink =3D GetFirstHardwareInfoByType ( + &HwInfoList, + HardwareInfoTypeHostBridge, + sizeof (HOST_BRIDGE_INFO) + ); + + while (!EndOfHardwareInfoList (&HwInfoList, HwLink)) { + HwInfo =3D HARDWARE_INFO_FROM_LINK (HwLink); + + HardwareInfoPciHostBridgeGet ( + HwInfo->Data.PciHostBridge, + HwInfo->Header.Size, + &RootBridgeNumber, + &LastRootBridgeNumber, + &HwInfoAttributes, + &HwInfoDmaAbove4G, + &HwInfoNoExtendedConfigSpace, + &HwInfoCombineMemPMem, + &HwInfoIo, + &HwInfoMem, + &HwInfoMemAbove4G, + &HwInfoPMem, + &HwInfoPMemAbove4G, + NULL + ); =20 - // - // The "main" root bus is always there. - // - LastRootBridgeNumber =3D BusMin; + HwInfoAllocationAttributes =3D 0; + if (HwInfoCombineMemPMem) { + HwInfoAllocationAttributes |=3D EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PM= EM; + } =20 - // - // Scan all other root buses. If function 0 of any device on a bus retur= ns a - // VendorId register value different from all-bits-one, then that bus is - // alive. - // - for (RootBridgeNumber =3D BusMin + 1; - RootBridgeNumber <=3D BusMax && Initialized < ExtraRootBridges; - ++RootBridgeNumber) - { - UINTN Device; - - for (Device =3D 0; Device <=3D PCI_MAX_DEVICE; ++Device) { - if (PciRead16 ( - PCI_LIB_ADDRESS ( - RootBridgeNumber, - Device, - 0, - PCI_VENDOR_ID_OFFSET - ) - ) !=3D MAX_UINT16) + if ((HwInfoMemAbove4G.Limit > HwInfoMemAbove4G.Base) || + (HwInfoPMemAbove4G.Limit > HwInfoPMemAbove4G.Base)) { - break; + HwInfoAllocationAttributes |=3D EFI_PCI_HOST_BRIDGE_MEM64_DECODE; } - } =20 - if (Device <=3D 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, fo= r any - // subordinate buses that might exist behind PCI bridges hanging off= it. - // Status =3D PciHostBridgeUtilityInitRootBridge ( - Attributes, - Attributes, - AllocationAttributes, - DmaAbove4G, - NoExtendedConfigSpace, - (UINT8)LastRootBridgeNumber, - (UINT8)(RootBridgeNumber - 1), - Io, - Mem, - MemAbove4G, - PMem, - PMemAbove4G, + HwInfoAttributes, + HwInfoAttributes, + HwInfoAllocationAttributes, + HwInfoDmaAbove4G, + HwInfoNoExtendedConfigSpace, + RootBridgeNumber, + LastRootBridgeNumber, + &HwInfoIo, + &HwInfoMem, + &HwInfoMemAbove4G, + &HwInfoPMem, + &HwInfoPMemAbove4G, &Bridges[Initialized] ); + if (EFI_ERROR (Status)) { goto FreeBridges; } =20 ++Initialized; - LastRootBridgeNumber =3D RootBridgeNumber; + + HwLink =3D GetNextHardwareInfoByType ( + &HwInfoList, + HwLink, + HardwareInfoTypeHostBridge, + sizeof (HOST_BRIDGE_INFO) + ); } + } else { + Initialized =3D 0; + + // + // The "main" root bus is always there. + // + LastRootBridgeNumber =3D BusMin; + + // + // Scan all other root buses. If function 0 of any device on a bus ret= urns a + // VendorId register value different from all-bits-one, then that bus = is + // alive. + // + for (RootBridgeNumber =3D BusMin + 1; + RootBridgeNumber <=3D BusMax && Initialized < ExtraRootBridges; + ++RootBridgeNumber) + { + UINTN Device; + + for (Device =3D 0; Device <=3D PCI_MAX_DEVICE; ++Device) { + if (PciRead16 ( + PCI_LIB_ADDRESS ( + RootBridgeNumber, + Device, + 0, + PCI_VENDOR_ID_OFFSET + ) + ) !=3D MAX_UINT16) + { + break; + } + } + + if (Device <=3D 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 o= ff it. + // + Status =3D 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 =3D RootBridgeNumber; + } + } + + // + // Install the last root bus (which might be the only, ie. main, root = bus, if + // we've found no extra root buses). + // + Status =3D PciHostBridgeUtilityInitRootBridge ( + Attributes, + Attributes, + AllocationAttributes, + DmaAbove4G, + NoExtendedConfigSpace, + (UINT8)LastRootBridgeNumber, + (UINT8)BusMax, + Io, + Mem, + MemAbove4G, + PMem, + PMemAbove4G, + &Bridges[Initialized] + ); + if (EFI_ERROR (Status)) { + goto FreeBridges; + } + + ++Initialized; } =20 + *Count =3D Initialized; + + // If resources were allocated for host bridges info, release them // - // Install the last root bus (which might be the only, ie. main, root bu= s, if - // we've found no extra root buses). - // - Status =3D PciHostBridgeUtilityInitRootBridge ( - Attributes, - Attributes, - AllocationAttributes, - DmaAbove4G, - NoExtendedConfigSpace, - (UINT8)LastRootBridgeNumber, - (UINT8)BusMax, - Io, - Mem, - MemAbove4G, - PMem, - PMemAbove4G, - &Bridges[Initialized] - ); - if (EFI_ERROR (Status)) { - goto FreeBridges; + if (HardwareInfoBlob) { + FreePool (HardwareInfoBlob); } =20 - ++Initialized; + FreeHardwareInfoList (&HwInfoList); =20 - *Count =3D Initialized; return Bridges; =20 FreeBridges: @@ -399,7 +580,15 @@ FreeBridges: PciHostBridgeUtilityUninitRootBridge (&Bridges[Initialized]); } =20 - FreePool (Bridges); + if (Bridges) { + FreePool (Bridges); + } + + if (HardwareInfoBlob) { + FreePool (HardwareInfoBlob); + } + + FreeHardwareInfoList (&HwInfoList); return NULL; } =20 diff --git a/OvmfPkg/Library/PciHostBridgeUtilityLib/PciHostBridgeUtilityLi= b.inf b/OvmfPkg/Library/PciHostBridgeUtilityLib/PciHostBridgeUtilityLib.inf index 83a734c172..5b32eaf5d2 100644 --- a/OvmfPkg/Library/PciHostBridgeUtilityLib/PciHostBridgeUtilityLib.inf +++ b/OvmfPkg/Library/PciHostBridgeUtilityLib/PciHostBridgeUtilityLib.inf @@ -38,6 +38,7 @@ BaseMemoryLib DebugLib DevicePathLib + HardwareInfoLib MemoryAllocationLib PciLib QemuFwCfgLib --=20 2.17.1 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 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#85876): https://edk2.groups.io/g/devel/message/85876 Mute This Topic: https://groups.io/mt/88565407/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Sun Apr 28 21:49:04 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+85877+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+85877+1787277+3901457@groups.io ARC-Seal: i=1; a=rsa-sha256; t=1642702650; cv=none; d=zohomail.com; s=zohoarc; b=iS/6fU7svWJ8II7/dyYpxnhg9XUzIPdfPGDNG/jrPEiJeh9ECheSBrOFYp6n8BkViBM2uEn668UTRM38kyMPmZVle4asx4DwNvW8SOw9Q711iKyVTyPI7llmR7/orZJxWdDlVtVWenGfRcdjutlibAOWscoZt0og4m/lIhglGGU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1642702650; h=Content-Type:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=VFZDJYcXKQ0eS8ywUPgFg5Th51UA/BxKs7izuWzNSKc=; b=krZ0281TUDxKFM+X/c8ZIBkBzSv+AChD2/kUnZWOMsyLXGUJFqcOxP2O7Zc/15c+0T7jPNqd58lK/FlWKr0kNNkMF1JcMthRorNKnnIECcHpUq1bUf6KhCyHA/mI4EjX+fHeKSNl71cV4snwjS9vL7P7FvQhUPbG27fwA2lRrmY= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+85877+1787277+3901457@groups.io Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1642702650556131.07846499996606; Thu, 20 Jan 2022 10:17:30 -0800 (PST) Return-Path: X-Received: by 127.0.0.2 with SMTP id howmYY1788612xi21GYtPWCg; Thu, 20 Jan 2022 10:17:30 -0800 X-Received: from smtp-fw-80006.amazon.com (smtp-fw-80006.amazon.com [99.78.197.217]) by mx.groups.io with SMTP id smtpd.web10.15142.1642698782649190491 for ; Thu, 20 Jan 2022 09:13:02 -0800 X-IronPort-AV: E=Sophos;i="5.88,302,1635206400"; d="scan'208";a="56730620" X-Received: from pdx4-co-svc-p1-lb2-vlan3.amazon.com (HELO email-inbound-relay-iad-1d-10222bbc.us-east-1.amazon.com) ([10.25.36.214]) by smtp-border-fw-80006.pdx80.corp.amazon.com with ESMTP; 20 Jan 2022 17:13:03 +0000 X-Received: from EX13D49EUC003.ant.amazon.com (iad12-ws-svc-p26-lb9-vlan3.iad.amazon.com [10.40.163.38]) by email-inbound-relay-iad-1d-10222bbc.us-east-1.amazon.com (Postfix) with ESMTPS id 3E2331A0031; Thu, 20 Jan 2022 17:13:00 +0000 (UTC) X-Received: from ub4014a598e6c52.ant.amazon.com (10.43.162.8) by EX13D49EUC003.ant.amazon.com (10.43.164.91) with Microsoft SMTP Server (TLS) id 15.0.1497.28; Thu, 20 Jan 2022 17:12:57 +0000 From: "Ojeda Leon, Nicolas via groups.io" To: CC: , Nicolas Ojeda Leon , Alexander Graf , Gerd Hoffmann Subject: [edk2-devel] [PATCH v2 6/8] MdeModulePkg, OvmfPkg: Add Pcd token for PCI pre-populated BARs Date: Thu, 20 Jan 2022 18:10:19 +0100 Message-ID: <94b634f64d1efe97f04bee16b8748c610089dca1.1642697671.git.ncoleon@amazon.com> In-Reply-To: References: MIME-Version: 1.0 X-Originating-IP: [10.43.162.8] X-ClientProxiedBy: EX13D12UWA004.ant.amazon.com (10.43.160.168) To EX13D49EUC003.ant.amazon.com (10.43.164.91) Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,ncoleon@amazon.com X-Gm-Message-State: sboUbzjD9qGeudIDEeqClL3Kx1787277AA= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1642702650; bh=nRp34OxWuE45LtBSaOQH/zfaUxXYa4xykBasWUD1IBM=; h=CC:Content-Type:Date:From:Reply-To:Subject:To; b=Qk/e34JW/EyI+8/rNVCwq5d7Gs8SmXUMqwDv/oMFJz6Ec4Us4O8JznLOoRvq4YmhkI3 bixxZ37bjBn/z78py9sh1bTRnYlTjF6UUp4RwxhVY1GxKvgdLaZlSDqrfaR6Hm2EeMskh yJPJ336Ahji8rEIWUmTJ8B8tI13/4ATUkVw= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1642702651655100013 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Create a new PCD boolean token in MdeModulePkg for global use. We use this token to indicate if the configuration, parsed from fw-cfg, requires pre-populated BARs to be preserved. During creation of root bridges configurations, the flag is set according to the "pre-populated-bars" item in fw-cfg. The Pcd token is created as a dynamic item so it can be modified at runtime and it is consumed in both Pei and Dxe PCI modules. In virtualized environments, the hypervisor provides a layer of isolation between the VMs and the hardware. This isolation may include address translations and shadowing of configurations that prevent guests directly modifying hardware registers. The hypervisor then takes care of emulating the hardware accesses requested by the guest. In some cases, the host may want the guest to use a specific value for some or all PCI BARs so that transactions in GPA level (particularly DMA) can make use of the controlled set of addresses. The host then indicates the guest to preserve those BARs that are pre-populated, that is, BARs that already report a value even before guest's firmware BAR placement. The token provides a globally accessible configuration flag to determine, during PCI BAR allocation, if pre-populated BARs must be respected. The pre-allocated PCI BARs are used in platforms in which MMIO resources are configured with the same host physical addresses in the guest so that DMA transactions can happen between PCI devices without packets going through the IOMMU. Performance is improved due to PCI packets travelling shorter distances and avoiding links reaching the Root Complex, which can get busy during I/O intensive periods. Cc: Alexander Graf Cc: Gerd Hoffmann Signed-off-by: Nicolas Ojeda Leon --- MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf | 1 + MdeModulePkg/MdeModulePkg.dec | 6 ++++++ .../PciHostBridgeUtilityLib.c | 17 +++++++++++++++++ .../PciHostBridgeUtilityLib.inf | 4 ++++ OvmfPkg/OvmfPkgX64.dsc | 1 + OvmfPkg/PlatformPei/PlatformPei.inf | 1 + 6 files changed, 30 insertions(+) diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf b/MdeModulePkg/Bu= s/Pci/PciBusDxe/PciBusDxe.inf index e317169d9c..046876bb3b 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf @@ -107,6 +107,7 @@ gEfiMdeModulePkgTokenSpaceGuid.PcdMrIovSupport ## CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdPciDisableBusEnumeration ## SOMETIM= ES_CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdPcieResizableBarSupport ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdPciPreservePopulatedMappings## CONSUMES =20 [UserExtensions.TianoCore."ExtraFiles"] PciBusDxeExtra.uni diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec index 463e889e9a..078877ba7f 100644 --- a/MdeModulePkg/MdeModulePkg.dec +++ b/MdeModulePkg/MdeModulePkg.dec @@ -1902,6 +1902,12 @@ # @Prompt Disable full PCI enumeration. gEfiMdeModulePkgTokenSpaceGuid.PcdPciDisableBusEnumeration|FALSE|BOOLEAN= |0x10000048 =20 + ## The flag to control preservation of pre-populated PCI BARs + # TRUE - Respect pre-populated PCI BARs + # FALSE - No pre-populated BARs, place all BARs + # @Prompt Enable preservsation of pre-populated PCI BARs + gEfiMdeModulePkgTokenSpaceGuid.PcdPciPreservePopulatedMappings|FALSE|BOO= LEAN|0x10000050 + ## Disk I/O - Number of Data Buffer block. # Define the size in block of the pre-allocated buffer. It provide better # performance for large Disk I/O requests. diff --git a/OvmfPkg/Library/PciHostBridgeUtilityLib/PciHostBridgeUtilityLi= b.c b/OvmfPkg/Library/PciHostBridgeUtilityLib/PciHostBridgeUtilityLib.c index b0e3b5e3cf..5c86f67f76 100644 --- a/OvmfPkg/Library/PciHostBridgeUtilityLib/PciHostBridgeUtilityLib.c +++ b/OvmfPkg/Library/PciHostBridgeUtilityLib/PciHostBridgeUtilityLib.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -260,6 +261,7 @@ PciHostBridgeUtilityGetRootBridges ( PCI_ROOT_BRIDGE_APERTURE HwInfoMemAbove4G; PCI_ROOT_BRIDGE_APERTURE HwInfoPMem; PCI_ROOT_BRIDGE_APERTURE HwInfoPMemAbove4G; + UINT64 PrePopulatedBars; =20 *Count =3D 0; =20 @@ -312,6 +314,21 @@ PciHostBridgeUtilityGetRootBridges ( )); } =20 + // + // Find file for pre-populated bars and set Pcd token if enabled + // + Status =3D QemuFwCfgFindFile ("etc/pre-populated-bars", &FwCfg= Item, &FwCfgSize); + PrePopulatedBars =3D 0; + if (!EFI_ERROR (Status) && (FwCfgSize =3D=3D sizeof (PrePopulatedBars)))= { + QemuFwCfgSelectItem (FwCfgItem); + QemuFwCfgReadBytes (FwCfgSize, &PrePopulatedBars); + + if (PrePopulatedBars) { + PcdSetBoolS (PcdPciPreservePopulatedMappings, TRUE); + DEBUG ((DEBUG_INFO, "%a: Pre-populated BARs present\n", __FUNCTION__= )); + } + } + // // Initialize the Hardware Info list head to start with an empty but val= id // list head. diff --git a/OvmfPkg/Library/PciHostBridgeUtilityLib/PciHostBridgeUtilityLi= b.inf b/OvmfPkg/Library/PciHostBridgeUtilityLib/PciHostBridgeUtilityLib.inf index 5b32eaf5d2..e08ff64244 100644 --- a/OvmfPkg/Library/PciHostBridgeUtilityLib/PciHostBridgeUtilityLib.inf +++ b/OvmfPkg/Library/PciHostBridgeUtilityLib/PciHostBridgeUtilityLib.inf @@ -40,5 +40,9 @@ DevicePathLib HardwareInfoLib MemoryAllocationLib + PcdLib PciLib QemuFwCfgLib + +[Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdPciPreservePopulatedMappings diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc index 062e16482d..628e70f906 100644 --- a/OvmfPkg/OvmfPkgX64.dsc +++ b/OvmfPkg/OvmfPkgX64.dsc @@ -594,6 +594,7 @@ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase|0 gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase|0 !endif + gEfiMdeModulePkgTokenSpaceGuid.PcdPciPreservePopulatedMappings|FALSE gEfiMdeModulePkgTokenSpaceGuid.PcdVideoHorizontalResolution|800 gEfiMdeModulePkgTokenSpaceGuid.PcdVideoVerticalResolution|600 gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiS3Enable|FALSE diff --git a/OvmfPkg/PlatformPei/PlatformPei.inf b/OvmfPkg/PlatformPei/Plat= formPei.inf index 413b92b855..37d4e1092f 100644 --- a/OvmfPkg/PlatformPei/PlatformPei.inf +++ b/OvmfPkg/PlatformPei/PlatformPei.inf @@ -96,6 +96,7 @@ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize gEfiMdeModulePkgTokenSpaceGuid.PcdEmuVariableNvStoreReserved + gEfiMdeModulePkgTokenSpaceGuid.PcdPciPreservePopulatedMappings gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable gEfiMdeModulePkgTokenSpaceGuid.PcdSetNxForStack --=20 2.17.1 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 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#85877): https://edk2.groups.io/g/devel/message/85877 Mute This Topic: https://groups.io/mt/88565408/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Sun Apr 28 21:49:04 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+85879+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+85879+1787277+3901457@groups.io ARC-Seal: i=1; a=rsa-sha256; t=1642702651; cv=none; d=zohomail.com; s=zohoarc; b=dhjfbb1z3xGEiJBtRBtD9KGjju0LzhNuyB0c9R0CbQw6iADEPoMbaw7gt8wkQvBhJ9hXLTFEwwWVAztMjvfo2uESjIeD7WqqgkvKe5uNudNkx99NJYO3l+dMFfonCOi0UkfAWCC8vVgDXXhSASrFs+cDyYKpQqLDge+7xhrQR28= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1642702651; h=Content-Type:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=isc8iK6OgAdpAnYQgKahvBBi30Am6gU+Rh29Mv/gu2s=; b=JmBJaM6tHrf1k7ldDkRPjsrg2BYlJsMBVNmynUD7ESvBrOmxyJdkes3UnSDW42r3OCr7Y2r1EE/u4CDMgJ4NxFhIVzUeTSSazo23T6LLwaIGUvdb+i8+bJg0lpsAv+0YfO9LmKmcy2D6A/aSh3MwqnwOJZJ5rhitajInGhRortQ= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+85879+1787277+3901457@groups.io Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1642702651631437.1229959734403; Thu, 20 Jan 2022 10:17:31 -0800 (PST) Return-Path: X-Received: by 127.0.0.2 with SMTP id JHhkYY1788612x0o4TJjsSEh; Thu, 20 Jan 2022 10:17:31 -0800 X-Received: from smtp-fw-6002.amazon.com (smtp-fw-6002.amazon.com [52.95.49.90]) by mx.groups.io with SMTP id smtpd.web11.15072.1642698803425094157 for ; Thu, 20 Jan 2022 09:13:23 -0800 X-IronPort-AV: E=Sophos;i="5.88,302,1635206400"; d="scan'208";a="170417474" X-Received: from iad12-co-svc-p1-lb1-vlan2.amazon.com (HELO email-inbound-relay-iad-1d-5a6d5c37.us-east-1.amazon.com) ([10.43.8.2]) by smtp-border-fw-6002.iad6.amazon.com with ESMTP; 20 Jan 2022 17:13:13 +0000 X-Received: from EX13D49EUC003.ant.amazon.com (iad12-ws-svc-p26-lb9-vlan2.iad.amazon.com [10.40.163.34]) by email-inbound-relay-iad-1d-5a6d5c37.us-east-1.amazon.com (Postfix) with ESMTPS id 1CE97C09A2; Thu, 20 Jan 2022 17:13:11 +0000 (UTC) X-Received: from ub4014a598e6c52.ant.amazon.com (10.43.162.8) by EX13D49EUC003.ant.amazon.com (10.43.164.91) with Microsoft SMTP Server (TLS) id 15.0.1497.28; Thu, 20 Jan 2022 17:13:08 +0000 From: "Ojeda Leon, Nicolas via groups.io" To: CC: , Nicolas Ojeda Leon , Alexander Graf , Gerd Hoffmann Subject: [edk2-devel] [PATCH v2 7/8] MdeModulePkg/Pci MdePkg: Create service to retrieve PCI base addresses Date: Thu, 20 Jan 2022 18:10:20 +0100 Message-ID: In-Reply-To: References: MIME-Version: 1.0 X-Originating-IP: [10.43.162.8] X-ClientProxiedBy: EX13D12UWA004.ant.amazon.com (10.43.160.168) To EX13D49EUC003.ant.amazon.com (10.43.164.91) Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,ncoleon@amazon.com X-Gm-Message-State: zHahCaRNYpU7Fj1ekSrtJwoWx1787277AA= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1642702651; bh=kEJwuYtoOWuHAXM1EEu1N+h7VeykDKeYJemg5rUbjBc=; h=CC:Content-Type:Date:From:Reply-To:Subject:To; b=nn9ZKW2e41wNXIHAg03Skbj95XIF80O9IIfzWE/4kx/prMsAYUGHIuQwnH5I/KOJPXm 8dlkXr8CkHtVWCXk/n7ZcHwZxj6Va7Taaab1bt09qSzlK774sIj71Otbp/wy42sIlV0+O BqlkeTXvqlpT6fzauLT6G36zw55uMwRZ6Cw= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1642702654056100023 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Extend the PCI host bridge resource allocation protocol to include one more service that retrieves the base addresses of all resources of a given root bridge. The service is defined to provide, on runtime, the possibility to fetch the base addresses of a root bridge, replicating the address alignment used when placing the host bridge's resources in the Gcd memory map. The intention of this service, initially, is to allow the PCI allocation process to get the base addresses before allocating the individual BARs grouped under a root bridge. This enables the placing logic to be enhanced to account and calculate offsets for pre-populated BARs (PCI devices' BARs that are already configured and need to be respected). Cc: Alexander Graf Cc: Gerd Hoffmann Signed-off-by: Nicolas Ojeda Leon --- MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c | 10 +++ .../Bus/Pci/PciHostBridgeDxe/PciHostBridge.c | 81 +++++++++++++++++++ .../Bus/Pci/PciHostBridgeDxe/PciHostBridge.h | 29 +++++++ .../PciHostBridgeResourceAllocation.h | 33 ++++++++ 4 files changed, 153 insertions(+) diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c b/MdeModulePkg/Bus/Pci= /PciBusDxe/PciLib.c index 63d149b3b8..2ffbc08256 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c @@ -582,6 +582,16 @@ PciHostBridgeResourceAllocator ( PciResUsageTypical ); =20 + Status =3D PciResAlloc->GetResourcesBases ( + PciResAlloc, + RootBridgeDev->Handle, + &IoBase, + &Mem32Base, + &PMem32Base, + &Mem64Base, + &PMem64Base + ); + // // Get the max ROM size that the root bridge can process // Insert to resource map so that there will be dedicate MEM32 resou= rce range for Option ROM. diff --git a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c b/MdeMod= ulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c index b20bcd310a..ddd31f78d6 100644 --- a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c +++ b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c @@ -591,6 +591,7 @@ InitializePciHostBridge ( HostBridge->ResAlloc.SubmitResources =3D SubmitResources; HostBridge->ResAlloc.GetProposedResources =3D GetProposedResources; HostBridge->ResAlloc.PreprocessController =3D PreprocessController; + HostBridge->ResAlloc.GetResourcesBases =3D GetResourcesBases; =20 Status =3D gBS->InstallMultipleProtocolInterfaces ( &HostBridge->Handle, @@ -1734,3 +1735,83 @@ PreprocessController ( =20 return EFI_INVALID_PARAMETER; } + +/** + + Retrieve the aligned base addresses for all resources of a root bridge. + + @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PRO= TOCOL instance. + @param RootBridgeHandle RootBridgeHandle returned by GetNextRootBridge = to locate the + root bridge of interest among the list of root = bridges. + @param IoBase Returns the PIO aperture base address. + @param Mem32Base Returns the 32-bit aperture base address. + @param PMem32Base Returns the 32-bit prefetchable aperture base a= ddress. + @param Mem64Base Returns the 64-bit aperture base address. + @param PMem64Base Returns the 64-bit prefetchable aperture base a= ddress. + + @retval EFI_SUCCESS Succeed. + @retval EFI_NOT_FOUND Root bridge was not found. + +**/ +EFI_STATUS +EFIAPI +GetResourcesBases ( + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, + IN EFI_HANDLE RootBridgeHandle, + OUT UINT64 *IoBase, + OUT UINT64 *Mem32Base, + OUT UINT64 *PMem32Base, + OUT UINT64 *Mem64Base, + OUT UINT64 *PMem64Base + ) +{ + PCI_HOST_BRIDGE_INSTANCE *HostBridge; + PCI_ROOT_BRIDGE_INSTANCE *RootBridge; + LIST_ENTRY *Link; + UINT64 Alignment; + UINTN BitsOfAlignment; + + HostBridge =3D PCI_HOST_BRIDGE_FROM_THIS (This); + + for (Link =3D GetFirstNode (&HostBridge->RootBridges) + ; !IsNull (&HostBridge->RootBridges, Link) + ; Link =3D GetNextNode (&HostBridge->RootBridges, Link) + ) + { + RootBridge =3D ROOT_BRIDGE_FROM_LINK (Link); + + if (RootBridgeHandle =3D=3D RootBridge->Handle) { + // + // Have to make sure Alignment is handled since we are doing direct = address allocation + // + Alignment =3D RootBridge->ResAllocNode[TypeIo].Alignment; + BitsOfAlignment =3D MIN (15, LowBitSet64 (Alignment + 1)); + *IoBase =3D ALIGN_VALUE (RootBridge->Io.Base, Alignment + 1); + *IoBase =3D ALIGN_VALUE (*IoBase, LShiftU64 (1, BitsOfAlignm= ent)); + + Alignment =3D RootBridge->ResAllocNode[TypeMem32].Alignment; + BitsOfAlignment =3D MIN (31, LowBitSet64 (Alignment + 1)); + *Mem32Base =3D ALIGN_VALUE (RootBridge->Mem.Base, Alignment + 1= ); + *Mem32Base =3D ALIGN_VALUE (*Mem32Base, LShiftU64 (1, BitsOfAli= gnment)); + + Alignment =3D RootBridge->ResAllocNode[TypePMem32].Alignment; + BitsOfAlignment =3D MIN (31, LowBitSet64 (Alignment + 1)); + *PMem32Base =3D ALIGN_VALUE (RootBridge->PMem.Base, Alignment + = 1); + *PMem32Base =3D ALIGN_VALUE (*PMem32Base, LShiftU64 (1, BitsOfAl= ignment)); + + Alignment =3D RootBridge->ResAllocNode[TypeMem64].Alignment; + BitsOfAlignment =3D MIN (63, LowBitSet64 (Alignment + 1)); + *Mem64Base =3D ALIGN_VALUE (RootBridge->MemAbove4G.Base, Alignm= ent + 1); + *Mem64Base =3D ALIGN_VALUE (*Mem64Base, LShiftU64 (1, BitsOfAli= gnment)); + + Alignment =3D RootBridge->ResAllocNode[TypePMem64].Alignment; + BitsOfAlignment =3D MIN (63, LowBitSet64 (Alignment + 1)); + *PMem64Base =3D ALIGN_VALUE (RootBridge->PMemAbove4G.Base, Align= ment + 1); + *PMem64Base =3D ALIGN_VALUE (*PMem64Base, LShiftU64 (1, BitsOfAl= ignment)); + + return EFI_SUCCESS; + } + } + + return EFI_NOT_FOUND; +} diff --git a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.h b/MdeMod= ulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.h index e7a30fd909..07ba496602 100644 --- a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.h +++ b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.h @@ -240,6 +240,35 @@ PreprocessController ( IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase ); =20 +/** + + Retrieve the aligned base addresses for all resources of a root bridge. + + @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PRO= TOCOL instance. + @param RootBridgeHandle RootBridgeHandle returned by GetNextRootBridge = to locate the + root bridge of interest among the list of root = bridges. + @param IoBase Returns the PIO aperture base address. + @param Mem32Base Returns the 32-bit aperture base address. + @param PMem32Base Returns the 32-bit prefetchable aperture base a= ddress. + @param Mem64Base Returns the 64-bit aperture base address. + @param PMem64Base Returns the 64-bit prefetchable aperture base a= ddress. + + @retval EFI_SUCCESS Succeed. + @retval EFI_NOT_FOUND Root bridge was not found. + +**/ +EFI_STATUS +EFIAPI +GetResourcesBases ( + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, + IN EFI_HANDLE RootBridgeHandle, + OUT UINT64 *IoBase, + OUT UINT64 *Mem32Base, + OUT UINT64 *PMem32Base, + OUT UINT64 *Mem64Base, + OUT UINT64 *PMem64Base + ); + /** This routine constructs the resource descriptors for all root bridges an= d call PciHostBridgeResourceConflict(). =20 diff --git a/MdePkg/Include/Protocol/PciHostBridgeResourceAllocation.h b/Md= ePkg/Include/Protocol/PciHostBridgeResourceAllocation.h index 5ef7c000d6..ab91acb174 100644 --- a/MdePkg/Include/Protocol/PciHostBridgeResourceAllocation.h +++ b/MdePkg/Include/Protocol/PciHostBridgeResourceAllocation.h @@ -367,6 +367,33 @@ EFI_STATUS IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase ); =20 +/** + Retrieves the base addresses of ost bridge resources. + + @param This The pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE= _ALLOCATION_PROTOCOL instance. + @param RootBridgeHandle The PCI root bridge handle. + @param IoBase The pointer to PIO aperture base address. + @param Mem32Base The pointer to 32-bit aperture base address. + @param PMem32Base The pointer to 32-bit prefetchable aperture bas= e address. + @param Mem64Base The pointer to 64-bit aperture base address. + @param PMem64Base The pointer to 64-bit prefetchable aperture bas= e address. + + @retval EFI_SUCCESS Succeed. + @retval EFI_NOT_FOUND Root bridge was not found. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL_GET_RESOURCES_BA= SES)( + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, + IN EFI_HANDLE RootBridgeHandle, + OUT UINT64 *IoBase, + OUT UINT64 *Mem32Base, + OUT UINT64 *PMem32Base, + OUT UINT64 *Mem64Base, + OUT UINT64 *PMem64Base + ); + /// /// Provides the basic interfaces to abstract a PCI host bridge resource a= llocation. /// @@ -415,6 +442,12 @@ struct _EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOC= OL { /// before enumeration. /// EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL_PREPROCESS_CONTROLLER = PreprocessController; + + /// + /// Returns the aligned base addresses of the different resource windows + /// of the host bridge. Intended for use before resources are submitted. + /// + EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL_GET_RESOURCES_BASES = GetResourcesBases; }; =20 extern EFI_GUID gEfiPciHostBridgeResourceAllocationProtocolGuid; --=20 2.17.1 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 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#85879): https://edk2.groups.io/g/devel/message/85879 Mute This Topic: https://groups.io/mt/88565410/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Sun Apr 28 21:49:04 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+85878+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+85878+1787277+3901457@groups.io ARC-Seal: i=1; a=rsa-sha256; t=1642702651; cv=none; d=zohomail.com; s=zohoarc; b=Hva+5QX0WjMwFfUgX0bQNWRGVzf0tKyFNX9m6sbvPJaOE0EvphNyomsZOdfqhXLSmqU8Kr8AFBCKowbo/w47URmFJRknns0+6rwH/zonWd6HSfUXhoG9bdV5HNR9UUH4o0IZ0Onos8VyJ6tJJv2TzsbBTKnZ6JyQy6MFeYcjU1o= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1642702651; h=Content-Type:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=LAEx8qe9ErF2OCT0QoeMJk6rHDvVObfAUAH8irQSnvU=; b=KaKL8CAE00QxwONB5bKqgKP4t58LZ5qUWCB9hkbYiAiQPArQ5m6mLYP5MsWO+wMP67Y0U75R5AEDGYWpPV44nhNtwciQrApVJ91iKnLg2TIfkiyYtVdGbBQU8ZoNhOF5J1IzAisqSvyuMJDUrkI05UljKvH9m8mfYRbly0CxkjY= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+85878+1787277+3901457@groups.io Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1642702651127721.2779643598615; Thu, 20 Jan 2022 10:17:31 -0800 (PST) Return-Path: X-Received: by 127.0.0.2 with SMTP id Q8sxYY1788612xSo8ofiU12T; Thu, 20 Jan 2022 10:17:30 -0800 X-Received: from smtp-fw-9103.amazon.com (smtp-fw-9103.amazon.com [207.171.188.200]) by mx.groups.io with SMTP id smtpd.web12.14837.1642698799567143219 for ; Thu, 20 Jan 2022 09:13:19 -0800 X-IronPort-AV: E=Sophos;i="5.88,302,1635206400"; d="scan'208";a="986096369" X-Received: from pdx4-co-svc-p1-lb2-vlan2.amazon.com (HELO email-inbound-relay-iad-1d-5a6d5c37.us-east-1.amazon.com) ([10.25.36.210]) by smtp-border-fw-9103.sea19.amazon.com with ESMTP; 20 Jan 2022 17:13:18 +0000 X-Received: from EX13D49EUC003.ant.amazon.com (iad12-ws-svc-p26-lb9-vlan2.iad.amazon.com [10.40.163.34]) by email-inbound-relay-iad-1d-5a6d5c37.us-east-1.amazon.com (Postfix) with ESMTPS id 4829EC098E; Thu, 20 Jan 2022 17:13:17 +0000 (UTC) X-Received: from ub4014a598e6c52.ant.amazon.com (10.43.162.8) by EX13D49EUC003.ant.amazon.com (10.43.164.91) with Microsoft SMTP Server (TLS) id 15.0.1497.28; Thu, 20 Jan 2022 17:13:14 +0000 From: "Ojeda Leon, Nicolas via groups.io" To: CC: , Nicolas Ojeda Leon , Alexander Graf , Gerd Hoffmann Subject: [edk2-devel] [PATCH v2 8/8] MdeModulePkg/PciBusDxe: Handling of pre-populated PCI BARs Date: Thu, 20 Jan 2022 18:10:21 +0100 Message-ID: <51882a6a217cd7e2b560ea00f6601db4c9f27b42.1642697671.git.ncoleon@amazon.com> In-Reply-To: References: MIME-Version: 1.0 X-Originating-IP: [10.43.162.8] X-ClientProxiedBy: EX13D12UWA004.ant.amazon.com (10.43.160.168) To EX13D49EUC003.ant.amazon.com (10.43.164.91) Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,ncoleon@amazon.com X-Gm-Message-State: MVTplFv3T4XNwKdRAnEO0DcDx1787277AA= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1642702650; bh=bDZacKeO1JLGGGJBRKVCEk1kX5mJMz+2//Aqlfai254=; h=CC:Content-Type:Date:From:Reply-To:Subject:To; b=lEPqbucaOMeO4Y2qCCD3sg49ZJEoiklKuQnIkBFJaIKTMHe4hRxLHf0T0F44X3f7/J9 nB4bwvdbibruqL1OfUdbFr+abDfAs7nx/1TmYhVNgnvt2bFhBaQxomG4l1tWgHTjeQmjk cm0gjJlv+dSFptBRPQRaOD2TG8As11kGQbk= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1642702651807100018 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Extend the PCI BAR placement logic in order to consider pre-populated resources first, if indicated by the Pcd token for such purpose. The PCI_BAR type is augmented by one field for mapping the absolute address of prepopulated BARs into a root bridge relative offset. As part of the CreateResourceMap stage of the PCI resource allocation process, all the resources belonging to a root bridge are analyzed and if a BaseAddress (absolute address read from the PCI device during enumeration) is present, it is translated into a root-bridge relative offset and the space occupied by it is marked as used in the root bridge's aperture. This process is performed before the regular placement logic is executed. The remaining unassigned BARs are then placed according to default logic starting after the last pre-populated resource. The motivation behind respecting pre-populated BARs is that the hypervisor can decide on placement of some resources and the guest must use the same values to benefit from performance optimizations or specific requirements. Cc: Alexander Graf Cc: Gerd Hoffmann Signed-off-by: Nicolas Ojeda Leon --- MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h | 1 + .../Bus/Pci/PciBusDxe/PciEnumeratorSupport.c | 5 +- MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c | 11 + .../Bus/Pci/PciBusDxe/PciResourceSupport.c | 277 +++++++++++++++++- .../Bus/Pci/PciBusDxe/PciResourceSupport.h | 20 ++ 5 files changed, 310 insertions(+), 4 deletions(-) diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h b/MdeModulePkg/Bus/Pci= /PciBusDxe/PciBus.h index 4b58c3ea9b..9218566bf6 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h @@ -94,6 +94,7 @@ typedef enum { // struct _PCI_BAR { UINT64 BaseAddress; + UINT64 BaseAddressOffset; UINT64 Length; UINT64 Alignment; PCI_BAR_TYPE BarType; diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c b/MdeMod= ulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c index 9251388bc2..91caf162e0 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c @@ -1776,8 +1776,9 @@ PciParseBar ( return Offset + 4; } =20 - PciIoDevice->PciBar[BarIndex].BarTypeFixed =3D FALSE; - PciIoDevice->PciBar[BarIndex].Offset =3D (UINT8)Offset; + PciIoDevice->PciBar[BarIndex].BarTypeFixed =3D FALSE; + PciIoDevice->PciBar[BarIndex].Offset =3D (UINT8)Offset; + PciIoDevice->PciBar[BarIndex].BaseAddressOffset =3D 0; if ((Value & 0x01) !=3D 0) { // // Device I/Os diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c b/MdeModulePkg/Bus/Pci= /PciBusDxe/PciLib.c index 2ffbc08256..452ca10540 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c @@ -605,6 +605,17 @@ PciHostBridgeResourceAllocator ( GetResourceFromDevice (RootBridgeDev, IoBridge, Mem32Bridge, PMem3= 2Bridge, Mem64Bridge, PMem64Bridge); } =20 + // + // Handle pre-populated resources + // + PopulateResourceAperture ( + Mem32Base, + PMem32Base, + Mem64Base, + PMem64Base, + RootBridgeDev + ); + // // Create resourcemap by going through all the devices subject to th= is root bridge // diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c b/MdeModul= ePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c index 8ffd05f327..e2a550bf8e 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c @@ -324,6 +324,266 @@ CalculateApertureIo16 ( Bridge->Length =3D MAX (Bridge->Length, PaddingAperture); } =20 +/** + Analyze a single BAR and if it is pre-populated (its baseAddress is alre= ady + set), calculate the offset inside the root bridge. + + @param Bar PCI BAR to be placed if pre-populated + @param Base Base address of the root bridge + +**/ +STATIC +VOID +PrePopulateBAR ( + IN OUT PCI_BAR *Bar, + IN UINT64 Base + ) +{ + if (Base =3D=3D gAllOne) { + return; + } + + // + // Pre-populated IO space BARs are not supported + // + if ((Bar->BarType =3D=3D PciBarTypeIo16) || (Bar->BarType =3D=3D PciBarT= ypeIo32)) { + return; + } + + if (Bar->BaseAddress < Base) { + return; + } + + if (Bar->BaseAddress !=3D 0) { + Bar->BaseAddressOffset =3D Bar->BaseAddress - Base; + } +} + +/** + Calculate and set the address offset inside the root bridge of device + BARs that are pre-populated. + + @param Dev PCI device whose BARs are to be analyzed + @param Base Base address of the root bridge under which the device + is located. + + */ +STATIC +VOID +PopulateDeviceBars ( + IN UINT64 Mem32Base, + IN UINT64 PMem32Base, + IN UINT64 Mem64Base, + IN UINT64 PMem64Base, + IN PCI_IO_DEVICE *Dev + ) +{ + UINTN Index; + + for (Index =3D 0; Index < PCI_MAX_BAR; Index++) { + switch (Dev->PciBar[Index].BarType) { + case PciBarTypeMem32: + PrePopulateBAR (&Dev->PciBar[Index], Mem32Base); + break; + + case PciBarTypePMem32: + PrePopulateBAR (&Dev->PciBar[Index], PMem32Base); + break; + + case PciBarTypeMem64: + PrePopulateBAR (&Dev->PciBar[Index], Mem64Base); + break; + + case PciBarTypePMem64: + PrePopulateBAR (&Dev->PciBar[Index], PMem64Base); + break; + + default: + break; + } + } +} + +/** + Considering the Bridge attributes specifying the supported resources, + merge the base addresses to fake the non-suported types belonging to + the alternative type. + + @param Mem32Base 32-bit base address + @param PMem32Base 32-bit prefetchable base address + @param Mem64Base 64-bit base address + @param PMem64Base 64-bit prefetchable base address + @param Bridge PCI resource node for given bridge device. + + */ +STATIC +VOID +MergeBridgeResourceBases ( + IN OUT UINT64 *Mem32Base, + IN OUT UINT64 *PMem32Base, + IN OUT UINT64 *Mem64Base, + IN OUT UINT64 *PMem64Base, + IN PCI_IO_DEVICE *Bridge + ) +{ + // + // if root bridge supports combined Pmem Mem decoding + // merge these two type of resource + // + if (BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_PMEM_MEM_COMBINE_SUP= PORTED)) { + *PMem32Base =3D *Mem32Base; + *PMem64Base =3D *Mem64Base; + } + + // + // If bridge doesn't support Pmem32 + // degrade it to mem32 + // + if (!BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_PMEM32_DECODE_SUPPO= RTED)) { + *PMem32Base =3D *Mem32Base; + } + + // + // If firmware is in 32-bit mode, + // then degrade PMEM64/MEM64 requests + // + if (sizeof (UINTN) <=3D 4) { + *Mem64Base =3D *Mem32Base; + *PMem64Base =3D *PMem32Base; + } else { + // + // if the bridge does not support MEM64, degrade MEM64 to MEM32 + // + if (!BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_MEM64_DECODE_SUPP= ORTED)) { + *Mem64Base =3D *Mem32Base; + } + + // + // if the bridge does not support PMEM64, degrade PMEM64 to PMEM32 + // + if (!BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_PMEM64_DECODE_SUP= PORTED)) { + *PMem64Base =3D *PMem32Base; + } + } +} + +/** + Populate a root bridge's resource aperture according to + initial conditions ruled by individual pre-populated + resources + + @param Bridge PCI resource node for given bridge device. + @param Base Resource aperture base address + +**/ +VOID +PopulateResourceAperture ( + IN UINT64 Mem32Base, + IN UINT64 PMem32Base, + IN UINT64 Mem64Base, + IN UINT64 PMem64Base, + IN OUT PCI_IO_DEVICE *Bridge + ) +{ + PCI_IO_DEVICE *Temp; + LIST_ENTRY *CurrentLink; + + // + // Verify if pre-populated BARs need to be respected, otherwise + // there is no need to pre-populate any resource + // + if (!PcdGetBool (PcdPciPreservePopulatedMappings)) { + return; + } + + CurrentLink =3D Bridge->ChildList.ForwardLink; + + // + // Merge base addresses of the different types depending on resource + // decoding supported by the bridge + // + MergeBridgeResourceBases ( + &Mem32Base, + &PMem32Base, + &Mem64Base, + &PMem64Base, + Bridge + ); + + while (CurrentLink !=3D NULL && CurrentLink !=3D &Bridge->ChildList) { + Temp =3D PCI_IO_DEVICE_FROM_LINK (CurrentLink); + + PopulateDeviceBars ( + Mem32Base, + PMem32Base, + Mem64Base, + PMem64Base, + Temp + ); + + // + // Recursive call to analyze the hierarchical tree under a bridge + // + if (IS_PCI_BRIDGE (&Temp->Pci)) { + PopulateResourceAperture ( + Mem32Base, + PMem32Base, + Mem64Base, + PMem64Base, + Temp + ); + } + + CurrentLink =3D CurrentLink->ForwardLink; + } +} + +/** + Calculate the current used resource of the bridge provided that some + of the resources under it might been pre-populated. + + @param Bridge PCI resource node for given bridge device. + +**/ +STATIC +UINT64 +GetBridgePopulatedAperture ( + IN PCI_RESOURCE_NODE *Bridge + ) +{ + UINT64 Aperture; + UINT64 EndAddress; + LIST_ENTRY *CurrentLink; + PCI_RESOURCE_NODE *Node; + PCI_BAR *Bar; + + Aperture =3D 0; + + // + // Analyze all resource nodes looking for the prepopulated with the + // highest address used. + // + for ( CurrentLink =3D GetFirstNode (&Bridge->ChildList) + ; !IsNull (&Bridge->ChildList, CurrentLink) + ; CurrentLink =3D GetNextNode (&Bridge->ChildList, CurrentLink) + ) + { + Node =3D RESOURCE_NODE_FROM_LINK (CurrentLink); + + Bar =3D &Node->PciDev->PciBar[Node->Bar]; + + if (Bar->BaseAddress !=3D 0) { + EndAddress =3D Bar->BaseAddressOffset + Bar->Length; + + if (EndAddress > Aperture) { + Aperture =3D EndAddress; + } + } + } + + return Aperture; +} + /** This function is used to calculate the resource aperture for a given bridge device. @@ -337,6 +597,7 @@ CalculateResourceAperture ( ) { UINT64 Aperture[2]; + UINT64 InitialAperture; LIST_ENTRY *CurrentLink; PCI_RESOURCE_NODE *Node; =20 @@ -349,8 +610,14 @@ CalculateResourceAperture ( return; } =20 - Aperture[PciResUsageTypical] =3D 0; - Aperture[PciResUsagePadding] =3D 0; + // + // Initialize apertures at bridge's current resource usage + // which might be occupied by pre-populated resources. + // + InitialAperture =3D GetBridgePopulatedAperture (Bridge); + Aperture[PciResUsageTypical] =3D InitialAperture; + Aperture[PciResUsagePadding] =3D InitialAperture; + // // Assume the bridge is aligned // @@ -361,6 +628,12 @@ CalculateResourceAperture ( { Node =3D RESOURCE_NODE_FROM_LINK (CurrentLink); =20 + PCI_BAR *Bar =3D &Node->PciDev->PciBar[Node->Bar]; + if (PcdGetBool (PcdPciPreservePopulatedMappings) && Bar->BaseAddress) { + Node->Offset =3D Bar->BaseAddressOffset; + continue; + } + // // It's possible for a bridge to contain multiple padding resource // nodes due to DegradeResource(). diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.h b/MdeModul= ePkg/Bus/Pci/PciBusDxe/PciResourceSupport.h index 1527d4eafa..c5ab5f3fd9 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.h +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.h @@ -111,6 +111,26 @@ CalculateApertureIo16 ( IN PCI_RESOURCE_NODE *Bridge ); =20 +/** + Populate a root bridge's resource aperture according to + initial conditions ruled by individual pre-populated + resources + + @note Pre-populated PIO BARs are not supported. + + @param Bridge PCI resource node for given bridge device. + @param Base Resource aperture base address + +**/ +VOID +PopulateResourceAperture ( + IN UINT64 Mem32Base, + IN UINT64 PMem32Base, + IN UINT64 Mem64Base, + IN UINT64 PMem64Base, + IN OUT PCI_IO_DEVICE *Bridge + ); + /** This function is used to calculate the resource aperture for a given bridge device. --=20 2.17.1 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 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#85878): https://edk2.groups.io/g/devel/message/85878 Mute This Topic: https://groups.io/mt/88565409/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-