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
next prev 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