]> git.proxmox.com Git - mirror_edk2.git/commitdiff
Fix a bug that the invalid public key will never be removed from public key database.
authorsfu5 <sfu5@6f19259b-4bc3-4df7-8a09-765794883524>
Wed, 9 Jan 2013 05:09:39 +0000 (05:09 +0000)
committersfu5 <sfu5@6f19259b-4bc3-4df7-8a09-765794883524>
Wed, 9 Jan 2013 05:09:39 +0000 (05:09 +0000)
Signed-off-by: Fu Siyuan <siyuan.fu@intel.com>
Reviewed-by: Ye Ting <ting.ye@intel.com>
Reviewed-by: Dong Guo <guo.dong@intel.com>
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@14041 6f19259b-4bc3-4df7-8a09-765794883524

SecurityPkg/VariableAuthenticated/RuntimeDxe/AuthService.c
SecurityPkg/VariableAuthenticated/RuntimeDxe/Variable.c
SecurityPkg/VariableAuthenticated/RuntimeDxe/Variable.h

index 64ce968ac10859599e9508e00cedef814489e644..1ba934b92294afe44fd9551803e12e5cf11121a7 100644 (file)
@@ -15,7 +15,7 @@
   They will do basic validation for authentication data structure, then call crypto library\r
   to verify the signature.\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
