From nobody Sat Nov 2 14:37:51 2024 Delivered-To: importer@patchew.org Received-SPF: none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) client-ip=198.145.21.10; envelope-from=edk2-devel-bounces@lists.01.org; helo=ml01.01.org; Authentication-Results: mx.zoho.com; spf=none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) smtp.mailfrom=edk2-devel-bounces@lists.01.org; Return-Path: Received: from ml01.01.org (ml01.01.org [198.145.21.10]) by mx.zohomail.com with SMTPS id 1489213652344964.7567174454755; Fri, 10 Mar 2017 22:27:32 -0800 (PST) Received: from [127.0.0.1] (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id 4FF4B803E8; Fri, 10 Mar 2017 22:27:24 -0800 (PST) Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id A8484803E8 for ; Fri, 10 Mar 2017 22:27:22 -0800 (PST) Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 45D6661BAD; Sat, 11 Mar 2017 06:27:23 +0000 (UTC) Received: from lacos-laptop-7.usersys.redhat.com (ovpn-116-21.phx2.redhat.com [10.3.116.21]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v2B6QvsQ001140; Sat, 11 Mar 2017 01:27:22 -0500 X-Original-To: edk2-devel@ml01.01.org From: Laszlo Ersek To: edk2-devel-01 Date: Sat, 11 Mar 2017 07:26:51 +0100 Message-Id: <20170311062651.28351-13-lersek@redhat.com> In-Reply-To: <20170311062651.28351-1-lersek@redhat.com> References: <20170311062651.28351-1-lersek@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Sat, 11 Mar 2017 06:27:23 +0000 (UTC) Subject: [edk2] [PATCH v2 12/12] OvmfPkg/AcpiPlatformDxe: save fw_cfg boot script with QemuFwCfgS3Lib X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Jordan Justen MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Errors-To: edk2-devel-bounces@lists.01.org Sender: "edk2-devel" X-ZohoMail: RSF_4 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" Drop the explicit S3SaveState protocol and opcode management; instead, create ACPI S3 Boot Script opcodes for the WRITE_POINTER commands with QemuFwCfgS3Lib functions. In this case, we have a dynamically allocated Context structure, hence the patch demonstrates how the FW_CFG_BOOT_SCRIPT_CALLBACK_FUNCTION takes ownership of Context. Cc: Jordan Justen Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=3D394 Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Laszlo Ersek --- Notes: v2: - rename QemuFwCfgS3TransferOwnership to QemuFwCfgS3CallWhenBootScriptReady [Jordan] - rename FW_CFG_BOOT_SCRIPT_APPEND_FUNCTION to FW_CFG_BOOT_SCRIPT_CALLBACK_FUNCTION [Jordan] - rename QemuFwCfgS3WriteBytes, QemuFwCfgS3ReadBytes, QemuFwCfgS3SkipBytes, and QemuFwCfgS3CheckValue to QemuFwCfgS3ScriptWriteBytes, QemuFwCfgS3ScriptReadBytes, QemuFwCfgS3ScriptSkipBytes, and QemuFwCfgS3ScriptCheckValue, respectively [Jordan] OvmfPkg/AcpiPlatformDxe/AcpiPlatformDxe.inf | 1 - OvmfPkg/AcpiPlatformDxe/QemuFwCfgAcpiPlatformDxe.inf | 1 - OvmfPkg/AcpiPlatformDxe/AcpiPlatform.h | 2 +- OvmfPkg/AcpiPlatformDxe/BootScript.c | 262 +++++----------= ----- OvmfPkg/AcpiPlatformDxe/QemuFwCfgAcpi.c | 7 + 5 files changed, 64 insertions(+), 209 deletions(-) diff --git a/OvmfPkg/AcpiPlatformDxe/AcpiPlatformDxe.inf b/OvmfPkg/AcpiPlat= formDxe/AcpiPlatformDxe.inf index 42edc97b3da2..9a9b2e6bb2e5 100644 --- a/OvmfPkg/AcpiPlatformDxe/AcpiPlatformDxe.inf +++ b/OvmfPkg/AcpiPlatformDxe/AcpiPlatformDxe.inf @@ -61,7 +61,6 @@ [LibraryClasses] [Protocols] gEfiAcpiTableProtocolGuid # PROTOCOL ALWAYS_CONSUMED gEfiPciIoProtocolGuid # PROTOCOL SOMETIMES_CONSU= MED - gEfiS3SaveStateProtocolGuid # PROTOCOL SOMETIMES_CONSU= MED =20 [Guids] gEfiXenInfoGuid diff --git a/OvmfPkg/AcpiPlatformDxe/QemuFwCfgAcpiPlatformDxe.inf b/OvmfPkg= /AcpiPlatformDxe/QemuFwCfgAcpiPlatformDxe.inf index a9350540215d..adc50cfd9f76 100644 --- a/OvmfPkg/AcpiPlatformDxe/QemuFwCfgAcpiPlatformDxe.inf +++ b/OvmfPkg/AcpiPlatformDxe/QemuFwCfgAcpiPlatformDxe.inf @@ -51,7 +51,6 @@ [LibraryClasses] [Protocols] gEfiAcpiTableProtocolGuid # PROTOCOL ALWAYS_CONSUMED gEfiPciIoProtocolGuid # PROTOCOL SOMETIMES_CONSU= MED - gEfiS3SaveStateProtocolGuid # PROTOCOL SOMETIMES_CONSU= MED =20 [Guids] gRootBridgesConnectedEventGroupGuid diff --git a/OvmfPkg/AcpiPlatformDxe/AcpiPlatform.h b/OvmfPkg/AcpiPlatformD= xe/AcpiPlatform.h index 0f035a0d5751..83b981ee005d 100644 --- a/OvmfPkg/AcpiPlatformDxe/AcpiPlatform.h +++ b/OvmfPkg/AcpiPlatformDxe/AcpiPlatform.h @@ -115,7 +115,7 @@ SaveCondensedWritePointerToS3Context ( =20 EFI_STATUS TransferS3ContextToBootScript ( - IN CONST S3_CONTEXT *S3Context + IN S3_CONTEXT *S3Context ); =20 #endif diff --git a/OvmfPkg/AcpiPlatformDxe/BootScript.c b/OvmfPkg/AcpiPlatformDxe= /BootScript.c index bff42ad8b9b0..a7d2f9e38f57 100644 --- a/OvmfPkg/AcpiPlatformDxe/BootScript.c +++ b/OvmfPkg/AcpiPlatformDxe/BootScript.c @@ -15,7 +15,7 @@ =20 #include #include -#include +#include =20 #include "AcpiPlatform.h" =20 @@ -53,19 +53,11 @@ struct S3_CONTEXT { =20 // // Scratch buffer, allocated in EfiReservedMemoryType type memory, for the= ACPI -// S3 Boot Script opcodes to work on. We use the buffer to compose and to -// replay several fw_cfg select+skip and write operations, using the DMA a= ccess -// method. The fw_cfg operations will implement the actions dictated by -// CONDENSED_WRITE_POINTER objects. +// S3 Boot Script opcodes to work on. // #pragma pack (1) -typedef struct { - FW_CFG_DMA_ACCESS Access; // filled in from - // CONDENSED_WRITE_POINTER.PointerItem, - // CONDENSED_WRITE_POINTER.PointerSize, - // CONDENSED_WRITE_POINTER.PointerOffs= et - UINT64 PointerValue; // filled in from - // CONDENSED_WRITE_POINTER.PointerValue +typedef union { + UINT64 PointerValue; // filled in from CONDENSED_WRITE_POINTER.PointerVa= lue } SCRATCH_BUFFER; #pragma pack () =20 @@ -197,220 +189,78 @@ SaveCondensedWritePointerToS3Context ( =20 =20 /** - 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. - - @retval EFI_OUT_OF_RESOURCES Out of memory. - - @retval EFI_SUCCESS The translation of S3Context to ACPI S3 Bo= ot - Script opcodes has been successful. - - @return Error codes from underlying functions. + FW_CFG_BOOT_SCRIPT_CALLBACK_FUNCTION provided to QemuFwCfgS3Lib. **/ -EFI_STATUS -TransferS3ContextToBootScript ( - IN CONST S3_CONTEXT *S3Context +STATIC +VOID +EFIAPI +AppendFwCfgBootScript ( + IN OUT VOID *Context, OPTIONAL + IN OUT VOID *ExternalScratchBuffer ) { - EFI_STATUS Status; - EFI_S3_SAVE_STATE_PROTOCOL *S3SaveState; - SCRATCH_BUFFER *ScratchBuffer; - FW_CFG_DMA_ACCESS *Access; - UINT64 BigEndianAddressOfAccess; - UINT32 ControlPollData; - UINT32 ControlPollMask; - UINTN Index; + S3_CONTEXT *S3Context; + SCRATCH_BUFFER *ScratchBuffer; + UINTN Index; =20 - // - // If the following protocol lookup fails, it shall not happen due to an - // unexpected DXE driver dispatch order. - // - // Namely, this function is only invoked on QEMU. Therefore it is only - // reached after Platform BDS signals gRootBridgesConnectedEventGroupGuid - // (see OnRootBridgesConnected() in "EntryPoint.c"). Hence, because - // TransferS3ContextToBootScript() is invoked in BDS, all DXE drivers, - // including S3SaveStateDxe (producing EFI_S3_SAVE_STATE_PROTOCOL), have= been - // dispatched by the time we get here. (S3SaveStateDxe is not expected to - // have any stricter-than-TRUE DEPEX -- not a DEPEX that gets unblocked = only - // within BDS anyway.) - // - // Reaching this function also depends on QemuFwCfgS3Enabled(). That imp= lies - // S3SaveStateDxe has not exited immediately due to S3 being disabled. T= hus - // EFI_S3_SAVE_STATE_PROTOCOL can only be missing for genuinely unforese= eable - // reasons. - // - Status =3D gBS->LocateProtocol (&gEfiS3SaveStateProtocolGuid, - NULL /* Registration */, (VOID **)&S3SaveState); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "%a: LocateProtocol(): %r\n", __FUNCTION__, Statu= s)); - return Status; - } + S3Context =3D Context; + ScratchBuffer =3D ExternalScratchBuffer; =20 - ScratchBuffer =3D AllocateReservedPool (sizeof *ScratchBuffer); - if (ScratchBuffer =3D=3D NULL) { - return EFI_OUT_OF_RESOURCES; - } - - // - // Set up helper variables that we'll use identically for all - // CONDENSED_WRITE_POINTER elements. - // - Access =3D &ScratchBuffer->Access; - BigEndianAddressOfAccess =3D SwapBytes64 ((UINTN)Access); - ControlPollData =3D 0; - ControlPollMask =3D MAX_UINT32; - - // - // For each CONDENSED_WRITE_POINTER, we need six ACPI S3 Boot Script opc= odes: - // (1) restore an FW_CFG_DMA_ACCESS object in reserved memory that selec= ts - // the writeable fw_cfg file PointerFile (through PointerItem), and = skips - // to PointerOffset in it, - // (2) call QEMU with the FW_CFG_DMA_ACCESS object, - // (3) wait for the select+skip to finish, - // (4) restore a SCRATCH_BUFFER object in reserved memory that writes - // PointerValue (base address of the allocated / downloaded PointeeF= ile, - // plus PointeeOffset), of size PointerSize, into the fw_cfg file - // selected in (1), at the offset sought to in (1), - // (5) call QEMU with the FW_CFG_DMA_ACCESS object, - // (6) wait for the write to finish. - // - // EFI_S3_SAVE_STATE_PROTOCOL does not allow rolling back opcode additio= ns, - // therefore we treat any failure here as fatal. - // for (Index =3D 0; Index < S3Context->Used; ++Index) { CONST CONDENSED_WRITE_POINTER *Condensed; + RETURN_STATUS Status; =20 Condensed =3D &S3Context->WritePointers[Index]; =20 - // - // (1) restore an FW_CFG_DMA_ACCESS object in reserved memory that sel= ects - // the writeable fw_cfg file PointerFile (through PointerItem), and - // skips to PointerOffset in it, - // - Access->Control =3D SwapBytes32 ((UINT32)Condensed->PointerItem << 16 | - FW_CFG_DMA_CTL_SELECT | FW_CFG_DMA_CTL_SKIP); - Access->Length =3D SwapBytes32 (Condensed->PointerOffset); - Access->Address =3D 0; - Status =3D S3SaveState->Write ( - S3SaveState, // This - EFI_BOOT_SCRIPT_MEM_WRITE_OPCODE, // OpCode - EfiBootScriptWidthUint8, // Width - (UINT64)(UINTN)Access, // Address - sizeof *Access, // Count - Access // Buffer - ); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "%a: Index %Lu opcode 1: %r\n", __FUNCTION__, - (UINT64)Index, Status)); + Status =3D QemuFwCfgS3ScriptSkipBytes (Condensed->PointerItem, + Condensed->PointerOffset); + if (RETURN_ERROR (Status)) { goto FatalError; } =20 - // - // (2) call QEMU with the FW_CFG_DMA_ACCESS object, - // - Status =3D S3SaveState->Write ( - S3SaveState, // This - EFI_BOOT_SCRIPT_IO_WRITE_OPCODE, // OpCode - EfiBootScriptWidthUint32, // Width - (UINT64)FW_CFG_IO_DMA_ADDRESS, // Address - (UINTN)2, // Count - &BigEndianAddressOfAccess // Buffer - ); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "%a: Index %Lu opcode 2: %r\n", __FUNCTION__, - (UINT64)Index, Status)); - goto FatalError; - } - - // - // (3) wait for the select+skip to finish, - // - Status =3D S3SaveState->Write ( - S3SaveState, // This - EFI_BOOT_SCRIPT_MEM_POLL_OPCODE, // OpCode - EfiBootScriptWidthUint32, // Width - (UINT64)(UINTN)&Access->Control, // Address - &ControlPollData, // Data - &ControlPollMask, // DataMask - MAX_UINT64 // Delay - ); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "%a: Index %Lu opcode 3: %r\n", __FUNCTION__, - (UINT64)Index, Status)); - goto FatalError; - } - - // - // (4) restore a SCRATCH_BUFFER object in reserved memory that writes - // PointerValue (base address of the allocated / downloaded - // PointeeFile, plus PointeeOffset), of size PointerSize, into the - // fw_cfg file selected in (1), at the offset sought to in (1), - // - Access->Control =3D SwapBytes32 (FW_CFG_DMA_CTL_WRITE); - Access->Length =3D SwapBytes32 (Condensed->PointerSize); - Access->Address =3D SwapBytes64 ((UINTN)&ScratchBuffer->PointerValue); ScratchBuffer->PointerValue =3D Condensed->PointerValue; - Status =3D S3SaveState->Write ( - S3SaveState, // This - EFI_BOOT_SCRIPT_MEM_WRITE_OPCODE, // OpCode - EfiBootScriptWidthUint8, // Width - (UINT64)(UINTN)ScratchBuffer, // Address - sizeof *ScratchBuffer, // Count - ScratchBuffer // Buffer - ); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "%a: Index %Lu opcode 4: %r\n", __FUNCTION__, - (UINT64)Index, Status)); - goto FatalError; - } - - // - // (5) call QEMU with the FW_CFG_DMA_ACCESS object, - // - Status =3D S3SaveState->Write ( - S3SaveState, // This - EFI_BOOT_SCRIPT_IO_WRITE_OPCODE, // OpCode - EfiBootScriptWidthUint32, // Width - (UINT64)FW_CFG_IO_DMA_ADDRESS, // Address - (UINTN)2, // Count - &BigEndianAddressOfAccess // Buffer - ); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "%a: Index %Lu opcode 5: %r\n", __FUNCTION__, - (UINT64)Index, Status)); - goto FatalError; - } - - // - // (6) wait for the write to finish. - // - Status =3D S3SaveState->Write ( - S3SaveState, // This - EFI_BOOT_SCRIPT_MEM_POLL_OPCODE, // OpCode - EfiBootScriptWidthUint32, // Width - (UINT64)(UINTN)&Access->Control, // Address - &ControlPollData, // Data - &ControlPollMask, // DataMask - MAX_UINT64 // Delay - ); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "%a: Index %Lu opcode 6: %r\n", __FUNCTION__, - (UINT64)Index, Status)); + Status =3D QemuFwCfgS3ScriptWriteBytes (-1, Condensed->PointerSize); + if (RETURN_ERROR (Status)) { goto FatalError; } } =20 - DEBUG ((DEBUG_VERBOSE, "%a: boot script fragment saved, ScratchBuffer=3D= %p\n", - __FUNCTION__, (VOID *)ScratchBuffer)); - return EFI_SUCCESS; + DEBUG ((DEBUG_VERBOSE, "%a: boot script fragment saved\n", __FUNCTION__)= ); + + ReleaseS3Context (S3Context); + return; =20 FatalError: ASSERT (FALSE); CpuDeadLoop (); - return Status; +} + + +/** + 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= ered. + + @retval EFI_SUCCESS The translation of S3Context to ACPI S3 Boot Script + opcodes has been successfully executed or queued. + + @return Error codes from underlying functions. +**/ +EFI_STATUS +TransferS3ContextToBootScript ( + IN S3_CONTEXT *S3Context + ) +{ + RETURN_STATUS Status; + + Status =3D QemuFwCfgS3CallWhenBootScriptReady (AppendFwCfgBootScript, + S3Context, sizeof (SCRATCH_BUFFER)); + return (EFI_STATUS)Status; } diff --git a/OvmfPkg/AcpiPlatformDxe/QemuFwCfgAcpi.c b/OvmfPkg/AcpiPlatform= Dxe/QemuFwCfgAcpi.c index 76512534f5e0..7bb2e3f21821 100644 --- a/OvmfPkg/AcpiPlatformDxe/QemuFwCfgAcpi.c +++ b/OvmfPkg/AcpiPlatformDxe/QemuFwCfgAcpi.c @@ -848,6 +848,13 @@ InstallQemuFwCfgTables ( // if (S3Context !=3D NULL) { Status =3D TransferS3ContextToBootScript (S3Context); + if (EFI_ERROR (Status)) { + goto UninstallAcpiTables; + } + // + // Ownership of S3Context has been transfered. + // + S3Context =3D NULL; } =20 UninstallAcpiTables: --=20 2.9.3 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel