]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c
MdeModulePkg VariableDxe: Update it supports normal format variable storage
[mirror_edk2.git] / MdeModulePkg / Universal / Variable / RuntimeDxe / Variable.c
index 31e1937c2f19ed62daa1f29730548dbb4e34e441..77905a0a308086d3b7dc8acebc723dcaae159b4d 100644 (file)
@@ -16,7 +16,8 @@
   VariableServiceSetVariable() should also check authenticate data to avoid buffer overflow,\r
   integer overflow. It should also check attribute to avoid authentication bypass.\r
 \r
-Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>\r
+(C) Copyright 2015 Hewlett Packard Enterprise Development LP<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
@@ -36,6 +37,11 @@ VARIABLE_MODULE_GLOBAL  *mVariableModuleGlobal;
 ///\r
 VARIABLE_STORE_HEADER  *mNvVariableCache      = NULL;\r
 \r
+///\r
+/// Memory cache of Fv Header.\r
+///\r
+EFI_FIRMWARE_VOLUME_HEADER *mNvFvHeaderCache  = NULL;\r
+\r
 ///\r
 /// The memory entry used for variable statistics data.\r
 ///\r
@@ -91,20 +97,6 @@ AUTH_VAR_LIB_CONTEXT_IN mAuthContextIn = {
 \r
 AUTH_VAR_LIB_CONTEXT_OUT mAuthContextOut;\r
 \r
-/**\r
-\r
-  SecureBoot Hook for auth variable update.\r
-\r
-  @param[in] VariableName                 Name of Variable to be found.\r
-  @param[in] VendorGuid                   Variable vendor GUID.\r
-**/\r
-VOID\r
-EFIAPI\r
-SecureBootHook (\r
-  IN CHAR16                                 *VariableName,\r
-  IN EFI_GUID                               *VendorGuid\r
-  );\r
-\r
 /**\r
   Routine used to track statistical information about variable usage.\r
   The data is stored in the EFI system table so it can be accessed later.\r
@@ -333,7 +325,7 @@ UpdateVariableStore (
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  for (PtrBlockMapEntry = FwVolHeader->BlockMap; PtrBlockMapEntry->NumBlocks != 0; PtrBlockMapEntry++) {\r
+  for (PtrBlockMapEntry = mNvFvHeaderCache->BlockMap; PtrBlockMapEntry->NumBlocks != 0; PtrBlockMapEntry++) {\r
     for (BlockIndex2 = 0; BlockIndex2 < PtrBlockMapEntry->NumBlocks; BlockIndex2++) {\r
       //\r
       // Check to see if the Variable Writes are spanning through multiple\r
@@ -793,7 +785,7 @@ RecordVarErrorFlag (
       //\r
       // Update the data in NV cache.\r
       //\r
-      *VarErrFlag = Flag;\r
+      *VarErrFlag = TempFlag;\r
     }\r
   }\r
 }\r
@@ -1127,7 +1119,7 @@ Reclaim (
   // Install the new variable if it is not NULL.\r
   //\r
   if (NewVariable != NULL) {\r
-    if ((UINTN) (CurrPtr - ValidBuffer) + NewVariableSize > VariableStoreHeader->Size) {\r
+    if (((UINTN) CurrPtr - (UINTN) ValidBuffer) + NewVariableSize > VariableStoreHeader->Size) {\r
       //\r
       // No enough space to store the new variable.\r
       //\r
@@ -1168,8 +1160,8 @@ Reclaim (
     // If volatile variable store, just copy valid buffer.\r
     //\r
     SetMem ((UINT8 *) (UINTN) VariableBase, VariableStoreHeader->Size, 0xff);\r
-    CopyMem ((UINT8 *) (UINTN) VariableBase, ValidBuffer, (UINTN) (CurrPtr - ValidBuffer));\r
-    *LastVariableOffset = (UINTN) (CurrPtr - ValidBuffer);\r
+    CopyMem ((UINT8 *) (UINTN) VariableBase, ValidBuffer, (UINTN) CurrPtr - (UINTN) ValidBuffer);\r
+    *LastVariableOffset = (UINTN) CurrPtr - (UINTN) ValidBuffer;\r
     Status  = EFI_SUCCESS;\r
   } else {\r
     //\r
@@ -1180,11 +1172,14 @@ Reclaim (
               (VARIABLE_STORE_HEADER *) ValidBuffer\r
               );\r
     if (!EFI_ERROR (Status)) {\r
-      *LastVariableOffset = (UINTN) (CurrPtr - ValidBuffer);\r
+      *LastVariableOffset = (UINTN) CurrPtr - (UINTN) ValidBuffer;\r
       mVariableModuleGlobal->HwErrVariableTotalSize = HwErrVariableTotalSize;\r
       mVariableModuleGlobal->CommonVariableTotalSize = CommonVariableTotalSize;\r
       mVariableModuleGlobal->CommonUserVariableTotalSize = CommonUserVariableTotalSize;\r
     } else {\r
+      mVariableModuleGlobal->HwErrVariableTotalSize = 0;\r
+      mVariableModuleGlobal->CommonVariableTotalSize = 0;\r
+      mVariableModuleGlobal->CommonUserVariableTotalSize = 0;\r
       Variable = GetStartPointer ((VARIABLE_STORE_HEADER *)(UINTN)VariableBase);\r
       while (IsValidVariableHeader (Variable, GetEndPointer ((VARIABLE_STORE_HEADER *)(UINTN)VariableBase))) {\r
         NextVariable = GetNextVariablePtr (Variable);\r
@@ -1710,7 +1705,7 @@ CheckRemainingSpaceForConsistencyInternal (
   ASSERT_EFI_ERROR (Status);\r
 \r
   TotalNeededSize = 0;\r
-  Args = Marker;\r
+  VA_COPY (Args, Marker);\r
   VariableEntry = VA_ARG (Args, VARIABLE_ENTRY_CONSISTENCY *);\r
   while (VariableEntry != NULL) {\r
     //\r
@@ -1725,6 +1720,7 @@ CheckRemainingSpaceForConsistencyInternal (
     TotalNeededSize += VariableEntry->VariableSize;\r
     VariableEntry = VA_ARG (Args, VARIABLE_ENTRY_CONSISTENCY *);\r
   }\r
+  VA_END  (Args);\r
 \r
   if (RemainingVariableStorageSize >= TotalNeededSize) {\r
     //\r
@@ -1739,7 +1735,7 @@ CheckRemainingSpaceForConsistencyInternal (
     return FALSE;\r
   }\r
 \r
-  Args = Marker;\r
+  VA_COPY (Args, Marker);\r
   VariableEntry = VA_ARG (Args, VARIABLE_ENTRY_CONSISTENCY *);\r
   while (VariableEntry != NULL) {\r
     //\r
@@ -1769,6 +1765,7 @@ CheckRemainingSpaceForConsistencyInternal (
       //\r
       // No enough space for Variable[Index].\r
       //\r
+      VA_END (Args);\r
       return FALSE;\r
     }\r
     //\r
@@ -1777,6 +1774,7 @@ CheckRemainingSpaceForConsistencyInternal (
     RemainingVariableStorageSize -= VariableEntry->VariableSize;\r
     VariableEntry = VA_ARG (Args, VARIABLE_ENTRY_CONSISTENCY *);\r
   }\r
+  VA_END  (Args);\r
 \r
   return TRUE;\r
 }\r
@@ -2192,6 +2190,7 @@ UpdateVariable (
         // go to delete this variable in variable HOB and\r
         // try to flush other variables from HOB to flash.\r
         //\r
+        UpdateVariableInfo (VariableName, VendorGuid, FALSE, FALSE, FALSE, TRUE, FALSE);\r
         FlushHobVariableToFlash (VariableName, VendorGuid);\r
         return EFI_SUCCESS;\r
       }\r
@@ -2209,7 +2208,8 @@ UpdateVariable (
     VariableStoreHeader  = (VARIABLE_STORE_HEADER *) ((UINTN) mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase);\r
     Variable = &NvVariable;\r
     Variable->StartPtr = GetStartPointer (VariableStoreHeader);\r
-    Variable->EndPtr   = GetEndPointer (VariableStoreHeader);\r
+    Variable->EndPtr   = (VARIABLE_HEADER *)((UINTN)Variable->StartPtr + ((UINTN)CacheVariable->EndPtr - (UINTN)CacheVariable->StartPtr));\r
+\r
     Variable->CurrPtr  = (VARIABLE_HEADER *)((UINTN)Variable->StartPtr + ((UINTN)CacheVariable->CurrPtr - (UINTN)CacheVariable->StartPtr));\r
     if (CacheVariable->InDeletedTransitionPtr != NULL) {\r
       Variable->InDeletedTransitionPtr = (VARIABLE_HEADER *)((UINTN)Variable->StartPtr + ((UINTN)CacheVariable->InDeletedTransitionPtr - (UINTN)CacheVariable->StartPtr));\r
@@ -2247,7 +2247,7 @@ UpdateVariable (
       //\r
       // Only variable that have NV attributes can be updated/deleted in Runtime.\r
       //\r
-      if ((Variable->CurrPtr->Attributes & EFI_VARIABLE_NON_VOLATILE) == 0) {\r
+      if ((CacheVariable->CurrPtr->Attributes & EFI_VARIABLE_NON_VOLATILE) == 0) {\r
         Status = EFI_INVALID_PARAMETER;\r
         goto Done;\r
       }\r
@@ -2255,7 +2255,7 @@ UpdateVariable (
       //\r
       // Only variable that have RT attributes can be updated/deleted in Runtime.\r
       //\r
-      if ((Variable->CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0) {\r
+      if ((CacheVariable->CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0) {\r
         Status = EFI_INVALID_PARAMETER;\r
         goto Done;\r
       }\r
@@ -2273,7 +2273,8 @@ UpdateVariable (
         // Both ADDED and IN_DELETED_TRANSITION variable are present,\r
         // set IN_DELETED_TRANSITION one to DELETED state first.\r
         //\r
-        State = Variable->InDeletedTransitionPtr->State;\r
+        ASSERT (CacheVariable->InDeletedTransitionPtr != NULL);\r
+        State = CacheVariable->InDeletedTransitionPtr->State;\r
         State &= VAR_DELETED;\r
         Status = UpdateVariableStore (\r
                    &mVariableModuleGlobal->VariableGlobal,\r
@@ -2286,7 +2287,6 @@ UpdateVariable (
                    );\r
         if (!EFI_ERROR (Status)) {\r
           if (!Variable->Volatile) {\r
-            ASSERT (CacheVariable->InDeletedTransitionPtr != NULL);\r
             CacheVariable->InDeletedTransitionPtr->State = State;\r
           }\r
         } else {\r
@@ -2294,7 +2294,7 @@ UpdateVariable (
         }\r
       }\r
 \r
-      State = Variable->CurrPtr->State;\r
+      State = CacheVariable->CurrPtr->State;\r
       State &= VAR_DELETED;\r
 \r
       Status = UpdateVariableStore (\r
@@ -2319,8 +2319,8 @@ UpdateVariable (
     // If the variable is marked valid, and the same data has been passed in,\r
     // then return to the caller immediately.\r
     //\r
-    if (DataSizeOfVariable (Variable->CurrPtr) == DataSize &&\r
-        (CompareMem (Data, GetVariableDataPtr (Variable->CurrPtr), DataSize) == 0) &&\r
+    if (DataSizeOfVariable (CacheVariable->CurrPtr) == DataSize &&\r
+        (CompareMem (Data, GetVariableDataPtr (CacheVariable->CurrPtr), DataSize) == 0) &&\r
         ((Attributes & EFI_VARIABLE_APPEND_WRITE) == 0) &&\r
         (TimeStamp == NULL)) {\r
       //\r
@@ -2329,8 +2329,8 @@ UpdateVariable (
       UpdateVariableInfo (VariableName, VendorGuid, Variable->Volatile, FALSE, TRUE, FALSE, FALSE);\r
       Status = EFI_SUCCESS;\r
       goto Done;\r
-    } else if ((Variable->CurrPtr->State == VAR_ADDED) ||\r
-               (Variable->CurrPtr->State == (VAR_ADDED & VAR_IN_DELETED_TRANSITION))) {\r
+    } else if ((CacheVariable->CurrPtr->State == VAR_ADDED) ||\r
+               (CacheVariable->CurrPtr->State == (VAR_ADDED & VAR_IN_DELETED_TRANSITION))) {\r
 \r
       //\r
       // EFI_VARIABLE_APPEND_WRITE attribute only effects for existing variable.\r
@@ -2340,9 +2340,9 @@ UpdateVariable (
         // NOTE: From 0 to DataOffset of NextVariable is reserved for Variable Header and Name.\r
         // From DataOffset of NextVariable is to save the existing variable data.\r
         //\r
-        DataOffset = GetVariableDataOffset (Variable->CurrPtr);\r
+        DataOffset = GetVariableDataOffset (CacheVariable->CurrPtr);\r
         BufferForMerge = (UINT8 *) ((UINTN) NextVariable + DataOffset);\r
-        CopyMem (BufferForMerge, (UINT8 *) ((UINTN) Variable->CurrPtr + DataOffset), DataSizeOfVariable (Variable->CurrPtr));\r
+        CopyMem (BufferForMerge, (UINT8 *) ((UINTN) CacheVariable->CurrPtr + DataOffset), DataSizeOfVariable (CacheVariable->CurrPtr));\r
 \r
         //\r
         // Set Max Common/Auth Variable Data Size as default MaxDataSize.\r
@@ -2361,15 +2361,15 @@ UpdateVariable (
           MaxDataSize = PcdGet32 (PcdMaxHardwareErrorVariableSize) - DataOffset;\r
         }\r
 \r
-        if (DataSizeOfVariable (Variable->CurrPtr) + DataSize > MaxDataSize) {\r
+        if (DataSizeOfVariable (CacheVariable->CurrPtr) + DataSize > MaxDataSize) {\r
           //\r
           // Existing data size + new data size exceed maximum variable size limitation.\r
           //\r
           Status = EFI_INVALID_PARAMETER;\r
           goto Done;\r
         }\r
-        CopyMem ((UINT8*) ((UINTN) BufferForMerge + DataSizeOfVariable (Variable->CurrPtr)), Data, DataSize);\r
-        MergedBufSize = DataSizeOfVariable (Variable->CurrPtr) + DataSize;\r
+        CopyMem ((UINT8*) ((UINTN) BufferForMerge + DataSizeOfVariable (CacheVariable->CurrPtr)), Data, DataSize);\r
+        MergedBufSize = DataSizeOfVariable (CacheVariable->CurrPtr) + DataSize;\r
 \r
         //\r
         // BufferForMerge(from DataOffset of NextVariable) has included the merged existing and new data.\r
@@ -2382,7 +2382,7 @@ UpdateVariable (
       //\r
       // Mark the old variable as in delete transition.\r
       //\r
-      State = Variable->CurrPtr->State;\r
+      State = CacheVariable->CurrPtr->State;\r
       State &= VAR_IN_DELETED_TRANSITION;\r
 \r
       Status = UpdateVariableStore (\r
@@ -2456,7 +2456,7 @@ UpdateVariable (
         // with the variable, we need associate the new timestamp with the updated value.\r
         //\r
         if (Variable->CurrPtr != NULL) {\r
-          if (VariableCompareTimeStampInternal (&(((AUTHENTICATED_VARIABLE_HEADER *) Variable->CurrPtr)->TimeStamp), TimeStamp)) {\r
+          if (VariableCompareTimeStampInternal (&(((AUTHENTICATED_VARIABLE_HEADER *) CacheVariable->CurrPtr)->TimeStamp), TimeStamp)) {\r
             CopyMem (&AuthVariable->TimeStamp, TimeStamp, sizeof (EFI_TIME));\r
           }\r
         }\r
@@ -2712,7 +2712,8 @@ UpdateVariable (
       // Both ADDED and IN_DELETED_TRANSITION old variable are present,\r
       // set IN_DELETED_TRANSITION one to DELETED state first.\r
       //\r
-      State = Variable->InDeletedTransitionPtr->State;\r
+      ASSERT (CacheVariable->InDeletedTransitionPtr != NULL);\r
+      State = CacheVariable->InDeletedTransitionPtr->State;\r
       State &= VAR_DELETED;\r
       Status = UpdateVariableStore (\r
                  &mVariableModuleGlobal->VariableGlobal,\r
@@ -2725,7 +2726,6 @@ UpdateVariable (
                  );\r
       if (!EFI_ERROR (Status)) {\r
         if (!Variable->Volatile) {\r
-          ASSERT (CacheVariable->InDeletedTransitionPtr != NULL);\r
           CacheVariable->InDeletedTransitionPtr->State = State;\r
         }\r
       } else {\r
@@ -2774,7 +2774,8 @@ Done:
   @param Attributes                 Attribute value of the variable found.\r
   @param DataSize                   Size of Data found. If size is less than the\r
                                     data, this value contains the required size.\r
-  @param Data                       Data pointer.\r
+  @param Data                       The buffer to return the contents of the variable. May be NULL\r
+                                    with a zero DataSize in order to determine the size buffer needed.\r
 \r
   @return EFI_INVALID_PARAMETER     Invalid parameter.\r
   @return EFI_SUCCESS               Find the specified variable.\r
@@ -2789,7 +2790,7 @@ VariableServiceGetVariable (
   IN      EFI_GUID          *VendorGuid,\r
   OUT     UINT32            *Attributes OPTIONAL,\r
   IN OUT  UINTN             *DataSize,\r
-  OUT     VOID              *Data\r
+  OUT     VOID              *Data OPTIONAL\r
   )\r
 {\r
   EFI_STATUS              Status;\r
@@ -2800,6 +2801,10 @@ VariableServiceGetVariable (
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
+  if (VariableName[0] == 0) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
   AcquireLockOnlyAtBootTime(&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);\r
 \r
   Status = FindVariable (VariableName, VendorGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);\r
@@ -2850,8 +2855,11 @@ Done:
   @param[in]  VendorGuid    Variable Vendor Guid.\r
   @param[out] VariablePtr   Pointer to variable header address.\r
 \r
-  @return EFI_SUCCESS       Find the specified variable.\r
-  @return EFI_NOT_FOUND     Not found.\r
+  @retval EFI_SUCCESS           The function completed successfully.\r
+  @retval EFI_NOT_FOUND         The next variable was not found.\r
+  @retval EFI_INVALID_PARAMETER If VariableName is not an empty string, while VendorGuid is NULL.\r
+  @retval EFI_INVALID_PARAMETER The input values of VariableName and VendorGuid are not a name and\r
+                                GUID of an existing variable.\r
 \r
 **/\r
 EFI_STATUS\r
@@ -2871,6 +2879,19 @@ VariableServiceGetNextVariableInternal (
 \r
   Status = FindVariable (VariableName, VendorGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);\r
   if (Variable.CurrPtr == NULL || EFI_ERROR (Status)) {\r
+    //\r
+    // For VariableName is an empty string, FindVariable() will try to find and return\r
+    // the first qualified variable, and if FindVariable() returns error (EFI_NOT_FOUND)\r
+    // as no any variable is found, still go to return the error (EFI_NOT_FOUND).\r
+    //\r
+    if (VariableName[0] != 0) {\r
+      //\r
+      // For VariableName is not an empty string, and FindVariable() returns error as\r
+      // VariableName and VendorGuid are not a name and GUID of an existing variable,\r
+      // there is no way to get next variable, follow spec to return EFI_INVALID_PARAMETER.\r
+      //\r
+      Status = EFI_INVALID_PARAMETER;\r
+    }\r
     goto Done;\r
   }\r
 \r
@@ -2991,14 +3012,22 @@ Done:
   Caution: This function may receive untrusted input.\r
   This function may be invoked in SMM mode. This function will do basic validation, before parse the data.\r
 \r
-  @param VariableNameSize           Size of the variable name.\r
+  @param VariableNameSize           The size of the VariableName buffer. The size must be large\r
+                                    enough to fit input string supplied in VariableName buffer.\r
   @param VariableName               Pointer to variable name.\r
   @param VendorGuid                 Variable Vendor Guid.\r
 \r
-  @return EFI_INVALID_PARAMETER     Invalid parameter.\r
-  @return EFI_SUCCESS               Find the specified variable.\r
-  @return EFI_NOT_FOUND             Not found.\r
-  @return EFI_BUFFER_TO_SMALL       DataSize is too small for the result.\r
+  @retval EFI_SUCCESS               The function completed successfully.\r
+  @retval EFI_NOT_FOUND             The next variable was not found.\r
+  @retval EFI_BUFFER_TOO_SMALL      The VariableNameSize is too small for the result.\r
+                                    VariableNameSize has been updated with the size needed to complete the request.\r
+  @retval EFI_INVALID_PARAMETER     VariableNameSize is NULL.\r
+  @retval EFI_INVALID_PARAMETER     VariableName is NULL.\r
+  @retval EFI_INVALID_PARAMETER     VendorGuid is NULL.\r
+  @retval EFI_INVALID_PARAMETER     The input values of VariableName and VendorGuid are not a name and\r
+                                    GUID of an existing variable.\r
+  @retval EFI_INVALID_PARAMETER     Null-terminator is not found in the first VariableNameSize bytes of\r
+                                    the input VariableName buffer.\r
 \r
 **/\r
 EFI_STATUS\r
@@ -3010,6 +3039,7 @@ VariableServiceGetNextVariableName (
   )\r
 {\r
   EFI_STATUS              Status;\r
+  UINTN                   MaxLen;\r
   UINTN                   VarNameSize;\r
   VARIABLE_HEADER         *VariablePtr;\r
 \r
@@ -3017,6 +3047,18 @@ VariableServiceGetNextVariableName (
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
+  //\r
+  // Calculate the possible maximum length of name string, including the Null terminator.\r
+  //\r
+  MaxLen = *VariableNameSize / sizeof (CHAR16);\r
+  if ((MaxLen == 0) || (StrnLenS (VariableName, MaxLen) == MaxLen)) {\r
+    //\r
+    // Null-terminator is not found in the first VariableNameSize bytes of the input VariableName buffer,\r
+    // follow spec to return EFI_INVALID_PARAMETER.\r
+    //\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
   AcquireLockOnlyAtBootTime(&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);\r
 \r
   Status = VariableServiceGetNextVariableInternal (VariableName, VendorGuid, &VariablePtr);\r
@@ -3092,8 +3134,11 @@ VariableServiceSetVariable (
 \r
   //\r
   // Check for reserverd bit in variable attribute.\r
+  // EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS is deprecated but we still allow\r
+  // the delete operation of common authenticated variable at user physical presence.\r
+  // So leave EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS attribute check to AuthVariableLib\r
   //\r
-  if ((Attributes & (~EFI_VARIABLE_ATTRIBUTES_MASK)) != 0) {\r
+  if ((Attributes & (~(EFI_VARIABLE_ATTRIBUTES_MASK | EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS))) != 0) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
@@ -3101,7 +3146,11 @@ VariableServiceSetVariable (
   //  Make sure if runtime bit is set, boot service bit is set also.\r
   //\r
   if ((Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == EFI_VARIABLE_RUNTIME_ACCESS) {\r
-    return EFI_INVALID_PARAMETER;\r
+    if ((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) != 0) {\r
+      return EFI_UNSUPPORTED;\r
+    } else {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
   } else if ((Attributes & VARIABLE_ATTRIBUTE_AT_AW) != 0) {\r
     if (!mVariableModuleGlobal->VariableGlobal.AuthSupport) {\r
       //\r
@@ -3124,15 +3173,16 @@ VariableServiceSetVariable (
   //\r
   if (((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) == EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS)\r
      && ((Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) == EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS)) {\r
-    return EFI_INVALID_PARAMETER;\r
+    return EFI_UNSUPPORTED;\r
   }\r
 \r
   if ((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) == EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) {\r
-    if (DataSize < AUTHINFO_SIZE) {\r
-      //\r
-      // Try to write Authenticated Variable without AuthInfo.\r
-      //\r
-      return EFI_SECURITY_VIOLATION;\r
+    //\r
+    //  If DataSize == AUTHINFO_SIZE and then PayloadSize is 0.\r
+    //  Maybe it's the delete operation of common authenticated variable at user physical presence.\r
+    //\r
+    if (DataSize != AUTHINFO_SIZE) {\r
+      return EFI_UNSUPPORTED;\r
     }\r
     PayloadSize = DataSize - AUTHINFO_SIZE;\r
   } else if ((Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) == EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) {\r
@@ -3181,6 +3231,21 @@ VariableServiceSetVariable (
     }\r
   }\r
 \r
+  //\r
+  // Special Handling for MOR Lock variable.\r
+  //\r
+  Status = SetVariableCheckHandlerMor (VariableName, VendorGuid, Attributes, PayloadSize, (VOID *) ((UINTN) Data + DataSize - PayloadSize));\r
+  if (Status == EFI_ALREADY_STARTED) {\r
+    //\r
+    // EFI_ALREADY_STARTED means the SetVariable() action is handled inside of SetVariableCheckHandlerMor().\r
+    // Variable driver can just return SUCCESS.\r
+    //\r
+    return EFI_SUCCESS;\r
+  }\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
   Status = VarCheckLibSetVariableCheck (VariableName, VendorGuid, Attributes, PayloadSize, (VOID *) ((UINTN) Data + DataSize - PayloadSize), mRequestSource);\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
@@ -3463,6 +3528,13 @@ VariableServiceQueryVariableInfo (
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
+  if ((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) != 0) {\r
+    //\r
+    //  Deprecated attribute, make this check as highest priority.\r
+    //\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
   if ((Attributes & EFI_VARIABLE_ATTRIBUTES_MASK) == 0) {\r
     //\r
     // Make sure the Attributes combination is supported by the platform.\r
@@ -3616,6 +3688,8 @@ InitNonVolatileVariableStore (
   UINT32                                HwErrStorageSize;\r
   UINT32                                MaxUserNvVariableSpaceSize;\r
   UINT32                                BoottimeReservedNvVariableSpaceSize;\r
+  EFI_STATUS                            Status;\r
+  VOID                                  *FtwProtocol;\r
 \r
   mVariableModuleGlobal->FvbInstance = NULL;\r
 \r
@@ -3638,30 +3712,36 @@ InitNonVolatileVariableStore (
   //\r
   CopyMem (NvStorageData, (UINT8 *) (UINTN) NvStorageBase, NvStorageSize);\r
 \r
+  Status = GetFtwProtocol ((VOID **)&FtwProtocol);\r
   //\r
-  // Check the FTW last write data hob.\r
+  // If FTW protocol has been installed, no need to check FTW last write data hob.\r
   //\r
-  GuidHob = GetFirstGuidHob (&gEdkiiFaultTolerantWriteGuid);\r
-  if (GuidHob != NULL) {\r
-    FtwLastWriteData = (FAULT_TOLERANT_WRITE_LAST_WRITE_DATA *) GET_GUID_HOB_DATA (GuidHob);\r
-    if (FtwLastWriteData->TargetAddress == NvStorageBase) {\r
-      DEBUG ((EFI_D_INFO, "Variable: NV storage is backed up in spare block: 0x%x\n", (UINTN) FtwLastWriteData->SpareAddress));\r
-      //\r
-      // Copy the backed up NV storage data to the memory buffer from spare block.\r
-      //\r
-      CopyMem (NvStorageData, (UINT8 *) (UINTN) (FtwLastWriteData->SpareAddress), NvStorageSize);\r
-    } else if ((FtwLastWriteData->TargetAddress > NvStorageBase) &&\r
-               (FtwLastWriteData->TargetAddress < (NvStorageBase + NvStorageSize))) {\r
-      //\r
-      // Flash NV storage from the Offset is backed up in spare block.\r
-      //\r
-      BackUpOffset = (UINT32) (FtwLastWriteData->TargetAddress - NvStorageBase);\r
-      BackUpSize = NvStorageSize - BackUpOffset;\r
-      DEBUG ((EFI_D_INFO, "Variable: High partial NV storage from offset: %x is backed up in spare block: 0x%x\n", BackUpOffset, (UINTN) FtwLastWriteData->SpareAddress));\r
-      //\r
-      // Copy the partial backed up NV storage data to the memory buffer from spare block.\r
-      //\r
-      CopyMem (NvStorageData + BackUpOffset, (UINT8 *) (UINTN) FtwLastWriteData->SpareAddress, BackUpSize);\r
+  if (EFI_ERROR (Status)) {\r
+    //\r
+    // Check the FTW last write data hob.\r
+    //\r
+    GuidHob = GetFirstGuidHob (&gEdkiiFaultTolerantWriteGuid);\r
+    if (GuidHob != NULL) {\r
+      FtwLastWriteData = (FAULT_TOLERANT_WRITE_LAST_WRITE_DATA *) GET_GUID_HOB_DATA (GuidHob);\r
+      if (FtwLastWriteData->TargetAddress == NvStorageBase) {\r
+        DEBUG ((EFI_D_INFO, "Variable: NV storage is backed up in spare block: 0x%x\n", (UINTN) FtwLastWriteData->SpareAddress));\r
+        //\r
+        // Copy the backed up NV storage data to the memory buffer from spare block.\r
+        //\r
+        CopyMem (NvStorageData, (UINT8 *) (UINTN) (FtwLastWriteData->SpareAddress), NvStorageSize);\r
+      } else if ((FtwLastWriteData->TargetAddress > NvStorageBase) &&\r
+                 (FtwLastWriteData->TargetAddress < (NvStorageBase + NvStorageSize))) {\r
+        //\r
+        // Flash NV storage from the Offset is backed up in spare block.\r
+        //\r
+        BackUpOffset = (UINT32) (FtwLastWriteData->TargetAddress - NvStorageBase);\r
+        BackUpSize = NvStorageSize - BackUpOffset;\r
+        DEBUG ((EFI_D_INFO, "Variable: High partial NV storage from offset: %x is backed up in spare block: 0x%x\n", BackUpOffset, (UINTN) FtwLastWriteData->SpareAddress));\r
+        //\r
+        // Copy the partial backed up NV storage data to the memory buffer from spare block.\r
+        //\r
+        CopyMem (NvStorageData + BackUpOffset, (UINT8 *) (UINTN) FtwLastWriteData->SpareAddress, BackUpSize);\r
+      }\r
     }\r
   }\r
 \r
@@ -3676,13 +3756,16 @@ InitNonVolatileVariableStore (
     return EFI_VOLUME_CORRUPTED;\r
   }\r
 \r
-  VariableStoreBase = (EFI_PHYSICAL_ADDRESS) ((UINTN) FvHeader + FvHeader->HeaderLength);\r
-  VariableStoreLength = (UINT64) (NvStorageSize - FvHeader->HeaderLength);\r
+  VariableStoreBase = (UINTN) FvHeader + FvHeader->HeaderLength;\r
+  VariableStoreLength = NvStorageSize - FvHeader->HeaderLength;\r
 \r
+  mNvFvHeaderCache = FvHeader;\r
   mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase = VariableStoreBase;\r
   mNvVariableCache = (VARIABLE_STORE_HEADER *) (UINTN) VariableStoreBase;\r
   if (GetVariableStoreStatus (mNvVariableCache) != EfiValid) {\r
     FreePool (NvStorageData);\r
+    mNvFvHeaderCache = NULL;\r
+    mNvVariableCache = NULL;\r
     DEBUG((EFI_D_ERROR, "Variable Store header is corrupted\n"));\r
     return EFI_VOLUME_CORRUPTED;\r
   }\r
@@ -3858,7 +3941,6 @@ VariableWriteServiceInitialize (
   )\r
 {\r
   EFI_STATUS                      Status;\r
-  VARIABLE_STORE_HEADER           *VariableStoreHeader;\r
   UINTN                           Index;\r
   UINT8                           Data;\r
   EFI_PHYSICAL_ADDRESS            VariableStoreBase;\r
@@ -3871,18 +3953,17 @@ VariableWriteServiceInitialize (
   if (NvStorageBase == 0) {\r
     NvStorageBase = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashNvStorageVariableBase);\r
   }\r
-  VariableStoreBase = NvStorageBase + (((EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)(NvStorageBase))->HeaderLength);\r
+  VariableStoreBase = NvStorageBase + (mNvFvHeaderCache->HeaderLength);\r
 \r
   //\r
   // Let NonVolatileVariableBase point to flash variable store base directly after FTW ready.\r
   //\r
   mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase = VariableStoreBase;\r
-  VariableStoreHeader = (VARIABLE_STORE_HEADER *)(UINTN)VariableStoreBase;\r
 \r
   //\r
   // Check if the free area is really free.\r
   //\r
-  for (Index = mVariableModuleGlobal->NonVolatileLastVariableOffset; Index < VariableStoreHeader->Size; Index++) {\r
+  for (Index = mVariableModuleGlobal->NonVolatileLastVariableOffset; Index < mNvVariableCache->Size; Index++) {\r
     Data = ((UINT8 *) mNvVariableCache)[Index];\r
     if (Data != 0xff) {\r
       //\r
@@ -3938,7 +4019,7 @@ VariableWriteServiceInitialize (
   }\r
 \r
   if (!EFI_ERROR (Status)) {\r
-    for (Index = 0; Index < sizeof (mVariableEntryProperty) / sizeof (mVariableEntryProperty[0]); Index++) {\r
+    for (Index = 0; Index < ARRAY_SIZE (mVariableEntryProperty); Index++) {\r
       VariableEntry = &mVariableEntryProperty[Index];\r
       Status = VarCheckLibVariablePropertySet (VariableEntry->Name, VariableEntry->Guid, &VariableEntry->VariableProperty);\r
       ASSERT_EFI_ERROR (Status);\r
@@ -3946,10 +4027,114 @@ VariableWriteServiceInitialize (
   }\r
 \r
   ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);\r
+\r
+  //\r
+  // Initialize MOR Lock variable.\r
+  //\r
+  MorLockInit ();\r
+\r
   return Status;\r
 }\r
 \r
+/**\r
+  Convert normal variable storage to the allocated auth variable storage.\r
+\r
+  @param[in]  NormalVarStorage  Pointer to the normal variable storage header\r
+\r
+  @retval the allocated auth variable storage\r
+**/\r
+VOID *\r
+ConvertNormalVarStorageToAuthVarStorage (\r
+  VARIABLE_STORE_HEADER *NormalVarStorage\r
+  )\r
+{\r
+  VARIABLE_HEADER *StartPtr;\r
+  UINT8           *NextPtr;\r
+  VARIABLE_HEADER *EndPtr;\r
+  UINTN           AuthVarStroageSize;\r
+  AUTHENTICATED_VARIABLE_HEADER *AuthStartPtr;\r
+  VARIABLE_STORE_HEADER         *AuthVarStorage;\r
+\r
+  AuthVarStroageSize  = sizeof (VARIABLE_STORE_HEADER);\r
+  //\r
+  // Set AuthFormat as FALSE for normal variable storage\r
+  //\r
+  mVariableModuleGlobal->VariableGlobal.AuthFormat = FALSE;\r
+\r
+  //\r
+  // Calculate Auth Variable Storage Size\r
+  //\r
+  StartPtr = GetStartPointer (NormalVarStorage);\r
+  EndPtr   = GetEndPointer (NormalVarStorage);\r
+  while (StartPtr < EndPtr) {\r
+    if (StartPtr->State == VAR_ADDED) {\r
+      AuthVarStroageSize = HEADER_ALIGN (AuthVarStroageSize);\r
+      AuthVarStroageSize += sizeof (AUTHENTICATED_VARIABLE_HEADER);\r
+      AuthVarStroageSize += StartPtr->NameSize + GET_PAD_SIZE (StartPtr->NameSize);\r
+      AuthVarStroageSize += StartPtr->DataSize + GET_PAD_SIZE (StartPtr->DataSize);\r
+    }\r
+    StartPtr  = GetNextVariablePtr (StartPtr);\r
+  }\r
+\r
+  //\r
+  // Allocate Runtime memory for Auth Variable Storage\r
+  //\r
+  AuthVarStorage = AllocateRuntimeZeroPool (AuthVarStroageSize);\r
+  ASSERT (AuthVarStorage != NULL);\r
+  if (AuthVarStorage == NULL) {\r
+    return NULL;\r
+  }\r
 \r
+  //\r
+  // Copy Variable from Normal storage to Auth storage\r
+  //\r
+  StartPtr = GetStartPointer (NormalVarStorage);\r
+  EndPtr   = GetEndPointer (NormalVarStorage);\r
+  AuthStartPtr = (AUTHENTICATED_VARIABLE_HEADER *) GetStartPointer (AuthVarStorage);\r
+  while (StartPtr < EndPtr) {\r
+    if (StartPtr->State == VAR_ADDED) {\r
+      AuthStartPtr = (AUTHENTICATED_VARIABLE_HEADER *) HEADER_ALIGN (AuthStartPtr);\r
+      //\r
+      // Copy Variable Header\r
+      //\r
+      AuthStartPtr->StartId     = StartPtr->StartId;\r
+      AuthStartPtr->State       = StartPtr->State;\r
+      AuthStartPtr->Attributes  = StartPtr->Attributes;\r
+      AuthStartPtr->NameSize    = StartPtr->NameSize;\r
+      AuthStartPtr->DataSize    = StartPtr->DataSize;\r
+      CopyGuid (&AuthStartPtr->VendorGuid, &StartPtr->VendorGuid);\r
+      //\r
+      // Copy Variable Name\r
+      //\r
+      NextPtr = (UINT8 *) (AuthStartPtr + 1);\r
+      CopyMem (NextPtr, GetVariableNamePtr (StartPtr), AuthStartPtr->NameSize);\r
+      //\r
+      // Copy Variable Data\r
+      //\r
+      NextPtr = NextPtr + AuthStartPtr->NameSize + GET_PAD_SIZE (AuthStartPtr->NameSize);\r
+      CopyMem (NextPtr, GetVariableDataPtr (StartPtr), AuthStartPtr->DataSize);\r
+      //\r
+      // Go to next variable\r
+      //\r
+      AuthStartPtr = (AUTHENTICATED_VARIABLE_HEADER *) (NextPtr + AuthStartPtr->DataSize + GET_PAD_SIZE (AuthStartPtr->DataSize));\r
+    }\r
+    StartPtr = GetNextVariablePtr (StartPtr);\r
+  }\r
+  //\r
+  // Update Auth Storage Header\r
+  //\r
+  AuthVarStorage->Format = NormalVarStorage->Format;\r
+  AuthVarStorage->State  = NormalVarStorage->State;\r
+  AuthVarStorage->Size = (UINT32) (UINTN) ((UINT8 *) AuthStartPtr - (UINT8 *) AuthVarStorage);\r
+  CopyGuid (&AuthVarStorage->Signature, &gEfiAuthenticatedVariableGuid);\r
+  ASSERT (AuthVarStorage->Size <= AuthVarStroageSize);\r
+\r
+  //\r
+  // Restore AuthFormat\r
+  //\r
+  mVariableModuleGlobal->VariableGlobal.AuthFormat = TRUE;\r
+  return AuthVarStorage;\r
+}\r
 /**\r
   Initializes variable store area for non-volatile and volatile variable.\r
 \r
@@ -3970,6 +4155,7 @@ VariableCommonInitialize (
   EFI_HOB_GUID_TYPE               *GuidHob;\r
   EFI_GUID                        *VariableGuid;\r
   EFI_FIRMWARE_VOLUME_HEADER      *NvFvHeader;\r
+  BOOLEAN                         IsNormalVariableHob;\r
 \r
   //\r
   // Allocate runtime memory for variable driver global structure.\r
@@ -4011,12 +4197,24 @@ VariableCommonInitialize (
   //\r
   // Get HOB variable store.\r
   //\r
+  IsNormalVariableHob = FALSE;\r
   GuidHob = GetFirstGuidHob (VariableGuid);\r
+  if (GuidHob == NULL && VariableGuid == &gEfiAuthenticatedVariableGuid) {\r
+    //\r
+    // Try getting it from normal variable HOB\r
+    //\r
+    GuidHob = GetFirstGuidHob (&gEfiVariableGuid);\r
+    IsNormalVariableHob = TRUE;\r
+  }\r
   if (GuidHob != NULL) {\r
     VariableStoreHeader = GET_GUID_HOB_DATA (GuidHob);\r
-    VariableStoreLength = (UINT64) (GuidHob->Header.HobLength - sizeof (EFI_HOB_GUID_TYPE));\r
+    VariableStoreLength = GuidHob->Header.HobLength - sizeof (EFI_HOB_GUID_TYPE);\r
     if (GetVariableStoreStatus (VariableStoreHeader) == EfiValid) {\r
-      mVariableModuleGlobal->VariableGlobal.HobVariableBase = (EFI_PHYSICAL_ADDRESS) (UINTN) AllocateRuntimeCopyPool ((UINTN) VariableStoreLength, (VOID *) VariableStoreHeader);\r
+      if (IsNormalVariableHob == FALSE) {\r
+        mVariableModuleGlobal->VariableGlobal.HobVariableBase = (EFI_PHYSICAL_ADDRESS) (UINTN) AllocateRuntimeCopyPool ((UINTN) VariableStoreLength, (VOID *) VariableStoreHeader);\r
+      } else {\r
+        mVariableModuleGlobal->VariableGlobal.HobVariableBase = (EFI_PHYSICAL_ADDRESS) (UINTN) ConvertNormalVarStorageToAuthVarStorage ((VOID *) VariableStoreHeader);\r
+      }\r
       if (mVariableModuleGlobal->VariableGlobal.HobVariableBase == 0) {\r
         FreePool (NvFvHeader);\r
         FreePool (mVariableModuleGlobal);\r