@@ -437,6 +437,8 @@ AddPubKeyInStore (
   UINT32                  Index;\r
   VARIABLE_POINTER_TRACK  Variable;\r
   UINT8                   *Ptr;\r
+  UINT8                   *Data;\r
+  UINTN                   DataSize;\r
 \r
   if (PubKey == NULL) {\r
     return 0;\r
@@ -468,9 +470,45 @@ AddPubKeyInStore (
     //\r
     if (mPubKeyNumber == MAX_KEY_NUM) {\r
       //\r
-      // Notes: Database is full, need enhancement here, currently just return 0.\r
+      // Public key dadatase is full, try to reclaim invalid key.\r
       //\r
-      return 0;\r
+      if (AtRuntime ()) {\r
+        //\r
+        // NV storage can't reclaim at runtime.\r
+        //\r
+        return 0;\r
+      }\r
+      \r
+      Status = Reclaim (\r
+                 mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase,\r
+                 &mVariableModuleGlobal->NonVolatileLastVariableOffset,\r
+                 FALSE,\r
+                 NULL,\r
+                 TRUE,\r
+                 TRUE\r
+                 );\r
+      if (EFI_ERROR (Status)) {\r
+        return 0;\r
+      }\r
+\r
+      Status = FindVariable (\r
+                 AUTHVAR_KEYDB_NAME,\r
+                 &gEfiAuthenticatedVariableGuid,\r
+                 &Variable,\r
+                 &mVariableModuleGlobal->VariableGlobal,\r
+                 FALSE\r
+                 );\r
+      ASSERT_EFI_ERROR (Status);\r
+\r
+      DataSize  = DataSizeOfVariable (Variable.CurrPtr);\r
+      Data      = GetVariableDataPtr (Variable.CurrPtr);\r
+      ASSERT ((DataSize != 0) && (Data != NULL));\r
+      CopyMem (mPubKeyStore, (UINT8 *) Data, DataSize);\r
+      mPubKeyNumber = (UINT32) (DataSize / EFI_CERT_TYPE_RSA2048_SIZE);\r
+\r
+      if (mPubKeyNumber == MAX_KEY_NUM) {\r
+        return 0;\r
+      }     \r
     }\r
 \r
     CopyMem (mPubKeyStore + mPubKeyNumber * EFI_CERT_TYPE_RSA2048_SIZE, PubKey, EFI_CERT_TYPE_RSA2048_SIZE);\r
index 5f023dfdeef6ab2f28eb2d59db5a585b922c71b7..b192731ef44e4f2c3294b9acd90f5321ab349f9b 100644 (file)
@@ -16,7 +16,7 @@
   VariableServiceSetVariable() should also check authenticate data to avoid buffer overflow,\r
   integer overflow. It should also check attribute to avoid authentication bypass.\r
 \r
-Copyright (c) 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
@@ -511,21 +511,157 @@ GetEndPointer (
   return (VARIABLE_HEADER *) HEADER_ALIGN ((UINTN) VarStoreHeader + VarStoreHeader->Size);\r
 }\r
 \r
+/**\r
+\r
+  Check the PubKeyIndex is a valid key or not.\r
+\r
+  This function will iterate the NV storage to see if this PubKeyIndex is still referenced \r
+  by any valid count-based auth variabe.\r
+  \r
+  @param[in]  PubKeyIndex     Index of the public key in public key store.\r
+\r
+  @retval     TRUE            The PubKeyIndex is still in use.\r
+  @retval     FALSE           The PubKeyIndex is not referenced by any count-based auth variabe.\r
+  \r
+**/\r
+BOOLEAN\r
+IsValidPubKeyIndex (\r
+  IN   UINT32      PubKeyIndex\r
+  )\r
+{\r
+  VARIABLE_HEADER          *Variable;\r
+\r
+  if (PubKeyIndex > mPubKeyNumber) {\r
+    return FALSE;\r
+  }\r
+  \r
+  Variable = GetStartPointer (mNvVariableCache);\r
+  \r
+  while (IsValidVariableHeader (Variable)) {\r
+    if ((Variable->State == VAR_ADDED || Variable->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) && \r
+        Variable->PubKeyIndex == PubKeyIndex) {\r
+      return TRUE;\r
+    }\r
+    Variable = GetNextVariablePtr (Variable);\r
+  }\r
+  \r
+  return FALSE;\r
+}\r
 \r
 /**\r
 \r
-  Variable store garbage collection and reclaim operation.\r
+  Get the number of valid public key in PubKeyStore.\r
+  \r
+  @param[in]  PubKeyNumber     Number of the public key in public key store.\r
+\r
+  @return     Number of valid public key in PubKeyStore.\r
+\r
+**/\r
+UINT32\r
+GetValidPubKeyNumber (\r
+  IN   UINT32       PubKeyNumber\r
+  )\r
+{\r
+  UINT32       PubKeyIndex;\r
+  UINT32       Counter;\r
+\r
+  Counter = 0;\r
+  \r
+  for (PubKeyIndex = 1; PubKeyIndex <= PubKeyNumber; PubKeyIndex++) {\r
+    if (IsValidPubKeyIndex (PubKeyIndex)) {\r
+      Counter++;\r
+    }\r
+  }\r
+  \r
+  return Counter;\r
+}\r
+\r
+/**\r
+\r
+  Filter the useless key in public key store.\r
+\r
+  This function will find out all valid public keys in public key database, save them in new allocated \r
+  buffer NewPubKeyStore, and give the new PubKeyIndex. The caller is responsible for freeing buffer\r
+  NewPubKeyIndex and NewPubKeyStore with FreePool().\r
+\r
+  @param[in]   PubKeyStore          Point to the public key database.\r
+  @param[in]   PubKeyNumber         Number of the public key in PubKeyStore.\r
+  @param[out]  NewPubKeyIndex       Point to an array of new PubKeyIndex corresponds to NewPubKeyStore.\r
+  @param[out]  NewPubKeyStore       Saved all valid public keys in PubKeyStore.\r
+  @param[out]  NewPubKeySize        Buffer size of the NewPubKeyStore.\r
+  \r
+  @retval  EFI_SUCCESS              Trim operation is complete successfully.\r
+  @retval  EFI_OUT_OF_RESOURCES     No enough memory resources, or no useless key in PubKeyStore.\r
+  \r
+**/\r
+EFI_STATUS\r
+PubKeyStoreFilter (\r
+  IN   UINT8         *PubKeyStore,\r
+  IN   UINT32        PubKeyNumber,\r
+  OUT  UINT32        **NewPubKeyIndex,\r
+  OUT  UINT8         **NewPubKeyStore,\r
+  OUT  UINT32        *NewPubKeySize\r
+  )\r
+{\r
+  UINT32        PubKeyIndex;\r
+  UINT32        CopiedKey;\r
+  UINT32        NewPubKeyNumber;\r
+  \r
+  NewPubKeyNumber = GetValidPubKeyNumber (PubKeyNumber);\r
+  if (NewPubKeyNumber == PubKeyNumber) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  if (NewPubKeyNumber != 0) {\r
+    *NewPubKeySize = NewPubKeyNumber * EFI_CERT_TYPE_RSA2048_SIZE;\r
+  } else {\r
+    *NewPubKeySize = sizeof (UINT8);\r
+  }\r
+\r
+  *NewPubKeyStore = AllocatePool (*NewPubKeySize);\r
+  if (*NewPubKeyStore == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
 \r
-  @param VariableBase            Base address of variable store.\r
-  @param LastVariableOffset      Offset of last variable.\r
-  @param IsVolatile              The variable store is volatile or not;\r
-                                 if it is non-volatile, need FTW.\r
-  @param UpdatingVariable        Pointer to updating variable.\r
-  @param ReclaimAnyway           If TRUE, do reclaim anyway.\r
+  *NewPubKeyIndex = AllocateZeroPool ((PubKeyNumber + 1) * sizeof (UINT32));\r
+  if (*NewPubKeyIndex == NULL) {\r
+    FreePool (*NewPubKeyStore);\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
 \r
-  @return EFI_OUT_OF_RESOURCES\r
-  @return EFI_SUCCESS\r
-  @return Others\r
+  CopiedKey = 0;\r
+  for (PubKeyIndex = 1; PubKeyIndex <= PubKeyNumber; PubKeyIndex++) {\r
+    if (IsValidPubKeyIndex (PubKeyIndex)) {\r
+      CopyMem (\r
+        *NewPubKeyStore + CopiedKey * EFI_CERT_TYPE_RSA2048_SIZE,\r
+        PubKeyStore + (PubKeyIndex - 1) * EFI_CERT_TYPE_RSA2048_SIZE,\r
+        EFI_CERT_TYPE_RSA2048_SIZE\r
+        );\r
+      (*NewPubKeyIndex)[PubKeyIndex] = ++CopiedKey;\r
+    }\r
+  }\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+\r
+  Variable store garbage collection and reclaim operation.\r
+\r
+  If ReclaimPubKeyStore is FALSE, reclaim variable space by deleting the obsoleted varaibles.\r
+  If ReclaimPubKeyStore is TRUE, reclaim invalid key in public key database and update the PubKeyIndex\r
+  for all the count-based authenticate variable in NV storage.\r
+\r
+  @param[in]   VariableBase            Base address of variable store.\r
+  @param[out]  LastVariableOffset      Offset of last variable.\r
+  @param[in]   IsVolatile              The variable store is volatile or not;\r
+                                       if it is non-volatile, need FTW.\r
+  @param[in]   UpdatingVariable        Pointer to updating variable.\r
+  @param[in]   ReclaimPubKeyStore      Reclaim for public key database or not.\r
+  @param[in]   ReclaimAnyway           If TRUE, do reclaim anyway.\r
+  \r
+  @return EFI_OUT_OF_RESOURCES         No enough memory resources.\r
+  @return EFI_SUCCESS                  Reclaim operation has finished successfully.\r
+  @return Others                       Unexpect error happened during reclaim operation.\r
 \r
 **/\r
 EFI_STATUS\r
@@ -534,6 +670,7 @@ Reclaim (
   OUT UINTN                 *LastVariableOffset,\r
   IN  BOOLEAN               IsVolatile,\r
   IN  VARIABLE_HEADER       *UpdatingVariable,\r
+  IN  BOOLEAN               ReclaimPubKeyStore,\r
   IN  BOOLEAN               ReclaimAnyway\r
   )\r
 {\r
@@ -557,6 +694,10 @@ Reclaim (
   CHAR16                *UpdatingVariableNamePtr;\r
   UINTN                 CommonVariableTotalSize;\r
   UINTN                 HwErrVariableTotalSize;\r
+  UINT32                *NewPubKeyIndex;\r
+  UINT8                 *NewPubKeyStore;\r
+  UINT32                NewPubKeySize;\r
+  VARIABLE_HEADER       *PubKeyHeader;\r
   BOOLEAN               NeedDoReclaim;\r
 \r
   NeedDoReclaim = FALSE;\r
@@ -564,7 +705,11 @@ Reclaim (
 \r
   CommonVariableTotalSize = 0;\r
   HwErrVariableTotalSize  = 0;\r
-\r
+  NewPubKeyIndex = NULL;\r
+  NewPubKeyStore = NULL;\r
+  NewPubKeySize  = 0;\r
+  PubKeyHeader   = NULL;\r
+  \r
   //\r
   // Start Pointers for the variable.\r
   //\r
@@ -608,95 +753,90 @@ Reclaim (
   CopyMem (ValidBuffer, VariableStoreHeader, sizeof (VARIABLE_STORE_HEADER));\r
   CurrPtr = (UINT8 *) GetStartPointer ((VARIABLE_STORE_HEADER *) ValidBuffer);\r
 \r
-  //\r
-  // Reinstall all ADDED variables as long as they are not identical to Updating Variable.\r
-  //\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
+  if (ReclaimPubKeyStore) {\r
+    //\r
+    // Trim the PubKeyStore and get new PubKeyIndex.\r
+    //\r
+    Status = PubKeyStoreFilter (\r
+               mPubKeyStore,\r
+               mPubKeyNumber,\r
+               &NewPubKeyIndex,\r
+               &NewPubKeyStore,\r
+               &NewPubKeySize\r
+               );\r
+    if (EFI_ERROR (Status)) {\r
+      FreePool (ValidBuffer);\r
+      return Status;\r
+    }\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
+    //\r
+    // Refresh the PubKeyIndex for all valid variables (ADDED and IN_DELETED_TRANSITION).\r
+    //\r
+    Variable = GetStartPointer (mNvVariableCache);\r
+    while (IsValidVariableHeader (Variable)) {\r
+      NextVariable = GetNextVariablePtr (Variable);\r
+      if (Variable->State == VAR_ADDED || Variable->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {\r
+        if ((StrCmp (GetVariableNamePtr (Variable), AUTHVAR_KEYDB_NAME) == 0) && \r
+            (CompareGuid (&Variable->VendorGuid, &gEfiAuthenticatedVariableGuid))) {\r
+          //\r
+          // Skip the public key database, it will be reinstalled later.\r
+          //\r
+          PubKeyHeader = Variable;\r
           Variable = NextVariable;\r
           continue;\r
         }\r
+        \r
+        VariableSize = (UINTN) NextVariable - (UINTN) Variable;\r
+        CopyMem (CurrPtr, (UINT8 *) Variable, VariableSize);\r
+        ((VARIABLE_HEADER*) CurrPtr)->PubKeyIndex = NewPubKeyIndex[Variable->PubKeyIndex];\r
+        CurrPtr += VariableSize;\r
+        if ((!IsVolatile) && ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {\r
+          HwErrVariableTotalSize += VariableSize;\r
+        } else if ((!IsVolatile) && ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {\r
+          CommonVariableTotalSize += VariableSize;\r
+        }\r
       }\r
-      VariableSize = (UINTN) NextVariable - (UINTN) Variable;\r
-      CopyMem (CurrPtr, (UINT8 *) Variable, VariableSize);\r
-      CurrPtr += VariableSize;\r
-      if ((!IsVolatile) && ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {\r
-        HwErrVariableTotalSize += VariableSize;\r
-      } else if ((!IsVolatile) && ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {\r
-        CommonVariableTotalSize += VariableSize;\r
-      }\r
+      Variable = NextVariable;\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
-    if ((!IsVolatile) && ((UpdatingVariable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {\r
-        HwErrVariableTotalSize += VariableSize;\r
-    } else if ((!IsVolatile) && ((UpdatingVariable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {\r
-        CommonVariableTotalSize += VariableSize;\r
-    }\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
+    // Reinstall the new public key database.\r
+    //\r
+    CopyMem (CurrPtr, (UINT8*) PubKeyHeader, sizeof (VARIABLE_HEADER));\r
+    Variable = (VARIABLE_HEADER*) CurrPtr;\r
+    Variable->DataSize = NewPubKeySize;\r
+    StrCpy (GetVariableNamePtr (Variable), GetVariableNamePtr (PubKeyHeader));\r
+    CopyMem (GetVariableDataPtr (Variable), NewPubKeyStore, NewPubKeySize);\r
+    CurrPtr = (UINT8*) GetNextVariablePtr (Variable); \r
+    CommonVariableTotalSize += (UINTN) CurrPtr - (UINTN) Variable;\r
+  } else {\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
-      //\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
+          VariableNameSize         = NameSizeOfVariable(Variable);\r
+          UpdatingVariableNameSize = NameSizeOfVariable(UpdatingVariable);\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
+          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
-        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
         if ((!IsVolatile) && ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {\r
           HwErrVariableTotalSize += VariableSize;\r
@@ -704,9 +844,72 @@ Reclaim (
           CommonVariableTotalSize += VariableSize;\r
         }\r
       }\r
+      Variable = NextVariable;\r
     }\r
 \r
-    Variable = NextVariable;\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
+      if ((!IsVolatile) && ((UpdatingVariable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {\r
+          HwErrVariableTotalSize += VariableSize;\r
+      } else if ((!IsVolatile) && ((UpdatingVariable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {\r
+          CommonVariableTotalSize += VariableSize;\r
+      }\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
+          if ((!IsVolatile) && ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {\r
+            HwErrVariableTotalSize += VariableSize;\r
+          } else if ((!IsVolatile) && ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {\r
+            CommonVariableTotalSize += VariableSize;\r
+          }\r
+        }\r
+      }\r
+\r
+      Variable = NextVariable;\r
+    }\r
   }\r
 \r
   if (IsVolatile) {\r
@@ -748,6 +951,14 @@ Reclaim (
     *LastVariableOffset = (UINTN) NextVariable - (UINTN) VariableBase;\r
   }\r
 \r
+  if (NewPubKeyStore != NULL) {\r
+    FreePool (NewPubKeyStore);\r
+  }\r
+\r
+  if (NewPubKeyIndex != NULL) {\r
+    FreePool (NewPubKeyIndex);\r
+  }\r
+  \r
   FreePool (ValidBuffer);\r
 \r
   return Status;\r
@@ -1744,8 +1955,14 @@ UpdateVariable (
       //\r
       // Perform garbage collection & reclaim operation.\r
       //\r
-      Status = Reclaim (mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase,\r
-                        &mVariableModuleGlobal->NonVolatileLastVariableOffset, FALSE, Variable->CurrPtr, FALSE);\r
+      Status = Reclaim (\r
+                 mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase,\r
+                 &mVariableModuleGlobal->NonVolatileLastVariableOffset,\r
+                 FALSE,\r
+                 Variable->CurrPtr,\r
+                 FALSE,\r
+                 FALSE\r
+                 );\r
       if (EFI_ERROR (Status)) {\r
         goto Done;\r
       }\r
@@ -1859,8 +2076,14 @@ UpdateVariable (
       //\r
       // Perform garbage collection & reclaim operation.\r
       //\r
-      Status = Reclaim (mVariableModuleGlobal->VariableGlobal.VolatileVariableBase,\r
-                          &mVariableModuleGlobal->VolatileLastVariableOffset, TRUE, Variable->CurrPtr, FALSE);\r
+      Status = Reclaim (\r
+                 mVariableModuleGlobal->VariableGlobal.VolatileVariableBase,\r
+                 &mVariableModuleGlobal->VolatileLastVariableOffset,\r
+                 TRUE,\r
+                 Variable->CurrPtr,\r
+                 FALSE,\r
+                 FALSE\r
+                 );\r
       if (EFI_ERROR (Status)) {\r
         goto Done;\r
       }\r
@@ -2629,6 +2852,7 @@ ReclaimForOS(
             &mVariableModuleGlobal->NonVolatileLastVariableOffset,\r
             FALSE,\r
             NULL,\r
+            FALSE,\r
             FALSE\r
             );\r
     ASSERT_EFI_ERROR (Status);\r
@@ -2760,6 +2984,7 @@ VariableWriteServiceInitialize (
                  &mVariableModuleGlobal->NonVolatileLastVariableOffset,\r
                  FALSE,\r
                  NULL,\r
+                 FALSE,\r
                  TRUE\r
                  );\r
       if (EFI_ERROR (Status)) {\r
index 6a51bcce2a3dff8ae9495455a5165f300300619e..427245abcecfdb291cfd8ecc9574c04eebef7266 100644 (file)
@@ -2,7 +2,7 @@
   The internal header file includes the common header files, defines\r
   internal structure and functions used by Variable modules.\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
@@ -366,6 +366,37 @@ VariableCommonInitialize (
   VOID\r
   );\r
 \r
+/**\r
+\r
+  Variable store garbage collection and reclaim operation.\r
+\r
+  If ReclaimPubKeyStore is FALSE, reclaim variable space by deleting the obsoleted varaibles.\r
+  If ReclaimPubKeyStore is TRUE, reclaim invalid key in public key database and update the PubKeyIndex\r
+  for all the count-based authenticate variable in NV storage.\r
+\r
+  @param[in]   VariableBase            Base address of variable store.\r
+  @param[out]  LastVariableOffset      Offset of last variable.\r
+  @param[in]   IsVolatile              The variable store is volatile or not;\r
+                                       if it is non-volatile, need FTW.\r
+  @param[in]   UpdatingVariable        Pointer to updating variable.\r
+  @param[in]   ReclaimPubKeyStore      Reclaim for public key database or not.\r
+  @param[in]   ReclaimAnyway           If TRUE, do reclaim anyway.\r
+  \r
+  @return EFI_OUT_OF_RESOURCES         No enough memory resources.\r
+  @return EFI_SUCCESS                  Reclaim operation has finished successfully.\r
+  @return Others                       Unexpect error happened during reclaim operation.\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
+  IN  BOOLEAN               ReclaimPubKeyStore,\r
+  IN  BOOLEAN               ReclaimAnyway\r
+  );\r
+\r
 /**\r
   This function reclaims variable storage if free size is below the threshold.\r
   \r