@param[in] IsVolatile The variable store is volatile or not;\r
if it is non-volatile, need FTW.\r
@param[in, out] UpdatingPtrTrack Pointer to updating variable pointer track structure.\r
+ @param[in] NewVariable Pointer to new variable.\r
+ @param[in] NewVariableSize New variable size.\r
@param[in] ReclaimPubKeyStore Reclaim for public key database or not.\r
- @param[in] ReclaimAnyway If TRUE, do reclaim anyway.\r
\r
@return EFI_SUCCESS Reclaim operation has finished successfully.\r
- @return EFI_OUT_OF_RESOURCES No enough memory resources.\r
+ @return EFI_OUT_OF_RESOURCES No enough memory resources or variable space.\r
@return EFI_DEVICE_ERROR The public key database doesn't exist.\r
@return Others Unexpect error happened during reclaim operation.\r
\r
OUT UINTN *LastVariableOffset,\r
IN BOOLEAN IsVolatile,\r
IN OUT VARIABLE_POINTER_TRACK *UpdatingPtrTrack,\r
- IN BOOLEAN ReclaimPubKeyStore,\r
- IN BOOLEAN ReclaimAnyway\r
+ IN VARIABLE_HEADER *NewVariable,\r
+ IN UINTN NewVariableSize,\r
+ IN BOOLEAN ReclaimPubKeyStore\r
)\r
{\r
VARIABLE_HEADER *Variable;\r
UINT8 *ValidBuffer;\r
UINTN MaximumBufferSize;\r
UINTN VariableSize;\r
- UINTN VariableNameSize;\r
- UINTN UpdatingVariableNameSize;\r
UINTN NameSize;\r
UINT8 *CurrPtr;\r
VOID *Point0;\r
VOID *Point1;\r
BOOLEAN FoundAdded;\r
EFI_STATUS Status;\r
- CHAR16 *VariableNamePtr;\r
- CHAR16 *UpdatingVariableNamePtr;\r
UINTN CommonVariableTotalSize;\r
UINTN HwErrVariableTotalSize;\r
UINT32 *NewPubKeyIndex;\r
UINT8 *NewPubKeyStore;\r
UINT32 NewPubKeySize;\r
VARIABLE_HEADER *PubKeyHeader;\r
- BOOLEAN NeedDoReclaim;\r
VARIABLE_HEADER *UpdatingVariable;\r
+ VARIABLE_HEADER *UpdatingInDeletedTransition;\r
\r
UpdatingVariable = NULL;\r
+ UpdatingInDeletedTransition = NULL;\r
if (UpdatingPtrTrack != NULL) {\r
UpdatingVariable = UpdatingPtrTrack->CurrPtr;\r
+ UpdatingInDeletedTransition = UpdatingPtrTrack->InDeletedTransitionPtr;\r
}\r
\r
- NeedDoReclaim = FALSE;\r
VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINTN) VariableBase);\r
\r
CommonVariableTotalSize = 0;\r
\r
while (IsValidVariableHeader (Variable)) {\r
NextVariable = GetNextVariablePtr (Variable);\r
- if (Variable->State == VAR_ADDED ||\r
- Variable->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)\r
+ if ((Variable->State == VAR_ADDED || Variable->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) &&\r
+ Variable != UpdatingVariable &&\r
+ Variable != UpdatingInDeletedTransition\r
) {\r
VariableSize = (UINTN) NextVariable - (UINTN) Variable;\r
MaximumBufferSize += VariableSize;\r
- } else {\r
- NeedDoReclaim = TRUE;\r
}\r
\r
Variable = NextVariable;\r
}\r
\r
- if (!ReclaimAnyway && !NeedDoReclaim) {\r
- DEBUG ((EFI_D_INFO, "Variable driver: no DELETED variable found, so no variable space could be reclaimed.\n"));\r
- return EFI_SUCCESS;\r
+ if (NewVariable != NULL) {\r
+ //\r
+ // Add the new variable size.\r
+ //\r
+ MaximumBufferSize += NewVariableSize;\r
}\r
\r
//\r
CurrPtr = (UINT8 *) GetStartPointer ((VARIABLE_STORE_HEADER *) ValidBuffer);\r
\r
if (ReclaimPubKeyStore) {\r
+ ASSERT (IsVolatile == FALSE);\r
//\r
// Trim the PubKeyStore and get new PubKeyIndex.\r
//\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
+ if ((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
+ } else if ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != EFI_VARIABLE_HARDWARE_ERROR_RECORD) {\r
CommonVariableTotalSize += VariableSize;\r
}\r
}\r
Variable = GetStartPointer (VariableStoreHeader);\r
while (IsValidVariableHeader (Variable)) {\r
NextVariable = GetNextVariablePtr (Variable);\r
- if (Variable->State == VAR_ADDED) {\r
- if (UpdatingVariable != NULL) {\r
- if (UpdatingVariable == Variable) {\r
- Variable = NextVariable;\r
- continue;\r
- }\r
-\r
- VariableNameSize = NameSizeOfVariable(Variable);\r
- UpdatingVariableNameSize = NameSizeOfVariable(UpdatingVariable);\r
-\r
- VariableNamePtr = GetVariableNamePtr (Variable);\r
- UpdatingVariableNamePtr = GetVariableNamePtr (UpdatingVariable);\r
- if (CompareGuid (&Variable->VendorGuid, &UpdatingVariable->VendorGuid) &&\r
- VariableNameSize == UpdatingVariableNameSize &&\r
- CompareMem (VariableNamePtr, UpdatingVariableNamePtr, VariableNameSize) == 0 ) {\r
- Variable = NextVariable;\r
- continue;\r
- }\r
- }\r
+ if (Variable != UpdatingVariable && Variable->State == VAR_ADDED) {\r
VariableSize = (UINTN) NextVariable - (UINTN) Variable;\r
CopyMem (CurrPtr, (UINT8 *) Variable, VariableSize);\r
CurrPtr += VariableSize;\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
- UpdatingPtrTrack->CurrPtr = (VARIABLE_HEADER *)((UINTN)UpdatingPtrTrack->StartPtr + ((UINTN)CurrPtr - (UINTN)GetStartPointer ((VARIABLE_STORE_HEADER *) ValidBuffer)));\r
- UpdatingPtrTrack->InDeletedTransitionPtr = NULL;\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
+ Variable = GetStartPointer (VariableStoreHeader);\r
while (IsValidVariableHeader (Variable)) {\r
NextVariable = GetNextVariablePtr (Variable);\r
- if (Variable != UpdatingVariable && Variable->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {\r
+ if (Variable != UpdatingVariable && Variable != UpdatingInDeletedTransition && Variable->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {\r
\r
//\r
// Buffer has cached all ADDED variable.\r
\r
Variable = NextVariable;\r
}\r
+\r
+ //\r
+ // Install the new variable if it is not NULL.\r
+ //\r
+ if (NewVariable != NULL) {\r
+ if ((UINTN) (CurrPtr - ValidBuffer) + NewVariableSize > VariableStoreHeader->Size) {\r
+ //\r
+ // No enough space to store the new variable.\r
+ //\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
+ }\r
+ if (!IsVolatile) {\r
+ if ((NewVariable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD) {\r
+ HwErrVariableTotalSize += NewVariableSize;\r
+ } else if ((NewVariable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != EFI_VARIABLE_HARDWARE_ERROR_RECORD) {\r
+ CommonVariableTotalSize += NewVariableSize;\r
+ }\r
+ if ((HwErrVariableTotalSize > PcdGet32 (PcdHwErrStorageSize)) ||\r
+ (CommonVariableTotalSize > VariableStoreHeader->Size - sizeof (VARIABLE_STORE_HEADER) - PcdGet32 (PcdHwErrStorageSize))) {\r
+ //\r
+ // No enough space to store the new variable by NV or NV+HR attribute.\r
+ //\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
+ }\r
+ }\r
+\r
+ CopyMem (CurrPtr, (UINT8 *) NewVariable, NewVariableSize);\r
+ ((VARIABLE_HEADER *) CurrPtr)->State = VAR_ADDED;\r
+ if (UpdatingVariable != NULL) {\r
+ UpdatingPtrTrack->CurrPtr = (VARIABLE_HEADER *)((UINTN)UpdatingPtrTrack->StartPtr + ((UINTN)CurrPtr - (UINTN)GetStartPointer ((VARIABLE_STORE_HEADER *) ValidBuffer)));\r
+ UpdatingPtrTrack->InDeletedTransitionPtr = NULL;\r
+ }\r
+ CurrPtr += NewVariableSize;\r
+ }\r
}\r
\r
if (IsVolatile) {\r
// If volatile variable store, just copy valid buffer.\r
//\r
SetMem ((UINT8 *) (UINTN) VariableBase, VariableStoreHeader->Size, 0xff);\r
- CopyMem ((UINT8 *) (UINTN) VariableBase, ValidBuffer, (UINTN) (CurrPtr - (UINT8 *) ValidBuffer));\r
+ CopyMem ((UINT8 *) (UINTN) VariableBase, ValidBuffer, (UINTN) (CurrPtr - ValidBuffer));\r
Status = EFI_SUCCESS;\r
} else {\r
//\r
Status = FtwVariableSpace (\r
VariableBase,\r
ValidBuffer,\r
- (UINTN) (CurrPtr - (UINT8 *) ValidBuffer)\r
+ (UINTN) (CurrPtr - ValidBuffer)\r
);\r
CopyMem (mNvVariableCache, (CHAR8 *)(UINTN)VariableBase, VariableStoreHeader->Size);\r
}\r
if (!EFI_ERROR (Status)) {\r
- *LastVariableOffset = (UINTN) (CurrPtr - (UINT8 *) ValidBuffer);\r
+ *LastVariableOffset = (UINTN) (CurrPtr - ValidBuffer);\r
if (!IsVolatile) {\r
mVariableModuleGlobal->HwErrVariableTotalSize = HwErrVariableTotalSize;\r
mVariableModuleGlobal->CommonVariableTotalSize = CommonVariableTotalSize;\r
if (NewPubKeyIndex != NULL) {\r
FreePool (NewPubKeyIndex);\r
}\r
- \r
+\r
+Done:\r
FreePool (ValidBuffer);\r
\r
return Status;\r
goto Done;\r
}\r
//\r
- // Perform garbage collection & reclaim operation.\r
+ // Perform garbage collection & reclaim operation, and integrate the new variable at the same time.\r
//\r
Status = Reclaim (\r
mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase,\r
&mVariableModuleGlobal->NonVolatileLastVariableOffset,\r
FALSE,\r
Variable,\r
- FALSE,\r
+ NextVariable,\r
+ HEADER_ALIGN (VarSize),\r
FALSE\r
);\r
- if (EFI_ERROR (Status)) {\r
- goto Done;\r
- }\r
- //\r
- // If still no enough space, return out of resources.\r
- //\r
- if ((((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != 0)\r
- && ((VarSize + mVariableModuleGlobal->HwErrVariableTotalSize) > PcdGet32 (PcdHwErrStorageSize)))\r
- || (((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == 0)\r
- && ((VarSize + mVariableModuleGlobal->CommonVariableTotalSize) > NonVolatileVarableStoreSize - sizeof (VARIABLE_STORE_HEADER) - PcdGet32 (PcdHwErrStorageSize)))) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto Done;\r
- }\r
- if (Variable->CurrPtr != NULL) {\r
- CacheVariable->CurrPtr = (VARIABLE_HEADER *)((UINTN) CacheVariable->StartPtr + ((UINTN) Variable->CurrPtr - (UINTN) Variable->StartPtr));\r
- CacheVariable->InDeletedTransitionPtr = NULL;\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // The new variable has been integrated successfully during reclaiming.\r
+ //\r
+ if (Variable->CurrPtr != NULL) {\r
+ CacheVariable->CurrPtr = (VARIABLE_HEADER *)((UINTN) CacheVariable->StartPtr + ((UINTN) Variable->CurrPtr - (UINTN) Variable->StartPtr));\r
+ CacheVariable->InDeletedTransitionPtr = NULL;\r
+ }\r
+ UpdateVariableInfo (VariableName, VendorGuid, FALSE, FALSE, TRUE, FALSE, FALSE);\r
+ FlushHobVariableToFlash (VariableName, VendorGuid);\r
}\r
+ goto Done;\r
}\r
//\r
// Four steps\r
if ((UINT32) (VarSize + mVariableModuleGlobal->VolatileLastVariableOffset) >\r
((VARIABLE_STORE_HEADER *) ((UINTN) (mVariableModuleGlobal->VariableGlobal.VolatileVariableBase)))->Size) {\r
//\r
- // Perform garbage collection & reclaim operation.\r
+ // Perform garbage collection & reclaim operation, and integrate the new variable at the same time.\r
//\r
Status = Reclaim (\r
mVariableModuleGlobal->VariableGlobal.VolatileVariableBase,\r
&mVariableModuleGlobal->VolatileLastVariableOffset,\r
TRUE,\r
Variable,\r
- FALSE,\r
+ NextVariable,\r
+ HEADER_ALIGN (VarSize),\r
FALSE\r
);\r
- if (EFI_ERROR (Status)) {\r
- goto Done;\r
- }\r
- //\r
- // If still no enough space, return out of resources.\r
- //\r
- if ((UINT32) (VarSize + mVariableModuleGlobal->VolatileLastVariableOffset) >\r
- ((VARIABLE_STORE_HEADER *) ((UINTN) (mVariableModuleGlobal->VariableGlobal.VolatileVariableBase)))->Size\r
- ) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto Done;\r
- }\r
- if (Variable->CurrPtr != NULL) {\r
- CacheVariable->CurrPtr = (VARIABLE_HEADER *)((UINTN) CacheVariable->StartPtr + ((UINTN) Variable->CurrPtr - (UINTN) Variable->StartPtr));\r
- CacheVariable->InDeletedTransitionPtr = NULL;\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // The new variable has been integrated successfully during reclaiming.\r
+ //\r
+ if (Variable->CurrPtr != NULL) {\r
+ CacheVariable->CurrPtr = (VARIABLE_HEADER *)((UINTN) CacheVariable->StartPtr + ((UINTN) Variable->CurrPtr - (UINTN) Variable->StartPtr));\r
+ CacheVariable->InDeletedTransitionPtr = NULL;\r
+ }\r
+ UpdateVariableInfo (VariableName, VendorGuid, TRUE, FALSE, TRUE, FALSE, FALSE);\r
}\r
+ goto Done;\r
}\r
\r
NextVariable->State = VAR_ADDED;\r
&mVariableModuleGlobal->NonVolatileLastVariableOffset,\r
FALSE,\r
NULL,\r
- FALSE,\r
+ NULL,\r
+ 0,\r
FALSE\r
);\r
ASSERT_EFI_ERROR (Status);\r
&mVariableModuleGlobal->NonVolatileLastVariableOffset,\r
FALSE,\r
NULL,\r
- FALSE,\r
- TRUE\r
+ NULL,\r
+ 0,\r
+ FALSE\r
);\r
if (EFI_ERROR (Status)) {\r
return Status;\r