]> git.proxmox.com Git - mirror_edk2.git/blobdiff - EdkModulePkg/Universal/Variable/RuntimeDxe/Variable.c
Change the TPL lock level to EFI_TPL_NOTIFY. Variable Service is called in ResetSyste...
[mirror_edk2.git] / EdkModulePkg / Universal / Variable / RuntimeDxe / Variable.c
index 0d91520d9722ce74286dbecf64f8b8acc2a29efd..a9dff65494720ad418d134e2a735df49ffe22174 100644 (file)
@@ -1,6 +1,6 @@
 /*++\r
 \r
-Copyright (c) 2006, Intel Corporation                                                         \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
@@ -27,42 +27,39 @@ Revision History
 //\r
 ESAL_VARIABLE_GLOBAL  *mVariableModuleGlobal;\r
 \r
-UINT32\r
-EFIAPI\r
-ArrayLength (\r
-  IN CHAR16 *String\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
+VOID\r
+AcquireLockOnlyAtBootTime (\r
+  IN EFI_LOCK  *Lock\r
   )\r
-/*++\r
-\r
-Routine Description:\r
-\r
-  Determine the length of null terminated char16 array.\r
-\r
-Arguments:\r
-\r
-  String    Null-terminated CHAR16 array pointer.\r
-\r
-Returns:\r
-\r
-  UINT32    Number of bytes in the string, including the double NULL at the end;\r
-\r
---*/\r
 {\r
-  UINT32  Count;\r
-\r
-  if (NULL == String) {\r
-    return 0;\r
+  if (!EfiAtRuntime ()) {\r
+    EfiAcquireLock (Lock);\r
   }\r
+}\r
 \r
-  Count = 0;\r
-\r
-  while (0 != String[Count]) {\r
-    Count++;\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
+VOID\r
+ReleaseLockOnlyAtBootTime (\r
+  IN EFI_LOCK  *Lock\r
+  )\r
+{\r
+  if (!EfiAtRuntime ()) {\r
+    EfiReleaseLock (Lock);\r
   }\r
-\r
-  return (Count * 2) + 2;\r
 }\r
 \r
+STATIC\r
 BOOLEAN\r
 EFIAPI\r
 IsValidVariableHeader (\r
@@ -93,6 +90,7 @@ Returns:
   return TRUE;\r
 }\r
 \r
+STATIC\r
 EFI_STATUS\r
 EFIAPI\r
 UpdateVariableStore (\r
@@ -242,6 +240,7 @@ Returns:
   return EFI_SUCCESS;\r
 }\r
 \r
+STATIC\r
 VARIABLE_STORE_STATUS\r
 EFIAPI\r
 GetVariableStoreStatus (\r
@@ -283,6 +282,7 @@ Returns:
   }\r
 }\r
 \r
+STATIC\r
 UINT8 *\r
 EFIAPI\r
 GetVariableDataPtr (\r
@@ -310,6 +310,7 @@ Returns:
   return (UINT8 *) ((UINTN) GET_VARIABLE_NAME_PTR (Variable) + Variable->NameSize + GET_PAD_SIZE (Variable->NameSize));\r
 }\r
 \r
+STATIC\r
 VARIABLE_HEADER *\r
 EFIAPI\r
 GetNextVariablePtr (\r
@@ -340,6 +341,7 @@ Returns:
   return (VARIABLE_HEADER *) ((UINTN) GetVariableDataPtr (Variable) + Variable->DataSize + GET_PAD_SIZE (Variable->DataSize));\r
 }\r
 \r
+STATIC\r
 VARIABLE_HEADER *\r
 EFIAPI\r
 GetEndPointer (\r
@@ -367,6 +369,7 @@ Returns:
   return (VARIABLE_HEADER *) ((UINTN) VarStoreHeader + VarStoreHeader->Size);\r
 }\r
 \r
+STATIC\r
 EFI_STATUS\r
 EFIAPI\r
 Reclaim (\r
@@ -487,6 +490,7 @@ Returns:
   return Status;\r
 }\r
 \r
+STATIC\r
 EFI_STATUS\r
 EFIAPI\r
 FindVariable (\r
@@ -520,6 +524,13 @@ Returns:
   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
+\r
   //\r
   // 0: Non-Volatile, 1: Volatile\r
   //\r
@@ -552,7 +563,7 @@ Returns:
             return EFI_SUCCESS;\r
           } else {\r
             if (CompareGuid (VendorGuid, &Variable[Index]->VendorGuid)) {\r
-              if (!CompareMem (VariableName, GET_VARIABLE_NAME_PTR (Variable[Index]), ArrayLength (VariableName))) {\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
@@ -622,7 +633,7 @@ Returns:
   Status = FindVariable (VariableName, VendorGuid, &Variable, Global);\r
 \r
   if (Variable.CurrPtr == NULL || EFI_ERROR (Status)) {\r
-    return Status;\r
+    goto Done;\r
   }\r
   //\r
   // Get data size\r
@@ -630,7 +641,8 @@ Returns:
   VarDataSize = Variable.CurrPtr->DataSize;\r
   if (*DataSize >= VarDataSize) {\r
     if (Data == NULL) {\r
-      return EFI_INVALID_PARAMETER;\r
+      Status = EFI_INVALID_PARAMETER;\r
+      goto Done;\r
     }\r
 \r
     CopyMem (Data, GetVariableDataPtr (Variable.CurrPtr), VarDataSize);\r
@@ -639,11 +651,17 @@ Returns:
     }\r
 \r
     *DataSize = VarDataSize;\r
-    return EFI_SUCCESS;\r
+    Status = EFI_SUCCESS;\r
+    goto Done;\r
   } else {\r
     *DataSize = VarDataSize;\r
-    return EFI_BUFFER_TOO_SMALL;\r
+    Status = EFI_BUFFER_TOO_SMALL;\r
+    goto Done;\r
   }\r
+\r
+Done:\r
+  ReleaseLockOnlyAtBootTime (&Global->VariableServicesLock);\r
+  return Status;\r
 }\r
 \r
 EFI_STATUS\r
@@ -686,7 +704,7 @@ Returns:
   Status = FindVariable (VariableName, VendorGuid, &Variable, Global);\r
 \r
   if (Variable.CurrPtr == NULL || EFI_ERROR (Status)) {\r
-    return Status;\r
+    goto Done;\r
   }\r
 \r
   if (VariableName[0] != 0) {\r
@@ -707,7 +725,8 @@ Returns:
         Variable.StartPtr = (VARIABLE_HEADER *) ((UINTN) (Global->VolatileVariableBase + sizeof (VARIABLE_STORE_HEADER)));\r
         Variable.EndPtr = (VARIABLE_HEADER *) GetEndPointer ((VARIABLE_STORE_HEADER *) ((UINTN) Global->VolatileVariableBase));\r
       } else {\r
-        return EFI_NOT_FOUND;\r
+        Status = EFI_NOT_FOUND;\r
+        goto Done;\r
       }\r
 \r
       Variable.CurrPtr = Variable.StartPtr;\r
@@ -738,14 +757,16 @@ Returns:
         }\r
 \r
         *VariableNameSize = VarNameSize;\r
-        return Status;\r
+        goto Done;\r
       }\r
     }\r
 \r
     Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);\r
   }\r
 \r
