]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c
1. delete Include/Guid/VariableInfo.h
[mirror_edk2.git] / MdeModulePkg / Universal / Variable / RuntimeDxe / Variable.c
index ef8f72d38a777f1e914f0fdbe53fd524a49b5efe..d25fe038aa6800fc40e2e247b50fab72d88c8dab 100644 (file)
@@ -1,39 +1,55 @@
-/*++\r
+/** @file\r
 \r
-Copyright (c) 2006 - 2007, Intel Corporation\r
-All rights reserved. This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution.  The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
+  Implement all four UEFI Runtime Variable services for the nonvolatile\r
+  and volatile storage space and install variable architecture protocol.\r
+  \r
+Copyright (c) 2006 - 2009, Intel Corporation                                                         \r
+All rights reserved. This program and the accompanying materials                          \r
+are licensed and made available under the terms and conditions of the BSD License         \r
+which accompanies this distribution.  The full text of the license may be found at        \r
+http://opensource.org/licenses/bsd-license.php                                            \r
 \r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
 \r
-Module Name:\r
+**/\r
 \r
-  Variable.c\r
+#include "Variable.h"\r
 \r
-Abstract:\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
+///\r
+VARIABLE_CACHE_ENTRY mVariableCache[] = {\r
+  {\r
+    &gEfiGlobalVariableGuid,\r
+    L"Lang",\r
+    0x00000000,\r
+    0x00,\r
+    NULL\r
+  }\r
+};\r
 \r
-Revision History\r
+VARIABLE_INFO_ENTRY *gVariableInfo = NULL;\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
 \r
-#include "Variable.h"\r
-#include <Guid/FlashMapHob.h>\r
-\r
-//\r
-// Don't use module globals after the SetVirtualAddress map is signaled\r
-//\r
-ESAL_VARIABLE_GLOBAL  *mVariableModuleGlobal;\r
-\r
-//\r
-// This is a temperary function which will be removed\r
-// when EfiAcquireLock in UefiLib can handle the\r
-// the call in UEFI Runtimer driver in RT phase.\r
-//\r
-STATIC\r
+  @param  Lock         A pointer to the lock to acquire\r
+\r
+**/\r
 VOID\r
 AcquireLockOnlyAtBootTime (\r
   IN EFI_LOCK  *Lock\r
@@ -44,12 +60,18 @@ AcquireLockOnlyAtBootTime (
   }\r
 }\r
 \r
-//\r
-// This is a temperary function which will be removed\r
-// when EfiAcquireLock in UefiLib can handle the\r
-// the call in UEFI Runtimer driver in RT phase.\r
-//\r
-STATIC\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
@@ -60,40 +82,148 @@ ReleaseLockOnlyAtBootTime (
   }\r
 }\r
 \r
-STATIC\r
-BOOLEAN\r
-EFIAPI\r
-IsValidVariableHeader (\r
-  IN  VARIABLE_HEADER   *Variable\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
+  VariableInfo.efi can dump out the table. Only Boot Services variable \r
+  accesses are tracked by this code. The PcdVariableCollectStatistics\r
+  build flag controls if this feature is enabled. \r
+\r
+  A read that hits in the cache will have Read and Cache true for \r
+  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] Cache          TRUE for a cache hit.\r
+\r
+**/\r
+VOID\r
+UpdateVariableInfo (\r
+  IN  CHAR16                  *VariableName,\r
+  IN  EFI_GUID                *VendorGuid,\r
+  IN  BOOLEAN                 Volatile,\r
+  IN  BOOLEAN                 Read,\r
+  IN  BOOLEAN                 Write,\r
+  IN  BOOLEAN                 Delete,\r
+  IN  BOOLEAN                 Cache\r
   )\r
