The common variable operation routines shared by DXE_RUNTIME variable \r
module and DXE_SMM variable module.\r
\r
-Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>\r
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
@param IsVolatile The variable store is volatile or not;\r
if it is non-volatile, need FTW.\r
@param UpdatingPtrTrack Pointer to updating variable pointer track structure.\r
- @param ReclaimAnyway If TRUE, do reclaim anyway.\r
+ @param NewVariable Pointer to new variable.\r
+ @param NewVariableSize New variable size.\r
\r
@return EFI_OUT_OF_RESOURCES\r
@return EFI_SUCCESS\r
OUT UINTN *LastVariableOffset,\r
IN BOOLEAN IsVolatile,\r
IN OUT VARIABLE_POINTER_TRACK *UpdatingPtrTrack,\r
- IN BOOLEAN ReclaimAnyway\r
+ IN VARIABLE_HEADER *NewVariable,\r
+ IN UINTN NewVariableSize\r
)\r
{\r
VARIABLE_HEADER *Variable;\r
UINT8 *ValidBuffer;\r
UINTN MaximumBufferSize;\r
UINTN VariableSize;\r
- UINTN VariableNameSize;\r
- UINTN UpdatingVariableNameSize;\r
UINTN NameSize;\r
UINT8 *CurrPtr;\r
VOID *Point0;\r
VOID *Point1;\r
BOOLEAN FoundAdded;\r
EFI_STATUS Status;\r
- CHAR16 *VariableNamePtr;\r
- CHAR16 *UpdatingVariableNamePtr;\r
UINTN CommonVariableTotalSize;\r
UINTN HwErrVariableTotalSize;\r
- BOOLEAN NeedDoReclaim;\r
VARIABLE_HEADER *UpdatingVariable;\r
+ VARIABLE_HEADER *UpdatingInDeletedTransition;\r
\r
UpdatingVariable = NULL;\r
+ UpdatingInDeletedTransition = NULL;\r
if (UpdatingPtrTrack != NULL) {\r
UpdatingVariable = UpdatingPtrTrack->CurrPtr;\r
+ UpdatingInDeletedTransition = UpdatingPtrTrack->InDeletedTransitionPtr;\r
}\r
\r
- NeedDoReclaim = FALSE;\r
VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINTN) VariableBase);\r
\r
CommonVariableTotalSize = 0;\r
HwErrVariableTotalSize = 0;\r
\r
- //\r
- // Start Pointers for the variable.\r
- //\r
- Variable = GetStartPointer (VariableStoreHeader);\r
- MaximumBufferSize = sizeof (VARIABLE_STORE_HEADER);\r
+ if (IsVolatile) {\r
+ //\r
+ // Start Pointers for the variable.\r
+ //\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
- Variable->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)\r
- ) {\r
- VariableSize = (UINTN) NextVariable - (UINTN) Variable;\r
- MaximumBufferSize += VariableSize;\r
- } else {\r
- NeedDoReclaim = TRUE;\r
- }\r
+ while (IsValidVariableHeader (Variable)) {\r
+ NextVariable = GetNextVariablePtr (Variable);\r
+ if ((Variable->State == VAR_ADDED || Variable->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) &&\r
+ Variable != UpdatingVariable &&\r
+ Variable != UpdatingInDeletedTransition\r
+ ) {\r
+ VariableSize = (UINTN) NextVariable - (UINTN) Variable;\r
+ MaximumBufferSize += VariableSize;\r
+ }\r
\r
- Variable = NextVariable;\r
- }\r
+ Variable = NextVariable;\r
+ }\r
\r
- if (!ReclaimAnyway && !NeedDoReclaim) {\r
- DEBUG ((EFI_D_INFO, "Variable driver: no DELETED variable found, so no variable space could be reclaimed.\n"));\r
- return EFI_SUCCESS;\r
- }\r
+ if (NewVariable != NULL) {\r
+ //\r
+ // Add the new variable size.\r
+ //\r
+ MaximumBufferSize += NewVariableSize;\r
+ }\r
\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
+ // 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
+ } else {\r
+ //\r
+ // For NV variable reclaim, don't allocate pool here and just use mNvVariableCache\r
+ // as the buffer to reduce SMRAM consumption for SMM variable driver.\r
+ //\r
+ MaximumBufferSize = mNvVariableCache->Size;\r
+ ValidBuffer = (UINT8 *) mNvVariableCache;\r
}\r
\r
SetMem (ValidBuffer, MaximumBufferSize, 0xff);\r
Variable = GetStartPointer (VariableStoreHeader);\r
while (IsValidVariableHeader (Variable)) {\r
NextVariable = GetNextVariablePtr (Variable);\r
- if (Variable->State == VAR_ADDED) {\r
- if (UpdatingVariable != NULL) {\r
- if (UpdatingVariable == Variable) {\r
- Variable = NextVariable;\r
- continue;\r
- }\r
-\r
- VariableNameSize = NameSizeOfVariable(Variable);\r
- UpdatingVariableNameSize = NameSizeOfVariable(UpdatingVariable);\r
-\r
- VariableNamePtr = GetVariableNamePtr (Variable);\r
- UpdatingVariableNamePtr = GetVariableNamePtr (UpdatingVariable);\r
- if (CompareGuid (&Variable->VendorGuid, &UpdatingVariable->VendorGuid) &&\r
- VariableNameSize == UpdatingVariableNameSize &&\r
- CompareMem (VariableNamePtr, UpdatingVariableNamePtr, VariableNameSize) == 0 ) {\r
- Variable = NextVariable;\r
- continue;\r
- }\r
- }\r
+ if (Variable != UpdatingVariable && Variable->State == VAR_ADDED) {\r
VariableSize = (UINTN) NextVariable - (UINTN) Variable;\r
CopyMem (CurrPtr, (UINT8 *) Variable, VariableSize);\r
CurrPtr += VariableSize;\r
Variable = NextVariable;\r
}\r
\r
- //\r
- // Reinstall the variable being updated if it is not NULL.\r
- //\r
- if (UpdatingVariable != NULL) {\r
- VariableSize = (UINTN)(GetNextVariablePtr (UpdatingVariable)) - (UINTN)UpdatingVariable;\r
- CopyMem (CurrPtr, (UINT8 *) UpdatingVariable, VariableSize);\r
- UpdatingPtrTrack->CurrPtr = (VARIABLE_HEADER *)((UINTN)UpdatingPtrTrack->StartPtr + ((UINTN)CurrPtr - (UINTN)GetStartPointer ((VARIABLE_STORE_HEADER *) ValidBuffer)));\r
- UpdatingPtrTrack->InDeletedTransitionPtr = NULL;\r
- CurrPtr += VariableSize;\r
- if ((!IsVolatile) && ((UpdatingVariable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {\r
- HwErrVariableTotalSize += VariableSize;\r
- } else if ((!IsVolatile) && ((UpdatingVariable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {\r
- CommonVariableTotalSize += VariableSize;\r
- }\r
- }\r
-\r
//\r
// Reinstall all in delete transition variables.\r
// \r
- Variable = GetStartPointer (VariableStoreHeader);\r
+ Variable = GetStartPointer (VariableStoreHeader);\r
while (IsValidVariableHeader (Variable)) {\r
NextVariable = GetNextVariablePtr (Variable);\r
- if (Variable != UpdatingVariable && Variable->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {\r
+ if (Variable != UpdatingVariable && Variable != UpdatingInDeletedTransition && Variable->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {\r
\r
//\r
// Buffer has cached all ADDED variable. \r
Variable = NextVariable;\r
}\r
\r
+ //\r
+ // Install the new variable if it is not NULL.\r
+ //\r
+ if (NewVariable != NULL) {\r
+ if ((UINTN) (CurrPtr - ValidBuffer) + NewVariableSize > VariableStoreHeader->Size) {\r
+ //\r
+ // No enough space to store the new variable.\r
+ //\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
+ }\r
+ if (!IsVolatile) {\r
+ if ((NewVariable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD) {\r
+ HwErrVariableTotalSize += NewVariableSize;\r
+ } else if ((NewVariable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != EFI_VARIABLE_HARDWARE_ERROR_RECORD) {\r
+ CommonVariableTotalSize += NewVariableSize;\r
+ }\r
+ if ((HwErrVariableTotalSize > PcdGet32 (PcdHwErrStorageSize)) ||\r
+ (CommonVariableTotalSize > VariableStoreHeader->Size - sizeof (VARIABLE_STORE_HEADER) - PcdGet32 (PcdHwErrStorageSize))) {\r
+ //\r
+ // No enough space to store the new variable by NV or NV+HR attribute.\r
+ //\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
+ }\r
+ }\r
+\r
+ CopyMem (CurrPtr, (UINT8 *) NewVariable, NewVariableSize);\r
+ ((VARIABLE_HEADER *) CurrPtr)->State = VAR_ADDED;\r
+ if (UpdatingVariable != NULL) {\r
+ UpdatingPtrTrack->CurrPtr = (VARIABLE_HEADER *)((UINTN)UpdatingPtrTrack->StartPtr + ((UINTN)CurrPtr - (UINTN)GetStartPointer ((VARIABLE_STORE_HEADER *) ValidBuffer)));\r
+ UpdatingPtrTrack->InDeletedTransitionPtr = NULL;\r
+ }\r
+ CurrPtr += NewVariableSize;\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, (UINTN) (CurrPtr - (UINT8 *) ValidBuffer));\r
+ CopyMem ((UINT8 *) (UINTN) VariableBase, ValidBuffer, (UINTN) (CurrPtr - ValidBuffer));\r
+ *LastVariableOffset = (UINTN) (CurrPtr - ValidBuffer);\r
Status = EFI_SUCCESS;\r
} else {\r
//\r
//\r
Status = FtwVariableSpace (\r
VariableBase,\r
- ValidBuffer,\r
- (UINTN) (CurrPtr - (UINT8 *) ValidBuffer)\r
+ (VARIABLE_STORE_HEADER *) ValidBuffer\r
);\r
- CopyMem (mNvVariableCache, (CHAR8 *)(UINTN)VariableBase, VariableStoreHeader->Size);\r
- }\r
- if (!EFI_ERROR (Status)) {\r
- *LastVariableOffset = (UINTN) (CurrPtr - (UINT8 *) ValidBuffer);\r
- if (!IsVolatile) {\r
+ if (!EFI_ERROR (Status)) {\r
+ *LastVariableOffset = (UINTN) (CurrPtr - ValidBuffer);\r
mVariableModuleGlobal->HwErrVariableTotalSize = HwErrVariableTotalSize;\r
mVariableModuleGlobal->CommonVariableTotalSize = CommonVariableTotalSize;\r
- }\r
- } else {\r
- NextVariable = GetStartPointer ((VARIABLE_STORE_HEADER *)(UINTN)VariableBase);\r
- while (IsValidVariableHeader (NextVariable)) {\r
- VariableSize = NextVariable->NameSize + NextVariable->DataSize + sizeof (VARIABLE_HEADER);\r
- if ((!IsVolatile) && ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {\r
- mVariableModuleGlobal->HwErrVariableTotalSize += HEADER_ALIGN (VariableSize);\r
- } else if ((!IsVolatile) && ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {\r
- mVariableModuleGlobal->CommonVariableTotalSize += HEADER_ALIGN (VariableSize);\r
- }\r
+ } else {\r
+ NextVariable = GetStartPointer ((VARIABLE_STORE_HEADER *)(UINTN)VariableBase);\r
+ while (IsValidVariableHeader (NextVariable)) {\r
+ VariableSize = NextVariable->NameSize + NextVariable->DataSize + sizeof (VARIABLE_HEADER);\r
+ if ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD) {\r
+ mVariableModuleGlobal->HwErrVariableTotalSize += HEADER_ALIGN (VariableSize);\r
+ } else if ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != EFI_VARIABLE_HARDWARE_ERROR_RECORD) {\r
+ mVariableModuleGlobal->CommonVariableTotalSize += HEADER_ALIGN (VariableSize);\r
+ }\r
\r
- NextVariable = GetNextVariablePtr (NextVariable);\r
+ NextVariable = GetNextVariablePtr (NextVariable);\r
+ }\r
+ *LastVariableOffset = (UINTN) NextVariable - (UINTN) VariableBase;\r
}\r
- *LastVariableOffset = (UINTN) NextVariable - (UINTN) VariableBase;\r
}\r
\r
- FreePool (ValidBuffer);\r
+Done:\r
+ if (IsVolatile) {\r
+ FreePool (ValidBuffer);\r
+ } else {\r
+ //\r
+ // For NV variable reclaim, we use mNvVariableCache as the buffer, so copy the data back.\r
+ //\r
+ CopyMem (mNvVariableCache, (UINT8 *)(UINTN)VariableBase, VariableStoreHeader->Size);\r
+ }\r
\r
return Status;\r
}\r
\r
@param[in] DataSize Size of data. 0 means delete.\r
\r
+ @retval EFI_SUCCESS The update operation is successful or ignored.\r
+ @retval EFI_WRITE_PROTECTED Update PlatformLangCodes/LangCodes at runtime.\r
+ @retval EFI_OUT_OF_RESOURCES No enough variable space to do the update operation.\r
+ @retval Others Other errors happened during the update operation.\r
+\r
**/\r
-VOID\r
+EFI_STATUS\r
AutoUpdateLangVariable (\r
IN CHAR16 *VariableName,\r
IN VOID *Data,\r
// Don't do updates for delete operation\r
//\r
if (DataSize == 0) {\r
- return;\r
+ return EFI_SUCCESS;\r
}\r
\r
SetLanguageCodes = FALSE;\r
// PlatformLangCodes is a volatile variable, so it can not be updated at runtime.\r
//\r
if (AtRuntime ()) {\r
- return;\r
+ return EFI_WRITE_PROTECTED;\r
}\r
\r
SetLanguageCodes = TRUE;\r
// LangCodes is a volatile variable, so it can not be updated at runtime.\r
//\r
if (AtRuntime ()) {\r
- return;\r
+ return EFI_WRITE_PROTECTED;\r
}\r
\r
SetLanguageCodes = TRUE;\r
//\r
// Neither PlatformLang nor Lang is set, directly return\r
//\r
- return;\r
+ return EFI_SUCCESS;\r
}\r
}\r
}\r
- \r
+\r
+ Status = EFI_SUCCESS;\r
+\r
//\r
// According to UEFI spec, "Lang" and "PlatformLang" is NV|BS|RT attributions.\r
//\r
Status = UpdateVariable (EFI_LANG_VARIABLE_NAME, &gEfiGlobalVariableGuid, BestLang,\r
ISO_639_2_ENTRY_SIZE + 1, Attributes, &Variable);\r
\r
- DEBUG ((EFI_D_INFO, "Variable Driver Auto Update PlatformLang, PlatformLang:%a, Lang:%a\n", BestPlatformLang, BestLang));\r
-\r
- ASSERT_EFI_ERROR(Status);\r
+ DEBUG ((EFI_D_INFO, "Variable Driver Auto Update PlatformLang, PlatformLang:%a, Lang:%a: Status: %r\n", BestPlatformLang, BestLang, Status));\r
}\r
}\r
\r
Status = UpdateVariable (EFI_PLATFORM_LANG_VARIABLE_NAME, &gEfiGlobalVariableGuid, BestPlatformLang, \r
AsciiStrSize (BestPlatformLang), Attributes, &Variable);\r
\r
- DEBUG ((EFI_D_INFO, "Variable Driver Auto Update Lang, Lang:%a, PlatformLang:%a\n", BestLang, BestPlatformLang));\r
- ASSERT_EFI_ERROR (Status);\r
+ DEBUG ((EFI_D_INFO, "Variable Driver Auto Update Lang, Lang:%a, PlatformLang:%a Status: %r\n", BestLang, BestPlatformLang, Status));\r
}\r
}\r
}\r
+\r
+ return Status;\r
}\r
\r
/**\r
goto Done;\r
}\r
//\r
- // Perform garbage collection & reclaim operation.\r
+ // Perform garbage collection & reclaim operation, and integrate the new variable at the same time.\r
//\r
Status = Reclaim (mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase, \r
- &mVariableModuleGlobal->NonVolatileLastVariableOffset, FALSE, Variable, FALSE);\r
- if (EFI_ERROR (Status)) {\r
- goto Done;\r
- }\r
- //\r
- // If still no enough space, return out of resources.\r
- //\r
- if ((((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != 0) \r
- && ((VarSize + mVariableModuleGlobal->HwErrVariableTotalSize) > PcdGet32 (PcdHwErrStorageSize)))\r
- || (((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == 0) \r
- && ((VarSize + mVariableModuleGlobal->CommonVariableTotalSize) > NonVolatileVarableStoreSize - sizeof (VARIABLE_STORE_HEADER) - PcdGet32 (PcdHwErrStorageSize)))) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto Done;\r
- }\r
- if (Variable->CurrPtr != NULL) {\r
- CacheVariable->CurrPtr = (VARIABLE_HEADER *)((UINTN) CacheVariable->StartPtr + ((UINTN) Variable->CurrPtr - (UINTN) Variable->StartPtr));\r
- CacheVariable->InDeletedTransitionPtr = NULL;\r
+ &mVariableModuleGlobal->NonVolatileLastVariableOffset, FALSE, Variable, NextVariable, HEADER_ALIGN (VarSize));\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // The new variable has been integrated successfully during reclaiming.\r
+ //\r
+ if (Variable->CurrPtr != NULL) {\r
+ CacheVariable->CurrPtr = (VARIABLE_HEADER *)((UINTN) CacheVariable->StartPtr + ((UINTN) Variable->CurrPtr - (UINTN) Variable->StartPtr));\r
+ CacheVariable->InDeletedTransitionPtr = NULL;\r
+ }\r
+ UpdateVariableInfo (VariableName, VendorGuid, FALSE, FALSE, TRUE, FALSE, FALSE);\r
+ FlushHobVariableToFlash (VariableName, VendorGuid);\r
}\r
+ goto Done;\r
}\r
//\r
// Four steps\r
if ((UINT32) (VarSize + mVariableModuleGlobal->VolatileLastVariableOffset) >\r
((VARIABLE_STORE_HEADER *) ((UINTN) (mVariableModuleGlobal->VariableGlobal.VolatileVariableBase)))->Size) {\r
//\r
- // Perform garbage collection & reclaim operation.\r
+ // Perform garbage collection & reclaim operation, and integrate the new variable at the same time.\r
//\r
Status = Reclaim (mVariableModuleGlobal->VariableGlobal.VolatileVariableBase, \r
- &mVariableModuleGlobal->VolatileLastVariableOffset, TRUE, Variable, FALSE);\r
- if (EFI_ERROR (Status)) {\r
- goto Done;\r
- }\r
- //\r
- // If still no enough space, return out of resources.\r
- //\r
- if ((UINT32) (VarSize + mVariableModuleGlobal->VolatileLastVariableOffset) >\r
- ((VARIABLE_STORE_HEADER *) ((UINTN) (mVariableModuleGlobal->VariableGlobal.VolatileVariableBase)))->Size\r
- ) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto Done;\r
- }\r
- if (Variable->CurrPtr != NULL) {\r
- CacheVariable->CurrPtr = (VARIABLE_HEADER *)((UINTN) CacheVariable->StartPtr + ((UINTN) Variable->CurrPtr - (UINTN) Variable->StartPtr));\r
- CacheVariable->InDeletedTransitionPtr = NULL;\r
+ &mVariableModuleGlobal->VolatileLastVariableOffset, TRUE, Variable, NextVariable, HEADER_ALIGN (VarSize));\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // The new variable has been integrated successfully during reclaiming.\r
+ //\r
+ if (Variable->CurrPtr != NULL) {\r
+ CacheVariable->CurrPtr = (VARIABLE_HEADER *)((UINTN) CacheVariable->StartPtr + ((UINTN) Variable->CurrPtr - (UINTN) Variable->StartPtr));\r
+ CacheVariable->InDeletedTransitionPtr = NULL;\r
+ }\r
+ UpdateVariableInfo (VariableName, VendorGuid, TRUE, FALSE, TRUE, FALSE, FALSE);\r
}\r
+ goto Done;\r
}\r
\r
NextVariable->State = VAR_ADDED;\r
//\r
// Hook the operation of setting PlatformLangCodes/PlatformLang and LangCodes/Lang.\r
//\r
- AutoUpdateLangVariable (VariableName, Data, DataSize);\r
+ Status = AutoUpdateLangVariable (VariableName, Data, DataSize);\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // The auto update operation failed, directly return to avoid inconsistency between PlatformLang and Lang.\r
+ //\r
+ goto Done;\r
+ }\r
\r
Status = UpdateVariable (VariableName, VendorGuid, Data, DataSize, Attributes, &Variable);\r
\r
&mVariableModuleGlobal->NonVolatileLastVariableOffset,\r
FALSE,\r
NULL,\r
- FALSE\r
+ NULL,\r
+ 0\r
);\r
ASSERT_EFI_ERROR (Status);\r
}\r
&mVariableModuleGlobal->NonVolatileLastVariableOffset,\r
FALSE,\r
NULL,\r
- TRUE\r
+ NULL,\r
+ 0\r
);\r
if (EFI_ERROR (Status)) {\r
return Status;\r