-  return EFI_NOT_FOUND;\r
+Done:\r
+  ReleaseLockOnlyAtBootTime (&Global->VariableServicesLock);\r
+  return Status;\r
 }\r
 \r
 EFI_STATUS\r
@@ -809,39 +830,52 @@ Returns:
   Status = FindVariable (VariableName, VendorGuid, &Variable, Global);\r
 \r
   if (Status == EFI_INVALID_PARAMETER) {\r
-    return Status;\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_VARIABLE_SIZE (1024) bytes.\r
-  //\r
-  else if (sizeof (VARIABLE_HEADER) + ArrayLength (VariableName) + DataSize > MAX_VARIABLE_SIZE) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-  //\r
-  //  Make sure if runtime bit is set, boot service bit is set also\r
-  //\r
-  else if ((Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == EFI_VARIABLE_RUNTIME_ACCESS\r
-          ) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-  //\r
-  // Runtime but Attribute is not Runtime\r
-  //\r
-  else if (EfiAtRuntime () && Attributes && !(Attributes & EFI_VARIABLE_RUNTIME_ACCESS)) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-  //\r
-  // Cannot set volatile variable in Runtime\r
-  //\r
-  else if (EfiAtRuntime () && Attributes && !(Attributes & EFI_VARIABLE_NON_VOLATILE)) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-  //\r
-  // Setting a data variable with no access, or zero DataSize attributes\r
-  // specified causes it to be deleted.\r
-  //\r
-  else if (DataSize == 0 || Attributes == 0) {\r
+    goto Done;\r
+  } else if (!EFI_ERROR (Status) && Variable.Volatile && EfiAtRuntime()) {\r
+    //\r
+    // If EfiAtRuntime 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
+    Status = EFI_WRITE_PROTECTED;\r
+    goto Done;\r
+  } else if (sizeof (VARIABLE_HEADER) + StrSize (VariableName) + DataSize > MAX_VARIABLE_SIZE) {\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
+    //\r
+    Status = EFI_INVALID_PARAMETER;\r
+    goto Done;\r
+  } else if (Attributes == EFI_VARIABLE_NON_VOLATILE) {\r
+    //\r
+    //  Make sure not only EFI_VARIABLE_NON_VOLATILE is set \r
+    //\r
+    Status = EFI_INVALID_PARAMETER;\r
+    goto Done;\r
+  } else if ((Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == \r
+                EFI_VARIABLE_RUNTIME_ACCESS) {\r
+    //\r
+    //  Make sure if runtime bit is set, boot service bit is set also\r
+    //\r
+    Status = EFI_INVALID_PARAMETER;\r
+    goto Done;\r
+  } else if (EfiAtRuntime () && Attributes && !(Attributes & EFI_VARIABLE_RUNTIME_ACCESS)) {\r
+    //\r
+    // Runtime but Attribute is not Runtime\r
+    //\r
+    Status = EFI_INVALID_PARAMETER;\r
+    goto Done;\r
+  } else if (EfiAtRuntime () && Attributes && !(Attributes & EFI_VARIABLE_NON_VOLATILE)) {\r
+    //\r
+    // Cannot set volatile variable in Runtime\r
+    //\r
+    Status = EFI_INVALID_PARAMETER;\r
+    goto Done;\r
+  } else if (DataSize == 0 || (Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == 0) {\r
+    //\r
+    // Setting a data variable with no access, or zero DataSize attributes\r
+    // specified causes it to be deleted.\r
+    //\r
     if (!EFI_ERROR (Status)) {\r
       State = Variable.CurrPtr->State;\r
       State &= VAR_DELETED;\r
@@ -856,13 +890,15 @@ Returns:
                 &State\r
                 );\r
       if (EFI_ERROR (Status)) {\r
-        return Status;\r
+        goto Done;\r
       }\r
 \r
-      return EFI_SUCCESS;\r
+      Status = EFI_SUCCESS;\r
+      goto Done;\r
     }\r
 \r
-    return EFI_NOT_FOUND;\r
+    Status = EFI_NOT_FOUND;\r
+    goto Done;\r
   } else {\r
     if (!EFI_ERROR (Status)) {\r
       //\r
@@ -872,7 +908,8 @@ Returns:
       if (Variable.CurrPtr->DataSize == DataSize &&\r
           !CompareMem (Data, GetVariableDataPtr (Variable.CurrPtr), DataSize)\r
             ) {\r
-        return EFI_SUCCESS;\r
+        Status = EFI_SUCCESS;\r
+        goto Done;\r
       } else if (Variable.CurrPtr->State == VAR_ADDED) {\r
         //\r
         // Mark the old variable as in delete transition\r
@@ -890,7 +927,7 @@ Returns:
                   &State\r
                   );\r
         if (EFI_ERROR (Status)) {\r
-          return Status;\r
+          goto Done;\r
         }\r
       }\r
     }\r
@@ -911,7 +948,7 @@ Returns:
     //\r
     NextVariable->Reserved  = 0;\r
     VarNameOffset           = sizeof (VARIABLE_HEADER);\r
-    VarNameSize             = ArrayLength (VariableName);\r
+    VarNameSize             = StrSize (VariableName);\r
     CopyMem (\r
       (UINT8 *) ((UINTN) NextVariable + VarNameOffset),\r
       VariableName,\r
@@ -942,14 +979,15 @@ Returns:
             ((VARIABLE_STORE_HEADER *) ((UINTN) (Global->NonVolatileVariableBase)))->Size\r
             ) {\r
         if (EfiAtRuntime ()) {\r
-          return EFI_OUT_OF_RESOURCES;\r
+          Status = EFI_OUT_OF_RESOURCES;\r
+          goto Done;\r
         }\r
         //\r
         // Perform garbage collection & reclaim operation\r
         //\r
         Status = Reclaim (Global->NonVolatileVariableBase, NonVolatileOffset, FALSE);\r
         if (EFI_ERROR (Status)) {\r
-          return Status;\r
+          goto Done;\r
         }\r
         //\r
         // If still no enough space, return out of resources\r
@@ -957,7 +995,8 @@ Returns:
         if ((UINT32) (VarSize +*NonVolatileOffset) >\r
               ((VARIABLE_STORE_HEADER *) ((UINTN) (Global->NonVolatileVariableBase)))->Size\r
               ) {\r
-          return EFI_OUT_OF_RESOURCES;\r
+          Status = EFI_OUT_OF_RESOURCES;\r
+          goto Done;\r
         }\r
         \r
         Reclaimed = TRUE;\r
@@ -982,7 +1021,7 @@ Returns:
                 );\r
 \r
       if (EFI_ERROR (Status)) {\r
-        return Status;\r
+        goto Done;\r
       }\r
       //\r
       // Step 2:\r
@@ -998,7 +1037,7 @@ Returns:
                 );\r
 \r
       if (EFI_ERROR (Status)) {\r
-        return Status;\r
+        goto Done;\r
       }\r
       //\r
       // Step 3:\r
@@ -1015,14 +1054,15 @@ Returns:
                 );\r
 \r
       if (EFI_ERROR (Status)) {\r
-        return Status;\r
+        goto Done;\r
       }\r
 \r
       *NonVolatileOffset = *NonVolatileOffset + VarSize;\r
 \r
     } else {\r
       if (EfiAtRuntime ()) {\r
-        return EFI_INVALID_PARAMETER;\r
+        Status = EFI_INVALID_PARAMETER;\r
+        goto Done;\r
       }\r
 \r
       if ((UINT32) (VarSize +*VolatileOffset) >\r
@@ -1033,7 +1073,7 @@ Returns:
         //\r
         Status = Reclaim (Global->VolatileVariableBase, VolatileOffset, TRUE);\r
         if (EFI_ERROR (Status)) {\r
-          return Status;\r
+          goto Done;\r
         }\r
         //\r
         // If still no enough space, return out of resources\r
@@ -1041,7 +1081,8 @@ Returns:
         if ((UINT32) (VarSize +*VolatileOffset) >\r
               ((VARIABLE_STORE_HEADER *) ((UINTN) (Global->VolatileVariableBase)))->Size\r
               ) {\r
-          return EFI_OUT_OF_RESOURCES;\r
+          Status = EFI_OUT_OF_RESOURCES;\r
+          goto Done;\r
         }\r
         \r
         Reclaimed = TRUE;\r
@@ -1059,7 +1100,7 @@ Returns:
                 );\r
 \r
       if (EFI_ERROR (Status)) {\r
-        return Status;\r
+        goto Done;\r
       }\r
 \r
       *VolatileOffset = *VolatileOffset + VarSize;\r
@@ -1082,13 +1123,148 @@ Returns:
                 );\r
 \r
       if (EFI_ERROR (Status)) {\r
-        return Status;\r
+        goto Done;\r
       }\r
     }\r
   }\r
 \r
