]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.c
MdeModulePkg: Apply uncrustify changes
[mirror_edk2.git] / MdeModulePkg / Universal / Variable / RuntimeDxe / VariableSmm.c
index fb16af31b1a999863077ebe81dd527e124336124..517cae7b00f8e256adcbc80a5e37e10acab254f7 100644 (file)
   VariableServiceSetVariable(), VariableServiceQueryVariableInfo(), ReclaimForOS(),\r
   SmmVariableGetStatistics() should also do validation based on its own knowledge.\r
 \r
-Copyright (c) 2010 - 2015, 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
+#include <Library/VariablePolicyLib.h>\r
 \r
 #include <Guid/SmmVariableCommon.h>\r
-#include <Guid/ZeroGuid.h>\r
 #include "Variable.h"\r
+#include "VariableParsing.h"\r
+#include "VariableRuntimeCache.h"\r
+\r
+extern VARIABLE_STORE_HEADER  *mNvVariableCache;\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
+BOOLEAN  mAtRuntime              = FALSE;\r
+UINT8    *mVariableBufferPayload = NULL;\r
+UINTN    mVariableBufferPayloadSize;\r
 \r
 /**\r
   SecureBoot Hook for SetVariable.\r
@@ -57,11 +50,11 @@ extern VAR_CHECK_REQUEST_SOURCE                      mRequestSource;
 VOID\r
 EFIAPI\r
 SecureBootHook (\r
-  IN CHAR16                                 *VariableName,\r
-  IN EFI_GUID                               *VendorGuid\r
+  IN CHAR16    *VariableName,\r
+  IN EFI_GUID  *VendorGuid\r
   )\r
 {\r
-  return ;\r
+  return;\r
 }\r
 \r
 /**\r
@@ -85,14 +78,14 @@ SecureBootHook (
 EFI_STATUS\r
 EFIAPI\r
 SmmVariableSetVariable (\r
-  IN CHAR16                  *VariableName,\r
-  IN EFI_GUID                *VendorGuid,\r
-  IN UINT32                  Attributes,\r
-  IN UINTN                   DataSize,\r
-  IN VOID                    *Data\r
+  IN CHAR16    *VariableName,\r
+  IN EFI_GUID  *VendorGuid,\r
+  IN UINT32    Attributes,\r
+  IN UINTN     DataSize,\r
+  IN VOID      *Data\r
   )\r
 {\r
-  EFI_STATUS                 Status;\r
+  EFI_STATUS  Status;\r
 \r
   //\r
   // Disable write protection when the calling SetVariable() through EFI_SMM_VARIABLE_PROTOCOL.\r
@@ -109,16 +102,18 @@ SmmVariableSetVariable (
   return Status;\r
 }\r
 \r
-EFI_SMM_VARIABLE_PROTOCOL      gSmmVariable = {\r
+EFI_SMM_VARIABLE_PROTOCOL  gSmmVariable = {\r
   VariableServiceGetVariable,\r
   VariableServiceGetNextVariableName,\r
   SmmVariableSetVariable,\r
   VariableServiceQueryVariableInfo\r
 };\r
 \r
-EDKII_SMM_VAR_CHECK_PROTOCOL mSmmVarCheck = { VarCheckRegisterSetVariableCheckHandler,\r
-                                              VarCheckVariablePropertySet,\r
-                                              VarCheckVariablePropertyGet };\r
+EDKII_SMM_VAR_CHECK_PROTOCOL  mSmmVarCheck = {\r
+  VarCheckRegisterSetVariableCheckHandler,\r
+  VarCheckVariablePropertySet,\r
+  VarCheckVariablePropertyGet\r
+};\r
 \r
 /**\r
   Return TRUE if ExitBootServices () has been called.\r
@@ -151,8 +146,8 @@ AtRuntime (
 **/\r
 EFI_LOCK *\r
 InitializeLock (\r
-  IN OUT EFI_LOCK                         *Lock,\r
-  IN EFI_TPL                              Priority\r
+  IN OUT EFI_LOCK  *Lock,\r
+  IN EFI_TPL       Priority\r
   )\r
 {\r
   return Lock;\r
@@ -172,13 +167,11 @@ InitializeLock (
 **/\r
 VOID\r
 AcquireLockOnlyAtBootTime (\r
-  IN EFI_LOCK                             *Lock\r
+  IN EFI_LOCK  *Lock\r
   )\r
 {\r
-\r
 }\r
 \r
-\r
 /**\r
   Releases lock only at boot time. Simply returns at runtime.\r
 \r
@@ -193,14 +186,13 @@ AcquireLockOnlyAtBootTime (
 **/\r
 VOID\r
 ReleaseLockOnlyAtBootTime (\r
-  IN EFI_LOCK                             *Lock\r
+  IN EFI_LOCK  *Lock\r
   )\r
 {\r
-\r
 }\r
 \r
 /**\r
-  Retrive the SMM Fault Tolerent Write protocol interface.\r
+  Retrieve the SMM Fault Tolerent Write protocol interface.\r
 \r
   @param[out] FtwProtocol       The interface of SMM Ftw protocol\r
 \r
@@ -211,15 +203,15 @@ ReleaseLockOnlyAtBootTime (
 **/\r
 EFI_STATUS\r
 GetFtwProtocol (\r
-  OUT VOID                                **FtwProtocol\r
+  OUT VOID  **FtwProtocol\r
   )\r
 {\r
-  EFI_STATUS                              Status;\r
+  EFI_STATUS  Status;\r
 \r
   //\r
   // Locate Smm Fault Tolerent Write protocol\r
   //\r
-  Status = gSmst->SmmLocateProtocol (\r
+  Status = gMmst->MmLocateProtocol (\r
                     &gEfiSmmFaultTolerantWriteProtocolGuid,\r
                     NULL,\r
                     FtwProtocol\r
@@ -227,9 +219,8 @@ GetFtwProtocol (
   return Status;\r
 }\r
 \r
-\r
 /**\r
-  Retrive the SMM FVB protocol interface by HANDLE.\r
+  Retrieve the SMM FVB protocol interface by HANDLE.\r
 \r
   @param[in]  FvBlockHandle     The handle of SMM FVB protocol that provides services for\r
                                 reading, writing, and erasing the target block.\r
@@ -249,14 +240,13 @@ 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
+                  (VOID **)FvBlock\r
                   );\r
 }\r
 \r
-\r
 /**\r
   Function returns an array of handles that support the SMM FVB protocol\r
   in a buffer allocated from pool.\r
@@ -274,12 +264,12 @@ GetFvbByHandle (
 **/\r
 EFI_STATUS\r
 GetFvbCountAndBuffer (\r
-  OUT UINTN                               *NumberHandles,\r
-  OUT EFI_HANDLE                          **Buffer\r
+  OUT UINTN       *NumberHandles,\r
+  OUT EFI_HANDLE  **Buffer\r
   )\r
 {\r
-  EFI_STATUS                              Status;\r
-  UINTN                                   BufferSize;\r
+  EFI_STATUS  Status;\r
+  UINTN       BufferSize;\r
 \r
   if ((NumberHandles == NULL) || (Buffer == NULL)) {\r
     return EFI_INVALID_PARAMETER;\r
@@ -288,14 +278,14 @@ GetFvbCountAndBuffer (
   BufferSize     = 0;\r
   *NumberHandles = 0;\r
   *Buffer        = NULL;\r
-  Status = gSmst->SmmLocateHandle (\r
-                    ByProtocol,\r
-                    &gEfiSmmFirmwareVolumeBlockProtocolGuid,\r
-                    NULL,\r
-                    &BufferSize,\r
-                    *Buffer\r
-                    );\r
-  if (EFI_ERROR(Status) && Status != EFI_BUFFER_TOO_SMALL) {\r
+  Status         = gMmst->MmLocateHandle (\r
+                            ByProtocol,\r
+                            &gEfiSmmFirmwareVolumeBlockProtocolGuid,\r
+                            NULL,\r
+                            &BufferSize,\r
+                            *Buffer\r
+                            );\r
+  if (EFI_ERROR (Status) && (Status != EFI_BUFFER_TOO_SMALL)) {\r
     return EFI_NOT_FOUND;\r
   }\r
 \r
@@ -304,7 +294,7 @@ GetFvbCountAndBuffer (
     return EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
-  Status = gSmst->SmmLocateHandle (\r
+  Status = gMmst->MmLocateHandle (\r
                     ByProtocol,\r
                     &gEfiSmmFirmwareVolumeBlockProtocolGuid,\r
                     NULL,\r
@@ -312,8 +302,8 @@ GetFvbCountAndBuffer (
                     *Buffer\r
                     );\r
 \r
-  *NumberHandles = BufferSize / sizeof(EFI_HANDLE);\r
-  if (EFI_ERROR(Status)) {\r
+  *NumberHandles = BufferSize / sizeof (EFI_HANDLE);\r
+  if (EFI_ERROR (Status)) {\r
     *NumberHandles = 0;\r
     FreePool (*Buffer);\r
     *Buffer = NULL;\r
@@ -322,7 +312,6 @@ GetFvbCountAndBuffer (
   return Status;\r
 }\r
 \r
-\r
 /**\r
   Get the variable statistics information from the information buffer pointed by gVariableInfo.\r
 \r
@@ -345,15 +334,16 @@ GetFvbCountAndBuffer (
 **/\r
 EFI_STATUS\r
 SmmVariableGetStatistics (\r
-  IN OUT VARIABLE_INFO_ENTRY                           *InfoEntry,\r
-  IN OUT UINTN                                         *InfoSize\r
+  IN OUT VARIABLE_INFO_ENTRY  *InfoEntry,\r
+  IN OUT UINTN                *InfoSize\r
   )\r
 {\r
-  VARIABLE_INFO_ENTRY                                  *VariableInfo;\r
-  UINTN                                                NameLength;\r
-  UINTN                                                StatisticsInfoSize;\r
-  CHAR16                                               *InfoName;\r
-  EFI_GUID                                             VendorGuid;\r
+  VARIABLE_INFO_ENTRY  *VariableInfo;\r
+  UINTN                NameSize;\r
+  UINTN                StatisticsInfoSize;\r
+  CHAR16               *InfoName;\r
+  UINTN                InfoNameMaxSize;\r
+  EFI_GUID             VendorGuid;\r
 \r
   if (InfoEntry == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
@@ -364,21 +354,30 @@ SmmVariableGetStatistics (
     return EFI_UNSUPPORTED;\r
   }\r
 \r
-  StatisticsInfoSize = sizeof (VARIABLE_INFO_ENTRY) + StrSize (VariableInfo->Name);\r
+  StatisticsInfoSize = sizeof (VARIABLE_INFO_ENTRY);\r
   if (*InfoSize < StatisticsInfoSize) {\r
     *InfoSize = StatisticsInfoSize;\r
     return EFI_BUFFER_TOO_SMALL;\r
   }\r
-  InfoName = (CHAR16 *)(InfoEntry + 1);\r
+\r
+  InfoName        = (CHAR16 *)(InfoEntry + 1);\r
+  InfoNameMaxSize = (*InfoSize - sizeof (VARIABLE_INFO_ENTRY));\r
 \r
   CopyGuid (&VendorGuid, &InfoEntry->VendorGuid);\r
 \r
-  if (CompareGuid (&VendorGuid, &gZeroGuid)) {\r
+  if (IsZeroGuid (&VendorGuid)) {\r
     //\r
     // Return the first variable info\r
     //\r
+    NameSize           = StrSize (VariableInfo->Name);\r
+    StatisticsInfoSize = sizeof (VARIABLE_INFO_ENTRY) + NameSize;\r
+    if (*InfoSize < StatisticsInfoSize) {\r
+      *InfoSize = StatisticsInfoSize;\r
+      return EFI_BUFFER_TOO_SMALL;\r
+    }\r
+\r
     CopyMem (InfoEntry, VariableInfo, sizeof (VARIABLE_INFO_ENTRY));\r
-    CopyMem (InfoName, VariableInfo->Name, StrSize (VariableInfo->Name));\r
+    CopyMem (InfoName, VariableInfo->Name, NameSize);\r
     *InfoSize = StatisticsInfoSize;\r
     return EFI_SUCCESS;\r
   }\r
@@ -388,9 +387,9 @@ SmmVariableGetStatistics (
   //\r
   while (VariableInfo != NULL) {\r
     if (CompareGuid (&VariableInfo->VendorGuid, &VendorGuid)) {\r
-      NameLength = StrSize (VariableInfo->Name);\r
-      if (NameLength == StrSize (InfoName)) {\r
-        if (CompareMem (VariableInfo->Name, InfoName, NameLength) == 0) {\r
+      NameSize = StrSize (VariableInfo->Name);\r
+      if (NameSize <= InfoNameMaxSize) {\r
+        if (CompareMem (VariableInfo->Name, InfoName, NameSize) == 0) {\r
           //\r
           // Find the match one\r
           //\r
@@ -399,8 +398,9 @@ SmmVariableGetStatistics (
         }\r
       }\r
     }\r
+\r
     VariableInfo = VariableInfo->Next;\r
-  };\r
+  }\r
 \r
   if (VariableInfo == NULL) {\r
     *InfoSize = 0;\r
@@ -410,20 +410,20 @@ SmmVariableGetStatistics (
   //\r
   // Output the new variable info\r
   //\r
-  StatisticsInfoSize = sizeof (VARIABLE_INFO_ENTRY) + StrSize (VariableInfo->Name);\r
+  NameSize           = StrSize (VariableInfo->Name);\r
+  StatisticsInfoSize = sizeof (VARIABLE_INFO_ENTRY) + NameSize;\r
   if (*InfoSize < StatisticsInfoSize) {\r
     *InfoSize = StatisticsInfoSize;\r
     return EFI_BUFFER_TOO_SMALL;\r
   }\r
 \r
   CopyMem (InfoEntry, VariableInfo, sizeof (VARIABLE_INFO_ENTRY));\r
-  CopyMem (InfoName, VariableInfo->Name, StrSize (VariableInfo->Name));\r
+  CopyMem (InfoName, VariableInfo->Name, NameSize);\r
   *InfoSize = StatisticsInfoSize;\r
 \r
   return EFI_SUCCESS;\r
 }\r
 \r
-\r
 /**\r
   Communication service SMI Handler entry.\r
 \r
@@ -453,83 +453,97 @@ SmmVariableGetStatistics (
 EFI_STATUS\r
 EFIAPI\r
 SmmVariableHandler (\r
-  IN     EFI_HANDLE                                DispatchHandle,\r
-  IN     CONST VOID                                *RegisterContext,\r
-  IN OUT VOID                                      *CommBuffer,\r
-  IN OUT UINTN                                     *CommBufferSize\r
+  IN     EFI_HANDLE  DispatchHandle,\r
+  IN     CONST VOID  *RegisterContext,\r
+  IN OUT VOID        *CommBuffer,\r
+  IN OUT UINTN       *CommBufferSize\r
   )\r
 {\r
-  EFI_STATUS                                       Status;\r
-  SMM_VARIABLE_COMMUNICATE_HEADER                  *SmmVariableFunctionHeader;\r
-  SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE         *SmmVariableHeader;\r
-  SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME  *GetNextVariableName;\r
-  SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO     *QueryVariableInfo;\r
-  SMM_VARIABLE_COMMUNICATE_GET_PAYLOAD_SIZE        *GetPayloadSize;\r
-  VARIABLE_INFO_ENTRY                              *VariableInfo;\r
-  SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE           *VariableToLock;\r
-  SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY *CommVariableProperty;\r
-  UINTN                                            InfoSize;\r
-  UINTN                                            NameBufferSize;\r
-  UINTN                                            CommBufferPayloadSize;\r
-  UINTN                                            TempCommBufferSize;\r
+  EFI_STATUS                                               Status;\r
+  SMM_VARIABLE_COMMUNICATE_HEADER                          *SmmVariableFunctionHeader;\r
+  SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE                 *SmmVariableHeader;\r
+  SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME          *GetNextVariableName;\r
+  SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO             *QueryVariableInfo;\r
+  SMM_VARIABLE_COMMUNICATE_GET_PAYLOAD_SIZE                *GetPayloadSize;\r
+  SMM_VARIABLE_COMMUNICATE_RUNTIME_VARIABLE_CACHE_CONTEXT  *RuntimeVariableCacheContext;\r
+  SMM_VARIABLE_COMMUNICATE_GET_RUNTIME_CACHE_INFO          *GetRuntimeCacheInfo;\r
+  SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE                   *VariableToLock;\r
+  SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY     *CommVariableProperty;\r
+  VARIABLE_INFO_ENTRY                                      *VariableInfo;\r
+  VARIABLE_RUNTIME_CACHE_CONTEXT                           *VariableCacheContext;\r
+  VARIABLE_STORE_HEADER                                    *VariableCache;\r
+  UINTN                                                    InfoSize;\r
+  UINTN                                                    NameBufferSize;\r
+  UINTN                                                    CommBufferPayloadSize;\r
+  UINTN                                                    TempCommBufferSize;\r
 \r
   //\r
   // If input is invalid, stop processing this SMI\r
   //\r
-  if (CommBuffer == NULL || CommBufferSize == NULL) {\r
+  if ((CommBuffer == NULL) || (CommBufferSize == NULL)) {\r
     return EFI_SUCCESS;\r
   }\r
 \r
   TempCommBufferSize = *CommBufferSize;\r
 \r
   if (TempCommBufferSize < SMM_VARIABLE_COMMUNICATE_HEADER_SIZE) {\r
-    DEBUG ((EFI_D_ERROR, "SmmVariableHandler: SMM communication buffer size invalid!\n"));\r
+    DEBUG ((DEBUG_ERROR, "SmmVariableHandler: SMM communication buffer size invalid!\n"));\r
     return EFI_SUCCESS;\r
   }\r
+\r
   CommBufferPayloadSize = TempCommBufferSize - SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;\r
   if (CommBufferPayloadSize > mVariableBufferPayloadSize) {\r
-    DEBUG ((EFI_D_ERROR, "SmmVariableHandler: SMM communication buffer payload size invalid!\n"));\r
+    DEBUG ((DEBUG_ERROR, "SmmVariableHandler: SMM communication buffer payload size invalid!\n"));\r
     return EFI_SUCCESS;\r
   }\r
 \r
-  if (!SmmIsBufferOutsideSmmValid ((UINTN)CommBuffer, TempCommBufferSize)) {\r
-    DEBUG ((EFI_D_ERROR, "SmmVariableHandler: SMM communication buffer in SMRAM or overflow!\n"));\r
+  if (!VariableSmmIsBufferOutsideSmmValid ((UINTN)CommBuffer, TempCommBufferSize)) {\r
+    DEBUG ((DEBUG_ERROR, "SmmVariableHandler: SMM communication buffer in SMRAM or overflow!\n"));\r
     return EFI_SUCCESS;\r
   }\r
 \r
   SmmVariableFunctionHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *)CommBuffer;\r
   switch (SmmVariableFunctionHeader->Function) {\r
     case SMM_VARIABLE_FUNCTION_GET_VARIABLE:\r
-      if (CommBufferPayloadSize < OFFSET_OF(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)) {\r
-        DEBUG ((EFI_D_ERROR, "GetVariable: SMM communication buffer size invalid!\n"));\r
+      if (CommBufferPayloadSize < OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)) {\r
+        DEBUG ((DEBUG_ERROR, "GetVariable: SMM communication buffer size invalid!\n"));\r
         return EFI_SUCCESS;\r
       }\r
+\r
       //\r
       // Copy the input communicate buffer payload to pre-allocated SMM variable buffer payload.\r
       //\r
       CopyMem (mVariableBufferPayload, SmmVariableFunctionHeader->Data, CommBufferPayloadSize);\r
-      SmmVariableHeader = (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *) mVariableBufferPayload;\r
-      if (((UINTN)(~0) - SmmVariableHeader->DataSize < OFFSET_OF(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)) ||\r
-         ((UINTN)(~0) - SmmVariableHeader->NameSize < OFFSET_OF(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + SmmVariableHeader->DataSize)) {\r
+      SmmVariableHeader = (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *)mVariableBufferPayload;\r
+      if (((UINTN)(~0) - SmmVariableHeader->DataSize < OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)) ||\r
+          ((UINTN)(~0) - SmmVariableHeader->NameSize < OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + SmmVariableHeader->DataSize))\r
+      {\r
         //\r
         // Prevent InfoSize overflow happen\r
         //\r
         Status = EFI_ACCESS_DENIED;\r
         goto EXIT;\r
       }\r
-      InfoSize = OFFSET_OF(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)\r
+\r
+      InfoSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)\r
                  + SmmVariableHeader->DataSize + SmmVariableHeader->NameSize;\r
 \r
       //\r
       // SMRAM range check already covered before\r
       //\r
       if (InfoSize > CommBufferPayloadSize) {\r
-        DEBUG ((EFI_D_ERROR, "GetVariable: Data size exceed communication buffer size limit!\n"));\r
+        DEBUG ((DEBUG_ERROR, "GetVariable: Data size exceed communication buffer size limit!\n"));\r
         Status = EFI_ACCESS_DENIED;\r
         goto EXIT;\r
       }\r
 \r
-      if (SmmVariableHeader->NameSize < sizeof (CHAR16) || SmmVariableHeader->Name[SmmVariableHeader->NameSize/sizeof (CHAR16) - 1] != L'\0') {\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
         //\r
@@ -548,35 +562,37 @@ SmmVariableHandler (
       break;\r
 \r
     case SMM_VARIABLE_FUNCTION_GET_NEXT_VARIABLE_NAME:\r
-      if (CommBufferPayloadSize < OFFSET_OF(SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name)) {\r
-        DEBUG ((EFI_D_ERROR, "GetNextVariableName: SMM communication buffer size invalid!\n"));\r
+      if (CommBufferPayloadSize < OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name)) {\r
+        DEBUG ((DEBUG_ERROR, "GetNextVariableName: SMM communication buffer size invalid!\n"));\r
         return EFI_SUCCESS;\r
       }\r
+\r
       //\r
       // Copy the input communicate buffer payload to pre-allocated SMM variable buffer payload.\r
       //\r
       CopyMem (mVariableBufferPayload, SmmVariableFunctionHeader->Data, CommBufferPayloadSize);\r
-      GetNextVariableName = (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME *) mVariableBufferPayload;\r
-      if ((UINTN)(~0) - GetNextVariableName->NameSize < OFFSET_OF(SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name)) {\r
+      GetNextVariableName = (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME *)mVariableBufferPayload;\r
+      if ((UINTN)(~0) - GetNextVariableName->NameSize < OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name)) {\r
         //\r
         // Prevent InfoSize overflow happen\r
         //\r
         Status = EFI_ACCESS_DENIED;\r
         goto EXIT;\r
       }\r
-      InfoSize = OFFSET_OF(SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name) + GetNextVariableName->NameSize;\r
+\r
+      InfoSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name) + GetNextVariableName->NameSize;\r
 \r
       //\r
       // SMRAM range check already covered before\r
       //\r
       if (InfoSize > CommBufferPayloadSize) {\r
-        DEBUG ((EFI_D_ERROR, "GetNextVariableName: Data size exceed communication buffer size limit!\n"));\r
+        DEBUG ((DEBUG_ERROR, "GetNextVariableName: Data size exceed communication buffer size limit!\n"));\r
         Status = EFI_ACCESS_DENIED;\r
         goto EXIT;\r
       }\r
 \r
-      NameBufferSize = CommBufferPayloadSize - OFFSET_OF(SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name);\r
-      if (NameBufferSize < sizeof (CHAR16) || GetNextVariableName->Name[NameBufferSize/sizeof (CHAR16) - 1] != L'\0') {\r
+      NameBufferSize = CommBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name);\r
+      if ((NameBufferSize < sizeof (CHAR16)) || (GetNextVariableName->Name[NameBufferSize/sizeof (CHAR16) - 1] != L'\0')) {\r
         //\r
         // Make sure input VariableName is A Null-terminated string.\r
         //\r
@@ -593,24 +609,27 @@ SmmVariableHandler (
       break;\r
 \r
     case SMM_VARIABLE_FUNCTION_SET_VARIABLE:\r
-      if (CommBufferPayloadSize < OFFSET_OF(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)) {\r
-        DEBUG ((EFI_D_ERROR, "SetVariable: SMM communication buffer size invalid!\n"));\r
+      if (CommBufferPayloadSize < OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)) {\r
+        DEBUG ((DEBUG_ERROR, "SetVariable: SMM communication buffer size invalid!\n"));\r
         return EFI_SUCCESS;\r
       }\r
+\r
       //\r
       // Copy the input communicate buffer payload to pre-allocated SMM variable buffer payload.\r
       //\r
       CopyMem (mVariableBufferPayload, SmmVariableFunctionHeader->Data, CommBufferPayloadSize);\r
-      SmmVariableHeader = (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *) mVariableBufferPayload;\r
-      if (((UINTN)(~0) - SmmVariableHeader->DataSize < OFFSET_OF(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)) ||\r
-         ((UINTN)(~0) - SmmVariableHeader->NameSize < OFFSET_OF(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + SmmVariableHeader->DataSize)) {\r
+      SmmVariableHeader = (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *)mVariableBufferPayload;\r
+      if (((UINTN)(~0) - SmmVariableHeader->DataSize < OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)) ||\r
+          ((UINTN)(~0) - SmmVariableHeader->NameSize < OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + SmmVariableHeader->DataSize))\r
+      {\r
         //\r
         // Prevent InfoSize overflow happen\r
         //\r
         Status = EFI_ACCESS_DENIED;\r
         goto EXIT;\r
       }\r
-      InfoSize = OFFSET_OF(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)\r
+\r
+      InfoSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)\r
                  + SmmVariableHeader->DataSize + SmmVariableHeader->NameSize;\r
 \r
       //\r
@@ -618,12 +637,18 @@ SmmVariableHandler (
       // Data buffer should not contain SMM range\r
       //\r
       if (InfoSize > CommBufferPayloadSize) {\r
-        DEBUG ((EFI_D_ERROR, "SetVariable: Data size exceed communication buffer size limit!\n"));\r
+        DEBUG ((DEBUG_ERROR, "SetVariable: Data size exceed communication buffer size limit!\n"));\r
         Status = EFI_ACCESS_DENIED;\r
         goto EXIT;\r
       }\r
 \r
-      if (SmmVariableHeader->NameSize < sizeof (CHAR16) || SmmVariableHeader->Name[SmmVariableHeader->NameSize/sizeof (CHAR16) - 1] != L'\0') {\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
         //\r
@@ -642,10 +667,11 @@ SmmVariableHandler (
 \r
     case SMM_VARIABLE_FUNCTION_QUERY_VARIABLE_INFO:\r
       if (CommBufferPayloadSize < sizeof (SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO)) {\r
-        DEBUG ((EFI_D_ERROR, "QueryVariableInfo: SMM communication buffer size invalid!\n"));\r
+        DEBUG ((DEBUG_ERROR, "QueryVariableInfo: SMM communication buffer size invalid!\n"));\r
         return EFI_SUCCESS;\r
       }\r
-      QueryVariableInfo = (SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO *) SmmVariableFunctionHeader->Data;\r
+\r
+      QueryVariableInfo = (SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO *)SmmVariableFunctionHeader->Data;\r
 \r
       Status = VariableServiceQueryVariableInfo (\r
                  QueryVariableInfo->Attributes,\r
@@ -657,20 +683,25 @@ SmmVariableHandler (
 \r
     case SMM_VARIABLE_FUNCTION_GET_PAYLOAD_SIZE:\r
       if (CommBufferPayloadSize < sizeof (SMM_VARIABLE_COMMUNICATE_GET_PAYLOAD_SIZE)) {\r
-        DEBUG ((EFI_D_ERROR, "GetPayloadSize: SMM communication buffer size invalid!\n"));\r
+        DEBUG ((DEBUG_ERROR, "GetPayloadSize: SMM communication buffer size invalid!\n"));\r
         return EFI_SUCCESS;\r
       }\r
-      GetPayloadSize = (SMM_VARIABLE_COMMUNICATE_GET_PAYLOAD_SIZE *) SmmVariableFunctionHeader->Data;\r
+\r
+      GetPayloadSize                      = (SMM_VARIABLE_COMMUNICATE_GET_PAYLOAD_SIZE *)SmmVariableFunctionHeader->Data;\r
       GetPayloadSize->VariablePayloadSize = mVariableBufferPayloadSize;\r
-      Status = EFI_SUCCESS;\r
+      Status                              = EFI_SUCCESS;\r
       break;\r
 \r
     case SMM_VARIABLE_FUNCTION_READY_TO_BOOT:\r
-      if (AtRuntime()) {\r
+      if (AtRuntime ()) {\r
         Status = EFI_UNSUPPORTED;\r
         break;\r
       }\r
+\r
       if (!mEndOfDxe) {\r
+        MorLockInitAtEndOfDxe ();\r
+        Status = LockVariablePolicy ();\r
+        ASSERT_EFI_ERROR (Status);\r
         mEndOfDxe = TRUE;\r
         VarCheckLibInitializeAtEndOfDxe (NULL);\r
         //\r
@@ -678,31 +709,31 @@ SmmVariableHandler (
         //\r
         InitializeVariableQuota ();\r
       }\r
+\r
       ReclaimForOS ();\r
       Status = EFI_SUCCESS;\r
       break;\r
 \r
     case SMM_VARIABLE_FUNCTION_EXIT_BOOT_SERVICE:\r
       mAtRuntime = TRUE;\r
-      Status = EFI_SUCCESS;\r
+      Status     = EFI_SUCCESS;\r
       break;\r
 \r
     case SMM_VARIABLE_FUNCTION_GET_STATISTICS:\r
-      VariableInfo = (VARIABLE_INFO_ENTRY *) SmmVariableFunctionHeader->Data;\r
-      InfoSize = TempCommBufferSize - SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;\r
+      VariableInfo = (VARIABLE_INFO_ENTRY *)SmmVariableFunctionHeader->Data;\r
+      InfoSize     = TempCommBufferSize - SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;\r
 \r
       //\r
       // Do not need to check SmmVariableFunctionHeader->Data in SMRAM here.\r
       // It is covered by previous CommBuffer check\r
       //\r
 \r
-      if (!SmmIsBufferOutsideSmmValid ((EFI_PHYSICAL_ADDRESS)(UINTN)CommBufferSize, sizeof(UINTN))) {\r
-        DEBUG ((EFI_D_ERROR, "GetStatistics: SMM communication buffer in SMRAM!\n"));\r
-        Status = EFI_ACCESS_DENIED;\r
-        goto EXIT;\r
-      }\r
+      //\r
+      // Do not need to check CommBufferSize buffer as it should point to SMRAM\r
+      // that was used by SMM core to cache CommSize from SmmCommunication protocol.\r
+      //\r
 \r
-      Status = SmmVariableGetStatistics (VariableInfo, &InfoSize);\r
+      Status          = SmmVariableGetStatistics (VariableInfo, &InfoSize);\r
       *CommBufferSize = InfoSize + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;\r
       break;\r
 \r
@@ -710,55 +741,65 @@ SmmVariableHandler (
       if (mEndOfDxe) {\r
         Status = EFI_ACCESS_DENIED;\r
       } else {\r
-        VariableToLock = (SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE *) SmmVariableFunctionHeader->Data;\r
-        Status = VariableLockRequestToLock (\r
-                   NULL,\r
-                   VariableToLock->Name,\r
-                   &VariableToLock->Guid\r
-                   );\r
+        VariableToLock = (SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE *)SmmVariableFunctionHeader->Data;\r
+        Status         = VariableLockRequestToLock (\r
+                           NULL,\r
+                           VariableToLock->Name,\r
+                           &VariableToLock->Guid\r
+                           );\r
       }\r
+\r
       break;\r
     case SMM_VARIABLE_FUNCTION_VAR_CHECK_VARIABLE_PROPERTY_SET:\r
       if (mEndOfDxe) {\r
         Status = EFI_ACCESS_DENIED;\r
       } else {\r
-        CommVariableProperty = (SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY *) SmmVariableFunctionHeader->Data;\r
-        Status = VarCheckVariablePropertySet (\r
-                   CommVariableProperty->Name,\r
-                   &CommVariableProperty->Guid,\r
-                   &CommVariableProperty->VariableProperty\r
-                   );\r
+        CommVariableProperty = (SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY *)SmmVariableFunctionHeader->Data;\r
+        Status               = VarCheckVariablePropertySet (\r
+                                 CommVariableProperty->Name,\r
+                                 &CommVariableProperty->Guid,\r
+                                 &CommVariableProperty->VariableProperty\r
+                                 );\r
       }\r
+\r
       break;\r
     case SMM_VARIABLE_FUNCTION_VAR_CHECK_VARIABLE_PROPERTY_GET:\r
       if (CommBufferPayloadSize < OFFSET_OF (SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY, Name)) {\r
-        DEBUG ((EFI_D_ERROR, "VarCheckVariablePropertyGet: SMM communication buffer size invalid!\n"));\r
+        DEBUG ((DEBUG_ERROR, "VarCheckVariablePropertyGet: SMM communication buffer size invalid!\n"));\r
         return EFI_SUCCESS;\r
       }\r
+\r
       //\r
       // Copy the input communicate buffer payload to pre-allocated SMM variable buffer payload.\r
       //\r
       CopyMem (mVariableBufferPayload, SmmVariableFunctionHeader->Data, CommBufferPayloadSize);\r
-      CommVariableProperty = (SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY *) mVariableBufferPayload;\r
-      if ((UINTN) (~0) - CommVariableProperty->NameSize < OFFSET_OF (SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY, Name)) {\r
+      CommVariableProperty = (SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY *)mVariableBufferPayload;\r
+      if ((UINTN)(~0) - CommVariableProperty->NameSize < OFFSET_OF (SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY, Name)) {\r
         //\r
         // Prevent InfoSize overflow happen\r
         //\r
         Status = EFI_ACCESS_DENIED;\r
         goto EXIT;\r
       }\r
+\r
       InfoSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY, Name) + CommVariableProperty->NameSize;\r
 \r
       //\r
       // SMRAM range check already covered before\r
       //\r
       if (InfoSize > CommBufferPayloadSize) {\r
-        DEBUG ((EFI_D_ERROR, "VarCheckVariablePropertyGet: Data size exceed communication buffer size limit!\n"));\r
+        DEBUG ((DEBUG_ERROR, "VarCheckVariablePropertyGet: Data size exceed communication buffer size limit!\n"));\r
         Status = EFI_ACCESS_DENIED;\r
         goto EXIT;\r
       }\r
 \r
-      if (CommVariableProperty->NameSize < sizeof (CHAR16) || CommVariableProperty->Name[CommVariableProperty->NameSize/sizeof (CHAR16) - 1] != L'\0') {\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
         //\r
@@ -773,6 +814,177 @@ SmmVariableHandler (
                  );\r
       CopyMem (SmmVariableFunctionHeader->Data, mVariableBufferPayload, CommBufferPayloadSize);\r
       break;\r
+    case SMM_VARIABLE_FUNCTION_INIT_RUNTIME_VARIABLE_CACHE_CONTEXT:\r
+      if (CommBufferPayloadSize < sizeof (SMM_VARIABLE_COMMUNICATE_RUNTIME_VARIABLE_CACHE_CONTEXT)) {\r
+        DEBUG ((DEBUG_ERROR, "InitRuntimeVariableCacheContext: SMM communication buffer size invalid!\n"));\r
+        Status = EFI_ACCESS_DENIED;\r
+        goto EXIT;\r
+      }\r
+\r
+      if (mEndOfDxe) {\r
+        DEBUG ((DEBUG_ERROR, "InitRuntimeVariableCacheContext: Cannot init context after end of DXE!\n"));\r
+        Status = EFI_ACCESS_DENIED;\r
+        goto EXIT;\r
+      }\r
+\r
+      //\r
+      // Copy the input communicate buffer payload to the pre-allocated SMM variable payload buffer.\r
+      //\r
+      CopyMem (mVariableBufferPayload, SmmVariableFunctionHeader->Data, CommBufferPayloadSize);\r
+      RuntimeVariableCacheContext = (SMM_VARIABLE_COMMUNICATE_RUNTIME_VARIABLE_CACHE_CONTEXT *)mVariableBufferPayload;\r
+\r
+      //\r
+      // Verify required runtime cache buffers are provided.\r
+      //\r
+      if ((RuntimeVariableCacheContext->RuntimeVolatileCache == NULL) ||\r
+          (RuntimeVariableCacheContext->RuntimeNvCache == NULL) ||\r
+          (RuntimeVariableCacheContext->PendingUpdate == NULL) ||\r
+          (RuntimeVariableCacheContext->ReadLock == NULL) ||\r
+          (RuntimeVariableCacheContext->HobFlushComplete == NULL))\r
+      {\r
+        DEBUG ((DEBUG_ERROR, "InitRuntimeVariableCacheContext: Required runtime cache buffer is NULL!\n"));\r
+        Status = EFI_ACCESS_DENIED;\r
+        goto EXIT;\r
+      }\r
+\r
+      //\r
+      // Verify minimum size requirements for the runtime variable store buffers.\r
+      //\r
+      if (((RuntimeVariableCacheContext->RuntimeHobCache != NULL) &&\r
+           (RuntimeVariableCacheContext->RuntimeHobCache->Size < sizeof (VARIABLE_STORE_HEADER))) ||\r
+          (RuntimeVariableCacheContext->RuntimeVolatileCache->Size < sizeof (VARIABLE_STORE_HEADER)) ||\r
+          (RuntimeVariableCacheContext->RuntimeNvCache->Size < sizeof (VARIABLE_STORE_HEADER)))\r
+      {\r
+        DEBUG ((DEBUG_ERROR, "InitRuntimeVariableCacheContext: A runtime cache buffer size is invalid!\n"));\r
+        Status = EFI_ACCESS_DENIED;\r
+        goto EXIT;\r
+      }\r
+\r
+      //\r
+      // Verify runtime buffers do not overlap with SMRAM ranges.\r
+      //\r
+      if ((RuntimeVariableCacheContext->RuntimeHobCache != NULL) &&\r
+          !VariableSmmIsBufferOutsideSmmValid (\r
+             (UINTN)RuntimeVariableCacheContext->RuntimeHobCache,\r
+             (UINTN)RuntimeVariableCacheContext->RuntimeHobCache->Size\r
+             ))\r
+      {\r
+        DEBUG ((DEBUG_ERROR, "InitRuntimeVariableCacheContext: Runtime HOB cache buffer in SMRAM or overflow!\n"));\r
+        Status = EFI_ACCESS_DENIED;\r
+        goto EXIT;\r
+      }\r
+\r
+      if (!VariableSmmIsBufferOutsideSmmValid (\r
+             (UINTN)RuntimeVariableCacheContext->RuntimeVolatileCache,\r
+             (UINTN)RuntimeVariableCacheContext->RuntimeVolatileCache->Size\r
+             ))\r
+      {\r
+        DEBUG ((DEBUG_ERROR, "InitRuntimeVariableCacheContext: Runtime volatile cache buffer in SMRAM or overflow!\n"));\r
+        Status = EFI_ACCESS_DENIED;\r
+        goto EXIT;\r
+      }\r
+\r
+      if (!VariableSmmIsBufferOutsideSmmValid (\r
+             (UINTN)RuntimeVariableCacheContext->RuntimeNvCache,\r
+             (UINTN)RuntimeVariableCacheContext->RuntimeNvCache->Size\r
+             ))\r
+      {\r
+        DEBUG ((DEBUG_ERROR, "InitRuntimeVariableCacheContext: Runtime non-volatile cache buffer in SMRAM or overflow!\n"));\r
+        Status = EFI_ACCESS_DENIED;\r
+        goto EXIT;\r
+      }\r
+\r
+      if (!VariableSmmIsBufferOutsideSmmValid (\r
+             (UINTN)RuntimeVariableCacheContext->PendingUpdate,\r
+             sizeof (*(RuntimeVariableCacheContext->PendingUpdate))\r
+             ))\r
+      {\r
+        DEBUG ((DEBUG_ERROR, "InitRuntimeVariableCacheContext: Runtime cache pending update buffer in SMRAM or overflow!\n"));\r
+        Status = EFI_ACCESS_DENIED;\r
+        goto EXIT;\r
+      }\r
+\r
+      if (!VariableSmmIsBufferOutsideSmmValid (\r
+             (UINTN)RuntimeVariableCacheContext->ReadLock,\r
+             sizeof (*(RuntimeVariableCacheContext->ReadLock))\r
+             ))\r
+      {\r
+        DEBUG ((DEBUG_ERROR, "InitRuntimeVariableCacheContext: Runtime cache read lock buffer in SMRAM or overflow!\n"));\r
+        Status = EFI_ACCESS_DENIED;\r
+        goto EXIT;\r
+      }\r
+\r
+      if (!VariableSmmIsBufferOutsideSmmValid (\r
+             (UINTN)RuntimeVariableCacheContext->HobFlushComplete,\r
+             sizeof (*(RuntimeVariableCacheContext->HobFlushComplete))\r
+             ))\r
+      {\r
+        DEBUG ((DEBUG_ERROR, "InitRuntimeVariableCacheContext: Runtime cache HOB flush complete buffer in SMRAM or overflow!\n"));\r
+        Status = EFI_ACCESS_DENIED;\r
+        goto EXIT;\r
+      }\r
+\r
+      VariableCacheContext                                     = &mVariableModuleGlobal->VariableGlobal.VariableRuntimeCacheContext;\r
+      VariableCacheContext->VariableRuntimeHobCache.Store      = RuntimeVariableCacheContext->RuntimeHobCache;\r
+      VariableCacheContext->VariableRuntimeVolatileCache.Store = RuntimeVariableCacheContext->RuntimeVolatileCache;\r
+      VariableCacheContext->VariableRuntimeNvCache.Store       = RuntimeVariableCacheContext->RuntimeNvCache;\r
+      VariableCacheContext->PendingUpdate                      = RuntimeVariableCacheContext->PendingUpdate;\r
+      VariableCacheContext->ReadLock                           = RuntimeVariableCacheContext->ReadLock;\r
+      VariableCacheContext->HobFlushComplete                   = RuntimeVariableCacheContext->HobFlushComplete;\r
+\r
+      // Set up the intial pending request since the RT cache needs to be in sync with SMM cache\r
+      VariableCacheContext->VariableRuntimeHobCache.PendingUpdateOffset = 0;\r
+      VariableCacheContext->VariableRuntimeHobCache.PendingUpdateLength = 0;\r
+      if ((mVariableModuleGlobal->VariableGlobal.HobVariableBase > 0) &&\r
+          (VariableCacheContext->VariableRuntimeHobCache.Store != NULL))\r
+      {\r
+        VariableCache                                                     = (VARIABLE_STORE_HEADER *)(UINTN)mVariableModuleGlobal->VariableGlobal.HobVariableBase;\r
+        VariableCacheContext->VariableRuntimeHobCache.PendingUpdateLength = (UINT32)((UINTN)GetEndPointer (VariableCache) - (UINTN)VariableCache);\r
+        CopyGuid (&(VariableCacheContext->VariableRuntimeHobCache.Store->Signature), &(VariableCache->Signature));\r
+      }\r
+\r
+      VariableCache                                                          = (VARIABLE_STORE_HEADER  *)(UINTN)mVariableModuleGlobal->VariableGlobal.VolatileVariableBase;\r
+      VariableCacheContext->VariableRuntimeVolatileCache.PendingUpdateOffset = 0;\r
+      VariableCacheContext->VariableRuntimeVolatileCache.PendingUpdateLength = (UINT32)((UINTN)GetEndPointer (VariableCache) - (UINTN)VariableCache);\r
+      CopyGuid (&(VariableCacheContext->VariableRuntimeVolatileCache.Store->Signature), &(VariableCache->Signature));\r
+\r
+      VariableCache                                                    = (VARIABLE_STORE_HEADER  *)(UINTN)mNvVariableCache;\r
+      VariableCacheContext->VariableRuntimeNvCache.PendingUpdateOffset = 0;\r
+      VariableCacheContext->VariableRuntimeNvCache.PendingUpdateLength = (UINT32)((UINTN)GetEndPointer (VariableCache) - (UINTN)VariableCache);\r
+      CopyGuid (&(VariableCacheContext->VariableRuntimeNvCache.Store->Signature), &(VariableCache->Signature));\r
+\r
+      *(VariableCacheContext->PendingUpdate)    = TRUE;\r
+      *(VariableCacheContext->ReadLock)         = FALSE;\r
+      *(VariableCacheContext->HobFlushComplete) = FALSE;\r
+\r
+      Status = EFI_SUCCESS;\r
+      break;\r
+    case SMM_VARIABLE_FUNCTION_SYNC_RUNTIME_CACHE:\r
+      Status = FlushPendingRuntimeVariableCacheUpdates ();\r
+      break;\r
+    case SMM_VARIABLE_FUNCTION_GET_RUNTIME_CACHE_INFO:\r
+      if (CommBufferPayloadSize < sizeof (SMM_VARIABLE_COMMUNICATE_GET_RUNTIME_CACHE_INFO)) {\r
+        DEBUG ((DEBUG_ERROR, "GetRuntimeCacheInfo: SMM communication buffer size invalid!\n"));\r
+        return EFI_SUCCESS;\r
+      }\r
+\r
+      GetRuntimeCacheInfo = (SMM_VARIABLE_COMMUNICATE_GET_RUNTIME_CACHE_INFO *)SmmVariableFunctionHeader->Data;\r
+\r
+      if (mVariableModuleGlobal->VariableGlobal.HobVariableBase > 0) {\r
+        VariableCache                            = (VARIABLE_STORE_HEADER *)(UINTN)mVariableModuleGlobal->VariableGlobal.HobVariableBase;\r
+        GetRuntimeCacheInfo->TotalHobStorageSize = VariableCache->Size;\r
+      } else {\r
+        GetRuntimeCacheInfo->TotalHobStorageSize = 0;\r
+      }\r
+\r
+      VariableCache                                   = (VARIABLE_STORE_HEADER  *)(UINTN)mVariableModuleGlobal->VariableGlobal.VolatileVariableBase;\r
+      GetRuntimeCacheInfo->TotalVolatileStorageSize   = VariableCache->Size;\r
+      VariableCache                                   = (VARIABLE_STORE_HEADER  *)(UINTN)mNvVariableCache;\r
+      GetRuntimeCacheInfo->TotalNvStorageSize         = (UINTN)VariableCache->Size;\r
+      GetRuntimeCacheInfo->AuthenticatedVariableUsage = mVariableModuleGlobal->VariableGlobal.AuthFormat;\r
+\r
+      Status = EFI_SUCCESS;\r
+      break;\r
 \r
     default:\r
       Status = EFI_UNSUPPORTED;\r
@@ -798,12 +1010,17 @@ EXIT:
 EFI_STATUS\r
 EFIAPI\r
 SmmEndOfDxeCallback (\r
-  IN CONST EFI_GUID                       *Protocol,\r
-  IN VOID                                 *Interface,\r
-  IN EFI_HANDLE                           Handle\r
+  IN CONST EFI_GUID  *Protocol,\r
+  IN VOID            *Interface,\r
+  IN EFI_HANDLE      Handle\r
   )\r
 {\r
-  DEBUG ((EFI_D_INFO, "[Variable]SMM_END_OF_DXE is signaled\n"));\r
+  EFI_STATUS  Status;\r
+\r
+  DEBUG ((DEBUG_INFO, "[Variable]SMM_END_OF_DXE is signaled\n"));\r
+  MorLockInitAtEndOfDxe ();\r
+  Status = LockVariablePolicy ();\r
+  ASSERT_EFI_ERROR (Status);\r
   mEndOfDxe = TRUE;\r
   VarCheckLibInitializeAtEndOfDxe (NULL);\r
   //\r
@@ -817,6 +1034,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
@@ -834,12 +1073,13 @@ SmmEndOfDxeCallback (
 EFI_STATUS\r
 EFIAPI\r
 SmmFtwNotificationEvent (\r
-  IN CONST EFI_GUID                       *Protocol,\r
-  IN VOID                                 *Interface,\r
-  IN EFI_HANDLE                           Handle\r
+  IN CONST EFI_GUID  *Protocol,\r
+  IN VOID            *Interface,\r
+  IN EFI_HANDLE      Handle\r
   )\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
@@ -862,13 +1102,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
@@ -876,49 +1120,33 @@ 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
 \r
-\r
 /**\r
   Variable Driver main entry point. The Variable driver places the 4 EFI\r
   runtime services in the EFI System Table and installs arch protocols\r
   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
-  EFI_HANDLE                              VariableHandle;\r
-  VOID                                    *SmmFtwRegistration;\r
-  VOID                                    *SmmEndOfDxeRegistration;\r
+  EFI_STATUS  Status;\r
+  EFI_HANDLE  VariableHandle;\r
+  VOID        *SmmFtwRegistration;\r
+  VOID        *SmmEndOfDxeRegistration;\r
 \r
   //\r
   // Variable initialize.\r
@@ -930,15 +1158,15 @@ VariableServiceInitialize (
   // Install the Smm Variable Protocol on a new handle.\r
   //\r
   VariableHandle = NULL;\r
-  Status = gSmst->SmmInstallProtocolInterface (\r
-                    &VariableHandle,\r
-                    &gEfiSmmVariableProtocolGuid,\r
-                    EFI_NATIVE_INTERFACE,\r
-                    &gSmmVariable\r
-                    );\r
+  Status         = gMmst->MmInstallProtocolInterface (\r
+                            &VariableHandle,\r
+                            &gEfiSmmVariableProtocolGuid,\r
+                            EFI_NATIVE_INTERFACE,\r
+                            &gSmmVariable\r
+                            );\r
   ASSERT_EFI_ERROR (Status);\r
 \r
-  Status = gSmst->SmmInstallProtocolInterface (\r
+  Status = gMmst->MmInstallProtocolInterface (\r
                     &VariableHandle,\r
                     &gEdkiiSmmVarCheckProtocolGuid,\r
                     EFI_NATIVE_INTERFACE,\r
@@ -946,10 +1174,11 @@ VariableServiceInitialize (
                     );\r
   ASSERT_EFI_ERROR (Status);\r
 \r
-  mVariableBufferPayloadSize = GetNonVolatileMaxVariableSize () +\r
-                               OFFSET_OF (SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY, Name) - GetVariableHeaderSize ();\r
+  mVariableBufferPayloadSize =  GetMaxVariableSize () +\r
+                               OFFSET_OF (SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY, Name) -\r
+                               GetVariableHeaderSize (mVariableModuleGlobal->VariableGlobal.AuthFormat);\r
 \r
-  Status = gSmst->SmmAllocatePool (\r
+  Status = gMmst->MmAllocatePool (\r
                     EfiRuntimeServicesData,\r
                     mVariableBufferPayloadSize,\r
                     (VOID **)&mVariableBufferPayload\r
@@ -960,43 +1189,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
-\r
-\r