]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.c
MdeModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / MdeModulePkg / Universal / Variable / RuntimeDxe / VariableSmm.c
index 2184634f354425b8b23fa1db3eec3f366b22d23c..ec463d063ea4e1d5e0eb2bb0db5fdf3d43ea3873 100644 (file)
   VariableServiceSetVariable(), VariableServiceQueryVariableInfo(), ReclaimForOS(),\r
   SmmVariableGetStatistics() should also do validation based on its own knowledge.\r
 \r
-Copyright (c) 2010 - 2016, Intel Corporation. All rights reserved.<BR>\r
-This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution.  The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2018, Linaro, Ltd. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
 #include <Protocol/SmmVariable.h>\r
 #include <Protocol/SmmFirmwareVolumeBlock.h>\r
 #include <Protocol/SmmFaultTolerantWrite.h>\r
-#include <Protocol/SmmEndOfDxe.h>\r
+#include <Protocol/MmEndOfDxe.h>\r
 #include <Protocol/SmmVarCheck.h>\r
 \r
-#include <Library/SmmServicesTableLib.h>\r
-#include <Library/SmmMemLib.h>\r
+#include <Library/MmServicesTableLib.h>\r
 \r
 #include <Guid/SmmVariableCommon.h>\r
 #include "Variable.h"\r
 \r
-extern VARIABLE_INFO_ENTRY                           *gVariableInfo;\r
-EFI_HANDLE                                           mSmmVariableHandle      = NULL;\r
-EFI_HANDLE                                           mVariableHandle         = NULL;\r
 BOOLEAN                                              mAtRuntime              = FALSE;\r
 UINT8                                                *mVariableBufferPayload = NULL;\r
 UINTN                                                mVariableBufferPayloadSize;\r
