/** @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
#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
} 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
}\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
- ASSERT (FALSE);\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
\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
AlreadyEntered = TRUE;\r
\r
- ASSERT (LegacyMemoryAddress == NULL);\r
-\r
AcpiS3Context = AllocateMemoryBelow4G (EfiReservedMemoryType, sizeof(*AcpiS3Context));\r
ASSERT (AcpiS3Context != NULL);\r
AcpiS3ContextBuffer = (EFI_PHYSICAL_ADDRESS)(UINTN)AcpiS3Context;\r
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
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
**/\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 (!QemuFwCfgS3Enabled()) {\r
return EFI_LOAD_ERROR;\r
}\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 (!FeaturePcdGet (PcdSmmSmramRequire)) {\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &ImageHandle,\r
+ &gEfiLockBoxProtocolGuid, NULL,\r
+ NULL\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
}\r
\r
- Status = gBS->InstallMultipleProtocolInterfaces (\r
- &ImageHandle,\r
- &gEfiAcpiS3SaveProtocolGuid, &mS3Save,\r
- &gEfiLockBoxProtocolGuid, NULL,\r
- NULL\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