+  Status = EFI_SUCCESS;\r
+Done:\r
+  ReleaseLockOnlyAtBootTime (&Global->VariableServicesLock);\r
+  return Status;\r
+}\r
+\r
+#if (EFI_SPECIFICATION_VERSION >= 0x00020000)\r
+EFI_STATUS\r
+EFIAPI\r
+QueryVariableInfo (\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
+  )\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 the EFI variables associated with the attributes specified.\r
+  MaximumVariableSize             Pointer to the maximum size of the 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
+  UINT64                 VariableSize;\r
+  VARIABLE_STORE_HEADER  *VariableStoreHeader;\r
+\r
+  if(MaximumVariableStorageSize == NULL || RemainingVariableStorageSize == NULL || MaximumVariableSize == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if((Attributes & (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS)) == 0) {\r
+    //\r
+    // Make sure the Attributes combination is supported by the platform.\r
+    //\r
+    return EFI_UNSUPPORTED;\r
+  } else if ((Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == EFI_VARIABLE_RUNTIME_ACCESS) {\r
+    //\r
+    // 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
+    //\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
+  \r
+  if((Attributes & EFI_VARIABLE_NON_VOLATILE) == 0) {\r
+    //\r
+    // Query is Volatile related.\r
+    //\r
+    VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINTN) Global->VolatileVariableBase);    \r
+  } else {\r
+    //\r
+    // Query is Non-Volatile related.\r
+    //\r
+    VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINTN) Global->NonVolatileVariableBase);\r
+  }\r
+\r
+  //\r
+  // Now let's fill *MaximumVariableStorageSize *RemainingVariableStorageSize \r
+  // with the storage size (excluding the storage header size).\r
+  //\r
+  *MaximumVariableStorageSize   = VariableStoreHeader->Size - sizeof (VARIABLE_STORE_HEADER);\r
+  *RemainingVariableStorageSize = VariableStoreHeader->Size - sizeof (VARIABLE_STORE_HEADER);\r
+\r
+  //\r
+  // Let *MaximumVariableSize be MAX_VARIABLE_SIZE.\r
+  //\r
+  *MaximumVariableSize = MAX_VARIABLE_SIZE;\r
+\r
+  //\r
+  // Point to the starting address of the variables.\r
+  //\r
+  Variable = (VARIABLE_HEADER *) (VariableStoreHeader + 1);\r
+\r
+  //\r
+  // Now walk through the related variable store.\r
+  //\r
+  while (IsValidVariableHeader (Variable) && (Variable < GetEndPointer (VariableStoreHeader))) {\r
+    NextVariable = GetNextVariablePtr (Variable);\r
+    VariableSize = (UINT64) (UINTN) NextVariable - (UINT64) (UINTN) Variable;\r
+\r
+    if (EfiAtRuntime ()) {\r
+      //\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
+      //\r
+      *RemainingVariableStorageSize -= VariableSize;\r
+    } else {\r
+      //\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
+        *RemainingVariableStorageSize -= VariableSize;\r
+      }\r
+    }\r
+    \r
+    //\r
+    // Go to the next one\r
+    //\r
+    Variable = NextVariable;\r
+  }\r
\r
+  ReleaseLockOnlyAtBootTime (&Global->VariableServicesLock);\r
   return EFI_SUCCESS;\r
 }\r
