@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
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
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
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
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
\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
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
}\r
OrderedCollectionUninit (Tracker);\r
\r
+FreeS3Context:\r
+ if (S3Context != NULL) {\r
+ ReleaseS3Context (S3Context);\r
+ }\r
+\r
FreeLoader:\r
FreePool (LoaderStart);\r
\r