]> git.proxmox.com Git - mirror_edk2.git/blobdiff - OvmfPkg/AcpiS3SaveDxe/AcpiS3Save.c
OvmfPkg: fix conversion specifiers in DEBUG format strings
[mirror_edk2.git] / OvmfPkg / AcpiS3SaveDxe / AcpiS3Save.c
index 684ddb70114a3890ffcb49022fb0add79c923e0d..f20560f8fe1f0623321dfc425914acc9f3985ebf 100644 (file)
@@ -1,7 +1,11 @@
 /** @file\r
-  This is an implementation of the ACPI S3 Save protocol.  This is defined in\r
-  S3 boot path specification 0.9.\r
+  This is a replacement for the ACPI S3 Save protocol.\r
 \r
+  The ACPI S3 Save protocol used to be defined in the S3 boot path\r
+  specification 0.9. Instead, the same functionality is now hooked to the\r
+  End-of-Dxe event.\r
+\r
+Copyright (c) 2014-2015, Red Hat, Inc.<BR>\r
 Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>\r
 \r
 This program and the accompanying materials\r
@@ -24,23 +28,14 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <Library/LockBoxLib.h>\r
 #include <Library/PcdLib.h>\r
 #include <Library/DebugLib.h>\r
+#include <Library/QemuFwCfgLib.h>\r
 #include <Guid/AcpiVariableCompatibility.h>\r
 #include <Guid/AcpiS3Context.h>\r
 #include <Guid/Acpi.h>\r
-#include <Protocol/AcpiS3Save.h>\r
-#include <Protocol/S3SaveState.h>\r
-#include <Protocol/DxeSmmReadyToLock.h>\r
+#include <Guid/EventGroup.h>\r
+#include <Protocol/LockBox.h>\r
 #include <IndustryStandard/Acpi.h>\r
 \r
-#include "AcpiS3Save.h"\r
-\r
-UINTN     mLegacyRegionSize;\r
-\r
-EFI_ACPI_S3_SAVE_PROTOCOL mS3Save = {\r
-  LegacyGetS3MemorySize,\r
-  S3Ready,\r
-};\r
-\r
 EFI_GUID              mAcpiS3IdtrProfileGuid = {\r
   0xdea652b0, 0xd587, 0x4c54, { 0xb5, 0xb4, 0xc6, 0x82, 0xe7, 0xa0, 0xaa, 0x3d }\r
 };\r
@@ -366,7 +361,8 @@ S3CreateIdentityMappingPageTables (
     } else {\r
       TotalPageTableSize = (UINTN)(1 + NumberOfPml4EntriesNeeded);\r
     }\r
-    DEBUG ((EFI_D_ERROR, "TotalPageTableSize - %x pages\n", TotalPageTableSize));\r
+    DEBUG ((EFI_D_ERROR, "TotalPageTableSize - %Lx pages\n",\r
+      (UINT64)TotalPageTableSize));\r
 \r
     //\r
     // By architecture only one PageMapLevel4 exists - so lets allocate storage for it.\r
@@ -382,93 +378,18 @@ S3CreateIdentityMappingPageTables (
   }\r
 }\r
 \r
-/**\r
-  Gets the buffer of legacy memory below 1 MB \r
-  This function is to get the buffer in legacy memory below 1MB that is required during S3 resume.\r
-\r
-  @param This           A pointer to the EFI_ACPI_S3_SAVE_PROTOCOL instance.\r
-  @param Size           The returned size of legacy memory below 1 MB.\r
-\r
-  @retval EFI_SUCCESS           Size is successfully returned.\r
-  @retval EFI_INVALID_PARAMETER The pointer Size is NULL.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-LegacyGetS3MemorySize (\r
-  IN  EFI_ACPI_S3_SAVE_PROTOCOL   *This,\r
-  OUT UINTN                       *Size\r
-  )\r
-{\r
-  if (Size == NULL) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  *Size = mLegacyRegionSize;\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
-  Save the S3 boot script.\r
-\r
-  Note that we trigger DxeSmmReadyToLock here -- otherwise the script wouldn't\r
-  be saved actually. Triggering this protocol installation event in turn locks\r
-  down SMM, so no further changes to LockBoxes or SMRAM are possible\r
-  afterwards.\r
-**/\r
-STATIC\r
-VOID\r
-EFIAPI\r
-SaveS3BootScript (\r
-  VOID\r
-  )\r
-{\r
-  EFI_STATUS                 Status;\r
-  EFI_S3_SAVE_STATE_PROTOCOL *BootScript;\r
-  EFI_HANDLE                 Handle;\r
-  STATIC CONST UINT8         Info[] = { 0xDE, 0xAD, 0xBE, 0xEF };\r
-\r
-  Status = gBS->LocateProtocol (&gEfiS3SaveStateProtocolGuid, NULL,\r
-                  (VOID **) &BootScript);\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  //\r
-  // Despite the opcode documentation in the PI spec, the protocol\r
-  // implementation embeds a deep copy of the info in the boot script, rather\r
-  // than storing just a pointer to runtime or NVS storage.\r
-  //\r
-  Status = BootScript->Write(BootScript, EFI_BOOT_SCRIPT_INFORMATION_OPCODE,\r
-                         (UINT32) sizeof Info,\r
-                         (EFI_PHYSICAL_ADDRESS)(UINTN) &Info);\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  Handle = NULL;\r
-  Status = gBS->InstallProtocolInterface (&Handle,\r
-                  &gEfiDxeSmmReadyToLockProtocolGuid, EFI_NATIVE_INTERFACE,\r
-                  NULL);\r
-  ASSERT_EFI_ERROR (Status);\r
-}\r
-\r
-\r
 /**\r
   Prepares all information that is needed in the S3 resume boot path.\r
   \r
   Allocate the resources or prepare informations and save in ACPI variable set for S3 resume boot path  \r
   \r
-  @param This                 A pointer to the EFI_ACPI_S3_SAVE_PROTOCOL instance.\r
-  @param LegacyMemoryAddress  The base address of legacy memory.\r
-\r
-  @retval EFI_NOT_FOUND         Some necessary information cannot be found.\r
   @retval EFI_SUCCESS           All information was saved successfully.\r
-  @retval EFI_OUT_OF_RESOURCES  Resources were insufficient to save all the information.\r
-  @retval EFI_INVALID_PARAMETER The memory range is not located below 1 MB.\r
-\r
 **/\r
