]> git.proxmox.com Git - mirror_edk2.git/blobdiff - OvmfPkg/AcpiPlatformDxe/QemuFwCfgAcpi.c
OvmfPkg/AcpiPlatformDxe: replay QEMU_LOADER_WRITE_POINTER commands at S3
[mirror_edk2.git] / OvmfPkg / AcpiPlatformDxe / QemuFwCfgAcpi.c
index de827c2df2040b623c0084b353fdf60614a69c86..eadd690bef4e591697feda1cf3995e171e5b319f 100644 (file)
@@ -360,6 +360,11 @@ ProcessCmdAddChecksum (
   @param[in] Tracker        The ORDERED_COLLECTION tracking the BLOB user\r
                             structures created thus far.\r
 \r
+  @param[in,out] S3Context  The S3_CONTEXT object capturing the fw_cfg actions\r
+                            of successfully processed QEMU_LOADER_WRITE_POINTER\r
+                            commands, to be replayed at S3 resume. S3Context\r
+                            may be NULL if S3 is disabled.\r
+\r
   @retval EFI_PROTOCOL_ERROR  Malformed fw_cfg file name(s) have been found in\r
                               WritePointer. Or, the WritePointer command\r
                               references a file unknown to Tracker or the\r
@@ -369,13 +374,21 @@ ProcessCmdAddChecksum (
                               does not fit in the given pointer size.\r
 \r
   @retval EFI_SUCCESS         The pointer object inside the writeable fw_cfg\r
-                              file has been written.\r
+                              file has been written. If S3Context is not NULL,\r
+                              then WritePointer has been condensed into\r
+                              S3Context.\r
+\r
+  @return                     Error codes propagated from\r
+                              SaveCondensedWritePointerToS3Context(). The\r
+                              pointer object inside the writeable fw_cfg file\r
+                              has not been written.\r
 **/\r
 STATIC\r
 EFI_STATUS\r
 ProcessCmdWritePointer (\r
   IN     CONST QEMU_LOADER_WRITE_POINTER *WritePointer,\r
-  IN     CONST ORDERED_COLLECTION        *Tracker\r
+  IN     CONST ORDERED_COLLECTION        *Tracker,\r
+  IN OUT       S3_CONTEXT                *S3Context OPTIONAL\r
   )\r
 {\r
   RETURN_STATUS            Status;\r
@@ -432,6 +445,25 @@ ProcessCmdWritePointer (
     return EFI_PROTOCOL_ERROR;\r
   }\r
 \r
+  //\r
+  // If S3 is enabled, we have to capture the below fw_cfg actions in condensed\r
+  // form, to be replayed during S3 resume.\r
+  //\r
+  if (S3Context != NULL) {\r
+    EFI_STATUS SaveStatus;\r
+\r
+    SaveStatus = SaveCondensedWritePointerToS3Context (\r
+                   S3Context,\r
+                   (UINT16)PointerItem,\r
+                   WritePointer->PointerSize,\r
+                   WritePointer->PointerOffset,\r
+                   PointerValue\r
+                   );\r
+    if (EFI_ERROR (SaveStatus)) {\r
+      return SaveStatus;\r
+    }\r
+  }\r
+\r
   QemuFwCfgSelectItem (PointerItem);\r
   QemuFwCfgSkipBytes (WritePointer->PointerOffset);\r
   QemuFwCfgWriteBytes (WritePointer->PointerSize, &PointerValue);\r
@@ -701,6 +733,7 @@ InstallQemuFwCfgTables (
   CONST QEMU_LOADER_ENTRY  *WritePointerSubsetEnd;\r
   ORIGINAL_ATTRIBUTES      *OriginalPciAttributes;\r
   UINTN                    OriginalPciAttributesCount;\r
+  S3_CONTEXT               *S3Context;\r
   ORDERED_COLLECTION       *Tracker;\r
   UINTN                    *InstalledKey;\r
   INT32                    Installed;\r
@@ -726,10 +759,22 @@ InstallQemuFwCfgTables (
   RestorePciDecoding (OriginalPciAttributes, OriginalPciAttributesCount);\r
   LoaderEnd = LoaderStart + FwCfgSize / sizeof *LoaderEntry;\r
 \r
+  S3Context = NULL;\r
+  if (QemuFwCfgS3Enabled ()) {\r
+    //\r
+    // Size the allocation pessimistically, assuming that all commands in the\r
+    // script are QEMU_LOADER_WRITE_POINTER commands.\r
+    //\r
+    Status = AllocateS3Context (&S3Context, LoaderEnd - LoaderStart);\r
+    if (EFI_ERROR (Status)) {\r
+      goto FreeLoader;\r
+    }\r
+  }\r
+\r
   Tracker = OrderedCollectionInit (BlobCompare, BlobKeyCompare);\r
   if (Tracker == NULL) {\r
     Status = EFI_OUT_OF_RESOURCES;\r
-    goto FreeLoader;\r
+    goto FreeS3Context;\r
   }\r
 \r
   //\r
@@ -758,7 +803,7 @@ InstallQemuFwCfgTables (
 \r
     case QemuLoaderCmdWritePointer:\r
         Status = ProcessCmdWritePointer (&LoaderEntry->Command.WritePointer,\r
-                   Tracker);\r
+                   Tracker, S3Context);\r
         if (!EFI_ERROR (Status)) {\r
           WritePointerSubsetEnd = LoaderEntry + 1;\r
         }\r
@@ -790,11 +835,21 @@ InstallQemuFwCfgTables (
       Status = Process2ndPassCmdAddPointer (&LoaderEntry->Command.AddPointer,\r
                  Tracker, AcpiProtocol, InstalledKey, &Installed);\r
       if (EFI_ERROR (Status)) {\r
-        break;\r
+        goto UninstallAcpiTables;\r
       }\r
     }\r
   }\r
 \r
+  //\r
+  // Translating the condensed QEMU_LOADER_WRITE_POINTER commands to ACPI S3\r
+  // Boot Script opcodes has to be the last operation in this function, because\r
+  // if it succeeds, it cannot be undone.\r
+  //\r
+  if (S3Context != NULL) {\r
+    Status = TransferS3ContextToBootScript (S3Context);\r
+  }\r
+\r
+UninstallAcpiTables:\r
   if (EFI_ERROR (Status)) {\r
     //\r
     // roll back partial installation\r
@@ -847,6 +902,11 @@ RollbackWritePointersAndFreeTracker:
   }\r
   OrderedCollectionUninit (Tracker);\r
 \r
+FreeS3Context:\r
+  if (S3Context != NULL) {\r
+    ReleaseS3Context (S3Context);\r
+  }\r
+\r
 FreeLoader:\r
   FreePool (LoaderStart);\r
 \r