1. Update the logic of UpdateVariable() for updating variable from:

set old variable to IN_DELETED_TRANSITION -> check if reclaim is needed(If yes, do reclaim) -> add new variable -> set old variable to DELETED if no reclaim happened.
to:
set old variable to IN_DELETED_TRANSITION -> check if reclaim is needed(If yes, do reclaim) -> add new variable -> set old variable to DELETED.
2. Update UpdateVariable() to correctly handle the case "both ADDED and IN_DELETED_TRANSITION variable are present", and delete both old ADDED and IN_DELETED_TRANSITION variable when deleting or updating variable.
3. Update VariableServiceGetNextVariableName() to return the valid IN_DELETED_TRANSITION variable if only IN_DELETED_TRANSITION variable is present.

Signed-off-by: Star Zeng <star.zeng@intel.com>
Reviewed-by: Ruiyu Ni <ruiyu.ni@intel.com>

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@14065 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
lzeng14 2013-01-18 01:12:32 +00:00
parent e886b675bd
commit 23b0693579
4 changed files with 233 additions and 37 deletions

View File

@ -3,7 +3,7 @@
The common variable operation routines shared by DXE_RUNTIME variable The common variable operation routines shared by DXE_RUNTIME variable
module and DXE_SMM variable module. module and DXE_SMM variable module.
Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR> Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at which accompanies this distribution. The full text of the license may be found at
@ -504,7 +504,7 @@ GetEndPointer (
@param LastVariableOffset Offset of last variable. @param LastVariableOffset Offset of last variable.
@param IsVolatile The variable store is volatile or not; @param IsVolatile The variable store is volatile or not;
if it is non-volatile, need FTW. if it is non-volatile, need FTW.
@param UpdatingVariable Pointer to updating variable. @param UpdatingPtrTrack Pointer to updating variable pointer track structure.
@param ReclaimAnyway If TRUE, do reclaim anyway. @param ReclaimAnyway If TRUE, do reclaim anyway.
@return EFI_OUT_OF_RESOURCES @return EFI_OUT_OF_RESOURCES
@ -517,7 +517,7 @@ Reclaim (
IN EFI_PHYSICAL_ADDRESS VariableBase, IN EFI_PHYSICAL_ADDRESS VariableBase,
OUT UINTN *LastVariableOffset, OUT UINTN *LastVariableOffset,
IN BOOLEAN IsVolatile, IN BOOLEAN IsVolatile,
IN VARIABLE_HEADER *UpdatingVariable, IN OUT VARIABLE_POINTER_TRACK *UpdatingPtrTrack,
IN BOOLEAN ReclaimAnyway IN BOOLEAN ReclaimAnyway
) )
{ {
@ -542,6 +542,12 @@ Reclaim (
UINTN CommonVariableTotalSize; UINTN CommonVariableTotalSize;
UINTN HwErrVariableTotalSize; UINTN HwErrVariableTotalSize;
BOOLEAN NeedDoReclaim; BOOLEAN NeedDoReclaim;
VARIABLE_HEADER *UpdatingVariable;
UpdatingVariable = NULL;
if (UpdatingPtrTrack != NULL) {
UpdatingVariable = UpdatingPtrTrack->CurrPtr;
}
NeedDoReclaim = FALSE; NeedDoReclaim = FALSE;
VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINTN) VariableBase); VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINTN) VariableBase);
@ -635,6 +641,8 @@ Reclaim (
if (UpdatingVariable != NULL) { if (UpdatingVariable != NULL) {
VariableSize = (UINTN)(GetNextVariablePtr (UpdatingVariable)) - (UINTN)UpdatingVariable; VariableSize = (UINTN)(GetNextVariablePtr (UpdatingVariable)) - (UINTN)UpdatingVariable;
CopyMem (CurrPtr, (UINT8 *) UpdatingVariable, VariableSize); CopyMem (CurrPtr, (UINT8 *) UpdatingVariable, VariableSize);
UpdatingPtrTrack->CurrPtr = (VARIABLE_HEADER *)((UINTN)UpdatingPtrTrack->StartPtr + ((UINTN)CurrPtr - (UINTN)GetStartPointer ((VARIABLE_STORE_HEADER *) ValidBuffer)));
UpdatingPtrTrack->InDeletedTransitionPtr = NULL;
CurrPtr += VariableSize; CurrPtr += VariableSize;
if ((!IsVolatile) && ((UpdatingVariable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD)) { if ((!IsVolatile) && ((UpdatingVariable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {
HwErrVariableTotalSize += VariableSize; HwErrVariableTotalSize += VariableSize;
@ -667,7 +675,7 @@ Reclaim (
) { ) {
Point0 = (VOID *) GetVariableNamePtr (AddedVariable); Point0 = (VOID *) GetVariableNamePtr (AddedVariable);
Point1 = (VOID *) GetVariableNamePtr (Variable); Point1 = (VOID *) GetVariableNamePtr (Variable);
if (CompareMem (Point0, Point1, NameSizeOfVariable (AddedVariable)) == 0) { if (CompareMem (Point0, Point1, NameSize) == 0) {
FoundAdded = TRUE; FoundAdded = TRUE;
break; break;
} }
@ -760,6 +768,8 @@ FindVariableEx (
VARIABLE_HEADER *InDeletedVariable; VARIABLE_HEADER *InDeletedVariable;
VOID *Point; VOID *Point;
PtrTrack->InDeletedTransitionPtr = NULL;
// //
// Find the variable by walk through HOB, volatile and non-volatile variable store. // Find the variable by walk through HOB, volatile and non-volatile variable store.
// //
@ -777,6 +787,7 @@ FindVariableEx (
if (PtrTrack->CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) { if (PtrTrack->CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
InDeletedVariable = PtrTrack->CurrPtr; InDeletedVariable = PtrTrack->CurrPtr;
} else { } else {
PtrTrack->InDeletedTransitionPtr = InDeletedVariable;
return EFI_SUCCESS; return EFI_SUCCESS;
} }
} else { } else {
@ -788,6 +799,7 @@ FindVariableEx (
if (PtrTrack->CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) { if (PtrTrack->CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
InDeletedVariable = PtrTrack->CurrPtr; InDeletedVariable = PtrTrack->CurrPtr;
} else { } else {
PtrTrack->InDeletedTransitionPtr = InDeletedVariable;
return EFI_SUCCESS; return EFI_SUCCESS;
} }
} }
@ -1320,7 +1332,7 @@ AutoUpdateLangVariable (
// //
// Successfully convert PlatformLang to Lang, and set the BestLang value into Lang variable simultaneously. // Successfully convert PlatformLang to Lang, and set the BestLang value into Lang variable simultaneously.
// //
FindVariable (L"Lang", &gEfiGlobalVariableGuid, &Variable, (VARIABLE_GLOBAL *)mVariableModuleGlobal, FALSE); FindVariable (L"Lang", &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);
Status = UpdateVariable (L"Lang", &gEfiGlobalVariableGuid, BestLang, Status = UpdateVariable (L"Lang", &gEfiGlobalVariableGuid, BestLang,
ISO_639_2_ENTRY_SIZE + 1, Attributes, &Variable); ISO_639_2_ENTRY_SIZE + 1, Attributes, &Variable);
@ -1375,7 +1387,7 @@ AutoUpdateLangVariable (
@param[in] Data Variable data. @param[in] Data Variable data.
@param[in] DataSize Size of data. 0 means delete. @param[in] DataSize Size of data. 0 means delete.
@param[in] Attributes Attribues of the variable. @param[in] Attributes Attribues of the variable.
@param[in] CacheVariable The variable information which is used to keep track of variable usage. @param[in, out] CacheVariable The variable information which is used to keep track of variable usage.
@retval EFI_SUCCESS The update operation is success. @retval EFI_SUCCESS The update operation is success.
@retval EFI_OUT_OF_RESOURCES Variable region is full, can not write other data into this region. @retval EFI_OUT_OF_RESOURCES Variable region is full, can not write other data into this region.
@ -1388,7 +1400,7 @@ UpdateVariable (
IN VOID *Data, IN VOID *Data,
IN UINTN DataSize, IN UINTN DataSize,
IN UINT32 Attributes OPTIONAL, IN UINT32 Attributes OPTIONAL,
IN VARIABLE_POINTER_TRACK *CacheVariable IN OUT VARIABLE_POINTER_TRACK *CacheVariable
) )
{ {
EFI_STATUS Status; EFI_STATUS Status;
@ -1402,7 +1414,6 @@ UpdateVariable (
BOOLEAN Volatile; BOOLEAN Volatile;
EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb; EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;
UINT8 State; UINT8 State;
BOOLEAN Reclaimed;
VARIABLE_POINTER_TRACK *Variable; VARIABLE_POINTER_TRACK *Variable;
VARIABLE_POINTER_TRACK NvVariable; VARIABLE_POINTER_TRACK NvVariable;
VARIABLE_STORE_HEADER *VariableStoreHeader; VARIABLE_STORE_HEADER *VariableStoreHeader;
@ -1429,11 +1440,15 @@ UpdateVariable (
Variable->StartPtr = GetStartPointer (VariableStoreHeader); Variable->StartPtr = GetStartPointer (VariableStoreHeader);
Variable->EndPtr = GetEndPointer (VariableStoreHeader); Variable->EndPtr = GetEndPointer (VariableStoreHeader);
Variable->CurrPtr = (VARIABLE_HEADER *)((UINTN)Variable->StartPtr + ((UINTN)CacheVariable->CurrPtr - (UINTN)CacheVariable->StartPtr)); Variable->CurrPtr = (VARIABLE_HEADER *)((UINTN)Variable->StartPtr + ((UINTN)CacheVariable->CurrPtr - (UINTN)CacheVariable->StartPtr));
if (CacheVariable->InDeletedTransitionPtr != NULL) {
Variable->InDeletedTransitionPtr = (VARIABLE_HEADER *)((UINTN)Variable->StartPtr + ((UINTN)CacheVariable->InDeletedTransitionPtr - (UINTN)CacheVariable->StartPtr));
} else {
Variable->InDeletedTransitionPtr = NULL;
}
Variable->Volatile = FALSE; Variable->Volatile = FALSE;
} }
Fvb = mVariableModuleGlobal->FvbInstance; Fvb = mVariableModuleGlobal->FvbInstance;
Reclaimed = FALSE;
if (Variable->CurrPtr != NULL) { if (Variable->CurrPtr != NULL) {
// //
@ -1463,6 +1478,31 @@ UpdateVariable (
// causes it to be deleted. // causes it to be deleted.
// //
if (DataSize == 0 || (Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == 0) { if (DataSize == 0 || (Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == 0) {
if (Variable->InDeletedTransitionPtr != NULL) {
//
// Both ADDED and IN_DELETED_TRANSITION variable are present,
// set IN_DELETED_TRANSITION one to DELETED state first.
//
State = Variable->InDeletedTransitionPtr->State;
State &= VAR_DELETED;
Status = UpdateVariableStore (
&mVariableModuleGlobal->VariableGlobal,
Variable->Volatile,
FALSE,
Fvb,
(UINTN) &Variable->InDeletedTransitionPtr->State,
sizeof (UINT8),
&State
);
if (!EFI_ERROR (Status)) {
if (!Variable->Volatile) {
CacheVariable->InDeletedTransitionPtr->State = State;
}
} else {
goto Done;
}
}
State = Variable->CurrPtr->State; State = Variable->CurrPtr->State;
State &= VAR_DELETED; State &= VAR_DELETED;
@ -1607,7 +1647,7 @@ UpdateVariable (
// Perform garbage collection & reclaim operation. // Perform garbage collection & reclaim operation.
// //
Status = Reclaim (mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase, Status = Reclaim (mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase,
&mVariableModuleGlobal->NonVolatileLastVariableOffset, FALSE, Variable->CurrPtr, FALSE); &mVariableModuleGlobal->NonVolatileLastVariableOffset, FALSE, Variable, FALSE);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
goto Done; goto Done;
} }
@ -1621,7 +1661,10 @@ UpdateVariable (
Status = EFI_OUT_OF_RESOURCES; Status = EFI_OUT_OF_RESOURCES;
goto Done; goto Done;
} }
Reclaimed = TRUE; if (Variable->CurrPtr != NULL) {
CacheVariable->CurrPtr = (VARIABLE_HEADER *)((UINTN) CacheVariable->StartPtr + ((UINTN) Variable->CurrPtr - (UINTN) Variable->StartPtr));
CacheVariable->InDeletedTransitionPtr = NULL;
}
} }
// //
// Four steps // Four steps
@ -1722,7 +1765,7 @@ UpdateVariable (
// Perform garbage collection & reclaim operation. // Perform garbage collection & reclaim operation.
// //
Status = Reclaim (mVariableModuleGlobal->VariableGlobal.VolatileVariableBase, Status = Reclaim (mVariableModuleGlobal->VariableGlobal.VolatileVariableBase,
&mVariableModuleGlobal->VolatileLastVariableOffset, TRUE, Variable->CurrPtr, FALSE); &mVariableModuleGlobal->VolatileLastVariableOffset, TRUE, Variable, FALSE);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
goto Done; goto Done;
} }
@ -1735,7 +1778,10 @@ UpdateVariable (
Status = EFI_OUT_OF_RESOURCES; Status = EFI_OUT_OF_RESOURCES;
goto Done; goto Done;
} }
Reclaimed = TRUE; if (Variable->CurrPtr != NULL) {
CacheVariable->CurrPtr = (VARIABLE_HEADER *)((UINTN) CacheVariable->StartPtr + ((UINTN) Variable->CurrPtr - (UINTN) Variable->StartPtr));
CacheVariable->InDeletedTransitionPtr = NULL;
}
} }
NextVariable->State = VAR_ADDED; NextVariable->State = VAR_ADDED;
@ -1759,7 +1805,32 @@ UpdateVariable (
// //
// Mark the old variable as deleted. // Mark the old variable as deleted.
// //
if (!Reclaimed && !EFI_ERROR (Status) && Variable->CurrPtr != NULL) { if (!EFI_ERROR (Status) && Variable->CurrPtr != NULL) {
if (Variable->InDeletedTransitionPtr != NULL) {
//
// Both ADDED and IN_DELETED_TRANSITION old variable are present,
// set IN_DELETED_TRANSITION one to DELETED state first.
//
State = Variable->InDeletedTransitionPtr->State;
State &= VAR_DELETED;
Status = UpdateVariableStore (
&mVariableModuleGlobal->VariableGlobal,
Variable->Volatile,
FALSE,
Fvb,
(UINTN) &Variable->InDeletedTransitionPtr->State,
sizeof (UINT8),
&State
);
if (!EFI_ERROR (Status)) {
if (!Variable->Volatile) {
CacheVariable->InDeletedTransitionPtr->State = State;
}
} else {
goto Done;
}
}
State = Variable->CurrPtr->State; State = Variable->CurrPtr->State;
State &= VAR_DELETED; State &= VAR_DELETED;
@ -1947,6 +2018,7 @@ VariableServiceGetNextVariableName (
VARIABLE_STORE_TYPE Type; VARIABLE_STORE_TYPE Type;
VARIABLE_POINTER_TRACK Variable; VARIABLE_POINTER_TRACK Variable;
VARIABLE_POINTER_TRACK VariableInHob; VARIABLE_POINTER_TRACK VariableInHob;
VARIABLE_POINTER_TRACK VariablePtrTrack;
UINTN VarNameSize; UINTN VarNameSize;
EFI_STATUS Status; EFI_STATUS Status;
VARIABLE_STORE_HEADER *VariableStoreHeader[VariableStoreTypeMax]; VARIABLE_STORE_HEADER *VariableStoreHeader[VariableStoreTypeMax];
@ -2020,8 +2092,27 @@ VariableServiceGetNextVariableName (
// //
// Variable is found // Variable is found
// //
if (Variable.CurrPtr->State == VAR_ADDED) { if (Variable.CurrPtr->State == VAR_ADDED || Variable.CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
if ((AtRuntime () && ((Variable.CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0)) == 0) { if (!AtRuntime () || ((Variable.CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) != 0)) {
if (Variable.CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
//
// If it is a IN_DELETED_TRANSITION variable,
// and there is also a same ADDED one at the same time,
// don't return it.
//
VariablePtrTrack.StartPtr = Variable.StartPtr;
VariablePtrTrack.EndPtr = Variable.EndPtr;
Status = FindVariableEx (
GetVariableNamePtr (Variable.CurrPtr),
&Variable.CurrPtr->VendorGuid,
FALSE,
&VariablePtrTrack
);
if (!EFI_ERROR (Status) && VariablePtrTrack.CurrPtr->State == VAR_ADDED) {
Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);
continue;
}
}
// //
// Don't return NV variable when HOB overrides it // Don't return NV variable when HOB overrides it

View File

@ -3,7 +3,7 @@
The internal header file includes the common header files, defines The internal header file includes the common header files, defines
internal structure and functions used by Variable modules. internal structure and functions used by Variable modules.
Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR> Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at which accompanies this distribution. The full text of the license may be found at
@ -56,6 +56,13 @@ typedef enum {
typedef struct { typedef struct {
VARIABLE_HEADER *CurrPtr; VARIABLE_HEADER *CurrPtr;
//
// If both ADDED and IN_DELETED_TRANSITION variable are present,
// InDeletedTransitionPtr will point to the IN_DELETED_TRANSITION one.
// Otherwise, CurrPtr will point to the ADDED or IN_DELETED_TRANSITION one,
// and InDeletedTransitionPtr will be NULL at the same time.
//
VARIABLE_HEADER *InDeletedTransitionPtr;
VARIABLE_HEADER *EndPtr; VARIABLE_HEADER *EndPtr;
VARIABLE_HEADER *StartPtr; VARIABLE_HEADER *StartPtr;
BOOLEAN Volatile; BOOLEAN Volatile;
@ -141,7 +148,7 @@ FtwVariableSpace (
@param[in] Attributes Attribues of the variable. @param[in] Attributes Attribues of the variable.
@param[in] Variable The variable information that is used to keep track of variable usage. @param[in, out] Variable The variable information that is used to keep track of variable usage.
@retval EFI_SUCCESS The update operation is success. @retval EFI_SUCCESS The update operation is success.
@ -155,7 +162,7 @@ UpdateVariable (
IN VOID *Data, IN VOID *Data,
IN UINTN DataSize, IN UINTN DataSize,
IN UINT32 Attributes OPTIONAL, IN UINT32 Attributes OPTIONAL,
IN VARIABLE_POINTER_TRACK *Variable IN OUT VARIABLE_POINTER_TRACK *Variable
); );

View File

@ -655,7 +655,7 @@ PubKeyStoreFilter (
@param[out] LastVariableOffset Offset of last variable. @param[out] LastVariableOffset Offset of last variable.
@param[in] IsVolatile The variable store is volatile or not; @param[in] IsVolatile The variable store is volatile or not;
if it is non-volatile, need FTW. if it is non-volatile, need FTW.
@param[in] UpdatingVariable Pointer to updating variable. @param[in, out] UpdatingPtrTrack Pointer to updating variable pointer track structure.
@param[in] ReclaimPubKeyStore Reclaim for public key database or not. @param[in] ReclaimPubKeyStore Reclaim for public key database or not.
@param[in] ReclaimAnyway If TRUE, do reclaim anyway. @param[in] ReclaimAnyway If TRUE, do reclaim anyway.
@ -669,7 +669,7 @@ Reclaim (
IN EFI_PHYSICAL_ADDRESS VariableBase, IN EFI_PHYSICAL_ADDRESS VariableBase,
OUT UINTN *LastVariableOffset, OUT UINTN *LastVariableOffset,
IN BOOLEAN IsVolatile, IN BOOLEAN IsVolatile,
IN VARIABLE_HEADER *UpdatingVariable, IN OUT VARIABLE_POINTER_TRACK *UpdatingPtrTrack,
IN BOOLEAN ReclaimPubKeyStore, IN BOOLEAN ReclaimPubKeyStore,
IN BOOLEAN ReclaimAnyway IN BOOLEAN ReclaimAnyway
) )
@ -699,6 +699,12 @@ Reclaim (
UINT32 NewPubKeySize; UINT32 NewPubKeySize;
VARIABLE_HEADER *PubKeyHeader; VARIABLE_HEADER *PubKeyHeader;
BOOLEAN NeedDoReclaim; BOOLEAN NeedDoReclaim;
VARIABLE_HEADER *UpdatingVariable;
UpdatingVariable = NULL;
if (UpdatingPtrTrack != NULL) {
UpdatingVariable = UpdatingPtrTrack->CurrPtr;
}
NeedDoReclaim = FALSE; NeedDoReclaim = FALSE;
VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINTN) VariableBase); VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINTN) VariableBase);
@ -853,6 +859,8 @@ Reclaim (
if (UpdatingVariable != NULL) { if (UpdatingVariable != NULL) {
VariableSize = (UINTN)(GetNextVariablePtr (UpdatingVariable)) - (UINTN)UpdatingVariable; VariableSize = (UINTN)(GetNextVariablePtr (UpdatingVariable)) - (UINTN)UpdatingVariable;
CopyMem (CurrPtr, (UINT8 *) UpdatingVariable, VariableSize); CopyMem (CurrPtr, (UINT8 *) UpdatingVariable, VariableSize);
UpdatingPtrTrack->CurrPtr = (VARIABLE_HEADER *)((UINTN)UpdatingPtrTrack->StartPtr + ((UINTN)CurrPtr - (UINTN)GetStartPointer ((VARIABLE_STORE_HEADER *) ValidBuffer)));
UpdatingPtrTrack->InDeletedTransitionPtr = NULL;
CurrPtr += VariableSize; CurrPtr += VariableSize;
if ((!IsVolatile) && ((UpdatingVariable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD)) { if ((!IsVolatile) && ((UpdatingVariable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {
HwErrVariableTotalSize += VariableSize; HwErrVariableTotalSize += VariableSize;
@ -885,7 +893,7 @@ Reclaim (
) { ) {
Point0 = (VOID *) GetVariableNamePtr (AddedVariable); Point0 = (VOID *) GetVariableNamePtr (AddedVariable);
Point1 = (VOID *) GetVariableNamePtr (Variable); Point1 = (VOID *) GetVariableNamePtr (Variable);
if (CompareMem (Point0, Point1, NameSizeOfVariable (AddedVariable)) == 0) { if (CompareMem (Point0, Point1, NameSize) == 0) {
FoundAdded = TRUE; FoundAdded = TRUE;
break; break;
} }
@ -987,6 +995,8 @@ FindVariableEx (
VARIABLE_HEADER *InDeletedVariable; VARIABLE_HEADER *InDeletedVariable;
VOID *Point; VOID *Point;
PtrTrack->InDeletedTransitionPtr = NULL;
// //
// Find the variable by walk through HOB, volatile and non-volatile variable store. // Find the variable by walk through HOB, volatile and non-volatile variable store.
// //
@ -1004,6 +1014,7 @@ FindVariableEx (
if (PtrTrack->CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) { if (PtrTrack->CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
InDeletedVariable = PtrTrack->CurrPtr; InDeletedVariable = PtrTrack->CurrPtr;
} else { } else {
PtrTrack->InDeletedTransitionPtr = InDeletedVariable;
return EFI_SUCCESS; return EFI_SUCCESS;
} }
} else { } else {
@ -1015,6 +1026,7 @@ FindVariableEx (
if (PtrTrack->CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) { if (PtrTrack->CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
InDeletedVariable = PtrTrack->CurrPtr; InDeletedVariable = PtrTrack->CurrPtr;
} else { } else {
PtrTrack->InDeletedTransitionPtr = InDeletedVariable;
return EFI_SUCCESS; return EFI_SUCCESS;
} }
} }
@ -1606,7 +1618,7 @@ AutoUpdateLangVariable (
@param[in] Attributes Attributes of the variable. @param[in] Attributes Attributes of the variable.
@param[in] KeyIndex Index of associated public key. @param[in] KeyIndex Index of associated public key.
@param[in] MonotonicCount Value of associated monotonic count. @param[in] MonotonicCount Value of associated monotonic count.
@param[in] CacheVariable The variable information which is used to keep track of variable usage. @param[in, out] CacheVariable The variable information which is used to keep track of variable usage.
@param[in] TimeStamp Value of associated TimeStamp. @param[in] TimeStamp Value of associated TimeStamp.
@retval EFI_SUCCESS The update operation is success. @retval EFI_SUCCESS The update operation is success.
@ -1622,7 +1634,7 @@ UpdateVariable (
IN UINT32 Attributes OPTIONAL, IN UINT32 Attributes OPTIONAL,
IN UINT32 KeyIndex OPTIONAL, IN UINT32 KeyIndex OPTIONAL,
IN UINT64 MonotonicCount OPTIONAL, IN UINT64 MonotonicCount OPTIONAL,
IN VARIABLE_POINTER_TRACK *CacheVariable, IN OUT VARIABLE_POINTER_TRACK *CacheVariable,
IN EFI_TIME *TimeStamp OPTIONAL IN EFI_TIME *TimeStamp OPTIONAL
) )
{ {
@ -1638,7 +1650,6 @@ UpdateVariable (
BOOLEAN Volatile; BOOLEAN Volatile;
EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb; EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;
UINT8 State; UINT8 State;
BOOLEAN Reclaimed;
VARIABLE_POINTER_TRACK *Variable; VARIABLE_POINTER_TRACK *Variable;
VARIABLE_POINTER_TRACK NvVariable; VARIABLE_POINTER_TRACK NvVariable;
VARIABLE_STORE_HEADER *VariableStoreHeader; VARIABLE_STORE_HEADER *VariableStoreHeader;
@ -1678,11 +1689,15 @@ UpdateVariable (
Variable->StartPtr = GetStartPointer (VariableStoreHeader); Variable->StartPtr = GetStartPointer (VariableStoreHeader);
Variable->EndPtr = GetEndPointer (VariableStoreHeader); Variable->EndPtr = GetEndPointer (VariableStoreHeader);
Variable->CurrPtr = (VARIABLE_HEADER *)((UINTN)Variable->StartPtr + ((UINTN)CacheVariable->CurrPtr - (UINTN)CacheVariable->StartPtr)); Variable->CurrPtr = (VARIABLE_HEADER *)((UINTN)Variable->StartPtr + ((UINTN)CacheVariable->CurrPtr - (UINTN)CacheVariable->StartPtr));
if (CacheVariable->InDeletedTransitionPtr != NULL) {
Variable->InDeletedTransitionPtr = (VARIABLE_HEADER *)((UINTN)Variable->StartPtr + ((UINTN)CacheVariable->InDeletedTransitionPtr - (UINTN)CacheVariable->StartPtr));
} else {
Variable->InDeletedTransitionPtr = NULL;
}
Variable->Volatile = FALSE; Variable->Volatile = FALSE;
} }
Fvb = mVariableModuleGlobal->FvbInstance; Fvb = mVariableModuleGlobal->FvbInstance;
Reclaimed = FALSE;
// //
// Tricky part: Use scratch data area at the end of volatile variable store // Tricky part: Use scratch data area at the end of volatile variable store
@ -1730,6 +1745,31 @@ UpdateVariable (
// not delete the variable. // not delete the variable.
// //
if ((((Attributes & EFI_VARIABLE_APPEND_WRITE) == 0) && (DataSize == 0))|| ((Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == 0)) { if ((((Attributes & EFI_VARIABLE_APPEND_WRITE) == 0) && (DataSize == 0))|| ((Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == 0)) {
if (Variable->InDeletedTransitionPtr != NULL) {
//
// Both ADDED and IN_DELETED_TRANSITION variable are present,
// set IN_DELETED_TRANSITION one to DELETED state first.
//
State = Variable->InDeletedTransitionPtr->State;
State &= VAR_DELETED;
Status = UpdateVariableStore (
&mVariableModuleGlobal->VariableGlobal,
Variable->Volatile,
FALSE,
Fvb,
(UINTN) &Variable->InDeletedTransitionPtr->State,
sizeof (UINT8),
&State
);
if (!EFI_ERROR (Status)) {
if (!Variable->Volatile) {
CacheVariable->InDeletedTransitionPtr->State = State;
}
} else {
goto Done;
}
}
State = Variable->CurrPtr->State; State = Variable->CurrPtr->State;
State &= VAR_DELETED; State &= VAR_DELETED;
@ -1959,7 +1999,7 @@ UpdateVariable (
mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase, mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase,
&mVariableModuleGlobal->NonVolatileLastVariableOffset, &mVariableModuleGlobal->NonVolatileLastVariableOffset,
FALSE, FALSE,
Variable->CurrPtr, Variable,
FALSE, FALSE,
FALSE FALSE
); );
@ -1976,7 +2016,10 @@ UpdateVariable (
Status = EFI_OUT_OF_RESOURCES; Status = EFI_OUT_OF_RESOURCES;
goto Done; goto Done;
} }
Reclaimed = TRUE; if (Variable->CurrPtr != NULL) {
CacheVariable->CurrPtr = (VARIABLE_HEADER *)((UINTN) CacheVariable->StartPtr + ((UINTN) Variable->CurrPtr - (UINTN) Variable->StartPtr));
CacheVariable->InDeletedTransitionPtr = NULL;
}
} }
// //
// Four steps // Four steps
@ -2080,7 +2123,7 @@ UpdateVariable (
mVariableModuleGlobal->VariableGlobal.VolatileVariableBase, mVariableModuleGlobal->VariableGlobal.VolatileVariableBase,
&mVariableModuleGlobal->VolatileLastVariableOffset, &mVariableModuleGlobal->VolatileLastVariableOffset,
TRUE, TRUE,
Variable->CurrPtr, Variable,
FALSE, FALSE,
FALSE FALSE
); );
@ -2096,7 +2139,10 @@ UpdateVariable (
Status = EFI_OUT_OF_RESOURCES; Status = EFI_OUT_OF_RESOURCES;
goto Done; goto Done;
} }
Reclaimed = TRUE; if (Variable->CurrPtr != NULL) {
CacheVariable->CurrPtr = (VARIABLE_HEADER *)((UINTN) CacheVariable->StartPtr + ((UINTN) Variable->CurrPtr - (UINTN) Variable->StartPtr));
CacheVariable->InDeletedTransitionPtr = NULL;
}
} }
NextVariable->State = VAR_ADDED; NextVariable->State = VAR_ADDED;
@ -2120,7 +2166,32 @@ UpdateVariable (
// //
// Mark the old variable as deleted. // Mark the old variable as deleted.
// //
if (!Reclaimed && !EFI_ERROR (Status) && Variable->CurrPtr != NULL) { if (!EFI_ERROR (Status) && Variable->CurrPtr != NULL) {
if (Variable->InDeletedTransitionPtr != NULL) {
//
// Both ADDED and IN_DELETED_TRANSITION old variable are present,
// set IN_DELETED_TRANSITION one to DELETED state first.
//
State = Variable->InDeletedTransitionPtr->State;
State &= VAR_DELETED;
Status = UpdateVariableStore (
&mVariableModuleGlobal->VariableGlobal,
Variable->Volatile,
FALSE,
Fvb,
(UINTN) &Variable->InDeletedTransitionPtr->State,
sizeof (UINT8),
&State
);
if (!EFI_ERROR (Status)) {
if (!Variable->Volatile) {
CacheVariable->InDeletedTransitionPtr->State = State;
}
} else {
goto Done;
}
}
State = Variable->CurrPtr->State; State = Variable->CurrPtr->State;
State &= VAR_DELETED; State &= VAR_DELETED;
@ -2342,6 +2413,7 @@ VariableServiceGetNextVariableName (
VARIABLE_STORE_TYPE Type; VARIABLE_STORE_TYPE Type;
VARIABLE_POINTER_TRACK Variable; VARIABLE_POINTER_TRACK Variable;
VARIABLE_POINTER_TRACK VariableInHob; VARIABLE_POINTER_TRACK VariableInHob;
VARIABLE_POINTER_TRACK VariablePtrTrack;
UINTN VarNameSize; UINTN VarNameSize;
EFI_STATUS Status; EFI_STATUS Status;
VARIABLE_STORE_HEADER *VariableStoreHeader[VariableStoreTypeMax]; VARIABLE_STORE_HEADER *VariableStoreHeader[VariableStoreTypeMax];
@ -2415,8 +2487,27 @@ VariableServiceGetNextVariableName (
// //
// Variable is found // Variable is found
// //
if (Variable.CurrPtr->State == VAR_ADDED) { if (Variable.CurrPtr->State == VAR_ADDED || Variable.CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
if ((AtRuntime () && ((Variable.CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0)) == 0) { if (!AtRuntime () || ((Variable.CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) != 0)) {
if (Variable.CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
//
// If it is a IN_DELETED_TRANSITION variable,
// and there is also a same ADDED one at the same time,
// don't return it.
//
VariablePtrTrack.StartPtr = Variable.StartPtr;
VariablePtrTrack.EndPtr = Variable.EndPtr;
Status = FindVariableEx (
GetVariableNamePtr (Variable.CurrPtr),
&Variable.CurrPtr->VendorGuid,
FALSE,
&VariablePtrTrack
);
if (!EFI_ERROR (Status) && VariablePtrTrack.CurrPtr->State == VAR_ADDED) {
Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);
continue;
}
}
// //
// Don't return NV variable when HOB overrides it // Don't return NV variable when HOB overrides it

View File

@ -65,6 +65,13 @@ typedef enum {
typedef struct { typedef struct {
VARIABLE_HEADER *CurrPtr; VARIABLE_HEADER *CurrPtr;
//
// If both ADDED and IN_DELETED_TRANSITION variable are present,
// InDeletedTransitionPtr will point to the IN_DELETED_TRANSITION one.
// Otherwise, CurrPtr will point to the ADDED or IN_DELETED_TRANSITION one,
// and InDeletedTransitionPtr will be NULL at the same time.
//
VARIABLE_HEADER *InDeletedTransitionPtr;
VARIABLE_HEADER *EndPtr; VARIABLE_HEADER *EndPtr;
VARIABLE_HEADER *StartPtr; VARIABLE_HEADER *StartPtr;
BOOLEAN Volatile; BOOLEAN Volatile;
@ -209,7 +216,7 @@ DataSizeOfVariable (
@param[in] Attributes Attributes of the variable. @param[in] Attributes Attributes of the variable.
@param[in] KeyIndex Index of associated public key. @param[in] KeyIndex Index of associated public key.
@param[in] MonotonicCount Value of associated monotonic count. @param[in] MonotonicCount Value of associated monotonic count.
@param[in] Variable The variable information that is used to keep track of variable usage. @param[in, out] Variable The variable information that is used to keep track of variable usage.
@param[in] TimeStamp Value of associated TimeStamp. @param[in] TimeStamp Value of associated TimeStamp.
@ -226,7 +233,7 @@ UpdateVariable (
IN UINT32 Attributes OPTIONAL, IN UINT32 Attributes OPTIONAL,
IN UINT32 KeyIndex OPTIONAL, IN UINT32 KeyIndex OPTIONAL,
IN UINT64 MonotonicCount OPTIONAL, IN UINT64 MonotonicCount OPTIONAL,
IN VARIABLE_POINTER_TRACK *Variable, IN OUT VARIABLE_POINTER_TRACK *Variable,
IN EFI_TIME *TimeStamp OPTIONAL IN EFI_TIME *TimeStamp OPTIONAL
); );
@ -378,7 +385,7 @@ VariableCommonInitialize (
@param[out] LastVariableOffset Offset of last variable. @param[out] LastVariableOffset Offset of last variable.
@param[in] IsVolatile The variable store is volatile or not; @param[in] IsVolatile The variable store is volatile or not;
if it is non-volatile, need FTW. if it is non-volatile, need FTW.
@param[in] UpdatingVariable Pointer to updating variable. @param[in, out] UpdatingPtrTrack Pointer to updating variable pointer track structure.
@param[in] ReclaimPubKeyStore Reclaim for public key database or not. @param[in] ReclaimPubKeyStore Reclaim for public key database or not.
@param[in] ReclaimAnyway If TRUE, do reclaim anyway. @param[in] ReclaimAnyway If TRUE, do reclaim anyway.
@ -392,7 +399,7 @@ Reclaim (
IN EFI_PHYSICAL_ADDRESS VariableBase, IN EFI_PHYSICAL_ADDRESS VariableBase,
OUT UINTN *LastVariableOffset, OUT UINTN *LastVariableOffset,
IN BOOLEAN IsVolatile, IN BOOLEAN IsVolatile,
IN VARIABLE_HEADER *UpdatingVariable, IN OUT VARIABLE_POINTER_TRACK *UpdatingPtrTrack,
IN BOOLEAN ReclaimPubKeyStore, IN BOOLEAN ReclaimPubKeyStore,
IN BOOLEAN ReclaimAnyway IN BOOLEAN ReclaimAnyway
); );