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:
10 edited

Legend:

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

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

    r48674 r58459  
    44  (Fault Tolerant Write) protocol.
    55
    6 Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
     6Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
    77This program and the accompanying materials
    88are licensed and made available under the terms and conditions of the BSD License
     
    4848  UINT32                              LbaIndex;
    4949
     50  Fvb     = NULL;
    5051  *Lba    = (EFI_LBA) (-1);
    5152  *Offset = 0;
     
    100101
    101102  @param  VariableBase   Base address of variable to write
    102   @param  Buffer         Point to the data buffer.
    103   @param  BufferSize     The number of bytes of the data Buffer.
     103  @param  VariableBuffer Point to the variable data buffer.
    104104
    105105  @retval EFI_SUCCESS    The function completed successfully.
     
    111111FtwVariableSpace (
    112112  IN EFI_PHYSICAL_ADDRESS   VariableBase,
    113   IN UINT8                  *Buffer,
    114   IN UINTN                  BufferSize
     113  IN VARIABLE_STORE_HEADER  *VariableBuffer
    115114  )
    116115{
     
    119118  EFI_LBA                            VarLba;
    120119  UINTN                              VarOffset;
    121   UINT8                              *FtwBuffer;
    122120  UINTN                              FtwBufferSize;
    123121  EFI_FAULT_TOLERANT_WRITE_PROTOCOL  *FtwProtocol;
     
    144142    return EFI_ABORTED;
    145143  }
    146   //
    147   // Prepare for the variable data.
    148   //
     144
    149145  FtwBufferSize = ((VARIABLE_STORE_HEADER *) ((UINTN) VariableBase))->Size;
    150   FtwBuffer     = AllocatePool (FtwBufferSize);
    151   if (FtwBuffer == NULL) {
    152     return EFI_OUT_OF_RESOURCES;
    153   }
    154 
    155   SetMem (FtwBuffer, FtwBufferSize, (UINT8) 0xff);
    156   CopyMem (FtwBuffer, Buffer, BufferSize);
     146  ASSERT (FtwBufferSize == VariableBuffer->Size);
    157147
    158148  //
     
    166156                          NULL,           // PrivateData NULL
    167157                          FvbHandle,      // Fvb Handle
    168                           FtwBuffer      // write buffer
     158                          (VOID *) VariableBuffer // write buffer
    169159                          );
    170160
    171   FreePool (FtwBuffer);
    172161  return Status;
    173162}
  • 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.
  • trunk/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.h

    r48674 r58459  
    44  internal structure and functions used by Variable modules.
    55
    6 Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
     6Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
    77This program and the accompanying materials
    88are licensed and made available under the terms and conditions of the BSD License
     
    2323#include <Protocol/FirmwareVolumeBlock.h>
    2424#include <Protocol/Variable.h>
     25#include <Protocol/VariableLock.h>
    2526#include <Library/PcdLib.h>
    2627#include <Library/HobLib.h>
     
    3940#include <Guid/VariableFormat.h>
    4041#include <Guid/SystemNvDataGuid.h>
    41 
    42 #define VARIABLE_RECLAIM_THRESHOLD (1024)
     42#include <Guid/FaultTolerantWrite.h>
     43#include <Guid/HardwareErrorVariable.h>
     44
     45#define VARIABLE_ATTRIBUTE_BS_RT        (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS)
     46#define VARIABLE_ATTRIBUTE_NV_BS_RT     (VARIABLE_ATTRIBUTE_BS_RT | EFI_VARIABLE_NON_VOLATILE)
     47#define VARIABLE_ATTRIBUTE_NV_BS_RT_AT  (VARIABLE_ATTRIBUTE_NV_BS_RT | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS)
     48
     49typedef struct {
     50  CHAR16      *Name;
     51  UINT32      Attributes;
     52} GLOBAL_VARIABLE_ENTRY;
    4353
    4454///
     
    5666typedef struct {
    5767  VARIABLE_HEADER *CurrPtr;
     68  //
     69  // If both ADDED and IN_DELETED_TRANSITION variable are present,
     70  // InDeletedTransitionPtr will point to the IN_DELETED_TRANSITION one.
     71  // Otherwise, CurrPtr will point to the ADDED or IN_DELETED_TRANSITION one,
     72  // and InDeletedTransitionPtr will be NULL at the same time.
     73  //
     74  VARIABLE_HEADER *InDeletedTransitionPtr;
    5875  VARIABLE_HEADER *EndPtr;
    5976  VARIABLE_HEADER *StartPtr;
     
    85102  EFI_GUID    *Guid;
    86103  CHAR16      *Name;
    87   UINT32      Attributes;
    88   UINTN       DataSize;
    89   VOID        *Data;
    90 } VARIABLE_CACHE_ENTRY;
     104  UINTN       VariableSize;
     105} VARIABLE_ENTRY_CONSISTENCY;
     106
     107typedef struct {
     108  EFI_GUID    Guid;
     109  CHAR16      *Name;
     110  LIST_ENTRY  Link;
     111} VARIABLE_ENTRY;
     112
     113/**
     114  Flush the HOB variable to flash.
     115
     116  @param[in] VariableName       Name of variable has been updated or deleted.
     117  @param[in] VendorGuid         Guid of variable has been updated or deleted.
     118
     119**/
     120VOID
     121FlushHobVariableToFlash (
     122  IN CHAR16                     *VariableName,
     123  IN EFI_GUID                   *VendorGuid
     124  );
    91125
    92126/**
     
    98132
    99133  @param  VariableBase   Base address of the variable to write.
    100   @param  Buffer         Point to the data buffer.
    101   @param  BufferSize     The number of bytes of the data Buffer.
     134  @param  VariableBuffer Point to the variable data buffer.
    102135
    103136  @retval EFI_SUCCESS    The function completed successfully.
     
    109142FtwVariableSpace (
    110143  IN EFI_PHYSICAL_ADDRESS   VariableBase,
    111   IN UINT8                  *Buffer,
    112   IN UINTN                  BufferSize
     144  IN VARIABLE_STORE_HEADER  *VariableBuffer
    113145  );
    114146
     
    128160  @param[in] Attributes         Attribues of the variable.
    129161
    130   @param[in] Variable           The variable information that is used to keep track of variable usage.
     162  @param[in, out] Variable      The variable information that is used to keep track of variable usage.
    131163
    132164  @retval EFI_SUCCESS           The update operation is success.
     
    142174  IN      UINTN           DataSize,
    143175  IN      UINT32          Attributes OPTIONAL,
    144   IN      VARIABLE_POINTER_TRACK *Variable
     176  IN OUT  VARIABLE_POINTER_TRACK *Variable
    145177  );
    146178
     
    423455                                        associated with the attributes specified.
    424456
     457  @return EFI_SUCCESS                   Query successfully.
     458
     459**/
     460EFI_STATUS
     461EFIAPI
     462VariableServiceQueryVariableInfoInternal (
     463  IN  UINT32                 Attributes,
     464  OUT UINT64                 *MaximumVariableStorageSize,
     465  OUT UINT64                 *RemainingVariableStorageSize,
     466  OUT UINT64                 *MaximumVariableSize
     467  );
     468
     469/**
     470
     471  This code returns information about the EFI variables.
     472
     473  @param Attributes                     Attributes bitmask to specify the type of variables
     474                                        on which to return information.
     475  @param MaximumVariableStorageSize     Pointer to the maximum size of the storage space available
     476                                        for the EFI variables associated with the attributes specified.
     477  @param RemainingVariableStorageSize   Pointer to the remaining size of the storage space available
     478                                        for EFI variables associated with the attributes specified.
     479  @param MaximumVariableSize            Pointer to the maximum size of an individual EFI variables
     480                                        associated with the attributes specified.
     481
    425482  @return EFI_INVALID_PARAMETER         An invalid combination of attribute bits was supplied.
    426483  @return EFI_SUCCESS                   Query successfully.
     
    436493  OUT UINT64                 *MaximumVariableSize
    437494  ); 
    438  
     495
     496/**
     497  Mark a variable that will become read-only after leaving the DXE phase of execution.
     498
     499  @param[in] This          The VARIABLE_LOCK_PROTOCOL instance.
     500  @param[in] VariableName  A pointer to the variable name that will be made read-only subsequently.
     501  @param[in] VendorGuid    A pointer to the vendor GUID that will be made read-only subsequently.
     502
     503  @retval EFI_SUCCESS           The variable specified by the VariableName and the VendorGuid was marked
     504                                as pending to be read-only.
     505  @retval EFI_INVALID_PARAMETER VariableName or VendorGuid is NULL.
     506                                Or VariableName is an empty string.
     507  @retval EFI_ACCESS_DENIED     EFI_END_OF_DXE_EVENT_GROUP_GUID or EFI_EVENT_GROUP_READY_TO_BOOT has
     508                                already been signaled.
     509  @retval EFI_OUT_OF_RESOURCES  There is not enough resource to hold the lock request.
     510**/
     511EFI_STATUS
     512EFIAPI
     513VariableLockRequestToLock (
     514  IN CONST EDKII_VARIABLE_LOCK_PROTOCOL *This,
     515  IN       CHAR16                       *VariableName,
     516  IN       EFI_GUID                     *VendorGuid
     517  );
     518
    439519extern VARIABLE_MODULE_GLOBAL  *mVariableModuleGlobal;
    440520
  • trunk/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c

    r48674 r58459  
    44  and volatile storage space and install variable architecture protocol.
    55 
    6 Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
     6Copyright (C) 2013, Red Hat, Inc.
     7Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
    78This program and the accompanying materials                         
    89are licensed and made available under the terms and conditions of the BSD License         
     
    2223EFI_EVENT                      mVirtualAddressChangeEvent = NULL;
    2324EFI_EVENT                      mFtwRegistration           = NULL;
     25extern LIST_ENTRY              mLockedVariableList;
     26extern BOOLEAN                 mEndOfDxe;
     27EDKII_VARIABLE_LOCK_PROTOCOL   mVariableLock              = { VariableLockRequestToLock };
    2428
    2529/**
     
    219223  )
    220224{
     225  LIST_ENTRY     *Link;
     226  VARIABLE_ENTRY *Entry;
     227  EFI_STATUS     Status;
     228
    221229  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->GetBlockSize);
    222230  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->GetPhysicalAddress);
     
    232240  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase);
    233241  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->VariableGlobal.VolatileVariableBase);
     242  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->VariableGlobal.HobVariableBase);
    234243  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal);
    235244  EfiConvertPointer (0x0, (VOID **) &mNvVariableCache); 
     245
     246  //
     247  // in the list of locked variables, convert the name pointers first
     248  //
     249  for ( Link = GetFirstNode (&mLockedVariableList)
     250      ; !IsNull (&mLockedVariableList, Link)
     251      ; Link = GetNextNode (&mLockedVariableList, Link)
     252      ) {
     253    Entry = BASE_CR (Link, VARIABLE_ENTRY, Link);
     254    Status = EfiConvertPointer (0x0, (VOID **) &Entry->Name);
     255    ASSERT_EFI_ERROR (Status);
     256  }
     257  //
     258  // second, convert the list itself using UefiRuntimeLib
     259  //
     260  Status = EfiConvertList (0x0, &mLockedVariableList);
     261  ASSERT_EFI_ERROR (Status);
    236262}
    237263
     
    255281  )
    256282{
     283  //
     284  // Set the End Of DXE bit in case the EFI_END_OF_DXE_EVENT_GROUP_GUID event is not signaled.
     285  //
     286  mEndOfDxe = TRUE;
    257287  ReclaimForOS ();
    258288  if (FeaturePcdGet (PcdVariableCollectStatistics)) {
     
    261291}
    262292
     293/**
     294  Notification function of EFI_END_OF_DXE_EVENT_GROUP_GUID event group.
     295
     296  This is a notification function registered on EFI_END_OF_DXE_EVENT_GROUP_GUID event group.
     297
     298  @param  Event        Event whose notification function is being invoked.
     299  @param  Context      Pointer to the notification function's context.
     300
     301**/
     302VOID
     303EFIAPI
     304OnEndOfDxe (
     305  EFI_EVENT                               Event,
     306  VOID                                    *Context
     307  )
     308{
     309  mEndOfDxe = TRUE;
     310  if (PcdGetBool (PcdReclaimVariableSpaceAtEndOfDxe)) {
     311    ReclaimForOS ();
     312  }
     313}
    263314
    264315/**
     
    288339  EFI_PHYSICAL_ADDRESS                    VariableStoreBase;
    289340  UINT64                                  VariableStoreLength;
     341  UINTN                                   FtwMaxBlockSize;
    290342
    291343  //
     
    296348    return ;
    297349  }
    298  
     350
     351  Status = FtwProtocol->GetMaxBlockSize (FtwProtocol, &FtwMaxBlockSize);
     352  if (!EFI_ERROR (Status)) {
     353    ASSERT (PcdGet32 (PcdFlashNvStorageVariableSize) <= FtwMaxBlockSize);
     354  }
     355
    299356  //
    300357  // Find the proper FVB protocol for variable.
     
    313370  // Mark the variable storage region of the FLASH as RUNTIME.
    314371  //
    315   VariableStoreBase   = mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase;
     372  VariableStoreBase   = NvStorageVariableBase + (((EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)(NvStorageVariableBase))->HeaderLength);
    316373  VariableStoreLength = ((VARIABLE_STORE_HEADER *)(UINTN)VariableStoreBase)->Size;
    317374  BaseAddress = VariableStoreBase & (~EFI_PAGE_MASK);
     
    321378  Status      = gDS->GetMemorySpaceDescriptor (BaseAddress, &GcdDescriptor);
    322379  if (EFI_ERROR (Status)) {
    323     DEBUG ((DEBUG_WARN, "Variable driver failed to add EFI_MEMORY_RUNTIME attribute to Flash.\n"));
     380    DEBUG ((DEBUG_WARN, "Variable driver failed to get flash memory attribute.\n"));
    324381  } else {
    325382    Status = gDS->SetMemorySpaceAttributes (
     
    375432{
    376433  EFI_STATUS                            Status;
    377   EFI_EVENT                             ReadyToBootEvent;   
     434  EFI_EVENT                             ReadyToBootEvent;
     435  EFI_EVENT                             EndOfDxeEvent;
    378436
    379437  Status = VariableCommonInitialize ();
     438  ASSERT_EFI_ERROR (Status);
     439
     440  Status = gBS->InstallMultipleProtocolInterfaces (
     441                  &mHandle,
     442                  &gEdkiiVariableLockProtocolGuid,
     443                  &mVariableLock,
     444                  NULL
     445                  );
    380446  ASSERT_EFI_ERROR (Status);
    381447
     
    426492             &ReadyToBootEvent
    427493             );
     494  ASSERT_EFI_ERROR (Status);
     495
     496  //
     497  // Register the event handling function to set the End Of DXE flag.
     498  //
     499  Status = gBS->CreateEventEx (
     500                  EVT_NOTIFY_SIGNAL,
     501                  TPL_NOTIFY,
     502                  OnEndOfDxe,
     503                  NULL,
     504                  &gEfiEndOfDxeEventGroupGuid,
     505                  &EndOfDxeEvent
     506                  );
     507  ASSERT_EFI_ERROR (Status);
    428508
    429509  return EFI_SUCCESS;
  • trunk/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf

    r48674 r58459  
    11## @file
    2 # Component description file for Variable module.
     2# This module installs variable arch protocol and variable write arch protocol.
    33#
    4 # This module installs three EFI_RUNTIME_SERVICES: SetVariable, GetVariable, GetNextVariableName.
    5 # Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
     4# It provides four EFI_RUNTIME_SERVICES: SetVariable, GetVariable, GetNextVariableName and QueryVariableInfo.
     5#
     6#  Caution: This module requires additional review when modified.
     7#  This driver will have external input - variable data.
     8#  This external input must be validated carefully to avoid security issues such as
     9#  buffer overflow or integer overflow.
     10#
     11# Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
    612#
    713#  This program and the accompanying materials
     
    1824  INF_VERSION                    = 0x00010005
    1925  BASE_NAME                      = VariableRuntimeDxe
     26  MODULE_UNI_FILE                = VariableRuntimeDxe.uni
    2027  FILE_GUID                      = CBD2E4D5-7068-4FF5-B462-9822B4AD8D60
    2128  MODULE_TYPE                    = DXE_RUNTIME_DRIVER
     
    5663
    5764[Protocols]
    58   gEfiFirmwareVolumeBlockProtocolGuid           ## SOMETIMES_CONSUMES
    59   gEfiVariableWriteArchProtocolGuid             ## ALWAYS_PRODUCES
    60   gEfiVariableArchProtocolGuid                  ## ALWAYS_PRODUCES
    61   gEfiFaultTolerantWriteProtocolGuid            ## SOMETIMES_CONSUMES
     65  gEfiFirmwareVolumeBlockProtocolGuid           ## CONSUMES
     66  ## CONSUMES
     67  ## NOTIFY
     68  gEfiFaultTolerantWriteProtocolGuid
     69  gEfiVariableWriteArchProtocolGuid             ## PRODUCES
     70  gEfiVariableArchProtocolGuid                  ## PRODUCES
     71  gEdkiiVariableLockProtocolGuid                ## PRODUCES
    6272
    6373[Guids]
    64   gEfiVariableGuid                              ## PRODUCES ## Configuration Table Guid
    65   gEfiGlobalVariableGuid                        ## PRODUCES ## Variable Guid
    66   gEfiEventVirtualAddressChangeGuid             ## PRODUCES ## Event
    67   gEfiSystemNvDataFvGuid                        ## CONSUMES
     74  ## PRODUCES             ## GUID # Signature of Variable store header
     75  ## CONSUMES             ## GUID # Signature of Variable store header
     76  ## SOMETIMES_CONSUMES   ## HOB
     77  ## SOMETIMES_PRODUCES   ## SystemTable
     78  gEfiVariableGuid
     79  ## SOMETIMES_CONSUMES   ## Variable:L"PlatformLang"
     80  ## SOMETIMES_PRODUCES   ## Variable:L"PlatformLang"
     81  ## SOMETIMES_CONSUMES   ## Variable:L"Lang"
     82  ## SOMETIMES_PRODUCES   ## Variable:L"Lang"
     83  ## SOMETIMES_CONSUMES   ## Variable:L"HwErrRecSupport"
     84  gEfiGlobalVariableGuid
     85  gEfiEventVirtualAddressChangeGuid             ## CONSUMES             ## Event
     86  gEfiSystemNvDataFvGuid                        ## CONSUMES             ## GUID
     87  gEfiHardwareErrorVariableGuid                 ## SOMETIMES_CONSUMES   ## Variable:L"HwErrRec####"
     88  gEfiEndOfDxeEventGroupGuid                    ## CONSUMES             ## Event
     89  ## SOMETIMES_CONSUMES   ## HOB
     90  gEdkiiFaultTolerantWriteGuid
    6891
    6992[Pcd]
    70   gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize
    71   gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase
    72   gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64
    73   gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize
    74   gEfiMdeModulePkgTokenSpaceGuid.PcdMaxHardwareErrorVariableSize
    75   gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize
    76   gEfiMdeModulePkgTokenSpaceGuid.PcdHwErrStorageSize
    77  
     93  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize      ## CONSUMES
     94  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase      ## SOMETIMES_CONSUMES
     95  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64    ## CONSUMES
     96  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize                 ## CONSUMES
     97  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxHardwareErrorVariableSize    ## CONSUMES
     98  gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize               ## CONSUMES
     99  gEfiMdeModulePkgTokenSpaceGuid.PcdHwErrStorageSize                ## CONSUMES
     100  gEfiMdeModulePkgTokenSpaceGuid.PcdReclaimVariableSpaceAtEndOfDxe  ## CONSUMES
     101
    78102[FeaturePcd]
    79   gEfiMdeModulePkgTokenSpaceGuid.PcdVariableCollectStatistics  ## SOMETIME_CONSUMES (statistic the information of variable.)
     103  gEfiMdeModulePkgTokenSpaceGuid.PcdVariableCollectStatistics  ## CONSUMES # statistic the information of variable.
     104  gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultLangDeprecate ## CONSUMES
    80105
    81106[Depex]
    82107  TRUE
    83108
    84 # [Event]
    85 #   ##
    86 #   # Event will be signaled for VIRTUAL_ADDRESS_CHANGE event.
    87 #   #
    88 #   EVENT_TYPE_NOTIFY_SIGNAL                    ## PRODUCES
    89 #
    90 #
    91    
     109[UserExtensions.TianoCore."ExtraFiles"]
     110  VariableRuntimeDxeExtra.uni
  • trunk/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.c

    r48674 r58459  
    55  to provide variable services.
    66
    7 Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>
    8 This program and the accompanying materials                         
    9 are licensed and made available under the terms and conditions of the BSD License         
    10 which accompanies this distribution.  The full text of the license may be found at       
    11 http://opensource.org/licenses/bsd-license.php                                           
     7  Caution: This module requires additional review when modified.
     8  This driver will have external input - variable data and communicate buffer in SMM mode.
     9  This external input must be validated carefully to avoid security issue like
     10  buffer overflow, integer overflow.
     11
     12  SmmVariableHandler() will receive untrusted input and do basic validation.
     13
     14  Each sub function VariableServiceGetVariable(), VariableServiceGetNextVariableName(),
     15  VariableServiceSetVariable(), VariableServiceQueryVariableInfo(), ReclaimForOS(),
     16  SmmVariableGetStatistics() should also do validation based on its own knowledge.
     17
     18Copyright (c) 2010 - 2013, Intel Corporation. All rights reserved.<BR>
     19This program and the accompanying materials
     20are licensed and made available under the terms and conditions of the BSD License
     21which accompanies this distribution.  The full text of the license may be found at
     22http://opensource.org/licenses/bsd-license.php
    1223
    1324THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     
     
    1829#include <Protocol/SmmFirmwareVolumeBlock.h>
    1930#include <Protocol/SmmFaultTolerantWrite.h>
     31#include <Protocol/SmmEndOfDxe.h>
     32
    2033#include <Library/SmmServicesTableLib.h>
     34#include <Library/SmmMemLib.h>
    2135
    2236#include <Guid/VariableFormat.h>
     
    2943BOOLEAN                                              mAtRuntime              = FALSE;
    3044EFI_GUID                                             mZeroGuid               = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};
    31  
     45UINT8                                                *mVariableBufferPayload = NULL;
     46UINTN                                                mVariableBufferPayloadSize;
     47extern BOOLEAN                                       mEndOfDxe;
     48extern BOOLEAN                                       mEnableLocking;
     49
     50/**
     51
     52  This code sets variable in storage blocks (Volatile or Non-Volatile).
     53
     54  @param VariableName                     Name of Variable to be found.
     55  @param VendorGuid                       Variable vendor GUID.
     56  @param Attributes                       Attribute value of the variable found
     57  @param DataSize                         Size of Data found. If size is less than the
     58                                          data, this value contains the required size.
     59  @param Data                             Data pointer.
     60
     61  @return EFI_INVALID_PARAMETER           Invalid parameter.
     62  @return EFI_SUCCESS                     Set successfully.
     63  @return EFI_OUT_OF_RESOURCES            Resource not enough to set variable.
     64  @return EFI_NOT_FOUND                   Not found.
     65  @return EFI_WRITE_PROTECTED             Variable is read-only.
     66
     67**/
     68EFI_STATUS
     69EFIAPI
     70SmmVariableSetVariable (
     71  IN CHAR16                  *VariableName,
     72  IN EFI_GUID                *VendorGuid,
     73  IN UINT32                  Attributes,
     74  IN UINTN                   DataSize,
     75  IN VOID                    *Data
     76  )
     77{
     78  EFI_STATUS                 Status;
     79
     80  //
     81  // Disable write protection when the calling SetVariable() through EFI_SMM_VARIABLE_PROTOCOL.
     82  //
     83  mEnableLocking = FALSE;
     84  Status         = VariableServiceSetVariable (
     85                     VariableName,
     86                     VendorGuid,
     87                     Attributes,
     88                     DataSize,
     89                     Data
     90                     );
     91  mEnableLocking = TRUE;
     92  return Status;
     93}
     94
    3295EFI_SMM_VARIABLE_PROTOCOL      gSmmVariable = {
    3396  VariableServiceGetVariable,
    3497  VariableServiceGetNextVariableName,
    35   VariableServiceSetVariable,
     98  SmmVariableSetVariable,
    3699  VariableServiceQueryVariableInfo
    37100};
    38 
    39101
    40102/**
     
    233295  if (EFI_ERROR(Status)) {
    234296    *NumberHandles = 0;
     297    FreePool (*Buffer);
     298    *Buffer = NULL;
    235299  }
    236300
     
    242306  Get the variable statistics information from the information buffer pointed by gVariableInfo.
    243307
    244   @param[in, out]  InfoEntry   A pointer to the buffer of variable information entry.
    245                                On input, point to the variable information returned last time. if
    246                                InfoEntry->VendorGuid is zero, return the first information.
    247                                On output, point to the next variable information.
    248   @param[in, out]  InfoSize    On input, the size of the variable information buffer.
    249                                On output, the returned variable information size.
     308  Caution: This function may be invoked at SMM runtime.
     309  InfoEntry and InfoSize are external input. Care must be taken to make sure not security issue at runtime.
     310
     311  @param[in, out]  InfoEntry    A pointer to the buffer of variable information entry.
     312                                On input, point to the variable information returned last time. if
     313                                InfoEntry->VendorGuid is zero, return the first information.
     314                                On output, point to the next variable information.
     315  @param[in, out]  InfoSize     On input, the size of the variable information buffer.
     316                                On output, the returned variable information size.
    250317
    251318  @retval EFI_SUCCESS          The variable information is found and returned successfully.
     
    265332  UINTN                                                StatisticsInfoSize;
    266333  CHAR16                                               *InfoName;
    267  
     334  EFI_GUID                                             VendorGuid;
     335
    268336  ASSERT (InfoEntry != NULL);
    269337  VariableInfo = gVariableInfo;
     
    273341
    274342  StatisticsInfoSize = sizeof (VARIABLE_INFO_ENTRY) + StrSize (VariableInfo->Name);
    275   if (*InfoSize < sizeof (VARIABLE_INFO_ENTRY)) {
     343  if (*InfoSize < StatisticsInfoSize) {
    276344    *InfoSize = StatisticsInfoSize;
    277345    return EFI_BUFFER_TOO_SMALL;
     
    279347  InfoName = (CHAR16 *)(InfoEntry + 1);
    280348
    281   if (CompareGuid (&InfoEntry->VendorGuid, &mZeroGuid)) {
     349  CopyGuid (&VendorGuid, &InfoEntry->VendorGuid);
     350
     351  if (CompareGuid (&VendorGuid, &mZeroGuid)) {
    282352    //
    283353    // Return the first variable info
     
    293363  //
    294364  while (VariableInfo != NULL) {
    295     if (CompareGuid (&VariableInfo->VendorGuid, &InfoEntry->VendorGuid)) {
     365    if (CompareGuid (&VariableInfo->VendorGuid, &VendorGuid)) {
    296366      NameLength = StrSize (VariableInfo->Name);
    297367      if (NameLength == StrSize (InfoName)) {
     
    335405  This SMI handler provides services for the variable wrapper driver.
    336406
     407  Caution: This function may receive untrusted input.
     408  This variable data and communicate buffer are external input, so this function will do basic validation.
     409  Each sub function VariableServiceGetVariable(), VariableServiceGetNextVariableName(),
     410  VariableServiceSetVariable(), VariableServiceQueryVariableInfo(), ReclaimForOS(),
     411  SmmVariableGetStatistics() should also do validation based on its own knowledge.
     412
    337413  @param[in]     DispatchHandle  The unique handle assigned to this handler by SmiHandlerRegister().
    338414  @param[in]     RegisterContext Points to an optional handler context which was specified when the
     
    365441  SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO     *QueryVariableInfo;
    366442  VARIABLE_INFO_ENTRY                              *VariableInfo;
     443  SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE           *VariableToLock;
    367444  UINTN                                            InfoSize;
    368 
    369   ASSERT (CommBuffer != NULL);
     445  UINTN                                            NameBufferSize;
     446  UINTN                                            CommBufferPayloadSize;
     447  UINTN                                            TempCommBufferSize;
     448
     449  //
     450  // If input is invalid, stop processing this SMI
     451  //
     452  if (CommBuffer == NULL || CommBufferSize == NULL) {
     453    return EFI_SUCCESS;
     454  }
     455
     456  TempCommBufferSize = *CommBufferSize;
     457
     458  if (TempCommBufferSize < SMM_VARIABLE_COMMUNICATE_HEADER_SIZE) {
     459    DEBUG ((EFI_D_ERROR, "SmmVariableHandler: SMM communication buffer size invalid!\n"));
     460    return EFI_SUCCESS;
     461  }
     462  CommBufferPayloadSize = TempCommBufferSize - SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;
     463  if (CommBufferPayloadSize > mVariableBufferPayloadSize) {
     464    DEBUG ((EFI_D_ERROR, "SmmVariableHandler: SMM communication buffer payload size invalid!\n"));
     465    return EFI_SUCCESS;
     466  }
     467
     468  if (!SmmIsBufferOutsideSmmValid ((UINTN)CommBuffer, TempCommBufferSize)) {
     469    DEBUG ((EFI_D_ERROR, "SmmVariableHandler: SMM communication buffer in SMRAM or overflow!\n"));
     470    return EFI_SUCCESS;
     471  }
    370472
    371473  SmmVariableFunctionHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *)CommBuffer;
    372474  switch (SmmVariableFunctionHeader->Function) {
    373475    case SMM_VARIABLE_FUNCTION_GET_VARIABLE:
    374       SmmVariableHeader = (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *) SmmVariableFunctionHeader->Data;     
     476      if (CommBufferPayloadSize < OFFSET_OF(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)) {
     477        DEBUG ((EFI_D_ERROR, "GetVariable: SMM communication buffer size invalid!\n"));
     478        return EFI_SUCCESS;
     479      }
     480      //
     481      // Copy the input communicate buffer payload to pre-allocated SMM variable buffer payload.
     482      //
     483      CopyMem (mVariableBufferPayload, SmmVariableFunctionHeader->Data, CommBufferPayloadSize);
     484      SmmVariableHeader = (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *) mVariableBufferPayload;
     485      if (((UINTN)(~0) - SmmVariableHeader->DataSize < OFFSET_OF(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)) ||
     486         ((UINTN)(~0) - SmmVariableHeader->NameSize < OFFSET_OF(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + SmmVariableHeader->DataSize)) {
     487        //
     488        // Prevent InfoSize overflow happen
     489        //
     490        Status = EFI_ACCESS_DENIED;
     491        goto EXIT;
     492      }
     493      InfoSize = OFFSET_OF(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)
     494                 + SmmVariableHeader->DataSize + SmmVariableHeader->NameSize;
     495
     496      //
     497      // SMRAM range check already covered before
     498      //
     499      if (InfoSize > CommBufferPayloadSize) {
     500        DEBUG ((EFI_D_ERROR, "GetVariable: Data size exceed communication buffer size limit!\n"));
     501        Status = EFI_ACCESS_DENIED;
     502        goto EXIT;
     503      }
     504
     505      if (SmmVariableHeader->NameSize < sizeof (CHAR16) || SmmVariableHeader->Name[SmmVariableHeader->NameSize/sizeof (CHAR16) - 1] != L'\0') {
     506        //
     507        // Make sure VariableName is A Null-terminated string.
     508        //
     509        Status = EFI_ACCESS_DENIED;
     510        goto EXIT;
     511      }
     512
    375513      Status = VariableServiceGetVariable (
    376514                 SmmVariableHeader->Name,
     
    380518                 (UINT8 *)SmmVariableHeader->Name + SmmVariableHeader->NameSize
    381519                 );
     520      CopyMem (SmmVariableFunctionHeader->Data, mVariableBufferPayload, CommBufferPayloadSize);
    382521      break;
    383522     
    384523    case SMM_VARIABLE_FUNCTION_GET_NEXT_VARIABLE_NAME:
    385       GetNextVariableName = (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME *) SmmVariableFunctionHeader->Data;
     524      if (CommBufferPayloadSize < OFFSET_OF(SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name)) {
     525        DEBUG ((EFI_D_ERROR, "GetNextVariableName: SMM communication buffer size invalid!\n"));
     526        return EFI_SUCCESS;
     527      }
     528      //
     529      // Copy the input communicate buffer payload to pre-allocated SMM variable buffer payload.
     530      //
     531      CopyMem (mVariableBufferPayload, SmmVariableFunctionHeader->Data, CommBufferPayloadSize);
     532      GetNextVariableName = (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME *) mVariableBufferPayload;
     533      if ((UINTN)(~0) - GetNextVariableName->NameSize < OFFSET_OF(SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name)) {
     534        //
     535        // Prevent InfoSize overflow happen
     536        //
     537        Status = EFI_ACCESS_DENIED;
     538        goto EXIT;
     539      }
     540      InfoSize = OFFSET_OF(SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name) + GetNextVariableName->NameSize;
     541
     542      //
     543      // SMRAM range check already covered before
     544      //
     545      if (InfoSize > CommBufferPayloadSize) {
     546        DEBUG ((EFI_D_ERROR, "GetNextVariableName: Data size exceed communication buffer size limit!\n"));
     547        Status = EFI_ACCESS_DENIED;
     548        goto EXIT;
     549      }
     550
     551      NameBufferSize = CommBufferPayloadSize - OFFSET_OF(SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name);
     552      if (NameBufferSize < sizeof (CHAR16) || GetNextVariableName->Name[NameBufferSize/sizeof (CHAR16) - 1] != L'\0') {
     553        //
     554        // Make sure input VariableName is A Null-terminated string.
     555        //
     556        Status = EFI_ACCESS_DENIED;
     557        goto EXIT;
     558      }
     559
    386560      Status = VariableServiceGetNextVariableName (
    387561                 &GetNextVariableName->NameSize,
     
    389563                 &GetNextVariableName->Guid
    390564                 );
     565      CopyMem (SmmVariableFunctionHeader->Data, mVariableBufferPayload, CommBufferPayloadSize);
    391566      break;
    392567     
    393568    case SMM_VARIABLE_FUNCTION_SET_VARIABLE:
    394       SmmVariableHeader = (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *) SmmVariableFunctionHeader->Data;
     569      if (CommBufferPayloadSize < OFFSET_OF(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)) {
     570        DEBUG ((EFI_D_ERROR, "SetVariable: SMM communication buffer size invalid!\n"));
     571        return EFI_SUCCESS;
     572      }
     573      //
     574      // Copy the input communicate buffer payload to pre-allocated SMM variable buffer payload.
     575      //
     576      CopyMem (mVariableBufferPayload, SmmVariableFunctionHeader->Data, CommBufferPayloadSize);
     577      SmmVariableHeader = (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *) mVariableBufferPayload;
     578      if (((UINTN)(~0) - SmmVariableHeader->DataSize < OFFSET_OF(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)) ||
     579         ((UINTN)(~0) - SmmVariableHeader->NameSize < OFFSET_OF(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + SmmVariableHeader->DataSize)) {
     580        //
     581        // Prevent InfoSize overflow happen
     582        //
     583        Status = EFI_ACCESS_DENIED;
     584        goto EXIT;
     585      }
     586      InfoSize = OFFSET_OF(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)
     587                 + SmmVariableHeader->DataSize + SmmVariableHeader->NameSize;
     588
     589      //
     590      // SMRAM range check already covered before
     591      // Data buffer should not contain SMM range
     592      //
     593      if (InfoSize > CommBufferPayloadSize) {
     594        DEBUG ((EFI_D_ERROR, "SetVariable: Data size exceed communication buffer size limit!\n"));
     595        Status = EFI_ACCESS_DENIED;
     596        goto EXIT;
     597      }
     598
     599      if (SmmVariableHeader->NameSize < sizeof (CHAR16) || SmmVariableHeader->Name[SmmVariableHeader->NameSize/sizeof (CHAR16) - 1] != L'\0') {
     600        //
     601        // Make sure VariableName is A Null-terminated string.
     602        //
     603        Status = EFI_ACCESS_DENIED;
     604        goto EXIT;
     605      }
     606
    395607      Status = VariableServiceSetVariable (
    396608                 SmmVariableHeader->Name,
     
    403615     
    404616    case SMM_VARIABLE_FUNCTION_QUERY_VARIABLE_INFO:
     617      if (CommBufferPayloadSize < sizeof (SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO)) {
     618        DEBUG ((EFI_D_ERROR, "QueryVariableInfo: SMM communication buffer size invalid!\n"));
     619        return EFI_SUCCESS;
     620      }
    405621      QueryVariableInfo = (SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO *) SmmVariableFunctionHeader->Data;
     622
    406623      Status = VariableServiceQueryVariableInfo (
    407624                 QueryVariableInfo->Attributes,
     
    413630
    414631    case SMM_VARIABLE_FUNCTION_READY_TO_BOOT:
     632      mEndOfDxe = TRUE;
     633      if (AtRuntime()) {
     634        Status = EFI_UNSUPPORTED;
     635        break;
     636      }
    415637      ReclaimForOS ();
    416638      Status = EFI_SUCCESS;
     
    424646    case SMM_VARIABLE_FUNCTION_GET_STATISTICS:
    425647      VariableInfo = (VARIABLE_INFO_ENTRY *) SmmVariableFunctionHeader->Data;
    426       InfoSize = *CommBufferSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_HEADER, Data);
     648      InfoSize = TempCommBufferSize - SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;
     649
     650      //
     651      // Do not need to check SmmVariableFunctionHeader->Data in SMRAM here.
     652      // It is covered by previous CommBuffer check
     653      //
     654     
     655      if (!SmmIsBufferOutsideSmmValid ((EFI_PHYSICAL_ADDRESS)(UINTN)CommBufferSize, sizeof(UINTN))) {
     656        DEBUG ((EFI_D_ERROR, "GetStatistics: SMM communication buffer in SMRAM!\n"));
     657        Status = EFI_ACCESS_DENIED;
     658        goto EXIT;
     659      } 
     660
    427661      Status = SmmVariableGetStatistics (VariableInfo, &InfoSize);
    428       *CommBufferSize = InfoSize + OFFSET_OF (SMM_VARIABLE_COMMUNICATE_HEADER, Data);
     662      *CommBufferSize = InfoSize + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;
    429663      break;
    430664
     665    case SMM_VARIABLE_FUNCTION_LOCK_VARIABLE:
     666      if (mEndOfDxe) {
     667        Status = EFI_ACCESS_DENIED;
     668      } else {
     669        VariableToLock = (SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE *) SmmVariableFunctionHeader->Data;
     670        Status = VariableLockRequestToLock (
     671                   NULL,
     672                   VariableToLock->Name,
     673                   &VariableToLock->Guid
     674                   );
     675      }
     676      break;
     677
    431678    default:
    432       ASSERT (FALSE);
    433679      Status = EFI_UNSUPPORTED;
    434680  }
    435681
     682EXIT:
     683
    436684  SmmVariableFunctionHeader->ReturnStatus = Status;
    437685
     
    439687}
    440688
     689/**
     690  SMM END_OF_DXE protocol notification event handler.
     691
     692  @param  Protocol   Points to the protocol's unique identifier
     693  @param  Interface  Points to the interface instance
     694  @param  Handle     The handle on which the interface was installed
     695
     696  @retval EFI_SUCCESS   SmmEndOfDxeCallback runs successfully
     697
     698**/
     699EFI_STATUS
     700EFIAPI
     701SmmEndOfDxeCallback (
     702  IN CONST EFI_GUID                       *Protocol,
     703  IN VOID                                 *Interface,
     704  IN EFI_HANDLE                           Handle
     705  )
     706{
     707  DEBUG ((EFI_D_INFO, "[Variable]END_OF_DXE is signaled\n"));
     708  mEndOfDxe = TRUE;
     709  if (PcdGetBool (PcdReclaimVariableSpaceAtEndOfDxe)) {
     710    ReclaimForOS ();
     711  }
     712  return EFI_SUCCESS;
     713}
    441714
    442715/**
     
    466739  EFI_SMM_FAULT_TOLERANT_WRITE_PROTOCOL   *FtwProtocol;
    467740  EFI_PHYSICAL_ADDRESS                    NvStorageVariableBase;
     741  UINTN                                   FtwMaxBlockSize;
    468742 
    469743  if (mVariableModuleGlobal->FvbInstance != NULL) {
     
    477751  if (EFI_ERROR (Status)) {
    478752    return Status;
     753  }
     754
     755  Status = FtwProtocol->GetMaxBlockSize (FtwProtocol, &FtwMaxBlockSize);
     756  if (!EFI_ERROR (Status)) {
     757    ASSERT (PcdGet32 (PcdFlashNvStorageVariableSize) <= FtwMaxBlockSize);
    479758  }
    480759
     
    533812  EFI_HANDLE                              VariableHandle;
    534813  VOID                                    *SmmFtwRegistration;
    535  
     814  VOID                                    *SmmEndOfDxeRegistration;
     815
    536816  //
    537817  // Variable initialize.
     
    552832  ASSERT_EFI_ERROR (Status);
    553833
     834  mVariableBufferPayloadSize = MAX (PcdGet32 (PcdMaxVariableSize), PcdGet32 (PcdMaxHardwareErrorVariableSize)) +
     835                               OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) - sizeof (VARIABLE_HEADER);
     836
     837  Status = gSmst->SmmAllocatePool (
     838                    EfiRuntimeServicesData,
     839                    mVariableBufferPayloadSize,
     840                    (VOID **)&mVariableBufferPayload
     841                    );
     842  ASSERT_EFI_ERROR (Status);
     843
    554844  ///
    555845  /// Register SMM variable SMI handler
     
    571861 
    572862  //
     863  // Register EFI_SMM_END_OF_DXE_PROTOCOL_GUID notify function.
     864  //
     865  Status = gSmst->SmmRegisterProtocolNotify (
     866                    &gEfiSmmEndOfDxeProtocolGuid,
     867                    SmmEndOfDxeCallback,
     868                    &SmmEndOfDxeRegistration
     869                    );
     870  ASSERT_EFI_ERROR (Status);
     871
     872  //
    573873  // Register FtwNotificationEvent () notify function.
    574874  //
  • trunk/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf

    r48674 r58459  
    11## @file
    2 #  Component description file for SMM Variable module.
    3 #
    42#  This module installs SMM variable protocol into SMM protocol database,
    53#  which can be used by SMM driver, and installs SMM variable protocol
     
    97#  SMM Runtime DXE module would install variable arch protocol and variable
    108#  write arch protocol based on SMM variable module.
    11 # Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>
    129#
    13 #  This program and the accompanying materials
    14 #  are licensed and made available under the terms and conditions of the BSD License
    15 #  which accompanies this distribution. The full text of the license may be found at
    16 #  http://opensource.org/licenses/bsd-license.php
    17 #  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
    18 #  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     10#  Caution: This module requires additional review when modified.
     11#  This driver will have external input - variable data and communicate buffer in SMM mode.
     12#  This external input must be validated carefully to avoid security issue like
     13#  buffer overflow, integer overflow.
     14#
     15# Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR>
     16# This program and the accompanying materials
     17# are licensed and made available under the terms and conditions of the BSD License
     18# which accompanies this distribution. The full text of the license may be found at
     19# http://opensource.org/licenses/bsd-license.php
     20# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     21# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
    1922#
    2023#
     
    2427  INF_VERSION                    = 0x00010005
    2528  BASE_NAME                      = VariableSmm
     29  MODULE_UNI_FILE                = VariableSmm.uni
    2630  FILE_GUID                      = 23A089B3-EED5-4ac5-B2AB-43E3298C2343
    2731  MODULE_TYPE                    = DXE_SMM_DRIVER
     
    5862  DxeServicesTableLib
    5963  HobLib
     64  PcdLib
     65  SmmMemLib
    6066
    6167[Protocols]
    62   gEfiSmmFirmwareVolumeBlockProtocolGuid        ## SOMETIMES_CONSUMES
    63   gEfiSmmVariableProtocolGuid                   ## ALWAYS_PRODUCES
    64   gEfiSmmFaultTolerantWriteProtocolGuid         ## SOMETIMES_CONSUMES
     68  gEfiSmmFirmwareVolumeBlockProtocolGuid        ## CONSUMES
     69  ## CONSUMES
     70  ## NOTIFY
     71  gEfiSmmFaultTolerantWriteProtocolGuid
     72  ## PRODUCES
     73  ## UNDEFINED # SmiHandlerRegister
     74  gEfiSmmVariableProtocolGuid
     75  gEfiSmmEndOfDxeProtocolGuid                   ## CONSUMES
    6576
    6677[Guids]
    67   gEfiVariableGuid                              ## PRODUCES ## Configuration Table Guid
    68   gEfiGlobalVariableGuid                        ## PRODUCES ## Variable Guid
    69   gSmmVariableWriteGuid                         ## PRODUCES ## SMM Variable Write Guid
    70   gEfiSystemNvDataFvGuid                        ## CONSUMES
     78  ## PRODUCES             ## GUID # Signature of Variable store header
     79  ## CONSUMES             ## GUID # Signature of Variable store header
     80  ## SOMETIMES_CONSUMES   ## HOB
     81  gEfiVariableGuid
     82  ## SOMETIMES_CONSUMES   ## Variable:L"PlatformLang"
     83  ## SOMETIMES_PRODUCES   ## Variable:L"PlatformLang"
     84  ## SOMETIMES_CONSUMES   ## Variable:L"Lang"
     85  ## SOMETIMES_PRODUCES   ## Variable:L"Lang"
     86  ## SOMETIMES_CONSUMES   ## Variable:L"HwErrRecSupport"
     87  gEfiGlobalVariableGuid
     88  gSmmVariableWriteGuid                         ## PRODUCES             ## UNDEFINED # Install protocol
     89  gEfiSystemNvDataFvGuid                        ## CONSUMES             ## GUID
     90  gEfiHardwareErrorVariableGuid                 ## SOMETIMES_CONSUMES   ## Variable:L"HwErrRec####"
     91  ## SOMETIMES_CONSUMES   ## HOB
     92  gEdkiiFaultTolerantWriteGuid
    7193
    7294[Pcd]
    73   gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize
    74   gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase
    75   gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64
    76   gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize
    77   gEfiMdeModulePkgTokenSpaceGuid.PcdMaxHardwareErrorVariableSize
    78   gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize
    79   gEfiMdeModulePkgTokenSpaceGuid.PcdHwErrStorageSize
    80  
     95  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize      ## CONSUMES
     96  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase      ## SOMETIMES_CONSUMES
     97  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64    ## CONSUMES
     98  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize                 ## CONSUMES
     99  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxHardwareErrorVariableSize    ## CONSUMES
     100  gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize               ## CONSUMES
     101  gEfiMdeModulePkgTokenSpaceGuid.PcdHwErrStorageSize                ## CONSUMES
     102  gEfiMdeModulePkgTokenSpaceGuid.PcdReclaimVariableSpaceAtEndOfDxe  ## CONSUMES
     103
    81104[FeaturePcd]
    82   gEfiMdeModulePkgTokenSpaceGuid.PcdVariableCollectStatistics  ## SOMETIME_CONSUMES (statistic the information of variable.)
     105  gEfiMdeModulePkgTokenSpaceGuid.PcdVariableCollectStatistics   ## CONSUMES # statistic the information of variable.
     106  gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultLangDeprecate  ## CONSUMES
    83107
    84108[Depex]
    85109  TRUE
    86110
    87    
     111[UserExtensions.TianoCore."ExtraFiles"]
     112  VariableSmmExtra.uni
  • trunk/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c

    r48674 r58459  
    55  based on SMM variable module.
    66
    7 Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>
     7  Caution: This module requires additional review when modified.
     8  This driver will have external input - variable data.
     9  This external input must be validated carefully to avoid security issue like
     10  buffer overflow, integer overflow.
     11
     12  RuntimeServiceGetVariable() and RuntimeServiceSetVariable() are external API
     13  to receive data buffer. The size should be checked carefully.
     14
     15  InitCommunicateBuffer() is really function to check the variable data size.
     16
     17Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR>
    818This program and the accompanying materials                         
    919are licensed and made available under the terms and conditions of the BSD License         
     
    2030#include <Protocol/SmmCommunication.h>
    2131#include <Protocol/SmmVariable.h>
     32#include <Protocol/VariableLock.h>
    2233
    2334#include <Library/UefiBootServicesTableLib.h>
     
    4354UINT8                           *mVariableBufferPhysical    = NULL;
    4455UINTN                            mVariableBufferSize;
    45 
     56UINTN                            mVariableBufferPayloadSize;
     57EFI_LOCK                         mVariableServicesLock;
     58EDKII_VARIABLE_LOCK_PROTOCOL     mVariableLock;
     59
     60/**
     61  Acquires lock only at boot time. Simply returns at runtime.
     62
     63  This is a temperary function that will be removed when
     64  EfiAcquireLock() in UefiLib can handle the call in UEFI
     65  Runtimer driver in RT phase.
     66  It calls EfiAcquireLock() at boot time, and simply returns
     67  at runtime.
     68
     69  @param  Lock         A pointer to the lock to acquire.
     70
     71**/
     72VOID
     73AcquireLockOnlyAtBootTime (
     74  IN EFI_LOCK                             *Lock
     75  )
     76{
     77  if (!EfiAtRuntime ()) {
     78    EfiAcquireLock (Lock);
     79  }
     80}
     81
     82/**
     83  Releases lock only at boot time. Simply returns at runtime.
     84
     85  This is a temperary function which will be removed when
     86  EfiReleaseLock() in UefiLib can handle the call in UEFI
     87  Runtimer driver in RT phase.
     88  It calls EfiReleaseLock() at boot time and simply returns
     89  at runtime.
     90
     91  @param  Lock         A pointer to the lock to release.
     92
     93**/
     94VOID
     95ReleaseLockOnlyAtBootTime (
     96  IN EFI_LOCK                             *Lock
     97  )
     98{
     99  if (!EfiAtRuntime ()) {
     100    EfiReleaseLock (Lock);
     101  }
     102}
    46103
    47104/**
     
    50107  The communicate size is: SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE +
    51108  DataSize.
     109
     110  Caution: This function may receive untrusted input.
     111  The data size external input, so this function will validate it carefully to avoid buffer overflow.
    52112
    53113  @param[out]      DataPtr          Points to the data in the communicate buffer.
     
    116176}
    117177
     178/**
     179  Mark a variable that will become read-only after leaving the DXE phase of execution.
     180
     181  @param[in] This          The VARIABLE_LOCK_PROTOCOL instance.
     182  @param[in] VariableName  A pointer to the variable name that will be made read-only subsequently.
     183  @param[in] VendorGuid    A pointer to the vendor GUID that will be made read-only subsequently.
     184
     185  @retval EFI_SUCCESS           The variable specified by the VariableName and the VendorGuid was marked
     186                                as pending to be read-only.
     187  @retval EFI_INVALID_PARAMETER VariableName or VendorGuid is NULL.
     188                                Or VariableName is an empty string.
     189  @retval EFI_ACCESS_DENIED     EFI_END_OF_DXE_EVENT_GROUP_GUID or EFI_EVENT_GROUP_READY_TO_BOOT has
     190                                already been signaled.
     191  @retval EFI_OUT_OF_RESOURCES  There is not enough resource to hold the lock request.
     192**/
     193EFI_STATUS
     194EFIAPI
     195VariableLockRequestToLock (
     196  IN CONST EDKII_VARIABLE_LOCK_PROTOCOL *This,
     197  IN       CHAR16                       *VariableName,
     198  IN       EFI_GUID                     *VendorGuid
     199  )
     200{
     201  EFI_STATUS                                Status;
     202  UINTN                                     VariableNameSize;
     203  UINTN                                     PayloadSize;
     204  SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE    *VariableToLock;
     205
     206  if (VariableName == NULL || VariableName[0] == 0 || VendorGuid == NULL) {
     207    return EFI_INVALID_PARAMETER;
     208  }
     209
     210  VariableNameSize = StrSize (VariableName);
     211  VariableToLock   = NULL;
     212
     213  //
     214  // If VariableName exceeds SMM payload limit. Return failure
     215  //
     216  if (VariableNameSize > mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE, Name)) {
     217    return EFI_INVALID_PARAMETER;
     218  }
     219
     220  AcquireLockOnlyAtBootTime(&mVariableServicesLock);
     221
     222  //
     223  // Init the communicate buffer. The buffer data size is:
     224  // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.
     225  //
     226  PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE, Name) + VariableNameSize;
     227  Status = InitCommunicateBuffer ((VOID **) &VariableToLock, PayloadSize, SMM_VARIABLE_FUNCTION_LOCK_VARIABLE);
     228  if (EFI_ERROR (Status)) {
     229    goto Done;
     230  }
     231  ASSERT (VariableToLock != NULL);
     232
     233  CopyGuid (&VariableToLock->Guid, VendorGuid);
     234  VariableToLock->NameSize = VariableNameSize;
     235  CopyMem (VariableToLock->Name, VariableName, VariableToLock->NameSize);
     236
     237  //
     238  // Send data to SMM.
     239  //
     240  Status = SendCommunicateBuffer (PayloadSize);
     241
     242Done:
     243  ReleaseLockOnlyAtBootTime (&mVariableServicesLock);
     244  return Status;
     245}
    118246
    119247/**
    120248  This code finds variable in storage blocks (Volatile or Non-Volatile).
     249
     250  Caution: This function may receive untrusted input.
     251  The data size is external input, so this function will validate it carefully to avoid buffer overflow.
    121252
    122253  @param[in]      VariableName       Name of Variable to be found.
     
    146277  UINTN                                     PayloadSize;
    147278  SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE  *SmmVariableHeader;
     279  UINTN                                     TempDataSize;
     280  UINTN                                     VariableNameSize;
    148281
    149282  if (VariableName == NULL || VendorGuid == NULL || DataSize == NULL) {
     
    154287    return EFI_INVALID_PARAMETER;
    155288  }
    156  
     289
     290  TempDataSize          = *DataSize;
     291  VariableNameSize      = StrSize (VariableName);
     292  SmmVariableHeader     = NULL;
     293
     294  //
     295  // If VariableName exceeds SMM payload limit. Return failure
     296  //
     297  if (VariableNameSize > mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)) {
     298    return EFI_INVALID_PARAMETER;
     299  }
     300
     301  AcquireLockOnlyAtBootTime(&mVariableServicesLock);
     302
    157303  //
    158304  // Init the communicate buffer. The buffer data size is:
    159305  // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.
    160306  //
    161   PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + StrSize (VariableName);
     307  if (TempDataSize > mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) - VariableNameSize) {
     308    //
     309    // If output data buffer exceed SMM payload limit. Trim output buffer to SMM payload size
     310    //
     311    TempDataSize = mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) - VariableNameSize;
     312  }
     313  PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + VariableNameSize + TempDataSize;
     314
    162315  Status = InitCommunicateBuffer ((VOID **)&SmmVariableHeader, PayloadSize, SMM_VARIABLE_FUNCTION_GET_VARIABLE);
    163316  if (EFI_ERROR (Status)) {
    164     return Status;
     317    goto Done;
    165318  }
    166319  ASSERT (SmmVariableHeader != NULL);
    167320
    168321  CopyGuid (&SmmVariableHeader->Guid, VendorGuid);
    169   SmmVariableHeader->DataSize   = *DataSize;
    170   SmmVariableHeader->NameSize   = StrSize (VariableName);
     322  SmmVariableHeader->DataSize   = TempDataSize;
     323  SmmVariableHeader->NameSize   = VariableNameSize;
    171324  if (Attributes == NULL) {
    172325    SmmVariableHeader->Attributes = 0;
     
    184337  // Get data from SMM.
    185338  //
    186   *DataSize = SmmVariableHeader->DataSize;
     339  if (Status == EFI_SUCCESS || Status == EFI_BUFFER_TOO_SMALL) {
     340    //
     341    // SMM CommBuffer DataSize can be a trimed value
     342    // Only update DataSize when needed
     343    //
     344    *DataSize = SmmVariableHeader->DataSize;
     345  }
    187346  if (Attributes != NULL) {
    188347    *Attributes = SmmVariableHeader->Attributes;
     
    190349
    191350  if (EFI_ERROR (Status)) {
    192     return Status;
     351    goto Done;
    193352  }
    194353
    195354  CopyMem (Data, (UINT8 *)SmmVariableHeader->Name + SmmVariableHeader->NameSize, SmmVariableHeader->DataSize);
    196355
     356Done:
     357  ReleaseLockOnlyAtBootTime (&mVariableServicesLock);
    197358  return Status;
    198359}
     
    223384  UINTN                                           PayloadSize;
    224385  SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME *SmmGetNextVariableName;
     386  UINTN                                           OutVariableNameSize;
     387  UINTN                                           InVariableNameSize;
    225388
    226389  if (VariableNameSize == NULL || VariableName == NULL || VendorGuid == NULL) {
    227390    return EFI_INVALID_PARAMETER;
    228391  }
    229  
     392
     393  OutVariableNameSize   = *VariableNameSize;
     394  InVariableNameSize    = StrSize (VariableName);
     395  SmmGetNextVariableName = NULL;
     396
     397  //
     398  // If input string exceeds SMM payload limit. Return failure
     399  //
     400  if (InVariableNameSize > mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name)) {
     401    return EFI_INVALID_PARAMETER;
     402  }
     403
     404  AcquireLockOnlyAtBootTime(&mVariableServicesLock);
     405
    230406  //
    231407  // Init the communicate buffer. The buffer data size is:
    232408  // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.
    233409  //
    234   PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name) + *VariableNameSize;
     410  if (OutVariableNameSize > mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name)) {
     411    //
     412    // If output buffer exceed SMM payload limit. Trim output buffer to SMM payload size
     413    //
     414    OutVariableNameSize = mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name);
     415  }
     416  //
     417  // Payload should be Guid + NameSize + MAX of Input & Output buffer
     418  //
     419  PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name) + MAX (OutVariableNameSize, InVariableNameSize);
     420
     421
    235422  Status = InitCommunicateBuffer ((VOID **)&SmmGetNextVariableName, PayloadSize, SMM_VARIABLE_FUNCTION_GET_NEXT_VARIABLE_NAME);
    236423  if (EFI_ERROR (Status)) {
    237     return Status;
     424    goto Done;
    238425  }
    239426  ASSERT (SmmGetNextVariableName != NULL);
    240427
    241   SmmGetNextVariableName->NameSize = *VariableNameSize;
     428  //
     429  // SMM comm buffer->NameSize is buffer size for return string
     430  //
     431  SmmGetNextVariableName->NameSize = OutVariableNameSize;
     432
    242433  CopyGuid (&SmmGetNextVariableName->Guid, VendorGuid);
    243   CopyMem (SmmGetNextVariableName->Name, VariableName, *VariableNameSize);
     434  //
     435  // Copy whole string
     436  //
     437  CopyMem (SmmGetNextVariableName->Name, VariableName, InVariableNameSize);
     438  if (OutVariableNameSize > InVariableNameSize) {
     439    ZeroMem ((UINT8 *) SmmGetNextVariableName->Name + InVariableNameSize, OutVariableNameSize - InVariableNameSize);
     440  }
    244441
    245442  //
     
    251448  // Get data from SMM.
    252449  //
    253   *VariableNameSize = SmmGetNextVariableName->NameSize;   
    254   if (EFI_ERROR (Status)) {
    255     return Status;
     450  if (Status == EFI_SUCCESS || Status == EFI_BUFFER_TOO_SMALL) {
     451    //
     452    // SMM CommBuffer NameSize can be a trimed value
     453    // Only update VariableNameSize when needed
     454    //
     455    *VariableNameSize = SmmGetNextVariableName->NameSize;
     456  }
     457  if (EFI_ERROR (Status)) {
     458    goto Done;
    256459  }
    257460 
     
    259462  CopyMem (VariableName, SmmGetNextVariableName->Name, SmmGetNextVariableName->NameSize); 
    260463
     464Done:
     465  ReleaseLockOnlyAtBootTime (&mVariableServicesLock);
    261466  return Status;
    262467}
     
    264469/**
    265470  This code sets variable in storage blocks (Volatile or Non-Volatile).
     471
     472  Caution: This function may receive untrusted input.
     473  The data size and data are external input, so this function will validate it carefully to avoid buffer overflow.
    266474
    267475  @param[in] VariableName                 Name of Variable to be found.
     
    292500  UINTN                                     PayloadSize;
    293501  SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE  *SmmVariableHeader;
     502  UINTN                                     VariableNameSize;
    294503   
    295504  //
     
    303512    return EFI_INVALID_PARAMETER;
    304513  }
    305  
     514
     515  VariableNameSize      = StrSize (VariableName);
     516  SmmVariableHeader     = NULL;
     517
     518  //
     519  // If VariableName or DataSize exceeds SMM payload limit. Return failure
     520  //
     521  if ((VariableNameSize > mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)) ||
     522      (DataSize > mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) - VariableNameSize)){
     523    return EFI_INVALID_PARAMETER;
     524  }
     525
     526  AcquireLockOnlyAtBootTime(&mVariableServicesLock);
     527 
    306528  //
    307529  // Init the communicate buffer. The buffer data size is:
    308530  // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.
    309531  //
    310   PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + StrSize (VariableName) + DataSize;
     532  PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + VariableNameSize + DataSize;
    311533  Status = InitCommunicateBuffer ((VOID **)&SmmVariableHeader, PayloadSize, SMM_VARIABLE_FUNCTION_SET_VARIABLE);
    312534  if (EFI_ERROR (Status)) {
    313     return Status;
     535    goto Done;
    314536  }
    315537  ASSERT (SmmVariableHeader != NULL);
     
    317539  CopyGuid ((EFI_GUID *) &SmmVariableHeader->Guid, VendorGuid);
    318540  SmmVariableHeader->DataSize   = DataSize;
    319   SmmVariableHeader->NameSize   = StrSize (VariableName);
     541  SmmVariableHeader->NameSize   = VariableNameSize;
    320542  SmmVariableHeader->Attributes = Attributes;
    321543  CopyMem (SmmVariableHeader->Name, VariableName, SmmVariableHeader->NameSize);
     
    326548  //
    327549  Status = SendCommunicateBuffer (PayloadSize);
    328  
     550
     551Done:
     552  ReleaseLockOnlyAtBootTime (&mVariableServicesLock);
    329553  return Status;
    330554}
     
    361585  SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO *SmmQueryVariableInfo;
    362586
     587  SmmQueryVariableInfo = NULL;
     588
    363589  if(MaximumVariableStorageSize == NULL || RemainingVariableStorageSize == NULL || MaximumVariableSize == NULL || Attributes == 0) {
    364590    return EFI_INVALID_PARAMETER;
    365591  }
    366  
     592
     593  AcquireLockOnlyAtBootTime(&mVariableServicesLock);
     594
    367595  //
    368596  // Init the communicate buffer. The buffer data size is:
     
    372600  Status = InitCommunicateBuffer ((VOID **)&SmmQueryVariableInfo, PayloadSize, SMM_VARIABLE_FUNCTION_QUERY_VARIABLE_INFO);
    373601  if (EFI_ERROR (Status)) {
    374     return Status;
     602    goto Done;
    375603  }
    376604  ASSERT (SmmQueryVariableInfo != NULL);
     
    383611  Status = SendCommunicateBuffer (PayloadSize);
    384612  if (EFI_ERROR (Status)) {
    385     return Status;
     613    goto Done;
    386614  }
    387615
     
    392620  *MaximumVariableStorageSize   = SmmQueryVariableInfo->MaximumVariableStorageSize;
    393621  *RemainingVariableStorageSize = SmmQueryVariableInfo->RemainingVariableStorageSize;
    394  
    395   return EFI_SUCCESS;
     622
     623Done:
     624  ReleaseLockOnlyAtBootTime (&mVariableServicesLock);
     625  return Status;
    396626}
    397627
     
    502732 
    503733  //
    504   // Allocate memory for variable store.
    505   //
    506   mVariableBufferSize  = SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;
    507   mVariableBufferSize += MAX (PcdGet32 (PcdMaxVariableSize), PcdGet32 (PcdMaxHardwareErrorVariableSize));
     734  // Allocate memory for variable communicate buffer.
     735  //
     736  mVariableBufferPayloadSize = MAX (PcdGet32 (PcdMaxVariableSize), PcdGet32 (PcdMaxHardwareErrorVariableSize)) +
     737                               OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) - sizeof (VARIABLE_HEADER);
     738  mVariableBufferSize  = SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + mVariableBufferPayloadSize;
    508739  mVariableBuffer      = AllocateRuntimePool (mVariableBufferSize);
    509740  ASSERT (mVariableBuffer != NULL);
     
    586817  )
    587818{
     819  EFI_STATUS                                Status;
    588820  VOID                                      *SmmVariableRegistration;
    589821  VOID                                      *SmmVariableWriteRegistration;
    590822  EFI_EVENT                                 OnReadyToBootEvent;
    591823  EFI_EVENT                                 ExitBootServiceEvent;
    592  
     824
     825  EfiInitializeLock (&mVariableServicesLock, TPL_NOTIFY);
     826
     827  mVariableLock.RequestToLock = VariableLockRequestToLock;
     828  Status = gBS->InstallMultipleProtocolInterfaces (
     829                  &mHandle,
     830                  &gEdkiiVariableLockProtocolGuid,
     831                  &mVariableLock,
     832                  NULL
     833                  );
     834  ASSERT_EFI_ERROR (Status);
     835
    593836  //
    594837  // Smm variable service is ready
  • trunk/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf

    r48674 r58459  
    11## @file
    2 Component description file for Variable SmmRuntimeDxe module.
     2This module is the Runtime DXE part correspond to SMM variable module.
    33#
    4 #  This module is the Runtime DXE part correspond to SMM variable module. It
    5 #  installs variable arch protocol and variable write arch protocol and works
    6 #  with SMM variable module together.
    7 # Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>
     4#  It installs variable arch protocol and variable write arch protocol to provide
     5#  four EFI_RUNTIME_SERVICES: SetVariable, GetVariable, GetNextVariableName and QueryVariableInfo
     6#  and works with SMM variable module together.
     7#
     8#  Caution: This module requires additional review when modified.
     9#  This driver will have external input - variable data.
     10#  This external input must be validated carefully to avoid security issues such as
     11#  buffer overflow or integer overflow.
     12#
     13# Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR>
    814#
    915#  This program and the accompanying materials
     
    2026  INF_VERSION                    = 0x00010005
    2127  BASE_NAME                      = VariableSmmRuntimeDxe
     28  MODULE_UNI_FILE                = VariableSmmRuntimeDxe.uni
    2229  FILE_GUID                      = 9F7DCADE-11EA-448a-A46F-76E003657DD1
    2330  MODULE_TYPE                    = DXE_RUNTIME_DRIVER
     
    5158
    5259[Protocols]
    53   gEfiVariableWriteArchProtocolGuid             ## ALWAYS_PRODUCES
    54   gEfiVariableArchProtocolGuid                  ## ALWAYS_PRODUCES 
    55   gEfiSmmCommunicationProtocolGuid
     60  gEfiVariableWriteArchProtocolGuid             ## PRODUCES
     61  gEfiVariableArchProtocolGuid                  ## PRODUCES
     62  gEfiSmmCommunicationProtocolGuid              ## CONSUMES
     63  ## CONSUMES
     64  ## NOTIFY
     65  ## UNDEFINED # Used to do smm communication
    5666  gEfiSmmVariableProtocolGuid
     67  gEdkiiVariableLockProtocolGuid                ## PRODUCES
    5768
    5869[Guids]
    59   gEfiEventVirtualAddressChangeGuid             ## PRODUCES ## Event
     70  gEfiEventVirtualAddressChangeGuid             ## CONSUMES ## Event
     71  gEfiEventExitBootServicesGuid                 ## CONSUMES ## Event
     72  ## CONSUMES ## GUID # Locate protocol
     73  ## CONSUMES ## GUID # Protocol notify
    6074  gSmmVariableWriteGuid
    6175
    6276[Pcd]
    63   gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize
    64   gEfiMdeModulePkgTokenSpaceGuid.PcdMaxHardwareErrorVariableSize
    65   gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase
     77  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize                 ## CONSUMES
     78  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxHardwareErrorVariableSize    ## CONSUMES
    6679 
    6780[Depex]
    6881  gEfiSmmCommunicationProtocolGuid
     82
     83[UserExtensions.TianoCore."ExtraFiles"]
     84  VariableSmmRuntimeDxeExtra.uni
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