+STATIC\r
 EFI_STATUS\r
 EFIAPI\r
 S3Ready (\r
-  IN EFI_ACPI_S3_SAVE_PROTOCOL    *This,\r
-  IN VOID                         *LegacyMemoryAddress\r
+  VOID\r
   )\r
 {\r
   EFI_STATUS                                    Status;\r
@@ -480,10 +401,7 @@ S3Ready (
 \r
   DEBUG ((EFI_D_INFO, "S3Ready!\n"));\r
 \r
-  //\r
-  // Platform may invoke AcpiS3Save->S3Save() before ExitPmAuth, because we need save S3 information there, while BDS ReadyToBoot may invoke it again.\r
-  // So if 2nd S3Save() is triggered later, we need ignore it.\r
-  //\r
+  ASSERT (!AlreadyEntered);\r
   if (AlreadyEntered) {\r
     return EFI_SUCCESS;\r
   }\r
@@ -533,10 +451,14 @@ S3Ready (
   AcpiS3Context->S3DebugBufferAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocateMemoryBelow4G (EfiReservedMemoryType, EFI_PAGE_SIZE);\r
   SetMem ((VOID *)(UINTN)AcpiS3Context->S3DebugBufferAddress, EFI_PAGE_SIZE, 0xff);\r
 \r
-  DEBUG((EFI_D_INFO, "AcpiS3Context: AcpiFacsTable is 0x%8x\n", AcpiS3Context->AcpiFacsTable));\r
-  DEBUG((EFI_D_INFO, "AcpiS3Context: IdtrProfile is 0x%8x\n", AcpiS3Context->IdtrProfile));\r
-  DEBUG((EFI_D_INFO, "AcpiS3Context: S3NvsPageTableAddress is 0x%8x\n", AcpiS3Context->S3NvsPageTableAddress));\r
-  DEBUG((EFI_D_INFO, "AcpiS3Context: S3DebugBufferAddress is 0x%8x\n", AcpiS3Context->S3DebugBufferAddress));\r
+  DEBUG ((EFI_D_INFO, "AcpiS3Context: AcpiFacsTable is 0x%8Lx\n",\r
+    AcpiS3Context->AcpiFacsTable));\r
+  DEBUG ((EFI_D_INFO, "AcpiS3Context: IdtrProfile is 0x%8Lx\n",\r
+    AcpiS3Context->IdtrProfile));\r
+  DEBUG ((EFI_D_INFO, "AcpiS3Context: S3NvsPageTableAddress is 0x%8Lx\n",\r
+    AcpiS3Context->S3NvsPageTableAddress));\r
+  DEBUG ((EFI_D_INFO, "AcpiS3Context: S3DebugBufferAddress is 0x%8Lx\n",\r
+    AcpiS3Context->S3DebugBufferAddress));\r
 \r
   Status = SaveLockBox (\r
              &gEfiAcpiVariableGuid,\r
@@ -555,19 +477,45 @@ S3Ready (
   Status = SetLockBoxAttributes (&gEfiAcpiS3ContextGuid, LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE);\r
   ASSERT_EFI_ERROR (Status);\r
 \r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Callback function executed when the EndOfDxe event group is signaled.\r
+\r
+  @param[in] Event    Event whose notification function is being invoked.\r
+  @param[in] Context  The pointer to the notification function's context, which\r
+                      is implementation-dependent.\r
+**/\r
+VOID\r
+EFIAPI\r
+OnEndOfDxe (\r
+  IN EFI_EVENT Event,\r
+  IN VOID      *Context\r
+  )\r
+{\r
+  EFI_STATUS Status;\r
+\r
   //\r
-  // Save the boot script too. Note that this requires/includes emitting the\r
-  // DxeSmmReadyToLock event, which in turn locks down SMM.\r
+  // Our S3Ready() function always succeeds.\r
   //\r
-  SaveS3BootScript ();\r
-  return EFI_SUCCESS;\r
+  Status = S3Ready ();\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Close the event, deregistering the callback and freeing resources.\r
+  //\r
+  Status = gBS->CloseEvent (Event);\r
+  ASSERT_EFI_ERROR (Status);\r
 }\r
 \r
+\r
 /**\r
   The Driver Entry Point.\r
   \r
-  The function is the driver Entry point which will produce AcpiS3SaveProtocol.\r
-  \r
+  The function is the driver Entry point that will register the End-of-Dxe\r
+  callback.\r
+\r
   @param ImageHandle   A handle for the image that is initializing this driver\r
   @param SystemTable   A pointer to the EFI system table\r
 \r
@@ -578,27 +526,32 @@ S3Ready (
 **/\r
 EFI_STATUS\r
 EFIAPI\r
-InstallAcpiS3Save (\r
+InstallEndOfDxeCallback (\r
   IN EFI_HANDLE           ImageHandle,\r
   IN EFI_SYSTEM_TABLE     *SystemTable\r
   )\r
 {\r
   EFI_STATUS        Status;\r
+  EFI_EVENT         EndOfDxeEvent;\r
 \r
-  if (!FeaturePcdGet(PcdPlatformCsmSupport)) {\r
-    //\r
-    // More memory for no CSM tip, because GDT need relocation\r
-    //\r
-    mLegacyRegionSize = 0x250;\r
-  } else {\r
-    mLegacyRegionSize = 0x100;\r
+  if (!QemuFwCfgS3Enabled()) {\r
+    return EFI_LOAD_ERROR;\r
   }\r
 \r
-  Status = gBS->InstallProtocolInterface (\r
+  Status = gBS->InstallMultipleProtocolInterfaces (\r
                   &ImageHandle,\r
-                  &gEfiAcpiS3SaveProtocolGuid,\r
-                  EFI_NATIVE_INTERFACE,\r
-                  &mS3Save\r
+                  &gEfiLockBoxProtocolGuid, NULL,\r
+                  NULL\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  Status = gBS->CreateEventEx (\r
+                  EVT_NOTIFY_SIGNAL,\r
+                  TPL_CALLBACK,\r
+                  OnEndOfDxe,\r
+                  NULL, /* NotifyContext */\r
+                  &gEfiEndOfDxeEventGroupGuid,\r
+                  &EndOfDxeEvent\r
                   );\r
   ASSERT_EFI_ERROR (Status);\r
   return Status;\r