/** @file\r
Save the S3 data to S3 boot script. \r
\r
- Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>\r
+ Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>\r
\r
This program and the accompanying materials\r
are licensed and made available under the terms and conditions\r
\r
Data structure usage:\r
\r
- +------------------------------+<-- PcdS3BootScriptTablePrivateDataPtr\r
+ +------------------------------+<------- PcdS3BootScriptTablePrivateDataPtr\r
+ | SCRIPT_TABLE_PRIVATE_DATA | (mS3BootScriptTablePtr, Before SmmReadyToLock)\r
+ | TableBase |--- PcdS3BootScriptTablePrivateSmmDataPtr\r
+ | TableLength |--|-- (mS3BootScriptTablePtr = mS3BootScriptTableSmmPtr, After SmmReadyToLock InSmm)\r
+ | TableMemoryPageNumber |--|-|----\r
+ | AtRuntime | | | |\r
+ | InSmm | | | |\r
+ | BootTimeScriptLength |--|-|---|---\r
+ | SmmLocked | | | | |\r
+ | BackFromS3 | | | | |\r
+ +------------------------------+ | | | |\r
+ | | | |\r
+ +------------------------------+<-- | | |\r
+ | EFI_BOOT_SCRIPT_TABLE_HEADER | | | |\r
+ | TableLength |----|-- | |\r
+ +------------------------------+ | | | |\r
+ | ...... | | | | |\r
+ +------------------------------+<---- | | |\r
+ | EFI_BOOT_SCRIPT_TERMINATE | | | |\r
+ +------------------------------+<------ | |\r
+ | |\r
+ | |\r
+ mBootScriptDataBootTimeGuid LockBox: | |\r
+ Used to restore data after back from S3| |\r
+ to handle potential INSERT boot script | |\r
+ at runtime. | |\r
+ +------------------------------+ | |\r
+ | Boot Time Boot Script | | |\r
+ | Before SmmReadyToLock | | |\r
+ | | | |\r
+ | | | |\r
+ +------------------------------+ | |\r
+ | Boot Time Boot Script | | |\r
+ | After SmmReadyToLock InSmm | | |\r
+ | | | |\r
+ +------------------------------+<-------|--|\r
+ | |\r
+ | |\r
+ mBootScriptDataGuid LockBox: (IN_PLACE) | |\r
+ Used to restore data at S3 resume. | |\r
+ +------------------------------+ | |\r
+ | Boot Time Boot Script | | |\r
+ | Before SmmReadyToLock | | |\r
+ | | | |\r
+ | | | |\r
+ +------------------------------+ | |\r
+ | Boot Time Boot Script | | |\r
+ | After SmmReadyToLock InSmm | | |\r
+ | | | |\r
+ +------------------------------+<-------|---\r
+ | Runtime Boot Script | |\r
+ | After SmmReadyToLock InSmm | |\r
+ +------------------------------+ |\r
+ | ...... | |\r
+ +------------------------------+<--------\r
+\r
+\r
+ mBootScriptTableBaseGuid LockBox: (IN_PLACE)\r
+ +------------------------------+\r
+ | mS3BootScriptTablePtr-> |\r
+ | TableBase |\r
+ +------------------------------+\r
+\r
+\r
+ mBootScriptSmmPrivateDataGuid LockBox: (IN_PLACE)\r
+ SMM private data with BackFromS3 = TRUE\r
+ at runtime. S3 will help restore it to\r
+ tell the Library the system is back from S3.\r
+ +------------------------------+\r
| SCRIPT_TABLE_PRIVATE_DATA |\r
- | TableBase |---\r
- | TableLength |--|--\r
- | AtRuntime | | |\r
- | InSmm | | |\r
- +------------------------------+ | |\r
- | |\r
- +------------------------------+<-- |\r
- | EFI_BOOT_SCRIPT_TABLE_HEADER | |\r
- | TableLength |----|--\r
- +------------------------------+ | |\r
- | ...... | | |\r
- +------------------------------+<---- |\r
- | EFI_BOOT_SCRIPT_TERMINATE | |\r
- +------------------------------+<------\r
+ | TableBase |\r
+ | TableLength |\r
+ | TableMemoryPageNumber |\r
+ | AtRuntime |\r
+ | InSmm |\r
+ | BootTimeScriptLength |\r
+ | SmmLocked |\r
+ | BackFromS3 = TRUE |\r
+ +------------------------------+\r
\r
**/\r
\r
SCRIPT_TABLE_PRIVATE_DATA *mS3BootScriptTablePtr;\r
-EFI_EVENT mEnterRuntimeEvent;\r
+\r
//\r
-// Allocate SMM copy because we can not use mS3BootScriptTablePtr when we AtRuntime in InSmm.\r
+// Allocate SMM copy because we can not use mS3BootScriptTablePtr after SmmReadyToLock in InSmm.\r
//\r
SCRIPT_TABLE_PRIVATE_DATA *mS3BootScriptTableSmmPtr;\r
-UINTN mLockBoxLength;\r
\r
EFI_GUID mBootScriptDataGuid = {\r
0xaea6b965, 0xdcf5, 0x4311, { 0xb4, 0xb8, 0xf, 0x12, 0x46, 0x44, 0x94, 0xd2 }\r
};\r
\r
-EFI_GUID mBootScriptDataOrgGuid = {\r
+EFI_GUID mBootScriptDataBootTimeGuid = {\r
0xb5af1d7a, 0xb8cf, 0x4eb3, { 0x89, 0x25, 0xa8, 0x20, 0xe1, 0x6b, 0x68, 0x7d }\r
};\r
\r
-EFI_GUID mBootScriptHeaderDataGuid = {\r
+EFI_GUID mBootScriptTableBaseGuid = {\r
0x1810ab4a, 0x2314, 0x4df6, { 0x81, 0xeb, 0x67, 0xc6, 0xec, 0x5, 0x85, 0x91 }\r
};\r
\r
+EFI_GUID mBootScriptSmmPrivateDataGuid = {\r
+ 0x627ee2da, 0x3bf9, 0x439b, { 0x92, 0x9f, 0x2e, 0xe, 0x6e, 0x9d, 0xba, 0x62 }\r
+};\r
+\r
/**\r
This is an internal function to add a terminate node the entry, recalculate the table \r
length and fill into the table. \r
return S3TableBase;\r
//\r
// NOTE: Here we did NOT adjust the mS3BootScriptTablePtr->TableLength to \r
- // mS3BootScriptTablePtr->TableLength + sizeof (EFI_BOOT_SCRIPT_TERMINATE). Because \r
- // maybe in runtime, we still need add entries into the table, and the runtime entry should be\r
- // added start before this TERMINATE node.\r
+ // mS3BootScriptTablePtr->TableLength + sizeof (EFI_BOOT_SCRIPT_TERMINATE).\r
+ // Because maybe after SmmReadyToLock, we still need add entries into the table,\r
+ // and the entry should be added start before this TERMINATE node.\r
//\r
} \r
\r
/**\r
This function save boot script data to LockBox.\r
- 1. BootSriptPrivate data, BootScript data - Image and DispatchContext are handled by platform.\r
- 2. BootScriptExecutor, BootScriptExecutor context\r
- - ACPI variable - (PI version) sould be handled by SMM driver. S3 Page table is handled here.\r
- - ACPI variable - framework version is already handled by Framework CPU driver.\r
+\r
**/\r
VOID\r
SaveBootScriptDataToLockBox (\r
EFI_STATUS Status;\r
\r
//\r
- // mS3BootScriptTablePtr->TableLength does not include EFI_BOOT_SCRIPT_TERMINATE, because we need add entry at runtime.\r
- // Save all info here, just in case that no one will add boot script entry in SMM.\r
+ // Save whole memory copy into LockBox.\r
+ // It will be used to restore data at S3 resume.\r
//\r
Status = SaveLockBox (\r
&mBootScriptDataGuid,\r
(VOID *)mS3BootScriptTablePtr->TableBase,\r
- mS3BootScriptTablePtr->TableLength + sizeof(EFI_BOOT_SCRIPT_TERMINATE)\r
+ EFI_PAGES_TO_SIZE (mS3BootScriptTablePtr->TableMemoryPageNumber)\r
);\r
ASSERT_EFI_ERROR (Status);\r
\r
Status = SetLockBoxAttributes (&mBootScriptDataGuid, LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE);\r
ASSERT_EFI_ERROR (Status);\r
\r
- //\r
- // We need duplicate the original copy, because it may have INSERT boot script at runtime in SMM.\r
- // If so, we should use original copy to restore data after OS rewrites the ACPINvs region.\r
- // Or the data inserted may cause some original boot script data lost.\r
- //\r
- Status = SaveLockBox (\r
- &mBootScriptDataOrgGuid,\r
- (VOID *)mS3BootScriptTablePtr->TableBase,\r
- mS3BootScriptTablePtr->TableLength + sizeof(EFI_BOOT_SCRIPT_TERMINATE)\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
-\r
//\r
// Just need save TableBase.\r
// Do not update other field because they will NOT be used in S3.\r
//\r
Status = SaveLockBox (\r
- &mBootScriptHeaderDataGuid,\r
+ &mBootScriptTableBaseGuid,\r
(VOID *)&mS3BootScriptTablePtr->TableBase,\r
sizeof(mS3BootScriptTablePtr->TableBase)\r
);\r
ASSERT_EFI_ERROR (Status);\r
\r
- Status = SetLockBoxAttributes (&mBootScriptHeaderDataGuid, LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE);\r
+ Status = SetLockBoxAttributes (&mBootScriptTableBaseGuid, LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE);\r
ASSERT_EFI_ERROR (Status);\r
}\r
\r
/**\r
This is the Event call back function to notify the Library the system is entering\r
- run time phase.\r
+ SmmLocked phase.\r
\r
@param Event Pointer to this event\r
- @param Context Event hanlder private data \r
+ @param Context Event handler private data \r
**/\r
VOID\r
EFIAPI\r
}\r
\r
//\r
- // Here we should tell the library that we are enter into runtime phase. and \r
- // the memory page number occupied by the table should not grow anymore.\r
+ // Here we should tell the library that we are entering SmmLocked phase.\r
+ // and the memory page number occupied by the table should not grow anymore.\r
//\r
- if (!mS3BootScriptTablePtr->AtRuntime) {\r
+ if (!mS3BootScriptTablePtr->SmmLocked) {\r
//\r
- // In boot time, we need not write the terminate node when adding a node to boot scipt table\r
- // or else, that will impact the performance. However, in runtime, we should append terminate\r
- // node on every add to boot script table\r
+ // Before SmmReadyToLock, we need not write the terminate node when adding a node to boot scipt table\r
+ // or else, that will impact the performance. However, after SmmReadyToLock, we should append terminate\r
+ // node on every add to boot script table.\r
//\r
S3BootScriptInternalCloseTable ();\r
- mS3BootScriptTablePtr->AtRuntime = TRUE;\r
+ mS3BootScriptTablePtr->SmmLocked = TRUE;\r
\r
//\r
// Save BootScript data to lockbox\r
//\r
SaveBootScriptDataToLockBox ();\r
}\r
-} \r
+}\r
+\r
/**\r
- This is the Event call back function is triggered in SMM to notify the Library the system is entering\r
- run time phase and set InSmm flag.\r
- \r
+ This is the Event call back function is triggered in SMM to notify the Library\r
+ the system is entering SmmLocked phase and set InSmm flag.\r
+\r
@param Protocol Points to the protocol's unique identifier\r
@param Interface Points to the interface instance\r
@param Handle The handle on which the interface was installed\r
}\r
\r
//\r
- // Last chance to call-out, just make sure AtRuntime is set\r
+ // Last chance to call-out, just make sure SmmLocked is set.\r
//\r
S3BootScriptEventCallBack (NULL, NULL);\r
\r
//\r
if (mS3BootScriptTableSmmPtr->TableBase == NULL) {\r
CopyMem (mS3BootScriptTableSmmPtr, mS3BootScriptTablePtr, sizeof(*mS3BootScriptTablePtr));\r
+\r
+ //\r
+ // Set InSmm, we allow boot script update when InSmm, but not allow boot script outside SMM.\r
+ // InSmm will only be checked if SmmLocked is TRUE.\r
+ //\r
+ mS3BootScriptTableSmmPtr->InSmm = TRUE;\r
}\r
//\r
- // We should not use ACPINvs copy, because it is not safe.\r
+ // We should not use ACPI Reserved copy, because it is not safe.\r
//\r
mS3BootScriptTablePtr = mS3BootScriptTableSmmPtr;\r
\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ This function is to save boot time boot script data to LockBox.\r
+\r
+ Because there may be INSERT boot script at runtime in SMM.\r
+ The boot time copy will be used to restore data after back from S3.\r
+ Otherwise the data inserted may cause some boot time boot script data lost\r
+ if only BootScriptData used.\r
+\r
+**/\r
+VOID\r
+SaveBootTimeDataToLockBox (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
//\r
- // Set InSmm, we allow boot script update when InSmm, but not allow boot script outside SMM.\r
- // InSmm will only be checked if AtRuntime is TRUE.\r
+ // ACPI Reserved copy is not safe, restore from BootScriptData LockBox first,\r
+ // and then save the data to BootScriptDataBootTime LockBox.\r
//\r
- mS3BootScriptTablePtr->InSmm = TRUE;\r
+ Status = RestoreLockBox (\r
+ &mBootScriptDataGuid,\r
+ NULL,\r
+ NULL\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
\r
//\r
- // Record LockBoxLength\r
+ // Save BootScriptDataBootTime\r
+ // It will be used to restore data after back from S3.\r
//\r
- mLockBoxLength = mS3BootScriptTableSmmPtr->TableLength + sizeof(EFI_BOOT_SCRIPT_TERMINATE);\r
+ Status = SaveLockBox (\r
+ &mBootScriptDataBootTimeGuid,\r
+ (VOID *) mS3BootScriptTablePtr->TableBase,\r
+ mS3BootScriptTablePtr->BootTimeScriptLength\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+}\r
+\r
+/**\r
+ This function save boot script SMM private data to LockBox with BackFromS3 = TRUE at runtime.\r
+ S3 resume will help restore it to tell the Library the system is back from S3.\r
+\r
+**/\r
+VOID\r
+SaveSmmPriviateDataToLockBoxAtRuntime (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Save boot script SMM private data with BackFromS3 = TRUE.\r
+ //\r
+ mS3BootScriptTablePtr->BackFromS3 = TRUE;\r
+ Status = SaveLockBox (\r
+ &mBootScriptSmmPrivateDataGuid,\r
+ (VOID *) mS3BootScriptTablePtr,\r
+ sizeof (SCRIPT_TABLE_PRIVATE_DATA)\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ Status = SetLockBoxAttributes (&mBootScriptSmmPrivateDataGuid, LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Set BackFromS3 flag back to FALSE to indicate that now is not back from S3.\r
+ //\r
+ mS3BootScriptTablePtr->BackFromS3 = FALSE;\r
+}\r
+\r
+/**\r
+ This is the Event call back function is triggered in SMM to notify the Library\r
+ the system is entering runtime phase.\r
+\r
+ @param[in] Protocol Points to the protocol's unique identifier\r
+ @param[in] Interface Points to the interface instance\r
+ @param[in] Handle The handle on which the interface was installed\r
+\r
+ @retval EFI_SUCCESS SmmAtRuntimeCallBack runs successfully\r
+ **/\r
+EFI_STATUS\r
+EFIAPI\r
+S3BootScriptSmmAtRuntimeCallBack (\r
+ IN CONST EFI_GUID *Protocol,\r
+ IN VOID *Interface,\r
+ IN EFI_HANDLE Handle\r
+ )\r
+{\r
+ if (!mS3BootScriptTablePtr->AtRuntime) {\r
+ mS3BootScriptTablePtr->BootTimeScriptLength = (UINT32) (mS3BootScriptTablePtr->TableLength + sizeof (EFI_BOOT_SCRIPT_TERMINATE));\r
+ SaveBootTimeDataToLockBox ();\r
+\r
+ mS3BootScriptTablePtr->AtRuntime = TRUE;\r
+ SaveSmmPriviateDataToLockBoxAtRuntime ();\r
+ }\r
\r
return EFI_SUCCESS;\r
}\r
BOOLEAN InSmm;\r
EFI_SMM_SYSTEM_TABLE2 *Smst;\r
EFI_PHYSICAL_ADDRESS Buffer;\r
+ EFI_EVENT Event;\r
\r
S3TablePtr = (SCRIPT_TABLE_PRIVATE_DATA*)(UINTN)PcdGet64(PcdS3BootScriptTablePrivateDataPtr);\r
//\r
Buffer = SIZE_4GB - 1;\r
Status = gBS->AllocatePages (\r
AllocateMaxAddress,\r
- EfiACPIMemoryNVS,\r
+ EfiReservedMemoryType,\r
EFI_SIZE_TO_PAGES(sizeof(SCRIPT_TABLE_PRIVATE_DATA)),\r
&Buffer\r
);\r
PcdSet64 (PcdS3BootScriptTablePrivateDataPtr, (UINT64) (UINTN)S3TablePtr); \r
ZeroMem (S3TablePtr, sizeof(SCRIPT_TABLE_PRIVATE_DATA)); \r
//\r
- // create event to notify the library system enter the runtime phase\r
+ // Create event to notify the library system enter the SmmLocked phase.\r
//\r
- mEnterRuntimeEvent = EfiCreateProtocolNotifyEvent (\r
- &gEfiDxeSmmReadyToLockProtocolGuid,\r
- TPL_CALLBACK,\r
- S3BootScriptEventCallBack,\r
- NULL,\r
- &Registration\r
- );\r
- ASSERT (mEnterRuntimeEvent != NULL);\r
- } \r
+ Event = EfiCreateProtocolNotifyEvent (\r
+ &gEfiDxeSmmReadyToLockProtocolGuid,\r
+ TPL_CALLBACK,\r
+ S3BootScriptEventCallBack,\r
+ NULL,\r
+ &Registration\r
+ );\r
+ ASSERT (Event != NULL);\r
+ }\r
mS3BootScriptTablePtr = S3TablePtr;\r
\r
//\r
\r
PcdSet64 (PcdS3BootScriptTablePrivateSmmDataPtr, (UINT64) (UINTN)S3TableSmmPtr);\r
ZeroMem (S3TableSmmPtr, sizeof(SCRIPT_TABLE_PRIVATE_DATA));\r
+\r
+ //\r
+ // Register SmmExitBootServices and SmmLegacyBoot notification.\r
+ //\r
+ Registration = NULL;\r
+ Status = Smst->SmmRegisterProtocolNotify (\r
+ &gEdkiiSmmExitBootServicesProtocolGuid,\r
+ S3BootScriptSmmAtRuntimeCallBack,\r
+ &Registration\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ Registration = NULL;\r
+ Status = Smst->SmmRegisterProtocolNotify (\r
+ &gEdkiiSmmLegacyBootProtocolGuid,\r
+ S3BootScriptSmmAtRuntimeCallBack,\r
+ &Registration\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
}\r
mS3BootScriptTableSmmPtr = S3TableSmmPtr;\r
\r
//\r
- // Then register event after lock\r
+ // Register SmmReadyToLock notification.\r
//\r
Registration = NULL;\r
Status = Smst->SmmRegisterProtocolNotify (\r
\r
S3TableBase = (EFI_PHYSICAL_ADDRESS)(UINTN)(mS3BootScriptTablePtr->TableBase);\r
if (S3TableBase == 0) {\r
+ //\r
// The table is not exist. This is the first to add entry. \r
- // Allocate ACPI script table space under 4G memory. We need it to save\r
- // some settings done by CSM, which runs after normal script table closed\r
+ // Allocate ACPI script table space under 4G memory.\r
//\r
S3TableBase = 0xffffffff;\r
Status = gBS->AllocatePages (\r
AllocateMaxAddress,\r
- EfiACPIMemoryNVS,\r
+ EfiReservedMemoryType,\r
2 + PcdGet16(PcdS3BootScriptRuntimeTableReservePageNumber),\r
(EFI_PHYSICAL_ADDRESS*)&S3TableBase\r
);\r
ScriptTableInfo = (EFI_BOOT_SCRIPT_TABLE_HEADER*)(UINTN)S3TableBase;\r
ScriptTableInfo->OpCode = S3_BOOT_SCRIPT_LIB_TABLE_OPCODE;\r
ScriptTableInfo->Length = (UINT8) sizeof (EFI_BOOT_SCRIPT_TABLE_HEADER);\r
+ ScriptTableInfo->Version = BOOT_SCRIPT_TABLE_VERSION;\r
ScriptTableInfo->TableLength = 0; // will be calculate at CloseTable\r
mS3BootScriptTablePtr->TableLength = sizeof (EFI_BOOT_SCRIPT_TABLE_HEADER);\r
mS3BootScriptTablePtr->TableBase = (UINT8*)(UINTN)S3TableBase;\r
}\r
\r
// Here we do not count the reserved memory for runtime script table.\r
- PageNumber = (UINT16)(mS3BootScriptTablePtr->TableMemoryPageNumber - PcdGet16(PcdS3BootScriptRuntimeTableReservePageNumber)); \r
+ PageNumber = (UINT16) (mS3BootScriptTablePtr->TableMemoryPageNumber - PcdGet16(PcdS3BootScriptRuntimeTableReservePageNumber));\r
TableLength = mS3BootScriptTablePtr->TableLength;\r
- if ((UINT32)(PageNumber * EFI_PAGE_SIZE) < (TableLength + EntryLength + sizeof (EFI_BOOT_SCRIPT_TERMINATE))) {\r
+ if ((UINTN) EFI_PAGES_TO_SIZE ((UINTN) PageNumber) < (UINTN) (TableLength + EntryLength + sizeof (EFI_BOOT_SCRIPT_TERMINATE))) {\r
// \r
// The buffer is too small to hold the table, Reallocate the buffer\r
//\r
NewS3TableBase = 0xffffffff;\r
Status = gBS->AllocatePages (\r
AllocateMaxAddress,\r
- EfiACPIMemoryNVS,\r
+ EfiReservedMemoryType,\r
2 + PageNumber + PcdGet16(PcdS3BootScriptRuntimeTableReservePageNumber),\r
(EFI_PHYSICAL_ADDRESS*)&NewS3TableBase\r
);\r
return NewEntryPtr; \r
}\r
/**\r
- To get the start address from which a new runtime s3 boot script entry will write into.\r
+ To get the start address from which a new runtime(after SmmReadyToLock) s3 boot script entry will write into.\r
In this case, it should be ensured that there is enough buffer to hold the entry.\r
\r
@param EntryLength the new entry length.\r
\r
- @retval the address from which the a new s3 runtime script entry will write into\r
+ @retval the address from which the a new s3 runtime(after SmmReadyToLock) script entry will write into\r
**/\r
UINT8*\r
S3BootScriptGetRuntimeEntryAddAddress (\r
//\r
// Check if the memory range reserved for S3 Boot Script table is large enough to hold the node. \r
//\r
- if (mS3BootScriptTablePtr->TableLength + EntryLength + sizeof (EFI_BOOT_SCRIPT_TERMINATE) <= EFI_PAGES_TO_SIZE((UINT32)(mS3BootScriptTablePtr->TableMemoryPageNumber))) {\r
+ if ((UINTN) (mS3BootScriptTablePtr->TableLength + EntryLength + sizeof (EFI_BOOT_SCRIPT_TERMINATE)) <= (UINTN) EFI_PAGES_TO_SIZE ((UINTN) (mS3BootScriptTablePtr->TableMemoryPageNumber))) {\r
NewEntryPtr = mS3BootScriptTablePtr->TableBase + mS3BootScriptTablePtr->TableLength; \r
mS3BootScriptTablePtr->TableLength = mS3BootScriptTablePtr->TableLength + EntryLength;\r
//\r
}\r
return (UINT8*)NewEntryPtr; \r
}\r
+\r
+/**\r
+ This function is to restore boot time boot script data from LockBox.\r
+\r
+**/\r
+VOID\r
+RestoreBootTimeDataFromLockBox (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN LockBoxLength;\r
+\r
+ //\r
+ // Restore boot time boot script data from LockBox.\r
+ //\r
+ LockBoxLength = mS3BootScriptTablePtr->BootTimeScriptLength;\r
+ Status = RestoreLockBox (\r
+ &mBootScriptDataBootTimeGuid,\r
+ (VOID *) mS3BootScriptTablePtr->TableBase,\r
+ &LockBoxLength\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Update the data to BootScriptData LockBox.\r
+ //\r
+ Status = UpdateLockBox (\r
+ &mBootScriptDataGuid,\r
+ 0,\r
+ (VOID *) mS3BootScriptTablePtr->TableBase,\r
+ LockBoxLength\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Update TableLength.\r
+ //\r
+ mS3BootScriptTablePtr->TableLength = (UINT32) (mS3BootScriptTablePtr->BootTimeScriptLength - sizeof (EFI_BOOT_SCRIPT_TERMINATE));\r
+}\r
+\r
/**\r
To get the start address from which a new s3 boot script entry will write into.\r
\r
@param EntryLength the new entry length.\r
\r
- @retval the address from which the a new s3 runtime script entry will write into \r
+ @retval the address from which the a new s3 boot script entry will write into \r
**/ \r
UINT8* \r
S3BootScriptGetEntryAddAddress (\r
)\r
{\r
UINT8* NewEntryPtr;\r
- EFI_BOOT_SCRIPT_TABLE_HEADER TableHeader;\r
- EFI_STATUS Status;\r
- UINTN OrgLockBoxLength;\r
\r
- if (mS3BootScriptTablePtr->AtRuntime) {\r
+ if (mS3BootScriptTablePtr->SmmLocked) {\r
//\r
- // We need check InSmm when AtRuntime, because after SmmReadyToLock, only SMM driver is allowed to write boot script.\r
+ // We need check InSmm, because after SmmReadyToLock, only SMM driver is allowed to write boot script.\r
//\r
if (!mS3BootScriptTablePtr->InSmm) {\r
//\r
- // Add DEBUG ERROR, so that we can find it at boot time.\r
- // Do not use ASSERT, because we may have test invoke this interface.\r
+ // Add DEBUG ERROR, so that we can find it after SmmReadyToLock.\r
+ // Do not use ASSERT, because we may have test to invoke this interface.\r
//\r
- DEBUG ((EFI_D_ERROR, "FATAL ERROR: Set boot script after ReadyToLock!!!\n"));\r
+ DEBUG ((EFI_D_ERROR, "FATAL ERROR: Set boot script outside SMM after SmmReadyToLock!!!\n"));\r
return NULL;\r
}\r
\r
- //\r
- // NOTE: OS will restore ACPINvs data. After S3, the table length in mS3BootScriptTableSmmPtr (SMM) is different with\r
- // table length in BootScriptTable header (ACPINvs).\r
- // So here we need sync them. We choose ACPINvs table length, because we want to override the boot script saved\r
- // in SMM every time.\r
- //\r
- ASSERT (mS3BootScriptTablePtr == mS3BootScriptTableSmmPtr);\r
- CopyMem ((VOID*)&TableHeader, (VOID*)mS3BootScriptTablePtr->TableBase, sizeof(EFI_BOOT_SCRIPT_TABLE_HEADER));\r
- if (mS3BootScriptTablePtr->TableLength + sizeof(EFI_BOOT_SCRIPT_TERMINATE) != TableHeader.TableLength) {\r
+ if (mS3BootScriptTablePtr->BackFromS3) {\r
//\r
- // Restore it to use original value\r
+ // Back from S3, restore boot time boot script data from LockBox\r
+ // and set BackFromS3 flag back to FALSE.\r
//\r
- OrgLockBoxLength = mLockBoxLength;\r
- Status = RestoreLockBox (\r
- &mBootScriptDataOrgGuid,\r
- (VOID *)mS3BootScriptTablePtr->TableBase,\r
- &OrgLockBoxLength\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
- ASSERT (OrgLockBoxLength == mLockBoxLength);\r
-\r
- //\r
- // Update the current BootScriptData into LockBox as well\r
- //\r
- Status = UpdateLockBox (\r
- &mBootScriptDataGuid,\r
- 0,\r
- (VOID *)mS3BootScriptTablePtr->TableBase,\r
- OrgLockBoxLength\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- //\r
- // NOTE: We should NOT use TableHeader.TableLength, because it is already updated to be whole length.\r
- //\r
- mS3BootScriptTablePtr->TableLength = (UINT32)(mLockBoxLength - sizeof(EFI_BOOT_SCRIPT_TERMINATE));\r
+ RestoreBootTimeDataFromLockBox ();\r
+ mS3BootScriptTablePtr->BackFromS3 = FALSE;\r
}\r
\r
NewEntryPtr = S3BootScriptGetRuntimeEntryAddAddress (EntryLength);\r
-\r
- if (EntryLength != 0) {\r
- //\r
- // Now the length field is updated, need sync to lockbox.\r
- // So in S3 resume, the data can be restored correctly.\r
- //\r
- CopyMem ((VOID*)&TableHeader, (VOID*)mS3BootScriptTablePtr->TableBase, sizeof(EFI_BOOT_SCRIPT_TABLE_HEADER));\r
- Status = UpdateLockBox (\r
- &mBootScriptDataGuid,\r
- OFFSET_OF(EFI_BOOT_SCRIPT_TABLE_HEADER, TableLength),\r
- &TableHeader.TableLength,\r
- sizeof(TableHeader.TableLength)\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
- }\r
- } else { \r
+ } else {\r
NewEntryPtr = S3BootScriptGetBootTimeEntryAddAddress (EntryLength);\r
} \r
return NewEntryPtr;\r
)\r
{\r
EFI_STATUS Status;\r
- UINTN ScriptOffset;\r
-\r
- ScriptOffset = (UINTN) (Script - mS3BootScriptTablePtr->TableBase);\r
+ UINT32 ScriptOffset;\r
+ UINT32 TotalScriptLength;\r
\r
- if (!mS3BootScriptTablePtr->AtRuntime || !mS3BootScriptTablePtr->InSmm || ScriptOffset >= mLockBoxLength) {\r
+ if (!mS3BootScriptTablePtr->SmmLocked || !mS3BootScriptTablePtr->InSmm) {\r
//\r
- // If it is not at runtime in SMM or in the range that needs to be synced in LockBox, just return.\r
+ // If it is not after SmmReadyToLock in SMM,\r
+ // just return.\r
//\r
return ;\r
}\r
\r
+ ScriptOffset = (UINT32) (Script - mS3BootScriptTablePtr->TableBase);\r
+\r
+ TotalScriptLength = (UINT32) (mS3BootScriptTablePtr->TableLength + sizeof (EFI_BOOT_SCRIPT_TERMINATE));\r
+\r
//\r
// Update BootScriptData\r
// So in S3 resume, the data can be restored correctly.\r
&mBootScriptDataGuid,\r
ScriptOffset,\r
(VOID *)((UINTN)mS3BootScriptTablePtr->TableBase + ScriptOffset),\r
- mLockBoxLength - ScriptOffset\r
+ TotalScriptLength - ScriptOffset\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Now the length field is updated, need sync to lockbox.\r
+ // So at S3 resume, the data can be restored correctly.\r
+ //\r
+ Status = UpdateLockBox (\r
+ &mBootScriptDataGuid,\r
+ OFFSET_OF (EFI_BOOT_SCRIPT_TABLE_HEADER, TableLength),\r
+ &TotalScriptLength,\r
+ sizeof (TotalScriptLength)\r
);\r
ASSERT_EFI_ERROR (Status);\r
}\r
for Framework Spec compatibility.\r
\r
If anyone does call CloseTable() on a real platform, then the caller is responsible for figuring out \r
- how to get the script to run on an S3 resume because the boot script maintained by the lib will be \r
+ how to get the script to run at S3 resume because the boot script maintained by the lib will be \r
destroyed.\r
\r
@return the base address of the new copy of the boot script table. \r
/**\r
Adds a record for memory reads of the memory location and continues when the exit criteria is\r
satisfied or after a defined duration.\r
- \r
+\r
+ Please aware, below interface is different with PI specification, Vol 5:\r
+ EFI_S3_SAVE_STATE_PROTOCOL.Write() for EFI_BOOT_SCRIPT_MEM_POLL_OPCODE.\r
+ "Duration" below is microseconds, while "Delay" in PI specification means\r
+ the number of 100ns units to poll.\r
+\r
@param Width The width of the memory operations.\r
@param Address The base address of the memory operations.\r
@param BitMask A pointer to the bit mask to be AND-ed with the data read from the register.\r