/** @file\r
\r
-Copyright (c) 2010 - 2016, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2010 - 2018, 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
#include <Library/LockBoxLib.h>\r
#include <Library/DebugLib.h>\r
#include <Guid/SmmLockBox.h>\r
+#include <Guid/EndOfS3Resume.h>\r
+#include <Protocol/SmmReadyToLock.h>\r
+#include <Protocol/SmmEndOfDxe.h>\r
+#include <Protocol/SmmSxDispatch2.h>\r
\r
#include "SmmLockBoxLibPrivate.h"\r
\r
LIST_ENTRY mLockBoxQueue = INITIALIZE_LIST_HEAD_VARIABLE (mLockBoxQueue);\r
\r
BOOLEAN mSmmConfigurationTableInstalled = FALSE;\r
+VOID *mSmmLockBoxRegistrationSmmEndOfDxe = NULL;\r
+VOID *mSmmLockBoxRegistrationSmmReadyToLock = NULL;\r
+VOID *mSmmLockBoxRegistrationEndOfS3Resume = NULL;\r
+BOOLEAN mSmmLockBoxSmmReadyToLock = FALSE;\r
+BOOLEAN mSmmLockBoxDuringS3Resume = FALSE;\r
\r
/**\r
This function return SmmLockBox context from SMST.\r
return NULL;\r
}\r
\r
+/**\r
+ Notification for SMM ReadyToLock protocol.\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 Notification runs successfully.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SmmLockBoxSmmReadyToLockNotify (\r
+ IN CONST EFI_GUID *Protocol,\r
+ IN VOID *Interface,\r
+ IN EFI_HANDLE Handle\r
+ )\r
+{\r
+ mSmmLockBoxSmmReadyToLock = TRUE;\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Main entry point for an SMM handler dispatch or communicate-based callback.\r
+\r
+ @param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().\r
+ @param[in] Context Points to an optional handler context which was specified when the\r
+ handler was registered.\r
+ @param[in,out] CommBuffer A pointer to a collection of data in memory that will\r
+ be conveyed from a non-SMM environment into an SMM environment.\r
+ @param[in,out] CommBufferSize The size of the CommBuffer.\r
+\r
+ @retval EFI_SUCCESS The interrupt was handled and quiesced. No other handlers\r
+ should still be called.\r
+ @retval EFI_WARN_INTERRUPT_SOURCE_QUIESCED The interrupt has been quiesced but other handlers should\r
+ still be called.\r
+ @retval EFI_WARN_INTERRUPT_SOURCE_PENDING The interrupt is still pending and other handlers should still\r
+ be called.\r
+ @retval EFI_INTERRUPT_PENDING The interrupt could not be quiesced.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SmmLockBoxS3EntryCallBack (\r
+ IN EFI_HANDLE DispatchHandle,\r
+ IN CONST VOID *Context OPTIONAL,\r
+ IN OUT VOID *CommBuffer OPTIONAL,\r
+ IN OUT UINTN *CommBufferSize OPTIONAL\r
+ )\r
+{\r
+ mSmmLockBoxDuringS3Resume = TRUE;\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Notification for SMM EndOfDxe protocol.\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 Notification runs successfully.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SmmLockBoxSmmEndOfDxeNotify (\r
+ IN CONST EFI_GUID *Protocol,\r
+ IN VOID *Interface,\r
+ IN EFI_HANDLE Handle\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_SMM_SX_DISPATCH2_PROTOCOL *SxDispatch;\r
+ EFI_SMM_SX_REGISTER_CONTEXT EntryRegisterContext;\r
+ EFI_HANDLE S3EntryHandle;\r
+\r
+ //\r
+ // Locate SmmSxDispatch2 protocol.\r
+ //\r
+ Status = gSmst->SmmLocateProtocol (\r
+ &gEfiSmmSxDispatch2ProtocolGuid,\r
+ NULL,\r
+ (VOID **)&SxDispatch\r
+ );\r
+ if (!EFI_ERROR (Status) && (SxDispatch != NULL)) {\r
+ //\r
+ // Register a S3 entry callback function to\r
+ // determine if it will be during S3 resume.\r
+ //\r
+ EntryRegisterContext.Type = SxS3;\r
+ EntryRegisterContext.Phase = SxEntry;\r
+ Status = SxDispatch->Register (\r
+ SxDispatch,\r
+ SmmLockBoxS3EntryCallBack,\r
+ &EntryRegisterContext,\r
+ &S3EntryHandle\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Notification for SMM EndOfS3Resume protocol.\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 Notification runs successfully.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SmmLockBoxEndOfS3ResumeNotify (\r
+ IN CONST EFI_GUID *Protocol,\r
+ IN VOID *Interface,\r
+ IN EFI_HANDLE Handle\r
+ )\r
+{\r
+ mSmmLockBoxDuringS3Resume = FALSE;\r
+ return EFI_SUCCESS;\r
+}\r
+\r
/**\r
Constructor for SmmLockBox library.\r
This is used to set SmmLockBox context, which will be used in PEI phase in S3 boot path later.\r
@param[in] ImageHandle Image handle of this driver.\r
@param[in] SystemTable A Pointer to the EFI System Table.\r
\r
- @retval EFI_SUCEESS \r
+ @retval EFI_SUCEESS\r
@return Others Some error occurs.\r
**/\r
EFI_STATUS\r
\r
DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib SmmLockBoxSmmConstructor - Enter\n"));\r
\r
+ //\r
+ // Register SmmReadyToLock notification.\r
+ //\r
+ Status = gSmst->SmmRegisterProtocolNotify (\r
+ &gEfiSmmReadyToLockProtocolGuid,\r
+ SmmLockBoxSmmReadyToLockNotify,\r
+ &mSmmLockBoxRegistrationSmmReadyToLock\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Register SmmEndOfDxe notification.\r
+ //\r
+ Status = gSmst->SmmRegisterProtocolNotify (\r
+ &gEfiSmmEndOfDxeProtocolGuid,\r
+ SmmLockBoxSmmEndOfDxeNotify,\r
+ &mSmmLockBoxRegistrationSmmEndOfDxe\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Register EndOfS3Resume notification.\r
+ //\r
+ Status = gSmst->SmmRegisterProtocolNotify (\r
+ &gEdkiiEndOfS3ResumeGuid,\r
+ SmmLockBoxEndOfS3ResumeNotify,\r
+ &mSmmLockBoxRegistrationEndOfS3Resume\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
//\r
// Check if gEfiSmmLockBoxCommunicationGuid is installed by someone\r
//\r
DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib uninstall SmmLockBoxCommunication configuration table\n"));\r
}\r
\r
+ if (mSmmLockBoxRegistrationSmmReadyToLock != NULL) {\r
+ //\r
+ // Unregister SmmReadyToLock notification.\r
+ //\r
+ Status = gSmst->SmmRegisterProtocolNotify (\r
+ &gEfiSmmReadyToLockProtocolGuid,\r
+ NULL,\r
+ &mSmmLockBoxRegistrationSmmReadyToLock\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ }\r
+ if (mSmmLockBoxRegistrationSmmEndOfDxe != NULL) {\r
+ //\r
+ // Unregister SmmEndOfDxe notification.\r
+ //\r
+ Status = gSmst->SmmRegisterProtocolNotify (\r
+ &gEfiSmmEndOfDxeProtocolGuid,\r
+ NULL,\r
+ &mSmmLockBoxRegistrationSmmEndOfDxe\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ }\r
+ if (mSmmLockBoxRegistrationEndOfS3Resume != NULL) {\r
+ //\r
+ // Unregister EndOfS3Resume notification.\r
+ //\r
+ Status = gSmst->SmmRegisterProtocolNotify (\r
+ &gEdkiiEndOfS3ResumeGuid,\r
+ NULL,\r
+ &mSmmLockBoxRegistrationEndOfS3Resume\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ }\r
+\r
return EFI_SUCCESS;\r
}\r
\r
// Basic check\r
//\r
if ((Guid == NULL) ||\r
- ((Attributes & ~LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE) != 0)) {\r
+ ((Attributes & ~(LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE | LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY)) != 0)) {\r
+ DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib SetLockBoxAttributes - Exit (%r)\n", EFI_INVALID_PARAMETER));\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (((Attributes & LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE) != 0) &&\r
+ ((Attributes & LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY) != 0)) {\r
DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib SetLockBoxAttributes - Exit (%r)\n", EFI_INVALID_PARAMETER));\r
+ DEBUG ((EFI_D_INFO, " LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE and LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY\n\n"));\r
+ DEBUG ((EFI_D_INFO, " can not be set together\n"));\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
return EFI_NOT_FOUND;\r
}\r
\r
+ if ((((Attributes & LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE) != 0) &&\r
+ ((LockBox->Attributes & LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY) != 0)) ||\r
+ (((LockBox->Attributes & LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE) != 0) &&\r
+ ((Attributes & LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY) != 0))) {\r
+ DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib SetLockBoxAttributes 0x%lx 0x%lx - Exit (%r)\n", LockBox->Attributes, Attributes, EFI_INVALID_PARAMETER));\r
+ DEBUG ((EFI_D_INFO, " LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE and LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY\n\n"));\r
+ DEBUG ((EFI_D_INFO, " can not be set together\n"));\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
//\r
// Update data\r
//\r
\r
@retval RETURN_SUCCESS the information is restored successfully.\r
@retval RETURN_INVALID_PARAMETER the Guid is NULL, or one of Buffer and Length is NULL.\r
- @retval RETURN_WRITE_PROTECTED Buffer and Length are NULL, but the LockBox has no \r
+ @retval RETURN_WRITE_PROTECTED Buffer and Length are NULL, but the LockBox has no\r
LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE attribute.\r
@retval RETURN_BUFFER_TOO_SMALL the Length is too small to hold the confidential information.\r
@retval RETURN_NOT_FOUND the requested GUID not found.\r
return EFI_NOT_FOUND;\r
}\r
\r
+ if (((LockBox->Attributes & LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY) != 0) &&\r
+ mSmmLockBoxSmmReadyToLock &&\r
+ !mSmmLockBoxDuringS3Resume) {\r
+ //\r
+ // With LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY,\r
+ // this LockBox can be restored in S3 resume only.\r
+ //\r
+ return EFI_ACCESS_DENIED;\r
+ }\r
+\r
//\r
// Set RestoreBuffer\r
//\r