]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c
Fix an K9 issue in variable driver.
[mirror_edk2.git] / MdeModulePkg / Universal / Variable / RuntimeDxe / Variable.c
index dca3e30370e1a8993efb205f6aa12c31a5e88e30..52419f07967d2e86442bebfba0c838d68c55bc56 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
 \r
-  Implement all four UEFI Runtime Variable services for the nonvolatile\r
-  and volatile storage space and install variable architecture protocol.\r
+  The common variable operation routines shared by DXE_RINTIME variable \r
+  module and DXE_SMM variable module.\r
   \r
 Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>\r
 This program and the accompanying materials                          \r
@@ -17,110 +17,16 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include "Variable.h"\r
 \r
 VARIABLE_MODULE_GLOBAL  *mVariableModuleGlobal;\r
-EFI_EVENT   mVirtualAddressChangeEvent = NULL;\r
-EFI_HANDLE  mHandle = NULL;\r
 \r
 ///\r
-/// The current Hii implementation accesses this variable many times on every boot.\r
-/// Other common variables are only accessed once. This is why this cache algorithm\r
-/// only targets a single variable. Probably to get an performance improvement out of\r
-/// a Cache you would need a cache that improves the search performance for a variable.\r
+/// Define a memory cache that improves the search performance for a variable.\r
 ///\r
-VARIABLE_CACHE_ENTRY mVariableCache[] = {\r
-  {\r
-    &gEfiGlobalVariableGuid,\r
-    L"Lang",\r
-    0x00000000,\r
-    0x00,\r
-    NULL\r
-  },\r
-  {\r
-    &gEfiGlobalVariableGuid,\r
-    L"PlatformLang",\r
-    0x00000000,\r
-    0x00,\r
-    NULL\r
-  }\r
-};\r
-\r
-VARIABLE_INFO_ENTRY *gVariableInfo      = NULL;\r
-EFI_EVENT           mFvbRegistration    = NULL;\r
-\r
-/**\r
-  Update the variable region with Variable information. These are the same \r
-  arguments as the EFI Variable services.\r
-\r
-  @param[in] VariableName       Name of variable\r
-\r
-  @param[in] VendorGuid         Guid of variable\r
-\r
-  @param[in] Data               Variable data\r
-\r
-  @param[in] DataSize           Size of data. 0 means delete\r
-\r
-  @param[in] Attributes              Attribues of the variable\r
-\r
-  @param[in] Variable           The variable information which is used to keep track of variable usage.\r
-\r
-  @retval EFI_SUCCESS           The update operation is success.\r
-\r
-  @retval EFI_OUT_OF_RESOURCES  Variable region is full, can not write other data into this region.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-UpdateVariable (\r
-  IN      CHAR16                 *VariableName,\r
-  IN      EFI_GUID               *VendorGuid,\r
-  IN      VOID                   *Data,\r
-  IN      UINTN                  DataSize,\r
-  IN      UINT32                 Attributes OPTIONAL,\r
-  IN      VARIABLE_POINTER_TRACK *Variable\r
-  );\r
-\r
-/**\r
-  Acquires lock only at boot time. Simply returns at runtime.\r
-\r
-  This is a temperary function which will be removed when\r
-  EfiAcquireLock() in UefiLib can handle the call in UEFI\r
-  Runtimer driver in RT phase.\r
-  It calls EfiAcquireLock() at boot time, and simply returns\r
-  at runtime.\r
+VARIABLE_STORE_HEADER  *mNvVariableCache = NULL;\r
 \r
-  @param  Lock         A pointer to the lock to acquire\r
-\r
-**/\r
-VOID\r
-AcquireLockOnlyAtBootTime (\r
-  IN EFI_LOCK  *Lock\r
-  )\r
-{\r
-  if (!EfiAtRuntime ()) {\r
-    EfiAcquireLock (Lock);\r
-  }\r
-}\r
-\r
-/**\r
-  Releases lock only at boot time. Simply returns at runtime.\r
-\r
-  This is a temperary function which will be removed when\r
-  EfiReleaseLock() in UefiLib can handle the call in UEFI\r
-  Runtimer driver in RT phase.\r
-  It calls EfiReleaseLock() at boot time, and simply returns\r
-  at runtime.\r
-\r
-  @param  Lock         A pointer to the lock to release\r
-\r
-**/\r
-VOID\r
-ReleaseLockOnlyAtBootTime (\r
-  IN EFI_LOCK  *Lock\r
-  )\r
-{\r
-  if (!EfiAtRuntime ()) {\r
-    EfiReleaseLock (Lock);\r
-  }\r
-}\r
+///\r
+/// The memory entry used for variable statistics data.\r
+///\r
+VARIABLE_INFO_ENTRY    *gVariableInfo    = NULL;\r
 \r
 \r
 /**\r
@@ -134,12 +40,12 @@ ReleaseLockOnlyAtBootTime (
   the transaction. Data is allocated by this routine, but never\r
   freed.\r
 \r
-  @param[in] VariableName   Name of the Variable to track\r
-  @param[in] VendorGuid     Guid of the Variable to track\r
-  @param[in] Volatile       TRUE if volatile FALSE if non-volatile\r
-  @param[in] Read           TRUE if GetVariable() was called\r
-  @param[in] Write          TRUE if SetVariable() was called\r
-  @param[in] Delete         TRUE if deleted via SetVariable()\r
+  @param[in] VariableName   Name of the Variable to track.\r
+  @param[in] VendorGuid     Guid of the Variable to track.\r
+  @param[in] Volatile       TRUE if volatile FALSE if non-volatile.\r
+  @param[in] Read           TRUE if GetVariable() was called.\r
+  @param[in] Write          TRUE if SetVariable() was called.\r
+  @param[in] Delete         TRUE if deleted via SetVariable().\r
   @param[in] Cache          TRUE for a cache hit.\r
 \r
 **/\r
