summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvanjeff <vanjeff@6f19259b-4bc3-4df7-8a09-765794883524>2013-05-09 06:13:30 +0000
committervanjeff <vanjeff@6f19259b-4bc3-4df7-8a09-765794883524>2013-05-09 06:13:30 +0000
commit62d69074e0d17589f92b1fd9aaac8f8a18a46019 (patch)
treee87a7cc5b590d48540accb0b0e86cefdd6c07d9f
parentf812c2259ac27f26f29c7e11a9acbacb45ceb386 (diff)
downloadedk2-62d69074e0d17589f92b1fd9aaac8f8a18a46019.zip
edk2-62d69074e0d17589f92b1fd9aaac8f8a18a46019.tar.gz
edk2-62d69074e0d17589f92b1fd9aaac8f8a18a46019.tar.bz2
Sync patches r13975, r14029, r14041, r14065, r14084, r14086 and r14139 from main trunk.
1. Move the declaration of gEfiCertDbGuid to the package's Include folder. 2. Don't assume that flush the HOB variable to flash must be successful. 3. When no DELETED variable found, no variable space could be reclaimed, so just give some debug info and return EFI_SUCCESS. 4. Fix a bug that the invalid public key will never be removed from public key database. 5. a. 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. b. 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. c. Update VariableServiceGetNextVariableName() to return the valid IN_DELETED_TRANSITION variable if only IN_DELETED_TRANSITION variable is present. 6. Check for NULL pointer before dereference it. 7. Add error handling code to prevent variable store corruption in release build. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/branches/UDK2010.SR1@14333 6f19259b-4bc3-4df7-8a09-765794883524
-rw-r--r--MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c270
-rw-r--r--MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.h26
-rw-r--r--MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c3
-rw-r--r--SecurityPkg/Include/Guid/AuthenticatedVariableFormat.h1
-rw-r--r--SecurityPkg/VariableAuthenticated/RuntimeDxe/AuthService.c51
-rw-r--r--SecurityPkg/VariableAuthenticated/RuntimeDxe/AuthService.h2
-rw-r--r--SecurityPkg/VariableAuthenticated/RuntimeDxe/Variable.c692
-rw-r--r--SecurityPkg/VariableAuthenticated/RuntimeDxe/Variable.h58
8 files changed, 903 insertions, 200 deletions
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c b/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c
index 46e81a0..cd3f5ef 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c
@@ -3,7 +3,7 @@
The common variable operation routines shared by DXE_RUNTIME variable
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
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
@@ -504,7 +504,8 @@ GetEndPointer (
@param LastVariableOffset Offset of last variable.
@param IsVolatile The variable store is volatile or not;
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.
@return EFI_OUT_OF_RESOURCES
@return EFI_SUCCESS
@@ -516,7 +517,8 @@ Reclaim (
IN EFI_PHYSICAL_ADDRESS VariableBase,
OUT UINTN *LastVariableOffset,
IN BOOLEAN IsVolatile,
- IN VARIABLE_HEADER *UpdatingVariable
+ IN OUT VARIABLE_POINTER_TRACK *UpdatingPtrTrack,
+ IN BOOLEAN ReclaimAnyway
)
{
VARIABLE_HEADER *Variable;
@@ -539,7 +541,15 @@ Reclaim (
CHAR16 *UpdatingVariableNamePtr;
UINTN CommonVariableTotalSize;
UINTN HwErrVariableTotalSize;
+ BOOLEAN NeedDoReclaim;
+ VARIABLE_HEADER *UpdatingVariable;
+ UpdatingVariable = NULL;
+ if (UpdatingPtrTrack != NULL) {
+ UpdatingVariable = UpdatingPtrTrack->CurrPtr;
+ }
+
+ NeedDoReclaim = FALSE;
VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINTN) VariableBase);
CommonVariableTotalSize = 0;
@@ -558,11 +568,18 @@ Reclaim (
) {
VariableSize = (UINTN) NextVariable - (UINTN) Variable;
MaximumBufferSize += VariableSize;
+ } else {
+ NeedDoReclaim = TRUE;
}
Variable = NextVariable;
}
+ if (!ReclaimAnyway && !NeedDoReclaim) {
+ DEBUG ((EFI_D_INFO, "Variable driver: no DELETED variable found, so no variable space could be reclaimed.\n"));
+ return EFI_SUCCESS;
+ }
+
//
// Reserve the 1 Bytes with Oxff to identify the
// end of the variable buffer.
@@ -624,6 +641,8 @@ Reclaim (
if (UpdatingVariable != NULL) {
VariableSize = (UINTN)(GetNextVariablePtr (UpdatingVariable)) - (UINTN)UpdatingVariable;
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;
if ((!IsVolatile) && ((UpdatingVariable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {
HwErrVariableTotalSize += VariableSize;
@@ -656,7 +675,7 @@ Reclaim (
) {
Point0 = (VOID *) GetVariableNamePtr (AddedVariable);
Point1 = (VOID *) GetVariableNamePtr (Variable);
- if (CompareMem (Point0, Point1, NameSizeOfVariable (AddedVariable)) == 0) {
+ if (CompareMem (Point0, Point1, NameSize) == 0) {
FoundAdded = TRUE;
break;
}
@@ -749,6 +768,8 @@ FindVariableEx (
VARIABLE_HEADER *InDeletedVariable;
VOID *Point;
+ PtrTrack->InDeletedTransitionPtr = NULL;
+
//
// Find the variable by walk through HOB, volatile and non-volatile variable store.
//
@@ -766,6 +787,7 @@ FindVariableEx (
if (PtrTrack->CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
InDeletedVariable = PtrTrack->CurrPtr;
} else {
+ PtrTrack->InDeletedTransitionPtr = InDeletedVariable;
return EFI_SUCCESS;
}
} else {
@@ -777,6 +799,7 @@ FindVariableEx (
if (PtrTrack->CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
InDeletedVariable = PtrTrack->CurrPtr;
} else {
+ PtrTrack->InDeletedTransitionPtr = InDeletedVariable;
return EFI_SUCCESS;
}
}
@@ -1309,7 +1332,7 @@ AutoUpdateLangVariable (
//
// 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,
ISO_639_2_ENTRY_SIZE + 1, Attributes, &Variable);
@@ -1364,7 +1387,7 @@ AutoUpdateLangVariable (
@param[in] Data Variable data.
@param[in] DataSize Size of data. 0 means delete.
@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_OUT_OF_RESOURCES Variable region is full, can not write other data into this region.
@@ -1377,7 +1400,7 @@ UpdateVariable (
IN VOID *Data,
IN UINTN DataSize,
IN UINT32 Attributes OPTIONAL,
- IN VARIABLE_POINTER_TRACK *CacheVariable
+ IN OUT VARIABLE_POINTER_TRACK *CacheVariable
)
{
EFI_STATUS Status;
@@ -1391,7 +1414,6 @@ UpdateVariable (
BOOLEAN Volatile;
EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;
UINT8 State;
- BOOLEAN Reclaimed;
VARIABLE_POINTER_TRACK *Variable;
VARIABLE_POINTER_TRACK NvVariable;
VARIABLE_STORE_HEADER *VariableStoreHeader;
@@ -1418,11 +1440,15 @@ UpdateVariable (
Variable->StartPtr = GetStartPointer (VariableStoreHeader);
Variable->EndPtr = GetEndPointer (VariableStoreHeader);
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;
}
Fvb = mVariableModuleGlobal->FvbInstance;
- Reclaimed = FALSE;
if (Variable->CurrPtr != NULL) {
//
@@ -1452,6 +1478,32 @@ UpdateVariable (
// causes it to be deleted.
//
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) {
+ ASSERT (CacheVariable->InDeletedTransitionPtr != NULL);
+ CacheVariable->InDeletedTransitionPtr->State = State;
+ }
+ } else {
+ goto Done;
+ }
+ }
+
State = Variable->CurrPtr->State;
State &= VAR_DELETED;
@@ -1468,6 +1520,7 @@ UpdateVariable (
UpdateVariableInfo (VariableName, VendorGuid, Variable->Volatile, FALSE, FALSE, TRUE, FALSE);
if (!Variable->Volatile) {
CacheVariable->CurrPtr->State = State;
+ FlushHobVariableToFlash (VariableName, VendorGuid);
}
}
goto Done;
@@ -1595,7 +1648,7 @@ UpdateVariable (
// Perform garbage collection & reclaim operation.
//
Status = Reclaim (mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase,
- &mVariableModuleGlobal->NonVolatileLastVariableOffset, FALSE, Variable->CurrPtr);
+ &mVariableModuleGlobal->NonVolatileLastVariableOffset, FALSE, Variable, FALSE);
if (EFI_ERROR (Status)) {
goto Done;
}
@@ -1609,7 +1662,10 @@ UpdateVariable (
Status = EFI_OUT_OF_RESOURCES;
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
@@ -1710,7 +1766,7 @@ UpdateVariable (
// Perform garbage collection & reclaim operation.
//
Status = Reclaim (mVariableModuleGlobal->VariableGlobal.VolatileVariableBase,
- &mVariableModuleGlobal->VolatileLastVariableOffset, TRUE, Variable->CurrPtr);
+ &mVariableModuleGlobal->VolatileLastVariableOffset, TRUE, Variable, FALSE);
if (EFI_ERROR (Status)) {
goto Done;
}
@@ -1723,7 +1779,10 @@ UpdateVariable (
Status = EFI_OUT_OF_RESOURCES;
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;
@@ -1747,7 +1806,33 @@ UpdateVariable (
//
// 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) {
+ ASSERT (CacheVariable->InDeletedTransitionPtr != NULL);
+ CacheVariable->InDeletedTransitionPtr->State = State;
+ }
+ } else {
+ goto Done;
+ }
+ }
+
State = Variable->CurrPtr->State;
State &= VAR_DELETED;
@@ -1767,6 +1852,9 @@ UpdateVariable (
if (!EFI_ERROR (Status)) {
UpdateVariableInfo (VariableName, VendorGuid, Volatile, FALSE, TRUE, FALSE, FALSE);
+ if (!Volatile) {
+ FlushHobVariableToFlash (VariableName, VendorGuid);
+ }
}
Done:
@@ -1932,6 +2020,7 @@ VariableServiceGetNextVariableName (
VARIABLE_STORE_TYPE Type;
VARIABLE_POINTER_TRACK Variable;
VARIABLE_POINTER_TRACK VariableInHob;
+ VARIABLE_POINTER_TRACK VariablePtrTrack;
UINTN VarNameSize;
EFI_STATUS Status;
VARIABLE_STORE_HEADER *VariableStoreHeader[VariableStoreTypeMax];
@@ -2005,8 +2094,27 @@ VariableServiceGetNextVariableName (
//
// Variable is found
//
- if (Variable.CurrPtr->State == VAR_ADDED) {
- if ((AtRuntime () && ((Variable.CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0)) == 0) {
+ 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)) {
+ 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
@@ -2388,12 +2496,102 @@ ReclaimForOS(
mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase,
&mVariableModuleGlobal->NonVolatileLastVariableOffset,
FALSE,
- NULL
+ NULL,
+ FALSE
);
ASSERT_EFI_ERROR (Status);
}
}
+/**
+ Flush the HOB variable to flash.
+
+ @param[in] VariableName Name of variable has been updated or deleted.
+ @param[in] VendorGuid Guid of variable has been updated or deleted.
+
+**/
+VOID
+FlushHobVariableToFlash (
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid
+ )
+{
+ EFI_STATUS Status;
+ VARIABLE_STORE_HEADER *VariableStoreHeader;
+ VARIABLE_HEADER *Variable;
+ VOID *VariableData;
+ BOOLEAN ErrorFlag;
+
+ ErrorFlag = FALSE;
+
+ //
+ // Flush the HOB variable to flash.
+ //
+ if (mVariableModuleGlobal->VariableGlobal.HobVariableBase != 0) {
+ VariableStoreHeader = (VARIABLE_STORE_HEADER *) (UINTN) mVariableModuleGlobal->VariableGlobal.HobVariableBase;
+ //
+ // Set HobVariableBase to 0, it can avoid SetVariable to call back.
+ //
+ mVariableModuleGlobal->VariableGlobal.HobVariableBase = 0;
+ for ( Variable = GetStartPointer (VariableStoreHeader)
+ ; (Variable < GetEndPointer (VariableStoreHeader) && IsValidVariableHeader (Variable))
+ ; Variable = GetNextVariablePtr (Variable)
+ ) {
+ if (Variable->State != VAR_ADDED) {
+ //
+ // The HOB variable has been set to DELETED state in local.
+ //
+ continue;
+ }
+ ASSERT ((Variable->Attributes & EFI_VARIABLE_NON_VOLATILE) != 0);
+ if (VendorGuid == NULL || VariableName == NULL ||
+ !CompareGuid (VendorGuid, &Variable->VendorGuid) ||
+ StrCmp (VariableName, GetVariableNamePtr (Variable)) != 0) {
+ VariableData = GetVariableDataPtr (Variable);
+ Status = VariableServiceSetVariable (
+ GetVariableNamePtr (Variable),
+ &Variable->VendorGuid,
+ Variable->Attributes,
+ Variable->DataSize,
+ VariableData
+ );
+ DEBUG ((EFI_D_INFO, "Variable driver flush the HOB variable to flash: %g %s %r\n", &Variable->VendorGuid, GetVariableNamePtr (Variable), Status));
+ } else {
+ //
+ // The updated or deleted variable is matched with the HOB variable.
+ // Don't break here because we will try to set other HOB variables
+ // since this variable could be set successfully.
+ //
+ Status = EFI_SUCCESS;
+ }
+ if (!EFI_ERROR (Status)) {
+ //
+ // If set variable successful, or the updated or deleted variable is matched with the HOB variable,
+ // set the HOB variable to DELETED state in local.
+ //
+ DEBUG ((EFI_D_INFO, "Variable driver set the HOB variable to DELETED state in local: %g %s\n", &Variable->VendorGuid, GetVariableNamePtr (Variable)));
+ Variable->State &= VAR_DELETED;
+ } else {
+ ErrorFlag = TRUE;
+ }
+ }
+ if (ErrorFlag) {
+ //
+ // We still have HOB variable(s) not flushed in flash.
+ //
+ mVariableModuleGlobal->VariableGlobal.HobVariableBase = (EFI_PHYSICAL_ADDRESS) (UINTN) VariableStoreHeader;
+ } else {
+ //
+ // All HOB variables have been flushed in flash.
+ //
+ DEBUG ((EFI_D_INFO, "Variable driver: all HOB variables have been flushed in flash.\n"));
+ if (!AtRuntime ()) {
+ FreePool ((VOID *) VariableStoreHeader);
+ }
+ }
+ }
+
+}
/**
Initializes variable write service after FVB was ready.
@@ -2412,8 +2610,6 @@ VariableWriteServiceInitialize (
UINTN Index;
UINT8 Data;
EFI_PHYSICAL_ADDRESS VariableStoreBase;
- VARIABLE_HEADER *Variable;
- VOID *VariableData;
VariableStoreBase = mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase;
VariableStoreHeader = (VARIABLE_STORE_HEADER *)(UINTN)VariableStoreBase;
@@ -2431,7 +2627,8 @@ VariableWriteServiceInitialize (
mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase,
&mVariableModuleGlobal->NonVolatileLastVariableOffset,
FALSE,
- NULL
+ NULL,
+ TRUE
);
if (EFI_ERROR (Status)) {
return Status;
@@ -2440,33 +2637,8 @@ VariableWriteServiceInitialize (
}
}
- //
- // Flush the HOB variable to flash and invalidate HOB variable.
- //
- if (mVariableModuleGlobal->VariableGlobal.HobVariableBase != 0) {
- //
- // Clear the HobVariableBase to avoid SetVariable() updating the variable in HOB
- //
- VariableStoreHeader = (VARIABLE_STORE_HEADER *) (UINTN) mVariableModuleGlobal->VariableGlobal.HobVariableBase;
- mVariableModuleGlobal->VariableGlobal.HobVariableBase = 0;
+ FlushHobVariableToFlash (NULL, NULL);
- for ( Variable = GetStartPointer (VariableStoreHeader)
- ; (Variable < GetEndPointer (VariableStoreHeader) && IsValidVariableHeader (Variable))
- ; Variable = GetNextVariablePtr (Variable)
- ) {
- ASSERT (Variable->State == VAR_ADDED);
- ASSERT ((Variable->Attributes & EFI_VARIABLE_NON_VOLATILE) != 0);
- VariableData = GetVariableDataPtr (Variable);
- Status = VariableServiceSetVariable (
- GetVariableNamePtr (Variable),
- &Variable->VendorGuid,
- Variable->Attributes,
- Variable->DataSize,
- VariableData
- );
- ASSERT_EFI_ERROR (Status);
- }
- }
return EFI_SUCCESS;
}
@@ -2518,8 +2690,12 @@ VariableCommonInitialize (
GuidHob = GetFirstGuidHob (&gEfiVariableGuid);
if (GuidHob != NULL) {
VariableStoreHeader = GET_GUID_HOB_DATA (GuidHob);
+ VariableStoreLength = (UINT64) (GuidHob->Header.HobLength - sizeof (EFI_HOB_GUID_TYPE));
if (GetVariableStoreStatus (VariableStoreHeader) == EfiValid) {
- mVariableModuleGlobal->VariableGlobal.HobVariableBase = (EFI_PHYSICAL_ADDRESS) (UINTN) VariableStoreHeader;
+ mVariableModuleGlobal->VariableGlobal.HobVariableBase = (EFI_PHYSICAL_ADDRESS) (UINTN) AllocateRuntimeCopyPool ((UINTN) VariableStoreLength, (VOID *) VariableStoreHeader);
+ if (mVariableModuleGlobal->VariableGlobal.HobVariableBase == 0) {
+ return EFI_OUT_OF_RESOURCES;
+ }
} else {
DEBUG ((EFI_D_ERROR, "HOB Variable Store header is corrupted!\n"));
}
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.h b/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.h
index c4a16e6..8504ce0 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.h
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.h
@@ -3,7 +3,7 @@
The internal header file includes the common header files, defines
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
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
@@ -56,6 +56,13 @@ typedef enum {
typedef struct {
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 *StartPtr;
BOOLEAN Volatile;
@@ -91,6 +98,19 @@ typedef struct {
} VARIABLE_CACHE_ENTRY;
/**
+ Flush the HOB variable to flash.
+
+ @param[in] VariableName Name of variable has been updated or deleted.
+ @param[in] VendorGuid Guid of variable has been updated or deleted.
+
+**/
+VOID
+FlushHobVariableToFlash (
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid
+ );
+
+/**
Writes a buffer to variable storage space, in the working block.
This function writes a buffer to variable storage space into a firmware
@@ -128,7 +148,7 @@ FtwVariableSpace (
@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.
@@ -142,7 +162,7 @@ UpdateVariable (
IN VOID *Data,
IN UINTN DataSize,
IN UINT32 Attributes OPTIONAL,
- IN VARIABLE_POINTER_TRACK *Variable
+ IN OUT VARIABLE_POINTER_TRACK *Variable
);
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c
index 3b6efac..ba4d29a 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c
@@ -3,7 +3,7 @@
Implement all four UEFI Runtime Variable services for the nonvolatile
and volatile storage space and install variable architecture protocol.
-Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
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
@@ -231,6 +231,7 @@ VariableClassAddressChangeEvent (
EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->PlatformLang);
EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase);
EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->VariableGlobal.VolatileVariableBase);
+ EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->VariableGlobal.HobVariableBase);
EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal);
EfiConvertPointer (0x0, (VOID **) &mNvVariableCache);
}
diff --git a/SecurityPkg/Include/Guid/AuthenticatedVariableFormat.h b/SecurityPkg/Include/Guid/AuthenticatedVariableFormat.h
index 4642040..965b12b 100644
--- a/SecurityPkg/Include/Guid/AuthenticatedVariableFormat.h
+++ b/SecurityPkg/Include/Guid/AuthenticatedVariableFormat.h
@@ -27,6 +27,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
extern EFI_GUID gEfiAuthenticatedVariableGuid;
extern EFI_GUID gEfiSecureBootEnableDisableGuid;
+extern EFI_GUID gEfiCertDbGuid;
///
/// "SecureBootEnable" variable for the Secure Boot feature enable/disable.
diff --git a/SecurityPkg/VariableAuthenticated/RuntimeDxe/AuthService.c b/SecurityPkg/VariableAuthenticated/RuntimeDxe/AuthService.c
index 1d953da..440ede9 100644
--- a/SecurityPkg/VariableAuthenticated/RuntimeDxe/AuthService.c
+++ b/SecurityPkg/VariableAuthenticated/RuntimeDxe/AuthService.c
@@ -15,7 +15,7 @@
They will do basic validation for authentication data structure, then call crypto library
to verify the signature.
-Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2009 - 2013, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
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
@@ -430,6 +430,8 @@ AddPubKeyInStore (
UINT32 Index;
VARIABLE_POINTER_TRACK Variable;
UINT8 *Ptr;
+ UINT8 *Data;
+ UINTN DataSize;
if (PubKey == NULL) {
return 0;
@@ -443,6 +445,10 @@ AddPubKeyInStore (
FALSE
);
ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR (Status)) {
+ return 0;
+ }
+
//
// Check whether the public key entry does exist.
//
@@ -461,9 +467,48 @@ AddPubKeyInStore (
//
if (mPubKeyNumber == MAX_KEY_NUM) {
//
- // Notes: Database is full, need enhancement here, currently just return 0.
+ // Public key dadatase is full, try to reclaim invalid key.
//
- return 0;
+ if (AtRuntime ()) {
+ //
+ // NV storage can't reclaim at runtime.
+ //
+ return 0;
+ }
+
+ Status = Reclaim (
+ mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase,
+ &mVariableModuleGlobal->NonVolatileLastVariableOffset,
+ FALSE,
+ NULL,
+ TRUE,
+ TRUE
+ );
+ if (EFI_ERROR (Status)) {
+ return 0;
+ }
+
+ Status = FindVariable (
+ AUTHVAR_KEYDB_NAME,
+ &gEfiAuthenticatedVariableGuid,
+ &Variable,
+ &mVariableModuleGlobal->VariableGlobal,
+ FALSE
+ );
+ ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR (Status)) {
+ return 0;
+ }
+
+ DataSize = DataSizeOfVariable (Variable.CurrPtr);
+ Data = GetVariableDataPtr (Variable.CurrPtr);
+ ASSERT ((DataSize != 0) && (Data != NULL));
+ CopyMem (mPubKeyStore, (UINT8 *) Data, DataSize);
+ mPubKeyNumber = (UINT32) (DataSize / EFI_CERT_TYPE_RSA2048_SIZE);
+
+ if (mPubKeyNumber == MAX_KEY_NUM) {
+ return 0;
+ }
}
CopyMem (mPubKeyStore + mPubKeyNumber * EFI_CERT_TYPE_RSA2048_SIZE, PubKey, EFI_CERT_TYPE_RSA2048_SIZE);
diff --git a/SecurityPkg/VariableAuthenticated/RuntimeDxe/AuthService.h b/SecurityPkg/VariableAuthenticated/RuntimeDxe/AuthService.h
index abb8d7f..1fd687b 100644
--- a/SecurityPkg/VariableAuthenticated/RuntimeDxe/AuthService.h
+++ b/SecurityPkg/VariableAuthenticated/RuntimeDxe/AuthService.h
@@ -51,8 +51,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#define EFI_CERT_DB_NAME L"certdb"
#define MAX_CERTDB_SIZE (FixedPcdGet32 (PcdMaxVariableSize) - sizeof (VARIABLE_HEADER) - sizeof (EFI_CERT_DB_NAME))
-extern EFI_GUID gEfiCertDbGuid;
-
///
/// Struct to record signature requirement defined by UEFI spec.
/// For SigHeaderSize and SigDataSize, ((UINT32) ~0) means NO exact length requirement for this field.
diff --git a/SecurityPkg/VariableAuthenticated/RuntimeDxe/Variable.c b/SecurityPkg/VariableAuthenticated/RuntimeDxe/Variable.c
index 32138c1..f10d8f7 100644
--- a/SecurityPkg/VariableAuthenticated/RuntimeDxe/Variable.c
+++ b/SecurityPkg/VariableAuthenticated/RuntimeDxe/Variable.c
@@ -16,7 +16,7 @@
VariableServiceSetVariable() should also check authenticate data to avoid buffer overflow,
integer overflow. It should also check attribute to avoid authentication bypass.
-Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2009 - 2013, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
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
@@ -511,28 +511,168 @@ GetEndPointer (
return (VARIABLE_HEADER *) HEADER_ALIGN ((UINTN) VarStoreHeader + VarStoreHeader->Size);
}
+/**
+
+ Check the PubKeyIndex is a valid key or not.
+
+ This function will iterate the NV storage to see if this PubKeyIndex is still referenced
+ by any valid count-based auth variabe.
+
+ @param[in] PubKeyIndex Index of the public key in public key store.
+
+ @retval TRUE The PubKeyIndex is still in use.
+ @retval FALSE The PubKeyIndex is not referenced by any count-based auth variabe.
+
+**/
+BOOLEAN
+IsValidPubKeyIndex (
+ IN UINT32 PubKeyIndex
+ )
+{
+ VARIABLE_HEADER *Variable;
+
+ if (PubKeyIndex > mPubKeyNumber) {
+ return FALSE;
+ }
+
+ Variable = GetStartPointer (mNvVariableCache);
+
+ while (IsValidVariableHeader (Variable)) {
+ if ((Variable->State == VAR_ADDED || Variable->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) &&
+ Variable->PubKeyIndex == PubKeyIndex) {
+ return TRUE;
+ }
+ Variable = GetNextVariablePtr (Variable);
+ }
+
+ return FALSE;
+}
/**
- Variable store garbage collection and reclaim operation.
+ Get the number of valid public key in PubKeyStore.
+
+ @param[in] PubKeyNumber Number of the public key in public key store.
+
+ @return Number of valid public key in PubKeyStore.
+
+**/
+UINT32
+GetValidPubKeyNumber (
+ IN UINT32 PubKeyNumber
+ )
+{
+ UINT32 PubKeyIndex;
+ UINT32 Counter;
+
+ Counter = 0;
+
+ for (PubKeyIndex = 1; PubKeyIndex <= PubKeyNumber; PubKeyIndex++) {
+ if (IsValidPubKeyIndex (PubKeyIndex)) {
+ Counter++;
+ }
+ }
+
+ return Counter;
+}
+
+/**
+
+ Filter the useless key in public key store.
+
+ This function will find out all valid public keys in public key database, save them in new allocated
+ buffer NewPubKeyStore, and give the new PubKeyIndex. The caller is responsible for freeing buffer
+ NewPubKeyIndex and NewPubKeyStore with FreePool().
+
+ @param[in] PubKeyStore Point to the public key database.
+ @param[in] PubKeyNumber Number of the public key in PubKeyStore.
+ @param[out] NewPubKeyIndex Point to an array of new PubKeyIndex corresponds to NewPubKeyStore.
+ @param[out] NewPubKeyStore Saved all valid public keys in PubKeyStore.
+ @param[out] NewPubKeySize Buffer size of the NewPubKeyStore.
+
+ @retval EFI_SUCCESS Trim operation is complete successfully.
+ @retval EFI_OUT_OF_RESOURCES No enough memory resources, or no useless key in PubKeyStore.
+
+**/
+EFI_STATUS
+PubKeyStoreFilter (
+ IN UINT8 *PubKeyStore,
+ IN UINT32 PubKeyNumber,
+ OUT UINT32 **NewPubKeyIndex,
+ OUT UINT8 **NewPubKeyStore,
+ OUT UINT32 *NewPubKeySize
+ )
+{
+ UINT32 PubKeyIndex;
+ UINT32 CopiedKey;
+ UINT32 NewPubKeyNumber;
+
+ NewPubKeyNumber = GetValidPubKeyNumber (PubKeyNumber);
+ if (NewPubKeyNumber == PubKeyNumber) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ if (NewPubKeyNumber != 0) {
+ *NewPubKeySize = NewPubKeyNumber * EFI_CERT_TYPE_RSA2048_SIZE;
+ } else {
+ *NewPubKeySize = sizeof (UINT8);
+ }
+
+ *NewPubKeyStore = AllocatePool (*NewPubKeySize);
+ if (*NewPubKeyStore == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ *NewPubKeyIndex = AllocateZeroPool ((PubKeyNumber + 1) * sizeof (UINT32));
+ if (*NewPubKeyIndex == NULL) {
+ FreePool (*NewPubKeyStore);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ CopiedKey = 0;
+ for (PubKeyIndex = 1; PubKeyIndex <= PubKeyNumber; PubKeyIndex++) {
+ if (IsValidPubKeyIndex (PubKeyIndex)) {
+ CopyMem (
+ *NewPubKeyStore + CopiedKey * EFI_CERT_TYPE_RSA2048_SIZE,
+ PubKeyStore + (PubKeyIndex - 1) * EFI_CERT_TYPE_RSA2048_SIZE,
+ EFI_CERT_TYPE_RSA2048_SIZE
+ );
+ (*NewPubKeyIndex)[PubKeyIndex] = ++CopiedKey;
+ }
+ }
+ return EFI_SUCCESS;
+}
- @param VariableBase Base address of variable store.
- @param LastVariableOffset Offset of last variable.
- @param IsVolatile The variable store is volatile or not;
- if it is non-volatile, need FTW.
- @param UpdatingVariable Pointer to updating variable.
+/**
- @return EFI_OUT_OF_RESOURCES
- @return EFI_SUCCESS
- @return Others
+ Variable store garbage collection and reclaim operation.
+
+ If ReclaimPubKeyStore is FALSE, reclaim variable space by deleting the obsoleted varaibles.
+ If ReclaimPubKeyStore is TRUE, reclaim invalid key in public key database and update the PubKeyIndex
+ for all the count-based authenticate variable in NV storage.
+
+ @param[in] VariableBase Base address of variable store.
+ @param[out] LastVariableOffset Offset of last variable.
+ @param[in] IsVolatile The variable store is volatile or not;
+ if it is non-volatile, need FTW.
+ @param[in, out] UpdatingPtrTrack Pointer to updating variable pointer track structure.
+ @param[in] ReclaimPubKeyStore Reclaim for public key database or not.
+ @param[in] ReclaimAnyway If TRUE, do reclaim anyway.
+
+ @return EFI_SUCCESS Reclaim operation has finished successfully.
+ @return EFI_OUT_OF_RESOURCES No enough memory resources.
+ @return EFI_DEVICE_ERROR The public key database doesn't exist.
+ @return Others Unexpect error happened during reclaim operation.
**/
EFI_STATUS
Reclaim (
- IN EFI_PHYSICAL_ADDRESS VariableBase,
- OUT UINTN *LastVariableOffset,
- IN BOOLEAN IsVolatile,
- IN VARIABLE_HEADER *UpdatingVariable
+ IN EFI_PHYSICAL_ADDRESS VariableBase,
+ OUT UINTN *LastVariableOffset,
+ IN BOOLEAN IsVolatile,
+ IN OUT VARIABLE_POINTER_TRACK *UpdatingPtrTrack,
+ IN BOOLEAN ReclaimPubKeyStore,
+ IN BOOLEAN ReclaimAnyway
)
{
VARIABLE_HEADER *Variable;
@@ -555,12 +695,28 @@ Reclaim (
CHAR16 *UpdatingVariableNamePtr;
UINTN CommonVariableTotalSize;
UINTN HwErrVariableTotalSize;
+ UINT32 *NewPubKeyIndex;
+ UINT8 *NewPubKeyStore;
+ UINT32 NewPubKeySize;
+ VARIABLE_HEADER *PubKeyHeader;
+ BOOLEAN NeedDoReclaim;
+ VARIABLE_HEADER *UpdatingVariable;
+ UpdatingVariable = NULL;
+ if (UpdatingPtrTrack != NULL) {
+ UpdatingVariable = UpdatingPtrTrack->CurrPtr;
+ }
+
+ NeedDoReclaim = FALSE;
VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINTN) VariableBase);
CommonVariableTotalSize = 0;
HwErrVariableTotalSize = 0;
-
+ NewPubKeyIndex = NULL;
+ NewPubKeyStore = NULL;
+ NewPubKeySize = 0;
+ PubKeyHeader = NULL;
+
//
// Start Pointers for the variable.
//
@@ -574,11 +730,18 @@ Reclaim (
) {
VariableSize = (UINTN) NextVariable - (UINTN) Variable;
MaximumBufferSize += VariableSize;
+ } else {
+ NeedDoReclaim = TRUE;
}
Variable = NextVariable;
}
+ if (!ReclaimAnyway && !NeedDoReclaim) {
+ DEBUG ((EFI_D_INFO, "Variable driver: no DELETED variable found, so no variable space could be reclaimed.\n"));
+ return EFI_SUCCESS;
+ }
+
//
// Reserve the 1 Bytes with Oxff to identify the
// end of the variable buffer.
@@ -597,95 +760,97 @@ Reclaim (
CopyMem (ValidBuffer, VariableStoreHeader, sizeof (VARIABLE_STORE_HEADER));
CurrPtr = (UINT8 *) GetStartPointer ((VARIABLE_STORE_HEADER *) ValidBuffer);
- //
- // Reinstall all ADDED variables as long as they are not identical to Updating Variable.
- //
- Variable = GetStartPointer (VariableStoreHeader);
- while (IsValidVariableHeader (Variable)) {
- NextVariable = GetNextVariablePtr (Variable);
- if (Variable->State == VAR_ADDED) {
- if (UpdatingVariable != NULL) {
- if (UpdatingVariable == Variable) {
- Variable = NextVariable;
- continue;
- }
-
- VariableNameSize = NameSizeOfVariable(Variable);
- UpdatingVariableNameSize = NameSizeOfVariable(UpdatingVariable);
+ if (ReclaimPubKeyStore) {
+ //
+ // Trim the PubKeyStore and get new PubKeyIndex.
+ //
+ Status = PubKeyStoreFilter (
+ mPubKeyStore,
+ mPubKeyNumber,
+ &NewPubKeyIndex,
+ &NewPubKeyStore,
+ &NewPubKeySize
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (ValidBuffer);
+ return Status;
+ }
- VariableNamePtr = GetVariableNamePtr (Variable);
- UpdatingVariableNamePtr = GetVariableNamePtr (UpdatingVariable);
- if (CompareGuid (&Variable->VendorGuid, &UpdatingVariable->VendorGuid) &&
- VariableNameSize == UpdatingVariableNameSize &&
- CompareMem (VariableNamePtr, UpdatingVariableNamePtr, VariableNameSize) == 0 ) {
+ //
+ // Refresh the PubKeyIndex for all valid variables (ADDED and IN_DELETED_TRANSITION).
+ //
+ Variable = GetStartPointer (mNvVariableCache);
+ while (IsValidVariableHeader (Variable)) {
+ NextVariable = GetNextVariablePtr (Variable);
+ if (Variable->State == VAR_ADDED || Variable->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
+ if ((StrCmp (GetVariableNamePtr (Variable), AUTHVAR_KEYDB_NAME) == 0) &&
+ (CompareGuid (&Variable->VendorGuid, &gEfiAuthenticatedVariableGuid))) {
+ //
+ // Skip the public key database, it will be reinstalled later.
+ //
+ PubKeyHeader = Variable;
Variable = NextVariable;
continue;
}
+
+ VariableSize = (UINTN) NextVariable - (UINTN) Variable;
+ CopyMem (CurrPtr, (UINT8 *) Variable, VariableSize);
+ ((VARIABLE_HEADER*) CurrPtr)->PubKeyIndex = NewPubKeyIndex[Variable->PubKeyIndex];
+ CurrPtr += VariableSize;
+ if ((!IsVolatile) && ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {
+ HwErrVariableTotalSize += VariableSize;
+ } else if ((!IsVolatile) && ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {
+ CommonVariableTotalSize += VariableSize;
+ }
}
- VariableSize = (UINTN) NextVariable - (UINTN) Variable;
- CopyMem (CurrPtr, (UINT8 *) Variable, VariableSize);
- CurrPtr += VariableSize;
- if ((!IsVolatile) && ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {
- HwErrVariableTotalSize += VariableSize;
- } else if ((!IsVolatile) && ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {
- CommonVariableTotalSize += VariableSize;
- }
+ Variable = NextVariable;
}
- Variable = NextVariable;
- }
- //
- // Reinstall the variable being updated if it is not NULL.
- //
- if (UpdatingVariable != NULL) {
- VariableSize = (UINTN)(GetNextVariablePtr (UpdatingVariable)) - (UINTN)UpdatingVariable;
- CopyMem (CurrPtr, (UINT8 *) UpdatingVariable, VariableSize);
- CurrPtr += VariableSize;
- if ((!IsVolatile) && ((UpdatingVariable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {
- HwErrVariableTotalSize += VariableSize;
- } else if ((!IsVolatile) && ((UpdatingVariable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {
- CommonVariableTotalSize += VariableSize;
+ //
+ // Reinstall the new public key database.
+ //
+ ASSERT (PubKeyHeader != NULL);
+ if (PubKeyHeader == NULL) {
+ FreePool (ValidBuffer);
+ FreePool (NewPubKeyIndex);
+ FreePool (NewPubKeyStore);
+ return EFI_DEVICE_ERROR;
}
- }
-
- //
- // Reinstall all in delete transition variables.
- //
- Variable = GetStartPointer (VariableStoreHeader);
- while (IsValidVariableHeader (Variable)) {
- NextVariable = GetNextVariablePtr (Variable);
- if (Variable != UpdatingVariable && Variable->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
+ CopyMem (CurrPtr, (UINT8*) PubKeyHeader, sizeof (VARIABLE_HEADER));
+ Variable = (VARIABLE_HEADER*) CurrPtr;
+ Variable->DataSize = NewPubKeySize;
+ StrCpy (GetVariableNamePtr (Variable), GetVariableNamePtr (PubKeyHeader));
+ CopyMem (GetVariableDataPtr (Variable), NewPubKeyStore, NewPubKeySize);
+ CurrPtr = (UINT8*) GetNextVariablePtr (Variable);
+ CommonVariableTotalSize += (UINTN) CurrPtr - (UINTN) Variable;
+ } else {
+ //
+ // Reinstall all ADDED variables as long as they are not identical to Updating Variable.
+ //
+ Variable = GetStartPointer (VariableStoreHeader);
+ while (IsValidVariableHeader (Variable)) {
+ NextVariable = GetNextVariablePtr (Variable);
+ if (Variable->State == VAR_ADDED) {
+ if (UpdatingVariable != NULL) {
+ if (UpdatingVariable == Variable) {
+ Variable = NextVariable;
+ continue;
+ }
- //
- // Buffer has cached all ADDED variable.
- // Per IN_DELETED variable, we have to guarantee that
- // no ADDED one in previous buffer.
- //
+ VariableNameSize = NameSizeOfVariable(Variable);
+ UpdatingVariableNameSize = NameSizeOfVariable(UpdatingVariable);
- 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)) == 0) {
- FoundAdded = TRUE;
- break;
+ VariableNamePtr = GetVariableNamePtr (Variable);
+ UpdatingVariableNamePtr = GetVariableNamePtr (UpdatingVariable);
+ if (CompareGuid (&Variable->VendorGuid, &UpdatingVariable->VendorGuid) &&
+ VariableNameSize == UpdatingVariableNameSize &&
+ CompareMem (VariableNamePtr, UpdatingVariableNamePtr, VariableNameSize) == 0 ) {
+ Variable = NextVariable;
+ continue;
}
}
- AddedVariable = NextAddedVariable;
- }
- if (!FoundAdded) {
- //
- // Promote VAR_IN_DELETED_TRANSITION to VAR_ADDED.
- //
VariableSize = (UINTN) NextVariable - (UINTN) Variable;
CopyMem (CurrPtr, (UINT8 *) Variable, VariableSize);
- ((VARIABLE_HEADER *) CurrPtr)->State = VAR_ADDED;
CurrPtr += VariableSize;
if ((!IsVolatile) && ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {
HwErrVariableTotalSize += VariableSize;
@@ -693,9 +858,74 @@ Reclaim (
CommonVariableTotalSize += VariableSize;
}
}
+ Variable = NextVariable;
}
- Variable = NextVariable;
+ //
+ // Reinstall the variable being updated if it is not NULL.
+ //
+ if (UpdatingVariable != NULL) {
+ VariableSize = (UINTN)(GetNextVariablePtr (UpdatingVariable)) - (UINTN)UpdatingVariable;
+ 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;
+ if ((!IsVolatile) && ((UpdatingVariable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {
+ HwErrVariableTotalSize += VariableSize;
+ } else if ((!IsVolatile) && ((UpdatingVariable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {
+ CommonVariableTotalSize += VariableSize;
+ }
+ }
+
+ //
+ // Reinstall all in delete transition variables.
+ //
+ Variable = GetStartPointer (VariableStoreHeader);
+ while (IsValidVariableHeader (Variable)) {
+ NextVariable = GetNextVariablePtr (Variable);
+ if (Variable != UpdatingVariable && 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, NameSize) == 0) {
+ FoundAdded = TRUE;
+ break;
+ }
+ }
+ AddedVariable = NextAddedVariable;
+ }
+ if (!FoundAdded) {
+ //
+ // Promote VAR_IN_DELETED_TRANSITION to VAR_ADDED.
+ //
+ VariableSize = (UINTN) NextVariable - (UINTN) Variable;
+ CopyMem (CurrPtr, (UINT8 *) Variable, VariableSize);
+ ((VARIABLE_HEADER *) CurrPtr)->State = VAR_ADDED;
+ CurrPtr += VariableSize;
+ if ((!IsVolatile) && ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {
+ HwErrVariableTotalSize += VariableSize;
+ } else if ((!IsVolatile) && ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {
+ CommonVariableTotalSize += VariableSize;
+ }
+ }
+ }
+
+ Variable = NextVariable;
+ }
}
if (IsVolatile) {
@@ -737,6 +967,14 @@ Reclaim (
*LastVariableOffset = (UINTN) NextVariable - (UINTN) VariableBase;
}
+ if (NewPubKeyStore != NULL) {
+ FreePool (NewPubKeyStore);
+ }
+
+ if (NewPubKeyIndex != NULL) {
+ FreePool (NewPubKeyIndex);
+ }
+
FreePool (ValidBuffer);
return Status;
@@ -765,6 +1003,8 @@ FindVariableEx (
VARIABLE_HEADER *InDeletedVariable;
VOID *Point;
+ PtrTrack->InDeletedTransitionPtr = NULL;
+
//
// Find the variable by walk through HOB, volatile and non-volatile variable store.
//
@@ -782,6 +1022,7 @@ FindVariableEx (
if (PtrTrack->CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
InDeletedVariable = PtrTrack->CurrPtr;
} else {
+ PtrTrack->InDeletedTransitionPtr = InDeletedVariable;
return EFI_SUCCESS;
}
} else {
@@ -793,6 +1034,7 @@ FindVariableEx (
if (PtrTrack->CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
InDeletedVariable = PtrTrack->CurrPtr;
} else {
+ PtrTrack->InDeletedTransitionPtr = InDeletedVariable;
return EFI_SUCCESS;
}
}
@@ -1384,7 +1626,7 @@ AutoUpdateLangVariable (
@param[in] Attributes Attributes of the variable.
@param[in] KeyIndex Index of associated public key.
@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.
@retval EFI_SUCCESS The update operation is success.
@@ -1400,7 +1642,7 @@ UpdateVariable (
IN UINT32 Attributes OPTIONAL,
IN UINT32 KeyIndex OPTIONAL,
IN UINT64 MonotonicCount OPTIONAL,
- IN VARIABLE_POINTER_TRACK *CacheVariable,
+ IN OUT VARIABLE_POINTER_TRACK *CacheVariable,
IN EFI_TIME *TimeStamp OPTIONAL
)
{
@@ -1416,7 +1658,6 @@ UpdateVariable (
BOOLEAN Volatile;
EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;
UINT8 State;
- BOOLEAN Reclaimed;
VARIABLE_POINTER_TRACK *Variable;
VARIABLE_POINTER_TRACK NvVariable;
VARIABLE_STORE_HEADER *VariableStoreHeader;
@@ -1455,11 +1696,15 @@ UpdateVariable (
Variable->StartPtr = GetStartPointer (VariableStoreHeader);
Variable->EndPtr = GetEndPointer (VariableStoreHeader);
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;
}
Fvb = mVariableModuleGlobal->FvbInstance;
- Reclaimed = FALSE;
//
// Tricky part: Use scratch data area at the end of volatile variable store
@@ -1507,6 +1752,32 @@ UpdateVariable (
// not delete the variable.
//
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) {
+ ASSERT (CacheVariable->InDeletedTransitionPtr != NULL);
+ CacheVariable->InDeletedTransitionPtr->State = State;
+ }
+ } else {
+ goto Done;
+ }
+ }
+
State = Variable->CurrPtr->State;
State &= VAR_DELETED;
@@ -1523,6 +1794,7 @@ UpdateVariable (
UpdateVariableInfo (VariableName, VendorGuid, Variable->Volatile, FALSE, FALSE, TRUE, FALSE);
if (!Variable->Volatile) {
CacheVariable->CurrPtr->State = State;
+ FlushHobVariableToFlash (VariableName, VendorGuid);
}
}
goto Done;
@@ -1558,11 +1830,14 @@ UpdateVariable (
// Set Max Common Variable Data Size as default MaxDataSize
//
MaxDataSize = PcdGet32 (PcdMaxVariableSize) - sizeof (VARIABLE_HEADER) - StrSize (VariableName) - GET_PAD_SIZE (StrSize (VariableName));
- if (CompareGuid (VendorGuid, &gEfiImageSecurityDatabaseGuid) ||
- (CompareGuid (VendorGuid, &gEfiGlobalVariableGuid) && (StrCmp (VariableName, EFI_KEY_EXCHANGE_KEY_NAME) == 0))) {
+
+
+ if ((CompareGuid (VendorGuid, &gEfiImageSecurityDatabaseGuid) &&
+ ((StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE) == 0) || (StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE1) == 0))) ||
+ (CompareGuid (VendorGuid, &gEfiGlobalVariableGuid) && (StrCmp (VariableName, EFI_KEY_EXCHANGE_KEY_NAME) == 0))) {
+
//
- // For variables with the GUID EFI_IMAGE_SECURITY_DATABASE_GUID (i.e. where the data
- // buffer is formatted as EFI_SIGNATURE_LIST), the driver shall not perform an append of
+ // For variables with formatted as EFI_SIGNATURE_LIST, the driver shall not perform an append of
// EFI_SIGNATURE_DATA values that are already part of the existing variable value.
//
Status = AppendSignatureList (
@@ -1753,8 +2028,14 @@ UpdateVariable (
//
// Perform garbage collection & reclaim operation.
//
- Status = Reclaim (mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase,
- &mVariableModuleGlobal->NonVolatileLastVariableOffset, FALSE, Variable->CurrPtr);
+ Status = Reclaim (
+ mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase,
+ &mVariableModuleGlobal->NonVolatileLastVariableOffset,
+ FALSE,
+ Variable,
+ FALSE,
+ FALSE
+ );
if (EFI_ERROR (Status)) {
goto Done;
}
@@ -1768,7 +2049,10 @@ UpdateVariable (
Status = EFI_OUT_OF_RESOURCES;
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
@@ -1868,8 +2152,14 @@ UpdateVariable (
//
// Perform garbage collection & reclaim operation.
//
- Status = Reclaim (mVariableModuleGlobal->VariableGlobal.VolatileVariableBase,
- &mVariableModuleGlobal->VolatileLastVariableOffset, TRUE, Variable->CurrPtr);
+ Status = Reclaim (
+ mVariableModuleGlobal->VariableGlobal.VolatileVariableBase,
+ &mVariableModuleGlobal->VolatileLastVariableOffset,
+ TRUE,
+ Variable,
+ FALSE,
+ FALSE
+ );
if (EFI_ERROR (Status)) {
goto Done;
}
@@ -1882,7 +2172,10 @@ UpdateVariable (
Status = EFI_OUT_OF_RESOURCES;
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;
@@ -1906,7 +2199,33 @@ UpdateVariable (
//
// 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) {
+ ASSERT (CacheVariable->InDeletedTransitionPtr != NULL);
+ CacheVariable->InDeletedTransitionPtr->State = State;
+ }
+ } else {
+ goto Done;
+ }
+ }
+
State = Variable->CurrPtr->State;
State &= VAR_DELETED;
@@ -1926,6 +2245,9 @@ UpdateVariable (
if (!EFI_ERROR (Status)) {
UpdateVariableInfo (VariableName, VendorGuid, Volatile, FALSE, TRUE, FALSE, FALSE);
+ if (!Volatile) {
+ FlushHobVariableToFlash (VariableName, VendorGuid);
+ }
}
Done:
@@ -2125,6 +2447,7 @@ VariableServiceGetNextVariableName (
VARIABLE_STORE_TYPE Type;
VARIABLE_POINTER_TRACK Variable;
VARIABLE_POINTER_TRACK VariableInHob;
+ VARIABLE_POINTER_TRACK VariablePtrTrack;
UINTN VarNameSize;
EFI_STATUS Status;
VARIABLE_STORE_HEADER *VariableStoreHeader[VariableStoreTypeMax];
@@ -2198,8 +2521,27 @@ VariableServiceGetNextVariableName (
//
// Variable is found
//
- if (Variable.CurrPtr->State == VAR_ADDED) {
- if ((AtRuntime () && ((Variable.CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0)) == 0) {
+ 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)) {
+ 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
@@ -2639,12 +2981,103 @@ ReclaimForOS(
mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase,
&mVariableModuleGlobal->NonVolatileLastVariableOffset,
FALSE,
- NULL
+ NULL,
+ FALSE,
+ FALSE
);
ASSERT_EFI_ERROR (Status);
}
}
+/**
+ Flush the HOB variable to flash.
+
+ @param[in] VariableName Name of variable has been updated or deleted.
+ @param[in] VendorGuid Guid of variable has been updated or deleted.
+
+**/
+VOID
+FlushHobVariableToFlash (
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid
+ )
+{
+ EFI_STATUS Status;
+ VARIABLE_STORE_HEADER *VariableStoreHeader;
+ VARIABLE_HEADER *Variable;
+ VOID *VariableData;
+ BOOLEAN ErrorFlag;
+
+ ErrorFlag = FALSE;
+
+ //
+ // Flush the HOB variable to flash.
+ //
+ if (mVariableModuleGlobal->VariableGlobal.HobVariableBase != 0) {
+ VariableStoreHeader = (VARIABLE_STORE_HEADER *) (UINTN) mVariableModuleGlobal->VariableGlobal.HobVariableBase;
+ //
+ // Set HobVariableBase to 0, it can avoid SetVariable to call back.
+ //
+ mVariableModuleGlobal->VariableGlobal.HobVariableBase = 0;
+ for ( Variable = GetStartPointer (VariableStoreHeader)
+ ; (Variable < GetEndPointer (VariableStoreHeader) && IsValidVariableHeader (Variable))
+ ; Variable = GetNextVariablePtr (Variable)
+ ) {
+ if (Variable->State != VAR_ADDED) {
+ //
+ // The HOB variable has been set to DELETED state in local.
+ //
+ continue;
+ }
+ ASSERT ((Variable->Attributes & EFI_VARIABLE_NON_VOLATILE) != 0);
+ if (VendorGuid == NULL || VariableName == NULL ||
+ !CompareGuid (VendorGuid, &Variable->VendorGuid) ||
+ StrCmp (VariableName, GetVariableNamePtr (Variable)) != 0) {
+ VariableData = GetVariableDataPtr (Variable);
+ Status = VariableServiceSetVariable (
+ GetVariableNamePtr (Variable),
+ &Variable->VendorGuid,
+ Variable->Attributes,
+ Variable->DataSize,
+ VariableData
+ );
+ DEBUG ((EFI_D_INFO, "Variable driver flush the HOB variable to flash: %g %s %r\n", &Variable->VendorGuid, GetVariableNamePtr (Variable), Status));
+ } else {
+ //
+ // The updated or deleted variable is matched with the HOB variable.
+ // Don't break here because we will try to set other HOB variables
+ // since this variable could be set successfully.
+ //
+ Status = EFI_SUCCESS;
+ }
+ if (!EFI_ERROR (Status)) {
+ //
+ // If set variable successful, or the updated or deleted variable is matched with the HOB variable,
+ // set the HOB variable to DELETED state in local.
+ //
+ DEBUG ((EFI_D_INFO, "Variable driver set the HOB variable to DELETED state in local: %g %s\n", &Variable->VendorGuid, GetVariableNamePtr (Variable)));
+ Variable->State &= VAR_DELETED;
+ } else {
+ ErrorFlag = TRUE;
+ }
+ }
+ if (ErrorFlag) {
+ //
+ // We still have HOB variable(s) not flushed in flash.
+ //
+ mVariableModuleGlobal->VariableGlobal.HobVariableBase = (EFI_PHYSICAL_ADDRESS) (UINTN) VariableStoreHeader;
+ } else {
+ //
+ // All HOB variables have been flushed in flash.
+ //
+ DEBUG ((EFI_D_INFO, "Variable driver: all HOB variables have been flushed in flash.\n"));
+ if (!AtRuntime ()) {
+ FreePool ((VOID *) VariableStoreHeader);
+ }
+ }
+ }
+
+}
/**
Initializes variable write service after FVB was ready.
@@ -2663,8 +3096,6 @@ VariableWriteServiceInitialize (
UINTN Index;
UINT8 Data;
EFI_PHYSICAL_ADDRESS VariableStoreBase;
- VARIABLE_HEADER *Variable;
- VOID *VariableData;
VariableStoreBase = mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase;
VariableStoreHeader = (VARIABLE_STORE_HEADER *)(UINTN)VariableStoreBase;
@@ -2682,7 +3113,9 @@ VariableWriteServiceInitialize (
mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase,
&mVariableModuleGlobal->NonVolatileLastVariableOffset,
FALSE,
- NULL
+ NULL,
+ FALSE,
+ TRUE
);
if (EFI_ERROR (Status)) {
return Status;
@@ -2691,34 +3124,7 @@ VariableWriteServiceInitialize (
}
}
-
- //
- // Flush the HOB variable to flash and invalidate HOB variable.
- //
- if (mVariableModuleGlobal->VariableGlobal.HobVariableBase != 0) {
- //
- // Clear the HobVariableBase to avoid SetVariable() updating the variable in HOB
- //
- VariableStoreHeader = (VARIABLE_STORE_HEADER *) (UINTN) mVariableModuleGlobal->VariableGlobal.HobVariableBase;
- mVariableModuleGlobal->VariableGlobal.HobVariableBase = 0;
-
- for ( Variable = GetStartPointer (VariableStoreHeader)
- ; (Variable < GetEndPointer (VariableStoreHeader) && IsValidVariableHeader (Variable))
- ; Variable = GetNextVariablePtr (Variable)
- ) {
- ASSERT (Variable->State == VAR_ADDED);
- ASSERT ((Variable->Attributes & EFI_VARIABLE_NON_VOLATILE) != 0);
- VariableData = GetVariableDataPtr (Variable);
- Status = VariableServiceSetVariable (
- GetVariableNamePtr (Variable),
- &Variable->VendorGuid,
- Variable->Attributes,
- Variable->DataSize,
- VariableData
- );
- ASSERT_EFI_ERROR (Status);
- }
- }
+ FlushHobVariableToFlash (NULL, NULL);
//
// Authenticated variable initialize.
@@ -2776,8 +3182,12 @@ VariableCommonInitialize (
GuidHob = GetFirstGuidHob (&gEfiAuthenticatedVariableGuid);
if (GuidHob != NULL) {
VariableStoreHeader = GET_GUID_HOB_DATA (GuidHob);
+ VariableStoreLength = (UINT64) (GuidHob->Header.HobLength - sizeof (EFI_HOB_GUID_TYPE));
if (GetVariableStoreStatus (VariableStoreHeader) == EfiValid) {
- mVariableModuleGlobal->VariableGlobal.HobVariableBase = (EFI_PHYSICAL_ADDRESS) (UINTN) VariableStoreHeader;
+ mVariableModuleGlobal->VariableGlobal.HobVariableBase = (EFI_PHYSICAL_ADDRESS) (UINTN) AllocateRuntimeCopyPool ((UINTN) VariableStoreLength, (VOID *) VariableStoreHeader);
+ if (mVariableModuleGlobal->VariableGlobal.HobVariableBase == 0) {
+ return EFI_OUT_OF_RESOURCES;
+ }
} else {
DEBUG ((EFI_D_ERROR, "HOB Variable Store header is corrupted!\n"));
}
diff --git a/SecurityPkg/VariableAuthenticated/RuntimeDxe/Variable.h b/SecurityPkg/VariableAuthenticated/RuntimeDxe/Variable.h
index 563485f..4501583 100644
--- a/SecurityPkg/VariableAuthenticated/RuntimeDxe/Variable.h
+++ b/SecurityPkg/VariableAuthenticated/RuntimeDxe/Variable.h
@@ -2,7 +2,7 @@
The internal header file includes the common header files, defines
internal structure and functions used by Variable modules.
-Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2009 - 2013, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
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
@@ -65,6 +65,13 @@ typedef enum {
typedef struct {
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 *StartPtr;
BOOLEAN Volatile;
@@ -100,6 +107,19 @@ typedef struct {
} VARIABLE_CACHE_ENTRY;
/**
+ Flush the HOB variable to flash.
+
+ @param[in] VariableName Name of variable has been updated or deleted.
+ @param[in] VendorGuid Guid of variable has been updated or deleted.
+
+**/
+VOID
+FlushHobVariableToFlash (
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid
+ );
+
+/**
Writes a buffer to variable storage space, in the working block.
This function writes a buffer to variable storage space into a firmware
@@ -196,7 +216,7 @@ DataSizeOfVariable (
@param[in] Attributes Attributes of the variable.
@param[in] KeyIndex Index of associated public key.
@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.
@@ -213,7 +233,7 @@ UpdateVariable (
IN UINT32 Attributes OPTIONAL,
IN UINT32 KeyIndex OPTIONAL,
IN UINT64 MonotonicCount OPTIONAL,
- IN VARIABLE_POINTER_TRACK *Variable,
+ IN OUT VARIABLE_POINTER_TRACK *Variable,
IN EFI_TIME *TimeStamp OPTIONAL
);
@@ -354,6 +374,38 @@ VariableCommonInitialize (
);
/**
+
+ Variable store garbage collection and reclaim operation.
+
+ If ReclaimPubKeyStore is FALSE, reclaim variable space by deleting the obsoleted varaibles.
+ If ReclaimPubKeyStore is TRUE, reclaim invalid key in public key database and update the PubKeyIndex
+ for all the count-based authenticate variable in NV storage.
+
+ @param[in] VariableBase Base address of variable store.
+ @param[out] LastVariableOffset Offset of last variable.
+ @param[in] IsVolatile The variable store is volatile or not;
+ if it is non-volatile, need FTW.
+ @param[in, out] UpdatingPtrTrack Pointer to updating variable pointer track structure.
+ @param[in] ReclaimPubKeyStore Reclaim for public key database or not.
+ @param[in] ReclaimAnyway If TRUE, do reclaim anyway.
+
+ @return EFI_SUCCESS Reclaim operation has finished successfully.
+ @return EFI_OUT_OF_RESOURCES No enough memory resources.
+ @return EFI_DEVICE_ERROR The public key database doesn't exist.
+ @return Others Unexpect error happened during reclaim operation.
+
+**/
+EFI_STATUS
+Reclaim (
+ IN EFI_PHYSICAL_ADDRESS VariableBase,
+ OUT UINTN *LastVariableOffset,
+ IN BOOLEAN IsVolatile,
+ IN OUT VARIABLE_POINTER_TRACK *UpdatingPtrTrack,
+ IN BOOLEAN ReclaimPubKeyStore,
+ IN BOOLEAN ReclaimAnyway
+ );
+
+/**
This function reclaims variable storage if free size is below the threshold.
**/