alder_lake_bios/Insyde/InsydeModulePkg/Universal/Variable/VariableRuntimeDxe/Reclaim.c

782 lines
25 KiB
C

/** @file
Handles non-volatile variable store garbage collection, using FTW
(Fault Tolerant Write Lite) protocol.
;******************************************************************************
;* Copyright (c) 2012 - 2020, Insyde Software Corp. All Rights Reserved.
;*
;* You may not reproduce, distribute, publish, display, perform, modify, adapt,
;* transmit, broadcast, present, recite, release, license or otherwise exploit
;* any part of this publication in any form, by any means, without the prior
;* written permission of Insyde Software Corporation.
;*
;******************************************************************************
*/
#include "Variable.h"
#include "VariableCache.h"
#include <PostCode.h>
/**
Gets LBA of block and offset by given address."
This function gets the Logical Block Address (LBA) of a firmware
volume block containing the given address, and the offset of the
address on the block.
@param[in] Address Address which should be contained
by returned FVB handle.
@param[out] Lba Pointer to LBA for output.
@param[out] Offset Pointer to offset for output.
@retval EFI_SUCCESS LBA and offset successfully returned.
@retval EFI_NOT_FOUND Fail to find FVB handle by address.
@retval EFI_ABORTED Fail to find valid LBA and offset.
**/
EFI_STATUS
GetVariableStoreInfo (
IN EFI_PHYSICAL_ADDRESS VariableBase,
OUT EFI_PHYSICAL_ADDRESS *FvbBaseAddress,
OUT EFI_LBA *Lba,
OUT UINTN *Offset
)
{
EFI_STATUS Status;
EFI_HANDLE FvbHandle;
EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;
EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
EFI_FV_BLOCK_MAP_ENTRY *FvbMapEntry;
UINT32 LbaIndex;
*Lba = (EFI_LBA) (-1);
*Offset = 0;
//
// Get the proper FVB
//
Status = GetFvbInfoByAddress (VariableBase, &FvbHandle, &Fvb);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Get the Base Address of FV
//
Status = Fvb->GetPhysicalAddress (Fvb, FvbBaseAddress);
if (EFI_ERROR (Status)) {
return Status;
}
FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) *FvbBaseAddress);
//
// Get the (LBA, Offset) of Address
//
if ((VariableBase >= *FvbBaseAddress) && (VariableBase <= (*FvbBaseAddress + FwVolHeader->FvLength))) {
if ((FwVolHeader->FvLength) > (FwVolHeader->HeaderLength)) {
//
// BUGBUG: Assume one FV has one type of BlockLength
//
FvbMapEntry = &FwVolHeader->BlockMap[0];
for (LbaIndex = 1; LbaIndex <= FvbMapEntry->NumBlocks; LbaIndex += 1) {
if (VariableBase < (*FvbBaseAddress + FvbMapEntry->Length * LbaIndex)) {
//
// Found the (Lba, Offset)
//
*Lba = LbaIndex - 1;
*Offset = (UINTN) (VariableBase - (*FvbBaseAddress + FvbMapEntry->Length * (LbaIndex - 1)));
return EFI_SUCCESS;
}
}
}
}
return EFI_ABORTED;
}
/**
Writes a buffer to variable storage space, in the working block.
This function writes a buffer to variable storage space into a firmware
volume block device. The destination is specified by the parameter
VariableBase. Fault Tolerant Write protocol is used for writing.
@param[in] VariableBase Base address of the variable to write.
@param[in] Buffer Point to the data buffer.
@retval EFI_SUCCESS The function completed successfully.
@retval EFI_NOT_FOUND Fail to locate Fault Tolerant Write protocol.
@retval EFI_ABORTED The function could not complete successfully.
**/
EFI_STATUS
FtwVariableSpace (
IN EFI_PHYSICAL_ADDRESS VariableBase,
IN UINT8 *Buffer
)
{
EFI_STATUS Status;
EFI_FTW_LITE_PROTOCOL *FtwLiteProtocol;
EFI_LBA VarLba;
UINTN VarOffset;
UINT8 *FtwBuffer;
UINTN FtwBufferSize;
EFI_SMM_FTW_PROTOCOL *SmmFtwProtocol;
FtwBufferSize = GetNonVolatileVariableStoreSize ();
FtwBuffer = Buffer;
if (mSmst == NULL) {
//
// Prepare for the variable data
//
FtwLiteProtocol = mVariableReclaimInfo->FtwLiteProtocol;
VarOffset = mVariableReclaimInfo->VariableOffset;
VarLba = mVariableReclaimInfo->VariableLba;
//
// FTW write record
//
Status = FtwLiteProtocol->Write (
FtwLiteProtocol,
NULL,
VarLba, // LBA
VarOffset, // Offset
&FtwBufferSize, // NumBytes,
FtwBuffer
);
} else {
SmmFtwProtocol = NULL;
if (SmmFtwProtocol == NULL) {
Status = mSmst->SmmLocateProtocol (
&gEfiSmmFtwProtocolGuid,
NULL,
(VOID **)&SmmFtwProtocol
);
if (EFI_ERROR (Status)) {
return Status;
}
}
//
// FTW write record
//
Status = SmmFtwProtocol->Write(
SmmFtwProtocol,
mSmmVariableGlobal->VariableStoreInfo.FvbBaseAddress,
mSmmVariableGlobal->VariableStoreInfo.Lba,
mSmmVariableGlobal->VariableStoreInfo.Offset,
&FtwBufferSize,
FtwBuffer
);
}
return Status;
}
/**
Variable store garbage collection and reclaim operation.
@param[in] VariableBase Base address of variable store
@param[in] LastVariableOffset Offset of last variable
@param[in] IsVolatile The variable store is volatile or not,
if it is non-volatile, need FTW
@param[in] CurrentVariable If it is not NULL, it means not to process
current variable for Reclaim.
@return EFI_SUCCESS Reclaim variable store successfully.
@return EFI_OUT_OF_RESOURCES Allocate pool failed or total variable size is large than variable store size.
@return Others Other error causes reclaim failed.
**/
EFI_STATUS
EFIAPI
Reclaim (
IN EFI_PHYSICAL_ADDRESS VariableBase,
OUT UINTN *LastVariableOffset,
IN BOOLEAN IsVolatile,
IN OUT VARIABLE_HEADER **CurrentVariable OPTIONAL
)
{
VARIABLE_HEADER *Variable;
VARIABLE_HEADER *StartPtr;
VARIABLE_HEADER *EndPtr;
VARIABLE_HEADER *NextVariable;
VARIABLE_STORE_HEADER *VariableStoreHeader;
UINT8 *ValidBuffer;
UINTN VariableSize;
UINT8 *CurrPtr;
EFI_STATUS Status;
VARIABLE_HEADER *WorkingVariable;
UINTN TotalBufferSize;
UINTN CommonUserVariableTotalSize;
POST_CODE (DXE_VARIABLE_RECLAIM);
VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINTN) VariableBase);
StartPtr = GetStartPointer (VariableStoreHeader);
Variable = StartPtr;
EndPtr = GetNonVolatileEndPointer (VariableStoreHeader);
CommonUserVariableTotalSize = 0;
//
// To make the reclaim, here we just allocate a memory that equal to the original memory
//
if (IsVolatile) {
TotalBufferSize = GetVariableStoreSize (VariableStoreHeader);
} else {
TotalBufferSize = GetNonVolatileVariableStoreSize ();
}
WorkingVariable = NULL;
ValidBuffer = (UINT8 *) mVariableReclaimInfo->BackupBuffer;
SetMem (ValidBuffer, TotalBufferSize, 0xff);
CurrPtr = ValidBuffer;
//
// Copy variable store header
//
CopyMem (CurrPtr, VariableStoreHeader, GetVariableStoreHeaderSize ());
CurrPtr += GetVariableStoreHeaderSize ();
for (Variable = GetStartPointer (VariableStoreHeader); IsValidVariableHeader (Variable); Variable = NextVariable) {
NextVariable = GetNextVariablePtr (Variable);
//
// Check the contents of this variable is in variable range.
//
if ((UINTN) NextVariable - (UINTN) VariableBase > TotalBufferSize) {
ASSERT (FALSE);
break;
}
//
// check variable name size is correct.
//
if (Variable->NameSize != StrSize (GET_VARIABLE_NAME_PTR (Variable))) {
ASSERT (FALSE);
continue;
}
//
// State VAR_ADDED or VAR_IN_DELETED_TRANSITION are to kept,
// The CurrentVariable, is also saved, as SetVariable may fail duo to lack of space
//
if ((Variable->State == VAR_ADDED || Variable->State == (VAR_ADDED & VAR_IN_DELETED_TRANSITION)) &&
IsMostValueVariable (Variable, StartPtr, EndPtr)) {
VariableSize = (UINTN) NextVariable - (UINTN) Variable;
CopyMem (CurrPtr, (UINT8 *) Variable, VariableSize);
if (IsUserVariable ((CHAR16 *) (Variable + 1), &Variable->VendorGuid)) {
CommonUserVariableTotalSize += VariableSize;
}
//
// If CurrentVariable == Variable, mark as VAR_IN_DELETED_TRANSITION
//
if (Variable->State == (VAR_ADDED & VAR_IN_DELETED_TRANSITION) && CurrentVariable != NULL) {
if (Variable != *CurrentVariable){
((VARIABLE_HEADER *)CurrPtr)->State = VAR_ADDED;
} else {
WorkingVariable = (VARIABLE_HEADER *) ((UINTN) VariableBase + ((UINTN) CurrPtr - (UINTN) ValidBuffer));
}
} else {
((VARIABLE_HEADER *)CurrPtr)->State = VAR_ADDED;
}
CurrPtr += VariableSize;
}
}
if (IsVolatile) {
//
// If volatile variable store, just copy valid buffer
//
SetMem ((UINT8 *) (UINTN) VariableBase, GetVariableStoreSize (VariableStoreHeader), 0xff);
CopyMem ((UINT8 *) (UINTN) VariableBase, ValidBuffer, (UINTN) CurrPtr - (UINTN) ValidBuffer);
*LastVariableOffset = (UINTN) (CurrPtr - ValidBuffer);
Status = EFI_SUCCESS;
} else {
//
// If non-volatile variable store, perform FTW here.
//
Status = FtwVariableSpace (VariableBase, ValidBuffer);
if (!EFI_ERROR (Status)) {
if (mSmst == NULL) {
mVariableModuleGlobal->CommonUserVariableTotalSize = CommonUserVariableTotalSize;
} else {
mSmmVariableGlobal->ProtectedModeVariableModuleGlobal->CommonUserVariableTotalSize = CommonUserVariableTotalSize;
}
*LastVariableOffset = (UINTN) CurrPtr - (UINTN) ValidBuffer;
}
}
if (EFI_ERROR (Status)) {
*LastVariableOffset = 0;
if (mSmst || !VariableAtRuntime ()) {
REPORT_STATUS_CODE (
EFI_ERROR_CODE,
EFI_SOFTWARE_EFI_RUNTIME_SERVICE | H2O_VARIABLE_RECLAIM_FAILED
);
}
}
if (!EFI_ERROR (Status) && CurrentVariable != NULL) {
*CurrentVariable = WorkingVariable;
}
if (!EFI_ERROR (Status) && !IsVolatile && mVariableModuleGlobal->NonVolatileVariableCache != NULL) {
SetMem (mVariableModuleGlobal->NonVolatileVariableCache, TotalBufferSize, 0xff);
CopyMem (
mVariableModuleGlobal->NonVolatileVariableCache,
(VOID *) (UINTN) VariableBase,
(UINTN) (CurrPtr - ValidBuffer)
);
SetNonVolatileVariableCacheCrc32 ();
} else if (!IsVolatile && mVariableModuleGlobal->NonVolatileVariableCache != NULL) {
//
// Turn off variable cache, if reclaim NV data failed
//
DisableVariableCache ();
}
return Status;
}
/**
Check the variable is whether in the preserved variable table or not.
@param[In] Variable pointer to the variable
@retval TRUE the variable is in the preserved variable table
@retval FALSE the variable is not in the preserved variable table
**/
STATIC
BOOLEAN
IsVariableInKeepList (
VARIABLE_HEADER *Variable
)
{
UINTN Index;
for (Index = 0; mVariableModuleGlobal->PreservedVariableTable[Index].VariableName != NULL; Index++) {
if ((CompareGuid (&Variable->VendorGuid, &mVariableModuleGlobal->PreservedVariableTable[Index].VendorGuid)) &&
(StrCmp (GET_VARIABLE_NAME_PTR (Variable), mVariableModuleGlobal->PreservedVariableTable[Index].VariableName) == 0)) {
return TRUE;
}
}
return FALSE;
}
/**
Check the variable is whether authenticated or not.
@param[In] Variable pointer to the variable
@retval TRUE the variable is authenticated
@retval FALSE the variable is not authenticated
**/
STATIC
BOOLEAN
IsAuthenticatedVariable (
VARIABLE_HEADER *Variable
)
{
if (((Variable->Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) == EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) ||
((Variable->Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) == EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS)) {
return TRUE;
}
return FALSE;
}
/**
This function elimates all the variables except authenticated variables and
the variables form mVariableModuleGlobal->PreservedVariableTable.
@param[In] ValidBuffer pointer to the valid variable buffer
@param[In] TotalBufferSize the total size of the variable region
@param[Out] ValidVariableSize pointer to the size of the valid variable
**/
STATIC
VOID
ElimateVariableWhenRegionFull (
IN UINT8 *ValidBuffer,
IN UINTN TotalBufferSize,
OUT UINTN *ValidVariableSize
)
{
VARIABLE_HEADER *Variable;
VARIABLE_HEADER *NextVariable;
UINTN VariableSize;
UINT8 *ValidVariablePtr;
if (mVariableModuleGlobal->PreservedVariableTable == NULL) {
return;
}
Variable = (VARIABLE_HEADER *) (ValidBuffer + GetVariableStoreHeaderSize ());
ValidVariablePtr = (UINT8 *) Variable;
VariableSize = 0;
while (IsValidVariableHeader (Variable)) {
NextVariable = GetNextVariablePtr (Variable);
VariableSize = (UINTN) NextVariable - (UINTN) Variable;
if (IsVariableInKeepList (Variable) || IsAuthenticatedVariable (Variable)) {
if (ValidVariablePtr != (UINT8 *) Variable) {
CopyMem (ValidVariablePtr, Variable, VariableSize);
}
ValidVariablePtr = ValidVariablePtr + VariableSize;
}
Variable = NextVariable;
}
*ValidVariableSize = (UINTN) (ValidVariablePtr - ValidBuffer);
SetMem (ValidVariablePtr, TotalBufferSize - *ValidVariableSize, 0xFF);
}
/**
non-volatile variable store garbage collection and reclaim operation
@param[in] Variable Pointer to new added variable.
@param[in] VarSize The size of new added variable size.
@param[in] VariableBase Base address of variable store
@param[out] LastVariableOffset Offset of last variable
@retval EFI_SUCCESS Reclaim non-volatile variable store successfully.
@retval EFI_INVALID_PARAMETER Any input parameter is invalid.
@retval EFI_OUT_OF_RESOURCES Allocate pool failed or total variable size is large than variable store size.
@retval EFI_DEVICE_ERROR Unable to reclaim non-volatile variable caused by flash device error.
--*/
EFI_STATUS
EFIAPI
ReclaimNonVolatileVariable (
IN VARIABLE_HEADER *NewVariable,
IN UINTN NewVarSize,
IN EFI_PHYSICAL_ADDRESS VariableBase,
OUT UINTN *LastVariableOffset
)
{
VARIABLE_HEADER *Variable;
VARIABLE_HEADER *StartPtr;
VARIABLE_HEADER *EndPtr;
VARIABLE_HEADER *NextVariable;
VARIABLE_STORE_HEADER *VariableStoreHeader;
UINT8 *ValidBuffer;
UINTN ValidBufferSize;
UINTN VariableSize;
UINTN TotalBufferSize;
UINT8 *CurrPtr;
EFI_STATUS Status;
UINTN CommonUserVariableTotalSize;
POST_CODE (DXE_VARIABLE_RECLAIM);
if (NewVariable == NULL || LastVariableOffset == NULL) {
return EFI_INVALID_PARAMETER;
}
CommonUserVariableTotalSize = 0;
TotalBufferSize = GetNonVolatileVariableStoreSize ();
if (mVariableModuleGlobal->NonVolatileVariableCache == NULL) {
VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINTN) VariableBase);
} else {
CopyMem (
mVariableModuleGlobal->NonVolatileVariableCache,
(VOID *) (UINTN) VariableBase,
TotalBufferSize
);
VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINTN) mVariableModuleGlobal->NonVolatileVariableCache);
SetNonVolatileVariableCacheCrc32 ();
}
StartPtr = GetStartPointer (VariableStoreHeader);
Variable = StartPtr;
EndPtr = GetNonVolatileEndPointer (VariableStoreHeader);
ValidBuffer = (UINT8 *) mVariableReclaimInfo->BackupBuffer;
SetMem (ValidBuffer, TotalBufferSize, 0xff);
CurrPtr = ValidBuffer;
//
// Copy variable store header
//
CopyMem (CurrPtr, VariableStoreHeader, GetVariableStoreHeaderSize ());
CurrPtr += GetVariableStoreHeaderSize ();
for (Variable = GetStartPointer (VariableStoreHeader); IsValidVariableHeader (Variable); Variable = NextVariable) {
NextVariable = GetNextVariablePtr (Variable);
//
// Check the contents of this variable is in variable range.
//
if ((UINTN) NextVariable - (UINTN) VariableStoreHeader > TotalBufferSize) {
ASSERT (FALSE);
break;
}
//
// check variable name size is correct.
//
if (Variable->NameSize != StrSize (GET_VARIABLE_NAME_PTR (Variable))) {
ASSERT (FALSE);
continue;
}
//
// State VAR_ADDED or VAR_IN_DELETED_TRANSITION are to kept,
// The CurrentVariable, is also saved, as SetVariable may fail due to lack of space
//
if ((Variable->State == VAR_ADDED || Variable->State == (VAR_ADDED & VAR_IN_DELETED_TRANSITION)) &&
!(CompareGuid (&NewVariable->VendorGuid, &Variable->VendorGuid) &&
!StrCmp (GET_VARIABLE_NAME_PTR (NewVariable), GET_VARIABLE_NAME_PTR (Variable))) &&
IsMostValueVariable (Variable, StartPtr, EndPtr)) {
VariableSize = (UINTN) NextVariable - (UINTN) Variable;
CopyMem (CurrPtr, (UINT8 *) Variable, VariableSize);
((VARIABLE_HEADER *) CurrPtr)->State = VAR_ADDED;
CurrPtr += VariableSize;
if (IsUserVariable ((CHAR16 *) (Variable + 1), &Variable->VendorGuid)) {
CommonUserVariableTotalSize += VariableSize;
}
}
}
ValidBufferSize = (UINTN) (CurrPtr - ValidBuffer);
if (ValidBufferSize + NewVarSize > TotalBufferSize) {
if (mSmst || !VariableAtRuntime ()) {
REPORT_STATUS_CODE (
EFI_ERROR_CODE,
EFI_SOFTWARE_EFI_RUNTIME_SERVICE | H2O_VARIABLE_STORE_FULL
);
}
ElimateVariableWhenRegionFull (ValidBuffer, TotalBufferSize, &ValidBufferSize);
if (ValidBufferSize + NewVarSize > TotalBufferSize) {
if (mSmst != NULL) {
EFI_FREE_POOL (ValidBuffer);
}
return EFI_OUT_OF_RESOURCES;
}
CurrPtr = ValidBuffer + ValidBufferSize;
}
CopyMem (CurrPtr, NewVariable, NewVarSize);
((VARIABLE_HEADER *) CurrPtr)->State &= VAR_ADDED;
CurrPtr += NewVarSize;
//
// If non-volatile variable store, perform FTW here.
//
Status = FtwVariableSpace (VariableBase, ValidBuffer);
*LastVariableOffset = 0;
if (!EFI_ERROR (Status)) {
if (mSmst == NULL) {
mVariableModuleGlobal->CommonUserVariableTotalSize = CommonUserVariableTotalSize;
} else {
mSmmVariableGlobal->ProtectedModeVariableModuleGlobal->CommonUserVariableTotalSize = CommonUserVariableTotalSize;
}
*LastVariableOffset = (UINTN) CurrPtr - (UINTN) ValidBuffer;
} else if (mSmst || !VariableAtRuntime ()) {
REPORT_STATUS_CODE (
EFI_ERROR_CODE,
EFI_SOFTWARE_EFI_RUNTIME_SERVICE | H2O_VARIABLE_RECLAIM_FAILED
);
}
if (!EFI_ERROR (Status) && mVariableModuleGlobal->NonVolatileVariableCache != NULL) {
SetMem (mVariableModuleGlobal->NonVolatileVariableCache, TotalBufferSize, 0xff);
CopyMem (
mVariableModuleGlobal->NonVolatileVariableCache,
(VOID *) (UINTN) VariableBase,
(UINTN) CurrPtr - (UINTN) ValidBuffer
);
SetNonVolatileVariableCacheCrc32 ();
} else if (mVariableModuleGlobal->NonVolatileVariableCache != NULL){
//
// reclaim failed, turn off variable chache to prevent from data corrupted
//
DisableVariableCache ();
}
return Status;
}
/**
Internal function to check the existence of VARIABLE_RECLAIM_THRESHOLD variable.
@retval TRUE VARIABLE_RECLAIM_THRESHOLD variable exists.
@retval FALSE VARIABLE_RECLAIM_THRESHOLD variable doesn't exist.
**/
BOOLEAN
DoesNeedDoReclaimVariableExist (
VOID
)
{
EFI_STATUS Status;
VARIABLE_POINTER_TRACK Variable;
UINTN VariableCount;
Status = FindVariableByLifetime (
NEED_DO_RECLAIM_NAME,
&gEfiGenericVariableGuid,
&Variable,
&VariableCount,
&mVariableModuleGlobal->VariableBase
);
return EFI_ERROR (Status) ? FALSE : TRUE;
}
/**
Internal function to delete VARIABLE_RECLAIM_THRESHOLD variable.
@retval EFI_SUCCESS VARIABLE_RECLAIM_THRESHOLD variable exists.
@return Other VARIABLE_RECLAIM_THRESHOLD variable doesn't exist.
**/
STATIC
EFI_STATUS
DeleteNeedDoReclaimVariable (
VOID
)
{
EFI_STATUS Status;
VARIABLE_POINTER_TRACK Variable;
UINTN VariableCount;
Status = FindVariableByLifetime (
NEED_DO_RECLAIM_NAME,
&gEfiGenericVariableGuid,
&Variable,
&VariableCount,
&mVariableModuleGlobal->VariableBase
);
if (EFI_ERROR (Status)) {
return EFI_SUCCESS;
}
return UpdateVariable (
NEED_DO_RECLAIM_NAME,
&gEfiGenericVariableGuid,
NULL,
0,
0,
0,
0,
&Variable,
NULL,
&mVariableModuleGlobal->VariableBase
);
}
/**
Make sure the remaining non-volatile variable space is larger than
VARIABLE_RECLAIM_THRESHOLD before boot to OS
**/
VOID
EFIAPI
ReclaimForOS (
VOID
)
{
EFI_STATUS Status;
STATIC BOOLEAN Reclaimed;
//
// This function will be called only once at EndOfDxe or ReadyToBoot event.
//
if (Reclaimed) {
return;
}
Reclaimed = TRUE;
mVariableModuleGlobal->NonVolatileLastVariableOffset = GetCurrentNonVolatileOffset ();
//
// Check if the free area is blow a threshold
//
if ((GetNonVolatileVariableStoreSize () - mVariableModuleGlobal->NonVolatileLastVariableOffset) < VARIABLE_RECLAIM_THRESHOLD ||
DoesNeedDoReclaimVariableExist ()) {
Status = Reclaim (
mVariableModuleGlobal->VariableBase.NonVolatileVariableBase,
&mVariableModuleGlobal->NonVolatileLastVariableOffset,
FALSE,
NULL
);
ASSERT(!EFI_ERROR(Status));
if (!EFI_ERROR (Status) && DoesNeedDoReclaimVariableExist ()) {
DeleteNeedDoReclaimVariable ();
}
}
}
/**
Internal function to check VARIABLE_RECLAIM_THRESHOLD or set NEED_DO_RECLAIM_NAME variable to make sure system will
do reclaim in next boot.
@retval EFI_SUCCESS Nonvolatile variable free space is smaller than VARIABLE_RECLAIM_THRESHOLD or
set NEED_DO_RECLAIM_NAME variable successfully.
@return Other Any error occurred while writing NEED_DO_RECLAIM_NAME variable.
**/
EFI_STATUS
SetDoReclaimNextBoot (
VOID
)
{
EFI_STATUS Status;
VARIABLE_POINTER_TRACK Variable;
UINTN VariableCount;
UINT8 Data;
VARIABLE_GLOBAL *Global;
//
// System will do reclaim next boot if free area is below a threshold, so just return EFI_SUCCESS if free is below
// a threshold.
//
if ((GetNonVolatileVariableStoreSize () - GetCurrentNonVolatileOffset ()) < VARIABLE_RECLAIM_THRESHOLD) {
return EFI_SUCCESS;
}
//
// return EFI_SUCCESS directly if Need do reclaim variable is set
//
Global = &mVariableModuleGlobal->VariableBase;
Status = FindVariableByLifetime (
NEED_DO_RECLAIM_NAME,
&gEfiGenericVariableGuid,
&Variable,
&VariableCount,
Global
);
if (!EFI_ERROR (Status)) {
return EFI_SUCCESS;
}
//
// Write NEED_DO_RECLAIM_NAME variable to indicate system need do reclaim next POST.
//
Data = 1;
return UpdateVariable (
NEED_DO_RECLAIM_NAME,
&gEfiGenericVariableGuid,
&Data,
sizeof (UINT8),
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
0,
0,
&Variable,
NULL,
Global
);
}
/**
Convert all of preserved variable table relative pointers to virtual address.
**/
VOID
PreservedTableAddressChange (
VOID
)
{
UINTN Index;
if (mVariableModuleGlobal->PreservedVariableTable == NULL) {
return;
}
for (Index = 0; mVariableModuleGlobal->PreservedVariableTable[Index].VariableName != NULL; Index++) {
gRT->ConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->PreservedVariableTable[Index].VariableName);
}
gRT->ConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->PreservedVariableTable);
}