+#endif\r
 \r
 EFI_STATUS\r
 EFIAPI\r
@@ -1125,14 +1301,14 @@ Returns:
   UINT32                          Instance;\r
   EFI_PHYSICAL_ADDRESS            FvVolHdr;\r
 \r
-  EFI_FLASH_MAP_ENTRY_DATA        *FlashMapEntryData;\r
+  UINT64                          TempVariableStoreHeader;\r
+\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
-  EFI_PEI_HOB_POINTERS            GuidHob;\r
 \r
   Status = gBS->AllocatePool (\r
                   EfiRuntimeServicesData,\r
@@ -1143,6 +1319,9 @@ Returns:
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
+\r
+  EfiInitializeLock(&mVariableModuleGlobal->VariableGlobal[Physical].VariableServicesLock, EFI_TPL_NOTIFY);\r
+  \r
   //\r
   // Allocate memory for volatile variable store\r
   //\r
@@ -1162,7 +1341,7 @@ Returns:
   //\r
   //  Variable Specific Data\r
   //\r
-  mVariableModuleGlobal->VariableBase[Physical].VolatileVariableBase = (EFI_PHYSICAL_ADDRESS) (UINTN) VolatileVariableStore;\r
+  mVariableModuleGlobal->VariableGlobal[Physical].VolatileVariableBase = (EFI_PHYSICAL_ADDRESS) (UINTN) VolatileVariableStore;\r
   mVariableModuleGlobal->VolatileLastVariableOffset = sizeof (VARIABLE_STORE_HEADER);\r
 \r
   VolatileVariableStore->Signature                  = VARIABLE_STORE_SIGNATURE;\r
@@ -1176,35 +1355,11 @@ Returns:
   // Get non volatile varaible store\r
   //\r
 \r
-  FlashMapEntryData = NULL;\r
-\r
-  GuidHob.Raw = GetHobList ();\r
-  while (NULL != (GuidHob.Raw = GetNextGuidHob (&gEfiFlashMapHobGuid, GuidHob.Raw))) {\r
-    FlashMapEntryData = (EFI_FLASH_MAP_ENTRY_DATA *) GET_GUID_HOB_DATA (GuidHob.Guid);\r
-\r
-    if (FlashMapEntryData->AreaType == EFI_FLASH_AREA_EFI_VARIABLES) {\r
-      break;\r
-    }\r
-    GuidHob.Raw = GET_NEXT_HOB (GuidHob);\r
-  }\r
-\r
-  if (NULL == GuidHob.Raw || FlashMapEntryData == NULL) {\r
-    gBS->FreePool (mVariableModuleGlobal);\r
-    gBS->FreePool (VolatileVariableStore);\r
-    return EFI_NOT_FOUND;\r
-  }\r
-\r
-  //\r
-  // Currently only one non-volatile variable store is supported\r
-  //\r
-  if (FlashMapEntryData->NumEntries != 1) {\r
-    gBS->FreePool (mVariableModuleGlobal);\r
-    gBS->FreePool (VolatileVariableStore);\r
-    return EFI_UNSUPPORTED;\r
-  }\r
-\r
-  CopyMem (&VariableStoreEntry, &FlashMapEntryData->Entries[0], sizeof (VariableStoreEntry));\r
-\r
+  TempVariableStoreHeader = (UINT64) PcdGet32 (PcdFlashNvStorageVariableBase);\r
+  VariableStoreEntry.Base = TempVariableStoreHeader + \\r
+                              (((EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) (TempVariableStoreHeader)) -> HeaderLength);\r
+  VariableStoreEntry.Length = (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
@@ -1232,7 +1387,7 @@ Returns:
   //\r
   // Get address of non volatile variable store base\r
   //\r
-  mVariableModuleGlobal->VariableBase[Physical].NonVolatileVariableBase = VariableStoreEntry.Base;\r
+  mVariableModuleGlobal->VariableGlobal[Physical].NonVolatileVariableBase = VariableStoreEntry.Base;\r
 \r
   //\r
   // Check Integrity\r
@@ -1241,7 +1396,7 @@ Returns:
   // Find the Correct Instance of the FV Block Service.\r
   //\r
   Instance  = 0;\r
-  CurrPtr   = (CHAR8 *) ((UINTN) mVariableModuleGlobal->VariableBase[Physical].NonVolatileVariableBase);\r
+  CurrPtr   = (CHAR8 *) ((UINTN) mVariableModuleGlobal->VariableGlobal[Physical].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
@@ -1256,7 +1411,7 @@ Returns:
   if (GetVariableStoreStatus (VariableStoreHeader) == EfiValid) {\r
     if (~VariableStoreHeader->Size == 0) {\r
       Status = UpdateVariableStore (\r
-                &mVariableModuleGlobal->VariableBase[Physical],\r
+                &mVariableModuleGlobal->VariableGlobal[Physical],\r
                 FALSE,\r
                 FALSE,\r
                 mVariableModuleGlobal->FvbInstance,\r
@@ -1270,7 +1425,7 @@ Returns:
       }\r
     }\r
 \r
-    mVariableModuleGlobal->VariableBase[Physical].NonVolatileVariableBase = (EFI_PHYSICAL_ADDRESS) ((UINTN) CurrPtr);\r
+    mVariableModuleGlobal->VariableGlobal[Physical].NonVolatileVariableBase = (EFI_PHYSICAL_ADDRESS) ((UINTN) CurrPtr);\r
     //\r
     // Parse non-volatile variable data and get last variable offset\r
     //\r
@@ -1283,17 +1438,34 @@ 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
+      gBS->FreePool (mVariableModuleGlobal);\r
+      gBS->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->VariableBase[Physical].NonVolatileVariableBase)[Index];\r
+      Data = ((UINT8 *) (UINTN) mVariableModuleGlobal->VariableGlobal[Physical].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->VariableBase[Physical].NonVolatileVariableBase,\r
+                  mVariableModuleGlobal->VariableGlobal[Physical].NonVolatileVariableBase,\r
                   &mVariableModuleGlobal->NonVolatileLastVariableOffset,\r
                   FALSE\r
                   );\r