summaryrefslogtreecommitdiffstats
path: root/OvmfPkg/AcpiPlatformDxe/QemuFwCfgAcpi.c
diff options
context:
space:
mode:
authorLaszlo Ersek <lersek@redhat.com>2017-02-09 17:32:40 +0100
committerLaszlo Ersek <lersek@redhat.com>2017-02-21 13:10:42 +0100
commitdf73df138d9d53f7f7570f4fe97a6cde941a2656 (patch)
tree44476421f4a08c953cd16e5175b9fce511ba9394 /OvmfPkg/AcpiPlatformDxe/QemuFwCfgAcpi.c
parent9965cbd424f22b35e7743c2f59ab3ee1db15142a (diff)
downloadedk2-df73df138d9d53f7f7570f4fe97a6cde941a2656.tar.gz
edk2-df73df138d9d53f7f7570f4fe97a6cde941a2656.tar.bz2
edk2-df73df138d9d53f7f7570f4fe97a6cde941a2656.zip
OvmfPkg/AcpiPlatformDxe: replay QEMU_LOADER_WRITE_POINTER commands at S3
Ultimately, each QEMU_LOADER_WRITE_POINTER command creates a guest memory reference in some QEMU device. When the virtual machine is reset, the device willfully forgets the guest address, since the guest memory is wholly invalidated during platform reset. ... Unless the reset is part of S3 resume. Then the guest memory is preserved intact, and the firmware must reprogram those devices with the original guest memory allocation addresses. This patch accumulates the fw_cfg select, skip and write operations of ProcessCmdWritePointer() in a validated / condensed form, and turns them into an ACPI S3 Boot Script fragment at the very end of InstallQemuFwCfgTables(). Cc: Jordan Justen <jordan.l.justen@intel.com> Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=359 Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Laszlo Ersek <lersek@redhat.com> Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
Diffstat (limited to 'OvmfPkg/AcpiPlatformDxe/QemuFwCfgAcpi.c')
-rw-r--r--OvmfPkg/AcpiPlatformDxe/QemuFwCfgAcpi.c70
1 files changed, 65 insertions, 5 deletions
diff --git a/OvmfPkg/AcpiPlatformDxe/QemuFwCfgAcpi.c b/OvmfPkg/AcpiPlatformDxe/QemuFwCfgAcpi.c
index de827c2df2..eadd690bef 100644
--- a/OvmfPkg/AcpiPlatformDxe/QemuFwCfgAcpi.c
+++ b/OvmfPkg/AcpiPlatformDxe/QemuFwCfgAcpi.c
@@ -360,6 +360,11 @@ ProcessCmdAddChecksum (
@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 actions
+ of successfully processed QEMU_LOADER_WRITE_POINTER
+ commands, to be replayed at S3 resume. S3Context
+ may be NULL if S3 is disabled.
+
@retval EFI_PROTOCOL_ERROR Malformed fw_cfg file name(s) have been found in
WritePointer. Or, the WritePointer command
references a file unknown to Tracker or the
@@ -369,13 +374,21 @@ ProcessCmdAddChecksum (
does not fit in the given pointer size.
@retval EFI_SUCCESS The pointer object inside the writeable fw_cfg
- file has been written.
+ file has been written. If S3Context is not NULL,
+ then WritePointer has been condensed into
+ S3Context.
+
+ @return Error codes propagated from
+ SaveCondensedWritePointerToS3Context(). The
+ pointer object inside the writeable fw_cfg file
+ has not been written.
**/
STATIC
EFI_STATUS
ProcessCmdWritePointer (
IN CONST QEMU_LOADER_WRITE_POINTER *WritePointer,
- IN CONST ORDERED_COLLECTION *Tracker
+ IN CONST ORDERED_COLLECTION *Tracker,
+ IN OUT S3_CONTEXT *S3Context OPTIONAL
)
{
RETURN_STATUS Status;
@@ -432,6 +445,25 @@ ProcessCmdWritePointer (
return EFI_PROTOCOL_ERROR;
}
+ //
+ // If S3 is enabled, we have to capture the below fw_cfg actions in condensed
+ // form, to be replayed during S3 resume.
+ //
+ if (S3Context != NULL) {
+ EFI_STATUS SaveStatus;
+
+ SaveStatus = SaveCondensedWritePointerToS3Context (
+ S3Context,
+ (UINT16)PointerItem,
+ WritePointer->PointerSize,
+ WritePointer->PointerOffset,
+ PointerValue
+ );
+ if (EFI_ERROR (SaveStatus)) {
+ return SaveStatus;
+ }
+ }
+
QemuFwCfgSelectItem (PointerItem);
QemuFwCfgSkipBytes (WritePointer->PointerOffset);
QemuFwCfgWriteBytes (WritePointer->PointerSize, &PointerValue);
@@ -701,6 +733,7 @@ InstallQemuFwCfgTables (
CONST QEMU_LOADER_ENTRY *WritePointerSubsetEnd;
ORIGINAL_ATTRIBUTES *OriginalPciAttributes;
UINTN OriginalPciAttributesCount;
+ S3_CONTEXT *S3Context;
ORDERED_COLLECTION *Tracker;
UINTN *InstalledKey;
INT32 Installed;
@@ -726,10 +759,22 @@ InstallQemuFwCfgTables (
RestorePciDecoding (OriginalPciAttributes, OriginalPciAttributesCount);
LoaderEnd = LoaderStart + FwCfgSize / sizeof *LoaderEntry;
+ S3Context = NULL;
+ if (QemuFwCfgS3Enabled ()) {
+ //
+ // Size the allocation pessimistically, assuming that all commands in the
+ // script are QEMU_LOADER_WRITE_POINTER commands.
+ //
+ Status = AllocateS3Context (&S3Context, LoaderEnd - LoaderStart);
+ if (EFI_ERROR (Status)) {
+ goto FreeLoader;
+ }
+ }
+
Tracker = OrderedCollectionInit (BlobCompare, BlobKeyCompare);
if (Tracker == NULL) {
Status = EFI_OUT_OF_RESOURCES;
- goto FreeLoader;
+ goto FreeS3Context;
}
//
@@ -758,7 +803,7 @@ InstallQemuFwCfgTables (
case QemuLoaderCmdWritePointer:
Status = ProcessCmdWritePointer (&LoaderEntry->Command.WritePointer,
- Tracker);
+ Tracker, S3Context);
if (!EFI_ERROR (Status)) {
WritePointerSubsetEnd = LoaderEntry + 1;
}
@@ -790,11 +835,21 @@ InstallQemuFwCfgTables (
Status = Process2ndPassCmdAddPointer (&LoaderEntry->Command.AddPointer,
Tracker, AcpiProtocol, InstalledKey, &Installed);
if (EFI_ERROR (Status)) {
- break;
+ 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, because
+ // if it succeeds, it cannot be undone.
+ //
+ if (S3Context != NULL) {
+ Status = TransferS3ContextToBootScript (S3Context);
+ }
+
+UninstallAcpiTables:
if (EFI_ERROR (Status)) {
//
// roll back partial installation
@@ -847,6 +902,11 @@ RollbackWritePointersAndFreeTracker:
}
OrderedCollectionUninit (Tracker);
+FreeS3Context:
+ if (S3Context != NULL) {
+ ReleaseS3Context (S3Context);
+ }
+
FreeLoader:
FreePool (LoaderStart);