public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: Laszlo Ersek <lersek@redhat.com>
To: edk2-devel-01 <edk2-devel@ml01.01.org>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Subject: [PATCH v2 12/12] OvmfPkg/AcpiPlatformDxe: save fw_cfg boot script with QemuFwCfgS3Lib
Date: Sat, 11 Mar 2017 07:26:51 +0100	[thread overview]
Message-ID: <20170311062651.28351-13-lersek@redhat.com> (raw)
In-Reply-To: <20170311062651.28351-1-lersek@redhat.com>

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 <jordan.l.justen@intel.com>
Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=394
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
---

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/AcpiPlatformDxe/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_CONSUMED
-  gEfiS3SaveStateProtocolGuid                   # PROTOCOL SOMETIMES_CONSUMED
 
 [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_CONSUMED
-  gEfiS3SaveStateProtocolGuid                   # PROTOCOL SOMETIMES_CONSUMED
 
 [Guids]
   gRootBridgesConnectedEventGroupGuid
diff --git a/OvmfPkg/AcpiPlatformDxe/AcpiPlatform.h b/OvmfPkg/AcpiPlatformDxe/AcpiPlatform.h
index 0f035a0d5751..83b981ee005d 100644
--- a/OvmfPkg/AcpiPlatformDxe/AcpiPlatform.h
+++ b/OvmfPkg/AcpiPlatformDxe/AcpiPlatform.h
@@ -115,7 +115,7 @@ SaveCondensedWritePointerToS3Context (
 
 EFI_STATUS
 TransferS3ContextToBootScript (
-  IN CONST S3_CONTEXT *S3Context
+  IN S3_CONTEXT *S3Context
   );
 
 #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 @@
 
 #include <Library/MemoryAllocationLib.h>
 #include <Library/QemuFwCfgLib.h>
-#include <Protocol/S3SaveState.h>
+#include <Library/QemuFwCfgS3Lib.h>
 
 #include "AcpiPlatform.h"
 
@@ -53,19 +53,11 @@ struct S3_CONTEXT {
 
 //
 // 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 access
-// 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.PointerOffset
-  UINT64            PointerValue; // filled in from
-                                  //   CONDENSED_WRITE_POINTER.PointerValue
+typedef union {
+  UINT64 PointerValue; // filled in from CONDENSED_WRITE_POINTER.PointerValue
 } SCRATCH_BUFFER;
 #pragma pack ()
 
@@ -197,220 +189,78 @@ SaveCondensedWritePointerToS3Context (
 
 
 /**
-  Translate and append the information from an S3_CONTEXT object to the ACPI 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 Boot
-                                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;
 
-  //
-  // 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 implies
-  // S3SaveStateDxe has not exited immediately due to S3 being disabled. Thus
-  // EFI_S3_SAVE_STATE_PROTOCOL can only be missing for genuinely unforeseeable
-  // reasons.
-  //
-  Status = gBS->LocateProtocol (&gEfiS3SaveStateProtocolGuid,
-                  NULL /* Registration */, (VOID **)&S3SaveState);
-  if (EFI_ERROR (Status)) {
-    DEBUG ((DEBUG_ERROR, "%a: LocateProtocol(): %r\n", __FUNCTION__, Status));
-    return Status;
-  }
+  S3Context = Context;
+  ScratchBuffer = ExternalScratchBuffer;
 
-  ScratchBuffer = AllocateReservedPool (sizeof *ScratchBuffer);
-  if (ScratchBuffer == NULL) {
-    return EFI_OUT_OF_RESOURCES;
-  }
-
-  //
-  // Set up helper variables that we'll use identically for all
-  // CONDENSED_WRITE_POINTER elements.
-  //
-  Access = &ScratchBuffer->Access;
-  BigEndianAddressOfAccess = SwapBytes64 ((UINTN)Access);
-  ControlPollData = 0;
-  ControlPollMask = MAX_UINT32;
-
-  //
-  // For each CONDENSED_WRITE_POINTER, we need six ACPI S3 Boot Script opcodes:
-  // (1) restore an FW_CFG_DMA_ACCESS object in reserved memory that selects
-  //     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 PointeeFile,
-  //     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 additions,
-  // therefore we treat any failure here as fatal.
-  //
   for (Index = 0; Index < S3Context->Used; ++Index) {
     CONST CONDENSED_WRITE_POINTER *Condensed;
+    RETURN_STATUS                 Status;
 
     Condensed = &S3Context->WritePointers[Index];
 
-    //
-    // (1) restore an FW_CFG_DMA_ACCESS object in reserved memory that selects
-    //     the writeable fw_cfg file PointerFile (through PointerItem), and
-    //     skips to PointerOffset in it,
-    //
-    Access->Control = SwapBytes32 ((UINT32)Condensed->PointerItem << 16 |
-                        FW_CFG_DMA_CTL_SELECT | FW_CFG_DMA_CTL_SKIP);
-    Access->Length = SwapBytes32 (Condensed->PointerOffset);
-    Access->Address = 0;
-    Status = 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 = QemuFwCfgS3ScriptSkipBytes (Condensed->PointerItem,
+               Condensed->PointerOffset);
+    if (RETURN_ERROR (Status)) {
       goto FatalError;
     }
 
-    //
-    // (2) call QEMU with the FW_CFG_DMA_ACCESS object,
-    //
-    Status = 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 = 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 = SwapBytes32 (FW_CFG_DMA_CTL_WRITE);
-    Access->Length = SwapBytes32 (Condensed->PointerSize);
-    Access->Address = SwapBytes64 ((UINTN)&ScratchBuffer->PointerValue);
     ScratchBuffer->PointerValue = Condensed->PointerValue;
-    Status = 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 = 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 = 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 = QemuFwCfgS3ScriptWriteBytes (-1, Condensed->PointerSize);
+    if (RETURN_ERROR (Status)) {
       goto FatalError;
     }
   }
 
-  DEBUG ((DEBUG_VERBOSE, "%a: boot script fragment saved, ScratchBuffer=%p\n",
-    __FUNCTION__, (VOID *)ScratchBuffer));
-  return EFI_SUCCESS;
+  DEBUG ((DEBUG_VERBOSE, "%a: boot script fragment saved\n", __FUNCTION__));
+
+  ReleaseS3Context (S3Context);
+  return;
 
 FatalError:
   ASSERT (FALSE);
   CpuDeadLoop ();
-  return Status;
+}
+
+
+/**
+  Translate and append the information from an S3_CONTEXT object to the ACPI 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 successfully,
+                        the caller must set the S3Context pointer -- originally
+                        returned by AllocateS3Context() -- immediately to NULL,
+                        because the ownership of S3Context has been transfered.
+
+  @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 = QemuFwCfgS3CallWhenBootScriptReady (AppendFwCfgBootScript,
+             S3Context, sizeof (SCRATCH_BUFFER));
+  return (EFI_STATUS)Status;
 }
diff --git a/OvmfPkg/AcpiPlatformDxe/QemuFwCfgAcpi.c b/OvmfPkg/AcpiPlatformDxe/QemuFwCfgAcpi.c
index 76512534f5e0..7bb2e3f21821 100644
--- a/OvmfPkg/AcpiPlatformDxe/QemuFwCfgAcpi.c
+++ b/OvmfPkg/AcpiPlatformDxe/QemuFwCfgAcpi.c
@@ -848,6 +848,13 @@ InstallQemuFwCfgTables (
   //
   if (S3Context != NULL) {
     Status = TransferS3ContextToBootScript (S3Context);
+    if (EFI_ERROR (Status)) {
+      goto UninstallAcpiTables;
+    }
+    //
+    // Ownership of S3Context has been transfered.
+    //
+    S3Context = NULL;
   }
 
 UninstallAcpiTables:
-- 
2.9.3



  parent reply	other threads:[~2017-03-11  6:27 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-03-11  6:26 [PATCH v2 00/12] ArmVirtPkg, OvmfPkg: factor out QemuFwCfgS3Lib Laszlo Ersek
2017-03-11  6:26 ` [PATCH v2 01/12] OvmfPkg: introduce QemuFwCfgS3Lib class Laszlo Ersek
2017-03-11  6:26 ` [PATCH v2 02/12] OvmfPkg/QemuFwCfgS3Lib: add initial Base Null library instance Laszlo Ersek
2017-03-11  6:26 ` [PATCH v2 03/12] OvmfPkg/QemuFwCfgS3Lib: add initial PEI and DXE fw_cfg library instances Laszlo Ersek
2017-03-11  6:26 ` [PATCH v2 04/12] ArmVirtPkg: resolve QemuFwCfgS3Lib Laszlo Ersek
2017-03-11  6:26 ` [PATCH v2 05/12] OvmfPkg: " Laszlo Ersek
2017-03-11  6:26 ` [PATCH v2 06/12] ArmVirtPkg, OvmfPkg: retire QemuFwCfgS3Enabled() from QemuFwCfgLib Laszlo Ersek
2017-03-11  6:26 ` [PATCH v2 07/12] OvmfPkg/QemuFwCfgS3Lib: add boot script opcode generation APIs to libclass Laszlo Ersek
2017-03-11  6:26 ` [PATCH v2 08/12] OvmfPkg/QemuFwCfgS3Lib: implement opcode APIs for Base Null instance Laszlo Ersek
2017-03-11  6:26 ` [PATCH v2 09/12] OvmfPkg/QemuFwCfgS3Lib: implement opcode APIs for PEI fw_cfg instance Laszlo Ersek
2017-03-11  6:26 ` [PATCH v2 10/12] OvmfPkg/QemuFwCfgS3Lib: implement opcode APIs for DXE " Laszlo Ersek
2017-03-11  6:26 ` [PATCH v2 11/12] OvmfPkg/SmmControl2Dxe: save fw_cfg boot script with QemuFwCfgS3Lib Laszlo Ersek
2017-03-11  6:26 ` Laszlo Ersek [this message]
2017-03-14 18:14 ` [PATCH v2 00/12] ArmVirtPkg, OvmfPkg: factor out QemuFwCfgS3Lib Jordan Justen
2017-03-14 20:56   ` Laszlo Ersek

Reply instructions:

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

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

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

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

  git send-email \
    --in-reply-to=20170311062651.28351-13-lersek@redhat.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

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

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