@@ -158,15 +64,15 @@ UpdateVariableInfo (
 \r
   if (FeaturePcdGet (PcdVariableCollectStatistics)) {\r
 \r
-    if (EfiAtRuntime ()) {\r
-      // Don't collect statistics at runtime\r
+    if (AtRuntime ()) {\r
+      // Don't collect statistics at runtime.\r
       return;\r
     }\r
 \r
     if (gVariableInfo == NULL) {\r
       //\r
-      // on the first call allocate a entry and place a pointer to it in\r
-      // the EFI System Table\r
+      // On the first call allocate a entry and place a pointer to it in\r
+      // the EFI System Table.\r
       //\r
       gVariableInfo = AllocateZeroPool (sizeof (VARIABLE_INFO_ENTRY));\r
       ASSERT (gVariableInfo != NULL);\r
@@ -176,8 +82,6 @@ UpdateVariableInfo (
       ASSERT (gVariableInfo->Name != NULL);\r
       StrCpy (gVariableInfo->Name, VariableName);\r
       gVariableInfo->Volatile = Volatile;\r
-\r
-      gBS->InstallConfigurationTable (&gEfiVariableGuid, gVariableInfo);\r
     }\r
 \r
     \r
@@ -204,7 +108,7 @@ UpdateVariableInfo (
       if (Entry->Next == NULL) {\r
         //\r
         // If the entry is not in the table add it.\r
-        // Next iteration of the loop will fill in the data\r
+        // Next iteration of the loop will fill in the data.\r
         //\r
         Entry->Next = AllocateZeroPool (sizeof (VARIABLE_INFO_ENTRY));\r
         ASSERT (Entry->Next != NULL);\r
@@ -249,18 +153,18 @@ IsValidVariableHeader (
   This function writes data to the FWH at the correct LBA even if the LBAs\r
   are fragmented.\r
 \r
-  @param Global                  Pointer to VARAIBLE_GLOBAL structure\r
-  @param Volatile                Point out the Variable is Volatile or Non-Volatile\r
-  @param SetByIndex              TRUE if target pointer is given as index\r
-                                 FALSE if target pointer is absolute\r
-  @param Fvb                     Pointer to the writable FVB protocol\r
+  @param Global                  Pointer to VARAIBLE_GLOBAL structure.\r
+  @param Volatile                Point out the Variable is Volatile or Non-Volatile.\r
+  @param SetByIndex              TRUE if target pointer is given as index.\r
+                                 FALSE if target pointer is absolute.\r
+  @param Fvb                     Pointer to the writable FVB protocol.\r
   @param DataPtrIndex            Pointer to the Data from the end of VARIABLE_STORE_HEADER\r
-                                 structure\r
-  @param DataSize                Size of data to be written\r
-  @param Buffer                  Pointer to the buffer from which data is written\r
+                                 structure.\r
+  @param DataSize                Size of data to be written.\r
+  @param Buffer                  Pointer to the buffer from which data is written.\r
 \r
-  @retval EFI_INVALID_PARAMETER  Parameters not valid\r
-  @retval EFI_SUCCESS            Variable store successfully updated\r
+  @retval EFI_INVALID_PARAMETER  Parameters not valid.\r
+  @retval EFI_SUCCESS            Variable store successfully updated.\r
 \r
 **/\r
 EFI_STATUS\r
@@ -292,16 +196,17 @@ UpdateVariableStore (
   DataPtr     = DataPtrIndex;\r
 \r
   //\r
-  // Check if the Data is Volatile\r
+  // Check if the Data is Volatile.\r
   //\r
   if (!Volatile) {\r
+    ASSERT (Fvb != NULL);\r
     Status = Fvb->GetPhysicalAddress(Fvb, &FvVolHdr);\r
     ASSERT_EFI_ERROR (Status);\r
 \r
     FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) FvVolHdr);\r
     //\r
     // Data Pointer should point to the actual Address where data is to be\r
-    // written\r
+    // written.\r
     //\r
     if (SetByIndex) {\r
       DataPtr += mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase;\r
@@ -313,7 +218,7 @@ UpdateVariableStore (
   } else {\r
     //\r
     // Data Pointer should point to the actual Address where data is to be\r
-    // written\r
+    // written.\r
     //\r
     VolatileBase = (VARIABLE_STORE_HEADER *) ((UINTN) mVariableModuleGlobal->VariableGlobal.VolatileVariableBase);\r
     if (SetByIndex) {\r
@@ -332,7 +237,7 @@ UpdateVariableStore (
   }\r
   \r
   //\r
-  // If we are here we are dealing with Non-Volatile Variables\r
+  // If we are here we are dealing with Non-Volatile Variables.\r
   //\r
   LinearOffset  = (UINTN) FwVolHeader;\r
   CurrWritePtr  = (UINTN) DataPtr;\r
@@ -394,9 +299,9 @@ UpdateVariableStore (
 \r
   @param VarStoreHeader  Pointer to the Variable Store Header.\r
 \r
-  @retval EfiRaw         Variable store status is raw\r
-  @retval EfiValid       Variable store status is valid\r
-  @retval EfiInvalid     Variable store status is invalid\r
+  @retval EfiRaw         Variable store status is raw.\r
+  @retval EfiValid       Variable store status is valid.\r
+  @retval EfiInvalid     Variable store status is invalid.\r
 \r
 **/\r
 VARIABLE_STORE_STATUS\r
@@ -430,9 +335,9 @@ GetVariableStoreStatus (
 \r
   This code gets the size of name of variable.\r
 \r
-  @param Variable        Pointer to the Variable Header\r
+  @param Variable        Pointer to the Variable Header.\r
 \r
-  @return UINTN          Size of variable in bytes\r
+  @return UINTN          Size of variable in bytes.\r
 \r
 **/\r
 UINTN\r
@@ -453,9 +358,9 @@ NameSizeOfVariable (
 \r
   This code gets the size of variable data.\r
 \r
-  @param Variable        Pointer to the Variable Header\r
+  @param Variable        Pointer to the Variable Header.\r
 \r
-  @return Size of variable in bytes\r
+  @return Size of variable in bytes.\r
 \r
 **/\r
 UINTN\r
@@ -476,9 +381,9 @@ DataSizeOfVariable (
 \r
   This code gets the pointer to the variable name.\r
 \r
-  @param Variable        Pointer to the Variable Header\r
+  @param Variable        Pointer to the Variable Header.\r
 \r
-  @return Pointer to Variable Name which is Unicode encoding\r
+  @return Pointer to Variable Name which is Unicode encoding.\r
 \r
 **/\r
 CHAR16 *\r
@@ -494,9 +399,9 @@ GetVariableNamePtr (
 \r
   This code gets the pointer to the variable data.\r
 \r
-  @param Variable        Pointer to the Variable Header\r
+  @param Variable        Pointer to the Variable Header.\r
 \r
-  @return Pointer to Variable Data\r
+  @return Pointer to Variable Data.\r
 \r
 **/\r
 UINT8 *\r
@@ -507,7 +412,7 @@ GetVariableDataPtr (
   UINTN Value;\r
   \r
   //\r
-  // Be careful about pad size for alignment\r
+  // Be careful about pad size for alignment.\r
   //\r
   Value =  (UINTN) GetVariableNamePtr (Variable);\r
   Value += NameSizeOfVariable (Variable);\r
@@ -521,9 +426,9 @@ GetVariableDataPtr (
 \r
   This code gets the pointer to the next variable header.\r
 \r
-  @param Variable        Pointer to the Variable Header\r
+  @param Variable        Pointer to the Variable Header.\r
 \r
-  @return Pointer to next variable header\r
+  @return Pointer to next variable header.\r
 \r
 **/\r
 VARIABLE_HEADER *\r
@@ -542,7 +447,7 @@ GetNextVariablePtr (
   Value += GET_PAD_SIZE (DataSizeOfVariable (Variable));\r
 \r
   //\r
-  // Be careful about pad size for alignment\r
+  // Be careful about pad size for alignment.\r
   //\r
   return (VARIABLE_HEADER *) HEADER_ALIGN (Value);\r
 }\r
@@ -553,7 +458,7 @@ GetNextVariablePtr (
 \r
   @param VarStoreHeader  Pointer to the Variable Store Header.\r
 \r
-  @return Pointer to the first variable header\r
+  @return Pointer to the first variable header.\r
 \r
 **/\r
 VARIABLE_HEADER *\r
@@ -562,7 +467,7 @@ GetStartPointer (
   )\r
 {\r
   //\r
-  // The end of variable store\r
+  // The end of variable store.\r
   //\r
   return (VARIABLE_HEADER *) HEADER_ALIGN (VarStoreHeader + 1);\r
 }\r
@@ -574,9 +479,9 @@ GetStartPointer (
   This function gets pointer to the end of the variable storage\r
   area, according to the input variable store header.\r
 \r
-  @param VarStoreHeader  Pointer to the Variable Store Header\r
+  @param VarStoreHeader  Pointer to the Variable Store Header.\r
 \r
-  @return Pointer to the end of the variable storage area  \r
+  @return Pointer to the end of the variable storage area. \r
 \r
 **/\r
 VARIABLE_HEADER *\r
@@ -595,11 +500,11 @@ GetEndPointer (
 \r
   Variable store garbage collection and reclaim operation.\r
 \r
-  @param VariableBase            Base address of variable store\r
-  @param LastVariableOffset      Offset of last variable\r
-  @param IsVolatile              The variable store is volatile or not,\r
-                                 if it is non-volatile, need FTW\r
-  @param UpdatingVariable        Pointer to updateing variable.\r
+  @param VariableBase            Base address of variable store.\r
+  @param LastVariableOffset      Offset of last variable.\r
+  @param IsVolatile              The variable store is volatile or not;\r
+                                 if it is non-volatile, need FTW.\r
+  @param UpdatingVariable        Pointer to updating variable.\r
 \r
   @return EFI_OUT_OF_RESOURCES\r
   @return EFI_SUCCESS\r
@@ -635,7 +540,7 @@ Reclaim (
 \r
   VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINTN) VariableBase);\r
   //\r
-  // recaluate the total size of Common/HwErr type variables in non-volatile area.\r
+  // Recalculate the total size of Common/HwErr type variables in non-volatile area.\r
   //\r
   if (!IsVolatile) {\r
     mVariableModuleGlobal->CommonVariableTotalSize = 0;\r
@@ -673,13 +578,13 @@ Reclaim (
   SetMem (ValidBuffer, MaximumBufferSize, 0xff);\r
 \r
   //\r
-  // Copy variable store header\r
+  // Copy variable store header.\r
   //\r
   CopyMem (ValidBuffer, VariableStoreHeader, sizeof (VARIABLE_STORE_HEADER));\r
   CurrPtr = (UINT8 *) GetStartPointer ((VARIABLE_STORE_HEADER *) ValidBuffer);\r
 \r
   //\r
-  // Reinstall all ADDED variables as long as they are not identical to Updating Variable\r
+  // Reinstall all ADDED variables as long as they are not identical to Updating Variable.\r
   // \r
   Variable = GetStartPointer (VariableStoreHeader);\r
   while (IsValidVariableHeader (Variable)) {\r
@@ -716,7 +621,7 @@ Reclaim (
   }\r
 \r
   //\r
-  // Reinstall the variable being updated if it is not NULL\r
+  // Reinstall the variable being updated if it is not NULL.\r
   //\r
   if (UpdatingVariable != NULL) {\r
     VariableSize = (UINTN)(GetNextVariablePtr (UpdatingVariable)) - (UINTN)UpdatingVariable;\r
@@ -730,7 +635,7 @@ Reclaim (
   }\r
 \r
   //\r
-  // Reinstall all in delete transition variables\r
+  // Reinstall all in delete transition variables.\r
   // \r
   Variable      = GetStartPointer (VariableStoreHeader);\r
   while (IsValidVariableHeader (Variable)) {\r
@@ -762,7 +667,7 @@ Reclaim (
       }\r
       if (!FoundAdded) {\r
         //\r
-        // Promote VAR_IN_DELETED_TRANSITION to VAR_ADDED\r
+        // Promote VAR_IN_DELETED_TRANSITION to VAR_ADDED.\r
         //\r
         VariableSize = (UINTN) NextVariable - (UINTN) Variable;\r
         CopyMem (CurrPtr, (UINT8 *) Variable, VariableSize);\r
@@ -781,11 +686,11 @@ Reclaim (
 \r
   if (IsVolatile) {\r
     //\r
-    // If volatile variable store, just copy valid buffer\r
+    // 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 - (UINT8 *) ValidBuffer));\r
-    Status              = EFI_SUCCESS;\r
+    Status  = EFI_SUCCESS;\r
   } else {\r
     //\r
     // If non-volatile variable store, perform FTW here.\r
@@ -795,6 +700,7 @@ Reclaim (
               ValidBuffer,\r
               (UINTN) (CurrPtr - (UINT8 *) ValidBuffer)\r
               );\r
+    CopyMem (mNvVariableCache, (CHAR8 *)(UINTN)VariableBase, VariableStoreHeader->Size);\r
   }\r
   if (!EFI_ERROR (Status)) {\r
     *LastVariableOffset = (UINTN) (CurrPtr - (UINT8 *) ValidBuffer);\r
@@ -808,126 +714,6 @@ Reclaim (
 }\r
 \r
 \r
-/**\r
-  Update the Cache with Variable information. These are the same \r
-  arguments as the EFI Variable services.\r
-\r
-  @param[in] VariableName  Name of variable\r
-  @param[in] VendorGuid    Guid of variable\r
-  @param[in] Attributes    Attribues of the variable\r
-  @param[in] DataSize      Size of data. 0 means delete\r
-  @param[in] Data          Variable data\r
-\r
-**/\r
-VOID\r
-UpdateVariableCache (\r
-  IN      CHAR16            *VariableName,\r
-  IN      EFI_GUID          *VendorGuid,\r
-  IN      UINT32            Attributes,\r
-  IN      UINTN             DataSize,\r
-  IN      VOID              *Data\r
-  )\r
-{\r
-  VARIABLE_CACHE_ENTRY      *Entry;\r
-  UINTN                     Index;\r
-\r
-  if (EfiAtRuntime ()) {\r
-    //\r
-    // Don't use the cache at runtime\r
-    // \r
-    return;\r
-  }\r
-\r
-  for (Index = 0, Entry = mVariableCache; Index < sizeof (mVariableCache)/sizeof (VARIABLE_CACHE_ENTRY); Index++, Entry++) {\r
-    if (CompareGuid (VendorGuid, Entry->Guid)) {\r
-      if (StrCmp (VariableName, Entry->Name) == 0) { \r
-        Entry->Attributes = Attributes;\r
-        if (DataSize == 0) {\r
-          //\r
-          // Delete Case\r
-          //\r
-          if (Entry->DataSize != 0) {\r
-            FreePool (Entry->Data);\r
-          }\r
-          Entry->DataSize = DataSize;\r
-        } else if (DataSize == Entry->DataSize) {\r
-          CopyMem (Entry->Data, Data, DataSize);\r
-        } else {\r
-          Entry->Data = AllocatePool (DataSize);\r
-          ASSERT (Entry->Data != NULL);\r
-\r
-          Entry->DataSize = DataSize;\r
-          CopyMem (Entry->Data, Data, DataSize);\r
-        }\r
-      }\r
-    }\r
-  }\r
-}\r
-\r
-\r
-/**\r
-  Search the cache to check if the variable is in it.\r
-\r
-  This function searches the variable cache. If the variable to find exists, return its data\r
-  and attributes.\r
-\r
-  @param  VariableName          A Null-terminated Unicode string that is the name of the vendor's\r
-                                variable.  Each VariableName is unique for each \r
-                                VendorGuid.\r
-  @param  VendorGuid            A unique identifier for the vendor\r
-  @param  Attributes            Pointer to the attributes bitmask of the variable for output.\r
-  @param  DataSize              On input, size of the buffer of Data.\r
-                                On output, size of the variable's data.\r
-  @param  Data                  Pointer to the data buffer for output.\r
-\r
-  @retval EFI_SUCCESS           VariableGuid & VariableName data was returned.\r
-  @retval EFI_NOT_FOUND         No matching variable found in cache.\r
-  @retval EFI_BUFFER_TOO_SMALL  *DataSize is smaller than size of the variable's data to return.\r
-\r
-**/\r
-EFI_STATUS\r
-FindVariableInCache (\r
-  IN      CHAR16            *VariableName,\r
-  IN      EFI_GUID          *VendorGuid,\r
-  OUT     UINT32            *Attributes OPTIONAL,\r
-  IN OUT  UINTN             *DataSize,\r
-  OUT     VOID              *Data\r
-  )\r
-{\r
-  VARIABLE_CACHE_ENTRY      *Entry;\r
-  UINTN                     Index;\r
-\r
-  if (EfiAtRuntime ()) {\r
-    // Don't use the cache at runtime\r
-    return EFI_NOT_FOUND;\r
-  }\r
-\r
-  for (Index = 0, Entry = mVariableCache; Index < sizeof (mVariableCache)/sizeof (VARIABLE_CACHE_ENTRY); Index++, Entry++) {\r
-    if (CompareGuid (VendorGuid, Entry->Guid)) {\r
-      if (StrCmp (VariableName, Entry->Name) == 0) {\r
-        if (Entry->DataSize == 0) {\r
-          // Variable was deleted so return not found\r
-          return EFI_NOT_FOUND;\r
-        } else if (Entry->DataSize > *DataSize) {\r
-          // If the buffer is too small return correct size\r
-          *DataSize = Entry->DataSize;\r
-          return EFI_BUFFER_TOO_SMALL;\r
-        } else {\r
-          *DataSize = Entry->DataSize;\r
-          // Return the data\r
-          CopyMem (Data, Entry->Data, Entry->DataSize);\r
-          if (Attributes != NULL) {\r
-            *Attributes = Entry->Attributes;\r
-          }\r
-          return EFI_SUCCESS;\r
-        }\r
-      }\r
-    }\r
-  }\r
-  \r
-  return EFI_NOT_FOUND;\r
-}\r
-\r
 /**\r
   Finds variable in storage blocks of volatile and non-volatile storage areas.\r
 \r
@@ -936,7 +722,7 @@ FindVariableInCache (
   qualified variable without comparing VariableName and VendorGuid.\r
   Otherwise, VariableName and VendorGuid are compared.\r
 \r
-  @param  VariableName                Name of the variable to be found\r
+  @param  VariableName                Name of the variable to be found.\r
   @param  VendorGuid                  Vendor GUID to be found.\r
   @param  PtrTrack                    VARIABLE_POINTER_TRACK structure for output,\r
                                       including the range searched and the target position.\r
@@ -945,8 +731,8 @@ FindVariableInCache (
                                       NV variable storage area, and a lock.\r
 \r
   @retval EFI_INVALID_PARAMETER       If VariableName is not an empty string, while\r
-                                      VendorGuid is NULL\r
-  @retval EFI_SUCCESS                 Variable successfully found\r
+                                      VendorGuid is NULL.\r
+  @retval EFI_SUCCESS                 Variable successfully found.\r
   @retval EFI_NOT_FOUND               Variable not found\r
 \r
 **/\r
@@ -966,12 +752,12 @@ FindVariable (
   VOID                    *Point;\r
 \r
   //\r
-  // 0: Volatile, 1: Non-Volatile\r
+  // 0: Volatile, 1: Non-Volatile.\r
   // The index and attributes mapping must be kept in this order as RuntimeServiceGetNextVariableName\r
-  // make use of this mapping to implement search algorithme.\r
+  // make use of this mapping to implement search algorithm.\r
   //\r
   VariableStoreHeader[0]  = (VARIABLE_STORE_HEADER *) ((UINTN) mVariableModuleGlobal->VariableGlobal.VolatileVariableBase);\r
-  VariableStoreHeader[1]  = (VARIABLE_STORE_HEADER *) ((UINTN) mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase);\r
+  VariableStoreHeader[1]  = mNvVariableCache;\r
 \r
   //\r
   // Start Pointers for the variable.\r
@@ -985,7 +771,7 @@ FindVariable (
   }\r
 \r
   //\r
-  // Find the variable by walk through volatile and then non-volatile variable store\r
+  // Find the variable by walk through volatile and then non-volatile variable store.\r
   //\r
   InDeletedVariable     = NULL;\r
   InDeletedStorageIndex = 0;\r
@@ -994,7 +780,7 @@ FindVariable (
       if (Variable[Index]->State == VAR_ADDED || \r
           Variable[Index]->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)\r
          ) {\r
-        if (!EfiAtRuntime () || ((Variable[Index]->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) != 0)) {\r
+        if (!AtRuntime () || ((Variable[Index]->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) != 0)) {\r
           if (VariableName[0] == 0) {\r
             if (Variable[Index]->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {\r
               InDeletedVariable     = Variable[Index];\r
@@ -1067,7 +853,7 @@ FindVariable (
   @param  Lang                        Configured language.\r
   @param  Iso639Language              A bool value to signify if the handler is operated on ISO639 or RFC4646.\r
 \r
-  @retval the index of language in the language codes.\r
+  @retval The index of language in the language codes.\r
 \r
 **/\r
 UINTN\r
@@ -1127,7 +913,7 @@ GetIndexFromSupportedLangCodes(
 /**\r
   Get language string from supported language codes according to index.\r
 \r
-  This code is used to get corresponding language string in supported language codes. It can handle\r
+  This code is used to get corresponding language strings in supported language codes. It can handle\r
   RFC4646 and ISO639 language tags.\r
   In ISO639 language tags, take 3-characters as a delimitation. Find language string according to the index.\r
   In RFC4646 language tags, take semicolon as a delimitation. Find language string according to the index.\r
@@ -1144,10 +930,10 @@ GetIndexFromSupportedLangCodes(
   The return value is "fr".\r
 \r
   @param  SupportedLang               Platform supported language codes.\r
-  @param  Index                       the index in supported language codes.\r
+  @param  Index                       The index in supported language codes.\r
   @param  Iso639Language              A bool value to signify if the handler is operated on ISO639 or RFC4646.\r
 \r
-  @retval the language string in the language codes.\r
+  @retval The language string in the language codes.\r
 \r
 **/\r
 CHAR8 *\r
@@ -1165,18 +951,18 @@ GetLangFromSupportedLangCodes (
   Supported = SupportedLang;\r
   if (Iso639Language) {\r
     //\r
-    // according to the index of Lang string in SupportedLang string to get the language.\r
-    // As this code will be invoked in RUNTIME, therefore there is not memory allocate/free operation.\r
+    // According to the index of Lang string in SupportedLang string to get the language.\r
+    // This code will be invoked in RUNTIME, therefore there is not a memory allocate/free operation.\r
     // In driver entry, it pre-allocates a runtime attribute memory to accommodate this string.\r
     //\r
     CompareLength = ISO_639_2_ENTRY_SIZE;\r
     mVariableModuleGlobal->Lang[CompareLength] = '\0';\r
     return CopyMem (mVariableModuleGlobal->Lang, SupportedLang + Index * CompareLength, CompareLength);\r
-\r
+      \r
   } else {\r
     while (TRUE) {\r
       //\r
-      // take semicolon as delimitation, sequentially traverse supported language codes.\r
+      // Take semicolon as delimitation, sequentially traverse supported language codes.\r
       //\r
       for (CompareLength = 0; *Supported != ';' && *Supported != '\0'; CompareLength++) {\r
         Supported++;\r
@@ -1191,7 +977,7 @@ GetLangFromSupportedLangCodes (
       }\r
       if (SubIndex == Index) {\r
         //\r
-        // according to the index of Lang string in SupportedLang string to get the language.\r
+        // According to the index of Lang string in SupportedLang string to get the language.\r
         // As this code will be invoked in RUNTIME, therefore there is not memory allocate/free operation.\r
         // In driver entry, it pre-allocates a runtime attribute memory to accommodate this string.\r
         //\r
@@ -1199,7 +985,7 @@ GetLangFromSupportedLangCodes (
         return CopyMem (mVariableModuleGlobal->PlatformLang, Supported - CompareLength, CompareLength);\r
       }\r
       SubIndex++;\r
-      \r
+\r
       //\r
       // Skip ';' characters in Supported\r
       //\r
@@ -1347,11 +1133,11 @@ VariableGetBestLanguage (
   According to UEFI spec, PlatformLangCodes/LangCodes are only set once in firmware initialization,\r
   and are read-only. Therefore, in variable driver, only store the original value for other use.\r
 \r
-  @param[in] VariableName       Name of variable\r
+  @param[in] VariableName       Name of variable.\r
 \r
-  @param[in] Data               Variable data\r
+  @param[in] Data               Variable data.\r
 \r
-  @param[in] DataSize           Size of data. 0 means delete\r
+  @param[in] DataSize           Size of data. 0 means delete.\r
 \r
 **/\r
 VOID\r
@@ -1382,7 +1168,7 @@ AutoUpdateLangVariable(
     //\r
     // PlatformLangCodes is a volatile variable, so it can not be updated at runtime.\r
     //\r
-    if (EfiAtRuntime ()) {\r
+    if (AtRuntime ()) {\r
       return;\r
     }\r
 \r
@@ -1412,7 +1198,7 @@ AutoUpdateLangVariable(
     //\r
     // LangCodes is a volatile variable, so it can not be updated at runtime.\r
     //\r
-    if (EfiAtRuntime ()) {\r
+    if (AtRuntime ()) {\r
       return;\r
     }\r
 \r
@@ -1492,7 +1278,8 @@ AutoUpdateLangVariable(
         //\r
         FindVariable (L"Lang", &gEfiGlobalVariableGuid, &Variable, (VARIABLE_GLOBAL *)mVariableModuleGlobal);\r
 \r
-        Status = UpdateVariable (L"Lang", &gEfiGlobalVariableGuid, BestLang, ISO_639_2_ENTRY_SIZE + 1, Attributes, &Variable);\r
+        Status = UpdateVariable (L"Lang", &gEfiGlobalVariableGuid, BestLang,\r
+                                 ISO_639_2_ENTRY_SIZE + 1, Attributes, &Variable);\r
 \r
         DEBUG ((EFI_D_INFO, "Variable Driver Auto Update PlatformLang, PlatformLang:%a, Lang:%a\n", BestPlatformLang, BestLang));\r
 \r
@@ -1539,32 +1326,25 @@ AutoUpdateLangVariable(
   Update the variable region with Variable information. These are the same \r
   arguments as the EFI Variable services.\r
 \r
-  @param[in] VariableName       Name of variable\r
-\r
-  @param[in] VendorGuid         Guid of variable\r
-\r
-  @param[in] Data               Variable data\r
-\r
-  @param[in] DataSize           Size of data. 0 means delete\r
-\r
-  @param[in] Attributes         Attribues of the variable\r
-\r
-  @param[in] Variable           The variable information which is used to keep track of variable usage.\r
-\r
+  @param[in] VariableName       Name of variable.\r
+  @param[in] VendorGuid         Guid of variable.\r
+  @param[in] Data               Variable data.\r
+  @param[in] DataSize           Size of data. 0 means delete.\r
+  @param[in] Attributes         Attribues of the variable.\r
+  @param[in] CacheVariable      The variable information which is used to keep track of variable usage.\r
+  \r
   @retval EFI_SUCCESS           The update operation is success.\r
-\r
   @retval EFI_OUT_OF_RESOURCES  Variable region is full, can not write other data into this region.\r
 \r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
 UpdateVariable (\r
-  IN      CHAR16          *VariableName,\r
-  IN      EFI_GUID        *VendorGuid,\r
-  IN      VOID            *Data,\r
-  IN      UINTN           DataSize,\r
-  IN      UINT32          Attributes OPTIONAL,\r
-  IN      VARIABLE_POINTER_TRACK *Variable\r
+  IN      CHAR16                      *VariableName,\r
+  IN      EFI_GUID                    *VendorGuid,\r
+  IN      VOID                        *Data,\r
+  IN      UINTN                       DataSize,\r
+  IN      UINT32                      Attributes      OPTIONAL,\r
+  IN      VARIABLE_POINTER_TRACK      *CacheVariable\r
   )\r
 {\r
   EFI_STATUS                          Status;\r
@@ -1579,19 +1359,45 @@ UpdateVariable (
   EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  *Fvb;\r
   UINT8                               State;\r
   BOOLEAN                             Reclaimed;\r
+  VARIABLE_POINTER_TRACK              *Variable;\r
+  VARIABLE_POINTER_TRACK              NvVariable;\r
+  VARIABLE_STORE_HEADER               *VariableStoreHeader;\r
+  UINTN                               CacheOffset;\r
 \r
-  Fvb               = mVariableModuleGlobal->FvbInstance;\r
-  Reclaimed         = FALSE;\r
+  if ((mVariableModuleGlobal->FvbInstance == NULL) && ((Attributes & EFI_VARIABLE_NON_VOLATILE) != 0)) {\r
+    //\r
+    // The FVB protocol is not ready. Trying to update NV variable prior to the installation\r
+    // of EFI_VARIABLE_WRITE_ARCH_PROTOCOL.\r
+    //\r
+    return EFI_NOT_AVAILABLE_YET;     \r
+  }\r
+\r
+  if ((CacheVariable->CurrPtr == NULL) || CacheVariable->Volatile) {\r
+    Variable = CacheVariable;\r
+  } else {\r
+    //\r
+    // Update/Delete existing NV variable.\r
+    // CacheVariable points to the variable in the memory copy of Flash area\r
+    // Now let Variable points to the same variable in Flash area.\r
+    //\r
+    VariableStoreHeader  = (VARIABLE_STORE_HEADER *) ((UINTN) mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase);\r
+    Variable = &NvVariable;    \r
+    Variable->StartPtr = GetStartPointer (VariableStoreHeader);\r
+    Variable->EndPtr   = GetEndPointer (VariableStoreHeader);\r
+    Variable->CurrPtr  = (VARIABLE_HEADER *)((UINTN)Variable->StartPtr + ((UINTN)CacheVariable->CurrPtr - (UINTN)CacheVariable->StartPtr));\r
+    Variable->Volatile = FALSE;\r
+  } \r
+\r
+  Fvb       = mVariableModuleGlobal->FvbInstance;\r
+  Reclaimed = FALSE;\r
 \r
   if (Variable->CurrPtr != NULL) {\r
     //\r
-    // Update/Delete existing variable\r
+    // Update/Delete existing variable.\r
     //\r
-    Volatile = Variable->Volatile;\r
-    \r
-    if (EfiAtRuntime ()) {        \r
+    if (AtRuntime ()) {        \r
       //\r
-      // If EfiAtRuntime and the variable is Volatile and Runtime Access,  \r
+      // If AtRuntime and the variable is Volatile and Runtime Access,  \r
       // the volatile is ReadOnly, and SetVariable should be aborted and \r
       // return EFI_WRITE_PROTECTED.\r
       //\r
@@ -1600,16 +1406,17 @@ UpdateVariable (
         goto Done;\r
       }\r
       //\r
-      // Only variable have NV attribute can be updated/deleted in Runtime\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
         Status = EFI_INVALID_PARAMETER;\r
         goto Done;      \r
       }\r
     }\r
+\r
     //\r
     // Setting a data variable with no access, or zero DataSize attributes\r
-    // specified causes it to be deleted.\r
+    // causes it to be deleted.\r
     //\r
     if (DataSize == 0 || (Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == 0) {    \r
       State = Variable->CurrPtr->State;\r
@@ -1625,26 +1432,28 @@ UpdateVariable (
                  &State\r
                  ); \r
       if (!EFI_ERROR (Status)) {\r
-        UpdateVariableInfo (VariableName, VendorGuid, Volatile, FALSE, FALSE, TRUE, FALSE);\r
-        UpdateVariableCache (VariableName, VendorGuid, Attributes, DataSize, Data);\r
+        UpdateVariableInfo (VariableName, VendorGuid, Variable->Volatile, FALSE, FALSE, TRUE, FALSE);\r
+        if (!Variable->Volatile) {\r
+          CacheVariable->CurrPtr->State = State;\r
+        }\r
       }\r
       goto Done;     \r
     }\r
     //\r
-    // If the variable is marked valid and the same data has been passed in\r
+    // 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
       \r
-      UpdateVariableInfo (VariableName, VendorGuid, Volatile, FALSE, TRUE, FALSE, FALSE);\r
+      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
 \r
       //\r
-      // Mark the old variable as in delete transition\r
+      // Mark the old variable as in delete transition.\r
       //\r
       State = Variable->CurrPtr->State;\r
       State &= VAR_IN_DELETED_TRANSITION;\r
@@ -1661,15 +1470,18 @@ UpdateVariable (
       if (EFI_ERROR (Status)) {\r
         goto Done;  \r
       } \r
+      if (!Variable->Volatile) {\r
+        CacheVariable->CurrPtr->State = State;\r
+      }\r
     }    \r
   } else {\r
     //\r
-    // Not found existing variable. Create a new variable\r
+    // Not found existing variable. Create a new variable.\r
     //  \r
     \r
     //\r
     // Make sure we are trying to create a new variable.\r
-    // Setting a data variable with no access, or zero DataSize attributes means to delete it.    \r
+    // Setting a data variable with zero DataSize or no access attributes means to delete it.    \r
     //\r
     if (DataSize == 0 || (Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == 0) {\r
       Status = EFI_NOT_FOUND;\r
@@ -1677,9 +1489,9 @@ UpdateVariable (
     }\r
         \r
     //\r
-    // Only variable have NV|RT attribute can be created in Runtime\r
+    // Only variable have NV|RT attribute can be created in Runtime.\r
     //\r
-    if (EfiAtRuntime () &&\r
+    if (AtRuntime () &&\r
         (((Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0) || ((Attributes & EFI_VARIABLE_NON_VOLATILE) == 0))) {\r
       Status = EFI_INVALID_PARAMETER;\r
       goto Done;\r
@@ -1689,6 +1501,7 @@ UpdateVariable (
   //\r
   // Function part - create a new variable and copy the data.\r
   // Both update a variable and create a variable will come here.\r
+\r
   //\r
   // Tricky part: Use scratch data area at the end of volatile variable store\r
   // as a temporary storage.\r
@@ -1703,9 +1516,9 @@ UpdateVariable (
   //\r
   // NextVariable->State = VAR_ADDED;\r
   //\r
-  NextVariable->Reserved  = 0;\r
-  VarNameOffset           = sizeof (VARIABLE_HEADER);\r
-  VarNameSize             = StrSize (VariableName);\r
+  NextVariable->Reserved        = 0;\r
+  VarNameOffset                 = sizeof (VARIABLE_HEADER);\r
+  VarNameSize                   = StrSize (VariableName);\r
   CopyMem (\r
     (UINT8 *) ((UINTN) NextVariable + VarNameOffset),\r
     VariableName,\r
@@ -1721,7 +1534,7 @@ UpdateVariable (
   //\r
   // There will be pad bytes after Data, the NextVariable->NameSize and\r
   // NextVariable->DataSize should not include pad size so that variable\r
-  // service can get actual size in GetVariable\r
+  // service can get actual size in GetVariable.\r
   //\r
   NextVariable->NameSize  = (UINT32)VarNameSize;\r
   NextVariable->DataSize  = (UINT32)DataSize;\r
@@ -1733,7 +1546,7 @@ UpdateVariable (
   VarSize = VarDataOffset + DataSize + GET_PAD_SIZE (DataSize);\r
   if ((Attributes & EFI_VARIABLE_NON_VOLATILE) != 0) {\r
     //\r
-    // Create a nonvolatile variable\r
+    // Create a nonvolatile variable.\r
     //\r
     Volatile = FALSE;\r
     NonVolatileVarableStoreSize = ((VARIABLE_STORE_HEADER *)(UINTN)(mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase))->Size;\r
@@ -1741,12 +1554,12 @@ UpdateVariable (
       && ((VarSize + mVariableModuleGlobal->HwErrVariableTotalSize) > PcdGet32 (PcdHwErrStorageSize)))\r
       || (((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == 0) \r
       && ((VarSize + mVariableModuleGlobal->CommonVariableTotalSize) > NonVolatileVarableStoreSize - sizeof (VARIABLE_STORE_HEADER) - PcdGet32 (PcdHwErrStorageSize)))) {\r
-      if (EfiAtRuntime ()) {\r
+      if (AtRuntime ()) {\r
         Status = EFI_OUT_OF_RESOURCES;\r
         goto Done;\r
       }\r
       //\r
-      // Perform garbage collection & reclaim operation\r
+      // Perform garbage collection & reclaim operation.\r
       //\r
       Status = Reclaim (mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase, \r
                         &mVariableModuleGlobal->NonVolatileLastVariableOffset, FALSE, Variable->CurrPtr);\r
@@ -1754,7 +1567,7 @@ UpdateVariable (
         goto Done;\r
       }\r
       //\r
-      // If still no enough space, return out of resources\r
+      // If still no enough space, return out of resources.\r
       //\r
       if ((((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != 0) \r
         && ((VarSize + mVariableModuleGlobal->HwErrVariableTotalSize) > PcdGet32 (PcdHwErrStorageSize)))\r
@@ -1766,7 +1579,7 @@ UpdateVariable (
       Reclaimed = TRUE;\r
     }\r
     //\r
-    // Three steps\r
+    // Four steps\r
     // 1. Write variable header\r
     // 2. Set variable state to header valid  \r
     // 3. Write variable data\r
@@ -1775,6 +1588,7 @@ UpdateVariable (
     //\r
     // Step 1:\r
     //\r
+    CacheOffset = mVariableModuleGlobal->NonVolatileLastVariableOffset;\r
     Status = UpdateVariableStore (\r
                &mVariableModuleGlobal->VariableGlobal,\r
                FALSE,\r
@@ -1798,9 +1612,9 @@ UpdateVariable (
                FALSE,\r
                TRUE,\r
                Fvb,\r
-               mVariableModuleGlobal->NonVolatileLastVariableOffset,\r
-               sizeof (VARIABLE_HEADER),\r
-               (UINT8 *) NextVariable\r
+               mVariableModuleGlobal->NonVolatileLastVariableOffset + OFFSET_OF (VARIABLE_HEADER, State),\r
+               sizeof (UINT8),\r
+               &NextVariable->State\r
                );\r
 \r
     if (EFI_ERROR (Status)) {\r
@@ -1831,9 +1645,9 @@ UpdateVariable (
                FALSE,\r
                TRUE,\r
                Fvb,\r
-               mVariableModuleGlobal->NonVolatileLastVariableOffset,\r
-               sizeof (VARIABLE_HEADER),\r
-               (UINT8 *) NextVariable\r
+               mVariableModuleGlobal->NonVolatileLastVariableOffset + OFFSET_OF (VARIABLE_HEADER, State),\r
+               sizeof (UINT8),\r
+               &NextVariable->State\r
                );\r
 \r
     if (EFI_ERROR (Status)) {\r
@@ -1847,16 +1661,20 @@ UpdateVariable (
     } else {\r
       mVariableModuleGlobal->CommonVariableTotalSize += HEADER_ALIGN (VarSize);\r
     }\r
+    //\r
+    // update the memory copy of Flash region.\r
+    //\r
+    CopyMem ((UINT8 *)mNvVariableCache + CacheOffset, (UINT8 *)NextVariable, VarSize);\r
   } else {\r
     //\r
-    // Create a volatile variable\r
+    // Create a volatile variable.\r
     //      \r
     Volatile = TRUE;\r
 \r
     if ((UINT32) (VarSize + mVariableModuleGlobal->VolatileLastVariableOffset) >\r
         ((VARIABLE_STORE_HEADER *) ((UINTN) (mVariableModuleGlobal->VariableGlobal.VolatileVariableBase)))->Size) {\r
       //\r
-      // Perform garbage collection & reclaim operation\r
+      // Perform garbage collection & reclaim operation.\r
       //\r
       Status = Reclaim (mVariableModuleGlobal->VariableGlobal.VolatileVariableBase, \r
                           &mVariableModuleGlobal->VolatileLastVariableOffset, TRUE, Variable->CurrPtr);\r
@@ -1864,7 +1682,7 @@ UpdateVariable (
         goto Done;\r
       }\r
       //\r
-      // If still no enough space, return out of resources\r
+      // If still no enough space, return out of resources.\r
       //\r
       if ((UINT32) (VarSize + mVariableModuleGlobal->VolatileLastVariableOffset) >\r
             ((VARIABLE_STORE_HEADER *) ((UINTN) (mVariableModuleGlobal->VariableGlobal.VolatileVariableBase)))->Size\r
@@ -1894,7 +1712,7 @@ UpdateVariable (
   }\r
 \r
   //\r
-  // Mark the old variable as deleted\r
+  // Mark the old variable as deleted.\r
   //\r
   if (!Reclaimed && !EFI_ERROR (Status) && Variable->CurrPtr != NULL) {\r
     State = Variable->CurrPtr->State;\r
@@ -1909,11 +1727,13 @@ UpdateVariable (
              sizeof (UINT8),\r
              &State\r
              );\r
+    if (!EFI_ERROR (Status) && !Variable->Volatile) {         \r
+      CacheVariable->CurrPtr->State = State;\r
+    }\r
   }\r
 \r
   if (!EFI_ERROR (Status)) {\r
     UpdateVariableInfo (VariableName, VendorGuid, Volatile, FALSE, TRUE, FALSE, FALSE);\r
-    UpdateVariableCache (VariableName, VendorGuid, Attributes, DataSize, Data);\r
   }\r
 \r
 Done:\r
@@ -1931,15 +1751,15 @@ Done:
                                     data, this value contains the required size.\r
   @param Data                       Data pointer.\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
+  @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
 \r
 **/\r
 EFI_STATUS\r
 EFIAPI\r
-RuntimeServiceGetVariable (\r
+VariableServiceGetVariable (\r
   IN      CHAR16            *VariableName,\r
   IN      EFI_GUID          *VendorGuid,\r
   OUT     UINT32            *Attributes OPTIONAL,\r
@@ -1956,16 +1776,6 @@ RuntimeServiceGetVariable (
   }\r
 \r
   AcquireLockOnlyAtBootTime(&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);\r
-\r
-  //\r
-  // Find existing variable\r
-  //\r
-  Status = FindVariableInCache (VariableName, VendorGuid, Attributes, DataSize, Data);\r
-  if ((Status == EFI_BUFFER_TOO_SMALL) || (Status == EFI_SUCCESS)){\r
-    // Hit in the Cache\r
-    UpdateVariableInfo (VariableName, VendorGuid, FALSE, TRUE, FALSE, FALSE, TRUE);\r
-    goto Done;\r
-  }\r
   \r
   Status = FindVariable (VariableName, VendorGuid, &Variable, &mVariableModuleGlobal->VariableGlobal);\r
   if (Variable.CurrPtr == NULL || EFI_ERROR (Status)) {\r
@@ -1991,7 +1801,6 @@ RuntimeServiceGetVariable (
 \r
     *DataSize = VarDataSize;\r
     UpdateVariableInfo (VariableName, VendorGuid, Variable.Volatile, TRUE, FALSE, FALSE, FALSE);\r
-    UpdateVariableCache (VariableName, VendorGuid, Variable.CurrPtr->Attributes, VarDataSize, Data);\r
  \r
     Status = EFI_SUCCESS;\r
     goto Done;\r
@@ -2012,19 +1821,19 @@ Done:
 \r
   This code Finds the Next available variable.\r
 \r
-  @param VariableNameSize           Size of the variable name\r
-  @param VariableName               Pointer to variable name\r
-  @param VendorGuid                 Variable Vendor Guid\r
+  @param VariableNameSize           Size of the variable name.\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
+  @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
 \r
 **/\r
 EFI_STATUS\r
 EFIAPI\r
-RuntimeServiceGetNextVariableName (\r
+VariableServiceGetNextVariableName (\r
   IN OUT  UINTN             *VariableNameSize,\r
   IN OUT  CHAR16            *VariableName,\r
   IN OUT  EFI_GUID          *VendorGuid\r
@@ -2047,7 +1856,7 @@ RuntimeServiceGetNextVariableName (
 \r
   if (VariableName[0] != 0) {\r
     //\r
-    // If variable name is not NULL, get next variable\r
+    // If variable name is not NULL, get next variable.\r
     //\r
     Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);\r
   }\r
@@ -2055,7 +1864,7 @@ RuntimeServiceGetNextVariableName (
   while (TRUE) {\r
     //\r
     // If both volatile and non-volatile variable store are parsed,\r
-    // return not found\r
+    // return not found.\r
     //\r
     if (Variable.CurrPtr >= Variable.EndPtr || Variable.CurrPtr == NULL) {\r
       Variable.Volatile = (BOOLEAN) (Variable.Volatile ^ ((BOOLEAN) 0x1));\r
@@ -2076,7 +1885,7 @@ RuntimeServiceGetNextVariableName (
     // Variable is found\r
     //\r
     if (IsValidVariableHeader (Variable.CurrPtr) && Variable.CurrPtr->State == VAR_ADDED) {\r
-      if ((EfiAtRuntime () && ((Variable.CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0)) == 0) {\r
+      if ((AtRuntime () && ((Variable.CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0)) == 0) {\r
         VarNameSize = NameSizeOfVariable (Variable.CurrPtr);\r
         ASSERT (VarNameSize != 0);\r
 \r
@@ -2113,23 +1922,23 @@ Done:
 \r
   This code sets variable in storage blocks (Volatile or Non-Volatile).\r
 \r
-  @param VariableName                     Name of Variable to be found\r
-  @param VendorGuid                       Variable vendor GUID\r
+  @param VariableName                     Name of Variable to be found.\r
+  @param VendorGuid                       Variable vendor GUID.\r
   @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                             Data pointer.\r
 \r
-  @return EFI_INVALID_PARAMETER           Invalid parameter\r
-  @return EFI_SUCCESS                     Set successfully\r
-  @return EFI_OUT_OF_RESOURCES            Resource not enough to set variable\r
-  @return EFI_NOT_FOUND                   Not found\r
-  @return EFI_WRITE_PROTECTED             Variable is read-only\r
+  @return EFI_INVALID_PARAMETER           Invalid parameter.\r
+  @return EFI_SUCCESS                     Set successfully.\r
+  @return EFI_OUT_OF_RESOURCES            Resource not enough to set variable.\r
+  @return EFI_NOT_FOUND                   Not found.\r
+  @return EFI_WRITE_PROTECTED             Variable is read-only.\r
 \r
 **/\r
 EFI_STATUS\r
 EFIAPI\r
-RuntimeServiceSetVariable (\r
+VariableServiceSetVariable (\r
   IN CHAR16                  *VariableName,\r
   IN EFI_GUID                *VendorGuid,\r
   IN UINT32                  Attributes,\r
@@ -2143,11 +1952,11 @@ RuntimeServiceSetVariable (
   EFI_PHYSICAL_ADDRESS                Point;\r
 \r
   //\r
-  // Check input parameters\r
+  // Check input parameters.\r
   //\r
   if (VariableName == NULL || VariableName[0] == 0 || VendorGuid == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
-  }\r
+  } \r
 \r
   if (DataSize != 0 && Data == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
@@ -2161,7 +1970,7 @@ RuntimeServiceSetVariable (
   }\r
 \r
   //\r
-  //  Make sure if runtime bit is set, boot service bit is set also\r
+  //  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
@@ -2178,7 +1987,7 @@ RuntimeServiceSetVariable (
       return EFI_INVALID_PARAMETER;\r
     }\r
     //\r
-    // According to UEFI spec, HARDWARE_ERROR_RECORD variable name convention should be L"HwErrRecXXXX"\r
+    // According to UEFI spec, HARDWARE_ERROR_RECORD variable name convention should be L"HwErrRecXXXX".\r
     //\r
     if (StrnCmp(VariableName, L"HwErrRec", StrLen(L"HwErrRec")) != 0) {\r
       return EFI_INVALID_PARAMETER;\r
@@ -2197,12 +2006,12 @@ RuntimeServiceSetVariable (
   AcquireLockOnlyAtBootTime(&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);\r
 \r
   //\r
-  // Consider reentrant in MCA/INIT/NMI. It needs be reupdated;\r
+  // Consider reentrant in MCA/INIT/NMI. It needs be reupdated.\r
   //\r
   if (1 < InterlockedIncrement (&mVariableModuleGlobal->VariableGlobal.ReentrantState)) {\r
-    Point = mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase;;\r
+    Point = mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase;\r
     //\r
-    // Parse non-volatile variable data and get last variable offset\r
+    // Parse non-volatile variable data and get last variable offset.\r
     //\r
     NextVariable  = GetStartPointer ((VARIABLE_STORE_HEADER *) (UINTN) Point);\r
     while ((NextVariable < GetEndPointer ((VARIABLE_STORE_HEADER *) (UINTN) Point)) \r
@@ -2213,12 +2022,12 @@ RuntimeServiceSetVariable (
   }\r
 \r
   //\r
-  // Check whether the input variable is already existed\r
+  // Check whether the input variable is already existed.\r
   //\r
   FindVariable (VariableName, VendorGuid, &Variable, &mVariableModuleGlobal->VariableGlobal);\r
 \r
   //\r
-  // Hook the operation of setting PlatformLangCodes/PlatformLang and LangCodes/Lang\r
+  // Hook the operation of setting PlatformLangCodes/PlatformLang and LangCodes/Lang.\r
   //\r
   AutoUpdateLangVariable (VariableName, Data, DataSize);\r
 \r
@@ -2250,7 +2059,7 @@ RuntimeServiceSetVariable (
 **/\r
 EFI_STATUS\r
 EFIAPI\r
-RuntimeServiceQueryVariableInfo (\r
+VariableServiceQueryVariableInfo (\r
   IN  UINT32                 Attributes,\r
   OUT UINT64                 *MaximumVariableStorageSize,\r
   OUT UINT64                 *RemainingVariableStorageSize,\r
@@ -2281,7 +2090,7 @@ RuntimeServiceQueryVariableInfo (
     // Make sure if runtime bit is set, boot service bit is set also.\r
     //\r
     return EFI_INVALID_PARAMETER;\r
-  } else if (EfiAtRuntime () && ((Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0)) {\r
+  } else if (AtRuntime () && ((Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0)) {\r
     //\r
     // Make sure RT Attribute is set if we are in Runtime phase.\r
     //\r
@@ -2309,7 +2118,7 @@ RuntimeServiceQueryVariableInfo (
     //\r
     // Query is Non-Volatile related.\r
     //\r
-    VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINTN) mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase);\r
+    VariableStoreHeader = mNvVariableCache;\r
   }\r
 \r
   //\r
@@ -2348,9 +2157,9 @@ RuntimeServiceQueryVariableInfo (
     NextVariable = GetNextVariablePtr (Variable);\r
     VariableSize = (UINT64) (UINTN) NextVariable - (UINT64) (UINTN) Variable;\r
 \r
-    if (EfiAtRuntime ()) {\r
+    if (AtRuntime ()) {\r
       //\r
-      // we don't take the state of the variables in mind\r
+      // We don't take the state of the variables in mind\r
       // when calculating RemainingVariableStorageSize,\r
       // since the space occupied by variables not marked with\r
       // VAR_ADDED is not allowed to be reclaimed in Runtime.\r
@@ -2362,7 +2171,7 @@ RuntimeServiceQueryVariableInfo (
       }\r
     } else {\r
       //\r
-      // Only care about Variables with State VAR_ADDED,because\r
+      // Only care about Variables with State VAR_ADDED, because\r
       // the space not marked as VAR_ADDED is reclaimable now.\r
       //\r
       if (Variable->State == VAR_ADDED) {\r
@@ -2375,7 +2184,7 @@ RuntimeServiceQueryVariableInfo (
     }\r
 \r
     //\r
-    // Go to the next one\r
+    // Go to the next one.\r
     //\r
     Variable = NextVariable;\r
   }\r
@@ -2398,21 +2207,12 @@ RuntimeServiceQueryVariableInfo (
 \r
 \r
 /**\r
-  Notification function of EVT_GROUP_READY_TO_BOOT event group.\r
-\r
-  This is a notification function registered on EVT_GROUP_READY_TO_BOOT event group.\r
-  When the Boot Manager is about to load and execute a boot option, it reclaims variable\r
-  storage if free size is below the threshold.\r
-\r
-  @param  Event        Event whose notification function is being invoked\r
-  @param  Context      Pointer to the notification function's context\r
-\r
+  This function reclaims variable storage if free size is below the threshold.\r
+  \r
 **/\r
 VOID\r
-EFIAPI\r
 ReclaimForOS(\r
-  EFI_EVENT  Event,\r
-  VOID       *Context\r
+  VOID\r
   )\r
 {\r
   EFI_STATUS                     Status;\r
@@ -2443,10 +2243,58 @@ ReclaimForOS(
   }\r
 }\r
 \r
+\r
 /**\r
-  Initializes variable store area for non-volatile and volatile variable.\r
+  Initializes variable write service after FVB was ready.\r
+\r
+  @retval EFI_SUCCESS          Function successfully executed.\r
+  @retval Others               Fail to initialize the variable service.\r
+\r
+**/\r
+EFI_STATUS\r
+VariableWriteServiceInitialize (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS                      Status;\r
+  VARIABLE_STORE_HEADER           *VariableStoreHeader;\r
+  UINTN                           Index;\r
+  UINT8                           Data;\r
+  EFI_PHYSICAL_ADDRESS            VariableStoreBase;\r
+  UINT64                          VariableStoreLength;\r
+\r
+  VariableStoreBase   = mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase;\r
+  VariableStoreHeader = (VARIABLE_STORE_HEADER *)(UINTN)VariableStoreBase;\r
+  VariableStoreLength = VariableStoreHeader->Size;\r
+  \r
+  //\r
+  // Check if the free area is really free.\r
+  //\r
+  for (Index = mVariableModuleGlobal->NonVolatileLastVariableOffset; Index < VariableStoreLength; Index++) {\r
+    Data = ((UINT8 *) mNvVariableCache)[Index];\r
+    if (Data != 0xff) {\r
+      //\r
+      // There must be something wrong in variable store, do reclaim operation.\r
+      //\r
+      Status = Reclaim (\r
+                 mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase,\r
+                 &mVariableModuleGlobal->NonVolatileLastVariableOffset,\r
+                 FALSE,\r
+                 NULL\r
+                 );\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+      break;\r
+    }\r
+  }\r
 \r
-  @param  FvbProtocol           Pointer to an instance of EFI Firmware Volume Block Protocol.\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  Initializes variable store area for non-volatile and volatile variable.\r
 \r
   @retval EFI_SUCCESS           Function successfully executed.\r
   @retval EFI_OUT_OF_RESOURCES  Fail to allocate enough memory resource.\r
@@ -2454,7 +2302,7 @@ ReclaimForOS(
 **/\r
 EFI_STATUS\r
 VariableCommonInitialize (\r
-  IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol\r
+  VOID\r
   )\r
 {\r
   EFI_STATUS                      Status;\r
@@ -2462,18 +2310,11 @@ VariableCommonInitialize (
   VARIABLE_STORE_HEADER           *VariableStoreHeader;\r
   VARIABLE_HEADER                 *NextVariable;\r
   EFI_PHYSICAL_ADDRESS            TempVariableStoreHeader;\r
-  EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor;\r
-  EFI_PHYSICAL_ADDRESS            BaseAddress;\r
-  UINT64                          Length;\r
-  UINTN                           Index;\r
-  UINT8                           Data;\r
   EFI_PHYSICAL_ADDRESS            VariableStoreBase;\r
   UINT64                          VariableStoreLength;\r
-  EFI_EVENT                       ReadyToBootEvent;\r
   UINTN                           ScratchSize;\r
   UINTN                           VariableSize;\r
 \r
-  Status = EFI_SUCCESS;\r
   //\r
   // Allocate runtime memory for variable driver global structure.\r
   //\r
@@ -2482,7 +2323,7 @@ VariableCommonInitialize (
     return EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
-  EfiInitializeLock(&mVariableModuleGlobal->VariableGlobal.VariableServicesLock, TPL_NOTIFY);\r
+  InitializeLock (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock, TPL_NOTIFY);\r
 \r
   //\r
   // Note that in EdkII variable driver implementation, Hardware Error Record type variable\r
@@ -2505,139 +2346,69 @@ VariableCommonInitialize (
   SetMem (VolatileVariableStore, PcdGet32 (PcdVariableStoreSize) + ScratchSize, 0xff);\r
 \r
   //\r
-  //  Variable Specific Data\r
+  // Initialize Variable Specific Data.\r
   //\r
   mVariableModuleGlobal->VariableGlobal.VolatileVariableBase = (EFI_PHYSICAL_ADDRESS) (UINTN) VolatileVariableStore;\r
   mVariableModuleGlobal->VolatileLastVariableOffset = (UINTN) GetStartPointer (VolatileVariableStore) - (UINTN) VolatileVariableStore;\r
-  mVariableModuleGlobal->FvbInstance = FvbProtocol;\r
+  mVariableModuleGlobal->FvbInstance = NULL;\r
 \r
   CopyGuid (&VolatileVariableStore->Signature, &gEfiVariableGuid);\r
-  VolatileVariableStore->Size                       = PcdGet32 (PcdVariableStoreSize);\r
-  VolatileVariableStore->Format                     = VARIABLE_STORE_FORMATTED;\r
-  VolatileVariableStore->State                      = VARIABLE_STORE_HEALTHY;\r
-  VolatileVariableStore->Reserved                   = 0;\r
-  VolatileVariableStore->Reserved1                  = 0;\r
+  VolatileVariableStore->Size        = PcdGet32 (PcdVariableStoreSize);\r
+  VolatileVariableStore->Format      = VARIABLE_STORE_FORMATTED;\r
+  VolatileVariableStore->State       = VARIABLE_STORE_HEALTHY;\r
+  VolatileVariableStore->Reserved    = 0;\r
+  VolatileVariableStore->Reserved1   = 0;\r
 \r
   //\r
-  // Get non volatile varaible store\r
+  // Get non-volatile varaible store.\r
   //\r
 \r
   TempVariableStoreHeader = (EFI_PHYSICAL_ADDRESS) PcdGet64 (PcdFlashNvStorageVariableBase64);\r
   if (TempVariableStoreHeader == 0) {\r
     TempVariableStoreHeader = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashNvStorageVariableBase);\r
   }\r
-  \r
-  VariableStoreBase = TempVariableStoreHeader + \\r
+  VariableStoreBase       = TempVariableStoreHeader + \\r
+                              (((EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)(TempVariableStoreHeader)) -> HeaderLength);\r
+  VariableStoreLength     = (UINT64) PcdGet32 (PcdFlashNvStorageVariableSize) - \\r
                               (((EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)(TempVariableStoreHeader)) -> HeaderLength);\r
-  VariableStoreLength = (UINT64) PcdGet32 (PcdFlashNvStorageVariableSize) - \\r
-                                (((EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)(TempVariableStoreHeader)) -> HeaderLength);\r
-  //\r
-  // Mark the variable storage region of the FLASH as RUNTIME\r
-  //\r
-  BaseAddress = VariableStoreBase & (~EFI_PAGE_MASK);\r
-  Length      = VariableStoreLength + (VariableStoreBase - BaseAddress);\r
-  Length      = (Length + EFI_PAGE_SIZE - 1) & (~EFI_PAGE_MASK);\r
-\r
-  Status      = gDS->GetMemorySpaceDescriptor (BaseAddress, &GcdDescriptor);\r
-  if (EFI_ERROR (Status)) {\r
-    goto Done;\r
-  }\r
 \r
-  Status = gDS->SetMemorySpaceAttributes (\r
-                  BaseAddress,\r
-                  Length,\r
-                  GcdDescriptor.Attributes | EFI_MEMORY_RUNTIME\r
-                  );\r
-  if (EFI_ERROR (Status)) {\r
+  mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase = VariableStoreBase;\r
+  VariableStoreHeader = (VARIABLE_STORE_HEADER *)(UINTN)VariableStoreBase;\r
+  if (GetVariableStoreStatus (VariableStoreHeader) != EfiValid) {\r
+    Status = EFI_VOLUME_CORRUPTED;\r
+    DEBUG((EFI_D_INFO, "Variable Store header is corrupted\n"));\r
     goto Done;\r
-  }\r
+  }  \r
+  ASSERT(VariableStoreHeader->Size == VariableStoreLength);\r
+    \r
   //\r
-  // Get address of non volatile variable store base\r
+  // Parse non-volatile variable data and get last variable offset.\r
   //\r
-  mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase = VariableStoreBase;\r
-  VariableStoreHeader = (VARIABLE_STORE_HEADER *)(UINTN)VariableStoreBase;\r
-  if (GetVariableStoreStatus (VariableStoreHeader) == EfiValid) {\r
-    if (~VariableStoreHeader->Size == 0) {\r
-      Status = UpdateVariableStore (\r
-                &mVariableModuleGlobal->VariableGlobal,\r
-                FALSE,\r
-                FALSE,\r
-                mVariableModuleGlobal->FvbInstance,\r
-                (UINTN) &VariableStoreHeader->Size,\r
-                sizeof (UINT32),\r
-                (UINT8 *) &VariableStoreLength\r
-                );\r
-      //\r
-      // As Variables are stored in NV storage, which are slow devices,such as flash.\r
-      // Variable operation may skip checking variable program result to improve performance,\r
-      // We can assume Variable program is OK through some check point.\r
-      // Variable Store Size Setting should be the first Variable write operation,\r
-      // We can assume all Read/Write is OK if we can set Variable store size successfully.\r
-      // If write fail, we will assert here\r
-      //\r
-      ASSERT(VariableStoreHeader->Size == VariableStoreLength);\r
-\r
-      if (EFI_ERROR (Status)) {\r
-        goto Done;\r
-      }\r
-    }\r
-\r
-    //\r
-    // Parse non-volatile variable data and get last variable offset\r
-    //\r
-    NextVariable  = GetStartPointer ((VARIABLE_STORE_HEADER *)(UINTN)VariableStoreBase);\r
-    Status        = EFI_SUCCESS;\r
-\r
-    while (IsValidVariableHeader (NextVariable)) {\r
-      VariableSize = NextVariable->NameSize + NextVariable->DataSize + sizeof (VARIABLE_HEADER);\r
-      if ((NextVariable->Attributes & (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) == (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {\r
-        mVariableModuleGlobal->HwErrVariableTotalSize += HEADER_ALIGN (VariableSize);\r
-      } else {\r
-        mVariableModuleGlobal->CommonVariableTotalSize += HEADER_ALIGN (VariableSize);\r
-      }\r
-\r
-      NextVariable = GetNextVariablePtr (NextVariable);\r
+  NextVariable  = GetStartPointer ((VARIABLE_STORE_HEADER *)(UINTN)VariableStoreBase);\r
+  while (IsValidVariableHeader (NextVariable)) {\r
+    VariableSize = NextVariable->NameSize + NextVariable->DataSize + sizeof (VARIABLE_HEADER);\r
+    if ((NextVariable->Attributes & (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) == (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {\r
+      mVariableModuleGlobal->HwErrVariableTotalSize += HEADER_ALIGN (VariableSize);\r
+    } else {\r
+      mVariableModuleGlobal->CommonVariableTotalSize += HEADER_ALIGN (VariableSize);\r
     }\r
 \r
-    mVariableModuleGlobal->NonVolatileLastVariableOffset = (UINTN) NextVariable - (UINTN) VariableStoreBase;\r
-\r
-    //\r
-    // Check if the free area is really free.\r
-    //\r
-    for (Index = mVariableModuleGlobal->NonVolatileLastVariableOffset; Index < VariableStoreHeader->Size; Index++) {\r
-      Data = ((UINT8 *) (UINTN) mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase)[Index];\r
-      if (Data != 0xff) {\r
-        //\r
-        // There must be something wrong in variable store, do reclaim operation.\r
-        //\r
-        Status = Reclaim (\r
-                  mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase,\r
-                  &mVariableModuleGlobal->NonVolatileLastVariableOffset,\r
-                  FALSE,\r
-                  NULL\r
-                  );\r
-\r
-        if (EFI_ERROR (Status)) {\r
-          goto Done;\r
-        }\r
-\r
-        break;\r
-      }\r
-    }\r
+    NextVariable = GetNextVariablePtr (NextVariable);\r
+  }\r
 \r
-    //\r
-    // Register the event handling function to reclaim variable for OS usage.\r
-    //\r
-    Status = EfiCreateEventReadyToBootEx (\r
-               TPL_NOTIFY, \r
-               ReclaimForOS, \r
-               NULL, \r
-               &ReadyToBootEvent\r
-               );\r
-  } else {\r
-    Status = EFI_VOLUME_CORRUPTED;\r
-    DEBUG((EFI_D_INFO, "Variable Store header is corrupted\n"));\r
+  mVariableModuleGlobal->NonVolatileLastVariableOffset = (UINTN) NextVariable - (UINTN) VariableStoreBase;\r
+    \r
+  //\r
+  // Allocate runtime memory used for a memory copy of the FLASH region.\r
+  // Keep the memory and the FLASH in sync as updates occur\r
+  //\r
+  mNvVariableCache = AllocateRuntimeZeroPool ((UINTN)VariableStoreLength);\r
+  if (mNvVariableCache == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto Done;\r
   }\r
+  CopyMem (mNvVariableCache, (CHAR8 *)(UINTN)VariableStoreBase, (UINTN)VariableStoreLength);\r
+  Status = EFI_SUCCESS;\r
 \r
 Done:\r
   if (EFI_ERROR (Status)) {\r
@@ -2648,97 +2419,45 @@ Done:
   return Status;\r
 }\r
 \r
-/**\r
-  Notification function of EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE\r
-\r
-  This is a notification function registered on EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.\r
-  It convers pointer to new virtual address.\r
-\r
-  @param  Event        Event whose notification function is being invoked\r
-  @param  Context      Pointer to the notification function's context\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-VariableClassAddressChangeEvent (\r
-  IN EFI_EVENT        Event,\r
-  IN VOID             *Context\r
-  )\r
-{\r
-  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->GetBlockSize);\r
-  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->GetPhysicalAddress);\r
-  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->GetAttributes);\r
-  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->SetAttributes);\r
-  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->Read);\r
-  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->Write);\r
-  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->EraseBlocks);\r
-  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance);\r
-  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->PlatformLangCodes);\r
-  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->LangCodes);\r
-  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->PlatformLang);\r
-  EfiConvertPointer (\r
-    0x0,\r
-    (VOID **) &mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase\r
-    );\r
-  EfiConvertPointer (\r
-    0x0,\r
-    (VOID **) &mVariableModuleGlobal->VariableGlobal.VolatileVariableBase\r
-    );\r
-  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal);\r
-}\r
 \r
 /**\r
-  Firmware Volume Block Protocol notification event handler.\r
+  Get the proper fvb handle and/or fvb protocol by the given Flash address.\r
 \r
-  Discover NV Variable Store and install Variable Arch Protocol.\r
+  @param[in] Address        The Flash address.\r
+  @param[out] FvbHandle     In output, if it is not NULL, it points to the proper FVB handle.\r
+  @param[out] FvbProtocol   In output, if it is not NULL, it points to the proper FVB protocol.\r
 \r
-  @param[in] Event    Event whose notification function is being invoked.\r
-  @param[in] Context  Pointer to the notification function's context.\r
 **/\r
-VOID\r
-EFIAPI\r
-FvbNotificationEvent (\r
-  IN  EFI_EVENT       Event,\r
-  IN  VOID            *Context\r
+EFI_STATUS\r
+GetFvbInfoByAddress (\r
+  IN  EFI_PHYSICAL_ADDRESS                Address,\r
+  OUT EFI_HANDLE                          *FvbHandle OPTIONAL,\r
+  OUT EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  **FvbProtocol OPTIONAL\r
   )\r
 {\r
-  EFI_STATUS                          Status;\r
-  EFI_HANDLE                          *HandleBuffer;\r
-  UINTN                               HandleCount;\r
-  UINTN                               Index;\r
-  EFI_PHYSICAL_ADDRESS                FvbBaseAddress;\r
-  EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  *Fvb;\r
-  EFI_FIRMWARE_VOLUME_HEADER          *FwVolHeader;\r
-  EFI_FVB_ATTRIBUTES_2                Attributes;\r
-  EFI_SYSTEM_TABLE                    *SystemTable;\r
-  EFI_PHYSICAL_ADDRESS                NvStorageVariableBase;\r
-\r
-  SystemTable = (EFI_SYSTEM_TABLE *)Context;\r
-  Fvb         = NULL;\r
-  \r
+  EFI_STATUS                              Status;\r
+  EFI_HANDLE                              *HandleBuffer;\r
+  UINTN                                   HandleCount;\r
+  UINTN                                   Index;\r
+  EFI_PHYSICAL_ADDRESS                    FvbBaseAddress;\r
+  EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL      *Fvb;\r
+  EFI_FIRMWARE_VOLUME_HEADER              *FwVolHeader;\r
+  EFI_FVB_ATTRIBUTES_2                    Attributes;\r
\r
   //\r
-  // Locate all handles of Fvb protocol\r
+  // Get all FVB handles.\r
   //\r
-  Status = gBS->LocateHandleBuffer (\r
-                  ByProtocol,\r
-                  &gEfiFirmwareVolumeBlockProtocolGuid,\r
-                  NULL,\r
-                  &HandleCount,\r
-                  &HandleBuffer\r
-                  );\r
+  Status = GetFvbCountAndBuffer (&HandleCount, &HandleBuffer);\r
   if (EFI_ERROR (Status)) {\r
-    return ;\r
+    return EFI_NOT_FOUND;\r
   }\r
-  \r
+\r
   //\r
-  // Get the FVB to access variable store\r
+  // Get the FVB to access variable store.\r
   //\r
+  Fvb = NULL;\r
   for (Index = 0; Index < HandleCount; Index += 1, Status = EFI_NOT_FOUND, Fvb = NULL) {\r
-    Status = gBS->HandleProtocol (\r
-                    HandleBuffer[Index],\r
-                    &gEfiFirmwareVolumeBlockProtocolGuid,\r
-                    (VOID **) &Fvb\r
-                    );\r
+    Status = GetFvbByHandle (HandleBuffer[Index], &Fvb);\r
     if (EFI_ERROR (Status)) {\r
       Status = EFI_NOT_FOUND;\r
       break;\r
@@ -2751,8 +2470,9 @@ FvbNotificationEvent (
     if (EFI_ERROR (Status) || ((Attributes & EFI_FVB2_WRITE_STATUS) == 0)) {\r
       continue;     \r
     }\r
+    \r
     //\r
-    // Compare the address and select the right one\r
+    // Compare the address and select the right one.\r
     //\r
     Status = Fvb->GetPhysicalAddress (Fvb, &FvbBaseAddress);\r
     if (EFI_ERROR (Status)) {\r
@@ -2760,87 +2480,23 @@ FvbNotificationEvent (
     }\r
 \r
     FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) FvbBaseAddress);\r
-    NvStorageVariableBase = (EFI_PHYSICAL_ADDRESS) PcdGet64 (PcdFlashNvStorageVariableBase64);\r
-    if (NvStorageVariableBase == 0) {\r
-      NvStorageVariableBase = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashNvStorageVariableBase);\r
-    }\r
-    \r
-    if ((NvStorageVariableBase >= FvbBaseAddress) && (NvStorageVariableBase < (FvbBaseAddress + FwVolHeader->FvLength))) {\r
-      Status      = EFI_SUCCESS;\r
+    if ((Address >= FvbBaseAddress) && (Address < (FvbBaseAddress + FwVolHeader->FvLength))) {\r
+      if (FvbHandle != NULL) {\r
+        *FvbHandle  = HandleBuffer[Index];\r
+      }\r
+      if (FvbProtocol != NULL) {\r
+        *FvbProtocol = Fvb;\r
+      }\r
+      Status = EFI_SUCCESS;\r
       break;\r
     }\r
   }\r
-\r
   FreePool (HandleBuffer);\r
-  if (!EFI_ERROR (Status) && Fvb != NULL) {\r
-    //\r
-    // Close the notify event to avoid install gEfiVariableArchProtocolGuid & gEfiVariableWriteArchProtocolGuid again.\r
-    //\r
-    Status = gBS->CloseEvent (Event);  \r
-    ASSERT_EFI_ERROR (Status);\r
 \r
-    Status = VariableCommonInitialize (Fvb);\r
-    ASSERT_EFI_ERROR (Status);\r
-  \r
-    SystemTable->RuntimeServices->GetVariable         = RuntimeServiceGetVariable;\r
-    SystemTable->RuntimeServices->GetNextVariableName = RuntimeServiceGetNextVariableName;\r
-    SystemTable->RuntimeServices->SetVariable         = RuntimeServiceSetVariable;\r
-    SystemTable->RuntimeServices->QueryVariableInfo   = RuntimeServiceQueryVariableInfo;\r
-  \r
-    //\r
-    // Now install the Variable Runtime Architectural Protocol on a new handle\r
-    //\r
-    Status = gBS->InstallMultipleProtocolInterfaces (\r
-                  &mHandle,\r
-                  &gEfiVariableArchProtocolGuid, NULL,\r
-                  &gEfiVariableWriteArchProtocolGuid, NULL,\r
-                  NULL\r
-                  );\r
-    ASSERT_EFI_ERROR (Status);\r
-  \r
-    Status = gBS->CreateEventEx (\r
-                  EVT_NOTIFY_SIGNAL,\r
-                  TPL_NOTIFY,\r
-                  VariableClassAddressChangeEvent,\r
-                  NULL,\r
-                  &gEfiEventVirtualAddressChangeGuid,\r
-                  &mVirtualAddressChangeEvent\r
-                  );\r
-    ASSERT_EFI_ERROR (Status);\r
+  if (Fvb == NULL) {\r
+    Status = EFI_NOT_FOUND;\r
   }\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 availible. It also registers\r
-  notification function for 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
-  )\r
-{\r
-  //\r
-  // Register FvbNotificationEvent () notify function.\r
-  // \r
-  EfiCreateProtocolNotifyEvent (\r
-    &gEfiFirmwareVolumeBlockProtocolGuid,\r
-    TPL_CALLBACK,\r
-    FvbNotificationEvent,\r
-    (VOID *)SystemTable,\r
-    &mFvbRegistration\r
-    );\r
-\r
-  return EFI_SUCCESS;\r
+  return Status;  \r
 }\r
 \r