]> git.proxmox.com Git - mirror_edk2.git/blobdiff - OvmfPkg/AcpiPlatformDxe/BootScript.c
BaseTools: Clean up tools_def.template for XCODE5
[mirror_edk2.git] / OvmfPkg / AcpiPlatformDxe / BootScript.c
index 1ad468e2f834c199ac79504b9c616f2df671f64d..a7d2f9e38f5742f2b9894b5234a5705d39e56a30 100644 (file)
@@ -15,7 +15,7 @@
 \r
 #include <Library/MemoryAllocationLib.h>\r
 #include <Library/QemuFwCfgLib.h>\r
-#include <Protocol/S3SaveState.h>\r
+#include <Library/QemuFwCfgS3Lib.h>\r
 \r
 #include "AcpiPlatform.h"\r
 \r
@@ -53,19 +53,11 @@ struct S3_CONTEXT {
 \r
 //\r
 // Scratch buffer, allocated in EfiReservedMemoryType type memory, for the ACPI\r
-// S3 Boot Script opcodes to work on. We use the buffer to compose and to\r
-// replay several fw_cfg select+skip and write operations, using the DMA access\r
-// method. The fw_cfg operations will implement the actions dictated by\r
-// CONDENSED_WRITE_POINTER objects.\r
+// S3 Boot Script opcodes to work on.\r
 //\r
 #pragma pack (1)\r
-typedef struct {\r
-  FW_CFG_DMA_ACCESS Access;       // filled in from\r
-                                  //   CONDENSED_WRITE_POINTER.PointerItem,\r
-                                  //   CONDENSED_WRITE_POINTER.PointerSize,\r
-                                  //   CONDENSED_WRITE_POINTER.PointerOffset\r
-  UINT64            PointerValue; // filled in from\r
-                                  //   CONDENSED_WRITE_POINTER.PointerValue\r
+typedef union {\r
+  UINT64 PointerValue; // filled in from CONDENSED_WRITE_POINTER.PointerValue\r
 } SCRATCH_BUFFER;\r
 #pragma pack ()\r
 \r
@@ -197,220 +189,78 @@ SaveCondensedWritePointerToS3Context (
 \r
 \r
 /**\r
-  Translate and append the information from an S3_CONTEXT object to the ACPI S3\r
-  Boot Script.\r
-\r
-  The effects of a successful call to this function cannot be undone.\r
-\r
-  @param[in] S3Context  The S3_CONTEXT object to translate to ACPI S3 Boot\r
-                        Script opcodes.\r
-\r
-  @retval EFI_OUT_OF_RESOURCES  Out of memory.\r
-\r
-  @retval EFI_SUCCESS           The translation of S3Context to ACPI S3 Boot\r
-                                Script opcodes has been successful.\r
-\r
-  @return                       Error codes from underlying functions.\r
+  FW_CFG_BOOT_SCRIPT_CALLBACK_FUNCTION provided to QemuFwCfgS3Lib.\r
 **/\r
-EFI_STATUS\r
-TransferS3ContextToBootScript (\r
-  IN CONST S3_CONTEXT *S3Context\r
+STATIC\r
+VOID\r
+EFIAPI\r
+AppendFwCfgBootScript (\r
+  IN OUT VOID *Context,              OPTIONAL\r
+  IN OUT VOID *ExternalScratchBuffer\r
   )\r
 {\r
-  EFI_STATUS                 Status;\r
-  EFI_S3_SAVE_STATE_PROTOCOL *S3SaveState;\r
-  SCRATCH_BUFFER             *ScratchBuffer;\r
-  FW_CFG_DMA_ACCESS          *Access;\r
-  UINT64                     BigEndianAddressOfAccess;\r
-  UINT32                     ControlPollData;\r
-  UINT32                     ControlPollMask;\r
-  UINTN                      Index;\r
-\r
-  //\r
-  // If the following protocol lookup fails, it shall not happen due to an\r
-  // unexpected DXE driver dispatch order.\r
-  //\r
-  // Namely, this function is only invoked on QEMU. Therefore it is only\r
-  // reached after Platform BDS signals gRootBridgesConnectedEventGroupGuid\r
-  // (see OnRootBridgesConnected() in "EntryPoint.c"). Hence, because\r
-  // TransferS3ContextToBootScript() is invoked in BDS, all DXE drivers,\r
-  // including S3SaveStateDxe (producing EFI_S3_SAVE_STATE_PROTOCOL), have been\r
-  // dispatched by the time we get here. (S3SaveStateDxe is not expected to\r
-  // have any stricter-than-TRUE DEPEX -- not a DEPEX that gets unblocked only\r
-  // within BDS anyway.)\r
-  //\r
-  // Reaching this function also depends on QemuFwCfgS3Enabled(). That implies\r
-  // S3SaveStateDxe has not exited immediately due to S3 being disabled. Thus\r
-  // EFI_S3_SAVE_STATE_PROTOCOL can only be missing for genuinely unforeseeable\r
-  // reasons.\r
-  //\r
-  Status = gBS->LocateProtocol (&gEfiS3SaveStateProtocolGuid,\r
-                  NULL /* Registration */, (VOID **)&S3SaveState);\r
-  if (EFI_ERROR (Status)) {\r
-    DEBUG ((DEBUG_ERROR, "%a: LocateProtocol(): %r\n", __FUNCTION__, Status));\r
-    return Status;\r
-  }\r
+  S3_CONTEXT     *S3Context;\r
+  SCRATCH_BUFFER *ScratchBuffer;\r
+  UINTN          Index;\r
 \r
-  ScratchBuffer = AllocateReservedPool (sizeof *ScratchBuffer);\r
-  if (ScratchBuffer == NULL) {\r
-    return EFI_OUT_OF_RESOURCES;\r
-  }\r
+  S3Context = Context;\r
+  ScratchBuffer = ExternalScratchBuffer;\r
 \r
-  //\r
-  // Set up helper variables that we'll use identically for all\r
-  // CONDENSED_WRITE_POINTER elements.\r
-  //\r
-  Access = &ScratchBuffer->Access;\r
-  BigEndianAddressOfAccess = SwapBytes64 ((UINTN)Access);\r
-  ControlPollData = 0;\r
-  ControlPollMask = MAX_UINT32;\r
-\r
-  //\r
-  // For each CONDENSED_WRITE_POINTER, we need six ACPI S3 Boot Script opcodes:\r
-  // (1) restore an FW_CFG_DMA_ACCESS object in reserved memory that selects\r
-  //     the writeable fw_cfg file PointerFile (through PointerItem), and skips\r
-  //     to PointerOffset in it,\r
-  // (2) call QEMU with the FW_CFG_DMA_ACCESS object,\r
-  // (3) wait for the select+skip to finish,\r
-  // (4) restore a SCRATCH_BUFFER object in reserved memory that writes\r
-  //     PointerValue (base address of the allocated / downloaded PointeeFile,\r
-  //     plus PointeeOffset), of size PointerSize, into the fw_cfg file\r
-  //     selected in (1), at the offset sought to in (1),\r
-  // (5) call QEMU with the FW_CFG_DMA_ACCESS object,\r
-  // (6) wait for the write to finish.\r
-  //\r
-  // EFI_S3_SAVE_STATE_PROTOCOL does not allow rolling back opcode additions,\r
-  // therefore we treat any failure here as fatal.\r
-  //\r
   for (Index = 0; Index < S3Context->Used; ++Index) {\r
     CONST CONDENSED_WRITE_POINTER *Condensed;\r
+    RETURN_STATUS                 Status;\r
 \r
     Condensed = &S3Context->WritePointers[Index];\r
 \r
-    //\r
-    // (1) restore an FW_CFG_DMA_ACCESS object in reserved memory that selects\r
-    //     the writeable fw_cfg file PointerFile (through PointerItem), and\r
-    //     skips to PointerOffset in it,\r
-    //\r
-    Access->Control = SwapBytes32 ((UINT32)Condensed->PointerItem << 16 |\r
-                        FW_CFG_DMA_CTL_SELECT | FW_CFG_DMA_CTL_SKIP);\r
-    Access->Length = SwapBytes32 (Condensed->PointerOffset);\r
-    Access->Address = 0;\r
-    Status = S3SaveState->Write (\r
-                            S3SaveState,                      // This\r
-                            EFI_BOOT_SCRIPT_MEM_WRITE_OPCODE, // OpCode\r
-                            EfiBootScriptWidthUint8,          // Width\r
-                            (UINT64)(UINTN)Access,            // Address\r
-                            sizeof *Access,                   // Count\r
-                            Access                            // Buffer\r
-                            );\r
-    if (EFI_ERROR (Status)) {\r
-      DEBUG ((DEBUG_ERROR, "%a: Index %Lu opcode 1: %r\n", __FUNCTION__,\r
-        (UINT64)Index, Status));\r
-      goto FatalError;\r
-    }\r
-\r
-    //\r
-    // (2) call QEMU with the FW_CFG_DMA_ACCESS object,\r
-    //\r
-    Status = S3SaveState->Write (\r
-                            S3SaveState,                     // This\r
-                            EFI_BOOT_SCRIPT_IO_WRITE_OPCODE, // OpCode\r
-                            EfiBootScriptWidthUint32,        // Width\r
-                            (UINT64)0x514,                   // Address\r
-                            (UINTN)2,                        // Count\r
-                            &BigEndianAddressOfAccess        // Buffer\r
-                            );\r
-    if (EFI_ERROR (Status)) {\r
-      DEBUG ((DEBUG_ERROR, "%a: Index %Lu opcode 2: %r\n", __FUNCTION__,\r
-        (UINT64)Index, Status));\r
+    Status = QemuFwCfgS3ScriptSkipBytes (Condensed->PointerItem,\r
+               Condensed->PointerOffset);\r
+    if (RETURN_ERROR (Status)) {\r
       goto FatalError;\r
     }\r
 \r
-    //\r
-    // (3) wait for the select+skip to finish,\r
-    //\r
-    Status = S3SaveState->Write (\r
-                            S3SaveState,                     // This\r
-                            EFI_BOOT_SCRIPT_MEM_POLL_OPCODE, // OpCode\r
-                            EfiBootScriptWidthUint32,        // Width\r
-                            (UINT64)(UINTN)&Access->Control, // Address\r
-                            &ControlPollData,                // Data\r
-                            &ControlPollMask,                // DataMask\r
-                            MAX_UINT64                       // Delay\r
-                            );\r
-    if (EFI_ERROR (Status)) {\r
-      DEBUG ((DEBUG_ERROR, "%a: Index %Lu opcode 3: %r\n", __FUNCTION__,\r
-        (UINT64)Index, Status));\r
-      goto FatalError;\r
-    }\r
-\r
-    //\r
-    // (4) restore a SCRATCH_BUFFER object in reserved memory that writes\r
-    //     PointerValue (base address of the allocated / downloaded\r
-    //     PointeeFile, plus PointeeOffset), of size PointerSize, into the\r
-    //     fw_cfg file selected in (1), at the offset sought to in (1),\r
-    //\r
-    Access->Control = SwapBytes32 (FW_CFG_DMA_CTL_WRITE);\r
-    Access->Length = SwapBytes32 (Condensed->PointerSize);\r
-    Access->Address = SwapBytes64 ((UINTN)&ScratchBuffer->PointerValue);\r
     ScratchBuffer->PointerValue = Condensed->PointerValue;\r
-    Status = S3SaveState->Write (\r
-                            S3SaveState,                      // This\r
-                            EFI_BOOT_SCRIPT_MEM_WRITE_OPCODE, // OpCode\r
-                            EfiBootScriptWidthUint8,          // Width\r
-                            (UINT64)(UINTN)ScratchBuffer,     // Address\r
-                            sizeof *ScratchBuffer,            // Count\r
-                            ScratchBuffer                     // Buffer\r
-                            );\r
-    if (EFI_ERROR (Status)) {\r
-      DEBUG ((DEBUG_ERROR, "%a: Index %Lu opcode 4: %r\n", __FUNCTION__,\r
-        (UINT64)Index, Status));\r
-      goto FatalError;\r
-    }\r
-\r
-    //\r
-    // (5) call QEMU with the FW_CFG_DMA_ACCESS object,\r
-    //\r
-    Status = S3SaveState->Write (\r
-                            S3SaveState,                     // This\r
-                            EFI_BOOT_SCRIPT_IO_WRITE_OPCODE, // OpCode\r
-                            EfiBootScriptWidthUint32,        // Width\r
-                            (UINT64)0x514,                   // Address\r
-                            (UINTN)2,                        // Count\r
-                            &BigEndianAddressOfAccess        // Buffer\r
-                            );\r
-    if (EFI_ERROR (Status)) {\r
-      DEBUG ((DEBUG_ERROR, "%a: Index %Lu opcode 5: %r\n", __FUNCTION__,\r
-        (UINT64)Index, Status));\r
-      goto FatalError;\r
-    }\r
-\r
-    //\r
-    // (6) wait for the write to finish.\r
-    //\r
-    Status = S3SaveState->Write (\r
-                            S3SaveState,                     // This\r
-                            EFI_BOOT_SCRIPT_MEM_POLL_OPCODE, // OpCode\r
-                            EfiBootScriptWidthUint32,        // Width\r
-                            (UINT64)(UINTN)&Access->Control, // Address\r
-                            &ControlPollData,                // Data\r
-                            &ControlPollMask,                // DataMask\r
-                            MAX_UINT64                       // Delay\r
-                            );\r
-    if (EFI_ERROR (Status)) {\r
-      DEBUG ((DEBUG_ERROR, "%a: Index %Lu opcode 6: %r\n", __FUNCTION__,\r
-        (UINT64)Index, Status));\r
+    Status = QemuFwCfgS3ScriptWriteBytes (-1, Condensed->PointerSize);\r
+    if (RETURN_ERROR (Status)) {\r
       goto FatalError;\r
     }\r
   }\r
 \r
-  DEBUG ((DEBUG_VERBOSE, "%a: boot script fragment saved, ScratchBuffer=%p\n",\r
-    __FUNCTION__, (VOID *)ScratchBuffer));\r
-  return EFI_SUCCESS;\r
+  DEBUG ((DEBUG_VERBOSE, "%a: boot script fragment saved\n", __FUNCTION__));\r
+\r
+  ReleaseS3Context (S3Context);\r
+  return;\r
 \r
 FatalError:\r
   ASSERT (FALSE);\r
   CpuDeadLoop ();\r
-  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Translate and append the information from an S3_CONTEXT object to the ACPI S3\r
+  Boot Script.\r
+\r
+  The effects of a successful call to this function cannot be undone.\r
+\r
+  @param[in] S3Context  The S3_CONTEXT object to translate to ACPI S3 Boot\r
+                        Script opcodes. If the function returns successfully,\r
+                        the caller must set the S3Context pointer -- originally\r
+                        returned by AllocateS3Context() -- immediately to NULL,\r
+                        because the ownership of S3Context has been transfered.\r
+\r
+  @retval EFI_SUCCESS The translation of S3Context to ACPI S3 Boot Script\r
+                      opcodes has been successfully executed or queued.\r
+\r
+  @return             Error codes from underlying functions.\r
+**/\r
+EFI_STATUS\r
+TransferS3ContextToBootScript (\r
+  IN S3_CONTEXT *S3Context\r
+  )\r
+{\r
+  RETURN_STATUS Status;\r
+\r
+  Status = QemuFwCfgS3CallWhenBootScriptReady (AppendFwCfgBootScript,\r
+             S3Context, sizeof (SCRATCH_BUFFER));\r
+  return (EFI_STATUS)Status;\r
 }\r