-extern BOOLEAN                                       mEndOfDxe;\r
-extern VAR_CHECK_REQUEST_SOURCE                      mRequestSource;\r
 \r
 /**\r
   SecureBoot Hook for SetVariable.\r
@@ -218,7 +207,7 @@ GetFtwProtocol (
   //\r
   // Locate Smm Fault Tolerent Write protocol\r
   //\r
-  Status = gSmst->SmmLocateProtocol (\r
+  Status = gMmst->MmLocateProtocol (\r
                     &gEfiSmmFaultTolerantWriteProtocolGuid,\r
                     NULL,\r
                     FtwProtocol\r
@@ -248,7 +237,7 @@ GetFvbByHandle (
   //\r
   // To get the SMM FVB protocol interface on the handle\r
   //\r
-  return gSmst->SmmHandleProtocol (\r
+  return gMmst->MmHandleProtocol (\r
                   FvBlockHandle,\r
                   &gEfiSmmFirmwareVolumeBlockProtocolGuid,\r
                   (VOID **) FvBlock\r
@@ -287,7 +276,7 @@ GetFvbCountAndBuffer (
   BufferSize     = 0;\r
   *NumberHandles = 0;\r
   *Buffer        = NULL;\r
-  Status = gSmst->SmmLocateHandle (\r
+  Status = gMmst->MmLocateHandle (\r
                     ByProtocol,\r
                     &gEfiSmmFirmwareVolumeBlockProtocolGuid,\r
                     NULL,\r
@@ -303,7 +292,7 @@ GetFvbCountAndBuffer (
     return EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
-  Status = gSmst->SmmLocateHandle (\r
+  Status = gMmst->MmLocateHandle (\r
                     ByProtocol,\r
                     &gEfiSmmFirmwareVolumeBlockProtocolGuid,\r
                     NULL,\r
@@ -500,7 +489,7 @@ SmmVariableHandler (
     return EFI_SUCCESS;\r
   }\r
 \r
-  if (!SmmIsBufferOutsideSmmValid ((UINTN)CommBuffer, TempCommBufferSize)) {\r
+  if (!VariableSmmIsBufferOutsideSmmValid ((UINTN)CommBuffer, TempCommBufferSize)) {\r
     DEBUG ((EFI_D_ERROR, "SmmVariableHandler: SMM communication buffer in SMRAM or overflow!\n"));\r
     return EFI_SUCCESS;\r
   }\r
@@ -537,6 +526,12 @@ SmmVariableHandler (
         goto EXIT;\r
       }\r
 \r
+      //\r
+      // The VariableSpeculationBarrier() call here is to ensure the previous\r
+      // range/content checks for the CommBuffer have been completed before the\r
+      // subsequent consumption of the CommBuffer content.\r
+      //\r
+      VariableSpeculationBarrier ();\r
       if (SmmVariableHeader->NameSize < sizeof (CHAR16) || SmmVariableHeader->Name[SmmVariableHeader->NameSize/sizeof (CHAR16) - 1] != L'\0') {\r
         //\r
         // Make sure VariableName is A Null-terminated string.\r
@@ -631,6 +626,12 @@ SmmVariableHandler (
         goto EXIT;\r
       }\r
 \r
+      //\r
+      // The VariableSpeculationBarrier() call here is to ensure the previous\r
+      // range/content checks for the CommBuffer have been completed before the\r
+      // subsequent consumption of the CommBuffer content.\r
+      //\r
+      VariableSpeculationBarrier ();\r
       if (SmmVariableHeader->NameSize < sizeof (CHAR16) || SmmVariableHeader->Name[SmmVariableHeader->NameSize/sizeof (CHAR16) - 1] != L'\0') {\r
         //\r
         // Make sure VariableName is A Null-terminated string.\r
@@ -679,6 +680,7 @@ SmmVariableHandler (
         break;\r
       }\r
       if (!mEndOfDxe) {\r
+        MorLockInitAtEndOfDxe ();\r
         mEndOfDxe = TRUE;\r
         VarCheckLibInitializeAtEndOfDxe (NULL);\r
         //\r
@@ -765,6 +767,12 @@ SmmVariableHandler (
         goto EXIT;\r
       }\r
 \r
+      //\r
+      // The VariableSpeculationBarrier() call here is to ensure the previous\r
+      // range/content checks for the CommBuffer have been completed before the\r
+      // subsequent consumption of the CommBuffer content.\r
+      //\r
+      VariableSpeculationBarrier ();\r
       if (CommVariableProperty->NameSize < sizeof (CHAR16) || CommVariableProperty->Name[CommVariableProperty->NameSize/sizeof (CHAR16) - 1] != L'\0') {\r
         //\r
         // Make sure VariableName is A Null-terminated string.\r
@@ -811,6 +819,7 @@ SmmEndOfDxeCallback (
   )\r
 {\r
   DEBUG ((EFI_D_INFO, "[Variable]SMM_END_OF_DXE is signaled\n"));\r
+  MorLockInitAtEndOfDxe ();\r
   mEndOfDxe = TRUE;\r
   VarCheckLibInitializeAtEndOfDxe (NULL);\r
   //\r
@@ -824,6 +833,28 @@ SmmEndOfDxeCallback (
   return EFI_SUCCESS;\r
 }\r
 \r
+/**\r
+  Initializes variable write service for SMM.\r
+\r
+**/\r
+VOID\r
+VariableWriteServiceInitializeSmm (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS    Status;\r
+\r
+  Status = VariableWriteServiceInitialize ();\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((DEBUG_ERROR, "Variable write service initialization failed. Status = %r\n", Status));\r
+  }\r
+\r
+  //\r
+  // Notify the variable wrapper driver the variable write service is ready\r
+  //\r
+  VariableNotifySmmWriteReady ();\r
+}\r
+\r
 /**\r
   SMM Fault Tolerant Write protocol notification event handler.\r
 \r
@@ -847,6 +878,7 @@ SmmFtwNotificationEvent (
   )\r
 {\r
   EFI_STATUS                              Status;\r
+  EFI_PHYSICAL_ADDRESS                    VariableStoreBase;\r
   EFI_SMM_FIRMWARE_VOLUME_BLOCK_PROTOCOL  *FvbProtocol;\r
   EFI_SMM_FAULT_TOLERANT_WRITE_PROTOCOL   *FtwProtocol;\r
   EFI_PHYSICAL_ADDRESS                    NvStorageVariableBase;\r
@@ -869,13 +901,17 @@ SmmFtwNotificationEvent (
     ASSERT (PcdGet32 (PcdFlashNvStorageVariableSize) <= FtwMaxBlockSize);\r
   }\r
 \r
+  NvStorageVariableBase = NV_STORAGE_VARIABLE_BASE;\r
+  VariableStoreBase = NvStorageVariableBase + mNvFvHeaderCache->HeaderLength;\r
+\r
+  //\r
+  // Let NonVolatileVariableBase point to flash variable store base directly after FTW ready.\r
+  //\r
+  mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase = VariableStoreBase;\r
+\r
   //\r
   // Find the proper FVB protocol for variable.\r
   //\r
-  NvStorageVariableBase = (EFI_PHYSICAL_ADDRESS) PcdGet64 (PcdFlashNvStorageVariableBase64);\r
-  if (NvStorageVariableBase == 0) {\r
-    NvStorageVariableBase = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashNvStorageVariableBase);\r
-  }\r
   Status = GetFvbInfoByAddress (NvStorageVariableBase, NULL, &FvbProtocol);\r
   if (EFI_ERROR (Status)) {\r
     return EFI_NOT_FOUND;\r
@@ -883,21 +919,10 @@ SmmFtwNotificationEvent (
 \r
   mVariableModuleGlobal->FvbInstance = FvbProtocol;\r
 \r
-  Status = VariableWriteServiceInitialize ();\r
-  if (EFI_ERROR (Status)) {\r
-    DEBUG ((DEBUG_ERROR, "Variable write service initialization failed. Status = %r\n", Status));\r
-  }\r
-\r
   //\r
-  // Notify the variable wrapper driver the variable write service is ready\r
+  // Initializes variable write service after FTW was ready.\r
   //\r
-  Status = gBS->InstallProtocolInterface (\r
-                  &mSmmVariableHandle,\r
-                  &gSmmVariableWriteGuid,\r
-                  EFI_NATIVE_INTERFACE,\r
-                  NULL\r
-                  );\r
-  ASSERT_EFI_ERROR (Status);\r
+  VariableWriteServiceInitializeSmm ();\r
 \r
   return EFI_SUCCESS;\r
 }\r
@@ -909,17 +934,13 @@ SmmFtwNotificationEvent (
   for variable read and write services being available. It also registers\r
   a notification function for an EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.\r
 \r
-  @param[in] ImageHandle    The firmware allocated handle for the EFI image.\r
-  @param[in] SystemTable    A pointer to the EFI System Table.\r
-\r
   @retval EFI_SUCCESS       Variable service successfully initialized.\r
 \r
 **/\r
 EFI_STATUS\r
 EFIAPI\r
