]> git.proxmox.com Git - mirror_edk2.git/commitdiff
SecurityPkg: Variable drivers robustly handle crashes during Reclaim().
authorStar Zeng <star.zeng@intel.com>
Wed, 3 Jul 2013 09:09:42 +0000 (09:09 +0000)
committerlzeng14 <lzeng14@6f19259b-4bc3-4df7-8a09-765794883524>
Wed, 3 Jul 2013 09:09:42 +0000 (09:09 +0000)
PEI variable implementation checks only the variable header signature for validity. This does not seem robust if system crash occurred during previous Reclaim() operation. If the crash occurred while FTW was rewriting the variable FV, the signature could be valid even though the rest of the FV isn't valid.
Solution: PEI variable and early phase(before FTW protocol ready) of DXE variable can check the FTW last write status provided by FaultTolerantWritePei and determine if all or partial variable data has been backed up in spare block, and then use the backed up data.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Star Zeng <star.zeng@intel.com>
Reviewed-by: Liming Gao <liming.gao@intel.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@14455 6f19259b-4bc3-4df7-8a09-765794883524

SecurityPkg/VariableAuthenticated/Pei/Variable.c
SecurityPkg/VariableAuthenticated/Pei/Variable.h
SecurityPkg/VariableAuthenticated/Pei/VariablePei.inf
SecurityPkg/VariableAuthenticated/RuntimeDxe/Variable.c
SecurityPkg/VariableAuthenticated/RuntimeDxe/Variable.h
SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableRuntimeDxe.inf
SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmm.inf

index 38b9170aa245ca0365642c9b491cdbd222aabde5..274feb31aca168a29181d036f2b3d13cb1ac337c 100644 (file)
@@ -172,7 +172,6 @@ GetVariableNamePtr (
   IN  VARIABLE_HEADER   *Variable\r
   )\r
 {\r
   IN  VARIABLE_HEADER   *Variable\r
   )\r
 {\r
-\r
   return (CHAR16 *) (Variable + 1);\r
 }\r
 \r
   return (CHAR16 *) (Variable + 1);\r
 }\r
 \r
