/** @file\r
- EFI Runtime Variable services.\r
+\r
+ Implement all four UEFI Runtime Variable services for the nonvolatile\r
+ and volatile storage space and install variable architecture protocol.\r
\r
- Copyright (c) 2006 - 2007, Intel Corporation \r
- All rights reserved. This program and the accompanying materials \r
- are licensed and made available under the terms and conditions of the BSD License \r
- which accompanies this distribution. The full text of the license may be found at \r
- http://opensource.org/licenses/bsd-license.php \r
+Copyright (c) 2006 - 2008, Intel Corporation \r
+All rights reserved. This program and the accompanying materials \r
+are licensed and made available under the terms and conditions of the BSD License \r
+which accompanies this distribution. The full text of the license may be found at \r
+http://opensource.org/licenses/bsd-license.php \r
\r
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
\r
**/\r
\r
\r
#include "Variable.h"\r
\r
-\r
-VARIABLE_MODULE_GLOBAL mRuntimeData;\r
-VARIABLE_MODULE_GLOBAL *mVariableModuleGlobal = &mRuntimeData;\r
+VARIABLE_MODULE_GLOBAL *mVariableModuleGlobal;\r
EFI_EVENT mVirtualAddressChangeEvent = NULL;\r
EFI_HANDLE mHandle = NULL;\r
\r
}\r
}\r
\r
+\r
+UINTN\r
+NameSizeOfVariable (\r
+ IN VARIABLE_HEADER *Variable\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ This code gets the size of name of variable.\r
+\r
+Arguments:\r
+\r
+ Variable Pointer to the Variable Header.\r
+\r
+Returns:\r
+\r
+ UINTN Size of variable in bytes\r
+\r
+--*/\r
+{\r
+ if (Variable->State == (UINT8) (-1) ||\r
+ Variable->DataSize == (UINT32) -1 ||\r
+ Variable->NameSize == (UINT32) -1 ||\r
+ Variable->Attributes == (UINT32) -1) {\r
+ return 0;\r
+ }\r
+ return (UINTN) Variable->NameSize;\r
+}\r
+\r
+UINTN\r
+DataSizeOfVariable (\r
+ IN VARIABLE_HEADER *Variable\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ This code gets the size of name of variable.\r
+\r
+Arguments:\r
+\r
+ Variable Pointer to the Variable Header.\r
+\r
+Returns:\r
+\r
+ UINTN Size of variable in bytes\r
+\r
+--*/\r
+{\r
+ if (Variable->State == (UINT8) -1 ||\r
+ Variable->DataSize == (UINT32) -1 ||\r
+ Variable->NameSize == (UINT32) -1 ||\r
+ Variable->Attributes == (UINT32) -1) {\r
+ return 0;\r
+ }\r
+ return (UINTN) Variable->DataSize;\r
+}\r
+\r
+CHAR16 *\r
+GetVariableNamePtr (\r
+ IN VARIABLE_HEADER *Variable\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ This code gets the pointer to the variable name.\r
+\r
+Arguments:\r
+\r
+ Variable Pointer to the Variable Header.\r
+\r
+Returns:\r
+\r
+ CHAR16* Pointer to Variable Name\r
+\r
+--*/\r
+{\r
+\r
+ return (CHAR16 *) (Variable + 1);\r
+}\r
+\r
UINT8 *\r
GetVariableDataPtr (\r
IN VARIABLE_HEADER *Variable\r
\r
--*/\r
{\r
+ UINTN Value;\r
+ \r
//\r
// Be careful about pad size for alignment\r
//\r
- return (UINT8 *) ((UINTN) GET_VARIABLE_NAME_PTR (Variable) + NAMESIZE_OF_VARIABLE (Variable) + GET_PAD_SIZE (NAMESIZE_OF_VARIABLE (Variable)));\r
+ Value = (UINTN) GetVariableNamePtr (Variable);\r
+ Value += NameSizeOfVariable (Variable);\r
+ Value += GET_PAD_SIZE (NameSizeOfVariable (Variable));\r
+\r
+ return (UINT8 *) Value;\r
}\r
\r
\r
\r
--*/\r
{\r
+ UINTN Value;\r
+\r
if (!IsValidVariableHeader (Variable)) {\r
return NULL;\r
}\r
+\r
+ Value = (UINTN) GetVariableDataPtr (Variable);\r
+ Value += DataSizeOfVariable (Variable);\r
+ Value += GET_PAD_SIZE (DataSizeOfVariable (Variable));\r
+\r
//\r
// Be careful about pad size for alignment\r
//\r
- return (VARIABLE_HEADER *) HEADER_ALIGN (((UINTN) GetVariableDataPtr (Variable) + DATASIZE_OF_VARIABLE (Variable) + GET_PAD_SIZE (DATASIZE_OF_VARIABLE (Variable))));\r
+ return (VARIABLE_HEADER *) HEADER_ALIGN (Value);\r
}\r
\r
VARIABLE_HEADER *\r
Reclaim (\r
IN EFI_PHYSICAL_ADDRESS VariableBase,\r
OUT UINTN *LastVariableOffset,\r
- IN BOOLEAN IsVolatile\r
+ IN BOOLEAN IsVolatile,\r
+ IN VARIABLE_HEADER *UpdatingVariable\r
)\r
/*++\r
\r
--*/\r
{\r
VARIABLE_HEADER *Variable;\r
+ VARIABLE_HEADER *AddedVariable;\r
VARIABLE_HEADER *NextVariable;\r
+ VARIABLE_HEADER *NextAddedVariable;\r
VARIABLE_STORE_HEADER *VariableStoreHeader;\r
UINT8 *ValidBuffer;\r
- UINTN ValidBufferSize;\r
+ UINTN MaximumBufferSize;\r
UINTN VariableSize;\r
+ UINTN NameSize;\r
UINT8 *CurrPtr;\r
+ VOID *Point0;\r
+ VOID *Point1;\r
+ BOOLEAN FoundAdded;\r
EFI_STATUS Status;\r
\r
VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINTN) VariableBase);\r
//\r
// Start Pointers for the variable.\r
//\r
- Variable = GetStartPointer (VariableStoreHeader);\r
- ValidBufferSize = sizeof (VARIABLE_STORE_HEADER);\r
+ Variable = GetStartPointer (VariableStoreHeader);\r
+ MaximumBufferSize = sizeof (VARIABLE_STORE_HEADER);\r
\r
while (IsValidVariableHeader (Variable)) {\r
NextVariable = GetNextVariablePtr (Variable);\r
- if (Variable->State == VAR_ADDED) {\r
+ if (Variable->State == VAR_ADDED || \r
+ Variable->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)\r
+ ) {\r
VariableSize = (UINTN) NextVariable - (UINTN) Variable;\r
- ValidBufferSize += VariableSize;\r
+ MaximumBufferSize += VariableSize;\r
}\r
\r
Variable = NextVariable;\r
}\r
\r
- ValidBuffer = AllocatePool (ValidBufferSize);\r
+ //\r
+ // Reserve the 1 Bytes with Oxff to identify the \r
+ // end of the variable buffer. \r
+ // \r
+ MaximumBufferSize += 1;\r
+ ValidBuffer = AllocatePool (MaximumBufferSize);\r
if (ValidBuffer == NULL) {\r
return EFI_OUT_OF_RESOURCES;\r
}\r
\r
- SetMem (ValidBuffer, ValidBufferSize, 0xff);\r
-\r
- CurrPtr = ValidBuffer;\r
+ SetMem (ValidBuffer, MaximumBufferSize, 0xff);\r
\r
//\r
// Copy variable store header\r
//\r
- CopyMem (CurrPtr, VariableStoreHeader, sizeof (VARIABLE_STORE_HEADER));\r
- CurrPtr = (UINT8 *) GetStartPointer (VariableStoreHeader);\r
+ CopyMem (ValidBuffer, VariableStoreHeader, sizeof (VARIABLE_STORE_HEADER));\r
+ CurrPtr = (UINT8 *) GetStartPointer ((VARIABLE_STORE_HEADER *) ValidBuffer);\r
\r
//\r
// Start Pointers for the variable.\r
//\r
- Variable = GetStartPointer (VariableStoreHeader);\r
\r
+ //\r
+ // Reinstall all ADDED variables\r
+ // \r
+ Variable = GetStartPointer (VariableStoreHeader);\r
while (IsValidVariableHeader (Variable)) {\r
NextVariable = GetNextVariablePtr (Variable);\r
if (Variable->State == VAR_ADDED) {\r
\r
Variable = NextVariable;\r
}\r
+ //\r
+ // Reinstall all in delete transition variables\r
+ // \r
+ Variable = GetStartPointer (VariableStoreHeader);\r
+ while (IsValidVariableHeader (Variable)) {\r
+ NextVariable = GetNextVariablePtr (Variable);\r
+ if (Variable->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {\r
+\r
+ //\r
+ // Buffer has cached all ADDED variable. \r
+ // Per IN_DELETED variable, we have to guarantee that\r
+ // no ADDED one in previous buffer. \r
+ // \r
+ \r
+ FoundAdded = FALSE;\r
+ AddedVariable = GetStartPointer ((VARIABLE_STORE_HEADER *) ValidBuffer);\r
+ while (IsValidVariableHeader (AddedVariable)) {\r
+ NextAddedVariable = GetNextVariablePtr (AddedVariable);\r
+ NameSize = NameSizeOfVariable (AddedVariable);\r
+ if (CompareGuid (&AddedVariable->VendorGuid, &Variable->VendorGuid) &&\r
+ NameSize == NameSizeOfVariable (Variable)\r
+ ) {\r
+ Point0 = (VOID *) GetVariableNamePtr (AddedVariable);\r
+ Point1 = (VOID *) GetVariableNamePtr (Variable);\r
+ if (!CompareMem (\r
+ Point0,\r
+ Point1,\r
+ NameSizeOfVariable (AddedVariable)\r
+ )\r
+ ) {\r
+ FoundAdded = TRUE;\r
+ break;\r
+ }\r
+ }\r
+ AddedVariable = NextAddedVariable;\r
+ }\r
+ if (!FoundAdded) {\r
+ VariableSize = (UINTN) NextVariable - (UINTN) Variable;\r
+ CopyMem (CurrPtr, (UINT8 *) Variable, VariableSize);\r
+ if (Variable != UpdatingVariable) {\r
+ ((VARIABLE_HEADER *) CurrPtr)->State = VAR_ADDED;\r
+ }\r
+ CurrPtr += VariableSize;\r
+ }\r
+ }\r
+\r
+ Variable = NextVariable;\r
+ }\r
\r
if (IsVolatile) {\r
//\r
// If volatile variable store, just copy valid buffer\r
//\r
SetMem ((UINT8 *) (UINTN) VariableBase, VariableStoreHeader->Size, 0xff);\r
- CopyMem ((UINT8 *) (UINTN) VariableBase, ValidBuffer, ValidBufferSize);\r
- *LastVariableOffset = ValidBufferSize;\r
+ CopyMem ((UINT8 *) (UINTN) VariableBase, ValidBuffer, (UINTN) (CurrPtr - (UINT8 *) ValidBuffer));\r
Status = EFI_SUCCESS;\r
} else {\r
//\r
Status = FtwVariableSpace (\r
VariableBase,\r
ValidBuffer,\r
- ValidBufferSize\r
+ (UINTN) (CurrPtr - (UINT8 *) ValidBuffer)\r
);\r
- if (!EFI_ERROR (Status)) {\r
- *LastVariableOffset = ValidBufferSize;\r
- }\r
}\r
-\r
- FreePool (ValidBuffer);\r
-\r
- if (EFI_ERROR (Status)) {\r
+ if (!EFI_ERROR (Status)) {\r
+ *LastVariableOffset = (UINTN) (CurrPtr - (UINT8 *) ValidBuffer);\r
+ } else {\r
*LastVariableOffset = 0;\r
}\r
\r
+ FreePool (ValidBuffer);\r
+\r
return Status;\r
}\r
\r
\r
--*/\r
{\r
- VARIABLE_HEADER *Variable[2];\r
- VARIABLE_STORE_HEADER *VariableStoreHeader[2];\r
- UINTN Index;\r
+ VARIABLE_HEADER *Variable[2];\r
+ VARIABLE_HEADER *InDeletedVariable;\r
+ VARIABLE_STORE_HEADER *VariableStoreHeader[2];\r
+ UINTN InDeletedStorageIndex;\r
+ UINTN Index;\r
+ VOID *Point;\r
\r
//\r
// 0: Volatile, 1: Non-Volatile\r
if (VariableName[0] != 0 && VendorGuid == NULL) {\r
return EFI_INVALID_PARAMETER;\r
}\r
+\r
//\r
// Find the variable by walk through volatile and then non-volatile variable store\r
//\r
+ InDeletedVariable = NULL;\r
+ InDeletedStorageIndex = 0;\r
for (Index = 0; Index < 2; Index++) {\r
- PtrTrack->StartPtr = GetStartPointer (VariableStoreHeader[Index]);\r
- PtrTrack->EndPtr = GetEndPointer (VariableStoreHeader[Index]);\r
-\r
while (IsValidVariableHeader (Variable[Index]) && (Variable[Index] <= GetEndPointer (VariableStoreHeader[Index]))) {\r
- if (Variable[Index]->State == VAR_ADDED) {\r
+ if (Variable[Index]->State == VAR_ADDED || \r
+ Variable[Index]->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)\r
+ ) {\r
if (!EfiAtRuntime () || (Variable[Index]->Attributes & EFI_VARIABLE_RUNTIME_ACCESS)) {\r
if (VariableName[0] == 0) {\r
- PtrTrack->CurrPtr = Variable[Index];\r
- PtrTrack->Volatile = (BOOLEAN)(Index == 0);\r
- return EFI_SUCCESS;\r
+ if (Variable[Index]->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {\r
+ InDeletedVariable = Variable[Index];\r
+ InDeletedStorageIndex = Index;\r
+ } else {\r
+ PtrTrack->StartPtr = GetStartPointer (VariableStoreHeader[Index]);\r
+ PtrTrack->EndPtr = GetEndPointer (VariableStoreHeader[Index]);\r
+ PtrTrack->CurrPtr = Variable[Index];\r
+ PtrTrack->Volatile = (BOOLEAN)(Index == 0);\r
+\r
+ return EFI_SUCCESS;\r
+ }\r
} else {\r
if (CompareGuid (VendorGuid, &Variable[Index]->VendorGuid)) {\r
- ASSERT (NAMESIZE_OF_VARIABLE (Variable[Index]) != 0);\r
- if (!CompareMem (VariableName, GET_VARIABLE_NAME_PTR (Variable[Index]), NAMESIZE_OF_VARIABLE (Variable[Index]))) {\r
- PtrTrack->CurrPtr = Variable[Index];\r
- PtrTrack->Volatile = (BOOLEAN)(Index == 0);\r
- return EFI_SUCCESS;\r
+ Point = (VOID *) GetVariableNamePtr (Variable[Index]);\r
+\r
+ ASSERT (NameSizeOfVariable (Variable[Index]) != 0);\r
+ if (!CompareMem (VariableName, Point, NameSizeOfVariable (Variable[Index]))) {\r
+ if (Variable[Index]->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {\r
+ InDeletedVariable = Variable[Index];\r
+ InDeletedStorageIndex = Index;\r
+ } else {\r
+ PtrTrack->StartPtr = GetStartPointer (VariableStoreHeader[Index]);\r
+ PtrTrack->EndPtr = GetEndPointer (VariableStoreHeader[Index]);\r
+ PtrTrack->CurrPtr = Variable[Index];\r
+ PtrTrack->Volatile = (BOOLEAN)(Index == 0);\r
+\r
+ return EFI_SUCCESS;\r
+ }\r
}\r
}\r
}\r
\r
Variable[Index] = GetNextVariablePtr (Variable[Index]);\r
}\r
+ if (InDeletedVariable != NULL) {\r
+ PtrTrack->StartPtr = GetStartPointer (VariableStoreHeader[InDeletedStorageIndex]);\r
+ PtrTrack->EndPtr = GetEndPointer (VariableStoreHeader[InDeletedStorageIndex]);\r
+ PtrTrack->CurrPtr = InDeletedVariable;\r
+ PtrTrack->Volatile = (BOOLEAN)(InDeletedStorageIndex == 0);\r
+ return EFI_SUCCESS;\r
+ }\r
}\r
PtrTrack->CurrPtr = NULL;\r
return EFI_NOT_FOUND;\r
//\r
// Get data size\r
//\r
- VarDataSize = DATASIZE_OF_VARIABLE (Variable.CurrPtr);\r
+ VarDataSize = DataSizeOfVariable (Variable.CurrPtr);\r
ASSERT (VarDataSize != 0);\r
\r
if (*DataSize >= VarDataSize) {\r
//\r
if (IsValidVariableHeader (Variable.CurrPtr) && Variable.CurrPtr->State == VAR_ADDED) {\r
if (!(EfiAtRuntime () && !(Variable.CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS))) {\r
- VarNameSize = NAMESIZE_OF_VARIABLE (Variable.CurrPtr);\r
+ VarNameSize = NameSizeOfVariable (Variable.CurrPtr);\r
ASSERT (VarNameSize != 0);\r
\r
if (VarNameSize <= *VariableNameSize) {\r
CopyMem (\r
VariableName,\r
- GET_VARIABLE_NAME_PTR (Variable.CurrPtr),\r
+ GetVariableNamePtr (Variable.CurrPtr),\r
VarNameSize\r
);\r
CopyMem (\r
// If the variable is marked valid and the same data has been passed in\r
// then return to the caller immediately.\r
//\r
- if (DATASIZE_OF_VARIABLE (Variable.CurrPtr) == DataSize &&\r
+ if (DataSizeOfVariable (Variable.CurrPtr) == DataSize &&\r
(CompareMem (Data, GetVariableDataPtr (Variable.CurrPtr), DataSize) == 0)) {\r
\r
UpdateVariableInfo (VariableName, VendorGuid, Volatile, FALSE, TRUE, FALSE, FALSE);\r
goto Done;\r
} else if ((Variable.CurrPtr->State == VAR_ADDED) ||\r
(Variable.CurrPtr->State == (VAR_ADDED & VAR_IN_DELETED_TRANSITION))) {\r
+\r
//\r
// Mark the old variable as in delete transition\r
//\r
//\r
// Perform garbage collection & reclaim operation\r
//\r
- Status = Reclaim (mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase, NonVolatileOffset, FALSE);\r
+ Status = Reclaim (mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase, NonVolatileOffset, FALSE, Variable.CurrPtr);\r
if (EFI_ERROR (Status)) {\r
goto Done;\r
}\r
//\r
// Three steps\r
// 1. Write variable header\r
- // 2. Write variable data\r
- // 3. Set variable state to valid\r
+ // 2. Set variable state to header valid \r
+ // 3. Write variable data\r
+ // 4. Set variable state to valid\r
//\r
//\r
// Step 1:\r
if (EFI_ERROR (Status)) {\r
goto Done;\r
}\r
+\r
//\r
// Step 2:\r
//\r
+ NextVariable->State = VAR_HEADER_VALID_ONLY;\r
+ Status = UpdateVariableStore (\r
+ &mVariableModuleGlobal->VariableGlobal,\r
+ FALSE,\r
+ TRUE,\r
+ Instance,\r
+ *NonVolatileOffset,\r
+ sizeof (VARIABLE_HEADER),\r
+ (UINT8 *) NextVariable\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+ //\r
+ // Step 3:\r
+ //\r
Status = UpdateVariableStore (\r
&mVariableModuleGlobal->VariableGlobal,\r
FALSE,\r
goto Done;\r
}\r
//\r
- // Step 3:\r
+ // Step 4:\r
//\r
NextVariable->State = VAR_ADDED;\r
Status = UpdateVariableStore (\r
//\r
// Perform garbage collection & reclaim operation\r
//\r
- Status = Reclaim (mVariableModuleGlobal->VariableGlobal.VolatileVariableBase, VolatileOffset, TRUE);\r
+ Status = Reclaim (mVariableModuleGlobal->VariableGlobal.VolatileVariableBase, VolatileOffset, TRUE, Variable.CurrPtr);\r
if (EFI_ERROR (Status)) {\r
goto Done;\r
}\r
return EFI_SUCCESS;\r
}\r
\r
+VOID\r
+EFIAPI\r
+ReclaimForOS(\r
+ EFI_EVENT Event,\r
+ VOID *Context\r
+ )\r
+{\r
+ UINT32 VarSize;\r
+ EFI_STATUS Status;\r
+\r
+ VarSize = ((VARIABLE_STORE_HEADER *) ((UINTN) mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase))->Size;\r
+ Status = EFI_SUCCESS; \r
+\r
+ //\r
+ // Check if the free area is blow a threshold\r
+ //\r
+ if ((VarSize - mVariableModuleGlobal->NonVolatileLastVariableOffset) < VARIABLE_RECLAIM_THRESHOLD) {\r
+ Status = Reclaim (\r
+ mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase,\r
+ &mVariableModuleGlobal->NonVolatileLastVariableOffset,\r
+ FALSE,\r
+ NULL\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ }\r
+}\r
+\r
EFI_STATUS\r
VariableCommonInitialize (\r
IN EFI_HANDLE ImageHandle,\r
UINT8 Data;\r
UINT64 VariableStoreBase;\r
UINT64 VariableStoreLength;\r
+ EFI_EVENT ReadyToBootEvent;\r
\r
+ Status = EFI_SUCCESS;\r
+ //\r
+ // Allocate runtime memory for variable driver global structure.\r
+ //\r
+ mVariableModuleGlobal = AllocateRuntimePool (sizeof (VARIABLE_MODULE_GLOBAL));\r
+ if (mVariableModuleGlobal == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
\r
EfiInitializeLock(&mVariableModuleGlobal->VariableGlobal.VariableServicesLock, TPL_NOTIFY);\r
mVariableModuleGlobal->VariableGlobal.ReentrantState = 0;\r
\r
Status = gDS->GetMemorySpaceDescriptor (BaseAddress, &GcdDescriptor);\r
if (EFI_ERROR (Status)) {\r
- FreePool (mVariableModuleGlobal);\r
- FreePool (VolatileVariableStore);\r
- return EFI_UNSUPPORTED;\r
+ goto Done;\r
}\r
\r
Status = gDS->SetMemorySpaceAttributes (\r
GcdDescriptor.Attributes | EFI_MEMORY_RUNTIME\r
);\r
if (EFI_ERROR (Status)) {\r
- FreePool (mVariableModuleGlobal);\r
- FreePool (VolatileVariableStore);\r
- return EFI_UNSUPPORTED;\r
+ goto Done;\r
}\r
//\r
// Get address of non volatile variable store base\r
ASSERT(VariableStoreHeader->Size == VariableStoreLength);\r
\r
if (EFI_ERROR (Status)) {\r
- return Status;\r
+ goto Done;\r
}\r
}\r
\r
\r
mVariableModuleGlobal->NonVolatileLastVariableOffset = (UINTN) NextVariable - (UINTN) CurrPtr;\r
\r
- //\r
- // Check if the free area is blow a threshold\r
- //\r
- if ((((VARIABLE_STORE_HEADER *)((UINTN) CurrPtr))->Size - mVariableModuleGlobal->NonVolatileLastVariableOffset) < VARIABLE_RECLAIM_THRESHOLD) {\r
- Status = Reclaim (\r
- mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase,\r
- &mVariableModuleGlobal->NonVolatileLastVariableOffset,\r
- FALSE\r
- );\r
- }\r
-\r
- if (EFI_ERROR (Status)) {\r
- FreePool (mVariableModuleGlobal);\r
- FreePool (VolatileVariableStore);\r
- return Status;\r
- }\r
-\r
//\r
// Check if the free area is really free.\r
//\r
Status = Reclaim (\r
mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase,\r
&mVariableModuleGlobal->NonVolatileLastVariableOffset,\r
- FALSE\r
+ FALSE,\r
+ NULL\r
);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
break;\r
}\r
}\r
+\r
+ //\r
+ // Register the event handling function to reclaim variable for OS usage.\r
+ //\r
+ Status = EfiCreateEventReadyToBootEx (\r
+ TPL_NOTIFY, \r
+ ReclaimForOS, \r
+ NULL, \r
+ &ReadyToBootEvent\r
+ );\r
}\r
\r
+Done:\r
if (EFI_ERROR (Status)) {\r
FreePool (mVariableModuleGlobal);\r
FreePool (VolatileVariableStore);\r
return Status;\r
}\r
\r
-\r
-\r
-\r
VOID\r
EFIAPI\r
VariableClassAddressChangeEvent (\r