-VariableServiceInitialize (\r
-  IN EFI_HANDLE                           ImageHandle,\r
-  IN EFI_SYSTEM_TABLE                     *SystemTable\r
+MmVariableServiceInitialize (\r
+  VOID\r
   )\r
 {\r
   EFI_STATUS                              Status;\r
@@ -937,7 +958,7 @@ VariableServiceInitialize (
   // Install the Smm Variable Protocol on a new handle.\r
   //\r
   VariableHandle = NULL;\r
-  Status = gSmst->SmmInstallProtocolInterface (\r
+  Status = gMmst->MmInstallProtocolInterface (\r
                     &VariableHandle,\r
                     &gEfiSmmVariableProtocolGuid,\r
                     EFI_NATIVE_INTERFACE,\r
@@ -945,7 +966,7 @@ VariableServiceInitialize (
                     );\r
   ASSERT_EFI_ERROR (Status);\r
 \r
-  Status = gSmst->SmmInstallProtocolInterface (\r
+  Status = gMmst->MmInstallProtocolInterface (\r
                     &VariableHandle,\r
                     &gEdkiiSmmVarCheckProtocolGuid,\r
                     EFI_NATIVE_INTERFACE,\r
@@ -953,10 +974,10 @@ VariableServiceInitialize (
                     );\r
   ASSERT_EFI_ERROR (Status);\r
 \r
-  mVariableBufferPayloadSize = GetNonVolatileMaxVariableSize () +\r
+  mVariableBufferPayloadSize = GetMaxVariableSize () +\r
                                OFFSET_OF (SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY, Name) - GetVariableHeaderSize ();\r
 \r
-  Status = gSmst->SmmAllocatePool (\r
+  Status = gMmst->MmAllocatePool (\r
                     EfiRuntimeServicesData,\r
                     mVariableBufferPayloadSize,\r
                     (VOID **)&mVariableBufferPayload\r
@@ -967,41 +988,42 @@ VariableServiceInitialize (
   /// Register SMM variable SMI handler\r
   ///\r
   VariableHandle = NULL;\r
-  Status = gSmst->SmiHandlerRegister (SmmVariableHandler, &gEfiSmmVariableProtocolGuid, &VariableHandle);\r
+  Status = gMmst->MmiHandlerRegister (SmmVariableHandler, &gEfiSmmVariableProtocolGuid, &VariableHandle);\r
   ASSERT_EFI_ERROR (Status);\r
 \r
   //\r
   // Notify the variable wrapper driver the variable service is ready\r
   //\r
-  Status = SystemTable->BootServices->InstallProtocolInterface (\r
-                                        &mVariableHandle,\r
-                                        &gEfiSmmVariableProtocolGuid,\r
-                                        EFI_NATIVE_INTERFACE,\r
-                                        &gSmmVariable\r
-                                        );\r
-  ASSERT_EFI_ERROR (Status);\r
+  VariableNotifySmmReady ();\r
 \r
   //\r
   // Register EFI_SMM_END_OF_DXE_PROTOCOL_GUID notify function.\r
   //\r
-  Status = gSmst->SmmRegisterProtocolNotify (\r
-                    &gEfiSmmEndOfDxeProtocolGuid,\r
+  Status = gMmst->MmRegisterProtocolNotify (\r
+                    &gEfiMmEndOfDxeProtocolGuid,\r
                     SmmEndOfDxeCallback,\r
                     &SmmEndOfDxeRegistration\r
                     );\r
   ASSERT_EFI_ERROR (Status);\r
 \r
-  //\r
-  // Register FtwNotificationEvent () notify function.\r
-  //\r
-  Status = gSmst->SmmRegisterProtocolNotify (\r
-                    &gEfiSmmFaultTolerantWriteProtocolGuid,\r
-                    SmmFtwNotificationEvent,\r
-                    &SmmFtwRegistration\r
-                    );\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  SmmFtwNotificationEvent (NULL, NULL, NULL);\r
+  if (!PcdGetBool (PcdEmuVariableNvModeEnable)) {\r
+    //\r
+    // Register FtwNotificationEvent () notify function.\r
+    //\r
+    Status = gMmst->MmRegisterProtocolNotify (\r
+                      &gEfiSmmFaultTolerantWriteProtocolGuid,\r
+                      SmmFtwNotificationEvent,\r
+                      &SmmFtwRegistration\r
+                      );\r
+    ASSERT_EFI_ERROR (Status);\r
+\r
+    SmmFtwNotificationEvent (NULL, NULL, NULL);\r
+  } else {\r
+    //\r
+    // Emulated non-volatile variable mode does not depend on FVB and FTW.\r
+    //\r
+    VariableWriteServiceInitializeSmm ();\r
+  }\r
 \r
   return EFI_SUCCESS;\r
 }\r