-/*++\r
+{\r
+  VARIABLE_INFO_ENTRY   *Entry;\r
+\r
+  if (FeaturePcdGet (PcdVariableCollectStatistics)) {\r
+\r
+    if (EfiAtRuntime ()) {\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
+      //\r
+      gVariableInfo = AllocateZeroPool (sizeof (VARIABLE_INFO_ENTRY));\r
+      ASSERT (gVariableInfo != NULL);\r
 \r
-Routine Description:\r
+      CopyGuid (&gVariableInfo->VendorGuid, VendorGuid);\r
+      gVariableInfo->Name = AllocatePool (StrLen (VariableName));\r
+      ASSERT (gVariableInfo->Name != NULL);\r
+      StrCpy (gVariableInfo->Name, VariableName);\r
+      gVariableInfo->Volatile = Volatile;\r
+\r
+      gBS->InstallConfigurationTable (&gEfiVariableGuid, gVariableInfo);\r
+    }\r
+\r
+    \r
+    for (Entry = gVariableInfo; Entry != NULL; Entry = Entry->Next) {\r
+      if (CompareGuid (VendorGuid, &Entry->VendorGuid)) {\r
+        if (StrCmp (VariableName, Entry->Name) == 0) {\r
+          if (Read) {\r
+            Entry->ReadCount++;\r
+          }\r
+          if (Write) {\r
+            Entry->WriteCount++;\r
+          }\r
+          if (Delete) {\r
+            Entry->DeleteCount++;\r
+          }\r
+          if (Cache) {\r
+            Entry->CacheCount++;\r
+          }\r
+\r
+          return;\r
+        }\r
+      }\r
+\r
+      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
+        //\r
+        Entry->Next = AllocateZeroPool (sizeof (VARIABLE_INFO_ENTRY));\r
+        ASSERT (Entry->Next != NULL);\r
+\r
+        CopyGuid (&Entry->Next->VendorGuid, VendorGuid);\r
+        Entry->Next->Name = AllocatePool (StrLen (VariableName));\r
+        ASSERT (Entry->Next->Name != NULL);\r
+        StrCpy (Entry->Next->Name, VariableName);\r
+        Entry->Next->Volatile = Volatile;\r
+      }\r
+\r
+    }\r
+  }\r
+}\r
+\r
+\r
+/**\r
 \r
   This code checks if variable header is valid or not.\r
 \r
-Arguments:\r
-  Variable              Pointer to the Variable Header.\r
+  @param Variable        Pointer to the Variable Header.\r
 \r
-Returns:\r
-  TRUE            Variable header is valid.\r
-  FALSE           Variable header is not valid.\r
+  @retval TRUE           Variable header is valid.\r
+  @retval FALSE          Variable header is not valid.\r
 \r
---*/\r
+**/\r
+BOOLEAN\r
+IsValidVariableHeader (\r
+  IN  VARIABLE_HEADER   *Variable\r
+  )\r
 {\r
-  if (Variable == NULL ||\r
-      Variable->StartId != VARIABLE_DATA ||\r
-      (sizeof (VARIABLE_HEADER) + Variable->NameSize + Variable->DataSize) > MAX_VARIABLE_SIZE\r
-      ) {\r
+  if (Variable == NULL || Variable->StartId != VARIABLE_DATA) {\r
     return FALSE;\r
   }\r
 \r
   return TRUE;\r
 }\r
 \r
-STATIC\r
+\r
+/**\r
+\r
+  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 Instance                Instance of FV Block services\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
+\r
+  @retval EFI_INVALID_PARAMETER  Parameters not valid\r
+  @retval EFI_SUCCESS            Variable store successfully updated\r
+\r
+**/\r
 EFI_STATUS\r
-EFIAPI\r
 UpdateVariableStore (\r
   IN  VARIABLE_GLOBAL         *Global,\r
   IN  BOOLEAN                 Volatile,\r
@@ -103,31 +233,6 @@ UpdateVariableStore (
   IN  UINT32                  DataSize,\r
   IN  UINT8                   *Buffer\r
   )\r
-/*++\r
-\r
-Routine Description:\r
-\r
-  This function writes data to the FWH at the correct LBA even if the LBAs\r
-  are fragmented.\r
-\r
-Arguments:\r
-\r
-  Global            - Pointer to VARAIBLE_GLOBAL structure\r
-  Volatile          - If the Variable is Volatile or Non-Volatile\r
-  SetByIndex        - TRUE: Target pointer is given as index\r
-                      FALSE: Target pointer is absolute\r
-  Instance          - Instance of FV Block services\r
-  DataPtrIndex      - Pointer to the Data from the end of VARIABLE_STORE_HEADER\r
-                      structure\r
-  DataSize          - Size of data to be written.\r
-  Buffer            - Pointer to the buffer from which data is written\r
-\r
-Returns:\r
-\r
-  EFI_INVALID_PARAMETER   - Parameters not valid\r
-  EFI_SUCCESS             - Variable store successfully updated\r
-\r
---*/\r
 {\r
   EFI_FV_BLOCK_MAP_ENTRY      *PtrBlockMapEntry;\r
   UINTN                       BlockIndex2;\r
@@ -157,7 +262,7 @@ Returns:
     // written\r
     //\r
     if (SetByIndex) {\r
-      DataPtr += Global->NonVolatileVariableBase;\r
+      DataPtr += mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase;\r
     }\r
 \r
     if ((DataPtr + DataSize) >= ((EFI_PHYSICAL_ADDRESS) (UINTN) ((UINT8 *) FwVolHeader + FwVolHeader->FvLength))) {\r
@@ -168,9 +273,9 @@ Returns:
     // Data Pointer should point to the actual Address where data is to be\r
     // written\r
     //\r
-    VolatileBase = (VARIABLE_STORE_HEADER *) ((UINTN) Global->VolatileVariableBase);\r
+    VolatileBase = (VARIABLE_STORE_HEADER *) ((UINTN) mVariableModuleGlobal->VariableGlobal.VolatileVariableBase);\r
     if (SetByIndex) {\r
-      DataPtr += Global->VolatileVariableBase;\r
+      DataPtr += mVariableModuleGlobal->VariableGlobal.VolatileVariableBase;\r
     }\r
 \r
     if ((DataPtr + DataSize) >= ((UINTN) ((UINT8 *) VolatileBase + VolatileBase->Size))) {\r
@@ -240,40 +345,36 @@ Returns:
   return EFI_SUCCESS;\r
 }\r
 \r
-STATIC\r
-VARIABLE_STORE_STATUS\r
-EFIAPI\r
-GetVariableStoreStatus (\r
-  IN VARIABLE_STORE_HEADER *VarStoreHeader\r
-  )\r
-/*++\r
 \r
-Routine Description:\r
+/**\r
 \r
   This code gets the current status of Variable Store.\r
 \r
-Arguments:\r
-\r
-  VarStoreHeader  Pointer to the Variable Store Header.\r
+  @param VarStoreHeader  Pointer to the Variable Store Header.\r
 \r
-Returns:\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
-  EfiRaw        Variable store status is raw\r
-  EfiValid      Variable store status is valid\r
-  EfiInvalid    Variable store status is invalid\r
-\r
---*/\r
+**/\r
+VARIABLE_STORE_STATUS\r
+GetVariableStoreStatus (\r
+  IN VARIABLE_STORE_HEADER *VarStoreHeader\r
+  )\r
 {\r
-  if (VarStoreHeader->Signature == VARIABLE_STORE_SIGNATURE &&\r
+  if (CompareGuid (&VarStoreHeader->Signature, &gEfiVariableGuid) &&\r
       VarStoreHeader->Format == VARIABLE_STORE_FORMATTED &&\r
       VarStoreHeader->State == VARIABLE_STORE_HEALTHY\r
       ) {\r
 \r
     return EfiValid;\r
-  } else if (VarStoreHeader->Signature == 0xffffffff &&\r
-           VarStoreHeader->Size == 0xffffffff &&\r
-           VarStoreHeader->Format == 0xff &&\r
-           VarStoreHeader->State == 0xff\r
+  } else if (((UINT32 *)(&VarStoreHeader->Signature))[0] == 0xffffffff &&\r
+             ((UINT32 *)(&VarStoreHeader->Signature))[1] == 0xffffffff &&\r
+             ((UINT32 *)(&VarStoreHeader->Signature))[2] == 0xffffffff &&\r
+             ((UINT32 *)(&VarStoreHeader->Signature))[3] == 0xffffffff &&\r
+             VarStoreHeader->Size == 0xffffffff &&\r
+             VarStoreHeader->Format == 0xff &&\r
+             VarStoreHeader->State == 0xff\r
           ) {\r
 \r
     return EfiRaw;\r
@@ -282,174 +383,334 @@ Returns:
   }\r
 }\r
 \r
-STATIC\r
-UINT8 *\r
-EFIAPI\r
-GetVariableDataPtr (\r
+\r
+/**\r
+\r
+  This code gets the size of name of variable.\r
+\r
+  @param Variable        Pointer to the Variable Header\r
+\r
+  @return UINTN          Size of variable in bytes\r
+\r
+**/\r
+UINTN\r
+NameSizeOfVariable (\r
   IN  VARIABLE_HEADER   *Variable\r
   )\r
-/*++\r
+{\r
+  if (Variable->State    == (UINT8) (-1) ||\r
+      Variable->DataSize == (UINT32) (-1) ||\r
+      Variable->NameSize == (UINT32) (-1) ||\r
+      Variable->Attributes == (UINT32) (-1)) {\r
+    return 0;\r
+  }\r
+  return (UINTN) Variable->NameSize;\r
+}\r
 \r
-Routine Description:\r
+/**\r
 \r
-  This code gets the pointer to the variable data.\r
+  This code gets the size of variable data.\r
+\r
+  @param Variable        Pointer to the Variable Header\r
+\r
+  @return Size of variable in bytes\r
+\r
+**/\r
+UINTN\r
+DataSizeOfVariable (\r
+  IN  VARIABLE_HEADER   *Variable\r
+  )\r
+{\r
+  if (Variable->State    == (UINT8)  (-1) ||\r
+      Variable->DataSize == (UINT32) (-1) ||\r
+      Variable->NameSize == (UINT32) (-1) ||\r
+      Variable->Attributes == (UINT32) (-1)) {\r
+    return 0;\r
+  }\r
+  return (UINTN) Variable->DataSize;\r
+}\r
 \r
-Arguments:\r
+/**\r
 \r
-  Variable            Pointer to the Variable Header.\r
+  This code gets the pointer to the variable name.\r
 \r
-Returns:\r
+  @param Variable        Pointer to the Variable Header\r
 \r
-  UINT8*              Pointer to Variable Data\r
+  @return Pointer to Variable Name which is Unicode encoding\r
 \r
---*/\r
+**/\r
+CHAR16 *\r
+GetVariableNamePtr (\r
+  IN  VARIABLE_HEADER   *Variable\r
+  )\r
 {\r
-  //\r
-  // Be careful about pad size for alignment\r
-  //\r
-  return (UINT8 *) ((UINTN) GET_VARIABLE_NAME_PTR (Variable) + Variable->NameSize + GET_PAD_SIZE (Variable->NameSize));\r
+\r
+  return (CHAR16 *) (Variable + 1);\r
 }\r
 \r
-STATIC\r
-VARIABLE_HEADER *\r
-GetNextVariablePtr (\r
+/**\r
+\r
+  This code gets the pointer to the variable data.\r
+\r
+  @param Variable        Pointer to the Variable Header\r
+\r
+  @return Pointer to Variable Data\r
+\r
+**/\r
+UINT8 *\r
+GetVariableDataPtr (\r
   IN  VARIABLE_HEADER   *Variable\r
   )\r
-/*++\r
+{\r
+  UINTN Value;\r
+  \r
+  //\r
+  // Be careful about pad size for alignment\r
+  //\r
+  Value =  (UINTN) GetVariableNamePtr (Variable);\r
+  Value += NameSizeOfVariable (Variable);\r
+  Value += GET_PAD_SIZE (NameSizeOfVariable (Variable));\r
 \r
-Routine Description:\r
+  return (UINT8 *) Value;\r
+}\r
 \r
-  This code gets the pointer to the next variable header.\r
 \r
-Arguments:\r
+/**\r
 \r
-  Variable              Pointer to the Variable Header.\r
+  This code gets the pointer to the next variable header.\r
 \r
-Returns:\r
+  @param Variable        Pointer to the Variable Header\r
 \r
-  VARIABLE_HEADER*      Pointer to next variable header.\r
+  @return Pointer to next variable header\r
 \r
---*/\r
+**/\r
+VARIABLE_HEADER *\r
+GetNextVariablePtr (\r
+  IN  VARIABLE_HEADER   *Variable\r
+  )\r
 {\r
+  UINTN Value;\r
+\r
   if (!IsValidVariableHeader (Variable)) {\r
     return NULL;\r
   }\r
+\r
+  Value =  (UINTN) GetVariableDataPtr (Variable);\r
+  Value += DataSizeOfVariable (Variable);\r
+  Value += GET_PAD_SIZE (DataSizeOfVariable (Variable));\r
+\r
   //\r
   // Be careful about pad size for alignment\r
   //\r
-  return (VARIABLE_HEADER *) ((UINTN) GetVariableDataPtr (Variable) + Variable->DataSize + GET_PAD_SIZE (Variable->DataSize));\r
+  return (VARIABLE_HEADER *) HEADER_ALIGN (Value);\r
 }\r
 \r
-STATIC\r
+/**\r
+\r
+  Gets the pointer to the first variable header in given variable store area.\r
+\r
+  @param VarStoreHeader  Pointer to the Variable Store Header.\r
+\r
+  @return Pointer to the first variable header\r
+\r
+**/\r
 VARIABLE_HEADER *\r
-EFIAPI\r
-GetEndPointer (\r
+GetStartPointer (\r
   IN VARIABLE_STORE_HEADER       *VarStoreHeader\r
   )\r
-/*++\r
-\r
-Routine Description:\r
+{\r
+  //\r
+  // The end of variable store\r
+  //\r
+  return (VARIABLE_HEADER *) HEADER_ALIGN (VarStoreHeader + 1);\r
+}\r
 \r
-  This code gets the pointer to the last variable memory pointer byte\r
+/**\r
 \r
-Arguments:\r
+  Gets the pointer to the end of the variable storage area.\r
 \r
-  VarStoreHeader        Pointer to the Variable Store Header.\r
+  This function gets pointer to the end of the variable storage\r
+  area, according to the input variable store header.\r
 \r
-Returns:\r
+  @param VarStoreHeader  Pointer to the Variable Store Header\r
 \r
-  VARIABLE_HEADER*      Pointer to last unavailable Variable Header\r
+  @return Pointer to the end of the variable storage area  \r
 \r
---*/\r
+**/\r
+VARIABLE_HEADER *\r
+GetEndPointer (\r
+  IN VARIABLE_STORE_HEADER       *VarStoreHeader\r
+  )\r
 {\r
   //\r
   // The end of variable store\r
   //\r
-  return (VARIABLE_HEADER *) ((UINTN) VarStoreHeader + VarStoreHeader->Size);\r
+  return (VARIABLE_HEADER *) HEADER_ALIGN ((UINTN) VarStoreHeader + VarStoreHeader->Size);\r
 }\r
 \r
-STATIC\r
-EFI_STATUS\r
-EFIAPI\r
-Reclaim (\r
-  IN  EFI_PHYSICAL_ADDRESS  VariableBase,\r
-  OUT UINTN                 *LastVariableOffset,\r
-  IN  BOOLEAN               IsVolatile\r
-  )\r
-/*++\r
-\r
-Routine Description:\r
-\r
-  Variable store garbage collection and reclaim operation\r
 \r
-Arguments:\r
+/**\r
 \r
-  VariableBase                Base address of variable store\r
-  LastVariableOffset          Offset of last variable\r
-  IsVolatile                  The variable store is volatile or not,\r
-                              if it is non-volatile, need FTW\r
+  Variable store garbage collection and reclaim operation.\r
 \r
-Returns:\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
 \r
-  EFI STATUS\r
+  @return EFI_OUT_OF_RESOURCES\r
+  @return EFI_SUCCESS\r
+  @return Others\r
 \r
---*/\r
+**/\r
+EFI_STATUS\r
+Reclaim (\r
+  IN  EFI_PHYSICAL_ADDRESS  VariableBase,\r
+  OUT UINTN                 *LastVariableOffset,\r
+  IN  BOOLEAN               IsVolatile,\r
+  IN  VARIABLE_HEADER       *UpdatingVariable\r
+  )\r
 {\r
   VARIABLE_HEADER       *Variable;\r
+  VARIABLE_HEADER       *AddedVariable;\r
   VARIABLE_HEADER       *NextVariable;\r
+  VARIABLE_HEADER       *NextAddedVariable;\r
   VARIABLE_STORE_HEADER *VariableStoreHeader;\r
   UINT8                 *ValidBuffer;\r
-  UINTN                 ValidBufferSize;\r
+  UINTN                 MaximumBufferSize;\r
   UINTN                 VariableSize;\r
+  UINTN                 VariableNameSize;\r
+  UINTN                 UpdatingVariableNameSize;\r
+  UINTN                 NameSize;\r
   UINT8                 *CurrPtr;\r
+  VOID                  *Point0;\r
+  VOID                  *Point1;\r
+  BOOLEAN               FoundAdded;\r
   EFI_STATUS            Status;\r
+  CHAR16                *VariableNamePtr;\r
+  CHAR16                *UpdatingVariableNamePtr;\r
 \r
   VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINTN) VariableBase);\r
 \r
   //\r
   // Start Pointers for the variable.\r
   //\r
-  Variable        = (VARIABLE_HEADER *) (VariableStoreHeader + 1);\r
-\r
-  ValidBufferSize = sizeof (VARIABLE_STORE_HEADER);\r
+  Variable          = GetStartPointer (VariableStoreHeader);\r
+  MaximumBufferSize = sizeof (VARIABLE_STORE_HEADER);\r
 \r
   while (IsValidVariableHeader (Variable)) {\r
     NextVariable = GetNextVariablePtr (Variable);\r
-    if (Variable->State == VAR_ADDED) {\r
+    if (Variable->State == VAR_ADDED || \r
+        Variable->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)\r
+       ) {\r
       VariableSize = (UINTN) NextVariable - (UINTN) Variable;\r
-      ValidBufferSize += VariableSize;\r
+      MaximumBufferSize += VariableSize;\r
     }\r
 \r
     Variable = NextVariable;\r
   }\r
 \r
-  ValidBuffer = AllocatePool (ValidBufferSize);\r
+  //\r
+  // Reserve the 1 Bytes with Oxff to identify the \r
+  // end of the variable buffer. \r
+  // \r
+  MaximumBufferSize += 1;\r
+  ValidBuffer = AllocatePool (MaximumBufferSize);\r
   if (ValidBuffer == NULL) {\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
-  SetMem (ValidBuffer, ValidBufferSize, 0xff);\r
-\r
-  CurrPtr = ValidBuffer;\r
+  SetMem (ValidBuffer, MaximumBufferSize, 0xff);\r
 \r
   //\r
   // Copy variable store header\r
   //\r
-  CopyMem (CurrPtr, VariableStoreHeader, sizeof (VARIABLE_STORE_HEADER));\r
-  CurrPtr += sizeof (VARIABLE_STORE_HEADER);\r
+  CopyMem (ValidBuffer, VariableStoreHeader, sizeof (VARIABLE_STORE_HEADER));\r
+  CurrPtr = (UINT8 *) GetStartPointer ((VARIABLE_STORE_HEADER *) ValidBuffer);\r
 \r
   //\r
-  // Start Pointers for the variable.\r
-  //\r
-  Variable = (VARIABLE_HEADER *) (VariableStoreHeader + 1);\r
-\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
     NextVariable = GetNextVariablePtr (Variable);\r
     if (Variable->State == VAR_ADDED) {\r
+      if (UpdatingVariable != NULL) {\r
+        if (UpdatingVariable == Variable) {\r
+          Variable = NextVariable;\r
+          continue;\r
+        }\r
+\r
+        VariableNameSize         = NameSizeOfVariable(Variable);\r
+        UpdatingVariableNameSize = NameSizeOfVariable(UpdatingVariable);\r
+\r
+        VariableNamePtr         = GetVariableNamePtr (Variable);\r
+        UpdatingVariableNamePtr = GetVariableNamePtr (UpdatingVariable);\r
+        if (CompareGuid (&Variable->VendorGuid, &UpdatingVariable->VendorGuid)    &&\r
+            VariableNameSize == UpdatingVariableNameSize &&\r
+            CompareMem (VariableNamePtr, UpdatingVariableNamePtr, VariableNameSize) == 0 ) {\r
+          Variable = NextVariable;\r
+          continue;\r
+        }\r
+      }\r
       VariableSize = (UINTN) NextVariable - (UINTN) Variable;\r
       CopyMem (CurrPtr, (UINT8 *) Variable, VariableSize);\r
       CurrPtr += VariableSize;\r
     }\r
+    Variable = NextVariable;\r
+  }\r
+\r
+  //\r
+  // Reinstall the variable being updated if it is not NULL\r
+  //\r
+  if (UpdatingVariable != NULL) {\r
+    VariableSize = (UINTN)(GetNextVariablePtr (UpdatingVariable)) - (UINTN)UpdatingVariable;\r
+    CopyMem (CurrPtr, (UINT8 *) UpdatingVariable, VariableSize);\r
+    CurrPtr += VariableSize;\r
+  }\r
+\r
+  //\r
+  // Reinstall all in delete transition variables\r
+  // \r
+  Variable      = GetStartPointer (VariableStoreHeader);\r
+  while (IsValidVariableHeader (Variable)) {\r
+    NextVariable = GetNextVariablePtr (Variable);\r
+    if (Variable != UpdatingVariable && Variable->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {\r
+\r
+      //\r
+      // Buffer has cached all ADDED variable. \r
+      // Per IN_DELETED variable, we have to guarantee that\r
+      // no ADDED one in previous buffer. \r
+      // \r
+     \r
+      FoundAdded = FALSE;\r
+      AddedVariable = GetStartPointer ((VARIABLE_STORE_HEADER *) ValidBuffer);\r
+      while (IsValidVariableHeader (AddedVariable)) {\r
+        NextAddedVariable = GetNextVariablePtr (AddedVariable);\r
+        NameSize = NameSizeOfVariable (AddedVariable);\r
+        if (CompareGuid (&AddedVariable->VendorGuid, &Variable->VendorGuid) &&\r
+            NameSize == NameSizeOfVariable (Variable)\r
+           ) {\r
+          Point0 = (VOID *) GetVariableNamePtr (AddedVariable);\r
+          Point1 = (VOID *) GetVariableNamePtr (Variable);\r
+          if (CompareMem (Point0, Point1, NameSizeOfVariable (AddedVariable)) == 0) {\r
+            FoundAdded = TRUE;\r
+            break;\r
+          }\r
+        }\r
+        AddedVariable = NextAddedVariable;\r
+      }\r
+      if (!FoundAdded) {\r
+        //\r
+        // Promote VAR_IN_DELETED_TRANSITION to VAR_ADDED\r
+        //\r
+        VariableSize = (UINTN) NextVariable - (UINTN) Variable;\r
+        CopyMem (CurrPtr, (UINT8 *) Variable, VariableSize);\r
+        ((VARIABLE_HEADER *) CurrPtr)->State = VAR_ADDED;\r
+        CurrPtr += VariableSize;\r
+      }\r
+    }\r
 \r
     Variable = NextVariable;\r
   }\r
@@ -459,8 +720,7 @@ Returns:
     // If volatile variable store, just copy valid buffer\r
     //\r
     SetMem ((UINT8 *) (UINTN) VariableBase, VariableStoreHeader->Size, 0xff);\r
-    CopyMem ((UINT8 *) (UINTN) VariableBase, ValidBuffer, ValidBufferSize);\r
-    *LastVariableOffset = ValidBufferSize;\r
+    CopyMem ((UINT8 *) (UINTN) VariableBase, ValidBuffer, (UINTN) (CurrPtr - (UINT8 *) ValidBuffer));\r
     Status              = EFI_SUCCESS;\r
   } else {\r
     //\r
@@ -469,99 +729,237 @@ Returns:
     Status = FtwVariableSpace (\r
               VariableBase,\r
               ValidBuffer,\r
-              ValidBufferSize\r
+              (UINTN) (CurrPtr - (UINT8 *) ValidBuffer)\r
               );\r
-    if (!EFI_ERROR (Status)) {\r
-      *LastVariableOffset = ValidBufferSize;\r
-    }\r
+  }\r
+  if (!EFI_ERROR (Status)) {\r
+    *LastVariableOffset = (UINTN) (CurrPtr - (UINT8 *) ValidBuffer);\r
+  } else {\r
+    *LastVariableOffset = 0;\r
   }\r
 \r
   FreePool (ValidBuffer);\r
 \r
-  if (EFI_ERROR (Status)) {\r
-    *LastVariableOffset = 0;\r
+  return Status;\r
+}\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
-  return Status;\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
-STATIC\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
-EFIAPI\r
-FindVariable (\r
-  IN  CHAR16                  *VariableName,\r
-  IN  EFI_GUID                *VendorGuid,\r
-  OUT VARIABLE_POINTER_TRACK  *PtrTrack,\r
-  IN  VARIABLE_GLOBAL         *Global\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
+{\r
+  VARIABLE_CACHE_ENTRY      *Entry;\r
+  UINTN                     Index;\r
 \r
-Routine Description:\r
+  if (EfiAtRuntime ()) {\r
+    // Don't use the cache at runtime\r
+    return EFI_NOT_FOUND;\r
+  }\r
 \r
-  This code finds variable in storage blocks (Volatile or Non-Volatile)\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
-Arguments:\r
+/**\r
+  Finds variable in storage blocks of volatile and non-volatile storage areas.\r
 \r
-  VariableName                Name of the variable to be found\r
-  VendorGuid                  Vendor GUID to be found.\r
-  PtrTrack                    Variable Track Pointer structure that contains\r
-                              Variable Information.\r
-                              Contains the pointer of Variable header.\r
-  Global                      VARIABLE_GLOBAL pointer\r
+  This code finds variable in storage blocks of volatile and non-volatile storage areas.\r
+  If VariableName is an empty string, then we just return the first\r
+  qualified variable without comparing VariableName and VendorGuid.\r
+  Otherwise, VariableName and VendorGuid are compared.\r
 \r
-Returns:\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
+  @param  Global                      Pointer to VARIABLE_GLOBAL structure, including\r
+                                      base of volatile variable storage area, base of\r
+                                      NV variable storage area, and a lock.\r
 \r
-  EFI STATUS\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
+  @retval EFI_INVALID_PARAMETER       Variable not found\r
 \r
---*/\r
+**/\r
+EFI_STATUS\r
+FindVariable (\r
+  IN  CHAR16                  *VariableName,\r
+  IN  EFI_GUID                *VendorGuid,\r
+  OUT VARIABLE_POINTER_TRACK  *PtrTrack,\r
+  IN  VARIABLE_GLOBAL         *Global\r
+  )\r
 {\r
-  VARIABLE_HEADER       *Variable[2];\r
-  VARIABLE_STORE_HEADER *VariableStoreHeader[2];\r
-  UINTN                 Index;\r
-\r
-  //\r
-  // We aquire the lock at the entry of FindVariable as GetVariable, GetNextVariableName\r
-  // SetVariable all call FindVariable at entry point. Please move "Aquire Lock" to\r
-  // the correct places if this assumption does not hold TRUE anymore.\r
-  //\r
-  AcquireLockOnlyAtBootTime(&Global->VariableServicesLock);\r
+  VARIABLE_HEADER         *Variable[2];\r
+  VARIABLE_HEADER         *InDeletedVariable;\r
+  VARIABLE_STORE_HEADER   *VariableStoreHeader[2];\r
+  UINTN                   InDeletedStorageIndex;\r
+  UINTN                   Index;\r
+  VOID                    *Point;\r
 \r
   //\r
-  // 0: Non-Volatile, 1: 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
   //\r
-  VariableStoreHeader[0]  = (VARIABLE_STORE_HEADER *) ((UINTN) Global->NonVolatileVariableBase);\r
-  VariableStoreHeader[1]  = (VARIABLE_STORE_HEADER *) ((UINTN) Global->VolatileVariableBase);\r
+  VariableStoreHeader[0]  = (VARIABLE_STORE_HEADER *) ((UINTN) mVariableModuleGlobal->VariableGlobal.VolatileVariableBase);\r
+  VariableStoreHeader[1]  = (VARIABLE_STORE_HEADER *) ((UINTN) mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase);\r
 \r
   //\r
   // Start Pointers for the variable.\r
   // Actual Data Pointer where data can be written.\r
   //\r
-  Variable[0] = (VARIABLE_HEADER *) (VariableStoreHeader[0] + 1);\r
-  Variable[1] = (VARIABLE_HEADER *) (VariableStoreHeader[1] + 1);\r
+  Variable[0] = GetStartPointer (VariableStoreHeader[0]);\r
+  Variable[1] = GetStartPointer (VariableStoreHeader[1]);\r
 \r
   if (VariableName[0] != 0 && VendorGuid == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
+\r
   //\r
-  // Find the variable by walk through non-volatile and 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
   for (Index = 0; Index < 2; Index++) {\r
-    PtrTrack->StartPtr  = (VARIABLE_HEADER *) (VariableStoreHeader[Index] + 1);\r
-    PtrTrack->EndPtr    = GetEndPointer (VariableStoreHeader[Index]);\r
-\r
     while (IsValidVariableHeader (Variable[Index]) && (Variable[Index] <= GetEndPointer (VariableStoreHeader[Index]))) {\r
-      if (Variable[Index]->State == VAR_ADDED) {\r
-        if (!EfiAtRuntime () || (Variable[Index]->Attributes & EFI_VARIABLE_RUNTIME_ACCESS)) {\r
+      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 (VariableName[0] == 0) {\r
-            PtrTrack->CurrPtr   = Variable[Index];\r
-            PtrTrack->Volatile  = (BOOLEAN) Index;\r
-            return EFI_SUCCESS;\r
+            if (Variable[Index]->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {\r
+              InDeletedVariable     = Variable[Index];\r
+              InDeletedStorageIndex = Index;\r
+            } else {\r
+              PtrTrack->StartPtr  = GetStartPointer (VariableStoreHeader[Index]);\r
+              PtrTrack->EndPtr    = GetEndPointer (VariableStoreHeader[Index]);\r
+              PtrTrack->CurrPtr   = Variable[Index];\r
+              PtrTrack->Volatile  = (BOOLEAN)(Index == 0);\r
+\r
+              return EFI_SUCCESS;\r
+            }\r
           } else {\r
             if (CompareGuid (VendorGuid, &Variable[Index]->VendorGuid)) {\r
-              if (!CompareMem (VariableName, GET_VARIABLE_NAME_PTR (Variable[Index]), Variable[Index]->NameSize)) {\r
-                PtrTrack->CurrPtr   = Variable[Index];\r
-                PtrTrack->Volatile  = (BOOLEAN) Index;\r
-                return EFI_SUCCESS;\r
+              Point = (VOID *) GetVariableNamePtr (Variable[Index]);\r
+\r
+              ASSERT (NameSizeOfVariable (Variable[Index]) != 0);\r
+              if (CompareMem (VariableName, Point, NameSizeOfVariable (Variable[Index])) == 0) {\r
+                if (Variable[Index]->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {\r
+                  InDeletedVariable     = Variable[Index];\r
+                  InDeletedStorageIndex = Index;\r
+                } else {\r
+                  PtrTrack->StartPtr  = GetStartPointer (VariableStoreHeader[Index]);\r
+                  PtrTrack->EndPtr    = GetEndPointer (VariableStoreHeader[Index]);\r
+                  PtrTrack->CurrPtr   = Variable[Index];\r
+                  PtrTrack->Volatile  = (BOOLEAN)(Index == 0);\r
+\r
+                  return EFI_SUCCESS;\r
+                }\r
               }\r
             }\r
           }\r
@@ -570,74 +968,77 @@ Returns:
 \r
       Variable[Index] = GetNextVariablePtr (Variable[Index]);\r
     }\r
-    //\r
-    // While (...)\r
-    //\r
+    if (InDeletedVariable != NULL) {\r
+      PtrTrack->StartPtr  = GetStartPointer (VariableStoreHeader[InDeletedStorageIndex]);\r
+      PtrTrack->EndPtr    = GetEndPointer (VariableStoreHeader[InDeletedStorageIndex]);\r
+      PtrTrack->CurrPtr   = InDeletedVariable;\r
+      PtrTrack->Volatile  = (BOOLEAN)(InDeletedStorageIndex == 0);\r
+      return EFI_SUCCESS;\r
+    }\r
   }\r
-  //\r
-  // for (...)\r
-  //\r
   PtrTrack->CurrPtr = NULL;\r
   return EFI_NOT_FOUND;\r
 }\r
 \r
+\r
+/**\r
+\r
+  This code finds 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 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
+                      \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
-GetVariable (\r
+RuntimeServiceGetVariable (\r
   IN      CHAR16            *VariableName,\r
   IN      EFI_GUID          *VendorGuid,\r
   OUT     UINT32            *Attributes OPTIONAL,\r
   IN OUT  UINTN             *DataSize,\r
-  OUT     VOID              *Data,\r
-  IN      VARIABLE_GLOBAL   *Global,\r
-  IN      UINT32            Instance\r
+  OUT     VOID              *Data\r
   )\r
-/*++\r
-\r
-Routine Description:\r
-\r
-  This code finds variable in storage blocks (Volatile or Non-Volatile)\r
-\r
-Arguments:\r
-\r
-  VariableName                Name of Variable to be found\r
-  VendorGuid                  Variable vendor GUID\r
-  Attributes OPTIONAL         Attribute value of the variable found\r
-  DataSize                    Size of Data found. If size is less than the\r
-                              data, this value contains the required size.\r
-  Data                        Data pointer\r
-  Global                      Pointer to VARIABLE_GLOBAL structure\r
-  Instance                    Instance of the Firmware Volume.\r
-\r
-Returns:\r
-\r
-  EFI_INVALID_PARAMETER       - Invalid parameter\r
-  EFI_SUCCESS                 - Find the specified variable\r
-  EFI_NOT_FOUND               - Not found\r
-  EFI_BUFFER_TO_SMALL         - DataSize is too small for the result\r
-\r
-\r
---*/\r
 {\r
+  EFI_STATUS              Status;\r
   VARIABLE_POINTER_TRACK  Variable;\r
   UINTN                   VarDataSize;\r
-  EFI_STATUS              Status;\r
 \r
   if (VariableName == NULL || VendorGuid == NULL || DataSize == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
+\r
+  AcquireLockOnlyAtBootTime(&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);\r
+\r
   //\r
   // Find existing variable\r
   //\r
-  Status = FindVariable (VariableName, VendorGuid, &Variable, Global);\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
     goto Done;\r
   }\r
+\r
   //\r
   // Get data size\r
   //\r
-  VarDataSize = Variable.CurrPtr->DataSize;\r
+  VarDataSize = DataSizeOfVariable (Variable.CurrPtr);\r
+  ASSERT (VarDataSize != 0);\r
+\r
   if (*DataSize >= VarDataSize) {\r
     if (Data == NULL) {\r
       Status = EFI_INVALID_PARAMETER;\r
@@ -650,6 +1051,9 @@ Returns:
     }\r
 \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
   } else {\r
@@ -659,38 +1063,33 @@ Returns:
   }\r
 \r
 Done:\r
-  ReleaseLockOnlyAtBootTime (&Global->VariableServicesLock);\r
+  ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);\r
   return Status;\r
 }\r
 \r
-EFI_STATUS\r
-EFIAPI\r
-GetNextVariableName (\r
-  IN OUT  UINTN             *VariableNameSize,\r
-  IN OUT  CHAR16            *VariableName,\r
-  IN OUT  EFI_GUID          *VendorGuid,\r
-  IN      VARIABLE_GLOBAL   *Global,\r
-  IN      UINT32            Instance\r
-  )\r
-/*++\r
-\r
-Routine Description:\r
 \r
-  This code Finds the Next available variable\r
 \r
-Arguments:\r
+/**\r
 \r
-  VariableNameSize            Size of the variable\r
-  VariableName                Pointer to variable name\r
-  VendorGuid                  Variable Vendor Guid\r
-  Global                      VARIABLE_GLOBAL structure pointer.\r
-  Instance                    FV instance\r
+  This code Finds the Next available variable.\r
 \r
-Returns:\r
+  @param VariableNameSize           Size of the variable name\r
+  @param VariableName               Pointer to variable name\r
+  @param VendorGuid                 Variable Vendor Guid\r
 \r
-  EFI STATUS\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
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RuntimeServiceGetNextVariableName (\r
+  IN OUT  UINTN             *VariableNameSize,\r
+  IN OUT  CHAR16            *VariableName,\r
+  IN OUT  EFI_GUID          *VendorGuid\r
+  )\r
 {\r
   VARIABLE_POINTER_TRACK  Variable;\r
   UINTN                   VarNameSize;\r
@@ -700,8 +1099,9 @@ Returns:
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  Status = FindVariable (VariableName, VendorGuid, &Variable, Global);\r
+  AcquireLockOnlyAtBootTime(&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);\r
 \r
+  Status = FindVariable (VariableName, VendorGuid, &Variable, &mVariableModuleGlobal->VariableGlobal);\r
   if (Variable.CurrPtr == NULL || EFI_ERROR (Status)) {\r
     goto Done;\r
   }\r
@@ -720,9 +1120,9 @@ Returns:
     //\r
     if (Variable.CurrPtr >= Variable.EndPtr || Variable.CurrPtr == NULL) {\r
       Variable.Volatile = (BOOLEAN) (Variable.Volatile ^ ((BOOLEAN) 0x1));\r
-      if (Variable.Volatile) {\r
-        Variable.StartPtr = (VARIABLE_HEADER *) ((UINTN) (Global->VolatileVariableBase + sizeof (VARIABLE_STORE_HEADER)));\r
-        Variable.EndPtr = (VARIABLE_HEADER *) GetEndPointer ((VARIABLE_STORE_HEADER *) ((UINTN) Global->VolatileVariableBase));\r
+      if (!Variable.Volatile) {\r
+        Variable.StartPtr = GetStartPointer ((VARIABLE_STORE_HEADER *) (UINTN) mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase);\r
+        Variable.EndPtr   = GetEndPointer ((VARIABLE_STORE_HEADER *) ((UINTN) mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase));\r
       } else {\r
         Status = EFI_NOT_FOUND;\r
         goto Done;\r
@@ -737,12 +1137,14 @@ Returns:
     // Variable is found\r
     //\r
     if (IsValidVariableHeader (Variable.CurrPtr) && Variable.CurrPtr->State == VAR_ADDED) {\r
-      if (!(EfiAtRuntime () && !(Variable.CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS))) {\r
-        VarNameSize = Variable.CurrPtr->NameSize;\r
+      if ((EfiAtRuntime () && ((Variable.CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0)) == 0) {\r
+        VarNameSize = NameSizeOfVariable (Variable.CurrPtr);\r
+        ASSERT (VarNameSize != 0);\r
+\r
         if (VarNameSize <= *VariableNameSize) {\r
           CopyMem (\r
             VariableName,\r
-            GET_VARIABLE_NAME_PTR (Variable.CurrPtr),\r
+            GetVariableNamePtr (Variable.CurrPtr),\r
             VarNameSize\r
             );\r
           CopyMem (\r
@@ -764,52 +1166,37 @@ Returns:
   }\r
 \r
 Done:\r
-  ReleaseLockOnlyAtBootTime (&Global->VariableServicesLock);\r
+  ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);\r
   return Status;\r
 }\r
 \r
+/**\r
+\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 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
+\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
-SetVariable (\r
+RuntimeServiceSetVariable (\r
   IN CHAR16                  *VariableName,\r
   IN EFI_GUID                *VendorGuid,\r
   IN UINT32                  Attributes,\r
   IN UINTN                   DataSize,\r
-  IN VOID                    *Data,\r
-  IN VARIABLE_GLOBAL         *Global,\r
-  IN UINTN                   *VolatileOffset,\r
-  IN UINTN                   *NonVolatileOffset,\r
-  IN UINT32                  Instance\r
+  IN VOID                    *Data\r
   )\r
-/*++\r
-\r
-Routine Description:\r
-\r
-  This code sets variable in storage blocks (Volatile or Non-Volatile)\r
-\r
-Arguments:\r
-\r
-  VariableName                    Name of Variable to be found\r
-  VendorGuid                      Variable vendor GUID\r
-  Attributes                      Attribute value of the variable found\r
-  DataSize                        Size of Data found. If size is less than the\r
-                                  data, this value contains the required size.\r
-  Data                            Data pointer\r
-  Global                          Pointer to VARIABLE_GLOBAL structure\r
-  VolatileOffset                  The offset of last volatile variable\r
-  NonVolatileOffset               The offset of last non-volatile variable\r
-  Instance                        Instance of the Firmware Volume.\r
-\r
-Returns:\r
-\r
-  EFI_INVALID_PARAMETER           - Invalid parameter\r
-  EFI_SUCCESS                     - Set successfully\r
-  EFI_OUT_OF_RESOURCES            - Resource not enough to set variable\r
-  EFI_NOT_FOUND                   - Not found\r
-  EFI_DEVICE_ERROR                - Variable can not be saved due to hardware failure\r
-  EFI_WRITE_PROTECTED             - Variable is read-only\r
-\r
---*/\r
 {\r
   VARIABLE_POINTER_TRACK  Variable;\r
   EFI_STATUS              Status;\r
@@ -820,8 +1207,11 @@ Returns:
   UINTN                   VarSize;\r
   UINT8                   State;\r
   BOOLEAN                 Reclaimed;\r
-\r
-  Reclaimed = FALSE;\r
+  UINTN                   *VolatileOffset;\r
+  UINTN                   *NonVolatileOffset;\r
+  UINT32                  Instance;\r
+  BOOLEAN                 Volatile;\r
+  EFI_PHYSICAL_ADDRESS    Point;\r
 \r
   //\r
   // Check input parameters\r
@@ -835,36 +1225,62 @@ Returns:
   if ((Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == EFI_VARIABLE_RUNTIME_ACCESS) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
+\r
   //\r
   //  The size of the VariableName, including the Unicode Null in bytes plus\r
-  //  the DataSize is limited to maximum size of MAX_HARDWARE_ERROR_VARIABLE_SIZE (32K)\r
-  //  bytes for HwErrRec, and MAX_VARIABLE_SIZE (1024) bytes for the others.\r
+  //  the DataSize is limited to maximum size of FixedPcdGet32(PcdMaxHardwareErrorVariableSize)\r
+  //  bytes for HwErrRec, and FixedPcdGet32(PcdMaxVariableSize) bytes for the others.\r
   //\r
   if ((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD) {\r
-    if ((DataSize > MAX_HARDWARE_ERROR_VARIABLE_SIZE) ||                                                       \r
-        (sizeof (VARIABLE_HEADER) + StrSize (VariableName) + DataSize > MAX_HARDWARE_ERROR_VARIABLE_SIZE)) {\r
+    if ((DataSize > FixedPcdGet32(PcdMaxHardwareErrorVariableSize)) ||                                                       \r
+        (sizeof (VARIABLE_HEADER) + StrSize (VariableName) + DataSize > FixedPcdGet32(PcdMaxHardwareErrorVariableSize))) {\r
       return EFI_INVALID_PARAMETER;\r
     }    \r
   } else {\r
   //\r
   //  The size of the VariableName, including the Unicode Null in bytes plus\r
-  //  the DataSize is limited to maximum size of MAX_VARIABLE_SIZE (1024) bytes.\r
+  //  the DataSize is limited to maximum size of FixedPcdGet32(PcdMaxVariableSize) bytes.\r
   //\r
-    if ((DataSize > MAX_VARIABLE_SIZE) ||\r
-        (sizeof (VARIABLE_HEADER) + StrSize (VariableName) + DataSize > MAX_VARIABLE_SIZE)) {\r
+    if ((DataSize > FixedPcdGet32(PcdMaxVariableSize)) ||\r
+        (sizeof (VARIABLE_HEADER) + StrSize (VariableName) + DataSize > FixedPcdGet32(PcdMaxVariableSize))) {\r
       return EFI_INVALID_PARAMETER;\r
     }  \r
   }  \r
+\r
+  AcquireLockOnlyAtBootTime(&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);\r
+\r
+  Reclaimed         = FALSE;\r
+  Instance          = mVariableModuleGlobal->FvbInstance;\r
+  VolatileOffset    = &mVariableModuleGlobal->VolatileLastVariableOffset;\r
+\r
   //\r
-  // Check whether the input variable is already existed\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
+    //\r
+    // Parse non-volatile variable data and get last variable offset\r
+    //\r
+    NextVariable  = GetStartPointer ((VARIABLE_STORE_HEADER *) (UINTN) Point);\r
+    while (IsValidVariableHeader (NextVariable)) {\r
+      NextVariable = GetNextVariablePtr (NextVariable);\r
+    }\r
+    mVariableModuleGlobal->NonVolatileLastVariableOffset = (UINTN) NextVariable - (UINTN) Point;\r
+  }\r
+\r
+  NonVolatileOffset = &mVariableModuleGlobal->NonVolatileLastVariableOffset;\r
   \r
-  Status = FindVariable (VariableName, VendorGuid, &Variable, Global);\r
 \r
+  //\r
+  // Check whether the input variable is already existed\r
+  //\r
+  \r
+  Status = FindVariable (VariableName, VendorGuid, &Variable, &mVariableModuleGlobal->VariableGlobal);\r
   if (Status == EFI_SUCCESS && Variable.CurrPtr != NULL) {\r
     //\r
     // Update/Delete existing variable\r
     //\r
+    Volatile = Variable.Volatile;\r
     \r
     if (EfiAtRuntime ()) {        \r
       //\r
@@ -879,7 +1295,7 @@ Returns:
       //\r
       // Only variable have NV attribute can be updated/deleted in Runtime\r
       //\r
-      if (!(Variable.CurrPtr->Attributes & EFI_VARIABLE_NON_VOLATILE)) {\r
+      if ((Variable.CurrPtr->Attributes & EFI_VARIABLE_NON_VOLATILE) == 0) {\r
         Status = EFI_INVALID_PARAMETER;\r
         goto Done;      \r
       }\r
@@ -893,7 +1309,7 @@ Returns:
       State &= VAR_DELETED;\r
 \r
       Status = UpdateVariableStore (\r
-                 Global,\r
+                 &mVariableModuleGlobal->VariableGlobal,\r
                  Variable.Volatile,\r
                  FALSE,\r
                  Instance,\r
@@ -901,18 +1317,25 @@ Returns:
                  sizeof (UINT8),\r
                  &State\r
                  ); \r
+      if (!EFI_ERROR (Status)) {\r
+        UpdateVariableInfo (VariableName, VendorGuid, Volatile, FALSE, FALSE, TRUE, FALSE);\r
+        UpdateVariableCache (VariableName, VendorGuid, Attributes, DataSize, Data);\r
+      }\r
       goto Done;     \r
     }\r
     //\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 (Variable.CurrPtr->DataSize == DataSize &&\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
       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
       //\r
@@ -920,7 +1343,7 @@ Returns:
       State &= VAR_IN_DELETED_TRANSITION;\r
 \r
       Status = UpdateVariableStore (\r
-                 Global,\r
+                 &mVariableModuleGlobal->VariableGlobal,\r
                  Variable.Volatile,\r
                  FALSE,\r
                  Instance,\r
@@ -930,7 +1353,7 @@ Returns:
                  );      \r
       if (EFI_ERROR (Status)) {\r
         goto Done;  \r
-      }\r
+      } \r
     }    \r
   } else if (Status == EFI_NOT_FOUND) {\r
     //\r
@@ -950,7 +1373,7 @@ Returns:
     // Only variable have NV|RT attribute can be created in Runtime\r
     //\r
     if (EfiAtRuntime () &&\r
-        (!(Attributes & EFI_VARIABLE_RUNTIME_ACCESS) || !(Attributes & EFI_VARIABLE_NON_VOLATILE))) {\r
+        (((Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0) || ((Attributes & EFI_VARIABLE_NON_VOLATILE) == 0))) {\r
       Status = EFI_INVALID_PARAMETER;\r
       goto Done;\r
     }         \r
@@ -969,9 +1392,9 @@ Returns:
   // Tricky part: Use scratch data area at the end of volatile variable store\r
   // as a temporary storage.\r
   //\r
-  NextVariable = GetEndPointer ((VARIABLE_STORE_HEADER *) ((UINTN) Global->VolatileVariableBase));\r
+  NextVariable = GetEndPointer ((VARIABLE_STORE_HEADER *) ((UINTN) mVariableModuleGlobal->VariableGlobal.VolatileVariableBase));\r
 \r
-  SetMem (NextVariable, SCRATCH_SIZE, 0xff);\r
+  SetMem (NextVariable, FixedPcdGet32(PcdMaxVariableSize), 0xff);\r
 \r
   NextVariable->StartId     = VARIABLE_DATA;\r
   NextVariable->Attributes  = Attributes;\r
@@ -1006,13 +1429,14 @@ Returns:
   // include pad size.\r
   //\r
   VarSize = VarDataOffset + DataSize + GET_PAD_SIZE (DataSize);\r
-  if (Attributes & EFI_VARIABLE_NON_VOLATILE) {\r
+  if ((Attributes & EFI_VARIABLE_NON_VOLATILE) != 0) {\r
     //\r
     // Create a nonvolatile variable\r
     //\r
+    Volatile = FALSE;\r
     \r
     if ((UINT32) (VarSize +*NonVolatileOffset) >\r
-          ((VARIABLE_STORE_HEADER *) ((UINTN) (Global->NonVolatileVariableBase)))->Size\r
+          ((VARIABLE_STORE_HEADER *) ((UINTN) (mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase)))->Size\r
           ) {\r
       if (EfiAtRuntime ()) {\r
         Status = EFI_OUT_OF_RESOURCES;\r
@@ -1021,7 +1445,7 @@ Returns:
       //\r
       // Perform garbage collection & reclaim operation\r
       //\r
-      Status = Reclaim (Global->NonVolatileVariableBase, NonVolatileOffset, FALSE);\r
+      Status = Reclaim (mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase, NonVolatileOffset, FALSE, Variable.CurrPtr);\r
       if (EFI_ERROR (Status)) {\r
         goto Done;\r
       }\r
@@ -1029,7 +1453,7 @@ Returns:
       // If still no enough space, return out of resources\r
       //\r
       if ((UINT32) (VarSize +*NonVolatileOffset) >\r
-            ((VARIABLE_STORE_HEADER *) ((UINTN) (Global->NonVolatileVariableBase)))->Size\r
+            ((VARIABLE_STORE_HEADER *) ((UINTN) (mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase)))->Size\r
             ) {\r
         Status = EFI_OUT_OF_RESOURCES;\r
         goto Done;\r
@@ -1040,14 +1464,15 @@ Returns:
     //\r
     // Three steps\r
     // 1. Write variable header\r
-    // 2. Write variable data\r
-    // 3. Set variable state to valid\r
+    // 2. Set variable state to header valid  \r
+    // 3. Write variable data\r
+    // 4. Set variable state to valid\r
     //\r
     //\r
     // Step 1:\r
     //\r
     Status = UpdateVariableStore (\r
-               Global,\r
+               &mVariableModuleGlobal->VariableGlobal,\r
                FALSE,\r
                TRUE,\r
                Instance,\r
@@ -1059,11 +1484,29 @@ Returns:
     if (EFI_ERROR (Status)) {\r
       goto Done;\r
     }\r
+\r
     //\r
     // Step 2:\r
     //\r
+    NextVariable->State = VAR_HEADER_VALID_ONLY;\r
+    Status = UpdateVariableStore (\r
+               &mVariableModuleGlobal->VariableGlobal,\r
+               FALSE,\r
+               TRUE,\r
+               Instance,\r
+               *NonVolatileOffset,\r
+               sizeof (VARIABLE_HEADER),\r
+               (UINT8 *) NextVariable\r
+               );\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      goto Done;\r
+    }\r
+    //\r
+    // Step 3:\r
+    //\r
     Status = UpdateVariableStore (\r
-               Global,\r
+               &mVariableModuleGlobal->VariableGlobal,\r
                FALSE,\r
                TRUE,\r
                Instance,\r
@@ -1076,11 +1519,11 @@ Returns:
       goto Done;\r
     }\r
     //\r
-    // Step 3:\r
+    // Step 4:\r
     //\r
     NextVariable->State = VAR_ADDED;\r
     Status = UpdateVariableStore (\r
-               Global,\r
+               &mVariableModuleGlobal->VariableGlobal,\r
                FALSE,\r
                TRUE,\r
                Instance,\r
@@ -1093,19 +1536,20 @@ Returns:
       goto Done;\r
     }\r
 \r
-    *NonVolatileOffset = *NonVolatileOffset + VarSize;\r
+    *NonVolatileOffset = HEADER_ALIGN (*NonVolatileOffset + VarSize);\r
 \r
   } else {\r
     //\r
     // Create a volatile variable\r
     //      \r
+    Volatile = TRUE;\r
 \r
     if ((UINT32) (VarSize +*VolatileOffset) >\r
-        ((VARIABLE_STORE_HEADER *) ((UINTN) (Global->VolatileVariableBase)))->Size) {\r
+        ((VARIABLE_STORE_HEADER *) ((UINTN) (mVariableModuleGlobal->VariableGlobal.VolatileVariableBase)))->Size) {\r
       //\r
       // Perform garbage collection & reclaim operation\r
       //\r
-      Status = Reclaim (Global->VolatileVariableBase, VolatileOffset, TRUE);\r
+      Status = Reclaim (mVariableModuleGlobal->VariableGlobal.VolatileVariableBase, VolatileOffset, TRUE, Variable.CurrPtr);\r
       if (EFI_ERROR (Status)) {\r
         goto Done;\r
       }\r
@@ -1113,7 +1557,7 @@ Returns:
       // If still no enough space, return out of resources\r
       //\r
       if ((UINT32) (VarSize +*VolatileOffset) >\r
-            ((VARIABLE_STORE_HEADER *) ((UINTN) (Global->VolatileVariableBase)))->Size\r
+            ((VARIABLE_STORE_HEADER *) ((UINTN) (mVariableModuleGlobal->VariableGlobal.VolatileVariableBase)))->Size\r
             ) {\r
         Status = EFI_OUT_OF_RESOURCES;\r
         goto Done;\r
@@ -1124,7 +1568,7 @@ Returns:
 \r
     NextVariable->State = VAR_ADDED;\r
     Status = UpdateVariableStore (\r
-               Global,\r
+               &mVariableModuleGlobal->VariableGlobal,\r
                TRUE,\r
                TRUE,\r
                Instance,\r
@@ -1137,7 +1581,7 @@ Returns:
       goto Done;\r
     }\r
 \r
-    *VolatileOffset = *VolatileOffset + VarSize;\r
+    *VolatileOffset = HEADER_ALIGN (*VolatileOffset + VarSize);\r
   }\r
   //\r
   // Mark the old variable as deleted\r
@@ -1147,7 +1591,7 @@ Returns:
     State &= VAR_DELETED;\r
 \r
     Status = UpdateVariableStore (\r
-               Global,\r
+               &mVariableModuleGlobal->VariableGlobal,\r
                Variable.Volatile,\r
                FALSE,\r
                Instance,\r
@@ -1155,52 +1599,51 @@ Returns:
                sizeof (UINT8),\r
                &State\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
     goto Done;      \r
   }\r
 \r
   Status = EFI_SUCCESS;\r
+  UpdateVariableInfo (VariableName, VendorGuid, Volatile, FALSE, TRUE, FALSE, FALSE);\r
+  UpdateVariableCache (VariableName, VendorGuid, Attributes, DataSize, Data);\r
+\r
 Done:\r
-  ReleaseLockOnlyAtBootTime (&Global->VariableServicesLock);\r
+  InterlockedDecrement (&mVariableModuleGlobal->VariableGlobal.ReentrantState);\r
+  ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);\r
+\r
   return Status;\r
 }\r
 \r
+/**\r
+\r
+  This code returns information about the EFI variables.\r
+\r
+  @param Attributes                     Attributes bitmask to specify the type of variables\r
+                                        on which to return information.\r
+  @param MaximumVariableStorageSize     Pointer to the maximum size of the storage space available\r
+                                        for the EFI variables associated with the attributes specified.\r
+  @param RemainingVariableStorageSize   Pointer to the remaining size of the storage space available\r
+                                        for EFI variables associated with the attributes specified.\r
+  @param MaximumVariableSize            Pointer to the maximum size of an individual EFI variables\r
+                                        associated with the attributes specified.\r
+\r
+  @return EFI_INVALID_PARAMETER         An invalid combination of attribute bits was supplied.\r
+  @return EFI_SUCCESS                   Query successfully.\r
+  @return EFI_UNSUPPORTED               The attribute is not supported on this platform.\r
+\r
+**/\r
 EFI_STATUS\r
 EFIAPI\r
-QueryVariableInfo (\r
+RuntimeServiceQueryVariableInfo (\r
   IN  UINT32                 Attributes,\r
   OUT UINT64                 *MaximumVariableStorageSize,\r
   OUT UINT64                 *RemainingVariableStorageSize,\r
-  OUT UINT64                 *MaximumVariableSize,\r
-  IN  VARIABLE_GLOBAL        *Global,\r
-  IN  UINT32                 Instance\r
+  OUT UINT64                 *MaximumVariableSize\r
   )\r
-/*++\r
-\r
-Routine Description:\r
-\r
-  This code returns information about the EFI variables.\r
-\r
-Arguments:\r
-\r
-  Attributes                      Attributes bitmask to specify the type of variables\r
-                                  on which to return information.\r
-  MaximumVariableStorageSize      Pointer to the maximum size of the storage space available\r
-                                  for the EFI variables associated with the attributes specified.\r
-  RemainingVariableStorageSize    Pointer to the remaining size of the storage space available\r
-                                  for EFI variables associated with the attributes specified.\r
-  MaximumVariableSize             Pointer to the maximum size of an individual EFI variables\r
-                                  associated with the attributes specified.\r
-  Global                          Pointer to VARIABLE_GLOBAL structure.\r
-  Instance                        Instance of the Firmware Volume.\r
-\r
-Returns:\r
-\r
-  EFI STATUS\r
-  EFI_INVALID_PARAMETER           - An invalid combination of attribute bits was supplied.\r
-  EFI_SUCCESS                     - Query successfully.\r
-  EFI_UNSUPPORTED                 - The attribute is not supported on this platform.\r
-\r
---*/\r
 {\r
   VARIABLE_HEADER        *Variable;\r
   VARIABLE_HEADER        *NextVariable;\r
@@ -1221,25 +1664,25 @@ Returns:
     // 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)) {\r
+  } else if (EfiAtRuntime () && ((Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0)) {\r
     //\r
     // Make sure RT Attribute is set if we are in Runtime phase.\r
     //\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  AcquireLockOnlyAtBootTime(&Global->VariableServicesLock);\r
+  AcquireLockOnlyAtBootTime(&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);\r
 \r
   if((Attributes & EFI_VARIABLE_NON_VOLATILE) == 0) {\r
     //\r
     // Query is Volatile related.\r
     //\r
-    VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINTN) Global->VolatileVariableBase);\r
+    VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINTN) mVariableModuleGlobal->VariableGlobal.VolatileVariableBase);\r
   } else {\r
     //\r
     // Query is Non-Volatile related.\r
     //\r
-    VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINTN) Global->NonVolatileVariableBase);\r
+    VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINTN) mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase);\r
   }\r
 \r
   //\r
@@ -1250,21 +1693,21 @@ Returns:
   *RemainingVariableStorageSize = VariableStoreHeader->Size - sizeof (VARIABLE_STORE_HEADER);\r
 \r
   //\r
-  // Let *MaximumVariableSize be MAX_VARIABLE_SIZE with the exception of the variable header size.\r
+  // Let *MaximumVariableSize be FixedPcdGet32(PcdMaxVariableSize) with the exception of the variable header size.\r
   //\r
-  *MaximumVariableSize = MAX_VARIABLE_SIZE - sizeof (VARIABLE_HEADER);\r
+  *MaximumVariableSize = FixedPcdGet32(PcdMaxVariableSize) - sizeof (VARIABLE_HEADER);\r
 \r
   //\r
   // Harware error record variable needs larger size.\r
   //\r
   if ((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD) {\r
-    *MaximumVariableSize = MAX_HARDWARE_ERROR_VARIABLE_SIZE - sizeof (VARIABLE_HEADER);\r
+    *MaximumVariableSize = FixedPcdGet32(PcdMaxHardwareErrorVariableSize) - sizeof (VARIABLE_HEADER);\r
   }\r
 \r
   //\r
   // Point to the starting address of the variables.\r
   //\r
-  Variable = (VARIABLE_HEADER *) (VariableStoreHeader + 1);\r
+  Variable = GetStartPointer (VariableStoreHeader);\r
 \r
   //\r
   // Now walk through the related variable store.\r
@@ -1303,35 +1746,64 @@ Returns:
     *MaximumVariableSize = *RemainingVariableStorageSize - sizeof (VARIABLE_HEADER);\r
   }\r
 \r
-  ReleaseLockOnlyAtBootTime (&Global->VariableServicesLock);\r
+  ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);\r
   return EFI_SUCCESS;\r
 }\r
 \r
-EFI_STATUS\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
+**/\r
+VOID\r
 EFIAPI\r
-VariableCommonInitialize (\r
-  IN EFI_HANDLE         ImageHandle,\r
-  IN EFI_SYSTEM_TABLE   *SystemTable\r
+ReclaimForOS(\r
+  EFI_EVENT  Event,\r
+  VOID       *Context\r
   )\r
-/*++\r
-\r
-Routine Description:\r
-  This function does common initialization for variable services\r
+{\r
+  UINT32                          VarSize;\r
+  EFI_STATUS                      Status;\r
 \r
-Arguments:\r
+  VarSize = ((VARIABLE_STORE_HEADER *) ((UINTN) mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase))->Size;\r
+  Status  = EFI_SUCCESS; \r
 \r
-  ImageHandle   - The firmware allocated handle for the EFI image.\r
-  SystemTable   - A pointer to the EFI System Table.\r
+  //\r
+  // Check if the free area is blow a threshold\r
+  //\r
+  if ((VarSize - mVariableModuleGlobal->NonVolatileLastVariableOffset) < VARIABLE_RECLAIM_THRESHOLD) {\r
+    Status = Reclaim (\r
+              mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase,\r
+              &mVariableModuleGlobal->NonVolatileLastVariableOffset,\r
+              FALSE,\r
+              NULL\r
+              );\r
+    ASSERT_EFI_ERROR (Status);\r
+  }\r
+}\r
 \r
-Returns:\r
+/**\r
+  Initializes variable store area for non-volatile and volatile variable.\r
 \r
-  Status code.\r
+  @param  ImageHandle           The Image handle of this driver.\r
+  @param  SystemTable           The pointer of EFI_SYSTEM_TABLE.\r
 \r
-  EFI_NOT_FOUND     - Variable store area not found.\r
-  EFI_UNSUPPORTED   - Currently only one non-volatile variable store is supported.\r
-  EFI_SUCCESS       - Variable services successfully initialized.\r
+  @retval EFI_SUCCESS           Function successfully executed.\r
+  @retval EFI_OUT_OF_RESOURCES  Fail to allocate enough memory resource.\r
 \r
---*/\r
+**/\r
+EFI_STATUS\r
+VariableCommonInitialize (\r
+  IN EFI_HANDLE         ImageHandle,\r
+  IN EFI_SYSTEM_TABLE   *SystemTable\r
+  )\r
 {\r
   EFI_STATUS                      Status;\r
   EFI_FIRMWARE_VOLUME_HEADER      *FwVolHeader;\r
@@ -1343,38 +1815,45 @@ Returns:
   EFI_PHYSICAL_ADDRESS            FvVolHdr;\r
   UINT64                          TempVariableStoreHeader;\r
   EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor;\r
-  EFI_FLASH_SUBAREA_ENTRY         VariableStoreEntry;\r
   UINT64                          BaseAddress;\r
   UINT64                          Length;\r
   UINTN                           Index;\r
   UINT8                           Data;\r
+  UINT64                          VariableStoreBase;\r
+  UINT64                          VariableStoreLength;\r
+  EFI_EVENT                       ReadyToBootEvent;\r
 \r
-  mVariableModuleGlobal = AllocateRuntimePool (sizeof (ESAL_VARIABLE_GLOBAL));\r
+  Status = EFI_SUCCESS;\r
+  //\r
+  // Allocate runtime memory for variable driver global structure.\r
+  //\r
+  mVariableModuleGlobal = AllocateRuntimePool (sizeof (VARIABLE_MODULE_GLOBAL));\r
   if (mVariableModuleGlobal == NULL) {\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
-  EfiInitializeLock(&mVariableModuleGlobal->VariableGlobal[Physical].VariableServicesLock, TPL_NOTIFY);\r
+  EfiInitializeLock(&mVariableModuleGlobal->VariableGlobal.VariableServicesLock, TPL_NOTIFY);\r
+  mVariableModuleGlobal->VariableGlobal.ReentrantState = 0;\r
 \r
   //\r
   // Allocate memory for volatile variable store\r
   //\r
-  VolatileVariableStore = AllocateRuntimePool (VARIABLE_STORE_SIZE + SCRATCH_SIZE);\r
+  VolatileVariableStore = AllocateRuntimePool (FixedPcdGet32(PcdVariableStoreSize) + FixedPcdGet32(PcdMaxVariableSize));\r
   if (VolatileVariableStore == NULL) {\r
     FreePool (mVariableModuleGlobal);\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
-  SetMem (VolatileVariableStore, VARIABLE_STORE_SIZE + SCRATCH_SIZE, 0xff);\r
+  SetMem (VolatileVariableStore, FixedPcdGet32(PcdVariableStoreSize) + FixedPcdGet32(PcdMaxVariableSize), 0xff);\r
 \r
   //\r
   //  Variable Specific Data\r
   //\r
-  mVariableModuleGlobal->VariableGlobal[Physical].VolatileVariableBase = (EFI_PHYSICAL_ADDRESS) (UINTN) VolatileVariableStore;\r
-  mVariableModuleGlobal->VolatileLastVariableOffset = sizeof (VARIABLE_STORE_HEADER);\r
+  mVariableModuleGlobal->VariableGlobal.VolatileVariableBase = (EFI_PHYSICAL_ADDRESS) (UINTN) VolatileVariableStore;\r
+  mVariableModuleGlobal->VolatileLastVariableOffset = (UINTN) GetStartPointer (VolatileVariableStore) - (UINTN) VolatileVariableStore;\r
 \r
-  VolatileVariableStore->Signature                  = VARIABLE_STORE_SIGNATURE;\r
-  VolatileVariableStore->Size                       = VARIABLE_STORE_SIZE;\r
+  CopyGuid (&VolatileVariableStore->Signature, &gEfiVariableGuid);\r
+  VolatileVariableStore->Size                       = FixedPcdGet32(PcdVariableStoreSize);\r
   VolatileVariableStore->Format                     = VARIABLE_STORE_FORMATTED;\r
   VolatileVariableStore->State                      = VARIABLE_STORE_HEALTHY;\r
   VolatileVariableStore->Reserved                   = 0;\r
@@ -1385,22 +1864,20 @@ Returns:
   //\r
 \r
   TempVariableStoreHeader = (UINT64) PcdGet32 (PcdFlashNvStorageVariableBase);\r
-  VariableStoreEntry.Base = TempVariableStoreHeader + \\r
+  VariableStoreBase = TempVariableStoreHeader + \\r
                               (((EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) (TempVariableStoreHeader)) -> HeaderLength);\r
-  VariableStoreEntry.Length = (UINT64) PcdGet32 (PcdFlashNvStorageVariableSize) - \\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 = VariableStoreEntry.Base & (~EFI_PAGE_MASK);\r
-  Length      = VariableStoreEntry.Length + (VariableStoreEntry.Base - BaseAddress);\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
-    FreePool (mVariableModuleGlobal);\r
-    FreePool (VolatileVariableStore);\r
-    return EFI_UNSUPPORTED;\r
+    goto Done;\r
   }\r
 \r
   Status = gDS->SetMemorySpaceAttributes (\r
@@ -1409,14 +1886,12 @@ Returns:
                   GcdDescriptor.Attributes | EFI_MEMORY_RUNTIME\r
                   );\r
   if (EFI_ERROR (Status)) {\r
-    FreePool (mVariableModuleGlobal);\r
-    FreePool (VolatileVariableStore);\r
-    return EFI_UNSUPPORTED;\r
+    goto Done;\r
   }\r
   //\r
   // Get address of non volatile variable store base\r
   //\r
-  mVariableModuleGlobal->VariableGlobal[Physical].NonVolatileVariableBase = VariableStoreEntry.Base;\r
+  mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase = VariableStoreBase;\r
 \r
   //\r
   // Check Integrity\r
@@ -1425,7 +1900,7 @@ Returns:
   // Find the Correct Instance of the FV Block Service.\r
   //\r
   Instance  = 0;\r
-  CurrPtr   = (CHAR8 *) ((UINTN) mVariableModuleGlobal->VariableGlobal[Physical].NonVolatileVariableBase);\r
+  CurrPtr   = (CHAR8 *) ((UINTN) mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase);\r
   while (EfiFvbGetPhysicalAddress (Instance, &FvVolHdr) == EFI_SUCCESS) {\r
     FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) FvVolHdr);\r
     if (CurrPtr >= (CHAR8 *) FwVolHeader && CurrPtr < (((CHAR8 *) FwVolHeader) + FwVolHeader->FvLength)) {\r
@@ -1440,13 +1915,13 @@ Returns:
   if (GetVariableStoreStatus (VariableStoreHeader) == EfiValid) {\r
     if (~VariableStoreHeader->Size == 0) {\r
       Status = UpdateVariableStore (\r
-                &mVariableModuleGlobal->VariableGlobal[Physical],\r
+                &mVariableModuleGlobal->VariableGlobal,\r
                 FALSE,\r
                 FALSE,\r
                 mVariableModuleGlobal->FvbInstance,\r
                 (UINTN) &VariableStoreHeader->Size,\r
                 sizeof (UINT32),\r
-                (UINT8 *) &VariableStoreEntry.Length\r
+                (UINT8 *) &VariableStoreLength\r
                 );\r
       //\r
       // As Variables are stored in NV storage, which are slow devices,such as flash.\r
@@ -1456,18 +1931,18 @@ Returns:
       // 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 == VariableStoreEntry.Length);\r
+      ASSERT(VariableStoreHeader->Size == VariableStoreLength);\r
 \r
       if (EFI_ERROR (Status)) {\r
-        return Status;\r
+        goto Done;\r
       }\r
     }\r
 \r
-    mVariableModuleGlobal->VariableGlobal[Physical].NonVolatileVariableBase = (EFI_PHYSICAL_ADDRESS) ((UINTN) CurrPtr);\r
+    mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase = (EFI_PHYSICAL_ADDRESS) ((UINTN) CurrPtr);\r
     //\r
     // Parse non-volatile variable data and get last variable offset\r
     //\r
-    NextVariable  = (VARIABLE_HEADER *) (CurrPtr + sizeof (VARIABLE_STORE_HEADER));\r
+    NextVariable  = GetStartPointer ((VARIABLE_STORE_HEADER *) CurrPtr);\r
     Status        = EFI_SUCCESS;\r
 \r
     while (IsValidVariableHeader (NextVariable)) {\r
@@ -1476,42 +1951,42 @@ Returns:
 \r
     mVariableModuleGlobal->NonVolatileLastVariableOffset = (UINTN) NextVariable - (UINTN) CurrPtr;\r
 \r
-    //\r
-    // Check if the free area is blow a threshold\r
-    //\r
-    if ((((VARIABLE_STORE_HEADER *)((UINTN) CurrPtr))->Size - mVariableModuleGlobal->NonVolatileLastVariableOffset) < VARIABLE_RECLAIM_THRESHOLD) {\r
-      Status = Reclaim (\r
-                mVariableModuleGlobal->VariableGlobal[Physical].NonVolatileVariableBase,\r
-                &mVariableModuleGlobal->NonVolatileLastVariableOffset,\r
-                FALSE\r
-                );\r
-    }\r
-\r
-    if (EFI_ERROR (Status)) {\r
-      FreePool (mVariableModuleGlobal);\r
-      FreePool (VolatileVariableStore);\r
-      return Status;\r
-    }\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[Physical].NonVolatileVariableBase)[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[Physical].NonVolatileVariableBase,\r
+                  mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase,\r
                   &mVariableModuleGlobal->NonVolatileLastVariableOffset,\r
-                  FALSE\r
+                  FALSE,\r
+                  NULL\r
                   );\r
+\r
+        if (EFI_ERROR (Status)) {\r
+          goto Done;\r
+        }\r
+\r
         break;\r
       }\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
   }\r
 \r
+Done:\r
   if (EFI_ERROR (Status)) {\r
     FreePool (mVariableModuleGlobal);\r
     FreePool (VolatileVariableStore);\r
@@ -1519,3 +1994,86 @@ Returns:
 \r
   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 (\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
+/**\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
+  EFI_STATUS  Status;\r
+\r
+  Status = VariableCommonInitialize (ImageHandle, SystemTable);\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
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r