From nobody Mon Feb 9 08:56:44 2026 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+75682+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+75682+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1622060924; cv=none; d=zohomail.com; s=zohoarc; b=mtqEyA8sn/wB3qWx1IvACkMJpGjhjRiBmDo7C9oXUCDNTBG6PY5SbsbnFzYgSEVO/QavhZtNpg/a36k3WQ5gXtY9awe6RtQ8TvC5fMEeFQnHlq6KdfrnZLkW8FODXyM26zYwCnTABMzQLbwpxwcxsO04ZqOp9M49Ch3ux061mrg= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1622060924; h=Content-Type:Content-Transfer-Encoding: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=MKlrGvey2smXbo3yov2sr5jJ6hEcWMkaPglLQsEhO4o=; b=DupFummRbmPGyAVGwKJqlWAqA46ugfRt5F154htBlhNn6Com2LYbyeE2AryFRhQP+wmnKC1O8Bs4fejUKuvp4/k65Pk+/1yAVbT8vMkrd/HuqPI6VGUdGjiwXt4Lt0rDmj6wPPO6jQXbba7wr0ubkI6sKOxC1dmwCNxY4AOs98k= 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+75682+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) header.from= Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1622060924260749.1414690071125; Wed, 26 May 2021 13:28:44 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id RL2YYY1788612xEE4wsLN8g6; Wed, 26 May 2021 13:28:43 -0700 X-Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by mx.groups.io with SMTP id smtpd.web11.2921.1622060917760361928 for ; Wed, 26 May 2021 13:28:38 -0700 X-Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-208-TrWGICKiMXiAdQnsvNpXWg-1; Wed, 26 May 2021 16:28:33 -0400 X-MC-Unique: TrWGICKiMXiAdQnsvNpXWg-1 X-Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 01CF2101371E; Wed, 26 May 2021 20:28:32 +0000 (UTC) X-Received: from lacos-laptop-7.usersys.redhat.com (ovpn-114-61.ams2.redhat.com [10.36.114.61]) by smtp.corp.redhat.com (Postfix) with ESMTP id D573016935; Wed, 26 May 2021 20:28:29 +0000 (UTC) From: "Laszlo Ersek" To: devel@edk2.groups.io Cc: Anthony Perard , Ard Biesheuvel , Jordan Justen , Julien Grall , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Subject: [edk2-devel] [PATCH 13/43] OvmfPkg/XenAcpiPlatformDxe: remove the QEMU ACPI linker/loader client Date: Wed, 26 May 2021 22:14:16 +0200 Message-Id: <20210526201446.12554-14-lersek@redhat.com> In-Reply-To: <20210526201446.12554-1-lersek@redhat.com> References: <20210526201446.12554-1-lersek@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com 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,lersek@redhat.com X-Gm-Message-State: 3XdsvVpU2kJt390C678XFDqqx1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1622060923; bh=MKlrGvey2smXbo3yov2sr5jJ6hEcWMkaPglLQsEhO4o=; h=Cc:Content-Type:Date:From:Reply-To:Subject:To; b=bhserO72eNO1CheeQ8mnirqgsGInPhPvn4G7HEQleZsjmBn6LGVt0yYvUZ+N+IqfWqT fPMGhbeZKVy8QVZhq9kQ3H/qLdVP2af4sT4lvgp1T6VM+b2OBlxwnpczRNXYnVnLJFK/2 A2eZPiUCbu22Z8MohsP4HN3AoSzfEwv3jg8= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Type: text/plain; charset="utf-8" The root of the QEMU ACPI linker/loader client in XenAcpiPlatformDxe is the InstallQemuFwCfgTables() function. This function always fails on Xen, due to its top-most QemuFwCfgFindFile() call. Remove the InstallQemuFwCfgTables() function call from XenAcpiPlatformDxe, along with all dependencies that now become unused. Cc: Anthony Perard Cc: Ard Biesheuvel Cc: Jordan Justen Cc: Julien Grall Cc: Philippe Mathieu-Daud=C3=A9 Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=3D2122 Signed-off-by: Laszlo Ersek Reviewed-by: Philippe Mathieu-Daude --- OvmfPkg/XenAcpiPlatformDxe/XenAcpiPlatformDxe.inf | 6 - OvmfPkg/XenAcpiPlatformDxe/AcpiPlatform.h | 51 - OvmfPkg/XenAcpiPlatformDxe/AcpiPlatform.c | 2 +- OvmfPkg/XenAcpiPlatformDxe/BootScript.c | 269 ----- OvmfPkg/XenAcpiPlatformDxe/PciDecoding.c | 194 ---- OvmfPkg/XenAcpiPlatformDxe/QemuFwCfgAcpi.c | 1196 -----------------= --- 6 files changed, 1 insertion(+), 1717 deletions(-) diff --git a/OvmfPkg/XenAcpiPlatformDxe/XenAcpiPlatformDxe.inf b/OvmfPkg/Xe= nAcpiPlatformDxe/XenAcpiPlatformDxe.inf index 379b5d56d565..72132e397dc1 100644 --- a/OvmfPkg/XenAcpiPlatformDxe/XenAcpiPlatformDxe.inf +++ b/OvmfPkg/XenAcpiPlatformDxe/XenAcpiPlatformDxe.inf @@ -21,17 +21,14 @@ [Defines] # VALID_ARCHITECTURES =3D IA32 X64 EBC # =20 [Sources] AcpiPlatform.c AcpiPlatform.h - BootScript.c EntryPoint.c - PciDecoding.c Qemu.c - QemuFwCfgAcpi.c Xen.c =20 [Packages] MdeModulePkg/MdeModulePkg.dec MdePkg/MdePkg.dec OvmfPkg/OvmfPkg.dec @@ -40,24 +37,21 @@ [Packages] [LibraryClasses] BaseLib BaseMemoryLib DebugLib DxeServicesTableLib MemoryAllocationLib - OrderedCollectionLib PcdLib QemuFwCfgLib - QemuFwCfgS3Lib UefiBootServicesTableLib UefiDriverEntryPoint XenPlatformLib =20 [Protocols] gEfiAcpiTableProtocolGuid # PROTOCOL ALWAYS_CONSUMED gEfiFirmwareVolume2ProtocolGuid # PROTOCOL SOMETIMES_CONSU= MED - gEfiPciIoProtocolGuid # PROTOCOL SOMETIMES_CONSU= MED =20 [Guids] gRootBridgesConnectedEventGroupGuid =20 [Pcd] gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiTableStorageFile diff --git a/OvmfPkg/XenAcpiPlatformDxe/AcpiPlatform.h b/OvmfPkg/XenAcpiPla= tformDxe/AcpiPlatform.h index 6259697c4b2d..d35143a00d01 100644 --- a/OvmfPkg/XenAcpiPlatformDxe/AcpiPlatform.h +++ b/OvmfPkg/XenAcpiPlatformDxe/AcpiPlatform.h @@ -8,20 +8,12 @@ **/ =20 #ifndef ACPI_PLATFORM_H_ #define ACPI_PLATFORM_H_ =20 #include // EFI_ACPI_TABLE_PROTOCOL -#include // EFI_PCI_IO_PROTOCOL - -typedef struct { - EFI_PCI_IO_PROTOCOL *PciIo; - UINT64 PciAttributes; -} ORIGINAL_ATTRIBUTES; - -typedef struct S3_CONTEXT S3_CONTEXT; =20 EFI_STATUS EFIAPI InstallAcpiTable ( IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol, IN VOID *AcpiTableBuffer, @@ -46,57 +38,14 @@ QemuInstallAcpiTable ( EFI_STATUS EFIAPI InstallXenTables ( IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol ); =20 -EFI_STATUS -EFIAPI -InstallQemuFwCfgTables ( - IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol - ); - EFI_STATUS EFIAPI InstallAcpiTables ( IN EFI_ACPI_TABLE_PROTOCOL *AcpiTable ); =20 -VOID -EnablePciDecoding ( - OUT ORIGINAL_ATTRIBUTES **OriginalAttributes, - OUT UINTN *Count - ); - -VOID -RestorePciDecoding ( - IN ORIGINAL_ATTRIBUTES *OriginalAttributes, - IN UINTN Count - ); - -EFI_STATUS -AllocateS3Context ( - OUT S3_CONTEXT **S3Context, - IN UINTN WritePointerCount - ); - -VOID -ReleaseS3Context ( - IN S3_CONTEXT *S3Context - ); - -EFI_STATUS -SaveCondensedWritePointerToS3Context ( - IN OUT S3_CONTEXT *S3Context, - IN UINT16 PointerItem, - IN UINT8 PointerSize, - IN UINT32 PointerOffset, - IN UINT64 PointerValue - ); - -EFI_STATUS -TransferS3ContextToBootScript ( - IN S3_CONTEXT *S3Context - ); - #endif =20 diff --git a/OvmfPkg/XenAcpiPlatformDxe/AcpiPlatform.c b/OvmfPkg/XenAcpiPla= tformDxe/AcpiPlatform.c index 2b2dc576754b..9c8b1e0fcffa 100644 --- a/OvmfPkg/XenAcpiPlatformDxe/AcpiPlatform.c +++ b/OvmfPkg/XenAcpiPlatformDxe/AcpiPlatform.c @@ -253,13 +253,13 @@ InstallAcpiTables ( { EFI_STATUS Status; =20 if (XenDetected ()) { Status =3D InstallXenTables (AcpiTable); } else { - Status =3D InstallQemuFwCfgTables (AcpiTable); + Status =3D EFI_UNSUPPORTED; } =20 if (EFI_ERROR (Status)) { Status =3D InstallOvmfFvTables (AcpiTable); } =20 diff --git a/OvmfPkg/XenAcpiPlatformDxe/BootScript.c b/OvmfPkg/XenAcpiPlatf= ormDxe/BootScript.c deleted file mode 100644 index 14d1e68694cb..000000000000 --- a/OvmfPkg/XenAcpiPlatformDxe/BootScript.c +++ /dev/null @@ -1,269 +0,0 @@ -/** @file - Append an ACPI S3 Boot Script fragment from the QEMU_LOADER_WRITE_POINTER - commands of QEMU's fully processed table linker/loader script. - - Copyright (C) 2017-2021, Red Hat, Inc. - - SPDX-License-Identifier: BSD-2-Clause-Patent -**/ - -#include // CpuDeadLoop() -#include // DEBUG() -#include // AllocatePool() -#include // QemuFwCfgS3ScriptSkipBytes() - -#include "AcpiPlatform.h" - - -// -// Condensed structure for capturing the fw_cfg operations -- select, skip, -// write -- inherent in executing a QEMU_LOADER_WRITE_POINTER command. -// -typedef struct { - UINT16 PointerItem; // resolved from QEMU_LOADER_WRITE_POINTER.Pointer= File - UINT8 PointerSize; // copied as-is from QEMU_LOADER_WRITE_POINTER - UINT32 PointerOffset; // copied as-is from QEMU_LOADER_WRITE_POINTER - UINT64 PointerValue; // resolved from QEMU_LOADER_WRITE_POINTER.Pointee= File - // and QEMU_LOADER_WRITE_POINTER.PointeeOffset -} CONDENSED_WRITE_POINTER; - - -// -// Context structure to accumulate CONDENSED_WRITE_POINTER objects from -// QEMU_LOADER_WRITE_POINTER commands. -// -// Any pointers in this structure own the pointed-to objects; that is, whe= n the -// context structure is released, all pointed-to objects must be released = too. -// -struct S3_CONTEXT { - CONDENSED_WRITE_POINTER *WritePointers; // one array element per process= ed - // QEMU_LOADER_WRITE_POINTER - // command - UINTN Allocated; // number of elements allocated = for - // WritePointers - UINTN Used; // number of elements populated = in - // WritePointers -}; - - -// -// Scratch buffer, allocated in EfiReservedMemoryType type memory, for the= ACPI -// S3 Boot Script opcodes to work on. -// -#pragma pack (1) -typedef union { - UINT64 PointerValue; // filled in from CONDENSED_WRITE_POINTER.PointerVa= lue -} SCRATCH_BUFFER; -#pragma pack () - - -/** - Allocate an S3_CONTEXT object. - - @param[out] S3Context The allocated S3_CONTEXT object is returned - through this parameter. - - @param[in] WritePointerCount Number of CONDENSED_WRITE_POINTER elements= to - allocate room for. WritePointerCount must = be - positive. - - @retval EFI_SUCCESS Allocation successful. - - @retval EFI_OUT_OF_RESOURCES Out of memory. - - @retval EFI_INVALID_PARAMETER WritePointerCount is zero. -**/ -EFI_STATUS -AllocateS3Context ( - OUT S3_CONTEXT **S3Context, - IN UINTN WritePointerCount - ) -{ - EFI_STATUS Status; - S3_CONTEXT *Context; - - if (WritePointerCount =3D=3D 0) { - return EFI_INVALID_PARAMETER; - } - - Context =3D AllocateZeroPool (sizeof *Context); - if (Context =3D=3D NULL) { - return EFI_OUT_OF_RESOURCES; - } - - Context->WritePointers =3D AllocatePool (WritePointerCount * - sizeof *Context->WritePointers); - if (Context->WritePointers =3D=3D NULL) { - Status =3D EFI_OUT_OF_RESOURCES; - goto FreeContext; - } - - Context->Allocated =3D WritePointerCount; - *S3Context =3D Context; - return EFI_SUCCESS; - -FreeContext: - FreePool (Context); - - return Status; -} - - -/** - Release an S3_CONTEXT object. - - @param[in] S3Context The object to release. -**/ -VOID -ReleaseS3Context ( - IN S3_CONTEXT *S3Context - ) -{ - FreePool (S3Context->WritePointers); - FreePool (S3Context); -} - - -/** - Save the information necessary to replicate a QEMU_LOADER_WRITE_POINTER - command during S3 resume, in condensed format. - - This function is to be called from ProcessCmdWritePointer(), after all t= he - sanity checks have passed, and before the fw_cfg operations are performe= d. - - @param[in,out] S3Context The S3_CONTEXT object into which the caller wa= nts - to save the information that was derived from - QEMU_LOADER_WRITE_POINTER. - - @param[in] PointerItem The FIRMWARE_CONFIG_ITEM that - QEMU_LOADER_WRITE_POINTER.PointerFile was reso= lved - to, expressed as a UINT16 value. - - @param[in] PointerSize Copied directly from - QEMU_LOADER_WRITE_POINTER.PointerSize. - - @param[in] PointerOffset Copied directly from - QEMU_LOADER_WRITE_POINTER.PointerOffset. - - @param[in] PointerValue The base address of the allocated / downloaded - fw_cfg blob that is identified by - QEMU_LOADER_WRITE_POINTER.PointeeFile, plus - QEMU_LOADER_WRITE_POINTER.PointeeOffset. - - @retval EFI_SUCCESS The information derived from - QEMU_LOADER_WRITE_POINTER has been success= fully - absorbed into S3Context. - - @retval EFI_OUT_OF_RESOURCES No room available in S3Context. -**/ -EFI_STATUS -SaveCondensedWritePointerToS3Context ( - IN OUT S3_CONTEXT *S3Context, - IN UINT16 PointerItem, - IN UINT8 PointerSize, - IN UINT32 PointerOffset, - IN UINT64 PointerValue - ) -{ - CONDENSED_WRITE_POINTER *Condensed; - - if (S3Context->Used =3D=3D S3Context->Allocated) { - return EFI_OUT_OF_RESOURCES; - } - Condensed =3D S3Context->WritePointers + S3Context->Used; - Condensed->PointerItem =3D PointerItem; - Condensed->PointerSize =3D PointerSize; - Condensed->PointerOffset =3D PointerOffset; - Condensed->PointerValue =3D PointerValue; - DEBUG ((DEBUG_VERBOSE, "%a: 0x%04x/[0x%08x+%d] :=3D 0x%Lx (%Lu)\n", - __FUNCTION__, PointerItem, PointerOffset, PointerSize, PointerValue, - (UINT64)S3Context->Used)); - ++S3Context->Used; - return EFI_SUCCESS; -} - - -/** - FW_CFG_BOOT_SCRIPT_CALLBACK_FUNCTION provided to QemuFwCfgS3Lib. -**/ -STATIC -VOID -EFIAPI -AppendFwCfgBootScript ( - IN OUT VOID *Context, OPTIONAL - IN OUT VOID *ExternalScratchBuffer - ) -{ - S3_CONTEXT *S3Context; - SCRATCH_BUFFER *ScratchBuffer; - UINTN Index; - - S3Context =3D Context; - ScratchBuffer =3D ExternalScratchBuffer; - - for (Index =3D 0; Index < S3Context->Used; ++Index) { - CONST CONDENSED_WRITE_POINTER *Condensed; - RETURN_STATUS Status; - - Condensed =3D &S3Context->WritePointers[Index]; - - Status =3D QemuFwCfgS3ScriptSkipBytes (Condensed->PointerItem, - Condensed->PointerOffset); - if (RETURN_ERROR (Status)) { - goto FatalError; - } - - ScratchBuffer->PointerValue =3D Condensed->PointerValue; - Status =3D QemuFwCfgS3ScriptWriteBytes (-1, Condensed->PointerSize); - if (RETURN_ERROR (Status)) { - goto FatalError; - } - } - - DEBUG ((DEBUG_VERBOSE, "%a: boot script fragment saved\n", __FUNCTION__)= ); - - ReleaseS3Context (S3Context); - return; - -FatalError: - ASSERT (FALSE); - CpuDeadLoop (); -} - - -/** - Translate and append the information from an S3_CONTEXT object to the AC= PI S3 - Boot Script. - - The effects of a successful call to this function cannot be undone. - - @param[in] S3Context The S3_CONTEXT object to translate to ACPI S3 Boot - Script opcodes. If the function returns successful= ly, - the caller must set the S3Context pointer -- origi= nally - returned by AllocateS3Context() -- immediately to = NULL, - because the ownership of S3Context has been transf= erred. - - @retval EFI_SUCCESS The translation of S3Context to ACPI S3 Boot Script - opcodes has been successfully executed or queued. (T= his - includes the case when S3Context was empty on input = and - no ACPI S3 Boot Script opcodes have been necessary to - produce.) - - @return Error codes from underlying functions. -**/ -EFI_STATUS -TransferS3ContextToBootScript ( - IN S3_CONTEXT *S3Context - ) -{ - RETURN_STATUS Status; - - if (S3Context->Used =3D=3D 0) { - ReleaseS3Context (S3Context); - return EFI_SUCCESS; - } - - Status =3D QemuFwCfgS3CallWhenBootScriptReady (AppendFwCfgBootScript, - S3Context, sizeof (SCRATCH_BUFFER)); - return (EFI_STATUS)Status; -} diff --git a/OvmfPkg/XenAcpiPlatformDxe/PciDecoding.c b/OvmfPkg/XenAcpiPlat= formDxe/PciDecoding.c deleted file mode 100644 index 00fc57eb13eb..000000000000 --- a/OvmfPkg/XenAcpiPlatformDxe/PciDecoding.c +++ /dev/null @@ -1,194 +0,0 @@ -/** @file - Temporarily enable IO and MMIO decoding for all PCI devices while QEMU - regenerates the ACPI tables. - - Copyright (C) 2016-2021, Red Hat, Inc. - - SPDX-License-Identifier: BSD-2-Clause-Patent -**/ - -#include // DEBUG() -#include // AllocatePool() -#include // gBS - -#include "AcpiPlatform.h" - - -/** - Collect all PciIo protocol instances in the system. Save their original - attributes, and enable IO and MMIO decoding for each. - - This is a best effort function; it doesn't return status codes. Its - caller is supposed to proceed even if this function fails. - - @param[out] OriginalAttributes On output, a dynamically allocated array= of - ORIGINAL_ATTRIBUTES elements. The array = lists - the PciIo protocol instances found in the - system at the time of the call, plus the - original PCI attributes for each. - - Before returning, the function enables I= O and - MMIO decoding for each PciIo instance it - finds. - - On error, or when no such instances are - found, OriginalAttributes is set to NULL. - - @param[out] Count On output, the number of elements in - OriginalAttributes. On error it is set to - zero. -**/ -VOID -EnablePciDecoding ( - OUT ORIGINAL_ATTRIBUTES **OriginalAttributes, - OUT UINTN *Count - ) -{ - EFI_STATUS Status; - UINTN NoHandles; - EFI_HANDLE *Handles; - ORIGINAL_ATTRIBUTES *OrigAttrs; - UINTN Idx; - - *OriginalAttributes =3D NULL; - *Count =3D 0; - - if (PcdGetBool (PcdPciDisableBusEnumeration)) { - // - // The platform downloads ACPI tables from QEMU in general, but there = are - // no root bridges in this execution. We're done. - // - return; - } - - Status =3D gBS->LocateHandleBuffer (ByProtocol, &gEfiPciIoProtocolGuid, - NULL /* SearchKey */, &NoHandles, &Handles); - if (Status =3D=3D EFI_NOT_FOUND) { - // - // No PCI devices were found on either of the root bridges. We're done. - // - return; - } - - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_WARN, "%a: LocateHandleBuffer(): %r\n", __FUNCTION__, - Status)); - return; - } - - OrigAttrs =3D AllocatePool (NoHandles * sizeof *OrigAttrs); - if (OrigAttrs =3D=3D NULL) { - DEBUG ((DEBUG_WARN, "%a: AllocatePool(): out of resources\n", - __FUNCTION__)); - goto FreeHandles; - } - - for (Idx =3D 0; Idx < NoHandles; ++Idx) { - EFI_PCI_IO_PROTOCOL *PciIo; - UINT64 Attributes; - - // - // Look up PciIo on the handle and stash it - // - Status =3D gBS->HandleProtocol (Handles[Idx], &gEfiPciIoProtocolGuid, - (VOID**)&PciIo); - ASSERT_EFI_ERROR (Status); - OrigAttrs[Idx].PciIo =3D PciIo; - - // - // Stash the current attributes - // - Status =3D PciIo->Attributes (PciIo, EfiPciIoAttributeOperationGet, 0, - &OrigAttrs[Idx].PciAttributes); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_WARN, "%a: EfiPciIoAttributeOperationGet: %r\n", - __FUNCTION__, Status)); - goto RestoreAttributes; - } - - // - // Retrieve supported attributes - // - Status =3D PciIo->Attributes (PciIo, EfiPciIoAttributeOperationSupport= ed, 0, - &Attributes); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_WARN, "%a: EfiPciIoAttributeOperationSupported: %r\n", - __FUNCTION__, Status)); - goto RestoreAttributes; - } - - // - // Enable IO and MMIO decoding - // - Attributes &=3D EFI_PCI_IO_ATTRIBUTE_IO | EFI_PCI_IO_ATTRIBUTE_MEMORY; - Status =3D PciIo->Attributes (PciIo, EfiPciIoAttributeOperationEnable, - Attributes, NULL); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_WARN, "%a: EfiPciIoAttributeOperationEnable: %r\n", - __FUNCTION__, Status)); - goto RestoreAttributes; - } - } - - // - // Success - // - FreePool (Handles); - *OriginalAttributes =3D OrigAttrs; - *Count =3D NoHandles; - return; - -RestoreAttributes: - while (Idx > 0) { - --Idx; - OrigAttrs[Idx].PciIo->Attributes (OrigAttrs[Idx].PciIo, - EfiPciIoAttributeOperationSet, - OrigAttrs[Idx].PciAttributes, - NULL - ); - } - FreePool (OrigAttrs); - -FreeHandles: - FreePool (Handles); -} - - -/** - Restore the original PCI attributes saved with EnablePciDecoding(). - - @param[in] OriginalAttributes The array allocated and populated by - EnablePciDecoding(). This parameter may be - NULL. If OriginalAttributes is NULL, then= the - function is a no-op; otherwise the PciIo - attributes will be restored, and the - OriginalAttributes array will be freed. - - @param[in] Count The Count value stored by EnablePciDecodi= ng(), - the number of elements in OriginalAttribu= tes. - Count may be zero if and only if - OriginalAttributes is NULL. -**/ -VOID -RestorePciDecoding ( - IN ORIGINAL_ATTRIBUTES *OriginalAttributes, - IN UINTN Count - ) -{ - UINTN Idx; - - ASSERT ((OriginalAttributes =3D=3D NULL) =3D=3D (Count =3D=3D 0)); - if (OriginalAttributes =3D=3D NULL) { - return; - } - - for (Idx =3D 0; Idx < Count; ++Idx) { - OriginalAttributes[Idx].PciIo->Attributes ( - OriginalAttributes[Idx].PciIo, - EfiPciIoAttributeOperationSet, - OriginalAttributes[Idx].PciAttributes, - NULL - ); - } - FreePool (OriginalAttributes); -} diff --git a/OvmfPkg/XenAcpiPlatformDxe/QemuFwCfgAcpi.c b/OvmfPkg/XenAcpiPl= atformDxe/QemuFwCfgAcpi.c deleted file mode 100644 index 521c06cf546f..000000000000 --- a/OvmfPkg/XenAcpiPlatformDxe/QemuFwCfgAcpi.c +++ /dev/null @@ -1,1196 +0,0 @@ -/** @file - OVMF ACPI support using QEMU's fw-cfg interface - - Copyright (C) 2012-2021, Red Hat, Inc. - Copyright (c) 2008 - 2014, Intel Corporation. All rights reserved.
- - SPDX-License-Identifier: BSD-2-Clause-Patent - -**/ - -#include // EFI_ACPI_DESCRIPTION_HEAD= ER -#include // QEMU_LOADER_FNAME_SIZE -#include // AsciiStrCmp() -#include // CopyMem() -#include // DEBUG() -#include // AllocatePool() -#include // OrderedCollectionMin() -#include // QemuFwCfgFindFile() -#include // QemuFwCfgS3Enabled() -#include // gBS - -#include "AcpiPlatform.h" - -// -// The user structure for the ordered collection that will track the fw_cfg -// blobs under processing. -// -typedef struct { - UINT8 File[QEMU_LOADER_FNAME_SIZE]; // NUL-terminated name of the fw_c= fg - // blob. This is the ordering / se= arch - // key. - UINTN Size; // The number of bytes in this blo= b. - UINT8 *Base; // Pointer to the blob data. - BOOLEAN HostsOnlyTableData; // TRUE iff the blob has been foun= d to - // only contain data that is direc= tly - // part of ACPI tables. -} BLOB; - - -/** - Compare a standalone key against a user structure containing an embedded= key. - - @param[in] StandaloneKey Pointer to the bare key. - - @param[in] UserStruct Pointer to the user structure with the embedded - key. - - @retval <0 If StandaloneKey compares less than UserStruct's key. - - @retval 0 If StandaloneKey compares equal to UserStruct's key. - - @retval >0 If StandaloneKey compares greater than UserStruct's key. -**/ -STATIC -INTN -EFIAPI -BlobKeyCompare ( - IN CONST VOID *StandaloneKey, - IN CONST VOID *UserStruct - ) -{ - CONST BLOB *Blob; - - Blob =3D UserStruct; - return AsciiStrCmp (StandaloneKey, (CONST CHAR8 *)Blob->File); -} - - -/** - Comparator function for two user structures. - - @param[in] UserStruct1 Pointer to the first user structure. - - @param[in] UserStruct2 Pointer to the second user structure. - - @retval <0 If UserStruct1 compares less than UserStruct2. - - @retval 0 If UserStruct1 compares equal to UserStruct2. - - @retval >0 If UserStruct1 compares greater than UserStruct2. -**/ -STATIC -INTN -EFIAPI -BlobCompare ( - IN CONST VOID *UserStruct1, - IN CONST VOID *UserStruct2 - ) -{ - CONST BLOB *Blob1; - - Blob1 =3D UserStruct1; - return BlobKeyCompare (Blob1->File, UserStruct2); -} - - -/** - Comparator function for two opaque pointers, ordering on (unsigned) poin= ter - value itself. - Can be used as both Key and UserStruct comparator. - - @param[in] Pointer1 First pointer. - - @param[in] Pointer2 Second pointer. - - @retval <0 If Pointer1 compares less than Pointer2. - - @retval 0 If Pointer1 compares equal to Pointer2. - - @retval >0 If Pointer1 compares greater than Pointer2. -**/ -STATIC -INTN -EFIAPI -PointerCompare ( - IN CONST VOID *Pointer1, - IN CONST VOID *Pointer2 - ) -{ - if (Pointer1 =3D=3D Pointer2) { - return 0; - } - if ((UINTN)Pointer1 < (UINTN)Pointer2) { - return -1; - } - return 1; -} - - -/** - Comparator function for two ASCII strings. Can be used as both Key and - UserStruct comparator. - - This function exists solely so we can avoid casting &AsciiStrCmp to - ORDERED_COLLECTION_USER_COMPARE and ORDERED_COLLECTION_KEY_COMPARE. - - @param[in] AsciiString1 Pointer to the first ASCII string. - - @param[in] AsciiString2 Pointer to the second ASCII string. - - @return The return value of AsciiStrCmp (AsciiString1, AsciiString2). -**/ -STATIC -INTN -EFIAPI -AsciiStringCompare ( - IN CONST VOID *AsciiString1, - IN CONST VOID *AsciiString2 - ) -{ - return AsciiStrCmp (AsciiString1, AsciiString2); -} - - -/** - Release the ORDERED_COLLECTION structure populated by - CollectAllocationsRestrictedTo32Bit() (below). - - This function may be called by CollectAllocationsRestrictedTo32Bit() its= elf, - on the error path. - - @param[in] AllocationsRestrictedTo32Bit The ORDERED_COLLECTION structur= e to - release. -**/ -STATIC -VOID -ReleaseAllocationsRestrictedTo32Bit ( - IN ORDERED_COLLECTION *AllocationsRestrictedTo32Bit -) -{ - ORDERED_COLLECTION_ENTRY *Entry, *Entry2; - - for (Entry =3D OrderedCollectionMin (AllocationsRestrictedTo32Bit); - Entry !=3D NULL; - Entry =3D Entry2) { - Entry2 =3D OrderedCollectionNext (Entry); - OrderedCollectionDelete (AllocationsRestrictedTo32Bit, Entry, NULL); - } - OrderedCollectionUninit (AllocationsRestrictedTo32Bit); -} - - -/** - Iterate over the linker/loader script, and collect the names of the fw_c= fg - blobs that are referenced by QEMU_LOADER_ADD_POINTER.PointeeFile fields,= such - that QEMU_LOADER_ADD_POINTER.PointerSize is less than 8. This means that= the - pointee blob's address will have to be patched into a narrower-than-8 by= te - pointer field, hence the pointee blob must not be allocated from 64-bit - address space. - - @param[out] AllocationsRestrictedTo32Bit The ORDERED_COLLECTION structu= re - linking (not copying / owning)= such - QEMU_LOADER_ADD_POINTER.Pointe= eFile - fields that name the blobs - restricted from 64-bit allocat= ion. - - @param[in] LoaderStart Points to the first entry in t= he - linker/loader script. - - @param[in] LoaderEnd Points one past the last entry= in - the linker/loader script. - - @retval EFI_SUCCESS AllocationsRestrictedTo32Bit has been - populated. - - @retval EFI_OUT_OF_RESOURCES Memory allocation failed. - - @retval EFI_PROTOCOL_ERROR Invalid linker/loader script contents. -**/ -STATIC -EFI_STATUS -CollectAllocationsRestrictedTo32Bit ( - OUT ORDERED_COLLECTION **AllocationsRestrictedTo32Bit, - IN CONST QEMU_LOADER_ENTRY *LoaderStart, - IN CONST QEMU_LOADER_ENTRY *LoaderEnd -) -{ - ORDERED_COLLECTION *Collection; - CONST QEMU_LOADER_ENTRY *LoaderEntry; - EFI_STATUS Status; - - Collection =3D OrderedCollectionInit (AsciiStringCompare, AsciiStringCom= pare); - if (Collection =3D=3D NULL) { - return EFI_OUT_OF_RESOURCES; - } - - for (LoaderEntry =3D LoaderStart; LoaderEntry < LoaderEnd; ++LoaderEntry= ) { - CONST QEMU_LOADER_ADD_POINTER *AddPointer; - - if (LoaderEntry->Type !=3D QemuLoaderCmdAddPointer) { - continue; - } - AddPointer =3D &LoaderEntry->Command.AddPointer; - - if (AddPointer->PointerSize >=3D 8) { - continue; - } - - if (AddPointer->PointeeFile[QEMU_LOADER_FNAME_SIZE - 1] !=3D '\0') { - DEBUG ((DEBUG_ERROR, "%a: malformed file name\n", __FUNCTION__)); - Status =3D EFI_PROTOCOL_ERROR; - goto RollBack; - } - - Status =3D OrderedCollectionInsert ( - Collection, - NULL, // Entry - (VOID *)AddPointer->PointeeFile - ); - switch (Status) { - case EFI_SUCCESS: - DEBUG (( - DEBUG_VERBOSE, - "%a: restricting blob \"%a\" from 64-bit allocation\n", - __FUNCTION__, - AddPointer->PointeeFile - )); - break; - case EFI_ALREADY_STARTED: - // - // The restriction has been recorded already. - // - break; - case EFI_OUT_OF_RESOURCES: - goto RollBack; - default: - ASSERT (FALSE); - } - } - - *AllocationsRestrictedTo32Bit =3D Collection; - return EFI_SUCCESS; - -RollBack: - ReleaseAllocationsRestrictedTo32Bit (Collection); - return Status; -} - - -/** - Process a QEMU_LOADER_ALLOCATE command. - - @param[in] Allocate The QEMU_LOADER_ALLOCATE comman= d to - process. - - @param[in,out] Tracker The ORDERED_COLLECTION tracking= the - BLOB user structures created th= us - far. - - @param[in] AllocationsRestrictedTo32Bit The ORDERED_COLLECTION populate= d by - the function - CollectAllocationsRestrictedTo3= 2Bit, - naming the fw_cfg blobs that mu= st - not be allocated from 64-bit ad= dress - space. - - @retval EFI_SUCCESS An area of whole AcpiNVS pages has been - allocated for the blob contents, and the - contents have been saved. A BLOB object (u= ser - structure) has been allocated from pool me= mory, - referencing the blob contents. The BLOB us= er - structure has been linked into Tracker. - - @retval EFI_PROTOCOL_ERROR Malformed fw_cfg file name has been found = in - Allocate, or the Allocate command referenc= es a - file that is already known by Tracker. - - @retval EFI_UNSUPPORTED Unsupported alignment request has been fou= nd in - Allocate. - - @retval EFI_OUT_OF_RESOURCES Pool allocation failed. - - @return Error codes from QemuFwCfgFindFile() and - gBS->AllocatePages(). -**/ -STATIC -EFI_STATUS -EFIAPI -ProcessCmdAllocate ( - IN CONST QEMU_LOADER_ALLOCATE *Allocate, - IN OUT ORDERED_COLLECTION *Tracker, - IN ORDERED_COLLECTION *AllocationsRestrictedTo32Bit - ) -{ - FIRMWARE_CONFIG_ITEM FwCfgItem; - UINTN FwCfgSize; - EFI_STATUS Status; - UINTN NumPages; - EFI_PHYSICAL_ADDRESS Address; - BLOB *Blob; - - if (Allocate->File[QEMU_LOADER_FNAME_SIZE - 1] !=3D '\0') { - DEBUG ((DEBUG_ERROR, "%a: malformed file name\n", __FUNCTION__)); - return EFI_PROTOCOL_ERROR; - } - - if (Allocate->Alignment > EFI_PAGE_SIZE) { - DEBUG ((DEBUG_ERROR, "%a: unsupported alignment 0x%x\n", __FUNCTION__, - Allocate->Alignment)); - return EFI_UNSUPPORTED; - } - - Status =3D QemuFwCfgFindFile ((CHAR8 *)Allocate->File, &FwCfgItem, &FwCf= gSize); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "%a: QemuFwCfgFindFile(\"%a\"): %r\n", __FUNCTION= __, - Allocate->File, Status)); - return Status; - } - - NumPages =3D EFI_SIZE_TO_PAGES (FwCfgSize); - Address =3D MAX_UINT64; - if (OrderedCollectionFind ( - AllocationsRestrictedTo32Bit, - Allocate->File - ) !=3D NULL) { - Address =3D MAX_UINT32; - } - Status =3D gBS->AllocatePages (AllocateMaxAddress, EfiACPIMemoryNVS, Num= Pages, - &Address); - if (EFI_ERROR (Status)) { - return Status; - } - - Blob =3D AllocatePool (sizeof *Blob); - if (Blob =3D=3D NULL) { - Status =3D EFI_OUT_OF_RESOURCES; - goto FreePages; - } - CopyMem (Blob->File, Allocate->File, QEMU_LOADER_FNAME_SIZE); - Blob->Size =3D FwCfgSize; - Blob->Base =3D (VOID *)(UINTN)Address; - Blob->HostsOnlyTableData =3D TRUE; - - Status =3D OrderedCollectionInsert (Tracker, NULL, Blob); - if (Status =3D=3D RETURN_ALREADY_STARTED) { - DEBUG ((DEBUG_ERROR, "%a: duplicated file \"%a\"\n", __FUNCTION__, - Allocate->File)); - Status =3D EFI_PROTOCOL_ERROR; - } - if (EFI_ERROR (Status)) { - goto FreeBlob; - } - - QemuFwCfgSelectItem (FwCfgItem); - QemuFwCfgReadBytes (FwCfgSize, Blob->Base); - ZeroMem (Blob->Base + Blob->Size, EFI_PAGES_TO_SIZE (NumPages) - Blob->S= ize); - - DEBUG ((DEBUG_VERBOSE, "%a: File=3D\"%a\" Alignment=3D0x%x Zone=3D%d Siz= e=3D0x%Lx " - "Address=3D0x%Lx\n", __FUNCTION__, Allocate->File, Allocate->Alignment, - Allocate->Zone, (UINT64)Blob->Size, (UINT64)(UINTN)Blob->Base)); - return EFI_SUCCESS; - -FreeBlob: - FreePool (Blob); - -FreePages: - gBS->FreePages (Address, NumPages); - - return Status; -} - - -/** - Process a QEMU_LOADER_ADD_POINTER command. - - @param[in] AddPointer The QEMU_LOADER_ADD_POINTER command to process. - - @param[in] Tracker The ORDERED_COLLECTION tracking the BLOB user - structures created thus far. - - @retval EFI_PROTOCOL_ERROR Malformed fw_cfg file name(s) have been foun= d in - AddPointer, or the AddPointer command refere= nces - a file unknown to Tracker, or the pointer to - relocate has invalid location, size, or valu= e, or - the relocated pointer value is not represent= able - in the given pointer size. - - @retval EFI_SUCCESS The pointer field inside the pointer blob has - been relocated. -**/ -STATIC -EFI_STATUS -EFIAPI -ProcessCmdAddPointer ( - IN CONST QEMU_LOADER_ADD_POINTER *AddPointer, - IN CONST ORDERED_COLLECTION *Tracker - ) -{ - ORDERED_COLLECTION_ENTRY *TrackerEntry, *TrackerEntry2; - BLOB *Blob, *Blob2; - UINT8 *PointerField; - UINT64 PointerValue; - - if (AddPointer->PointerFile[QEMU_LOADER_FNAME_SIZE - 1] !=3D '\0' || - AddPointer->PointeeFile[QEMU_LOADER_FNAME_SIZE - 1] !=3D '\0') { - DEBUG ((DEBUG_ERROR, "%a: malformed file name\n", __FUNCTION__)); - return EFI_PROTOCOL_ERROR; - } - - TrackerEntry =3D OrderedCollectionFind (Tracker, AddPointer->PointerFile= ); - TrackerEntry2 =3D OrderedCollectionFind (Tracker, AddPointer->PointeeFil= e); - if (TrackerEntry =3D=3D NULL || TrackerEntry2 =3D=3D NULL) { - DEBUG ((DEBUG_ERROR, "%a: invalid blob reference(s) \"%a\" / \"%a\"\n", - __FUNCTION__, AddPointer->PointerFile, AddPointer->PointeeFile)); - return EFI_PROTOCOL_ERROR; - } - - Blob =3D OrderedCollectionUserStruct (TrackerEntry); - Blob2 =3D OrderedCollectionUserStruct (TrackerEntry2); - if ((AddPointer->PointerSize !=3D 1 && AddPointer->PointerSize !=3D 2 && - AddPointer->PointerSize !=3D 4 && AddPointer->PointerSize !=3D 8) || - Blob->Size < AddPointer->PointerSize || - Blob->Size - AddPointer->PointerSize < AddPointer->PointerOffset) { - DEBUG ((DEBUG_ERROR, "%a: invalid pointer location or size in \"%a\"\n= ", - __FUNCTION__, AddPointer->PointerFile)); - return EFI_PROTOCOL_ERROR; - } - - PointerField =3D Blob->Base + AddPointer->PointerOffset; - PointerValue =3D 0; - CopyMem (&PointerValue, PointerField, AddPointer->PointerSize); - if (PointerValue >=3D Blob2->Size) { - DEBUG ((DEBUG_ERROR, "%a: invalid pointer value in \"%a\"\n", __FUNCTI= ON__, - AddPointer->PointerFile)); - return EFI_PROTOCOL_ERROR; - } - - // - // The memory allocation system ensures that the address of the byte pas= t the - // last byte of any allocated object is expressible (no wraparound). - // - ASSERT ((UINTN)Blob2->Base <=3D MAX_ADDRESS - Blob2->Size); - - PointerValue +=3D (UINT64)(UINTN)Blob2->Base; - if (AddPointer->PointerSize < 8 && - RShiftU64 (PointerValue, AddPointer->PointerSize * 8) !=3D 0) { - DEBUG ((DEBUG_ERROR, "%a: relocated pointer value unrepresentable in " - "\"%a\"\n", __FUNCTION__, AddPointer->PointerFile)); - return EFI_PROTOCOL_ERROR; - } - - CopyMem (PointerField, &PointerValue, AddPointer->PointerSize); - - DEBUG ((DEBUG_VERBOSE, "%a: PointerFile=3D\"%a\" PointeeFile=3D\"%a\" " - "PointerOffset=3D0x%x PointerSize=3D%d\n", __FUNCTION__, - AddPointer->PointerFile, AddPointer->PointeeFile, - AddPointer->PointerOffset, AddPointer->PointerSize)); - return EFI_SUCCESS; -} - - -/** - Process a QEMU_LOADER_ADD_CHECKSUM command. - - @param[in] AddChecksum The QEMU_LOADER_ADD_CHECKSUM command to process. - - @param[in] Tracker The ORDERED_COLLECTION tracking the BLOB user - structures created thus far. - - @retval EFI_PROTOCOL_ERROR Malformed fw_cfg file name has been found in - AddChecksum, or the AddChecksum command - references a file unknown to Tracker, or the - range to checksum is invalid. - - @retval EFI_SUCCESS The requested range has been checksummed. -**/ -STATIC -EFI_STATUS -EFIAPI -ProcessCmdAddChecksum ( - IN CONST QEMU_LOADER_ADD_CHECKSUM *AddChecksum, - IN CONST ORDERED_COLLECTION *Tracker - ) -{ - ORDERED_COLLECTION_ENTRY *TrackerEntry; - BLOB *Blob; - - if (AddChecksum->File[QEMU_LOADER_FNAME_SIZE - 1] !=3D '\0') { - DEBUG ((DEBUG_ERROR, "%a: malformed file name\n", __FUNCTION__)); - return EFI_PROTOCOL_ERROR; - } - - TrackerEntry =3D OrderedCollectionFind (Tracker, AddChecksum->File); - if (TrackerEntry =3D=3D NULL) { - DEBUG ((DEBUG_ERROR, "%a: invalid blob reference \"%a\"\n", __FUNCTION= __, - AddChecksum->File)); - return EFI_PROTOCOL_ERROR; - } - - Blob =3D OrderedCollectionUserStruct (TrackerEntry); - if (Blob->Size <=3D AddChecksum->ResultOffset || - Blob->Size < AddChecksum->Length || - Blob->Size - AddChecksum->Length < AddChecksum->Start) { - DEBUG ((DEBUG_ERROR, "%a: invalid checksum range in \"%a\"\n", - __FUNCTION__, AddChecksum->File)); - return EFI_PROTOCOL_ERROR; - } - - Blob->Base[AddChecksum->ResultOffset] =3D CalculateCheckSum8 ( - Blob->Base + AddChecksum->Start, - AddChecksum->Length - ); - DEBUG ((DEBUG_VERBOSE, "%a: File=3D\"%a\" ResultOffset=3D0x%x Start=3D0x= %x " - "Length=3D0x%x\n", __FUNCTION__, AddChecksum->File, - AddChecksum->ResultOffset, AddChecksum->Start, AddChecksum->Length)); - return EFI_SUCCESS; -} - - -/** - Process a QEMU_LOADER_WRITE_POINTER command. - - @param[in] WritePointer The QEMU_LOADER_WRITE_POINTER command to proce= ss. - - @param[in] Tracker The ORDERED_COLLECTION tracking the BLOB user - structures created thus far. - - @param[in,out] S3Context The S3_CONTEXT object capturing the fw_cfg act= ions - of successfully processed QEMU_LOADER_WRITE_PO= INTER - commands, to be replayed at S3 resume. S3Conte= xt - may be NULL if S3 is disabled. - - @retval EFI_PROTOCOL_ERROR Malformed fw_cfg file name(s) have been foun= d in - WritePointer. Or, the WritePointer command - references a file unknown to Tracker or the - fw_cfg directory. Or, the pointer object to - rewrite has invalid location, size, or initi= al - relative value. Or, the pointer value to sto= re - does not fit in the given pointer size. - - @retval EFI_SUCCESS The pointer object inside the writeable fw_c= fg - file has been written. If S3Context is not N= ULL, - then WritePointer has been condensed into - S3Context. - - @return Error codes propagated from - SaveCondensedWritePointerToS3Context(). The - pointer object inside the writeable fw_cfg f= ile - has not been written. -**/ -STATIC -EFI_STATUS -ProcessCmdWritePointer ( - IN CONST QEMU_LOADER_WRITE_POINTER *WritePointer, - IN CONST ORDERED_COLLECTION *Tracker, - IN OUT S3_CONTEXT *S3Context OPTIONAL - ) -{ - RETURN_STATUS Status; - FIRMWARE_CONFIG_ITEM PointerItem; - UINTN PointerItemSize; - ORDERED_COLLECTION_ENTRY *PointeeEntry; - BLOB *PointeeBlob; - UINT64 PointerValue; - - if (WritePointer->PointerFile[QEMU_LOADER_FNAME_SIZE - 1] !=3D '\0' || - WritePointer->PointeeFile[QEMU_LOADER_FNAME_SIZE - 1] !=3D '\0') { - DEBUG ((DEBUG_ERROR, "%a: malformed file name\n", __FUNCTION__)); - return EFI_PROTOCOL_ERROR; - } - - Status =3D QemuFwCfgFindFile ((CONST CHAR8 *)WritePointer->PointerFile, - &PointerItem, &PointerItemSize); - PointeeEntry =3D OrderedCollectionFind (Tracker, WritePointer->PointeeFi= le); - if (RETURN_ERROR (Status) || PointeeEntry =3D=3D NULL) { - DEBUG ((DEBUG_ERROR, - "%a: invalid fw_cfg file or blob reference \"%a\" / \"%a\"\n", - __FUNCTION__, WritePointer->PointerFile, WritePointer->PointeeFile)); - return EFI_PROTOCOL_ERROR; - } - - if ((WritePointer->PointerSize !=3D 1 && WritePointer->PointerSize !=3D = 2 && - WritePointer->PointerSize !=3D 4 && WritePointer->PointerSize !=3D = 8) || - (PointerItemSize < WritePointer->PointerSize) || - (PointerItemSize - WritePointer->PointerSize < - WritePointer->PointerOffset)) { - DEBUG ((DEBUG_ERROR, "%a: invalid pointer location or size in \"%a\"\n= ", - __FUNCTION__, WritePointer->PointerFile)); - return EFI_PROTOCOL_ERROR; - } - - PointeeBlob =3D OrderedCollectionUserStruct (PointeeEntry); - PointerValue =3D WritePointer->PointeeOffset; - if (PointerValue >=3D PointeeBlob->Size) { - DEBUG ((DEBUG_ERROR, "%a: invalid PointeeOffset\n", __FUNCTION__)); - return EFI_PROTOCOL_ERROR; - } - - // - // The memory allocation system ensures that the address of the byte pas= t the - // last byte of any allocated object is expressible (no wraparound). - // - ASSERT ((UINTN)PointeeBlob->Base <=3D MAX_ADDRESS - PointeeBlob->Size); - - PointerValue +=3D (UINT64)(UINTN)PointeeBlob->Base; - if (WritePointer->PointerSize < 8 && - RShiftU64 (PointerValue, WritePointer->PointerSize * 8) !=3D 0) { - DEBUG ((DEBUG_ERROR, "%a: pointer value unrepresentable in \"%a\"\n", - __FUNCTION__, WritePointer->PointerFile)); - return EFI_PROTOCOL_ERROR; - } - - // - // If S3 is enabled, we have to capture the below fw_cfg actions in cond= ensed - // form, to be replayed during S3 resume. - // - if (S3Context !=3D NULL) { - EFI_STATUS SaveStatus; - - SaveStatus =3D SaveCondensedWritePointerToS3Context ( - S3Context, - (UINT16)PointerItem, - WritePointer->PointerSize, - WritePointer->PointerOffset, - PointerValue - ); - if (EFI_ERROR (SaveStatus)) { - return SaveStatus; - } - } - - QemuFwCfgSelectItem (PointerItem); - QemuFwCfgSkipBytes (WritePointer->PointerOffset); - QemuFwCfgWriteBytes (WritePointer->PointerSize, &PointerValue); - - // - // Because QEMU has now learned PointeeBlob->Base, we must mark PointeeB= lob - // as unreleasable, for the case when the whole linker/loader script is - // handled successfully. - // - PointeeBlob->HostsOnlyTableData =3D FALSE; - - DEBUG ((DEBUG_VERBOSE, "%a: PointerFile=3D\"%a\" PointeeFile=3D\"%a\" " - "PointerOffset=3D0x%x PointeeOffset=3D0x%x PointerSize=3D%d\n", __FUNC= TION__, - WritePointer->PointerFile, WritePointer->PointeeFile, - WritePointer->PointerOffset, WritePointer->PointeeOffset, - WritePointer->PointerSize)); - return EFI_SUCCESS; -} - - -/** - Undo a QEMU_LOADER_WRITE_POINTER command. - - This function revokes (zeroes out) a guest memory reference communicated= to - QEMU earlier. The caller is responsible for invoking this function only = on - such QEMU_LOADER_WRITE_POINTER commands that have been successfully proc= essed - by ProcessCmdWritePointer(). - - @param[in] WritePointer The QEMU_LOADER_WRITE_POINTER command to undo. -**/ -STATIC -VOID -UndoCmdWritePointer ( - IN CONST QEMU_LOADER_WRITE_POINTER *WritePointer - ) -{ - RETURN_STATUS Status; - FIRMWARE_CONFIG_ITEM PointerItem; - UINTN PointerItemSize; - UINT64 PointerValue; - - Status =3D QemuFwCfgFindFile ((CONST CHAR8 *)WritePointer->PointerFile, - &PointerItem, &PointerItemSize); - ASSERT_RETURN_ERROR (Status); - - PointerValue =3D 0; - QemuFwCfgSelectItem (PointerItem); - QemuFwCfgSkipBytes (WritePointer->PointerOffset); - QemuFwCfgWriteBytes (WritePointer->PointerSize, &PointerValue); - - DEBUG ((DEBUG_VERBOSE, - "%a: PointerFile=3D\"%a\" PointerOffset=3D0x%x PointerSize=3D%d\n", __= FUNCTION__, - WritePointer->PointerFile, WritePointer->PointerOffset, - WritePointer->PointerSize)); -} - - -// -// We'll be saving the keys of installed tables so that we can roll them b= ack -// in case of failure. 128 tables should be enough for anyone (TM). -// -#define INSTALLED_TABLES_MAX 128 - -/** - Process a QEMU_LOADER_ADD_POINTER command in order to see if its target = byte - array is an ACPI table, and if so, install it. - - This function assumes that the entire QEMU linker/loader command file has - been processed successfully in a prior first pass. - - @param[in] AddPointer The QEMU_LOADER_ADD_POINTER command to proc= ess. - - @param[in] Tracker The ORDERED_COLLECTION tracking the BLOB us= er - structures. - - @param[in] AcpiProtocol The ACPI table protocol used to install tab= les. - - @param[in,out] InstalledKey On input, an array of INSTALLED_TABLES_MAX = UINTN - elements, allocated by the caller. On outpu= t, - the function will have stored (appended) the - AcpiProtocol-internal key of the ACPI table= that - the function has installed, if the AddPoint= er - command identified an ACPI table that is - different from RSDT and XSDT. - - @param[in,out] NumInstalled On input, the number of entries already use= d in - InstalledKey; it must be in [0, - INSTALLED_TABLES_MAX] inclusive. On output,= the - parameter is incremented if the AddPointer - command identified an ACPI table that is - different from RSDT and XSDT. - - @param[in,out] SeenPointers The ORDERED_COLLECTION tracking the absolute - target addresses that have been pointed-to = by - QEMU_LOADER_ADD_POINTER commands thus far. = If a - target address is encountered for the first - time, and it identifies an ACPI table that = is - different from RDST and XSDT, the table is - installed. If a target address is seen for = the - second or later times, it is skipped without - taking any action. - - @retval EFI_INVALID_PARAMETER NumInstalled was outside the allowed rang= e on - input. - - @retval EFI_OUT_OF_RESOURCES The AddPointer command identified an ACPI - table different from RSDT and XSDT, but t= here - was no more room in InstalledKey. - - @retval EFI_SUCCESS AddPointer has been processed. Either its - absolute target address has been encounte= red - before, or an ACPI table different from R= SDT - and XSDT has been installed (reflected by - InstalledKey and NumInstalled), or RSDT or - XSDT has been identified but not installe= d, or - the fw_cfg blob pointed-into by AddPointe= r has - been marked as hosting something else than - just direct ACPI table contents. - - @return Error codes returned by - AcpiProtocol->InstallAcpiTable(). -**/ -STATIC -EFI_STATUS -EFIAPI -Process2ndPassCmdAddPointer ( - IN CONST QEMU_LOADER_ADD_POINTER *AddPointer, - IN CONST ORDERED_COLLECTION *Tracker, - IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol, - IN OUT UINTN InstalledKey[INSTALLED_TABLES_MAX], - IN OUT INT32 *NumInstalled, - IN OUT ORDERED_COLLECTION *SeenPointers - ) -{ - CONST ORDERED_COLLECTION_ENTRY *TrackerEntry; - CONST ORDERED_COLLECTION_ENTRY *TrackerEntry2; - ORDERED_COLLECTION_ENTRY *SeenPointerEntry; - CONST BLOB *Blob; - BLOB *Blob2; - CONST UINT8 *PointerField; - UINT64 PointerValue; - UINTN Blob2Remaining; - UINTN TableSize; - CONST EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs; - CONST EFI_ACPI_DESCRIPTION_HEADER *Header; - EFI_STATUS Status; - - if (*NumInstalled < 0 || *NumInstalled > INSTALLED_TABLES_MAX) { - return EFI_INVALID_PARAMETER; - } - - TrackerEntry =3D OrderedCollectionFind (Tracker, AddPointer->PointerFile= ); - TrackerEntry2 =3D OrderedCollectionFind (Tracker, AddPointer->PointeeFil= e); - Blob =3D OrderedCollectionUserStruct (TrackerEntry); - Blob2 =3D OrderedCollectionUserStruct (TrackerEntry2); - PointerField =3D Blob->Base + AddPointer->PointerOffset; - PointerValue =3D 0; - CopyMem (&PointerValue, PointerField, AddPointer->PointerSize); - - // - // We assert that PointerValue falls inside Blob2's contents. This is en= sured - // by the Blob2->Size check and later checks in ProcessCmdAddPointer(). - // - Blob2Remaining =3D (UINTN)Blob2->Base; - ASSERT(PointerValue >=3D Blob2Remaining); - Blob2Remaining +=3D Blob2->Size; - ASSERT (PointerValue < Blob2Remaining); - - Status =3D OrderedCollectionInsert ( - SeenPointers, - &SeenPointerEntry, // for reverting insertion in error case - (VOID *)(UINTN)PointerValue - ); - if (EFI_ERROR (Status)) { - if (Status =3D=3D RETURN_ALREADY_STARTED) { - // - // Already seen this pointer, don't try to process it again. - // - DEBUG (( - DEBUG_VERBOSE, - "%a: PointerValue=3D0x%Lx already processed, skipping.\n", - __FUNCTION__, - PointerValue - )); - Status =3D EFI_SUCCESS; - } - return Status; - } - - Blob2Remaining -=3D (UINTN) PointerValue; - DEBUG ((DEBUG_VERBOSE, "%a: checking for ACPI header in \"%a\" at 0x%Lx " - "(remaining: 0x%Lx): ", __FUNCTION__, AddPointer->PointeeFile, - PointerValue, (UINT64)Blob2Remaining)); - - TableSize =3D 0; - - // - // To make our job simple, the FACS has a custom header. Sigh. - // - if (sizeof *Facs <=3D Blob2Remaining) { - Facs =3D (EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *)(UINTN)Pointe= rValue; - - if (Facs->Length >=3D sizeof *Facs && - Facs->Length <=3D Blob2Remaining && - Facs->Signature =3D=3D - EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE) { - DEBUG ((DEBUG_VERBOSE, "found \"%-4.4a\" size 0x%x\n", - (CONST CHAR8 *)&Facs->Signature, Facs->Length)); - TableSize =3D Facs->Length; - } - } - - // - // check for the uniform tables - // - if (TableSize =3D=3D 0 && sizeof *Header <=3D Blob2Remaining) { - Header =3D (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)PointerValue; - - if (Header->Length >=3D sizeof *Header && - Header->Length <=3D Blob2Remaining && - CalculateSum8 ((CONST UINT8 *)Header, Header->Length) =3D=3D 0) { - // - // This looks very much like an ACPI table from QEMU: - // - Length field consistent with both ACPI and containing blob size - // - checksum is correct - // - DEBUG ((DEBUG_VERBOSE, "found \"%-4.4a\" size 0x%x\n", - (CONST CHAR8 *)&Header->Signature, Header->Length)); - TableSize =3D Header->Length; - - // - // Skip RSDT and XSDT because those are handled by - // EFI_ACPI_TABLE_PROTOCOL automatically. - if (Header->Signature =3D=3D - EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE || - Header->Signature =3D=3D - EFI_ACPI_2_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE_SIGNATU= RE) { - return EFI_SUCCESS; - } - } - } - - if (TableSize =3D=3D 0) { - DEBUG ((DEBUG_VERBOSE, "not found; marking fw_cfg blob as opaque\n")); - Blob2->HostsOnlyTableData =3D FALSE; - return EFI_SUCCESS; - } - - if (*NumInstalled =3D=3D INSTALLED_TABLES_MAX) { - DEBUG ((DEBUG_ERROR, "%a: can't install more than %d tables\n", - __FUNCTION__, INSTALLED_TABLES_MAX)); - Status =3D EFI_OUT_OF_RESOURCES; - goto RollbackSeenPointer; - } - - Status =3D AcpiProtocol->InstallAcpiTable (AcpiProtocol, - (VOID *)(UINTN)PointerValue, TableSize, - &InstalledKey[*NumInstalled]); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "%a: InstallAcpiTable(): %r\n", __FUNCTION__, - Status)); - goto RollbackSeenPointer; - } - ++*NumInstalled; - return EFI_SUCCESS; - -RollbackSeenPointer: - OrderedCollectionDelete (SeenPointers, SeenPointerEntry, NULL); - return Status; -} - - -/** - Download, process, and install ACPI table data from the QEMU loader - interface. - - @param[in] AcpiProtocol The ACPI table protocol used to install tables. - - @retval EFI_UNSUPPORTED Firmware configuration is unavailable, or= QEMU - loader command with unsupported parameters - has been found. - - @retval EFI_NOT_FOUND The host doesn't export the required fw_c= fg - files. - - @retval EFI_OUT_OF_RESOURCES Memory allocation failed, or more than - INSTALLED_TABLES_MAX tables found. - - @retval EFI_PROTOCOL_ERROR Found invalid fw_cfg contents. - - @return Status codes returned by - AcpiProtocol->InstallAcpiTable(). - -**/ -EFI_STATUS -EFIAPI -InstallQemuFwCfgTables ( - IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol - ) -{ - EFI_STATUS Status; - FIRMWARE_CONFIG_ITEM FwCfgItem; - UINTN FwCfgSize; - QEMU_LOADER_ENTRY *LoaderStart; - CONST QEMU_LOADER_ENTRY *LoaderEntry, *LoaderEnd; - CONST QEMU_LOADER_ENTRY *WritePointerSubsetEnd; - ORIGINAL_ATTRIBUTES *OriginalPciAttributes; - UINTN OriginalPciAttributesCount; - ORDERED_COLLECTION *AllocationsRestrictedTo32Bit; - S3_CONTEXT *S3Context; - ORDERED_COLLECTION *Tracker; - UINTN *InstalledKey; - INT32 Installed; - ORDERED_COLLECTION_ENTRY *TrackerEntry, *TrackerEntry2; - ORDERED_COLLECTION *SeenPointers; - ORDERED_COLLECTION_ENTRY *SeenPointerEntry, *SeenPointerEntry2; - - Status =3D QemuFwCfgFindFile ("etc/table-loader", &FwCfgItem, &FwCfgSize= ); - if (EFI_ERROR (Status)) { - return Status; - } - if (FwCfgSize % sizeof *LoaderEntry !=3D 0) { - DEBUG ((DEBUG_ERROR, "%a: \"etc/table-loader\" has invalid size 0x%Lx\= n", - __FUNCTION__, (UINT64)FwCfgSize)); - return EFI_PROTOCOL_ERROR; - } - - LoaderStart =3D AllocatePool (FwCfgSize); - if (LoaderStart =3D=3D NULL) { - return EFI_OUT_OF_RESOURCES; - } - EnablePciDecoding (&OriginalPciAttributes, &OriginalPciAttributesCount); - QemuFwCfgSelectItem (FwCfgItem); - QemuFwCfgReadBytes (FwCfgSize, LoaderStart); - RestorePciDecoding (OriginalPciAttributes, OriginalPciAttributesCount); - LoaderEnd =3D LoaderStart + FwCfgSize / sizeof *LoaderEntry; - - AllocationsRestrictedTo32Bit =3D NULL; - Status =3D CollectAllocationsRestrictedTo32Bit ( - &AllocationsRestrictedTo32Bit, - LoaderStart, - LoaderEnd - ); - if (EFI_ERROR (Status)) { - goto FreeLoader; - } - - S3Context =3D NULL; - if (QemuFwCfgS3Enabled ()) { - // - // Size the allocation pessimistically, assuming that all commands in = the - // script are QEMU_LOADER_WRITE_POINTER commands. - // - Status =3D AllocateS3Context (&S3Context, LoaderEnd - LoaderStart); - if (EFI_ERROR (Status)) { - goto FreeAllocationsRestrictedTo32Bit; - } - } - - Tracker =3D OrderedCollectionInit (BlobCompare, BlobKeyCompare); - if (Tracker =3D=3D NULL) { - Status =3D EFI_OUT_OF_RESOURCES; - goto FreeS3Context; - } - - // - // first pass: process the commands - // - // "WritePointerSubsetEnd" points one past the last successful - // QEMU_LOADER_WRITE_POINTER command. Now when we're about to start the = first - // pass, no such command has been encountered yet. - // - WritePointerSubsetEnd =3D LoaderStart; - for (LoaderEntry =3D LoaderStart; LoaderEntry < LoaderEnd; ++LoaderEntry= ) { - switch (LoaderEntry->Type) { - case QemuLoaderCmdAllocate: - Status =3D ProcessCmdAllocate ( - &LoaderEntry->Command.Allocate, - Tracker, - AllocationsRestrictedTo32Bit - ); - break; - - case QemuLoaderCmdAddPointer: - Status =3D ProcessCmdAddPointer (&LoaderEntry->Command.AddPointer, - Tracker); - break; - - case QemuLoaderCmdAddChecksum: - Status =3D ProcessCmdAddChecksum (&LoaderEntry->Command.AddChecksum, - Tracker); - break; - - case QemuLoaderCmdWritePointer: - Status =3D ProcessCmdWritePointer (&LoaderEntry->Command.WritePoin= ter, - Tracker, S3Context); - if (!EFI_ERROR (Status)) { - WritePointerSubsetEnd =3D LoaderEntry + 1; - } - break; - - default: - DEBUG ((DEBUG_VERBOSE, "%a: unknown loader command: 0x%x\n", - __FUNCTION__, LoaderEntry->Type)); - break; - } - - if (EFI_ERROR (Status)) { - goto RollbackWritePointersAndFreeTracker; - } - } - - InstalledKey =3D AllocatePool (INSTALLED_TABLES_MAX * sizeof *InstalledK= ey); - if (InstalledKey =3D=3D NULL) { - Status =3D EFI_OUT_OF_RESOURCES; - goto RollbackWritePointersAndFreeTracker; - } - - SeenPointers =3D OrderedCollectionInit (PointerCompare, PointerCompare); - if (SeenPointers =3D=3D NULL) { - Status =3D EFI_OUT_OF_RESOURCES; - goto FreeKeys; - } - - // - // second pass: identify and install ACPI tables - // - Installed =3D 0; - for (LoaderEntry =3D LoaderStart; LoaderEntry < LoaderEnd; ++LoaderEntry= ) { - if (LoaderEntry->Type =3D=3D QemuLoaderCmdAddPointer) { - Status =3D Process2ndPassCmdAddPointer ( - &LoaderEntry->Command.AddPointer, - Tracker, - AcpiProtocol, - InstalledKey, - &Installed, - SeenPointers - ); - if (EFI_ERROR (Status)) { - goto UninstallAcpiTables; - } - } - } - - // - // Translating the condensed QEMU_LOADER_WRITE_POINTER commands to ACPI = S3 - // Boot Script opcodes has to be the last operation in this function, be= cause - // if it succeeds, it cannot be undone. - // - if (S3Context !=3D NULL) { - Status =3D TransferS3ContextToBootScript (S3Context); - if (EFI_ERROR (Status)) { - goto UninstallAcpiTables; - } - // - // Ownership of S3Context has been transferred. - // - S3Context =3D NULL; - } - -UninstallAcpiTables: - if (EFI_ERROR (Status)) { - // - // roll back partial installation - // - while (Installed > 0) { - --Installed; - AcpiProtocol->UninstallAcpiTable (AcpiProtocol, InstalledKey[Install= ed]); - } - } else { - DEBUG ((DEBUG_INFO, "%a: installed %d tables\n", __FUNCTION__, Install= ed)); - } - - for (SeenPointerEntry =3D OrderedCollectionMin (SeenPointers); - SeenPointerEntry !=3D NULL; - SeenPointerEntry =3D SeenPointerEntry2) { - SeenPointerEntry2 =3D OrderedCollectionNext (SeenPointerEntry); - OrderedCollectionDelete (SeenPointers, SeenPointerEntry, NULL); - } - OrderedCollectionUninit (SeenPointers); - -FreeKeys: - FreePool (InstalledKey); - -RollbackWritePointersAndFreeTracker: - // - // In case of failure, revoke any allocation addresses that were communi= cated - // to QEMU previously, before we release all the blobs. - // - if (EFI_ERROR (Status)) { - LoaderEntry =3D WritePointerSubsetEnd; - while (LoaderEntry > LoaderStart) { - --LoaderEntry; - if (LoaderEntry->Type =3D=3D QemuLoaderCmdWritePointer) { - UndoCmdWritePointer (&LoaderEntry->Command.WritePointer); - } - } - } - - // - // Tear down the tracker infrastructure. Each fw_cfg blob will be left in - // place only if we're exiting with success and the blob hosts data that= is - // not directly part of some ACPI table. - // - for (TrackerEntry =3D OrderedCollectionMin (Tracker); TrackerEntry !=3D = NULL; - TrackerEntry =3D TrackerEntry2) { - VOID *UserStruct; - BLOB *Blob; - - TrackerEntry2 =3D OrderedCollectionNext (TrackerEntry); - OrderedCollectionDelete (Tracker, TrackerEntry, &UserStruct); - Blob =3D UserStruct; - - if (EFI_ERROR (Status) || Blob->HostsOnlyTableData) { - DEBUG ((DEBUG_VERBOSE, "%a: freeing \"%a\"\n", __FUNCTION__, - Blob->File)); - gBS->FreePages ((UINTN)Blob->Base, EFI_SIZE_TO_PAGES (Blob->Size)); - } - FreePool (Blob); - } - OrderedCollectionUninit (Tracker); - -FreeS3Context: - if (S3Context !=3D NULL) { - ReleaseS3Context (S3Context); - } - -FreeAllocationsRestrictedTo32Bit: - ReleaseAllocationsRestrictedTo32Bit (AllocationsRestrictedTo32Bit); - -FreeLoader: - FreePool (LoaderStart); - - return Status; -} --=20 2.19.1.3.g30247aa5d201 -=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 (#75682): https://edk2.groups.io/g/devel/message/75682 Mute This Topic: https://groups.io/mt/83110541/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-