@@ -180,14 +179,16 @@ GetVariableNamePtr (
 /**\r
   This code gets the pointer to the variable data.\r
 \r
 /**\r
   This code gets the pointer to the variable data.\r
 \r
-  @param   Variable  Pointer to the Variable Header.\r
+  @param   Variable         Pointer to the Variable Header.\r
+  @param   VariableHeader   Pointer to the Variable Header that has consecutive content.\r
 \r
   @return  A UINT8* pointer to Variable Data.\r
 \r
 **/\r
 UINT8 *\r
 GetVariableDataPtr (\r
 \r
   @return  A UINT8* pointer to Variable Data.\r
 \r
 **/\r
 UINT8 *\r
 GetVariableDataPtr (\r
-  IN  VARIABLE_HEADER   *Variable\r
+  IN  VARIABLE_HEADER   *Variable,\r
+  IN  VARIABLE_HEADER   *VariableHeader\r
   )\r
 {\r
   UINTN Value;\r
   )\r
 {\r
   UINTN Value;\r
@@ -196,8 +197,8 @@ GetVariableDataPtr (
   // Be careful about pad size for alignment\r
   //\r
   Value =  (UINTN) GetVariableNamePtr (Variable);\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
+  Value += NameSizeOfVariable (VariableHeader);\r
+  Value += GET_PAD_SIZE (NameSizeOfVariable (VariableHeader));\r
 \r
   return (UINT8 *) Value;\r
 }\r
 \r
   return (UINT8 *) Value;\r
 }\r
@@ -206,34 +207,48 @@ GetVariableDataPtr (
 /**\r
   This code gets the pointer to the next variable header.\r
 \r
 /**\r
   This code gets the pointer to the next variable header.\r
 \r
-  @param  Variable  Pointer to the Variable Header.\r
+  @param  StoreInfo         Pointer to variable store info structure.\r
+  @param  Variable          Pointer to the Variable Header.\r
+  @param  VariableHeader    Pointer to the Variable Header that has consecutive content.\r
 \r
   @return  A VARIABLE_HEADER* pointer to next variable header.\r
 \r
 **/\r
 VARIABLE_HEADER *\r
 GetNextVariablePtr (\r
 \r
   @return  A VARIABLE_HEADER* pointer to next variable header.\r
 \r
 **/\r
 VARIABLE_HEADER *\r
 GetNextVariablePtr (\r
-  IN  VARIABLE_HEADER   *Variable\r
+  IN  VARIABLE_STORE_INFO   *StoreInfo,\r
+  IN  VARIABLE_HEADER       *Variable,\r
+  IN  VARIABLE_HEADER       *VariableHeader\r
   )\r
 {\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
+  EFI_PHYSICAL_ADDRESS  TargetAddress;\r
+  EFI_PHYSICAL_ADDRESS  SpareAddress;\r
+  UINTN                 Value;\r
 \r
 \r
+  Value =  (UINTN) GetVariableDataPtr (Variable, VariableHeader);\r
+  Value += DataSizeOfVariable (VariableHeader);\r
+  Value += GET_PAD_SIZE (DataSizeOfVariable (VariableHeader));\r
   //\r
   // Be careful about pad size for alignment\r
   //\r
   //\r
   // Be careful about pad size for alignment\r
   //\r
-  return (VARIABLE_HEADER *) HEADER_ALIGN (Value);\r
+  Value = HEADER_ALIGN (Value);\r
+\r
+  if (StoreInfo->FtwLastWriteData != NULL) {\r
+    TargetAddress = StoreInfo->FtwLastWriteData->TargetAddress;\r
+    SpareAddress = StoreInfo->FtwLastWriteData->SpareAddress;\r
+    if (((UINTN) Variable < (UINTN) TargetAddress) && (Value >= (UINTN) TargetAddress)) {\r
+      //\r
+      // Next variable is in spare block.\r
+      //\r
+      Value = (UINTN) SpareAddress + (Value - (UINTN) TargetAddress);\r
+    }\r
+  }\r
+\r
+  return (VARIABLE_HEADER *) Value;\r
 }\r
 \r
 /**\r
 }\r
 \r
 /**\r
-  This code gets the pointer to the variable name.\r
+  Get variable store status.\r
 \r
   @param  VarStoreHeader  Pointer to the Variable Store Header.\r
 \r
 \r
   @param  VarStoreHeader  Pointer to the Variable Store Header.\r
 \r
@@ -247,7 +262,6 @@ GetVariableStoreStatus (
   IN VARIABLE_STORE_HEADER *VarStoreHeader\r
   )\r
 {\r
   IN VARIABLE_STORE_HEADER *VarStoreHeader\r
   )\r
 {\r
-       \r
   if (CompareGuid (&VarStoreHeader->Signature, &gEfiAuthenticatedVariableGuid) &&\r
       VarStoreHeader->Format == VARIABLE_STORE_FORMATTED &&\r
       VarStoreHeader->State == VARIABLE_STORE_HEALTHY\r
   if (CompareGuid (&VarStoreHeader->Signature, &gEfiAuthenticatedVariableGuid) &&\r
       VarStoreHeader->Format == VARIABLE_STORE_FORMATTED &&\r
       VarStoreHeader->State == VARIABLE_STORE_HEALTHY\r
@@ -271,11 +285,85 @@ GetVariableStoreStatus (
   }\r
 }\r
 \r
   }\r
 }\r
 \r
+/**\r
+  Compare two variable names, one of them may be inconsecutive.\r
+\r
+  @param StoreInfo      Pointer to variable store info structure.\r
+  @param Name1          Pointer to one variable name.\r
+  @param Name2          Pointer to another variable name.\r
+  @param NameSize       Variable name size.\r
+\r
+  @retval TRUE          Name1 and Name2 are identical.\r
+  @retval FALSE         Name1 and Name2 are not identical.\r
+\r
+**/\r
+BOOLEAN\r
+CompareVariableName (\r
+  IN VARIABLE_STORE_INFO    *StoreInfo,\r
+  IN CONST CHAR16           *Name1,\r
+  IN CONST CHAR16           *Name2,\r
+  IN UINTN                  NameSize\r
+  )\r
+{\r
+  EFI_PHYSICAL_ADDRESS  TargetAddress;\r
+  EFI_PHYSICAL_ADDRESS  SpareAddress;\r
+  UINTN                 PartialNameSize;\r
+\r
+  if (StoreInfo->FtwLastWriteData != NULL) {\r
+    TargetAddress = StoreInfo->FtwLastWriteData->TargetAddress;\r
+    SpareAddress = StoreInfo->FtwLastWriteData->SpareAddress;\r
+    if (((UINTN) Name1 < (UINTN) TargetAddress) && (((UINTN) Name1 + NameSize) > (UINTN) TargetAddress)) {\r
+      //\r
+      // Name1 is inconsecutive.\r
+      //\r
+      PartialNameSize = (UINTN) TargetAddress - (UINTN) Name1;\r
+      //\r
+      // Partial content is in NV storage.\r
+      //\r
+      if (CompareMem ((UINT8 *) Name1, (UINT8 *) Name2, PartialNameSize) == 0) {\r
+        //\r
+        // Another partial content is in spare block.\r
+        //\r
+        if (CompareMem ((UINT8 *) (UINTN) SpareAddress, (UINT8 *) Name2 + PartialNameSize, NameSize - PartialNameSize) == 0) {\r
+          return TRUE;\r
+        }\r
+      }\r
+      return FALSE;\r
+    } else if (((UINTN) Name2 < (UINTN) TargetAddress) && (((UINTN) Name2 + NameSize) > (UINTN) TargetAddress)) {\r
+      //\r
+      // Name2 is inconsecutive.\r
+      //\r
+      PartialNameSize = (UINTN) TargetAddress - (UINTN) Name2;\r
+      //\r
+      // Partial content is in NV storage.\r
+      //\r
+      if (CompareMem ((UINT8 *) Name2, (UINT8 *) Name1, PartialNameSize) == 0) {\r
+        //\r
+        // Another partial content is in spare block.\r
+        //\r
+        if (CompareMem ((UINT8 *) (UINTN) SpareAddress, (UINT8 *) Name1 + PartialNameSize, NameSize - PartialNameSize) == 0) {\r
+          return TRUE;\r
+        }\r
+      }\r
+      return FALSE;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Both Name1 and Name2 are consecutive.\r
+  //\r
+  if (CompareMem ((UINT8 *) Name1, (UINT8 *) Name2, NameSize) == 0) {\r
+    return TRUE;\r
+  }\r
+  return FALSE;\r
+}\r
 \r
 /**\r
   This function compares a variable with variable entries in database.\r
 \r
 \r
 /**\r
   This function compares a variable with variable entries in database.\r
 \r
+  @param  StoreInfo     Pointer to variable store info structure.\r
   @param  Variable      Pointer to the variable in our database\r
   @param  Variable      Pointer to the variable in our database\r
+  @param  VariableHeader Pointer to the Variable Header that has consecutive content.\r
   @param  VariableName  Name of the variable to compare to 'Variable'\r
   @param  VendorGuid    GUID of the variable to compare to 'Variable'\r
   @param  PtrTrack      Variable Track Pointer structure that contains Variable Information.\r
   @param  VariableName  Name of the variable to compare to 'Variable'\r
   @param  VendorGuid    GUID of the variable to compare to 'Variable'\r
   @param  PtrTrack      Variable Track Pointer structure that contains Variable Information.\r
@@ -286,7 +374,9 @@ GetVariableStoreStatus (
 **/\r
 EFI_STATUS\r
 CompareWithValidVariable (\r
 **/\r
 EFI_STATUS\r
 CompareWithValidVariable (\r
+  IN  VARIABLE_STORE_INFO           *StoreInfo,\r
   IN  VARIABLE_HEADER               *Variable,\r
   IN  VARIABLE_HEADER               *Variable,\r
+  IN  VARIABLE_HEADER               *VariableHeader,\r
   IN  CONST CHAR16                  *VariableName,\r
   IN  CONST EFI_GUID                *VendorGuid,\r
   OUT VARIABLE_POINTER_TRACK        *PtrTrack\r
   IN  CONST CHAR16                  *VariableName,\r
   IN  CONST EFI_GUID                *VendorGuid,\r
   OUT VARIABLE_POINTER_TRACK        *PtrTrack\r
@@ -303,14 +393,14 @@ CompareWithValidVariable (
     // Instead we compare the GUID a UINT32 at a time and branch\r
     // on the first failed comparison.\r
     //\r
     // Instead we compare the GUID a UINT32 at a time and branch\r
     // on the first failed comparison.\r
     //\r
-    if ((((INT32 *) VendorGuid)[0] == ((INT32 *) &Variable->VendorGuid)[0]) &&\r
-        (((INT32 *) VendorGuid)[1] == ((INT32 *) &Variable->VendorGuid)[1]) &&\r
-        (((INT32 *) VendorGuid)[2] == ((INT32 *) &Variable->VendorGuid)[2]) &&\r
-        (((INT32 *) VendorGuid)[3] == ((INT32 *) &Variable->VendorGuid)[3])\r
+    if ((((INT32 *) VendorGuid)[0] == ((INT32 *) &VariableHeader->VendorGuid)[0]) &&\r
+        (((INT32 *) VendorGuid)[1] == ((INT32 *) &VariableHeader->VendorGuid)[1]) &&\r
+        (((INT32 *) VendorGuid)[2] == ((INT32 *) &VariableHeader->VendorGuid)[2]) &&\r
+        (((INT32 *) VendorGuid)[3] == ((INT32 *) &VariableHeader->VendorGuid)[3])\r
         ) {\r
         ) {\r
-      ASSERT (NameSizeOfVariable (Variable) != 0);\r
+      ASSERT (NameSizeOfVariable (VariableHeader) != 0);\r
       Point = (VOID *) GetVariableNamePtr (Variable);\r
       Point = (VOID *) GetVariableNamePtr (Variable);\r
-      if (CompareMem (VariableName, Point, NameSizeOfVariable (Variable)) == 0) {\r
+      if (CompareVariableName (StoreInfo, VariableName, Point, NameSizeOfVariable (VariableHeader))) {\r
         PtrTrack->CurrPtr = Variable;\r
         return EFI_SUCCESS;\r
       }\r
         PtrTrack->CurrPtr = Variable;\r
         return EFI_SUCCESS;\r
       }\r
@@ -321,26 +411,29 @@ CompareWithValidVariable (
 }\r
 \r
 /**\r
 }\r
 \r
 /**\r
-  Return the variable store header and the index table based on the Index.\r
+  Return the variable store header and the store info based on the Index.\r
 \r
 \r
-  @param Type      The type of the variable store.\r
-  @param IndexTable Return the index table.\r
+  @param Type       The type of the variable store.\r
+  @param StoreInfo  Return the store info.\r
 \r
   @return  Pointer to the variable store header.\r
 **/\r
 VARIABLE_STORE_HEADER *\r
 GetVariableStore (\r
   IN VARIABLE_STORE_TYPE         Type,\r
 \r
   @return  Pointer to the variable store header.\r
 **/\r
 VARIABLE_STORE_HEADER *\r
 GetVariableStore (\r
   IN VARIABLE_STORE_TYPE         Type,\r
-  OUT VARIABLE_INDEX_TABLE       **IndexTable  OPTIONAL\r
+  OUT VARIABLE_STORE_INFO        *StoreInfo\r
   )\r
 {\r
   )\r
 {\r
-  EFI_HOB_GUID_TYPE           *GuidHob;\r
-  EFI_FIRMWARE_VOLUME_HEADER  *FvHeader;\r
-  VARIABLE_STORE_HEADER       *VariableStoreHeader;\r
-\r
-  if (IndexTable != NULL) {\r
-    *IndexTable       = NULL;\r
-  }\r
+  EFI_HOB_GUID_TYPE                     *GuidHob;\r
+  EFI_FIRMWARE_VOLUME_HEADER            *FvHeader;\r
+  VARIABLE_STORE_HEADER                 *VariableStoreHeader;\r
+  EFI_PHYSICAL_ADDRESS                  NvStorageBase;\r
+  UINT32                                NvStorageSize;\r
+  FAULT_TOLERANT_WRITE_LAST_WRITE_DATA  *FtwLastWriteData;\r
+  UINT32                                BackUpOffset;\r
+\r
+  StoreInfo->IndexTable = NULL;\r
+  StoreInfo->FtwLastWriteData = NULL;\r
   VariableStoreHeader = NULL;\r
   switch (Type) {\r
     case VariableStoreTypeHob:\r
   VariableStoreHeader = NULL;\r
   switch (Type) {\r
     case VariableStoreTypeHob:\r
@@ -355,10 +448,42 @@ GetVariableStore (
         //\r
         // The content of NV storage for variable is not reliable in recovery boot mode.\r
         //\r
         //\r
         // The content of NV storage for variable is not reliable in recovery boot mode.\r
         //\r
-        FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) (PcdGet64 (PcdFlashNvStorageVariableBase64) != 0 ? \r
-                                                           PcdGet64 (PcdFlashNvStorageVariableBase64) : \r
-                                                           PcdGet32 (PcdFlashNvStorageVariableBase)\r
-                                                          );\r
+\r
+        NvStorageSize = PcdGet32 (PcdFlashNvStorageVariableSize);\r
+        NvStorageBase = (EFI_PHYSICAL_ADDRESS) (PcdGet64 (PcdFlashNvStorageVariableBase64) != 0 ? \r
+                                                PcdGet64 (PcdFlashNvStorageVariableBase64) : \r
+                                                PcdGet32 (PcdFlashNvStorageVariableBase)\r
+                                               );\r
+        //\r
+        // First let FvHeader point to NV storage base.\r
+        //\r
+        FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) NvStorageBase;\r
+\r
+        //\r
+        // Check the FTW last write data hob.\r
+        //\r
+        BackUpOffset = 0;\r
+        GuidHob = GetFirstGuidHob (&gEdkiiFaultTolerantWriteGuid);\r
+        if (GuidHob != NULL) {\r
+          FtwLastWriteData = (FAULT_TOLERANT_WRITE_LAST_WRITE_DATA *) GET_GUID_HOB_DATA (GuidHob);\r
+          if (FtwLastWriteData->TargetAddress == NvStorageBase) {\r
+            //\r
+            // Let FvHeader point to spare block.\r
+            //\r
+            FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) FtwLastWriteData->SpareAddress;\r
+            DEBUG ((EFI_D_INFO, "PeiVariable: NV storage is backed up in spare block: 0x%x\n", (UINTN) FtwLastWriteData->SpareAddress));\r
+          } else if ((FtwLastWriteData->TargetAddress > NvStorageBase) && (FtwLastWriteData->TargetAddress < (NvStorageBase + NvStorageSize))) {\r
+            StoreInfo->FtwLastWriteData = FtwLastWriteData;\r
+            //\r
+            // Flash NV storage from the offset is backed up in spare block.\r
+            //\r
+            BackUpOffset = (UINT32) (FtwLastWriteData->TargetAddress - NvStorageBase);\r
+            DEBUG ((EFI_D_INFO, "PeiVariable: High partial NV storage from offset: %x is backed up in spare block: 0x%x\n", BackUpOffset, (UINTN) FtwLastWriteData->SpareAddress));\r
+            //\r
+            // At least one block data in flash NV storage is still valid, so still leave FvHeader point to NV storage base.\r
+            //\r
+          }\r
+        }\r
 \r
         //\r
         // Check if the Firmware Volume is not corrupted\r
 \r
         //\r
         // Check if the Firmware Volume is not corrupted\r
@@ -370,23 +495,21 @@ GetVariableStore (
         \r
         VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINT8 *) FvHeader + FvHeader->HeaderLength);\r
 \r
         \r
         VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINT8 *) FvHeader + FvHeader->HeaderLength);\r
 \r
-        if (IndexTable != NULL) {\r
-          GuidHob = GetFirstGuidHob (&gEfiVariableIndexTableGuid);\r
-          if (GuidHob != NULL) {\r
-            *IndexTable = GET_GUID_HOB_DATA (GuidHob);\r
-          } else {\r
-            //\r
-            // If it's the first time to access variable region in flash, create a guid hob to record\r
-            // VAR_ADDED type variable info.\r
-            // Note that as the resource of PEI phase is limited, only store the limited number of \r
-            // VAR_ADDED type variables to reduce access time.\r
-            //\r
-            *IndexTable = BuildGuidHob (&gEfiVariableIndexTableGuid, sizeof (VARIABLE_INDEX_TABLE));\r
-            (*IndexTable)->Length      = 0;\r
-            (*IndexTable)->StartPtr    = GetStartPointer (VariableStoreHeader);\r
-            (*IndexTable)->EndPtr      = GetEndPointer   (VariableStoreHeader);\r
-            (*IndexTable)->GoneThrough = 0;\r
-          }\r
+        GuidHob = GetFirstGuidHob (&gEfiVariableIndexTableGuid);\r
+        if (GuidHob != NULL) {\r
+          StoreInfo->IndexTable = GET_GUID_HOB_DATA (GuidHob);\r
+        } else {\r
+          //\r
+          // If it's the first time to access variable region in flash, create a guid hob to record\r
+          // VAR_ADDED type variable info.\r
+          // Note that as the resource of PEI phase is limited, only store the limited number of \r
+          // VAR_ADDED type variables to reduce access time.\r
+          //\r
+          StoreInfo->IndexTable = (VARIABLE_INDEX_TABLE *) BuildGuidHob (&gEfiVariableIndexTableGuid, sizeof (VARIABLE_INDEX_TABLE));\r
+          StoreInfo->IndexTable->Length      = 0;\r
+          StoreInfo->IndexTable->StartPtr    = GetStartPointer (VariableStoreHeader);\r
+          StoreInfo->IndexTable->EndPtr      = GetEndPointer   (VariableStoreHeader);\r
+          StoreInfo->IndexTable->GoneThrough = 0;\r
         }\r
       }\r
       break;\r
         }\r
       }\r
       break;\r
@@ -396,14 +519,118 @@ GetVariableStore (
       break;\r
   }\r
 \r
       break;\r
   }\r
 \r
+  StoreInfo->VariableStoreHeader = VariableStoreHeader;\r
   return VariableStoreHeader;\r
 }\r
 \r
   return VariableStoreHeader;\r
 }\r
 \r
+/**\r
+  Get variable header that has consecutive content.\r
+\r
+  @param StoreInfo      Pointer to variable store info structure.\r
+  @param Variable       Pointer to the Variable Header.\r
+  @param VariableHeader Pointer to Pointer to the Variable Header that has consecutive content.\r
+\r
+  @retval TRUE          Variable header is valid.\r
+  @retval FALSE         Variable header is not valid.\r
+\r
+**/\r
+BOOLEAN\r
+GetVariableHeader (\r
+  IN VARIABLE_STORE_INFO    *StoreInfo,\r
+  IN VARIABLE_HEADER        *Variable,\r
+  OUT VARIABLE_HEADER       **VariableHeader\r
+  )\r
+{\r
+  EFI_PHYSICAL_ADDRESS  TargetAddress;\r
+  EFI_PHYSICAL_ADDRESS  SpareAddress;\r
+  EFI_HOB_GUID_TYPE     *GuidHob;\r
+  UINTN                 PartialHeaderSize;\r
+\r
+   //\r
+   // First assume variable header pointed by Variable is consecutive.\r
+   //\r
+  *VariableHeader = Variable;\r
+\r
+  if ((Variable != NULL) && (StoreInfo->FtwLastWriteData != NULL)) {\r
+    TargetAddress = StoreInfo->FtwLastWriteData->TargetAddress;\r
+    SpareAddress = StoreInfo->FtwLastWriteData->SpareAddress;\r
+    if (((UINTN) Variable < (UINTN) TargetAddress) && (((UINTN) Variable + sizeof (VARIABLE_HEADER)) > (UINTN) TargetAddress)) {\r
+      //\r
+      // Variable header pointed by Variable is inconsecutive,\r
+      // create a guid hob to combine the two partial variable header content together.\r
+      //\r
+      GuidHob = GetFirstGuidHob (&gEfiCallerIdGuid);\r
+      if (GuidHob != NULL) {\r
+        *VariableHeader = (VARIABLE_HEADER *) GET_GUID_HOB_DATA (GuidHob);\r
+      } else {\r
+        *VariableHeader = (VARIABLE_HEADER *) BuildGuidHob (&gEfiCallerIdGuid, sizeof (VARIABLE_HEADER));\r
+        PartialHeaderSize = (UINTN) TargetAddress - (UINTN) Variable;\r
+        //\r
+        // Partial content is in NV storage.\r
+        //\r
+        CopyMem ((UINT8 *) *VariableHeader, (UINT8 *) Variable, PartialHeaderSize);\r
+        //\r
+        // Another partial content is in spare block.\r
+        //\r
+        CopyMem ((UINT8 *) *VariableHeader + PartialHeaderSize, (UINT8 *) (UINTN) SpareAddress, sizeof (VARIABLE_HEADER) - PartialHeaderSize);\r
+      }\r
+    }\r
+  }\r
+\r
+  return IsValidVariableHeader (*VariableHeader);\r
+}\r
+\r
+/**\r
+  Get variable name or data to output buffer.\r
+\r
+  @param  StoreInfo     Pointer to variable store info structure.\r
+  @param  NameOrData    Pointer to the variable name/data that may be inconsecutive.\r
+  @param  Size          Variable name/data size.\r
+  @param  Buffer        Pointer to output buffer to hold the variable name/data.\r
+\r
+**/\r
+VOID\r
+GetVariableNameOrData (\r
+  IN VARIABLE_STORE_INFO    *StoreInfo,\r
+  IN UINT8                  *NameOrData,\r
+  IN UINTN                  Size,\r
+  OUT UINT8                 *Buffer\r
+  )\r
+{\r
+  EFI_PHYSICAL_ADDRESS  TargetAddress;\r
+  EFI_PHYSICAL_ADDRESS  SpareAddress;\r
+  UINTN                 PartialSize;\r
\r
+  if (StoreInfo->FtwLastWriteData != NULL) {\r
+    TargetAddress = StoreInfo->FtwLastWriteData->TargetAddress;\r
+    SpareAddress = StoreInfo->FtwLastWriteData->SpareAddress;\r
+    if (((UINTN) NameOrData < (UINTN) TargetAddress) && (((UINTN) NameOrData + Size) > (UINTN) TargetAddress)) {\r
+      //\r
+      // Variable name/data is inconsecutive.\r
+      //\r
+      PartialSize = (UINTN) TargetAddress - (UINTN) NameOrData;\r
+      //\r
+      // Partial content is in NV storage.\r
+      //\r
+      CopyMem (Buffer, NameOrData, PartialSize);\r
+      //\r
+      // Another partial content is in spare block.\r
+      //\r
+      CopyMem (Buffer + PartialSize, (UINT8 *) (UINTN) SpareAddress, Size - PartialSize);\r
+      return;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Variable name/data is consecutive.\r
+  //\r
+  CopyMem (Buffer, NameOrData, Size);\r
+}\r
+\r
 /**\r
   Find the variable in the specified variable store.\r
 \r
 /**\r
   Find the variable in the specified variable store.\r
 \r
-  @param  VariableStoreHeader Pointer to the variable store header.\r
-  @param  IndexTable          Pointer to the index table.\r
+  @param  StoreInfo           Pointer to the store info structure.\r
   @param  VariableName        Name of the variable to be found\r
   @param  VendorGuid          Vendor GUID to be found.\r
   @param  PtrTrack            Variable Track Pointer structure that contains Variable Information.\r
   @param  VariableName        Name of the variable to be found\r
   @param  VendorGuid          Vendor GUID to be found.\r
   @param  PtrTrack            Variable Track Pointer structure that contains Variable Information.\r
@@ -415,8 +642,7 @@ GetVariableStore (
 **/\r
 EFI_STATUS\r
 FindVariableEx (\r
 **/\r
 EFI_STATUS\r
 FindVariableEx (\r
-  IN VARIABLE_STORE_HEADER       *VariableStoreHeader,\r
-  IN VARIABLE_INDEX_TABLE        *IndexTable,\r
+  IN VARIABLE_STORE_INFO         *StoreInfo,\r
   IN CONST CHAR16                *VariableName,\r
   IN CONST EFI_GUID              *VendorGuid,\r
   OUT VARIABLE_POINTER_TRACK     *PtrTrack\r
   IN CONST CHAR16                *VariableName,\r
   IN CONST EFI_GUID              *VendorGuid,\r
   OUT VARIABLE_POINTER_TRACK     *PtrTrack\r
@@ -429,6 +655,11 @@ FindVariableEx (
   UINTN                   Offset;\r
   BOOLEAN                 StopRecord;\r
   VARIABLE_HEADER         *InDeletedVariable;\r
   UINTN                   Offset;\r
   BOOLEAN                 StopRecord;\r
   VARIABLE_HEADER         *InDeletedVariable;\r
+  VARIABLE_STORE_HEADER   *VariableStoreHeader;\r
+  VARIABLE_INDEX_TABLE    *IndexTable;\r
+  VARIABLE_HEADER         *VariableHeader;\r
+\r
+  VariableStoreHeader = StoreInfo->VariableStoreHeader;\r
 \r
   if (VariableStoreHeader == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
 \r
   if (VariableStoreHeader == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
@@ -442,6 +673,7 @@ FindVariableEx (
     return EFI_NOT_FOUND;\r
   }\r
 \r
     return EFI_NOT_FOUND;\r
   }\r
 \r
+  IndexTable = StoreInfo->IndexTable;\r
   PtrTrack->StartPtr = GetStartPointer (VariableStoreHeader);\r
   PtrTrack->EndPtr   = GetEndPointer   (VariableStoreHeader);\r
 \r
   PtrTrack->StartPtr = GetStartPointer (VariableStoreHeader);\r
   PtrTrack->EndPtr   = GetEndPointer   (VariableStoreHeader);\r
 \r
@@ -451,6 +683,7 @@ FindVariableEx (
   // No Variable Address equals zero, so 0 as initial value is safe.\r
   //\r
   MaxIndex   = NULL;\r
   // No Variable Address equals zero, so 0 as initial value is safe.\r
   //\r
   MaxIndex   = NULL;\r
+  VariableHeader = NULL;\r
 \r
   if (IndexTable != NULL) {\r
     //\r
 \r
   if (IndexTable != NULL) {\r
     //\r
@@ -461,8 +694,9 @@ FindVariableEx (
       ASSERT (Index < sizeof (IndexTable->Index) / sizeof (IndexTable->Index[0]));\r
       Offset   += IndexTable->Index[Index];\r
       MaxIndex  = (VARIABLE_HEADER *) ((UINT8 *) IndexTable->StartPtr + Offset);\r
       ASSERT (Index < sizeof (IndexTable->Index) / sizeof (IndexTable->Index[0]));\r
       Offset   += IndexTable->Index[Index];\r
       MaxIndex  = (VARIABLE_HEADER *) ((UINT8 *) IndexTable->StartPtr + Offset);\r
-      if (CompareWithValidVariable (MaxIndex, VariableName, VendorGuid, PtrTrack) == EFI_SUCCESS) {\r
-        if (PtrTrack->CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {\r
+      GetVariableHeader (StoreInfo, MaxIndex, &VariableHeader);\r
+      if (CompareWithValidVariable (StoreInfo, MaxIndex, VariableHeader, VariableName, VendorGuid, PtrTrack) == EFI_SUCCESS) {\r
+        if (VariableHeader->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {\r
           InDeletedVariable = PtrTrack->CurrPtr;\r
         } else {\r
           return EFI_SUCCESS;\r
           InDeletedVariable = PtrTrack->CurrPtr;\r
         } else {\r
           return EFI_SUCCESS;\r
@@ -484,7 +718,7 @@ FindVariableEx (
     // HOB exists but the variable cannot be found in HOB\r
     // If not found in HOB, then let's start from the MaxIndex we've found.\r
     //\r
     // HOB exists but the variable cannot be found in HOB\r
     // If not found in HOB, then let's start from the MaxIndex we've found.\r
     //\r
-    Variable     = GetNextVariablePtr (MaxIndex);\r
+    Variable     = GetNextVariablePtr (StoreInfo, MaxIndex, VariableHeader);\r
     LastVariable = MaxIndex;\r
   } else {\r
     //\r
     LastVariable = MaxIndex;\r
   } else {\r
     //\r
@@ -499,8 +733,8 @@ FindVariableEx (
   // Find the variable by walk through variable store\r
   //\r
   StopRecord = FALSE;\r
   // Find the variable by walk through variable store\r
   //\r
   StopRecord = FALSE;\r
-  while ((Variable < PtrTrack->EndPtr) && IsValidVariableHeader (Variable)) {\r
-    if (Variable->State == VAR_ADDED || Variable->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {\r
+  while (GetVariableHeader (StoreInfo, Variable, &VariableHeader)) {\r
+    if (VariableHeader->State == VAR_ADDED || VariableHeader->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {\r
       //\r
       // Record Variable in VariableIndex HOB\r
       //\r
       //\r
       // Record Variable in VariableIndex HOB\r
       //\r
@@ -518,8 +752,8 @@ FindVariableEx (
         }\r
       }\r
 \r
         }\r
       }\r
 \r
-      if (CompareWithValidVariable (Variable, VariableName, VendorGuid, PtrTrack) == EFI_SUCCESS) {\r
-        if (PtrTrack->CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {\r
+      if (CompareWithValidVariable (StoreInfo, Variable, VariableHeader, VariableName, VendorGuid, PtrTrack) == EFI_SUCCESS) {\r
+        if (VariableHeader->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {\r
           InDeletedVariable = PtrTrack->CurrPtr;\r
         } else {\r
           return EFI_SUCCESS;\r
           InDeletedVariable = PtrTrack->CurrPtr;\r
         } else {\r
           return EFI_SUCCESS;\r
@@ -527,7 +761,7 @@ FindVariableEx (
       }\r
     }\r
 \r
       }\r
     }\r
 \r
-    Variable = GetNextVariablePtr (Variable);\r
+    Variable = GetNextVariablePtr (StoreInfo, Variable, VariableHeader);\r
   }\r
   //\r
   // If gone through the VariableStore, that means we never find in Firmware any more.\r
   }\r
   //\r
   // If gone through the VariableStore, that means we never find in Firmware any more.\r
@@ -547,6 +781,7 @@ FindVariableEx (
   @param  VariableName  Name of the variable to be found\r
   @param  VendorGuid    Vendor GUID to be found.\r
   @param  PtrTrack      Variable Track Pointer structure that contains Variable Information.\r
   @param  VariableName  Name of the variable to be found\r
   @param  VendorGuid    Vendor GUID to be found.\r
   @param  PtrTrack      Variable Track Pointer structure that contains Variable Information.\r
+  @param  StoreInfo     Return the store info.\r
 \r
   @retval  EFI_SUCCESS            Variable found successfully\r
   @retval  EFI_NOT_FOUND          Variable not found\r
 \r
   @retval  EFI_SUCCESS            Variable found successfully\r
   @retval  EFI_NOT_FOUND          Variable not found\r
@@ -556,12 +791,11 @@ EFI_STATUS
 FindVariable (\r
   IN CONST  CHAR16            *VariableName,\r
   IN CONST  EFI_GUID          *VendorGuid,\r
 FindVariable (\r
   IN CONST  CHAR16            *VariableName,\r
   IN CONST  EFI_GUID          *VendorGuid,\r
-  OUT VARIABLE_POINTER_TRACK  *PtrTrack\r
+  OUT VARIABLE_POINTER_TRACK  *PtrTrack,\r
+  OUT VARIABLE_STORE_INFO     *StoreInfo\r
   )\r
 {\r
   EFI_STATUS                  Status;\r
   )\r
 {\r
   EFI_STATUS                  Status;\r
-  VARIABLE_STORE_HEADER       *VariableStoreHeader;\r
-  VARIABLE_INDEX_TABLE        *IndexTable;\r
   VARIABLE_STORE_TYPE         Type;\r
 \r
   if (VariableName[0] != 0 && VendorGuid == NULL) {\r
   VARIABLE_STORE_TYPE         Type;\r
 \r
   if (VariableName[0] != 0 && VendorGuid == NULL) {\r
@@ -569,10 +803,9 @@ FindVariable (
   }\r
 \r
   for (Type = (VARIABLE_STORE_TYPE) 0; Type < VariableStoreTypeMax; Type++) {\r
   }\r
 \r
   for (Type = (VARIABLE_STORE_TYPE) 0; Type < VariableStoreTypeMax; Type++) {\r
-    VariableStoreHeader = GetVariableStore (Type, &IndexTable);\r
+    GetVariableStore (Type, StoreInfo);\r
     Status = FindVariableEx (\r
     Status = FindVariableEx (\r
-               VariableStoreHeader,\r
-               IndexTable,\r
+               StoreInfo,\r
                VariableName,\r
                VendorGuid, \r
                PtrTrack\r
                VariableName,\r
                VendorGuid, \r
                PtrTrack\r
@@ -625,6 +858,8 @@ PeiGetVariable (
   VARIABLE_POINTER_TRACK  Variable;\r
   UINTN                   VarDataSize;\r
   EFI_STATUS              Status;\r
   VARIABLE_POINTER_TRACK  Variable;\r
   UINTN                   VarDataSize;\r
   EFI_STATUS              Status;\r
+  VARIABLE_STORE_INFO     StoreInfo;\r
+  VARIABLE_HEADER         *VariableHeader;\r
 \r
   if (VariableName == NULL || VariableGuid == NULL || DataSize == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
 \r
   if (VariableName == NULL || VariableGuid == NULL || DataSize == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
@@ -633,23 +868,25 @@ PeiGetVariable (
   //\r
   // Find existing variable\r
   //\r
   //\r
   // Find existing variable\r
   //\r
-  Status = FindVariable (VariableName, VariableGuid, &Variable);\r
+  Status = FindVariable (VariableName, VariableGuid, &Variable, &StoreInfo);\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
+  GetVariableHeader (&StoreInfo, Variable.CurrPtr, &VariableHeader);\r
+\r
   //\r
   // Get data size\r
   //\r
   //\r
   // Get data size\r
   //\r
-  VarDataSize = DataSizeOfVariable (Variable.CurrPtr);\r
+  VarDataSize = DataSizeOfVariable (VariableHeader);\r
   if (*DataSize >= VarDataSize) {\r
     if (Data == NULL) {\r
       return EFI_INVALID_PARAMETER;\r
     }\r
 \r
   if (*DataSize >= VarDataSize) {\r
     if (Data == NULL) {\r
       return EFI_INVALID_PARAMETER;\r
     }\r
 \r
-    CopyMem (Data, GetVariableDataPtr (Variable.CurrPtr), VarDataSize);\r
+    GetVariableNameOrData (&StoreInfo, GetVariableDataPtr (Variable.CurrPtr, VariableHeader), VarDataSize, Data);\r
 \r
     if (Attributes != NULL) {\r
 \r
     if (Attributes != NULL) {\r
-      *Attributes = Variable.CurrPtr->Attributes;\r
+      *Attributes = VariableHeader->Attributes;\r
     }\r
 \r
     *DataSize = VarDataSize;\r
     }\r
 \r
     *DataSize = VarDataSize;\r
@@ -702,16 +939,19 @@ PeiGetNextVariableName (
   VARIABLE_POINTER_TRACK  Variable;\r
   VARIABLE_POINTER_TRACK  VariableInHob;\r
   VARIABLE_POINTER_TRACK  VariablePtrTrack;\r
   VARIABLE_POINTER_TRACK  Variable;\r
   VARIABLE_POINTER_TRACK  VariableInHob;\r
   VARIABLE_POINTER_TRACK  VariablePtrTrack;\r
-  VARIABLE_INDEX_TABLE    *IndexTable;\r
   UINTN                   VarNameSize;\r
   EFI_STATUS              Status;\r
   VARIABLE_STORE_HEADER   *VariableStoreHeader[VariableStoreTypeMax];\r
   UINTN                   VarNameSize;\r
   EFI_STATUS              Status;\r
   VARIABLE_STORE_HEADER   *VariableStoreHeader[VariableStoreTypeMax];\r
+  VARIABLE_HEADER         *VariableHeader;\r
+  VARIABLE_STORE_INFO     StoreInfo;\r
+  VARIABLE_STORE_INFO     StoreInfoForNv;\r
+  VARIABLE_STORE_INFO     StoreInfoForHob;\r
 \r
   if (VariableName == NULL || VariableGuid == NULL || VariableNameSize == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
 \r
   if (VariableName == NULL || VariableGuid == NULL || VariableNameSize == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  Status = FindVariable (VariableName, VariableGuid, &Variable);\r
+  Status = FindVariable (VariableName, VariableGuid, &Variable, &StoreInfo);\r
   if (Variable.CurrPtr == NULL || Status != EFI_SUCCESS) {\r
     return Status;\r
   }\r
   if (Variable.CurrPtr == NULL || Status != EFI_SUCCESS) {\r
     return Status;\r
   }\r
@@ -720,20 +960,18 @@ PeiGetNextVariableName (
     //\r
     // If variable name is not NULL, get next variable\r
     //\r
     //\r
     // If variable name is not NULL, get next variable\r
     //\r
-    Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);\r
+    GetVariableHeader (&StoreInfo, Variable.CurrPtr, &VariableHeader);\r
+    Variable.CurrPtr = GetNextVariablePtr (&StoreInfo, Variable.CurrPtr, VariableHeader);\r
   }\r
 \r
   }\r
 \r
-  VariableStoreHeader[VariableStoreTypeHob] = GetVariableStore (VariableStoreTypeHob, NULL);\r
-  VariableStoreHeader[VariableStoreTypeNv]  = GetVariableStore (VariableStoreTypeNv, NULL);\r
+  VariableStoreHeader[VariableStoreTypeHob] = GetVariableStore (VariableStoreTypeHob, &StoreInfoForHob);\r
+  VariableStoreHeader[VariableStoreTypeNv]  = GetVariableStore (VariableStoreTypeNv, &StoreInfoForNv);\r
 \r
   while (TRUE) {\r
     //\r
     // Switch from HOB to Non-Volatile.\r
     //\r
 \r
   while (TRUE) {\r
     //\r
     // Switch from HOB to Non-Volatile.\r
     //\r
-    while ((Variable.CurrPtr >= Variable.EndPtr) ||\r
-           (Variable.CurrPtr == NULL)            ||\r
-           !IsValidVariableHeader (Variable.CurrPtr)\r
-          ) {\r
+    while (!GetVariableHeader (&StoreInfo, Variable.CurrPtr, &VariableHeader)) {\r
       //\r
       // Find current storage index\r
       //\r
       //\r
       // Find current storage index\r
       //\r
@@ -762,31 +1000,24 @@ PeiGetNextVariableName (
       Variable.StartPtr = GetStartPointer (VariableStoreHeader[Type]);\r
       Variable.EndPtr   = GetEndPointer   (VariableStoreHeader[Type]);\r
       Variable.CurrPtr  = Variable.StartPtr;\r
       Variable.StartPtr = GetStartPointer (VariableStoreHeader[Type]);\r
       Variable.EndPtr   = GetEndPointer   (VariableStoreHeader[Type]);\r
       Variable.CurrPtr  = Variable.StartPtr;\r
+      GetVariableStore (Type, &StoreInfo);\r
     }\r
 \r
     }\r
 \r
-    if (Variable.CurrPtr->State == VAR_ADDED || Variable.CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {\r
-      if (Variable.CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {\r
+    if (VariableHeader->State == VAR_ADDED || VariableHeader->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {\r
+      if (VariableHeader->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {\r
         //\r
         // If it is a IN_DELETED_TRANSITION variable,\r
         // and there is also a same ADDED one at the same time,\r
         // don't return it.\r
         //\r
         //\r
         // If it is a IN_DELETED_TRANSITION variable,\r
         // and there is also a same ADDED one at the same time,\r
         // don't return it.\r
         //\r
-        for (Type = (VARIABLE_STORE_TYPE) 0; Type < VariableStoreTypeMax; Type++) {\r
-          if ((VariableStoreHeader[Type] != NULL) && (Variable.StartPtr == GetStartPointer (VariableStoreHeader[Type]))) {\r
-            break;\r
-          }\r
-        }\r
-        ASSERT (Type < VariableStoreTypeMax);\r
-        GetVariableStore (Type, &IndexTable);\r
         Status = FindVariableEx (\r
         Status = FindVariableEx (\r
-                   VariableStoreHeader[Type],\r
-                   IndexTable,\r
+                   &StoreInfo,\r
                    GetVariableNamePtr (Variable.CurrPtr),\r
                    GetVariableNamePtr (Variable.CurrPtr),\r
-                   &Variable.CurrPtr->VendorGuid,\r
+                   &VariableHeader->VendorGuid,\r
                    &VariablePtrTrack\r
                    );\r
                    &VariablePtrTrack\r
                    );\r
-        if (!EFI_ERROR (Status) && VariablePtrTrack.CurrPtr->State == VAR_ADDED) {\r
-          Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);\r
+        if (!EFI_ERROR (Status) && VariablePtrTrack.CurrPtr != Variable.CurrPtr) {\r
+          Variable.CurrPtr = GetNextVariablePtr (&StoreInfo, Variable.CurrPtr, VariableHeader);\r
           continue;\r
         }\r
       }\r
           continue;\r
         }\r
       }\r
@@ -798,25 +1029,24 @@ PeiGetNextVariableName (
           (Variable.StartPtr == GetStartPointer (VariableStoreHeader[VariableStoreTypeNv]))\r
          ) {\r
         Status = FindVariableEx (\r
           (Variable.StartPtr == GetStartPointer (VariableStoreHeader[VariableStoreTypeNv]))\r
          ) {\r
         Status = FindVariableEx (\r
-                   VariableStoreHeader[VariableStoreTypeHob],\r
-                   NULL,\r
+                   &StoreInfoForHob,\r
                    GetVariableNamePtr (Variable.CurrPtr),\r
                    GetVariableNamePtr (Variable.CurrPtr),\r
-                   &Variable.CurrPtr->VendorGuid, \r
+                   &VariableHeader->VendorGuid, \r
                    &VariableInHob\r
                    );\r
         if (!EFI_ERROR (Status)) {\r
                    &VariableInHob\r
                    );\r
         if (!EFI_ERROR (Status)) {\r
-          Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);\r
+          Variable.CurrPtr = GetNextVariablePtr (&StoreInfo, Variable.CurrPtr, VariableHeader);\r
           continue;\r
         }\r
       }\r
 \r
           continue;\r
         }\r
       }\r
 \r
-      VarNameSize = NameSizeOfVariable (Variable.CurrPtr);\r
+      VarNameSize = NameSizeOfVariable (VariableHeader);\r
       ASSERT (VarNameSize != 0);\r
 \r
       if (VarNameSize <= *VariableNameSize) {\r
       ASSERT (VarNameSize != 0);\r
 \r
       if (VarNameSize <= *VariableNameSize) {\r
-        CopyMem (VariableName, GetVariableNamePtr (Variable.CurrPtr), VarNameSize);\r
+        GetVariableNameOrData (&StoreInfo, (UINT8 *) GetVariableNamePtr (Variable.CurrPtr), VarNameSize, (UINT8 *) VariableName);\r
 \r
 \r
-        CopyMem (VariableGuid, &Variable.CurrPtr->VendorGuid, sizeof (EFI_GUID));\r
+        CopyMem (VariableGuid, &VariableHeader->VendorGuid, sizeof (EFI_GUID));\r
 \r
         Status = EFI_SUCCESS;\r
       } else {\r
 \r
         Status = EFI_SUCCESS;\r
       } else {\r
@@ -829,7 +1059,7 @@ PeiGetNextVariableName (
       //\r
       return Status;\r
     } else {\r
       //\r
       return Status;\r
     } else {\r
-      Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);\r
+      Variable.CurrPtr = GetNextVariablePtr (&StoreInfo, Variable.CurrPtr, VariableHeader);\r
     }\r
   }\r
 }\r
     }\r
   }\r
 }\r
index a85d3bbab65dd4e58cf16b025f30d40f33dfd7d4..7693522ffbc7b96da5ef838b0ec2c1588adf7d8e 100644 (file)
@@ -2,7 +2,7 @@
   The internal header file includes the common header files, defines\r
   internal structure and functions used by PeiVariable module.\r
 \r
   The internal header file includes the common header files, defines\r
   internal structure and functions used by PeiVariable module.\r
 \r
-Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2009 - 2013, Intel Corporation. All rights reserved.<BR>\r
 This program and the accompanying materials \r
 are licensed and made available under the terms and conditions of the BSD License \r
 which accompanies this distribution.  The full text of the license may be found at \r
 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
@@ -30,6 +30,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <Guid/AuthenticatedVariableFormat.h>\r
 #include <Guid/VariableIndexTable.h>\r
 #include <Guid/SystemNvDataGuid.h>\r
 #include <Guid/AuthenticatedVariableFormat.h>\r
 #include <Guid/VariableIndexTable.h>\r
 #include <Guid/SystemNvDataGuid.h>\r
+#include <Guid/FaultTolerantWrite.h>\r
 \r
 typedef enum {\r
   VariableStoreTypeHob,\r
 \r
 typedef enum {\r
   VariableStoreTypeHob,\r
@@ -37,6 +38,17 @@ typedef enum {
   VariableStoreTypeMax\r
 } VARIABLE_STORE_TYPE;\r
 \r
   VariableStoreTypeMax\r
 } VARIABLE_STORE_TYPE;\r
 \r
+typedef struct {\r
+  VARIABLE_STORE_HEADER                   *VariableStoreHeader;\r
+  VARIABLE_INDEX_TABLE                    *IndexTable;\r
+  //\r
+  // If it is not NULL, it means there may be an inconsecutive variable whose\r
+  // partial content is still in NV storage, but another partial content is backed up\r
+  // in spare block.\r
+  //\r
+  FAULT_TOLERANT_WRITE_LAST_WRITE_DATA    *FtwLastWriteData;\r
+} VARIABLE_STORE_INFO;\r
+\r
 //\r
 // Functions\r
 //\r
 //\r
 // Functions\r
 //\r
index e74143cd19c5151e7e7b3470b0d8fe4fab7c1861..16ac97a3bb5bef72fe4bb947e0162a4efecf75d0 100644 (file)
@@ -1,7 +1,7 @@
 ## @file\r
 #  The component description for PEI variable driver. \r
 #\r
 ## @file\r
 #  The component description for PEI variable driver. \r
 #\r
-# Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>\r
+# Copyright (c) 2009 - 2013, Intel Corporation. All rights reserved.<BR>\r
 # This program and the accompanying materials\r
 # are licensed and made available under the terms and conditions of the BSD License\r
 # which accompanies this distribution. The full text of the license may be found at\r
 # 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
   gEfiAuthenticatedVariableGuid\r
   gEfiVariableIndexTableGuid\r
   gEfiSystemNvDataFvGuid\r
   gEfiAuthenticatedVariableGuid\r
   gEfiVariableIndexTableGuid\r
   gEfiSystemNvDataFvGuid\r
+  gEdkiiFaultTolerantWriteGuid\r
 \r
 [Ppis]\r
 \r
 [Ppis]\r
-  gEfiPeiReadOnlyVariable2PpiGuid                ## SOMETIMES_PRODUCES (Not for boot mode RECOVERY)\r
+  gEfiPeiReadOnlyVariable2PpiGuid                ## PRODUCES\r
 \r
 [Pcd]\r
 \r
 [Pcd]\r
-  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase  ## CONSUMES\r
-  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64  ## CONSUMES\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase      ## CONSUMES\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64    ## CONSUMES\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize      ## CONSUMES\r
 \r
 [Depex]\r
 \r
 [Depex]\r
-  TRUE\r
+  gEdkiiFaultTolerantWriteGuid\r
 \r
 #\r
 #  [BootMode]\r
 \r
 #\r
 #  [BootMode]\r
index 576623e88bea49d046eab7650cbce4cf88e78078..ef123d2d5c38d0fb6988f1672ef514c2c809de5d 100644 (file)
@@ -3068,6 +3068,135 @@ ReclaimForOS(
   }\r
 }\r
 \r
   }\r
 }\r
 \r
+/**\r
+  Init non-volatile variable store.\r
+\r
+  @retval EFI_SUCCESS           Function successfully executed.\r
+  @retval EFI_OUT_OF_RESOURCES  Fail to allocate enough memory resource.\r
+  @retval EFI_VOLUME_CORRUPTED  Variable Store or Firmware Volume for Variable Store is corrupted.\r
+\r
+**/\r
+EFI_STATUS\r
+InitNonVolatileVariableStore (\r
+  VOID\r
+  )\r
+{\r
+  EFI_FIRMWARE_VOLUME_HEADER            *FvHeader;\r
+  VARIABLE_HEADER                       *NextVariable;\r
+  EFI_PHYSICAL_ADDRESS                  VariableStoreBase;\r
+  UINT64                                VariableStoreLength;\r
+  UINTN                                 VariableSize;\r
+  EFI_HOB_GUID_TYPE                     *GuidHob;\r
+  EFI_PHYSICAL_ADDRESS                  NvStorageBase;\r
+  UINT8                                 *NvStorageData;\r
+  UINT32                                NvStorageSize;\r
+  FAULT_TOLERANT_WRITE_LAST_WRITE_DATA  *FtwLastWriteData;\r
+  UINT32                                BackUpOffset;\r
+  UINT32                                BackUpSize;\r
+\r
+  mVariableModuleGlobal->FvbInstance = NULL;\r
+\r
+  //\r
+  // Note that in EdkII variable driver implementation, Hardware Error Record type variable\r
+  // is stored with common variable in the same NV region. So the platform integrator should\r
+  // ensure that the value of PcdHwErrStorageSize is less than or equal to the value of\r
+  // PcdFlashNvStorageVariableSize.\r
+  //\r
+  ASSERT (PcdGet32 (PcdHwErrStorageSize) <= PcdGet32 (PcdFlashNvStorageVariableSize));\r
+\r
+  //\r
+  // Allocate runtime memory used for a memory copy of the FLASH region.\r
+  // Keep the memory and the FLASH in sync as updates occur.\r
+  //\r
+  NvStorageSize = PcdGet32 (PcdFlashNvStorageVariableSize);\r
+  NvStorageData = AllocateRuntimeZeroPool (NvStorageSize);\r
+  if (NvStorageData == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  NvStorageBase = (EFI_PHYSICAL_ADDRESS) PcdGet64 (PcdFlashNvStorageVariableBase64);\r
+  if (NvStorageBase == 0) {\r
+    NvStorageBase = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashNvStorageVariableBase);\r
+  }\r
+  //\r
+  // Copy NV storage data to the memory buffer.\r
+  //\r
+  CopyMem (NvStorageData, (UINT8 *) (UINTN) NvStorageBase, NvStorageSize);\r
+\r
+  //\r
+  // Check the FTW last write data hob.\r
+  //\r
+  GuidHob = GetFirstGuidHob (&gEdkiiFaultTolerantWriteGuid);\r
+  if (GuidHob != NULL) {\r
+    FtwLastWriteData = (FAULT_TOLERANT_WRITE_LAST_WRITE_DATA *) GET_GUID_HOB_DATA (GuidHob);\r
+    if (FtwLastWriteData->TargetAddress == NvStorageBase) {\r
+      DEBUG ((EFI_D_INFO, "Variable: NV storage is backed up in spare block: 0x%x\n", (UINTN) FtwLastWriteData->SpareAddress));\r
+      //\r
+      // Copy the backed up NV storage data to the memory buffer from spare block.\r
+      //\r
+      CopyMem (NvStorageData, (UINT8 *) (UINTN) (FtwLastWriteData->SpareAddress), NvStorageSize);\r
+    } else if ((FtwLastWriteData->TargetAddress > NvStorageBase) &&\r
+               (FtwLastWriteData->TargetAddress < (NvStorageBase + NvStorageSize))) {\r
+      //\r
+      // Flash NV storage from the Offset is backed up in spare block.\r
+      //\r
+      BackUpOffset = (UINT32) (FtwLastWriteData->TargetAddress - NvStorageBase);\r
+      BackUpSize = NvStorageSize - BackUpOffset;\r
+      DEBUG ((EFI_D_INFO, "Variable: High partial NV storage from offset: %x is backed up in spare block: 0x%x\n", BackUpOffset, (UINTN) FtwLastWriteData->SpareAddress));\r
+      //\r
+      // Copy the partial backed up NV storage data to the memory buffer from spare block.\r
+      //\r
+      CopyMem (NvStorageData + BackUpOffset, (UINT8 *) (UINTN) FtwLastWriteData->SpareAddress, BackUpSize);\r
+    }\r
+  }\r
+\r
+  FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) NvStorageData;\r
+\r
+  //\r
+  // Check if the Firmware Volume is not corrupted\r
+  //\r
+  if ((FvHeader->Signature != EFI_FVH_SIGNATURE) || (!CompareGuid (&gEfiSystemNvDataFvGuid, &FvHeader->FileSystemGuid))) {\r
+    FreePool (NvStorageData);\r
+    DEBUG ((EFI_D_ERROR, "Firmware Volume for Variable Store is corrupted\n"));\r
+    return EFI_VOLUME_CORRUPTED;\r
+  }\r
+\r
+  VariableStoreBase = (EFI_PHYSICAL_ADDRESS) ((UINTN) FvHeader + FvHeader->HeaderLength);\r
+  VariableStoreLength = (UINT64) (NvStorageSize - FvHeader->HeaderLength);\r
+\r
+  mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase = VariableStoreBase;\r
+  mNvVariableCache = (VARIABLE_STORE_HEADER *) (UINTN) VariableStoreBase;\r
+  if (GetVariableStoreStatus (mNvVariableCache) != EfiValid) {\r
+    FreePool (NvStorageData);\r
+    DEBUG((EFI_D_ERROR, "Variable Store header is corrupted\n"));\r
+    return EFI_VOLUME_CORRUPTED;\r
+  }\r
+  ASSERT(mNvVariableCache->Size == VariableStoreLength);\r
+\r
+  //\r
+  // The max variable or hardware error variable size should be < variable store size.\r
+  //\r
+  ASSERT(MAX (PcdGet32 (PcdMaxVariableSize), PcdGet32 (PcdMaxHardwareErrorVariableSize)) < VariableStoreLength);\r
+\r
+  //\r
+  // Parse non-volatile variable data and get last variable offset.\r
+  //\r
+  NextVariable  = GetStartPointer ((VARIABLE_STORE_HEADER *)(UINTN)VariableStoreBase);\r
+  while (IsValidVariableHeader (NextVariable)) {\r
+    VariableSize = NextVariable->NameSize + NextVariable->DataSize + sizeof (VARIABLE_HEADER);\r
+    if ((NextVariable->Attributes & (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) == (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {\r
+      mVariableModuleGlobal->HwErrVariableTotalSize += HEADER_ALIGN (VariableSize);\r
+    } else {\r
+      mVariableModuleGlobal->CommonVariableTotalSize += HEADER_ALIGN (VariableSize);\r
+    }\r
+\r
+    NextVariable = GetNextVariablePtr (NextVariable);\r
+  }\r
+  mVariableModuleGlobal->NonVolatileLastVariableOffset = (UINTN) NextVariable - (UINTN) VariableStoreBase;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
 /**\r
   Flush the HOB variable to flash.\r
 \r
 /**\r
   Flush the HOB variable to flash.\r
 \r
@@ -3159,7 +3288,7 @@ FlushHobVariableToFlash (
 }\r
 \r
 /**\r
 }\r
 \r
 /**\r
-  Initializes variable write service after FVB was ready.\r
+  Initializes variable write service after FTW was ready.\r
 \r
   @retval EFI_SUCCESS          Function successfully executed.\r
   @retval Others               Fail to initialize the variable service.\r
 \r
   @retval EFI_SUCCESS          Function successfully executed.\r
   @retval Others               Fail to initialize the variable service.\r
@@ -3175,8 +3304,18 @@ VariableWriteServiceInitialize (
   UINTN                           Index;\r
   UINT8                           Data;\r
   EFI_PHYSICAL_ADDRESS            VariableStoreBase;\r
   UINTN                           Index;\r
   UINT8                           Data;\r
   EFI_PHYSICAL_ADDRESS            VariableStoreBase;\r
+  EFI_PHYSICAL_ADDRESS            NvStorageBase;\r
+\r
+  NvStorageBase = (EFI_PHYSICAL_ADDRESS) PcdGet64 (PcdFlashNvStorageVariableBase64);\r
+  if (NvStorageBase == 0) {\r
+    NvStorageBase = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashNvStorageVariableBase);\r
+  }\r
+  VariableStoreBase = NvStorageBase + (((EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)(NvStorageBase))->HeaderLength);\r
 \r
 \r
-  VariableStoreBase   = mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase;\r
+  //\r
+  // Let NonVolatileVariableBase point to flash variable store base directly after FTW ready.\r
+  //\r
+  mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase = VariableStoreBase;\r
   VariableStoreHeader = (VARIABLE_STORE_HEADER *)(UINTN)VariableStoreBase;\r
 \r
   //\r
   VariableStoreHeader = (VARIABLE_STORE_HEADER *)(UINTN)VariableStoreBase;\r
 \r
   //\r
@@ -3229,12 +3368,8 @@ VariableCommonInitialize (
   EFI_STATUS                      Status;\r
   VARIABLE_STORE_HEADER           *VolatileVariableStore;\r
   VARIABLE_STORE_HEADER           *VariableStoreHeader;\r
   EFI_STATUS                      Status;\r
   VARIABLE_STORE_HEADER           *VolatileVariableStore;\r
   VARIABLE_STORE_HEADER           *VariableStoreHeader;\r
-  VARIABLE_HEADER                 *NextVariable;\r
-  EFI_PHYSICAL_ADDRESS            TempVariableStoreHeader;\r
-  EFI_PHYSICAL_ADDRESS            VariableStoreBase;\r
   UINT64                          VariableStoreLength;\r
   UINTN                           ScratchSize;\r
   UINT64                          VariableStoreLength;\r
   UINTN                           ScratchSize;\r
-  UINTN                           VariableSize;\r
   EFI_HOB_GUID_TYPE               *GuidHob;\r
 \r
   //\r
   EFI_HOB_GUID_TYPE               *GuidHob;\r
 \r
   //\r
@@ -3247,14 +3382,6 @@ VariableCommonInitialize (
 \r
   InitializeLock (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock, TPL_NOTIFY);\r
 \r
 \r
   InitializeLock (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock, TPL_NOTIFY);\r
 \r
-  //\r
-  // Note that in EdkII variable driver implementation, Hardware Error Record type variable\r
-  // is stored with common variable in the same NV region. So the platform integrator should\r
-  // ensure that the value of PcdHwErrStorageSize is less than or equal to the value of\r
-  // PcdFlashNvStorageVariableSize.\r
-  //\r
-  ASSERT (PcdGet32 (PcdHwErrStorageSize) <= PcdGet32 (PcdFlashNvStorageVariableSize));\r
-\r
   //\r
   // Get HOB variable store.\r
   //\r
   //\r
   // Get HOB variable store.\r
   //\r
@@ -3265,6 +3392,7 @@ VariableCommonInitialize (
     if (GetVariableStoreStatus (VariableStoreHeader) == EfiValid) {\r
       mVariableModuleGlobal->VariableGlobal.HobVariableBase = (EFI_PHYSICAL_ADDRESS) (UINTN) AllocateRuntimeCopyPool ((UINTN) VariableStoreLength, (VOID *) VariableStoreHeader);\r
       if (mVariableModuleGlobal->VariableGlobal.HobVariableBase == 0) {\r
     if (GetVariableStoreStatus (VariableStoreHeader) == EfiValid) {\r
       mVariableModuleGlobal->VariableGlobal.HobVariableBase = (EFI_PHYSICAL_ADDRESS) (UINTN) AllocateRuntimeCopyPool ((UINTN) VariableStoreLength, (VOID *) VariableStoreHeader);\r
       if (mVariableModuleGlobal->VariableGlobal.HobVariableBase == 0) {\r
+        FreePool (mVariableModuleGlobal);\r
         return EFI_OUT_OF_RESOURCES;\r
       }\r
     } else {\r
         return EFI_OUT_OF_RESOURCES;\r
       }\r
     } else {\r
@@ -3278,6 +3406,9 @@ VariableCommonInitialize (
   ScratchSize = MAX (PcdGet32 (PcdMaxVariableSize), PcdGet32 (PcdMaxHardwareErrorVariableSize));\r
   VolatileVariableStore = AllocateRuntimePool (PcdGet32 (PcdVariableStoreSize) + ScratchSize);\r
   if (VolatileVariableStore == NULL) {\r
   ScratchSize = MAX (PcdGet32 (PcdMaxVariableSize), PcdGet32 (PcdMaxHardwareErrorVariableSize));\r
   VolatileVariableStore = AllocateRuntimePool (PcdGet32 (PcdVariableStoreSize) + ScratchSize);\r
   if (VolatileVariableStore == NULL) {\r
+    if (mVariableModuleGlobal->VariableGlobal.HobVariableBase != 0) {\r
+      FreePool ((VOID *) (UINTN) mVariableModuleGlobal->VariableGlobal.HobVariableBase);\r
+    }\r
     FreePool (mVariableModuleGlobal);\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
     FreePool (mVariableModuleGlobal);\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
@@ -3289,7 +3420,6 @@ VariableCommonInitialize (
   //\r
   mVariableModuleGlobal->VariableGlobal.VolatileVariableBase = (EFI_PHYSICAL_ADDRESS) (UINTN) VolatileVariableStore;\r
   mVariableModuleGlobal->VolatileLastVariableOffset = (UINTN) GetStartPointer (VolatileVariableStore) - (UINTN) VolatileVariableStore;\r
   //\r
   mVariableModuleGlobal->VariableGlobal.VolatileVariableBase = (EFI_PHYSICAL_ADDRESS) (UINTN) VolatileVariableStore;\r
   mVariableModuleGlobal->VolatileLastVariableOffset = (UINTN) GetStartPointer (VolatileVariableStore) - (UINTN) VolatileVariableStore;\r
-  mVariableModuleGlobal->FvbInstance = NULL;\r
 \r
   CopyGuid (&VolatileVariableStore->Signature, &gEfiAuthenticatedVariableGuid);\r
   VolatileVariableStore->Size        = PcdGet32 (PcdVariableStoreSize);\r
 \r
   CopyGuid (&VolatileVariableStore->Signature, &gEfiAuthenticatedVariableGuid);\r
   VolatileVariableStore->Size        = PcdGet32 (PcdVariableStoreSize);\r
@@ -3299,74 +3429,13 @@ VariableCommonInitialize (
   VolatileVariableStore->Reserved1   = 0;\r
 \r
   //\r
   VolatileVariableStore->Reserved1   = 0;\r
 \r
   //\r
-  // Get non-volatile variable store.\r
-  //\r
-\r
-  TempVariableStoreHeader = (EFI_PHYSICAL_ADDRESS) PcdGet64 (PcdFlashNvStorageVariableBase64);\r
-  if (TempVariableStoreHeader == 0) {\r
-    TempVariableStoreHeader = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashNvStorageVariableBase);\r
-  }\r
-  \r
-  //\r
-  // Check if the Firmware Volume is not corrupted\r
-  //\r
-  if ((((EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)(TempVariableStoreHeader))->Signature != EFI_FVH_SIGNATURE) ||\r
-      (!CompareGuid (&gEfiSystemNvDataFvGuid, &((EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)(TempVariableStoreHeader))->FileSystemGuid))) {\r
-    Status = EFI_VOLUME_CORRUPTED;\r
-    DEBUG ((EFI_D_ERROR, "Firmware Volume for Variable Store is corrupted\n"));\r
-    goto Done;\r
-  }\r
-\r
-  VariableStoreBase       = TempVariableStoreHeader + \\r
-                              (((EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)(TempVariableStoreHeader)) -> HeaderLength);\r
-  VariableStoreLength     = (UINT64) PcdGet32 (PcdFlashNvStorageVariableSize) - \\r
-                              (((EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)(TempVariableStoreHeader)) -> HeaderLength);\r
-\r
-  mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase = VariableStoreBase;\r
-  VariableStoreHeader = (VARIABLE_STORE_HEADER *)(UINTN)VariableStoreBase;\r
-  if (GetVariableStoreStatus (VariableStoreHeader) != EfiValid) {\r
-    Status = EFI_VOLUME_CORRUPTED;\r
-    DEBUG((EFI_D_INFO, "Variable Store header is corrupted\n"));\r
-    goto Done;\r
-  }\r
-  ASSERT(VariableStoreHeader->Size == VariableStoreLength);\r
-\r
-  //\r
-  // The max variable or hardware error variable size should be < variable store size.\r
-  //\r
-  ASSERT(MAX (PcdGet32 (PcdMaxVariableSize), PcdGet32 (PcdMaxHardwareErrorVariableSize)) < VariableStoreLength);\r
-\r
-  //\r
-  // Parse non-volatile variable data and get last variable offset.\r
+  // Init non-volatile variable store.\r
   //\r
   //\r
-  NextVariable  = GetStartPointer ((VARIABLE_STORE_HEADER *)(UINTN)VariableStoreBase);\r
-  while (IsValidVariableHeader (NextVariable)) {\r
-    VariableSize = NextVariable->NameSize + NextVariable->DataSize + sizeof (VARIABLE_HEADER);\r
-    if ((NextVariable->Attributes & (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) == (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {\r
-      mVariableModuleGlobal->HwErrVariableTotalSize += HEADER_ALIGN (VariableSize);\r
-    } else {\r
-      mVariableModuleGlobal->CommonVariableTotalSize += HEADER_ALIGN (VariableSize);\r
-    }\r
-\r
-    NextVariable = GetNextVariablePtr (NextVariable);\r
-  }\r
-\r
-  mVariableModuleGlobal->NonVolatileLastVariableOffset = (UINTN) NextVariable - (UINTN) VariableStoreBase;\r
-\r
-  //\r
-  // Allocate runtime memory used for a memory copy of the FLASH region.\r
-  // Keep the memory and the FLASH in sync as updates occur\r
-  //\r
-  mNvVariableCache = AllocateRuntimeZeroPool ((UINTN)VariableStoreLength);\r
-  if (mNvVariableCache == NULL) {\r
-    Status = EFI_OUT_OF_RESOURCES;\r
-    goto Done;\r
-  }\r
-  CopyMem (mNvVariableCache, (CHAR8 *)(UINTN)VariableStoreBase, (UINTN)VariableStoreLength);\r
-  Status = EFI_SUCCESS;\r
-\r
-Done:\r
+  Status = InitNonVolatileVariableStore ();\r
   if (EFI_ERROR (Status)) {\r
   if (EFI_ERROR (Status)) {\r
+    if (mVariableModuleGlobal->VariableGlobal.HobVariableBase != 0) {\r
+      FreePool ((VOID *) (UINTN) mVariableModuleGlobal->VariableGlobal.HobVariableBase);\r
+    }\r
     FreePool (mVariableModuleGlobal);\r
     FreePool (VolatileVariableStore);\r
   }\r
     FreePool (mVariableModuleGlobal);\r
     FreePool (VolatileVariableStore);\r
   }\r
index f394414b3fe1fd791158a27c1da631dfe4cff4e2..ebd0b50b14053e08ea028cde32abc6ce9fa0fa81 100644 (file)
@@ -41,6 +41,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <Guid/AuthenticatedVariableFormat.h>\r
 #include <Guid/ImageAuthentication.h>\r
 #include <Guid/SystemNvDataGuid.h>\r
 #include <Guid/AuthenticatedVariableFormat.h>\r
 #include <Guid/ImageAuthentication.h>\r
 #include <Guid/SystemNvDataGuid.h>\r
+#include <Guid/FaultTolerantWrite.h>\r
 #include <Guid/HardwareErrorVariable.h>\r
 \r
 #define VARIABLE_RECLAIM_THRESHOLD (1024)\r
 #include <Guid/HardwareErrorVariable.h>\r
 \r
 #define VARIABLE_RECLAIM_THRESHOLD (1024)\r
index dbd7d6e470a4c8fae10f8f7a0ee140b111e21643..4904adae2e794c8251d30dc423ebc9d7ead02414 100644 (file)
@@ -6,7 +6,7 @@
 #  This external input must be validated carefully to avoid security issue like\r
 #  buffer overflow, integer overflow.\r
 #\r
 #  This external input must be validated carefully to avoid security issue like\r
 #  buffer overflow, integer overflow.\r
 #\r
-# Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>\r
+# Copyright (c) 2009 - 2013, Intel Corporation. All rights reserved.<BR>\r
 # This program and the accompanying materials\r
 # are licensed and made available under the terms and conditions of the BSD License\r
 # which accompanies this distribution. The full text of the license may be found at\r
 # 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
@@ -84,6 +84,7 @@
   gEfiCertDbGuid\r
   gEfiHardwareErrorVariableGuid                 ## SOMETIMES_CONSUMES\r
   gEfiEndOfDxeEventGroupGuid                    ## CONSUMES ## Event\r
   gEfiCertDbGuid\r
   gEfiHardwareErrorVariableGuid                 ## SOMETIMES_CONSUMES\r
   gEfiEndOfDxeEventGroupGuid                    ## CONSUMES ## Event\r
+  gEdkiiFaultTolerantWriteGuid                  ## CONSUMES\r
 \r
 [Pcd]\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize\r
 \r
 [Pcd]\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize\r
index a9a10976eb871793821281fd453d2144498c401f..4180309c7f828204739bf9ee5fb1b970420a167d 100644 (file)
@@ -14,7 +14,7 @@
 #  This external input must be validated carefully to avoid security issue like\r
 #  buffer overflow, integer overflow.\r
 #\r
 #  This external input must be validated carefully to avoid security issue like\r
 #  buffer overflow, integer overflow.\r
 #\r
-# Copyright (c) 2010 - 2012, Intel Corporation. All rights reserved.<BR>\r
+# Copyright (c) 2010 - 2013, Intel Corporation. All rights reserved.<BR>\r
 # This program and the accompanying materials\r
 # are licensed and made available under the terms and conditions of the BSD License\r
 # which accompanies this distribution. The full text of the license may be found at\r
 # 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
@@ -89,6 +89,7 @@
   gEfiSystemNvDataFvGuid                        ## CONSUMES\r
   gEfiCertDbGuid\r
   gEfiHardwareErrorVariableGuid                 ## SOMETIMES_CONSUMES\r
   gEfiSystemNvDataFvGuid                        ## CONSUMES\r
   gEfiCertDbGuid\r
   gEfiHardwareErrorVariableGuid                 ## SOMETIMES_CONSUMES\r
+  gEdkiiFaultTolerantWriteGuid                  ## CONSUMES\r
 \r
 [Pcd]\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize\r
 \r
 [Pcd]\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize\r