[Description]:

The patch enhanced variable services to support:
1) If adding variable does not execute completely, the state is in_deleted, the next time find variable should have to retrieve the in_deleted variable.
2) when Reclaiming the variable storage, the 1) variable should be considered.

[Impaction]:
This is backward-compatible update.

[Reference Info]:
9552, 8632

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@4916 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
yshang1 2008-03-19 07:09:03 +00:00
parent 695f7e9856
commit 814bae5269
1 changed files with 131 additions and 41 deletions

View File

@ -574,7 +574,8 @@ EFI_STATUS
Reclaim ( 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
) )
/*++ /*++
@ -596,12 +597,18 @@ Returns:
--*/ --*/
{ {
VARIABLE_HEADER *Variable; VARIABLE_HEADER *Variable;
VARIABLE_HEADER *AddedVariable;
VARIABLE_HEADER *NextVariable; VARIABLE_HEADER *NextVariable;
VARIABLE_HEADER *NextAddedVariable;
VARIABLE_STORE_HEADER *VariableStoreHeader; VARIABLE_STORE_HEADER *VariableStoreHeader;
UINT8 *ValidBuffer; UINT8 *ValidBuffer;
UINTN ValidBufferSize; UINTN MaximumBufferSize;
UINTN VariableSize; UINTN VariableSize;
UINTN NameSize;
UINT8 *CurrPtr; UINT8 *CurrPtr;
VOID *Point0;
VOID *Point1;
BOOLEAN FoundAdded;
EFI_STATUS Status; EFI_STATUS Status;
VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINTN) VariableBase); VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINTN) VariableBase);
@ -609,39 +616,47 @@ Returns:
// //
// Start Pointers for the variable. // Start Pointers for the variable.
// //
Variable = GetStartPointer (VariableStoreHeader); Variable = GetStartPointer (VariableStoreHeader);
ValidBufferSize = sizeof (VARIABLE_STORE_HEADER); MaximumBufferSize = sizeof (VARIABLE_STORE_HEADER);
while (IsValidVariableHeader (Variable)) { while (IsValidVariableHeader (Variable)) {
NextVariable = GetNextVariablePtr (Variable); NextVariable = GetNextVariablePtr (Variable);
if (Variable->State == VAR_ADDED) { if (Variable->State == VAR_ADDED ||
Variable->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)
) {
VariableSize = (UINTN) NextVariable - (UINTN) Variable; VariableSize = (UINTN) NextVariable - (UINTN) Variable;
ValidBufferSize += VariableSize; MaximumBufferSize += VariableSize;
} }
Variable = NextVariable; Variable = NextVariable;
} }
ValidBuffer = AllocatePool (ValidBufferSize); //
// Reserve the 1 Bytes with Oxff to identify the
// end of the variable buffer.
//
MaximumBufferSize += 1;
ValidBuffer = AllocatePool (MaximumBufferSize);
if (ValidBuffer == NULL) { if (ValidBuffer == NULL) {
return EFI_OUT_OF_RESOURCES; return EFI_OUT_OF_RESOURCES;
} }
SetMem (ValidBuffer, ValidBufferSize, 0xff); SetMem (ValidBuffer, MaximumBufferSize, 0xff);
CurrPtr = ValidBuffer;
// //
// Copy variable store header // Copy variable store header
// //
CopyMem (CurrPtr, VariableStoreHeader, sizeof (VARIABLE_STORE_HEADER)); CopyMem (ValidBuffer, VariableStoreHeader, sizeof (VARIABLE_STORE_HEADER));
CurrPtr = (UINT8 *) GetStartPointer ((VARIABLE_STORE_HEADER *) CurrPtr); CurrPtr = (UINT8 *) GetStartPointer ((VARIABLE_STORE_HEADER *) ValidBuffer);
// //
// Start Pointers for the variable. // Start Pointers for the variable.
// //
Variable = GetStartPointer (VariableStoreHeader);
//
// Reinstall all ADDED variables
//
Variable = GetStartPointer (VariableStoreHeader);
while (IsValidVariableHeader (Variable)) { while (IsValidVariableHeader (Variable)) {
NextVariable = GetNextVariablePtr (Variable); NextVariable = GetNextVariablePtr (Variable);
if (Variable->State == VAR_ADDED) { if (Variable->State == VAR_ADDED) {
@ -652,14 +667,61 @@ Returns:
Variable = NextVariable; Variable = NextVariable;
} }
//
// Reinstall all in delete transition variables
//
Variable = GetStartPointer (VariableStoreHeader);
while (IsValidVariableHeader (Variable)) {
NextVariable = GetNextVariablePtr (Variable);
if (Variable->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
//
// Buffer has cached all ADDED variable.
// Per IN_DELETED variable, we have to guarantee that
// no ADDED one in previous buffer.
//
FoundAdded = FALSE;
AddedVariable = GetStartPointer ((VARIABLE_STORE_HEADER *) ValidBuffer);
while (IsValidVariableHeader (AddedVariable)) {
NextAddedVariable = GetNextVariablePtr (AddedVariable);
NameSize = NameSizeOfVariable (AddedVariable);
if (CompareGuid (&AddedVariable->VendorGuid, &Variable->VendorGuid) &&
NameSize == NameSizeOfVariable (Variable)
) {
Point0 = (VOID *) GetVariableNamePtr (AddedVariable);
Point1 = (VOID *) GetVariableNamePtr (Variable);
if (!CompareMem (
Point0,
Point1,
NameSizeOfVariable (AddedVariable)
)
) {
FoundAdded = TRUE;
break;
}
}
AddedVariable = NextAddedVariable;
}
if (!FoundAdded) {
VariableSize = (UINTN) NextVariable - (UINTN) Variable;
CopyMem (CurrPtr, (UINT8 *) Variable, VariableSize);
if (Variable != UpdatingVariable) {
((VARIABLE_HEADER *) CurrPtr)->State = VAR_ADDED;
}
CurrPtr += VariableSize;
}
}
Variable = NextVariable;
}
if (IsVolatile) { if (IsVolatile) {
// //
// If volatile variable store, just copy valid buffer // If volatile variable store, just copy valid buffer
// //
SetMem ((UINT8 *) (UINTN) VariableBase, VariableStoreHeader->Size, 0xff); SetMem ((UINT8 *) (UINTN) VariableBase, VariableStoreHeader->Size, 0xff);
CopyMem ((UINT8 *) (UINTN) VariableBase, ValidBuffer, ValidBufferSize); CopyMem ((UINT8 *) (UINTN) VariableBase, ValidBuffer, (UINTN) (CurrPtr - (UINT8 *) ValidBuffer));
*LastVariableOffset = ValidBufferSize;
Status = EFI_SUCCESS; Status = EFI_SUCCESS;
} else { } else {
// //
@ -668,19 +730,17 @@ Returns:
Status = FtwVariableSpace ( Status = FtwVariableSpace (
VariableBase, VariableBase,
ValidBuffer, ValidBuffer,
ValidBufferSize (UINTN) (CurrPtr - (UINT8 *) ValidBuffer)
); );
if (!EFI_ERROR (Status)) { }
*LastVariableOffset = ValidBufferSize; if (!EFI_ERROR (Status)) {
} *LastVariableOffset = (UINTN) (CurrPtr - (UINT8 *) ValidBuffer);
} else {
*LastVariableOffset = 0;
} }
FreePool (ValidBuffer); FreePool (ValidBuffer);
if (EFI_ERROR (Status)) {
*LastVariableOffset = 0;
}
return Status; return Status;
} }
@ -838,10 +898,12 @@ Returns:
--*/ --*/
{ {
VARIABLE_HEADER *Variable[2]; VARIABLE_HEADER *Variable[2];
VARIABLE_STORE_HEADER *VariableStoreHeader[2]; VARIABLE_HEADER *InDeletedVariable;
UINTN Index; VARIABLE_STORE_HEADER *VariableStoreHeader[2];
VOID *Point; UINTN InDeletedStorageIndex;
UINTN Index;
VOID *Point;
// //
// 0: Volatile, 1: Non-Volatile // 0: Volatile, 1: Non-Volatile
@ -861,29 +923,47 @@ Returns:
if (VariableName[0] != 0 && VendorGuid == NULL) { if (VariableName[0] != 0 && VendorGuid == NULL) {
return EFI_INVALID_PARAMETER; return EFI_INVALID_PARAMETER;
} }
// //
// Find the variable by walk through volatile and then non-volatile variable store // Find the variable by walk through volatile and then non-volatile variable store
// //
InDeletedVariable = NULL;
InDeletedStorageIndex = 0;
for (Index = 0; Index < 2; Index++) { for (Index = 0; Index < 2; Index++) {
PtrTrack->StartPtr = GetStartPointer (VariableStoreHeader[Index]);
PtrTrack->EndPtr = GetEndPointer (VariableStoreHeader[Index]);
while (IsValidVariableHeader (Variable[Index]) && (Variable[Index] <= GetEndPointer (VariableStoreHeader[Index]))) { while (IsValidVariableHeader (Variable[Index]) && (Variable[Index] <= GetEndPointer (VariableStoreHeader[Index]))) {
if (Variable[Index]->State == VAR_ADDED) { if (Variable[Index]->State == VAR_ADDED ||
Variable[Index]->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)
) {
if (!EfiAtRuntime () || (Variable[Index]->Attributes & EFI_VARIABLE_RUNTIME_ACCESS)) { if (!EfiAtRuntime () || (Variable[Index]->Attributes & EFI_VARIABLE_RUNTIME_ACCESS)) {
if (VariableName[0] == 0) { if (VariableName[0] == 0) {
PtrTrack->CurrPtr = Variable[Index]; if (Variable[Index]->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
PtrTrack->Volatile = (BOOLEAN)(Index == 0); InDeletedVariable = Variable[Index];
return EFI_SUCCESS; InDeletedStorageIndex = Index;
} else {
PtrTrack->StartPtr = GetStartPointer (VariableStoreHeader[Index]);
PtrTrack->EndPtr = GetEndPointer (VariableStoreHeader[Index]);
PtrTrack->CurrPtr = Variable[Index];
PtrTrack->Volatile = (BOOLEAN)(Index == 0);
return EFI_SUCCESS;
}
} else { } else {
if (CompareGuid (VendorGuid, &Variable[Index]->VendorGuid)) { if (CompareGuid (VendorGuid, &Variable[Index]->VendorGuid)) {
Point = (VOID *) GetVariableNamePtr (Variable[Index]); Point = (VOID *) GetVariableNamePtr (Variable[Index]);
ASSERT (NameSizeOfVariable (Variable[Index]) != 0); ASSERT (NameSizeOfVariable (Variable[Index]) != 0);
if (!CompareMem (VariableName, Point, NameSizeOfVariable (Variable[Index]))) { if (!CompareMem (VariableName, Point, NameSizeOfVariable (Variable[Index]))) {
PtrTrack->CurrPtr = Variable[Index]; if (Variable[Index]->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
PtrTrack->Volatile = (BOOLEAN)(Index == 0); InDeletedVariable = Variable[Index];
return EFI_SUCCESS; InDeletedStorageIndex = Index;
} else {
PtrTrack->StartPtr = GetStartPointer (VariableStoreHeader[Index]);
PtrTrack->EndPtr = GetEndPointer (VariableStoreHeader[Index]);
PtrTrack->CurrPtr = Variable[Index];
PtrTrack->Volatile = (BOOLEAN)(Index == 0);
return EFI_SUCCESS;
}
} }
} }
} }
@ -892,6 +972,13 @@ Returns:
Variable[Index] = GetNextVariablePtr (Variable[Index]); Variable[Index] = GetNextVariablePtr (Variable[Index]);
} }
if (InDeletedVariable != NULL) {
PtrTrack->StartPtr = GetStartPointer (VariableStoreHeader[InDeletedStorageIndex]);
PtrTrack->EndPtr = GetEndPointer (VariableStoreHeader[InDeletedStorageIndex]);
PtrTrack->CurrPtr = InDeletedVariable;
PtrTrack->Volatile = (BOOLEAN)(InDeletedStorageIndex == 0);
return EFI_SUCCESS;
}
} }
PtrTrack->CurrPtr = NULL; PtrTrack->CurrPtr = NULL;
return EFI_NOT_FOUND; return EFI_NOT_FOUND;
@ -1279,6 +1366,7 @@ RuntimeServiceSetVariable (
goto Done; goto Done;
} else if ((Variable.CurrPtr->State == VAR_ADDED) || } else if ((Variable.CurrPtr->State == VAR_ADDED) ||
(Variable.CurrPtr->State == (VAR_ADDED & VAR_IN_DELETED_TRANSITION))) { (Variable.CurrPtr->State == (VAR_ADDED & VAR_IN_DELETED_TRANSITION))) {
// //
// Mark the old variable as in delete transition // Mark the old variable as in delete transition
// //
@ -1388,7 +1476,7 @@ RuntimeServiceSetVariable (
// //
// Perform garbage collection & reclaim operation // Perform garbage collection & reclaim operation
// //
Status = Reclaim (mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase, NonVolatileOffset, FALSE); Status = Reclaim (mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase, NonVolatileOffset, FALSE, Variable.CurrPtr);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
goto Done; goto Done;
} }
@ -1492,7 +1580,7 @@ RuntimeServiceSetVariable (
// //
// Perform garbage collection & reclaim operation // Perform garbage collection & reclaim operation
// //
Status = Reclaim (mVariableModuleGlobal->VariableGlobal.VolatileVariableBase, VolatileOffset, TRUE); Status = Reclaim (mVariableModuleGlobal->VariableGlobal.VolatileVariableBase, VolatileOffset, TRUE, Variable.CurrPtr);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
goto Done; goto Done;
} }
@ -1723,7 +1811,8 @@ ReclaimForOS(
Status = Reclaim ( Status = Reclaim (
mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase, mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase,
&mVariableModuleGlobal->NonVolatileLastVariableOffset, &mVariableModuleGlobal->NonVolatileLastVariableOffset,
FALSE FALSE,
NULL
); );
ASSERT_EFI_ERROR (Status); ASSERT_EFI_ERROR (Status);
} }
@ -1912,7 +2001,8 @@ Returns:
Status = Reclaim ( Status = Reclaim (
mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase, mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase,
&mVariableModuleGlobal->NonVolatileLastVariableOffset, &mVariableModuleGlobal->NonVolatileLastVariableOffset,
FALSE FALSE,
NULL
); );
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {