VirtualBox

Ignore:
Timestamp:
Oct 28, 2015 8:17:18 PM (9 years ago)
Author:
vboxsync
Message:

EFI/Firmware: 'svn merge /vendor/edk2/UDK2010.SR1 /vendor/edk2/current .', reverting and removing files+dirs listed in ReadMe.vbox, resolving conflicts with help from ../UDK2014.SP1/. This is a raw untested merge.

Location:
trunk/src/VBox/Devices/EFI/Firmware
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/EFI/Firmware

  • trunk/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c

    r48674 r58459  
    11/** @file
    22
    3   The common variable operation routines shared by DXE_RINTIME variable
     3  The common variable operation routines shared by DXE_RUNTIME variable
    44  module and DXE_SMM variable module.
    55 
    6 Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
     6  Caution: This module requires additional review when modified.
     7  This driver will have external input - variable data. They may be input in SMM mode.
     8  This external input must be validated carefully to avoid security issue like
     9  buffer overflow, integer overflow.
     10
     11  VariableServiceGetNextVariableName () and VariableServiceQueryVariableInfo() are external API.
     12  They need check input parameter.
     13
     14  VariableServiceGetVariable() and VariableServiceSetVariable() are external API
     15  to receive datasize and data buffer. The size should be checked carefully.
     16
     17Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
    718This program and the accompanying materials                         
    819are licensed and made available under the terms and conditions of the BSD License         
     
    2233/// Define a memory cache that improves the search performance for a variable.
    2334///
    24 VARIABLE_STORE_HEADER  *mNvVariableCache = NULL;
     35VARIABLE_STORE_HEADER  *mNvVariableCache      = NULL;
    2536
    2637///
    2738/// The memory entry used for variable statistics data.
    2839///
    29 VARIABLE_INFO_ENTRY    *gVariableInfo    = NULL;
    30 
     40VARIABLE_INFO_ENTRY    *gVariableInfo         = NULL;
     41
     42///
     43/// The list to store the variables which cannot be set after the EFI_END_OF_DXE_EVENT_GROUP_GUID
     44/// or EVT_GROUP_READY_TO_BOOT event.
     45///
     46LIST_ENTRY             mLockedVariableList    = INITIALIZE_LIST_HEAD_VARIABLE (mLockedVariableList);
     47
     48///
     49/// The flag to indicate whether the platform has left the DXE phase of execution.
     50///
     51BOOLEAN                mEndOfDxe              = FALSE;
     52
     53///
     54/// The flag to indicate whether the variable storage locking is enabled.
     55///
     56BOOLEAN                mEnableLocking         = TRUE;
     57
     58//
     59// To prevent name collisions with possible future globally defined variables,
     60// other internal firmware data variables that are not defined here must be
     61// saved with a unique VendorGuid other than EFI_GLOBAL_VARIABLE or
     62// any other GUID defined by the UEFI Specification. Implementations must
     63// only permit the creation of variables with a UEFI Specification-defined
     64// VendorGuid when these variables are documented in the UEFI Specification.
     65//
     66GLOBAL_VARIABLE_ENTRY mGlobalVariableList[] = {
     67  {EFI_LANG_CODES_VARIABLE_NAME,             VARIABLE_ATTRIBUTE_BS_RT},
     68  {EFI_LANG_VARIABLE_NAME,                   VARIABLE_ATTRIBUTE_NV_BS_RT},
     69  {EFI_TIME_OUT_VARIABLE_NAME,               VARIABLE_ATTRIBUTE_NV_BS_RT},
     70  {EFI_PLATFORM_LANG_CODES_VARIABLE_NAME,    VARIABLE_ATTRIBUTE_BS_RT},
     71  {EFI_PLATFORM_LANG_VARIABLE_NAME,          VARIABLE_ATTRIBUTE_NV_BS_RT},
     72  {EFI_CON_IN_VARIABLE_NAME,                 VARIABLE_ATTRIBUTE_NV_BS_RT},
     73  {EFI_CON_OUT_VARIABLE_NAME,                VARIABLE_ATTRIBUTE_NV_BS_RT},
     74  {EFI_ERR_OUT_VARIABLE_NAME,                VARIABLE_ATTRIBUTE_NV_BS_RT},
     75  {EFI_CON_IN_DEV_VARIABLE_NAME,             VARIABLE_ATTRIBUTE_BS_RT},
     76  {EFI_CON_OUT_DEV_VARIABLE_NAME,            VARIABLE_ATTRIBUTE_BS_RT},
     77  {EFI_ERR_OUT_DEV_VARIABLE_NAME,            VARIABLE_ATTRIBUTE_BS_RT},
     78  {EFI_BOOT_ORDER_VARIABLE_NAME,             VARIABLE_ATTRIBUTE_NV_BS_RT},
     79  {EFI_BOOT_NEXT_VARIABLE_NAME,              VARIABLE_ATTRIBUTE_NV_BS_RT},
     80  {EFI_BOOT_CURRENT_VARIABLE_NAME,           VARIABLE_ATTRIBUTE_BS_RT},
     81  {EFI_BOOT_OPTION_SUPPORT_VARIABLE_NAME,    VARIABLE_ATTRIBUTE_BS_RT},
     82  {EFI_DRIVER_ORDER_VARIABLE_NAME,           VARIABLE_ATTRIBUTE_NV_BS_RT},
     83  {EFI_HW_ERR_REC_SUPPORT_VARIABLE_NAME,     VARIABLE_ATTRIBUTE_NV_BS_RT},
     84  {EFI_SETUP_MODE_NAME,                      VARIABLE_ATTRIBUTE_BS_RT},
     85  {EFI_KEY_EXCHANGE_KEY_NAME,                VARIABLE_ATTRIBUTE_NV_BS_RT_AT},
     86  {EFI_PLATFORM_KEY_NAME,                    VARIABLE_ATTRIBUTE_NV_BS_RT_AT},
     87  {EFI_SIGNATURE_SUPPORT_NAME,               VARIABLE_ATTRIBUTE_BS_RT},
     88  {EFI_SECURE_BOOT_MODE_NAME,                VARIABLE_ATTRIBUTE_BS_RT},
     89  {EFI_KEK_DEFAULT_VARIABLE_NAME,            VARIABLE_ATTRIBUTE_BS_RT},
     90  {EFI_PK_DEFAULT_VARIABLE_NAME,             VARIABLE_ATTRIBUTE_BS_RT},
     91  {EFI_DB_DEFAULT_VARIABLE_NAME,             VARIABLE_ATTRIBUTE_BS_RT},
     92  {EFI_DBX_DEFAULT_VARIABLE_NAME,            VARIABLE_ATTRIBUTE_BS_RT},
     93  {EFI_DBT_DEFAULT_VARIABLE_NAME,            VARIABLE_ATTRIBUTE_BS_RT},
     94  {EFI_OS_INDICATIONS_SUPPORT_VARIABLE_NAME, VARIABLE_ATTRIBUTE_BS_RT},
     95  {EFI_OS_INDICATIONS_VARIABLE_NAME,         VARIABLE_ATTRIBUTE_NV_BS_RT},
     96  {EFI_VENDOR_KEYS_VARIABLE_NAME,            VARIABLE_ATTRIBUTE_BS_RT},
     97};
     98GLOBAL_VARIABLE_ENTRY mGlobalVariableList2[] = {
     99  {L"Boot####",                              VARIABLE_ATTRIBUTE_NV_BS_RT},
     100  {L"Driver####",                            VARIABLE_ATTRIBUTE_NV_BS_RT},
     101  {L"Key####",                               VARIABLE_ATTRIBUTE_NV_BS_RT},
     102};
    31103
    32104/**
     
    79151
    80152      CopyGuid (&gVariableInfo->VendorGuid, VendorGuid);
    81       gVariableInfo->Name = AllocatePool (StrSize (VariableName));
     153      gVariableInfo->Name = AllocateZeroPool (StrSize (VariableName));
    82154      ASSERT (gVariableInfo->Name != NULL);
    83       StrCpy (gVariableInfo->Name, VariableName);
     155      StrnCpy (gVariableInfo->Name, VariableName, StrLen (VariableName));
    84156      gVariableInfo->Volatile = Volatile;
    85157    }
     
    115187
    116188        CopyGuid (&Entry->Next->VendorGuid, VendorGuid);
    117         Entry->Next->Name = AllocatePool (StrSize (VariableName));
     189        Entry->Next->Name = AllocateZeroPool (StrSize (VariableName));
    118190        ASSERT (Entry->Next->Name != NULL);
    119         StrCpy (Entry->Next->Name, VariableName);
     191        StrnCpy (Entry->Next->Name, VariableName, StrLen (VariableName));
    120192        Entry->Next->Volatile = Volatile;
    121193      }
     
    130202  This code checks if variable header is valid or not.
    131203
    132   @param Variable        Pointer to the Variable Header.
    133 
    134   @retval TRUE           Variable header is valid.
    135   @retval FALSE          Variable header is not valid.
     204  @param Variable           Pointer to the Variable Header.
     205  @param VariableStoreEnd   Pointer to the Variable Store End.
     206
     207  @retval TRUE              Variable header is valid.
     208  @retval FALSE             Variable header is not valid.
    136209
    137210**/
    138211BOOLEAN
    139212IsValidVariableHeader (
    140   IN  VARIABLE_HEADER   *Variable
     213  IN  VARIABLE_HEADER       *Variable,
     214  IN  VARIABLE_HEADER       *VariableStoreEnd
    141215  )
    142216{
    143   if (Variable == NULL || Variable->StartId != VARIABLE_DATA) {
     217  if ((Variable == NULL) || (Variable >= VariableStoreEnd) || (Variable->StartId != VARIABLE_DATA)) {
     218    //
     219    // Variable is NULL or has reached the end of variable store,
     220    // or the StartId is not correct.
     221    //
    144222    return FALSE;
    145223  }
     
    439517  UINTN Value;
    440518
    441   if (!IsValidVariableHeader (Variable)) {
    442     return NULL;
    443   }
    444 
    445519  Value =  (UINTN) GetVariableDataPtr (Variable);
    446520  Value += DataSizeOfVariable (Variable);
     
    505579  @param IsVolatile              The variable store is volatile or not;
    506580                                 if it is non-volatile, need FTW.
    507   @param UpdatingVariable        Pointer to updating variable.
     581  @param UpdatingPtrTrack        Pointer to updating variable pointer track structure.
     582  @param NewVariable             Pointer to new variable.
     583  @param NewVariableSize         New variable size.
    508584
    509585  @return EFI_OUT_OF_RESOURCES
     
    517593  OUT UINTN                 *LastVariableOffset,
    518594  IN  BOOLEAN               IsVolatile,
    519   IN  VARIABLE_HEADER       *UpdatingVariable
     595  IN OUT VARIABLE_POINTER_TRACK *UpdatingPtrTrack,
     596  IN  VARIABLE_HEADER       *NewVariable,
     597  IN  UINTN                 NewVariableSize
    520598  )
    521599{
     
    528606  UINTN                 MaximumBufferSize;
    529607  UINTN                 VariableSize;
    530   UINTN                 VariableNameSize;
    531   UINTN                 UpdatingVariableNameSize;
    532608  UINTN                 NameSize;
    533609  UINT8                 *CurrPtr;
     
    536612  BOOLEAN               FoundAdded;
    537613  EFI_STATUS            Status;
    538   CHAR16                *VariableNamePtr;
    539   CHAR16                *UpdatingVariableNamePtr;
     614  UINTN                 CommonVariableTotalSize;
     615  UINTN                 HwErrVariableTotalSize;
     616  VARIABLE_HEADER       *UpdatingVariable;
     617  VARIABLE_HEADER       *UpdatingInDeletedTransition;
     618
     619  UpdatingVariable = NULL;
     620  UpdatingInDeletedTransition = NULL;
     621  if (UpdatingPtrTrack != NULL) {
     622    UpdatingVariable = UpdatingPtrTrack->CurrPtr;
     623    UpdatingInDeletedTransition = UpdatingPtrTrack->InDeletedTransitionPtr;
     624  }
    540625
    541626  VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINTN) VariableBase);
    542   //
    543   // Recalculate the total size of Common/HwErr type variables in non-volatile area.
    544   //
    545   if (!IsVolatile) {
    546     mVariableModuleGlobal->CommonVariableTotalSize = 0;
    547     mVariableModuleGlobal->HwErrVariableTotalSize  = 0;
    548   }
    549 
    550   //
    551   // Start Pointers for the variable.
    552   //
    553   Variable          = GetStartPointer (VariableStoreHeader);
    554   MaximumBufferSize = sizeof (VARIABLE_STORE_HEADER);
    555 
    556   while (IsValidVariableHeader (Variable)) {
    557     NextVariable = GetNextVariablePtr (Variable);
    558     if (Variable->State == VAR_ADDED ||
    559         Variable->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)
    560        ) {
    561       VariableSize = (UINTN) NextVariable - (UINTN) Variable;
    562       MaximumBufferSize += VariableSize;
    563     }
    564 
    565     Variable = NextVariable;
    566   }
    567 
    568   //
    569   // Reserve the 1 Bytes with Oxff to identify the
    570   // end of the variable buffer.
    571   //
    572   MaximumBufferSize += 1;
    573   ValidBuffer = AllocatePool (MaximumBufferSize);
    574   if (ValidBuffer == NULL) {
    575     return EFI_OUT_OF_RESOURCES;
     627
     628  CommonVariableTotalSize = 0;
     629  HwErrVariableTotalSize  = 0;
     630
     631  if (IsVolatile) {
     632    //
     633    // Start Pointers for the variable.
     634    //
     635    Variable          = GetStartPointer (VariableStoreHeader);
     636    MaximumBufferSize = sizeof (VARIABLE_STORE_HEADER);
     637
     638    while (IsValidVariableHeader (Variable, GetEndPointer (VariableStoreHeader))) {
     639      NextVariable = GetNextVariablePtr (Variable);
     640      if ((Variable->State == VAR_ADDED || Variable->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) &&
     641          Variable != UpdatingVariable &&
     642          Variable != UpdatingInDeletedTransition
     643         ) {
     644        VariableSize = (UINTN) NextVariable - (UINTN) Variable;
     645        MaximumBufferSize += VariableSize;
     646      }
     647
     648      Variable = NextVariable;
     649    }
     650
     651    if (NewVariable != NULL) {
     652      //
     653      // Add the new variable size.
     654      //
     655      MaximumBufferSize += NewVariableSize;
     656    }
     657
     658    //
     659    // Reserve the 1 Bytes with Oxff to identify the
     660    // end of the variable buffer.
     661    //
     662    MaximumBufferSize += 1;
     663    ValidBuffer = AllocatePool (MaximumBufferSize);
     664    if (ValidBuffer == NULL) {
     665      return EFI_OUT_OF_RESOURCES;
     666    }
     667  } else {
     668    //
     669    // For NV variable reclaim, don't allocate pool here and just use mNvVariableCache
     670    // as the buffer to reduce SMRAM consumption for SMM variable driver.
     671    //
     672    MaximumBufferSize = mNvVariableCache->Size;
     673    ValidBuffer = (UINT8 *) mNvVariableCache;
    576674  }
    577675
     
    588686  //
    589687  Variable = GetStartPointer (VariableStoreHeader);
    590   while (IsValidVariableHeader (Variable)) {
     688  while (IsValidVariableHeader (Variable, GetEndPointer (VariableStoreHeader))) {
    591689    NextVariable = GetNextVariablePtr (Variable);
    592     if (Variable->State == VAR_ADDED) {
    593       if (UpdatingVariable != NULL) {
    594         if (UpdatingVariable == Variable) {
    595           Variable = NextVariable;
    596           continue;
    597         }
    598 
    599         VariableNameSize         = NameSizeOfVariable(Variable);
    600         UpdatingVariableNameSize = NameSizeOfVariable(UpdatingVariable);
    601 
    602         VariableNamePtr         = GetVariableNamePtr (Variable);
    603         UpdatingVariableNamePtr = GetVariableNamePtr (UpdatingVariable);
    604         if (CompareGuid (&Variable->VendorGuid, &UpdatingVariable->VendorGuid)    &&
    605             VariableNameSize == UpdatingVariableNameSize &&
    606             CompareMem (VariableNamePtr, UpdatingVariableNamePtr, VariableNameSize) == 0 ) {
    607           Variable = NextVariable;
    608           continue;
    609         }
    610       }
     690    if (Variable != UpdatingVariable && Variable->State == VAR_ADDED) {
    611691      VariableSize = (UINTN) NextVariable - (UINTN) Variable;
    612692      CopyMem (CurrPtr, (UINT8 *) Variable, VariableSize);
    613693      CurrPtr += VariableSize;
    614694      if ((!IsVolatile) && ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {
    615         mVariableModuleGlobal->HwErrVariableTotalSize += VariableSize;
     695        HwErrVariableTotalSize += VariableSize;
    616696      } else if ((!IsVolatile) && ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {
    617         mVariableModuleGlobal->CommonVariableTotalSize += VariableSize;
     697        CommonVariableTotalSize += VariableSize;
    618698      }
    619699    }
    620700    Variable = NextVariable;
    621   }
    622 
    623   //
    624   // Reinstall the variable being updated if it is not NULL.
    625   //
    626   if (UpdatingVariable != NULL) {
    627     VariableSize = (UINTN)(GetNextVariablePtr (UpdatingVariable)) - (UINTN)UpdatingVariable;
    628     CopyMem (CurrPtr, (UINT8 *) UpdatingVariable, VariableSize);
    629     CurrPtr += VariableSize;
    630     if ((!IsVolatile) && ((UpdatingVariable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {
    631         mVariableModuleGlobal->HwErrVariableTotalSize += VariableSize;
    632     } else if ((!IsVolatile) && ((UpdatingVariable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {
    633         mVariableModuleGlobal->CommonVariableTotalSize += VariableSize;
    634     }
    635701  }
    636702
     
    638704  // Reinstall all in delete transition variables.
    639705  //
    640   Variable      = GetStartPointer (VariableStoreHeader);
    641   while (IsValidVariableHeader (Variable)) {
     706  Variable = GetStartPointer (VariableStoreHeader);
     707  while (IsValidVariableHeader (Variable, GetEndPointer (VariableStoreHeader))) {
    642708    NextVariable = GetNextVariablePtr (Variable);
    643     if (Variable != UpdatingVariable && Variable->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
     709    if (Variable != UpdatingVariable && Variable != UpdatingInDeletedTransition && Variable->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
    644710
    645711      //
     
    651717      FoundAdded = FALSE;
    652718      AddedVariable = GetStartPointer ((VARIABLE_STORE_HEADER *) ValidBuffer);
    653       while (IsValidVariableHeader (AddedVariable)) {
     719      while (IsValidVariableHeader (AddedVariable, GetEndPointer ((VARIABLE_STORE_HEADER *) ValidBuffer))) {
    654720        NextAddedVariable = GetNextVariablePtr (AddedVariable);
    655721        NameSize = NameSizeOfVariable (AddedVariable);
     
    659725          Point0 = (VOID *) GetVariableNamePtr (AddedVariable);
    660726          Point1 = (VOID *) GetVariableNamePtr (Variable);
    661           if (CompareMem (Point0, Point1, NameSizeOfVariable (AddedVariable)) == 0) {
     727          if (CompareMem (Point0, Point1, NameSize) == 0) {
    662728            FoundAdded = TRUE;
    663729            break;
     
    675741        CurrPtr += VariableSize;
    676742        if ((!IsVolatile) && ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {
    677           mVariableModuleGlobal->HwErrVariableTotalSize += VariableSize;
     743          HwErrVariableTotalSize += VariableSize;
    678744        } else if ((!IsVolatile) && ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {
    679           mVariableModuleGlobal->CommonVariableTotalSize += VariableSize;
     745          CommonVariableTotalSize += VariableSize;
    680746        }
    681747      }
     
    685751  }
    686752
     753  //
     754  // Install the new variable if it is not NULL.
     755  //
     756  if (NewVariable != NULL) {
     757    if ((UINTN) (CurrPtr - ValidBuffer) + NewVariableSize > VariableStoreHeader->Size) {
     758      //
     759      // No enough space to store the new variable.
     760      //
     761      Status = EFI_OUT_OF_RESOURCES;
     762      goto Done;
     763    }
     764    if (!IsVolatile) {
     765      if ((NewVariable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD) {
     766        HwErrVariableTotalSize += NewVariableSize;
     767      } else if ((NewVariable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != EFI_VARIABLE_HARDWARE_ERROR_RECORD) {
     768        CommonVariableTotalSize += NewVariableSize;
     769      }
     770      if ((HwErrVariableTotalSize > PcdGet32 (PcdHwErrStorageSize)) ||
     771          (CommonVariableTotalSize > VariableStoreHeader->Size - sizeof (VARIABLE_STORE_HEADER) - PcdGet32 (PcdHwErrStorageSize))) {
     772        //
     773        // No enough space to store the new variable by NV or NV+HR attribute.
     774        //
     775        Status = EFI_OUT_OF_RESOURCES;
     776        goto Done;
     777      }
     778    }
     779
     780    CopyMem (CurrPtr, (UINT8 *) NewVariable, NewVariableSize);
     781    ((VARIABLE_HEADER *) CurrPtr)->State = VAR_ADDED;
     782    if (UpdatingVariable != NULL) {
     783      UpdatingPtrTrack->CurrPtr = (VARIABLE_HEADER *)((UINTN)UpdatingPtrTrack->StartPtr + ((UINTN)CurrPtr - (UINTN)GetStartPointer ((VARIABLE_STORE_HEADER *) ValidBuffer)));
     784      UpdatingPtrTrack->InDeletedTransitionPtr = NULL;
     785    }
     786    CurrPtr += NewVariableSize;
     787  }
     788
    687789  if (IsVolatile) {
    688790    //
     
    690792    //
    691793    SetMem ((UINT8 *) (UINTN) VariableBase, VariableStoreHeader->Size, 0xff);
    692     CopyMem ((UINT8 *) (UINTN) VariableBase, ValidBuffer, (UINTN) (CurrPtr - (UINT8 *) ValidBuffer));
     794    CopyMem ((UINT8 *) (UINTN) VariableBase, ValidBuffer, (UINTN) (CurrPtr - ValidBuffer));
     795    *LastVariableOffset = (UINTN) (CurrPtr - ValidBuffer);
    693796    Status  = EFI_SUCCESS;
    694797  } else {
     
    698801    Status = FtwVariableSpace (
    699802              VariableBase,
    700               ValidBuffer,
    701               (UINTN) (CurrPtr - (UINT8 *) ValidBuffer)
     803              (VARIABLE_STORE_HEADER *) ValidBuffer
    702804              );
    703     CopyMem (mNvVariableCache, (CHAR8 *)(UINTN)VariableBase, VariableStoreHeader->Size);
    704   }
    705   if (!EFI_ERROR (Status)) {
    706     *LastVariableOffset = (UINTN) (CurrPtr - (UINT8 *) ValidBuffer);
     805    if (!EFI_ERROR (Status)) {
     806      *LastVariableOffset = (UINTN) (CurrPtr - ValidBuffer);
     807      mVariableModuleGlobal->HwErrVariableTotalSize = HwErrVariableTotalSize;
     808      mVariableModuleGlobal->CommonVariableTotalSize = CommonVariableTotalSize;
     809    } else {
     810      NextVariable  = GetStartPointer ((VARIABLE_STORE_HEADER *)(UINTN)VariableBase);
     811      while (IsValidVariableHeader (NextVariable, GetEndPointer ((VARIABLE_STORE_HEADER *)(UINTN)VariableBase))) {
     812        VariableSize = NextVariable->NameSize + NextVariable->DataSize + sizeof (VARIABLE_HEADER);
     813        if ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD) {
     814          mVariableModuleGlobal->HwErrVariableTotalSize += HEADER_ALIGN (VariableSize);
     815        } else if ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != EFI_VARIABLE_HARDWARE_ERROR_RECORD) {
     816          mVariableModuleGlobal->CommonVariableTotalSize += HEADER_ALIGN (VariableSize);
     817        }
     818
     819        NextVariable = GetNextVariablePtr (NextVariable);
     820      }
     821      *LastVariableOffset = (UINTN) NextVariable - (UINTN) VariableBase;
     822    }
     823  }
     824
     825Done:
     826  if (IsVolatile) {
     827    FreePool (ValidBuffer);
    707828  } else {
    708     *LastVariableOffset = 0;
    709   }
    710 
    711   FreePool (ValidBuffer);
     829    //
     830    // For NV variable reclaim, we use mNvVariableCache as the buffer, so copy the data back.
     831    //
     832    CopyMem (mNvVariableCache, (UINT8 *)(UINTN)VariableBase, VariableStoreHeader->Size);
     833  }
    712834
    713835  return Status;
     
    737859  VOID                           *Point;
    738860
     861  PtrTrack->InDeletedTransitionPtr = NULL;
     862
    739863  //
    740864  // Find the variable by walk through HOB, volatile and non-volatile variable store.
     
    743867
    744868  for ( PtrTrack->CurrPtr = PtrTrack->StartPtr
    745       ; (PtrTrack->CurrPtr < PtrTrack->EndPtr) && IsValidVariableHeader (PtrTrack->CurrPtr)
     869      ; IsValidVariableHeader (PtrTrack->CurrPtr, PtrTrack->EndPtr)
    746870      ; PtrTrack->CurrPtr = GetNextVariablePtr (PtrTrack->CurrPtr)
    747871      ) {
     
    754878            InDeletedVariable   = PtrTrack->CurrPtr;
    755879          } else {
     880            PtrTrack->InDeletedTransitionPtr = InDeletedVariable;
    756881            return EFI_SUCCESS;
    757882          }
     
    765890                InDeletedVariable     = PtrTrack->CurrPtr;
    766891              } else {
     892                PtrTrack->InDeletedTransitionPtr = InDeletedVariable;
    767893                return EFI_SUCCESS;
    768894              }
     
    11471273
    11481274/**
     1275  This function is to check if the remaining variable space is enough to set
     1276  all Variables from argument list successfully. The purpose of the check
     1277  is to keep the consistency of the Variables to be in variable storage.
     1278
     1279  Note: Variables are assumed to be in same storage.
     1280  The set sequence of Variables will be same with the sequence of VariableEntry from argument list,
     1281  so follow the argument sequence to check the Variables.
     1282
     1283  @param[in] Attributes         Variable attributes for Variable entries.
     1284  @param ...                    The variable argument list with type VARIABLE_ENTRY_CONSISTENCY *.
     1285                                A NULL terminates the list. The VariableSize of
     1286                                VARIABLE_ENTRY_CONSISTENCY is the variable data size as input.
     1287                                It will be changed to variable total size as output.
     1288
     1289  @retval TRUE                  Have enough variable space to set the Variables successfully.
     1290  @retval FALSE                 No enough variable space to set the Variables successfully.
     1291
     1292**/
     1293BOOLEAN
     1294EFIAPI
     1295CheckRemainingSpaceForConsistency (
     1296  IN UINT32                     Attributes,
     1297  ...
     1298  )
     1299{
     1300  EFI_STATUS                    Status;
     1301  VA_LIST                       Args;
     1302  VARIABLE_ENTRY_CONSISTENCY    *VariableEntry;
     1303  UINT64                        MaximumVariableStorageSize;
     1304  UINT64                        RemainingVariableStorageSize;
     1305  UINT64                        MaximumVariableSize;
     1306  UINTN                         TotalNeededSize;
     1307  UINTN                         OriginalVarSize;
     1308  VARIABLE_STORE_HEADER         *VariableStoreHeader;
     1309  VARIABLE_POINTER_TRACK        VariablePtrTrack;
     1310  VARIABLE_HEADER               *NextVariable;
     1311  UINTN                         VarNameSize;
     1312  UINTN                         VarDataSize;
     1313
     1314  //
     1315  // Non-Volatile related.
     1316  //
     1317  VariableStoreHeader = mNvVariableCache;
     1318
     1319  Status = VariableServiceQueryVariableInfoInternal (
     1320             Attributes,
     1321             &MaximumVariableStorageSize,
     1322             &RemainingVariableStorageSize,
     1323             &MaximumVariableSize
     1324             );
     1325  ASSERT_EFI_ERROR (Status);
     1326
     1327  TotalNeededSize = 0;
     1328  VA_START (Args, Attributes);
     1329  VariableEntry = VA_ARG (Args, VARIABLE_ENTRY_CONSISTENCY *);
     1330  while (VariableEntry != NULL) {
     1331    //
     1332    // Calculate variable total size.
     1333    //
     1334    VarNameSize  = StrSize (VariableEntry->Name);
     1335    VarNameSize += GET_PAD_SIZE (VarNameSize);
     1336    VarDataSize  = VariableEntry->VariableSize;
     1337    VarDataSize += GET_PAD_SIZE (VarDataSize);
     1338    VariableEntry->VariableSize = HEADER_ALIGN (sizeof (VARIABLE_HEADER) + VarNameSize + VarDataSize);
     1339
     1340    TotalNeededSize += VariableEntry->VariableSize;
     1341    VariableEntry = VA_ARG (Args, VARIABLE_ENTRY_CONSISTENCY *);
     1342  }
     1343  VA_END (Args);
     1344
     1345  if (RemainingVariableStorageSize >= TotalNeededSize) {
     1346    //
     1347    // Already have enough space.
     1348    //
     1349    return TRUE;
     1350  } else if (AtRuntime ()) {
     1351    //
     1352    // At runtime, no reclaim.
     1353    // The original variable space of Variables can't be reused.
     1354    //
     1355    return FALSE;
     1356  }
     1357
     1358  VA_START (Args, Attributes);
     1359  VariableEntry = VA_ARG (Args, VARIABLE_ENTRY_CONSISTENCY *);
     1360  while (VariableEntry != NULL) {
     1361    //
     1362    // Check if Variable[Index] has been present and get its size.
     1363    //
     1364    OriginalVarSize = 0;
     1365    VariablePtrTrack.StartPtr = GetStartPointer (VariableStoreHeader);
     1366    VariablePtrTrack.EndPtr   = GetEndPointer   (VariableStoreHeader);
     1367    Status = FindVariableEx (
     1368               VariableEntry->Name,
     1369               VariableEntry->Guid,
     1370               FALSE,
     1371               &VariablePtrTrack
     1372               );
     1373    if (!EFI_ERROR (Status)) {
     1374      //
     1375      // Get size of Variable[Index].
     1376      //
     1377      NextVariable = GetNextVariablePtr (VariablePtrTrack.CurrPtr);
     1378      OriginalVarSize = (UINTN) NextVariable - (UINTN) VariablePtrTrack.CurrPtr;
     1379      //
     1380      // Add the original size of Variable[Index] to remaining variable storage size.
     1381      //
     1382      RemainingVariableStorageSize += OriginalVarSize;
     1383    }
     1384    if (VariableEntry->VariableSize > RemainingVariableStorageSize) {
     1385      //
     1386      // No enough space for Variable[Index].
     1387      //
     1388      VA_END (Args);
     1389      return FALSE;
     1390    }
     1391    //
     1392    // Sub the (new) size of Variable[Index] from remaining variable storage size.
     1393    //
     1394    RemainingVariableStorageSize -= VariableEntry->VariableSize;
     1395    VariableEntry = VA_ARG (Args, VARIABLE_ENTRY_CONSISTENCY *);
     1396  }
     1397  VA_END (Args);
     1398
     1399  return TRUE;
     1400}
     1401
     1402/**
    11491403  Hook the operations in PlatformLangCodes, LangCodes, PlatformLang and Lang.
    11501404
     
    11601414  @param[in] DataSize           Size of data. 0 means delete.
    11611415
    1162 **/
    1163 VOID
     1416  @retval EFI_SUCCESS           The update operation is successful or ignored.
     1417  @retval EFI_WRITE_PROTECTED   Update PlatformLangCodes/LangCodes at runtime.
     1418  @retval EFI_OUT_OF_RESOURCES  No enough variable space to do the update operation.
     1419  @retval Others                Other errors happened during the update operation.
     1420
     1421**/
     1422EFI_STATUS
    11641423AutoUpdateLangVariable (
    11651424  IN  CHAR16             *VariableName,
     
    11751434  VARIABLE_POINTER_TRACK Variable;
    11761435  BOOLEAN                SetLanguageCodes;
     1436  VARIABLE_ENTRY_CONSISTENCY VariableEntry[2];
    11771437
    11781438  //
     
    11801440  //
    11811441  if (DataSize == 0) {
    1182     return;
     1442    return EFI_SUCCESS;
    11831443  }
    11841444
    11851445  SetLanguageCodes = FALSE;
    11861446
    1187   if (StrCmp (VariableName, L"PlatformLangCodes") == 0) {
     1447  if (StrCmp (VariableName, EFI_PLATFORM_LANG_CODES_VARIABLE_NAME) == 0) {
    11881448    //
    11891449    // PlatformLangCodes is a volatile variable, so it can not be updated at runtime.
    11901450    //
    11911451    if (AtRuntime ()) {
    1192       return;
     1452      return EFI_WRITE_PROTECTED;
    11931453    }
    11941454
     
    12151475    ASSERT (mVariableModuleGlobal->PlatformLang != NULL);
    12161476
    1217   } else if (StrCmp (VariableName, L"LangCodes") == 0) {
     1477  } else if (StrCmp (VariableName, EFI_LANG_CODES_VARIABLE_NAME) == 0) {
    12181478    //
    12191479    // LangCodes is a volatile variable, so it can not be updated at runtime.
    12201480    //
    12211481    if (AtRuntime ()) {
    1222       return;
     1482      return EFI_WRITE_PROTECTED;
    12231483    }
    12241484
     
    12431503    // Update PlatformLang if Lang is already set
    12441504    //
    1245     Status = FindVariable (L"PlatformLang", &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);
     1505    Status = FindVariable (EFI_PLATFORM_LANG_VARIABLE_NAME, &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);
    12461506    if (!EFI_ERROR (Status)) {
    12471507      //
    12481508      // Update Lang
    12491509      //
    1250       VariableName = L"PlatformLang";
     1510      VariableName = EFI_PLATFORM_LANG_VARIABLE_NAME;
    12511511      Data         = GetVariableDataPtr (Variable.CurrPtr);
    12521512      DataSize     = Variable.CurrPtr->DataSize;
    12531513    } else {
    1254       Status = FindVariable (L"Lang", &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);
     1514      Status = FindVariable (EFI_LANG_VARIABLE_NAME, &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);
    12551515      if (!EFI_ERROR (Status)) {
    12561516        //
    12571517        // Update PlatformLang
    12581518        //
    1259         VariableName = L"Lang";
     1519        VariableName = EFI_LANG_VARIABLE_NAME;
    12601520        Data         = GetVariableDataPtr (Variable.CurrPtr);
    12611521        DataSize     = Variable.CurrPtr->DataSize;
     
    12641524        // Neither PlatformLang nor Lang is set, directly return
    12651525        //
    1266         return;
    1267       }
    1268     }
    1269   }
    1270  
     1526        return EFI_SUCCESS;
     1527      }
     1528    }
     1529  }
     1530
     1531  Status = EFI_SUCCESS;
     1532
    12711533  //
    12721534  // According to UEFI spec, "Lang" and "PlatformLang" is NV|BS|RT attributions.
     
    12741536  Attributes = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS;
    12751537
    1276   if (StrCmp (VariableName, L"PlatformLang") == 0) {
     1538  if (StrCmp (VariableName, EFI_PLATFORM_LANG_VARIABLE_NAME) == 0) {
    12771539    //
    12781540    // Update Lang when PlatformLangCodes/LangCodes were set.
     
    12951557
    12961558        //
    1297         // Successfully convert PlatformLang to Lang, and set the BestLang value into Lang variable simultaneously.
    1298         //
    1299         FindVariable (L"Lang", &gEfiGlobalVariableGuid, &Variable, (VARIABLE_GLOBAL *)mVariableModuleGlobal, FALSE);
    1300 
    1301         Status = UpdateVariable (L"Lang", &gEfiGlobalVariableGuid, BestLang,
    1302                                  ISO_639_2_ENTRY_SIZE + 1, Attributes, &Variable);
    1303 
    1304         DEBUG ((EFI_D_INFO, "Variable Driver Auto Update PlatformLang, PlatformLang:%a, Lang:%a\n", BestPlatformLang, BestLang));
    1305 
    1306         ASSERT_EFI_ERROR(Status);
    1307       }
    1308     }
    1309 
    1310   } else if (StrCmp (VariableName, L"Lang") == 0) {
     1559        // Check the variable space for both Lang and PlatformLang variable.
     1560        //
     1561        VariableEntry[0].VariableSize = ISO_639_2_ENTRY_SIZE + 1;
     1562        VariableEntry[0].Guid = &gEfiGlobalVariableGuid;
     1563        VariableEntry[0].Name = EFI_LANG_VARIABLE_NAME;
     1564       
     1565        VariableEntry[1].VariableSize = AsciiStrSize (BestPlatformLang);
     1566        VariableEntry[1].Guid = &gEfiGlobalVariableGuid;
     1567        VariableEntry[1].Name = EFI_PLATFORM_LANG_VARIABLE_NAME;
     1568        if (!CheckRemainingSpaceForConsistency (VARIABLE_ATTRIBUTE_NV_BS_RT, &VariableEntry[0], &VariableEntry[1], NULL)) {
     1569          //
     1570          // No enough variable space to set both Lang and PlatformLang successfully.
     1571          //
     1572          Status = EFI_OUT_OF_RESOURCES;
     1573        } else {
     1574          //
     1575          // Successfully convert PlatformLang to Lang, and set the BestLang value into Lang variable simultaneously.
     1576          //
     1577          FindVariable (EFI_LANG_VARIABLE_NAME, &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);
     1578
     1579          Status = UpdateVariable (EFI_LANG_VARIABLE_NAME, &gEfiGlobalVariableGuid, BestLang,
     1580                                   ISO_639_2_ENTRY_SIZE + 1, Attributes, &Variable);
     1581        }
     1582
     1583        DEBUG ((EFI_D_INFO, "Variable Driver Auto Update PlatformLang, PlatformLang:%a, Lang:%a Status: %r\n", BestPlatformLang, BestLang, Status));
     1584      }
     1585    }
     1586
     1587  } else if (StrCmp (VariableName, EFI_LANG_VARIABLE_NAME) == 0) {
    13111588    //
    13121589    // Update PlatformLang when PlatformLangCodes/LangCodes were set.
     
    13291606
    13301607        //
    1331         // Successfully convert Lang to PlatformLang, and set the BestPlatformLang value into PlatformLang variable simultaneously.
    1332         //
    1333         FindVariable (L"PlatformLang", &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);
    1334 
    1335         Status = UpdateVariable (L"PlatformLang", &gEfiGlobalVariableGuid, BestPlatformLang,
    1336                                  AsciiStrSize (BestPlatformLang), Attributes, &Variable);
    1337 
    1338         DEBUG ((EFI_D_INFO, "Variable Driver Auto Update Lang, Lang:%a, PlatformLang:%a\n", BestLang, BestPlatformLang));
    1339         ASSERT_EFI_ERROR (Status);
    1340       }
    1341     }
     1608        // Check the variable space for both PlatformLang and Lang variable.
     1609        //
     1610        VariableEntry[0].VariableSize = AsciiStrSize (BestPlatformLang);
     1611        VariableEntry[0].Guid = &gEfiGlobalVariableGuid;
     1612        VariableEntry[0].Name = EFI_PLATFORM_LANG_VARIABLE_NAME;
     1613
     1614        VariableEntry[1].VariableSize = ISO_639_2_ENTRY_SIZE + 1;
     1615        VariableEntry[1].Guid = &gEfiGlobalVariableGuid;
     1616        VariableEntry[1].Name = EFI_LANG_VARIABLE_NAME;
     1617        if (!CheckRemainingSpaceForConsistency (VARIABLE_ATTRIBUTE_NV_BS_RT, &VariableEntry[0], &VariableEntry[1], NULL)) {
     1618          //
     1619          // No enough variable space to set both PlatformLang and Lang successfully.
     1620          //
     1621          Status = EFI_OUT_OF_RESOURCES;
     1622        } else {
     1623          //
     1624          // Successfully convert Lang to PlatformLang, and set the BestPlatformLang value into PlatformLang variable simultaneously.
     1625          //
     1626          FindVariable (EFI_PLATFORM_LANG_VARIABLE_NAME, &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);
     1627
     1628          Status = UpdateVariable (EFI_PLATFORM_LANG_VARIABLE_NAME, &gEfiGlobalVariableGuid, BestPlatformLang,
     1629                                   AsciiStrSize (BestPlatformLang), Attributes, &Variable);
     1630        }
     1631
     1632        DEBUG ((EFI_D_INFO, "Variable Driver Auto Update Lang, Lang:%a, PlatformLang:%a Status: %r\n", BestLang, BestPlatformLang, Status));
     1633      }
     1634    }
     1635  }
     1636
     1637  if (SetLanguageCodes) {
     1638    //
     1639    // Continue to set PlatformLangCodes or LangCodes.
     1640    //
     1641    return EFI_SUCCESS;
     1642  } else {
     1643    return Status;
    13421644  }
    13431645}
     
    13521654  @param[in] DataSize           Size of data. 0 means delete.
    13531655  @param[in] Attributes         Attribues of the variable.
    1354   @param[in] CacheVariable      The variable information which is used to keep track of variable usage.
     1656  @param[in, out] CacheVariable The variable information which is used to keep track of variable usage.
    13551657 
    13561658  @retval EFI_SUCCESS           The update operation is success.
     
    13651667  IN      UINTN                       DataSize,
    13661668  IN      UINT32                      Attributes      OPTIONAL,
    1367   IN      VARIABLE_POINTER_TRACK      *CacheVariable
     1669  IN OUT  VARIABLE_POINTER_TRACK      *CacheVariable
    13681670  )
    13691671{
     
    13791681  EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  *Fvb;
    13801682  UINT8                               State;
    1381   BOOLEAN                             Reclaimed;
    13821683  VARIABLE_POINTER_TRACK              *Variable;
    13831684  VARIABLE_POINTER_TRACK              NvVariable;
     
    14061707    Variable->EndPtr   = GetEndPointer (VariableStoreHeader);
    14071708    Variable->CurrPtr  = (VARIABLE_HEADER *)((UINTN)Variable->StartPtr + ((UINTN)CacheVariable->CurrPtr - (UINTN)CacheVariable->StartPtr));
     1709    if (CacheVariable->InDeletedTransitionPtr != NULL) {
     1710      Variable->InDeletedTransitionPtr = (VARIABLE_HEADER *)((UINTN)Variable->StartPtr + ((UINTN)CacheVariable->InDeletedTransitionPtr - (UINTN)CacheVariable->StartPtr));
     1711    } else {
     1712      Variable->InDeletedTransitionPtr = NULL;
     1713    }
    14081714    Variable->Volatile = FALSE;
    14091715  }
    14101716
    14111717  Fvb       = mVariableModuleGlobal->FvbInstance;
    1412   Reclaimed = FALSE;
    14131718
    14141719  if (Variable->CurrPtr != NULL) {
     
    14401745    //
    14411746    if (DataSize == 0 || (Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == 0) {   
     1747      if (Variable->InDeletedTransitionPtr != NULL) {
     1748        //
     1749        // Both ADDED and IN_DELETED_TRANSITION variable are present,
     1750        // set IN_DELETED_TRANSITION one to DELETED state first.
     1751        //
     1752        State = Variable->InDeletedTransitionPtr->State;
     1753        State &= VAR_DELETED;
     1754        Status = UpdateVariableStore (
     1755                   &mVariableModuleGlobal->VariableGlobal,
     1756                   Variable->Volatile,
     1757                   FALSE,
     1758                   Fvb,
     1759                   (UINTN) &Variable->InDeletedTransitionPtr->State,
     1760                   sizeof (UINT8),
     1761                   &State
     1762                   );
     1763        if (!EFI_ERROR (Status)) {
     1764          if (!Variable->Volatile) {
     1765            ASSERT (CacheVariable->InDeletedTransitionPtr != NULL);
     1766            CacheVariable->InDeletedTransitionPtr->State = State;
     1767          }
     1768        } else {
     1769          goto Done;
     1770        }
     1771      }
     1772
    14421773      State = Variable->CurrPtr->State;
    14431774      State &= VAR_DELETED;
     
    14561787        if (!Variable->Volatile) {
    14571788          CacheVariable->CurrPtr->State = State;
     1789          FlushHobVariableToFlash (VariableName, VendorGuid);
    14581790        }
    14591791      }
     
    15801912      }
    15811913      //
    1582       // Perform garbage collection & reclaim operation.
     1914      // Perform garbage collection & reclaim operation, and integrate the new variable at the same time.
    15831915      //
    15841916      Status = Reclaim (mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase,
    1585                         &mVariableModuleGlobal->NonVolatileLastVariableOffset, FALSE, Variable->CurrPtr);
    1586       if (EFI_ERROR (Status)) {
    1587         goto Done;
    1588       }
    1589       //
    1590       // If still no enough space, return out of resources.
    1591       //
    1592       if ((((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != 0)
    1593         && ((VarSize + mVariableModuleGlobal->HwErrVariableTotalSize) > PcdGet32 (PcdHwErrStorageSize)))
    1594         || (((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == 0)
    1595         && ((VarSize + mVariableModuleGlobal->CommonVariableTotalSize) > NonVolatileVarableStoreSize - sizeof (VARIABLE_STORE_HEADER) - PcdGet32 (PcdHwErrStorageSize)))) {
    1596         Status = EFI_OUT_OF_RESOURCES;
    1597         goto Done;
    1598       }
    1599       Reclaimed = TRUE;
     1917                        &mVariableModuleGlobal->NonVolatileLastVariableOffset, FALSE, Variable, NextVariable, HEADER_ALIGN (VarSize));
     1918      if (!EFI_ERROR (Status)) {
     1919        //
     1920        // The new variable has been integrated successfully during reclaiming.
     1921        //
     1922        if (Variable->CurrPtr != NULL) {
     1923          CacheVariable->CurrPtr = (VARIABLE_HEADER *)((UINTN) CacheVariable->StartPtr + ((UINTN) Variable->CurrPtr - (UINTN) Variable->StartPtr));
     1924          CacheVariable->InDeletedTransitionPtr = NULL;
     1925        }
     1926        UpdateVariableInfo (VariableName, VendorGuid, FALSE, FALSE, TRUE, FALSE, FALSE);
     1927        FlushHobVariableToFlash (VariableName, VendorGuid);
     1928      }
     1929      goto Done;
    16001930    }
    16011931    //
     
    16952025        ((VARIABLE_STORE_HEADER *) ((UINTN) (mVariableModuleGlobal->VariableGlobal.VolatileVariableBase)))->Size) {
    16962026      //
    1697       // Perform garbage collection & reclaim operation.
     2027      // Perform garbage collection & reclaim operation, and integrate the new variable at the same time.
    16982028      //
    16992029      Status = Reclaim (mVariableModuleGlobal->VariableGlobal.VolatileVariableBase,
    1700                           &mVariableModuleGlobal->VolatileLastVariableOffset, TRUE, Variable->CurrPtr);
    1701       if (EFI_ERROR (Status)) {
    1702         goto Done;
    1703       }
    1704       //
    1705       // If still no enough space, return out of resources.
    1706       //
    1707       if ((UINT32) (VarSize + mVariableModuleGlobal->VolatileLastVariableOffset) >
    1708             ((VARIABLE_STORE_HEADER *) ((UINTN) (mVariableModuleGlobal->VariableGlobal.VolatileVariableBase)))->Size
    1709             ) {
    1710         Status = EFI_OUT_OF_RESOURCES;
    1711         goto Done;
    1712       }
    1713       Reclaimed = TRUE;
     2030                          &mVariableModuleGlobal->VolatileLastVariableOffset, TRUE, Variable, NextVariable, HEADER_ALIGN (VarSize));
     2031      if (!EFI_ERROR (Status)) {
     2032        //
     2033        // The new variable has been integrated successfully during reclaiming.
     2034        //
     2035        if (Variable->CurrPtr != NULL) {
     2036          CacheVariable->CurrPtr = (VARIABLE_HEADER *)((UINTN) CacheVariable->StartPtr + ((UINTN) Variable->CurrPtr - (UINTN) Variable->StartPtr));
     2037          CacheVariable->InDeletedTransitionPtr = NULL;
     2038        }
     2039        UpdateVariableInfo (VariableName, VendorGuid, TRUE, FALSE, TRUE, FALSE, FALSE);
     2040      }
     2041      goto Done;
    17142042    }
    17152043
     
    17352063  // Mark the old variable as deleted.
    17362064  //
    1737   if (!Reclaimed && !EFI_ERROR (Status) && Variable->CurrPtr != NULL) {
     2065  if (!EFI_ERROR (Status) && Variable->CurrPtr != NULL) {
     2066    if (Variable->InDeletedTransitionPtr != NULL) {
     2067      //
     2068      // Both ADDED and IN_DELETED_TRANSITION old variable are present,
     2069      // set IN_DELETED_TRANSITION one to DELETED state first.
     2070      //
     2071      State = Variable->InDeletedTransitionPtr->State;
     2072      State &= VAR_DELETED;
     2073      Status = UpdateVariableStore (
     2074                 &mVariableModuleGlobal->VariableGlobal,
     2075                 Variable->Volatile,
     2076                 FALSE,
     2077                 Fvb,
     2078                 (UINTN) &Variable->InDeletedTransitionPtr->State,
     2079                 sizeof (UINT8),
     2080                 &State
     2081                 );
     2082      if (!EFI_ERROR (Status)) {
     2083        if (!Variable->Volatile) {
     2084          ASSERT (CacheVariable->InDeletedTransitionPtr != NULL);
     2085          CacheVariable->InDeletedTransitionPtr->State = State;
     2086        }
     2087      } else {
     2088        goto Done;
     2089      }
     2090    }
     2091
    17382092    State = Variable->CurrPtr->State;
    17392093    State &= VAR_DELETED;
     
    17552109  if (!EFI_ERROR (Status)) {
    17562110    UpdateVariableInfo (VariableName, VendorGuid, Volatile, FALSE, TRUE, FALSE, FALSE);
     2111    if (!Volatile) {
     2112      FlushHobVariableToFlash (VariableName, VendorGuid);
     2113    }
    17572114  }
    17582115
     
    17622119
    17632120/**
     2121  Check if a Unicode character is a hexadecimal character.
     2122
     2123  This function checks if a Unicode character is a
     2124  hexadecimal character.  The valid hexadecimal character is
     2125  L'0' to L'9', L'a' to L'f', or L'A' to L'F'.
     2126
     2127
     2128  @param Char           The character to check against.
     2129
     2130  @retval TRUE          If the Char is a hexadecmial character.
     2131  @retval FALSE         If the Char is not a hexadecmial character.
     2132
     2133**/
     2134BOOLEAN
     2135EFIAPI
     2136IsHexaDecimalDigitCharacter (
     2137  IN CHAR16             Char
     2138  )
     2139{
     2140  return (BOOLEAN) ((Char >= L'0' && Char <= L'9') || (Char >= L'A' && Char <= L'F') || (Char >= L'a' && Char <= L'f'));
     2141}
     2142
     2143/**
     2144
     2145  This code checks if variable is hardware error record variable or not.
     2146
     2147  According to UEFI spec, hardware error record variable should use the EFI_HARDWARE_ERROR_VARIABLE VendorGuid
     2148  and have the L"HwErrRec####" name convention, #### is a printed hex value and no 0x or h is included in the hex value.
     2149
     2150  @param VariableName   Pointer to variable name.
     2151  @param VendorGuid     Variable Vendor Guid.
     2152
     2153  @retval TRUE          Variable is hardware error record variable.
     2154  @retval FALSE         Variable is not hardware error record variable.
     2155
     2156**/
     2157BOOLEAN
     2158EFIAPI
     2159IsHwErrRecVariable (
     2160  IN CHAR16             *VariableName,
     2161  IN EFI_GUID           *VendorGuid
     2162  )
     2163{
     2164  if (!CompareGuid (VendorGuid, &gEfiHardwareErrorVariableGuid) ||
     2165      (StrLen (VariableName) != StrLen (L"HwErrRec####")) ||
     2166      (StrnCmp(VariableName, L"HwErrRec", StrLen (L"HwErrRec")) != 0) ||
     2167      !IsHexaDecimalDigitCharacter (VariableName[0x8]) ||
     2168      !IsHexaDecimalDigitCharacter (VariableName[0x9]) ||
     2169      !IsHexaDecimalDigitCharacter (VariableName[0xA]) ||
     2170      !IsHexaDecimalDigitCharacter (VariableName[0xB])) {
     2171    return FALSE;
     2172  }
     2173
     2174  return TRUE;
     2175}
     2176
     2177/**
     2178  This code checks if variable guid is global variable guid first.
     2179  If yes, further check if variable name is in mGlobalVariableList or mGlobalVariableList2 and attributes matched.
     2180
     2181  @param[in] VariableName       Pointer to variable name.
     2182  @param[in] VendorGuid         Variable Vendor Guid.
     2183  @param[in] Attributes         Attributes of the variable.
     2184
     2185  @retval EFI_SUCCESS           Variable is not global variable, or Variable is global variable, variable name is in the lists and attributes matched.
     2186  @retval EFI_INVALID_PARAMETER Variable is global variable, but variable name is not in the lists or attributes unmatched.
     2187
     2188**/
     2189EFI_STATUS
     2190EFIAPI
     2191CheckEfiGlobalVariable (
     2192  IN CHAR16             *VariableName,
     2193  IN EFI_GUID           *VendorGuid,
     2194  IN UINT32             Attributes
     2195  )
     2196{
     2197  UINTN     Index;
     2198  UINTN     NameLength;
     2199
     2200  if (CompareGuid (VendorGuid, &gEfiGlobalVariableGuid)){
     2201    //
     2202    // Try list 1, exactly match.
     2203    //
     2204    for (Index = 0; Index < sizeof (mGlobalVariableList)/sizeof (mGlobalVariableList[0]); Index++) {
     2205      if ((StrCmp (mGlobalVariableList[Index].Name, VariableName) == 0) &&
     2206          (Attributes == 0 || Attributes == mGlobalVariableList[Index].Attributes)) {
     2207        return EFI_SUCCESS;
     2208      }
     2209    }
     2210
     2211    //
     2212    // Try list 2.
     2213    //
     2214    NameLength = StrLen (VariableName) - 4;
     2215    for (Index = 0; Index < sizeof (mGlobalVariableList2)/sizeof (mGlobalVariableList2[0]); Index++) {
     2216      if ((StrLen (VariableName) == StrLen (mGlobalVariableList2[Index].Name)) &&
     2217          (StrnCmp (mGlobalVariableList2[Index].Name, VariableName, NameLength) == 0) &&
     2218          IsHexaDecimalDigitCharacter (VariableName[NameLength]) &&
     2219          IsHexaDecimalDigitCharacter (VariableName[NameLength + 1]) &&
     2220          IsHexaDecimalDigitCharacter (VariableName[NameLength + 2]) &&
     2221          IsHexaDecimalDigitCharacter (VariableName[NameLength + 3]) &&
     2222          (Attributes == 0 || Attributes == mGlobalVariableList2[Index].Attributes)) {
     2223        return EFI_SUCCESS;
     2224      }
     2225    }
     2226
     2227    DEBUG ((EFI_D_INFO, "[Variable]: set global variable with invalid variable name or attributes - %g:%s:%x\n", VendorGuid, VariableName, Attributes));
     2228    return EFI_INVALID_PARAMETER;
     2229  }
     2230
     2231  return EFI_SUCCESS;
     2232}
     2233
     2234/**
     2235  Mark a variable that will become read-only after leaving the DXE phase of execution.
     2236
     2237  @param[in] This          The VARIABLE_LOCK_PROTOCOL instance.
     2238  @param[in] VariableName  A pointer to the variable name that will be made read-only subsequently.
     2239  @param[in] VendorGuid    A pointer to the vendor GUID that will be made read-only subsequently.
     2240
     2241  @retval EFI_SUCCESS           The variable specified by the VariableName and the VendorGuid was marked
     2242                                as pending to be read-only.
     2243  @retval EFI_INVALID_PARAMETER VariableName or VendorGuid is NULL.
     2244                                Or VariableName is an empty string.
     2245  @retval EFI_ACCESS_DENIED     EFI_END_OF_DXE_EVENT_GROUP_GUID or EFI_EVENT_GROUP_READY_TO_BOOT has
     2246                                already been signaled.
     2247  @retval EFI_OUT_OF_RESOURCES  There is not enough resource to hold the lock request.
     2248**/
     2249EFI_STATUS
     2250EFIAPI
     2251VariableLockRequestToLock (
     2252  IN CONST EDKII_VARIABLE_LOCK_PROTOCOL *This,
     2253  IN       CHAR16                       *VariableName,
     2254  IN       EFI_GUID                     *VendorGuid
     2255  )
     2256{
     2257  VARIABLE_ENTRY                  *Entry;
     2258
     2259  if (VariableName == NULL || VariableName[0] == 0 || VendorGuid == NULL) {
     2260    return EFI_INVALID_PARAMETER;
     2261  }
     2262
     2263  if (mEndOfDxe) {
     2264    return EFI_ACCESS_DENIED;
     2265  }
     2266
     2267  Entry = AllocateRuntimeZeroPool (sizeof (*Entry) + StrSize (VariableName));
     2268  if (Entry == NULL) {
     2269    return EFI_OUT_OF_RESOURCES;
     2270  }
     2271
     2272  DEBUG ((EFI_D_INFO, "[Variable] Lock: %g:%s\n", VendorGuid, VariableName));
     2273
     2274  AcquireLockOnlyAtBootTime(&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);
     2275
     2276  Entry->Name = (CHAR16 *) (Entry + 1);
     2277  StrnCpy   (Entry->Name, VariableName, StrLen (VariableName));
     2278  CopyGuid (&Entry->Guid, VendorGuid);
     2279  InsertTailList (&mLockedVariableList, &Entry->Link);
     2280
     2281  ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);
     2282
     2283  return EFI_SUCCESS;
     2284}
     2285
     2286/**
    17642287
    17652288  This code finds variable in storage blocks (Volatile or Non-Volatile).
     2289
     2290  Caution: This function may receive untrusted input.
     2291  This function may be invoked in SMM mode, and datasize is external input.
     2292  This function will do basic validation, before parse the data.
    17662293
    17672294  @param VariableName               Name of Variable to be found.
     
    18422369  This code Finds the Next available variable.
    18432370
     2371  Caution: This function may receive untrusted input.
     2372  This function may be invoked in SMM mode. This function will do basic validation, before parse the data.
     2373
    18442374  @param VariableNameSize           Size of the variable name.
    18452375  @param VariableName               Pointer to variable name.
     
    18632393  VARIABLE_POINTER_TRACK  Variable;
    18642394  VARIABLE_POINTER_TRACK  VariableInHob;
     2395  VARIABLE_POINTER_TRACK  VariablePtrTrack;
    18652396  UINTN                   VarNameSize;
    18662397  EFI_STATUS              Status;
     
    18982429    // Switch from Volatile to HOB, to Non-Volatile.
    18992430    //
    1900     while ((Variable.CurrPtr >= Variable.EndPtr) ||
    1901            (Variable.CurrPtr == NULL)            ||
    1902            !IsValidVariableHeader (Variable.CurrPtr)
    1903           ) {
     2431    while (!IsValidVariableHeader (Variable.CurrPtr, Variable.EndPtr)) {
    19042432      //
    19052433      // Find current storage index
     
    19362464    // Variable is found
    19372465    //
    1938     if (Variable.CurrPtr->State == VAR_ADDED) {
    1939       if ((AtRuntime () && ((Variable.CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0)) == 0) {
     2466    if (Variable.CurrPtr->State == VAR_ADDED || Variable.CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
     2467      if (!AtRuntime () || ((Variable.CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) != 0)) {
     2468        if (Variable.CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
     2469          //
     2470          // If it is a IN_DELETED_TRANSITION variable,
     2471          // and there is also a same ADDED one at the same time,
     2472          // don't return it.
     2473          //
     2474          VariablePtrTrack.StartPtr = Variable.StartPtr;
     2475          VariablePtrTrack.EndPtr = Variable.EndPtr;
     2476          Status = FindVariableEx (
     2477                     GetVariableNamePtr (Variable.CurrPtr),
     2478                     &Variable.CurrPtr->VendorGuid,
     2479                     FALSE,
     2480                     &VariablePtrTrack
     2481                     );
     2482          if (!EFI_ERROR (Status) && VariablePtrTrack.CurrPtr->State == VAR_ADDED) {
     2483            Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);
     2484            continue;
     2485          }
     2486        }
    19402487
    19412488        //
     
    19872534  This code sets variable in storage blocks (Volatile or Non-Volatile).
    19882535
     2536  Caution: This function may receive untrusted input.
     2537  This function may be invoked in SMM mode, and datasize and data are external input.
     2538  This function will do basic validation, before parse the data.
     2539
    19892540  @param VariableName                     Name of Variable to be found.
    19902541  @param VendorGuid                       Variable vendor GUID.
     
    20152566  VARIABLE_HEADER                     *NextVariable;
    20162567  EFI_PHYSICAL_ADDRESS                Point;
     2568  LIST_ENTRY                          *Link;
     2569  VARIABLE_ENTRY                      *Entry;
    20172570
    20182571  //
     
    20282581
    20292582  //
    2030   // Not support authenticated variable write yet.
    2031   //
    2032   if ((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) != 0) {
     2583  // Not support authenticated or append variable write yet.
     2584  //
     2585  if ((Attributes & (EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS | EFI_VARIABLE_APPEND_WRITE)) != 0) {
    20332586    return EFI_INVALID_PARAMETER;
    20342587  }
     
    20382591  //
    20392592  if ((Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == EFI_VARIABLE_RUNTIME_ACCESS) {
     2593    return EFI_INVALID_PARAMETER;
     2594  }
     2595
     2596  if ((UINTN)(~0) - DataSize < StrSize(VariableName)){
     2597    //
     2598    // Prevent whole variable size overflow
     2599    //
    20402600    return EFI_INVALID_PARAMETER;
    20412601  }
     
    20472607  //
    20482608  if ((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD) {
    2049     if ((DataSize > PcdGet32 (PcdMaxHardwareErrorVariableSize)) ||
    2050         (sizeof (VARIABLE_HEADER) + StrSize (VariableName) + DataSize > PcdGet32 (PcdMaxHardwareErrorVariableSize))) {
     2609    if ( StrSize (VariableName) + DataSize > PcdGet32 (PcdMaxHardwareErrorVariableSize) - sizeof (VARIABLE_HEADER)) {
    20512610      return EFI_INVALID_PARAMETER;
    20522611    }
    2053     //
    2054     // According to UEFI spec, HARDWARE_ERROR_RECORD variable name convention should be L"HwErrRecXXXX".
    2055     //
    2056     if (StrnCmp(VariableName, L"HwErrRec", StrLen(L"HwErrRec")) != 0) {
     2612    if (!IsHwErrRecVariable(VariableName, VendorGuid)) {
    20572613      return EFI_INVALID_PARAMETER;
    20582614    }
     
    20622618    //  the DataSize is limited to maximum size of PcdGet32 (PcdMaxVariableSize) bytes.
    20632619    //
    2064     if ((DataSize > PcdGet32 (PcdMaxVariableSize)) ||
    2065         (sizeof (VARIABLE_HEADER) + StrSize (VariableName) + DataSize > PcdGet32 (PcdMaxVariableSize))) {
     2620    if (StrSize (VariableName) + DataSize > PcdGet32 (PcdMaxVariableSize) - sizeof (VARIABLE_HEADER)) {
    20662621      return EFI_INVALID_PARAMETER;
    20672622    } 
    2068   } 
     2623  }
     2624
     2625  Status = CheckEfiGlobalVariable (VariableName, VendorGuid, Attributes);
     2626  if (EFI_ERROR (Status)) {
     2627    return Status;
     2628  }
    20692629
    20702630  AcquireLockOnlyAtBootTime(&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);
     
    20792639    //
    20802640    NextVariable  = GetStartPointer ((VARIABLE_STORE_HEADER *) (UINTN) Point);
    2081     while ((NextVariable < GetEndPointer ((VARIABLE_STORE_HEADER *) (UINTN) Point))
    2082         && IsValidVariableHeader (NextVariable)) {
     2641    while (IsValidVariableHeader (NextVariable, GetEndPointer ((VARIABLE_STORE_HEADER *) (UINTN) Point))) {
    20832642      NextVariable = GetNextVariablePtr (NextVariable);
    20842643    }
    20852644    mVariableModuleGlobal->NonVolatileLastVariableOffset = (UINTN) NextVariable - (UINTN) Point;
     2645  }
     2646
     2647  if (mEndOfDxe && mEnableLocking) {
     2648    //
     2649    // Treat the variables listed in the forbidden variable list as read-only after leaving DXE phase.
     2650    //
     2651    for ( Link = GetFirstNode (&mLockedVariableList)
     2652        ; !IsNull (&mLockedVariableList, Link)
     2653        ; Link = GetNextNode (&mLockedVariableList, Link)
     2654        ) {
     2655      Entry = BASE_CR (Link, VARIABLE_ENTRY, Link);
     2656      if (CompareGuid (&Entry->Guid, VendorGuid) && (StrCmp (Entry->Name, VariableName) == 0)) {
     2657        Status = EFI_WRITE_PROTECTED;
     2658        DEBUG ((EFI_D_INFO, "[Variable]: Changing readonly variable after leaving DXE phase - %g:%s\n", VendorGuid, VariableName));
     2659        goto Done;
     2660      }
     2661    }
    20862662  }
    20872663
     
    20922668  if (!EFI_ERROR (Status)) {
    20932669    if (((Variable.CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0) && AtRuntime ()) {
    2094       return EFI_WRITE_PROTECTED;
    2095     }
    2096   }
    2097 
    2098   //
    2099   // Hook the operation of setting PlatformLangCodes/PlatformLang and LangCodes/Lang.
    2100   //
    2101   AutoUpdateLangVariable (VariableName, Data, DataSize);
     2670      Status = EFI_WRITE_PROTECTED;
     2671      goto Done;
     2672    }
     2673    if (Attributes != 0 && Attributes != Variable.CurrPtr->Attributes) {
     2674      //
     2675      // If a preexisting variable is rewritten with different attributes, SetVariable() shall not
     2676      // modify the variable and shall return EFI_INVALID_PARAMETER. Two exceptions to this rule:
     2677      // 1. No access attributes specified
     2678      // 2. The only attribute differing is EFI_VARIABLE_APPEND_WRITE
     2679      //
     2680      Status = EFI_INVALID_PARAMETER;
     2681      goto Done;
     2682    }
     2683  }
     2684
     2685  if (!FeaturePcdGet (PcdUefiVariableDefaultLangDeprecate)) {
     2686    //
     2687    // Hook the operation of setting PlatformLangCodes/PlatformLang and LangCodes/Lang.
     2688    //
     2689    Status = AutoUpdateLangVariable (VariableName, Data, DataSize);
     2690    if (EFI_ERROR (Status)) {
     2691      //
     2692      // The auto update operation failed, directly return to avoid inconsistency between PlatformLang and Lang.
     2693      //
     2694      goto Done;
     2695    }
     2696  }
    21022697
    21032698  Status = UpdateVariable (VariableName, VendorGuid, Data, DataSize, Attributes, &Variable);
    21042699
     2700Done:
    21052701  InterlockedDecrement (&mVariableModuleGlobal->VariableGlobal.ReentrantState);
    21062702  ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);
     
    21122708
    21132709  This code returns information about the EFI variables.
     2710
     2711  Caution: This function may receive untrusted input.
     2712  This function may be invoked in SMM mode. This function will do basic validation, before parse the data.
    21142713
    21152714  @param Attributes                     Attributes bitmask to specify the type of variables
     
    21222721                                        associated with the attributes specified.
    21232722
    2124   @return EFI_INVALID_PARAMETER         An invalid combination of attribute bits was supplied.
    21252723  @return EFI_SUCCESS                   Query successfully.
    2126   @return EFI_UNSUPPORTED               The attribute is not supported on this platform.
    21272724
    21282725**/
    21292726EFI_STATUS
    21302727EFIAPI
    2131 VariableServiceQueryVariableInfo (
     2728VariableServiceQueryVariableInfoInternal (
    21322729  IN  UINT32                 Attributes,
    21332730  OUT UINT64                 *MaximumVariableStorageSize,
     
    21422739  UINT64                 CommonVariableTotalSize;
    21432740  UINT64                 HwErrVariableTotalSize;
     2741  EFI_STATUS             Status;
     2742  VARIABLE_POINTER_TRACK VariablePtrTrack;
    21442743
    21452744  CommonVariableTotalSize = 0;
    21462745  HwErrVariableTotalSize = 0;
    2147 
    2148   if(MaximumVariableStorageSize == NULL || RemainingVariableStorageSize == NULL || MaximumVariableSize == NULL || Attributes == 0) {
    2149     return EFI_INVALID_PARAMETER;
    2150   }
    2151 
    2152   if((Attributes & (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) == 0) {
    2153     //
    2154     // Make sure the Attributes combination is supported by the platform.
    2155     //
    2156     return EFI_UNSUPPORTED; 
    2157   } else if ((Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == EFI_VARIABLE_RUNTIME_ACCESS) {
    2158     //
    2159     // Make sure if runtime bit is set, boot service bit is set also.
    2160     //
    2161     return EFI_INVALID_PARAMETER;
    2162   } else if (AtRuntime () && ((Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0)) {
    2163     //
    2164     // Make sure RT Attribute is set if we are in Runtime phase.
    2165     //
    2166     return EFI_INVALID_PARAMETER;
    2167   } else if ((Attributes & (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) == EFI_VARIABLE_HARDWARE_ERROR_RECORD) {
    2168     //
    2169     // Make sure Hw Attribute is set with NV.
    2170     //
    2171     return EFI_INVALID_PARAMETER;
    2172   } else if ((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) != 0) {
    2173     //
    2174     // Not support authentiated variable write yet.
    2175     //
    2176     return EFI_UNSUPPORTED;
    2177   }
    2178 
    2179   AcquireLockOnlyAtBootTime(&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);
    21802746
    21812747  if((Attributes & EFI_VARIABLE_NON_VOLATILE) == 0) {
     
    22232789  // Now walk through the related variable store.
    22242790  //
    2225   while ((Variable < GetEndPointer (VariableStoreHeader)) && IsValidVariableHeader (Variable)) {
     2791  while (IsValidVariableHeader (Variable, GetEndPointer (VariableStoreHeader))) {
    22262792    NextVariable = GetNextVariablePtr (Variable);
    22272793    VariableSize = (UINT64) (UINTN) NextVariable - (UINT64) (UINTN) Variable;
     
    22502816          CommonVariableTotalSize += VariableSize;
    22512817        }
     2818      } else if (Variable->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
     2819        //
     2820        // If it is a IN_DELETED_TRANSITION variable,
     2821        // and there is not also a same ADDED one at the same time,
     2822        // this IN_DELETED_TRANSITION variable is valid.
     2823        //
     2824        VariablePtrTrack.StartPtr = GetStartPointer (VariableStoreHeader);
     2825        VariablePtrTrack.EndPtr   = GetEndPointer   (VariableStoreHeader);
     2826        Status = FindVariableEx (
     2827                   GetVariableNamePtr (Variable),
     2828                   &Variable->VendorGuid,
     2829                   FALSE,
     2830                   &VariablePtrTrack
     2831                   );
     2832        if (!EFI_ERROR (Status) && VariablePtrTrack.CurrPtr->State != VAR_ADDED) {
     2833          if ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD) {
     2834            HwErrVariableTotalSize += VariableSize;
     2835          } else {
     2836            CommonVariableTotalSize += VariableSize;
     2837          }
     2838        }
    22522839      }
    22532840    }
     
    22712858  }
    22722859
    2273   ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);
    22742860  return EFI_SUCCESS;
    22752861}
    22762862
     2863/**
     2864
     2865  This code returns information about the EFI variables.
     2866
     2867  Caution: This function may receive untrusted input.
     2868  This function may be invoked in SMM mode. This function will do basic validation, before parse the data.
     2869
     2870  @param Attributes                     Attributes bitmask to specify the type of variables
     2871                                        on which to return information.
     2872  @param MaximumVariableStorageSize     Pointer to the maximum size of the storage space available
     2873                                        for the EFI variables associated with the attributes specified.
     2874  @param RemainingVariableStorageSize   Pointer to the remaining size of the storage space available
     2875                                        for EFI variables associated with the attributes specified.
     2876  @param MaximumVariableSize            Pointer to the maximum size of an individual EFI variables
     2877                                        associated with the attributes specified.
     2878
     2879  @return EFI_INVALID_PARAMETER         An invalid combination of attribute bits was supplied.
     2880  @return EFI_SUCCESS                   Query successfully.
     2881  @return EFI_UNSUPPORTED               The attribute is not supported on this platform.
     2882
     2883**/
     2884EFI_STATUS
     2885EFIAPI
     2886VariableServiceQueryVariableInfo (
     2887  IN  UINT32                 Attributes,
     2888  OUT UINT64                 *MaximumVariableStorageSize,
     2889  OUT UINT64                 *RemainingVariableStorageSize,
     2890  OUT UINT64                 *MaximumVariableSize
     2891  )
     2892{
     2893  EFI_STATUS             Status;
     2894
     2895  if(MaximumVariableStorageSize == NULL || RemainingVariableStorageSize == NULL || MaximumVariableSize == NULL || Attributes == 0) {
     2896    return EFI_INVALID_PARAMETER;
     2897  }
     2898
     2899  if((Attributes & (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) == 0) {
     2900    //
     2901    // Make sure the Attributes combination is supported by the platform.
     2902    //
     2903    return EFI_UNSUPPORTED;
     2904  } else if ((Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == EFI_VARIABLE_RUNTIME_ACCESS) {
     2905    //
     2906    // Make sure if runtime bit is set, boot service bit is set also.
     2907    //
     2908    return EFI_INVALID_PARAMETER;
     2909  } else if (AtRuntime () && ((Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0)) {
     2910    //
     2911    // Make sure RT Attribute is set if we are in Runtime phase.
     2912    //
     2913    return EFI_INVALID_PARAMETER;
     2914  } else if ((Attributes & (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) == EFI_VARIABLE_HARDWARE_ERROR_RECORD) {
     2915    //
     2916    // Make sure Hw Attribute is set with NV.
     2917    //
     2918    return EFI_INVALID_PARAMETER;
     2919  } else if ((Attributes & (EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS | EFI_VARIABLE_APPEND_WRITE)) != 0) {
     2920    //
     2921    // Not support authenticated or append variable write yet.
     2922    //
     2923    return EFI_UNSUPPORTED;
     2924  }
     2925
     2926  AcquireLockOnlyAtBootTime(&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);
     2927
     2928  Status = VariableServiceQueryVariableInfoInternal (
     2929             Attributes,
     2930             MaximumVariableStorageSize,
     2931             RemainingVariableStorageSize,
     2932             MaximumVariableSize
     2933             );
     2934
     2935  ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);
     2936  return Status;
     2937}
    22772938
    22782939/**
    22792940  This function reclaims variable storage if free size is below the threshold.
    2280  
     2941
     2942  Caution: This function may be invoked at SMM mode.
     2943  Care must be taken to make sure not security issue.
     2944
    22812945**/
    22822946VOID
     
    22892953  UINTN                          RemainingCommonVariableSpace;
    22902954  UINTN                          RemainingHwErrVariableSpace;
     2955  STATIC BOOLEAN                 Reclaimed;
     2956
     2957  //
     2958  // This function will be called only once at EndOfDxe or ReadyToBoot event.
     2959  //
     2960  if (Reclaimed) {
     2961    return;
     2962  }
     2963  Reclaimed = TRUE;
    22912964
    22922965  Status  = EFI_SUCCESS;
     
    23072980            &mVariableModuleGlobal->NonVolatileLastVariableOffset,
    23082981            FALSE,
    2309             NULL
     2982            NULL,
     2983            NULL,
     2984            0
    23102985            );
    23112986    ASSERT_EFI_ERROR (Status);
     
    23132988}
    23142989
    2315 
    23162990/**
    2317   Initializes variable write service after FVB was ready.
     2991  Init non-volatile variable store.
     2992
     2993  @retval EFI_SUCCESS           Function successfully executed.
     2994  @retval EFI_OUT_OF_RESOURCES  Fail to allocate enough memory resource.
     2995  @retval EFI_VOLUME_CORRUPTED  Variable Store or Firmware Volume for Variable Store is corrupted.
     2996
     2997**/
     2998EFI_STATUS
     2999InitNonVolatileVariableStore (
     3000  VOID
     3001  )
     3002{
     3003  EFI_FIRMWARE_VOLUME_HEADER            *FvHeader;
     3004  VARIABLE_HEADER                       *NextVariable;
     3005  EFI_PHYSICAL_ADDRESS                  VariableStoreBase;
     3006  UINT64                                VariableStoreLength;
     3007  UINTN                                 VariableSize;
     3008  EFI_HOB_GUID_TYPE                     *GuidHob;
     3009  EFI_PHYSICAL_ADDRESS                  NvStorageBase;
     3010  UINT8                                 *NvStorageData;
     3011  UINT32                                NvStorageSize;
     3012  FAULT_TOLERANT_WRITE_LAST_WRITE_DATA  *FtwLastWriteData;
     3013  UINT32                                BackUpOffset;
     3014  UINT32                                BackUpSize;
     3015
     3016  mVariableModuleGlobal->FvbInstance = NULL;
     3017
     3018  //
     3019  // Note that in EdkII variable driver implementation, Hardware Error Record type variable
     3020  // is stored with common variable in the same NV region. So the platform integrator should
     3021  // ensure that the value of PcdHwErrStorageSize is less than or equal to the value of
     3022  // PcdFlashNvStorageVariableSize.
     3023  //
     3024  ASSERT (PcdGet32 (PcdHwErrStorageSize) <= PcdGet32 (PcdFlashNvStorageVariableSize));
     3025
     3026  //
     3027  // Allocate runtime memory used for a memory copy of the FLASH region.
     3028  // Keep the memory and the FLASH in sync as updates occur.
     3029  //
     3030  NvStorageSize = PcdGet32 (PcdFlashNvStorageVariableSize);
     3031  NvStorageData = AllocateRuntimeZeroPool (NvStorageSize);
     3032  if (NvStorageData == NULL) {
     3033    return EFI_OUT_OF_RESOURCES;
     3034  }
     3035
     3036  NvStorageBase = (EFI_PHYSICAL_ADDRESS) PcdGet64 (PcdFlashNvStorageVariableBase64);
     3037  if (NvStorageBase == 0) {
     3038    NvStorageBase = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashNvStorageVariableBase);
     3039  }
     3040  //
     3041  // Copy NV storage data to the memory buffer.
     3042  //
     3043  CopyMem (NvStorageData, (UINT8 *) (UINTN) NvStorageBase, NvStorageSize);
     3044
     3045  //
     3046  // Check the FTW last write data hob.
     3047  //
     3048  GuidHob = GetFirstGuidHob (&gEdkiiFaultTolerantWriteGuid);
     3049  if (GuidHob != NULL) {
     3050    FtwLastWriteData = (FAULT_TOLERANT_WRITE_LAST_WRITE_DATA *) GET_GUID_HOB_DATA (GuidHob);
     3051    if (FtwLastWriteData->TargetAddress == NvStorageBase) {
     3052      DEBUG ((EFI_D_INFO, "Variable: NV storage is backed up in spare block: 0x%x\n", (UINTN) FtwLastWriteData->SpareAddress));
     3053      //
     3054      // Copy the backed up NV storage data to the memory buffer from spare block.
     3055      //
     3056      CopyMem (NvStorageData, (UINT8 *) (UINTN) (FtwLastWriteData->SpareAddress), NvStorageSize);
     3057    } else if ((FtwLastWriteData->TargetAddress > NvStorageBase) &&
     3058               (FtwLastWriteData->TargetAddress < (NvStorageBase + NvStorageSize))) {
     3059      //
     3060      // Flash NV storage from the offset is backed up in spare block.
     3061      //
     3062      BackUpOffset = (UINT32) (FtwLastWriteData->TargetAddress - NvStorageBase);
     3063      BackUpSize = NvStorageSize - BackUpOffset;
     3064      DEBUG ((EFI_D_INFO, "Variable: High partial NV storage from offset: %x is backed up in spare block: 0x%x\n", BackUpOffset, (UINTN) FtwLastWriteData->SpareAddress));
     3065      //
     3066      // Copy the partial backed up NV storage data to the memory buffer from spare block.
     3067      //
     3068      CopyMem (NvStorageData + BackUpOffset, (UINT8 *) (UINTN) FtwLastWriteData->SpareAddress, BackUpSize);
     3069    }
     3070  }
     3071
     3072  FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) NvStorageData;
     3073
     3074  //
     3075  // Check if the Firmware Volume is not corrupted
     3076  //
     3077  if ((FvHeader->Signature != EFI_FVH_SIGNATURE) || (!CompareGuid (&gEfiSystemNvDataFvGuid, &FvHeader->FileSystemGuid))) {
     3078    FreePool (NvStorageData);
     3079    DEBUG ((EFI_D_ERROR, "Firmware Volume for Variable Store is corrupted\n"));
     3080    return EFI_VOLUME_CORRUPTED;
     3081  }
     3082
     3083  VariableStoreBase = (EFI_PHYSICAL_ADDRESS) ((UINTN) FvHeader + FvHeader->HeaderLength);
     3084  VariableStoreLength = (UINT64) (NvStorageSize - FvHeader->HeaderLength);
     3085
     3086  mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase = VariableStoreBase;
     3087  mNvVariableCache = (VARIABLE_STORE_HEADER *) (UINTN) VariableStoreBase;
     3088  if (GetVariableStoreStatus (mNvVariableCache) != EfiValid) {
     3089    FreePool (NvStorageData);
     3090    DEBUG((EFI_D_ERROR, "Variable Store header is corrupted\n"));
     3091    return EFI_VOLUME_CORRUPTED;
     3092  }
     3093  ASSERT(mNvVariableCache->Size == VariableStoreLength);
     3094
     3095  //
     3096  // The max variable or hardware error variable size should be < variable store size.
     3097  //
     3098  ASSERT(MAX (PcdGet32 (PcdMaxVariableSize), PcdGet32 (PcdMaxHardwareErrorVariableSize)) < VariableStoreLength);
     3099
     3100  //
     3101  // Parse non-volatile variable data and get last variable offset.
     3102  //
     3103  NextVariable  = GetStartPointer ((VARIABLE_STORE_HEADER *)(UINTN)VariableStoreBase);
     3104  while (IsValidVariableHeader (NextVariable, GetEndPointer ((VARIABLE_STORE_HEADER *)(UINTN)VariableStoreBase))) {
     3105    VariableSize = NextVariable->NameSize + NextVariable->DataSize + sizeof (VARIABLE_HEADER);
     3106    if ((NextVariable->Attributes & (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) == (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {
     3107      mVariableModuleGlobal->HwErrVariableTotalSize += HEADER_ALIGN (VariableSize);
     3108    } else {
     3109      mVariableModuleGlobal->CommonVariableTotalSize += HEADER_ALIGN (VariableSize);
     3110    }
     3111
     3112    NextVariable = GetNextVariablePtr (NextVariable);
     3113  }
     3114  mVariableModuleGlobal->NonVolatileLastVariableOffset = (UINTN) NextVariable - (UINTN) VariableStoreBase;
     3115
     3116  return EFI_SUCCESS;
     3117}
     3118
     3119/**
     3120  Flush the HOB variable to flash.
     3121
     3122  @param[in] VariableName       Name of variable has been updated or deleted.
     3123  @param[in] VendorGuid         Guid of variable has been updated or deleted.
     3124
     3125**/
     3126VOID
     3127FlushHobVariableToFlash (
     3128  IN CHAR16                     *VariableName,
     3129  IN EFI_GUID                   *VendorGuid
     3130  )
     3131{
     3132  EFI_STATUS                    Status;
     3133  VARIABLE_STORE_HEADER         *VariableStoreHeader;
     3134  VARIABLE_HEADER               *Variable;
     3135  VOID                          *VariableData;
     3136  BOOLEAN                       ErrorFlag;
     3137
     3138  ErrorFlag = FALSE;
     3139
     3140  //
     3141  // Flush the HOB variable to flash.
     3142  //
     3143  if (mVariableModuleGlobal->VariableGlobal.HobVariableBase != 0) {
     3144    VariableStoreHeader = (VARIABLE_STORE_HEADER *) (UINTN) mVariableModuleGlobal->VariableGlobal.HobVariableBase;
     3145    //
     3146    // Set HobVariableBase to 0, it can avoid SetVariable to call back.
     3147    //
     3148    mVariableModuleGlobal->VariableGlobal.HobVariableBase = 0;
     3149    for ( Variable = GetStartPointer (VariableStoreHeader)
     3150        ; IsValidVariableHeader (Variable, GetEndPointer (VariableStoreHeader))
     3151        ; Variable = GetNextVariablePtr (Variable)
     3152        ) {
     3153      if (Variable->State != VAR_ADDED) {
     3154        //
     3155        // The HOB variable has been set to DELETED state in local.
     3156        //
     3157        continue;
     3158      }
     3159      ASSERT ((Variable->Attributes & EFI_VARIABLE_NON_VOLATILE) != 0);
     3160      if (VendorGuid == NULL || VariableName == NULL ||
     3161          !CompareGuid (VendorGuid, &Variable->VendorGuid) ||
     3162          StrCmp (VariableName, GetVariableNamePtr (Variable)) != 0) {
     3163        VariableData = GetVariableDataPtr (Variable);
     3164        Status = VariableServiceSetVariable (
     3165                   GetVariableNamePtr (Variable),
     3166                   &Variable->VendorGuid,
     3167                   Variable->Attributes,
     3168                   Variable->DataSize,
     3169                   VariableData
     3170                   );
     3171        DEBUG ((EFI_D_INFO, "Variable driver flush the HOB variable to flash: %g %s %r\n", &Variable->VendorGuid, GetVariableNamePtr (Variable), Status));
     3172      } else {
     3173        //
     3174        // The updated or deleted variable is matched with the HOB variable.
     3175        // Don't break here because we will try to set other HOB variables
     3176        // since this variable could be set successfully.
     3177        //
     3178        Status = EFI_SUCCESS;
     3179      }
     3180      if (!EFI_ERROR (Status)) {
     3181        //
     3182        // If set variable successful, or the updated or deleted variable is matched with the HOB variable,
     3183        // set the HOB variable to DELETED state in local.
     3184        //
     3185        DEBUG ((EFI_D_INFO, "Variable driver set the HOB variable to DELETED state in local: %g %s\n", &Variable->VendorGuid, GetVariableNamePtr (Variable)));
     3186        Variable->State &= VAR_DELETED;
     3187      } else {
     3188        ErrorFlag = TRUE;
     3189      }
     3190    }
     3191    if (ErrorFlag) {
     3192      //
     3193      // We still have HOB variable(s) not flushed in flash.
     3194      //
     3195      mVariableModuleGlobal->VariableGlobal.HobVariableBase = (EFI_PHYSICAL_ADDRESS) (UINTN) VariableStoreHeader;
     3196    } else {
     3197      //
     3198      // All HOB variables have been flushed in flash.
     3199      //
     3200      DEBUG ((EFI_D_INFO, "Variable driver: all HOB variables have been flushed in flash.\n"));
     3201      if (!AtRuntime ()) {
     3202        FreePool ((VOID *) VariableStoreHeader);
     3203      }
     3204    }
     3205  }
     3206
     3207}
     3208
     3209/**
     3210  Initializes variable write service after FTW was ready.
    23183211
    23193212  @retval EFI_SUCCESS          Function successfully executed.
     
    23313224  UINT8                           Data;
    23323225  EFI_PHYSICAL_ADDRESS            VariableStoreBase;
    2333   VARIABLE_HEADER                 *Variable;
    2334   VOID                            *VariableData;
    2335 
    2336   VariableStoreBase   = mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase;
     3226  EFI_PHYSICAL_ADDRESS            NvStorageBase;
     3227
     3228  NvStorageBase = (EFI_PHYSICAL_ADDRESS) PcdGet64 (PcdFlashNvStorageVariableBase64);
     3229  if (NvStorageBase == 0) {
     3230    NvStorageBase = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashNvStorageVariableBase);
     3231  }
     3232  VariableStoreBase = NvStorageBase + (((EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)(NvStorageBase))->HeaderLength);
     3233
     3234  //
     3235  // Let NonVolatileVariableBase point to flash variable store base directly after FTW ready.
     3236  //
     3237  mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase = VariableStoreBase;
    23373238  VariableStoreHeader = (VARIABLE_STORE_HEADER *)(UINTN)VariableStoreBase;
    23383239 
     
    23503251                 &mVariableModuleGlobal->NonVolatileLastVariableOffset,
    23513252                 FALSE,
    2352                  NULL
     3253                 NULL,
     3254                 NULL,
     3255                 0
    23533256                 );
    23543257      if (EFI_ERROR (Status)) {
     
    23593262  }
    23603263
    2361   //
    2362   // Flush the HOB variable to flash and invalidate HOB variable.
    2363   //
    2364   if (mVariableModuleGlobal->VariableGlobal.HobVariableBase != 0) {
    2365     //
    2366     // Clear the HobVariableBase to avoid SetVariable() updating the variable in HOB
    2367     //
    2368     VariableStoreHeader = (VARIABLE_STORE_HEADER *) (UINTN) mVariableModuleGlobal->VariableGlobal.HobVariableBase;
    2369     mVariableModuleGlobal->VariableGlobal.HobVariableBase = 0;
    2370 
    2371     for ( Variable = GetStartPointer (VariableStoreHeader)
    2372         ; (Variable < GetEndPointer (VariableStoreHeader) && IsValidVariableHeader (Variable))
    2373         ; Variable = GetNextVariablePtr (Variable)
    2374         ) {
    2375       ASSERT (Variable->State == VAR_ADDED);
    2376       ASSERT ((Variable->Attributes & EFI_VARIABLE_NON_VOLATILE) != 0);
    2377       VariableData = GetVariableDataPtr (Variable);
    2378       Status = VariableServiceSetVariable (
    2379                  GetVariableNamePtr (Variable),
    2380                  &Variable->VendorGuid,
    2381                  Variable->Attributes,
    2382                  Variable->DataSize,
    2383                  VariableData
    2384                  );
    2385       ASSERT_EFI_ERROR (Status);
    2386     }
    2387   }
     3264  FlushHobVariableToFlash (NULL, NULL);
     3265
    23883266  return EFI_SUCCESS;
    23893267}
     
    24053283  VARIABLE_STORE_HEADER           *VolatileVariableStore;
    24063284  VARIABLE_STORE_HEADER           *VariableStoreHeader;
    2407   VARIABLE_HEADER                 *NextVariable;
    2408   EFI_PHYSICAL_ADDRESS            TempVariableStoreHeader;
    2409   EFI_PHYSICAL_ADDRESS            VariableStoreBase;
    24103285  UINT64                          VariableStoreLength;
    24113286  UINTN                           ScratchSize;
    2412   UINTN                           VariableSize;
    24133287  EFI_HOB_GUID_TYPE               *GuidHob;
    24143288
     
    24243298
    24253299  //
    2426   // Note that in EdkII variable driver implementation, Hardware Error Record type variable
    2427   // is stored with common variable in the same NV region. So the platform integrator should
    2428   // ensure that the value of PcdHwErrStorageSize is less than or equal to the value of
    2429   // PcdFlashNvStorageVariableSize.
    2430   //
    2431   ASSERT (PcdGet32 (PcdHwErrStorageSize) <= PcdGet32 (PcdFlashNvStorageVariableSize));
    2432 
    2433   //
    24343300  // Get HOB variable store.
    24353301  //
     
    24373303  if (GuidHob != NULL) {
    24383304    VariableStoreHeader = GET_GUID_HOB_DATA (GuidHob);
     3305    VariableStoreLength = (UINT64) (GuidHob->Header.HobLength - sizeof (EFI_HOB_GUID_TYPE));
    24393306    if (GetVariableStoreStatus (VariableStoreHeader) == EfiValid) {
    2440       mVariableModuleGlobal->VariableGlobal.HobVariableBase = (EFI_PHYSICAL_ADDRESS) (UINTN) VariableStoreHeader;
     3307      mVariableModuleGlobal->VariableGlobal.HobVariableBase = (EFI_PHYSICAL_ADDRESS) (UINTN) AllocateRuntimeCopyPool ((UINTN) VariableStoreLength, (VOID *) VariableStoreHeader);
     3308      if (mVariableModuleGlobal->VariableGlobal.HobVariableBase == 0) {
     3309        FreePool (mVariableModuleGlobal);
     3310        return EFI_OUT_OF_RESOURCES;
     3311      }
    24413312    } else {
    24423313      DEBUG ((EFI_D_ERROR, "HOB Variable Store header is corrupted!\n"));
     
    24503321  VolatileVariableStore = AllocateRuntimePool (PcdGet32 (PcdVariableStoreSize) + ScratchSize);
    24513322  if (VolatileVariableStore == NULL) {
     3323    if (mVariableModuleGlobal->VariableGlobal.HobVariableBase != 0) {
     3324      FreePool ((VOID *) (UINTN) mVariableModuleGlobal->VariableGlobal.HobVariableBase);
     3325    }
    24523326    FreePool (mVariableModuleGlobal);
    24533327    return EFI_OUT_OF_RESOURCES;
     
    24613335  mVariableModuleGlobal->VariableGlobal.VolatileVariableBase = (EFI_PHYSICAL_ADDRESS) (UINTN) VolatileVariableStore;
    24623336  mVariableModuleGlobal->VolatileLastVariableOffset = (UINTN) GetStartPointer (VolatileVariableStore) - (UINTN) VolatileVariableStore;
    2463   mVariableModuleGlobal->FvbInstance = NULL;
    24643337
    24653338  CopyGuid (&VolatileVariableStore->Signature, &gEfiVariableGuid);
     
    24713344
    24723345  //
    2473   // Get non-volatile variable store.
    2474   //
    2475 
    2476   TempVariableStoreHeader = (EFI_PHYSICAL_ADDRESS) PcdGet64 (PcdFlashNvStorageVariableBase64);
    2477   if (TempVariableStoreHeader == 0) {
    2478     TempVariableStoreHeader = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashNvStorageVariableBase);
    2479   }
    2480 
    2481   //
    2482   // Check if the Firmware Volume is not corrupted
    2483   //
    2484   if ((((EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)(TempVariableStoreHeader))->Signature != EFI_FVH_SIGNATURE) ||
    2485       (!CompareGuid (&gEfiSystemNvDataFvGuid, &((EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)(TempVariableStoreHeader))->FileSystemGuid))) {
    2486     Status = EFI_VOLUME_CORRUPTED;
    2487     DEBUG ((EFI_D_ERROR, "Firmware Volume for Variable Store is corrupted\n"));
    2488     goto Done;
    2489   }
    2490 
    2491   VariableStoreBase       = TempVariableStoreHeader + \
    2492                               (((EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)(TempVariableStoreHeader)) -> HeaderLength);
    2493   VariableStoreLength     = (UINT64) PcdGet32 (PcdFlashNvStorageVariableSize) - \
    2494                               (((EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)(TempVariableStoreHeader)) -> HeaderLength);
    2495 
    2496   mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase = VariableStoreBase;
    2497   VariableStoreHeader = (VARIABLE_STORE_HEADER *)(UINTN)VariableStoreBase;
    2498   if (GetVariableStoreStatus (VariableStoreHeader) != EfiValid) {
    2499     Status = EFI_VOLUME_CORRUPTED;
    2500     DEBUG((EFI_D_INFO, "Variable Store header is corrupted\n"));
    2501     goto Done;
    2502   } 
    2503   ASSERT(VariableStoreHeader->Size == VariableStoreLength);
    2504    
    2505   //
    2506   // Parse non-volatile variable data and get last variable offset.
    2507   //
    2508   NextVariable  = GetStartPointer ((VARIABLE_STORE_HEADER *)(UINTN)VariableStoreBase);
    2509   while (IsValidVariableHeader (NextVariable)) {
    2510     VariableSize = NextVariable->NameSize + NextVariable->DataSize + sizeof (VARIABLE_HEADER);
    2511     if ((NextVariable->Attributes & (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) == (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {
    2512       mVariableModuleGlobal->HwErrVariableTotalSize += HEADER_ALIGN (VariableSize);
    2513     } else {
    2514       mVariableModuleGlobal->CommonVariableTotalSize += HEADER_ALIGN (VariableSize);
    2515     }
    2516 
    2517     NextVariable = GetNextVariablePtr (NextVariable);
    2518   }
    2519 
    2520   mVariableModuleGlobal->NonVolatileLastVariableOffset = (UINTN) NextVariable - (UINTN) VariableStoreBase;
    2521    
    2522   //
    2523   // Allocate runtime memory used for a memory copy of the FLASH region.
    2524   // Keep the memory and the FLASH in sync as updates occur
    2525   //
    2526   mNvVariableCache = AllocateRuntimeZeroPool ((UINTN)VariableStoreLength);
    2527   if (mNvVariableCache == NULL) {
    2528     Status = EFI_OUT_OF_RESOURCES;
    2529     goto Done;
    2530   }
    2531   CopyMem (mNvVariableCache, (CHAR8 *)(UINTN)VariableStoreBase, (UINTN)VariableStoreLength);
    2532   Status = EFI_SUCCESS;
    2533 
    2534 Done:
     3346  // Init non-volatile variable store.
     3347  //
     3348  Status = InitNonVolatileVariableStore ();
    25353349  if (EFI_ERROR (Status)) {
     3350    if (mVariableModuleGlobal->VariableGlobal.HobVariableBase != 0) {
     3351      FreePool ((VOID *) (UINTN) mVariableModuleGlobal->VariableGlobal.HobVariableBase);
     3352    }
    25363353    FreePool (mVariableModuleGlobal);
    25373354    FreePool (VolatileVariableStore);
     
    25663383  EFI_FVB_ATTRIBUTES_2                    Attributes;
    25673384 
     3385  Fvb = NULL;
     3386  HandleBuffer = NULL;
     3387
    25683388  //
    25693389  // Get all FVB handles.
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette