The common variable operation routines shared by DXE_RUNTIME variable \r
module and DXE_SMM variable module.\r
\r
-Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2006 - 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
@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 UpdatingPtrTrack Pointer to updating variable pointer track structure.\r
+ @param ReclaimAnyway If TRUE, do reclaim anyway.\r
\r
@return EFI_OUT_OF_RESOURCES\r
@return EFI_SUCCESS\r
IN EFI_PHYSICAL_ADDRESS VariableBase,\r
OUT UINTN *LastVariableOffset,\r
IN BOOLEAN IsVolatile,\r
- IN VARIABLE_HEADER *UpdatingVariable\r
+ IN OUT VARIABLE_POINTER_TRACK *UpdatingPtrTrack,\r
+ IN BOOLEAN ReclaimAnyway\r
)\r
{\r
VARIABLE_HEADER *Variable;\r
CHAR16 *UpdatingVariableNamePtr;\r
UINTN CommonVariableTotalSize;\r
UINTN HwErrVariableTotalSize;\r
+ BOOLEAN NeedDoReclaim;\r
+ VARIABLE_HEADER *UpdatingVariable;\r
\r
+ UpdatingVariable = NULL;\r
+ if (UpdatingPtrTrack != NULL) {\r
+ UpdatingVariable = UpdatingPtrTrack->CurrPtr;\r
+ }\r
+\r
+ NeedDoReclaim = FALSE;\r
VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINTN) VariableBase);\r
\r
CommonVariableTotalSize = 0;\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
+ }\r
+\r
//\r
// Reserve the 1 Bytes with Oxff to identify the \r
// end of the variable buffer. \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
) {\r
Point0 = (VOID *) GetVariableNamePtr (AddedVariable);\r
Point1 = (VOID *) GetVariableNamePtr (Variable);\r
- if (CompareMem (Point0, Point1, NameSizeOfVariable (AddedVariable)) == 0) {\r
+ if (CompareMem (Point0, Point1, NameSize) == 0) {\r
FoundAdded = TRUE;\r
break;\r
}\r
VARIABLE_HEADER *InDeletedVariable;\r
VOID *Point;\r
\r
+ PtrTrack->InDeletedTransitionPtr = NULL;\r
+\r
//\r
// Find the variable by walk through HOB, volatile and non-volatile variable store.\r
//\r
if (PtrTrack->CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {\r
InDeletedVariable = PtrTrack->CurrPtr;\r
} else {\r
+ PtrTrack->InDeletedTransitionPtr = InDeletedVariable;\r
return EFI_SUCCESS;\r
}\r
} else {\r
if (PtrTrack->CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {\r
InDeletedVariable = PtrTrack->CurrPtr;\r
} else {\r
+ PtrTrack->InDeletedTransitionPtr = InDeletedVariable;\r
return EFI_SUCCESS;\r
}\r
}\r
//\r
// Successfully convert PlatformLang to Lang, and set the BestLang value into Lang variable simultaneously.\r
//\r
- FindVariable (L"Lang", &gEfiGlobalVariableGuid, &Variable, (VARIABLE_GLOBAL *)mVariableModuleGlobal, FALSE);\r
+ FindVariable (L"Lang", &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);\r
\r
Status = UpdateVariable (L"Lang", &gEfiGlobalVariableGuid, BestLang,\r
ISO_639_2_ENTRY_SIZE + 1, Attributes, &Variable);\r
@param[in] Data Variable data.\r
@param[in] DataSize Size of data. 0 means delete.\r
@param[in] Attributes Attribues of the variable.\r
- @param[in] CacheVariable The variable information which is used to keep track of variable usage.\r
+ @param[in, out] CacheVariable The variable information which is used to keep track of variable usage.\r
\r
@retval EFI_SUCCESS The update operation is success.\r
@retval EFI_OUT_OF_RESOURCES Variable region is full, can not write other data into this region.\r
IN VOID *Data,\r
IN UINTN DataSize,\r
IN UINT32 Attributes OPTIONAL,\r
- IN VARIABLE_POINTER_TRACK *CacheVariable\r
+ IN OUT VARIABLE_POINTER_TRACK *CacheVariable\r
)\r
{\r
EFI_STATUS Status;\r
BOOLEAN Volatile;\r
EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;\r
UINT8 State;\r
- BOOLEAN Reclaimed;\r
VARIABLE_POINTER_TRACK *Variable;\r
VARIABLE_POINTER_TRACK NvVariable;\r
VARIABLE_STORE_HEADER *VariableStoreHeader;\r
Variable->StartPtr = GetStartPointer (VariableStoreHeader);\r
Variable->EndPtr = GetEndPointer (VariableStoreHeader);\r
Variable->CurrPtr = (VARIABLE_HEADER *)((UINTN)Variable->StartPtr + ((UINTN)CacheVariable->CurrPtr - (UINTN)CacheVariable->StartPtr));\r
+ if (CacheVariable->InDeletedTransitionPtr != NULL) {\r
+ Variable->InDeletedTransitionPtr = (VARIABLE_HEADER *)((UINTN)Variable->StartPtr + ((UINTN)CacheVariable->InDeletedTransitionPtr - (UINTN)CacheVariable->StartPtr));\r
+ } else {\r
+ Variable->InDeletedTransitionPtr = NULL;\r
+ }\r
Variable->Volatile = FALSE;\r
} \r
\r
Fvb = mVariableModuleGlobal->FvbInstance;\r
- Reclaimed = FALSE;\r
\r
if (Variable->CurrPtr != NULL) {\r
//\r
// causes it to be deleted.\r
//\r
if (DataSize == 0 || (Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == 0) { \r
+ if (Variable->InDeletedTransitionPtr != NULL) {\r
+ //\r
+ // Both ADDED and IN_DELETED_TRANSITION variable are present,\r
+ // set IN_DELETED_TRANSITION one to DELETED state first.\r
+ //\r
+ State = Variable->InDeletedTransitionPtr->State;\r
+ State &= VAR_DELETED;\r
+ Status = UpdateVariableStore (\r
+ &mVariableModuleGlobal->VariableGlobal,\r
+ Variable->Volatile,\r
+ FALSE,\r
+ Fvb,\r
+ (UINTN) &Variable->InDeletedTransitionPtr->State,\r
+ sizeof (UINT8),\r
+ &State\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ if (!Variable->Volatile) {\r
+ ASSERT (CacheVariable->InDeletedTransitionPtr != NULL);\r
+ CacheVariable->InDeletedTransitionPtr->State = State;\r
+ }\r
+ } else {\r
+ goto Done;\r
+ }\r
+ }\r
+\r
State = Variable->CurrPtr->State;\r
State &= VAR_DELETED;\r
\r
UpdateVariableInfo (VariableName, VendorGuid, Variable->Volatile, FALSE, FALSE, TRUE, FALSE);\r
if (!Variable->Volatile) {\r
CacheVariable->CurrPtr->State = State;\r
+ FlushHobVariableToFlash (VariableName, VendorGuid);\r
}\r
}\r
goto Done; \r
// Perform garbage collection & reclaim operation.\r
//\r
Status = Reclaim (mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase, \r
- &mVariableModuleGlobal->NonVolatileLastVariableOffset, FALSE, Variable->CurrPtr);\r
+ &mVariableModuleGlobal->NonVolatileLastVariableOffset, FALSE, Variable, FALSE);\r
if (EFI_ERROR (Status)) {\r
goto Done;\r
}\r
Status = EFI_OUT_OF_RESOURCES;\r
goto Done;\r
}\r
- Reclaimed = TRUE;\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
}\r
//\r
// Four steps\r
// Perform garbage collection & reclaim operation.\r
//\r
Status = Reclaim (mVariableModuleGlobal->VariableGlobal.VolatileVariableBase, \r
- &mVariableModuleGlobal->VolatileLastVariableOffset, TRUE, Variable->CurrPtr);\r
+ &mVariableModuleGlobal->VolatileLastVariableOffset, TRUE, Variable, FALSE);\r
if (EFI_ERROR (Status)) {\r
goto Done;\r
}\r
Status = EFI_OUT_OF_RESOURCES;\r
goto Done;\r
}\r
- Reclaimed = TRUE;\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
}\r
\r
NextVariable->State = VAR_ADDED;\r
//\r
// Mark the old variable as deleted.\r
//\r
- if (!Reclaimed && !EFI_ERROR (Status) && Variable->CurrPtr != NULL) {\r
+ if (!EFI_ERROR (Status) && Variable->CurrPtr != NULL) {\r
+ if (Variable->InDeletedTransitionPtr != NULL) {\r
+ //\r
+ // Both ADDED and IN_DELETED_TRANSITION old variable are present,\r
+ // set IN_DELETED_TRANSITION one to DELETED state first.\r
+ //\r
+ State = Variable->InDeletedTransitionPtr->State;\r
+ State &= VAR_DELETED;\r
+ Status = UpdateVariableStore (\r
+ &mVariableModuleGlobal->VariableGlobal,\r
+ Variable->Volatile,\r
+ FALSE,\r
+ Fvb,\r
+ (UINTN) &Variable->InDeletedTransitionPtr->State,\r
+ sizeof (UINT8),\r
+ &State\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ if (!Variable->Volatile) {\r
+ ASSERT (CacheVariable->InDeletedTransitionPtr != NULL);\r
+ CacheVariable->InDeletedTransitionPtr->State = State;\r
+ }\r
+ } else {\r
+ goto Done;\r
+ }\r
+ }\r
+\r
State = Variable->CurrPtr->State;\r
State &= VAR_DELETED;\r
\r
\r
if (!EFI_ERROR (Status)) {\r
UpdateVariableInfo (VariableName, VendorGuid, Volatile, FALSE, TRUE, FALSE, FALSE);\r
+ if (!Volatile) {\r
+ FlushHobVariableToFlash (VariableName, VendorGuid);\r
+ }\r
}\r
\r
Done:\r
VARIABLE_STORE_TYPE Type;\r
VARIABLE_POINTER_TRACK Variable;\r
VARIABLE_POINTER_TRACK VariableInHob;\r
+ VARIABLE_POINTER_TRACK VariablePtrTrack;\r
UINTN VarNameSize;\r
EFI_STATUS Status;\r
VARIABLE_STORE_HEADER *VariableStoreHeader[VariableStoreTypeMax];\r
//\r
// Variable is found\r
//\r
- if (Variable.CurrPtr->State == VAR_ADDED) {\r
- if ((AtRuntime () && ((Variable.CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0)) == 0) {\r
+ if (Variable.CurrPtr->State == VAR_ADDED || Variable.CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {\r
+ if (!AtRuntime () || ((Variable.CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) != 0)) {\r
+ if (Variable.CurrPtr->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
+ VariablePtrTrack.StartPtr = Variable.StartPtr;\r
+ VariablePtrTrack.EndPtr = Variable.EndPtr;\r
+ Status = FindVariableEx (\r
+ GetVariableNamePtr (Variable.CurrPtr),\r
+ &Variable.CurrPtr->VendorGuid,\r
+ FALSE,\r
+ &VariablePtrTrack\r
+ );\r
+ if (!EFI_ERROR (Status) && VariablePtrTrack.CurrPtr->State == VAR_ADDED) {\r
+ Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);\r
+ continue;\r
+ }\r
+ }\r
\r
//\r
// Don't return NV variable when HOB overrides it\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
+ if ((UINTN)(~0) - DataSize < StrSize(VariableName)){\r
+ //\r
+ // Prevent whole variable size overflow \r
+ // \r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
//\r
// The size of the VariableName, including the Unicode Null in bytes plus\r
// the DataSize is limited to maximum size of PcdGet32 (PcdMaxHardwareErrorVariableSize)\r
// bytes for HwErrRec, and PcdGet32 (PcdMaxVariableSize) bytes for the others.\r
//\r
if ((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD) {\r
- if ((DataSize > PcdGet32 (PcdMaxHardwareErrorVariableSize)) ||\r
- (sizeof (VARIABLE_HEADER) + StrSize (VariableName) + DataSize > PcdGet32 (PcdMaxHardwareErrorVariableSize))) {\r
+ if ( StrSize (VariableName) + DataSize > PcdGet32 (PcdMaxHardwareErrorVariableSize) - sizeof (VARIABLE_HEADER)) {\r
return EFI_INVALID_PARAMETER;\r
}\r
if (!IsHwErrRecVariable(VariableName, VendorGuid)) {\r
// The size of the VariableName, including the Unicode Null in bytes plus\r
// the DataSize is limited to maximum size of PcdGet32 (PcdMaxVariableSize) bytes.\r
//\r
- if ((DataSize > PcdGet32 (PcdMaxVariableSize)) ||\r
- (sizeof (VARIABLE_HEADER) + StrSize (VariableName) + DataSize > PcdGet32 (PcdMaxVariableSize))) {\r
+ if (StrSize (VariableName) + DataSize > PcdGet32 (PcdMaxVariableSize) - sizeof (VARIABLE_HEADER)) {\r
return EFI_INVALID_PARAMETER;\r
} \r
}\r
mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase,\r
&mVariableModuleGlobal->NonVolatileLastVariableOffset,\r
FALSE,\r
- NULL\r
+ NULL,\r
+ FALSE\r
);\r
ASSERT_EFI_ERROR (Status);\r
}\r
}\r
\r
+/**\r
+ Flush the HOB variable to flash.\r
+\r
+ @param[in] VariableName Name of variable has been updated or deleted.\r
+ @param[in] VendorGuid Guid of variable has been updated or deleted.\r
+\r
+**/\r
+VOID\r
+FlushHobVariableToFlash (\r
+ IN CHAR16 *VariableName,\r
+ IN EFI_GUID *VendorGuid\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ VARIABLE_STORE_HEADER *VariableStoreHeader;\r
+ VARIABLE_HEADER *Variable;\r
+ VOID *VariableData;\r
+ BOOLEAN ErrorFlag;\r
+\r
+ ErrorFlag = FALSE;\r
+\r
+ //\r
+ // Flush the HOB variable to flash.\r
+ //\r
+ if (mVariableModuleGlobal->VariableGlobal.HobVariableBase != 0) {\r
+ VariableStoreHeader = (VARIABLE_STORE_HEADER *) (UINTN) mVariableModuleGlobal->VariableGlobal.HobVariableBase;\r
+ //\r
+ // Set HobVariableBase to 0, it can avoid SetVariable to call back.\r
+ //\r
+ mVariableModuleGlobal->VariableGlobal.HobVariableBase = 0;\r
+ for ( Variable = GetStartPointer (VariableStoreHeader)\r
+ ; (Variable < GetEndPointer (VariableStoreHeader) && IsValidVariableHeader (Variable))\r
+ ; Variable = GetNextVariablePtr (Variable)\r
+ ) {\r
+ if (Variable->State != VAR_ADDED) {\r
+ //\r
+ // The HOB variable has been set to DELETED state in local.\r
+ //\r
+ continue;\r
+ }\r
+ ASSERT ((Variable->Attributes & EFI_VARIABLE_NON_VOLATILE) != 0);\r
+ if (VendorGuid == NULL || VariableName == NULL ||\r
+ !CompareGuid (VendorGuid, &Variable->VendorGuid) ||\r
+ StrCmp (VariableName, GetVariableNamePtr (Variable)) != 0) {\r
+ VariableData = GetVariableDataPtr (Variable);\r
+ Status = VariableServiceSetVariable (\r
+ GetVariableNamePtr (Variable),\r
+ &Variable->VendorGuid,\r
+ Variable->Attributes,\r
+ Variable->DataSize,\r
+ VariableData\r
+ );\r
+ DEBUG ((EFI_D_INFO, "Variable driver flush the HOB variable to flash: %g %s %r\n", &Variable->VendorGuid, GetVariableNamePtr (Variable), Status));\r
+ } else {\r
+ //\r
+ // The updated or deleted variable is matched with the HOB variable.\r
+ // Don't break here because we will try to set other HOB variables\r
+ // since this variable could be set successfully.\r
+ //\r
+ Status = EFI_SUCCESS;\r
+ }\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // If set variable successful, or the updated or deleted variable is matched with the HOB variable,\r
+ // set the HOB variable to DELETED state in local.\r
+ //\r
+ DEBUG ((EFI_D_INFO, "Variable driver set the HOB variable to DELETED state in local: %g %s\n", &Variable->VendorGuid, GetVariableNamePtr (Variable)));\r
+ Variable->State &= VAR_DELETED;\r
+ } else {\r
+ ErrorFlag = TRUE;\r
+ }\r
+ }\r
+ if (ErrorFlag) {\r
+ //\r
+ // We still have HOB variable(s) not flushed in flash.\r
+ //\r
+ mVariableModuleGlobal->VariableGlobal.HobVariableBase = (EFI_PHYSICAL_ADDRESS) (UINTN) VariableStoreHeader;\r
+ } else {\r
+ //\r
+ // All HOB variables have been flushed in flash.\r
+ //\r
+ DEBUG ((EFI_D_INFO, "Variable driver: all HOB variables have been flushed in flash.\n"));\r
+ if (!AtRuntime ()) {\r
+ FreePool ((VOID *) VariableStoreHeader);\r
+ }\r
+ }\r
+ }\r
+\r
+}\r
\r
/**\r
Initializes variable write service after FVB was ready.\r
UINTN Index;\r
UINT8 Data;\r
EFI_PHYSICAL_ADDRESS VariableStoreBase;\r
- VARIABLE_HEADER *Variable;\r
- VOID *VariableData;\r
\r
VariableStoreBase = mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase;\r
VariableStoreHeader = (VARIABLE_STORE_HEADER *)(UINTN)VariableStoreBase;\r
mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase,\r
&mVariableModuleGlobal->NonVolatileLastVariableOffset,\r
FALSE,\r
- NULL\r
+ NULL,\r
+ TRUE\r
);\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
}\r
\r
- //\r
- // Flush the HOB variable to flash and invalidate HOB variable.\r
- //\r
- if (mVariableModuleGlobal->VariableGlobal.HobVariableBase != 0) {\r
- //\r
- // Clear the HobVariableBase to avoid SetVariable() updating the variable in HOB\r
- //\r
- VariableStoreHeader = (VARIABLE_STORE_HEADER *) (UINTN) mVariableModuleGlobal->VariableGlobal.HobVariableBase;\r
- mVariableModuleGlobal->VariableGlobal.HobVariableBase = 0;\r
+ FlushHobVariableToFlash (NULL, NULL);\r
\r
- for ( Variable = GetStartPointer (VariableStoreHeader)\r
- ; (Variable < GetEndPointer (VariableStoreHeader) && IsValidVariableHeader (Variable))\r
- ; Variable = GetNextVariablePtr (Variable)\r
- ) {\r
- ASSERT (Variable->State == VAR_ADDED);\r
- ASSERT ((Variable->Attributes & EFI_VARIABLE_NON_VOLATILE) != 0);\r
- VariableData = GetVariableDataPtr (Variable);\r
- Status = VariableServiceSetVariable (\r
- GetVariableNamePtr (Variable),\r
- &Variable->VendorGuid,\r
- Variable->Attributes,\r
- Variable->DataSize,\r
- VariableData\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
- }\r
- }\r
return EFI_SUCCESS;\r
}\r
\r
GuidHob = GetFirstGuidHob (&gEfiVariableGuid);\r
if (GuidHob != NULL) {\r
VariableStoreHeader = GET_GUID_HOB_DATA (GuidHob);\r
+ VariableStoreLength = (UINT64) (GuidHob->Header.HobLength - sizeof (EFI_HOB_GUID_TYPE));\r
if (GetVariableStoreStatus (VariableStoreHeader) == EfiValid) {\r
- mVariableModuleGlobal->VariableGlobal.HobVariableBase = (EFI_PHYSICAL_ADDRESS) (UINTN) VariableStoreHeader;\r
+ mVariableModuleGlobal->VariableGlobal.HobVariableBase = (EFI_PHYSICAL_ADDRESS) (UINTN) AllocateRuntimeCopyPool ((UINTN) VariableStoreLength, (VOID *) VariableStoreHeader);\r
+ if (mVariableModuleGlobal->VariableGlobal.HobVariableBase == 0) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
} else {\r
DEBUG ((EFI_D_ERROR, "HOB Variable Store header is corrupted!\n"));\r
}\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
//\r