]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxSmmLib.c
MdeModulePkg LockBoxLib: Support LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY
[mirror_edk2.git] / MdeModulePkg / Library / SmmLockBoxLib / SmmLockBoxSmmLib.c
index 4960df755534da4fdbb9fc72bfc561e6ffa101b3..32a57b6a76654d853b3f0d99b61b2a180f55702c 100644 (file)
@@ -1,6 +1,6 @@
 /** @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
@@ -20,6 +20,10 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #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
@@ -31,6 +35,11 @@ SMM_LOCK_BOX_CONTEXT mSmmLockBoxContext;
 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
@@ -63,6 +72,128 @@ InternalGetSmmLockBoxContext (
   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
@@ -85,6 +216,36 @@ SmmLockBoxSmmConstructor (
 \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
@@ -158,6 +319,40 @@ SmmLockBoxSmmDestructor (
     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
@@ -354,8 +549,16 @@ SetLockBoxAttributes (
   // 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
@@ -368,6 +571,16 @@ SetLockBoxAttributes (
     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
@@ -496,6 +709,16 @@ RestoreLockBox (
     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