*NewPubKeyIndex = AllocateZeroPool ((PubKeyNumber + 1) * sizeof (UINT32));\r
if (*NewPubKeyIndex == NULL) {\r
FreePool (*NewPubKeyStore);\r
+ *NewPubKeyStore = NULL;\r
return EFI_OUT_OF_RESOURCES;\r
}\r
\r
NewPubKeyStore = NULL;\r
NewPubKeySize = 0;\r
PubKeyHeader = NULL;\r
- \r
- //\r
- // Start Pointers for the variable.\r
- //\r
- Variable = GetStartPointer (VariableStoreHeader);\r
- MaximumBufferSize = sizeof (VARIABLE_STORE_HEADER);\r
\r
- while (IsValidVariableHeader (Variable)) {\r
- NextVariable = GetNextVariablePtr (Variable);\r
- if ((Variable->State == VAR_ADDED || 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
+ if (IsVolatile) {\r
+ //\r
+ // Start Pointers for the variable.\r
+ //\r
+ Variable = GetStartPointer (VariableStoreHeader);\r
+ MaximumBufferSize = sizeof (VARIABLE_STORE_HEADER);\r
+\r
+ while (IsValidVariableHeader (Variable)) {\r
+ NextVariable = GetNextVariablePtr (Variable);\r
+ if ((Variable->State == VAR_ADDED || 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
+ }\r
+\r
+ Variable = NextVariable;\r
}\r
\r
- Variable = NextVariable;\r
- }\r
+ if (NewVariable != NULL) {\r
+ //\r
+ // Add the new variable size.\r
+ //\r
+ MaximumBufferSize += NewVariableSize;\r
+ }\r
\r
- if (NewVariable != NULL) {\r
//\r
- // Add the new variable size.\r
+ // Reserve the 1 Bytes with Oxff to identify the\r
+ // end of the variable buffer.\r
//\r
- MaximumBufferSize += NewVariableSize;\r
- }\r
-\r
- //\r
- // Reserve the 1 Bytes with Oxff to identify the\r
- // end of the variable buffer.\r
- //\r
- MaximumBufferSize += 1;\r
- ValidBuffer = AllocatePool (MaximumBufferSize);\r
- if (ValidBuffer == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
+ MaximumBufferSize += 1;\r
+ ValidBuffer = AllocatePool (MaximumBufferSize);\r
+ if (ValidBuffer == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ } else {\r
+ //\r
+ // For NV variable reclaim, don't allocate pool here and just use mNvVariableCache\r
+ // as the buffer to reduce SMRAM consumption for SMM variable driver.\r
+ //\r
+ MaximumBufferSize = mNvVariableCache->Size;\r
+ ValidBuffer = (UINT8 *) mNvVariableCache;\r
}\r
\r
SetMem (ValidBuffer, MaximumBufferSize, 0xff);\r
&NewPubKeySize\r
);\r
if (EFI_ERROR (Status)) {\r
- FreePool (ValidBuffer);\r
- return Status;\r
+ goto Done;\r
}\r
\r
//\r
// Refresh the PubKeyIndex for all valid variables (ADDED and IN_DELETED_TRANSITION).\r
//\r
- Variable = GetStartPointer (mNvVariableCache);\r
+ Variable = GetStartPointer (VariableStoreHeader);\r
while (IsValidVariableHeader (Variable)) {\r
NextVariable = GetNextVariablePtr (Variable);\r
if (Variable->State == VAR_ADDED || Variable->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {\r
//\r
ASSERT (PubKeyHeader != NULL);\r
if (PubKeyHeader == NULL) {\r
- FreePool (ValidBuffer);\r
- FreePool (NewPubKeyIndex);\r
- FreePool (NewPubKeyStore);\r
- return EFI_DEVICE_ERROR;\r
+ Status = EFI_DEVICE_ERROR;\r
+ goto Done;\r
}\r
CopyMem (CurrPtr, (UINT8*) PubKeyHeader, sizeof (VARIABLE_HEADER));\r
Variable = (VARIABLE_HEADER*) CurrPtr;\r
//\r
SetMem ((UINT8 *) (UINTN) VariableBase, VariableStoreHeader->Size, 0xff);\r
CopyMem ((UINT8 *) (UINTN) VariableBase, ValidBuffer, (UINTN) (CurrPtr - ValidBuffer));\r
+ *LastVariableOffset = (UINTN) (CurrPtr - ValidBuffer);\r
Status = EFI_SUCCESS;\r
} else {\r
//\r
//\r
Status = FtwVariableSpace (\r
VariableBase,\r
- ValidBuffer,\r
- (UINTN) (CurrPtr - ValidBuffer)\r
+ (VARIABLE_STORE_HEADER *) ValidBuffer\r
);\r
- CopyMem (mNvVariableCache, (CHAR8 *)(UINTN)VariableBase, VariableStoreHeader->Size);\r
- }\r
- if (!EFI_ERROR (Status)) {\r
- *LastVariableOffset = (UINTN) (CurrPtr - ValidBuffer);\r
- if (!IsVolatile) {\r
+ if (!EFI_ERROR (Status)) {\r
+ *LastVariableOffset = (UINTN) (CurrPtr - ValidBuffer);\r
mVariableModuleGlobal->HwErrVariableTotalSize = HwErrVariableTotalSize;\r
mVariableModuleGlobal->CommonVariableTotalSize = CommonVariableTotalSize;\r
- }\r
- } else {\r
- NextVariable = GetStartPointer ((VARIABLE_STORE_HEADER *)(UINTN)VariableBase);\r
- while (IsValidVariableHeader (NextVariable)) {\r
- VariableSize = NextVariable->NameSize + NextVariable->DataSize + sizeof (VARIABLE_HEADER);\r
- if ((!IsVolatile) && ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {\r
- mVariableModuleGlobal->HwErrVariableTotalSize += HEADER_ALIGN (VariableSize);\r
- } else if ((!IsVolatile) && ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {\r
- mVariableModuleGlobal->CommonVariableTotalSize += HEADER_ALIGN (VariableSize);\r
- }\r
+ } else {\r
+ NextVariable = GetStartPointer ((VARIABLE_STORE_HEADER *)(UINTN)VariableBase);\r
+ while (IsValidVariableHeader (NextVariable)) {\r
+ VariableSize = NextVariable->NameSize + NextVariable->DataSize + sizeof (VARIABLE_HEADER);\r
+ if ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD) {\r
+ mVariableModuleGlobal->HwErrVariableTotalSize += HEADER_ALIGN (VariableSize);\r
+ } else if ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != EFI_VARIABLE_HARDWARE_ERROR_RECORD) {\r
+ mVariableModuleGlobal->CommonVariableTotalSize += HEADER_ALIGN (VariableSize);\r
+ }\r
\r
- NextVariable = GetNextVariablePtr (NextVariable);\r
+ NextVariable = GetNextVariablePtr (NextVariable);\r
+ }\r
+ *LastVariableOffset = (UINTN) NextVariable - (UINTN) VariableBase;\r
}\r
- *LastVariableOffset = (UINTN) NextVariable - (UINTN) VariableBase;\r
}\r
\r
- if (NewPubKeyStore != NULL) {\r
- FreePool (NewPubKeyStore);\r
- }\r
+Done:\r
+ if (IsVolatile) {\r
+ FreePool (ValidBuffer);\r
+ } else {\r
+ //\r
+ // For NV variable reclaim, we use mNvVariableCache as the buffer, so copy the data back.\r
+ //\r
+ CopyMem (mNvVariableCache, (UINT8 *)(UINTN)VariableBase, VariableStoreHeader->Size);\r
\r
- if (NewPubKeyIndex != NULL) {\r
- FreePool (NewPubKeyIndex);\r
- }\r
+ if (NewPubKeyStore != NULL) {\r
+ FreePool (NewPubKeyStore);\r
+ }\r
\r
-Done:\r
- FreePool (ValidBuffer);\r
+ if (NewPubKeyIndex != NULL) {\r
+ FreePool (NewPubKeyIndex);\r
+ }\r
+ }\r
\r
return Status;\r
}\r
VARIABLE_POINTER_TRACK NvVariable;\r
VARIABLE_STORE_HEADER *VariableStoreHeader;\r
UINTN CacheOffset;\r
- UINTN BufSize;\r
+ UINT8 *BufferForMerge;\r
+ UINTN MergedBufSize;\r
+ BOOLEAN DataReady;\r
UINTN DataOffset;\r
\r
if (mVariableModuleGlobal->FvbInstance == NULL) {\r
//\r
NextVariable = GetEndPointer ((VARIABLE_STORE_HEADER *) ((UINTN) mVariableModuleGlobal->VariableGlobal.VolatileVariableBase));\r
ScratchSize = MAX (PcdGet32 (PcdMaxVariableSize), PcdGet32 (PcdMaxHardwareErrorVariableSize));\r
-\r
+ SetMem (NextVariable, ScratchSize, 0xff);\r
+ DataReady = FALSE;\r
\r
if (Variable->CurrPtr != NULL) {\r
//\r
// then return to the caller immediately.\r
//\r
if (DataSizeOfVariable (Variable->CurrPtr) == DataSize &&\r
- (CompareMem (Data, GetVariableDataPtr (Variable->CurrPtr), DataSize) == 0) &&\r
+ (CompareMem (Data, GetVariableDataPtr (Variable->CurrPtr), DataSize) == 0) &&\r
((Attributes & EFI_VARIABLE_APPEND_WRITE) == 0) &&\r
(TimeStamp == NULL)) {\r
//\r
//\r
if ((Attributes & EFI_VARIABLE_APPEND_WRITE) != 0) {\r
//\r
- // Cache the previous variable data into StorageArea.\r
+ // NOTE: From 0 to DataOffset of NextVariable is reserved for Variable Header and Name.\r
+ // From DataOffset of NextVariable is to save the existing variable data.\r
//\r
DataOffset = sizeof (VARIABLE_HEADER) + Variable->CurrPtr->NameSize + GET_PAD_SIZE (Variable->CurrPtr->NameSize);\r
- CopyMem (mStorageArea, (UINT8*)((UINTN) Variable->CurrPtr + DataOffset), Variable->CurrPtr->DataSize);\r
+ BufferForMerge = (UINT8 *) ((UINTN) NextVariable + DataOffset);\r
+ CopyMem (BufferForMerge, (UINT8 *) ((UINTN) Variable->CurrPtr + DataOffset), Variable->CurrPtr->DataSize);\r
\r
//\r
// Set Max Common Variable Data Size as default MaxDataSize \r
//\r
- MaxDataSize = PcdGet32 (PcdMaxVariableSize) - sizeof (VARIABLE_HEADER) - StrSize (VariableName) - GET_PAD_SIZE (StrSize (VariableName));\r
-\r
+ MaxDataSize = PcdGet32 (PcdMaxVariableSize) - DataOffset;\r
\r
if ((CompareGuid (VendorGuid, &gEfiImageSecurityDatabaseGuid) &&\r
((StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE) == 0) || (StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE1) == 0))) ||\r
(CompareGuid (VendorGuid, &gEfiGlobalVariableGuid) && (StrCmp (VariableName, EFI_KEY_EXCHANGE_KEY_NAME) == 0))) {\r
-\r
//\r
// For variables with formatted as EFI_SIGNATURE_LIST, the driver shall not perform an append of\r
// EFI_SIGNATURE_DATA values that are already part of the existing variable value.\r
//\r
Status = AppendSignatureList (\r
- mStorageArea, \r
+ BufferForMerge,\r
Variable->CurrPtr->DataSize, \r
MaxDataSize - Variable->CurrPtr->DataSize,\r
- Data, \r
- DataSize, \r
- &BufSize\r
+ Data,\r
+ DataSize,\r
+ &MergedBufSize\r
);\r
if (Status == EFI_BUFFER_TOO_SMALL) {\r
//\r
- // Signture List is too long, Failed to Append\r
+ // Signature List is too long, Failed to Append.\r
//\r
Status = EFI_INVALID_PARAMETER;\r
goto Done;\r
}\r
\r
- if (BufSize == Variable->CurrPtr->DataSize) {\r
+ if (MergedBufSize == Variable->CurrPtr->DataSize) {\r
if ((TimeStamp == NULL) || CompareTimeStamp (TimeStamp, &Variable->CurrPtr->TimeStamp)) {\r
//\r
// New EFI_SIGNATURE_DATA is not found and timestamp is not later\r
}\r
} else {\r
//\r
- // For other Variables, append the new data to the end of previous data.\r
+ // For other Variables, append the new data to the end of existing data.\r
// Max Harware error record variable data size is different from common variable\r
//\r
if ((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD) {\r
- MaxDataSize = PcdGet32 (PcdMaxHardwareErrorVariableSize) - sizeof (VARIABLE_HEADER) - StrSize (VariableName) - GET_PAD_SIZE (StrSize (VariableName));\r
+ MaxDataSize = PcdGet32 (PcdMaxHardwareErrorVariableSize) - DataOffset;\r
}\r
\r
if (Variable->CurrPtr->DataSize + DataSize > MaxDataSize) {\r
//\r
- // Exsiting data + Appended data exceed maximum variable size limitation \r
+ // Existing data size + new data size exceed maximum variable size limitation.\r
//\r
Status = EFI_INVALID_PARAMETER;\r
goto Done;\r
}\r
- CopyMem ((UINT8*)((UINTN) mStorageArea + Variable->CurrPtr->DataSize), Data, DataSize);\r
- BufSize = Variable->CurrPtr->DataSize + DataSize;\r
+ CopyMem ((UINT8*) ((UINTN) BufferForMerge + Variable->CurrPtr->DataSize), Data, DataSize);\r
+ MergedBufSize = Variable->CurrPtr->DataSize + DataSize;\r
}\r
\r
//\r
- // Override Data and DataSize which are used for combined data area including previous and new data.\r
+ // BufferForMerge(from DataOffset of NextVariable) has included the merged existing and new data.\r
//\r
- Data = mStorageArea;\r
- DataSize = BufSize;\r
+ Data = BufferForMerge;\r
+ DataSize = MergedBufSize;\r
+ DataReady = TRUE;\r
}\r
\r
//\r
//\r
// Function part - create a new variable and copy the data.\r
// Both update a variable and create a variable will come here.\r
-\r
- SetMem (NextVariable, ScratchSize, 0xff);\r
-\r
+ //\r
NextVariable->StartId = VARIABLE_DATA;\r
//\r
// NextVariable->State = VAR_ADDED;\r
VarNameSize\r
);\r
VarDataOffset = VarNameOffset + VarNameSize + GET_PAD_SIZE (VarNameSize);\r
- CopyMem (\r
- (UINT8 *) ((UINTN) NextVariable + VarDataOffset),\r
- Data,\r
- DataSize\r
- );\r
+\r
+ //\r
+ // If DataReady is TRUE, it means the variable data has been saved into\r
+ // NextVariable during EFI_VARIABLE_APPEND_WRITE operation preparation.\r
+ //\r
+ if (!DataReady) {\r
+ CopyMem (\r
+ (UINT8 *) ((UINTN) NextVariable + VarDataOffset),\r
+ Data,\r
+ DataSize\r
+ );\r
+ }\r
+\r
CopyMem (&NextVariable->VendorGuid, VendorGuid, sizeof (EFI_GUID));\r
//\r
// There will be pad bytes after Data, the NextVariable->NameSize and\r