Home | History | Annotate | Download | only in Pei
      1 /** @file
      2   Implement ReadOnly Variable Services required by PEIM and install
      3   PEI ReadOnly Varaiable2 PPI. These services operates the non volatile storage space.
      4 
      5 Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
      6 This program and the accompanying materials
      7 are licensed and made available under the terms and conditions of the BSD License
      8 which accompanies this distribution.  The full text of the license may be found at
      9 http://opensource.org/licenses/bsd-license.php
     10 
     11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     13 
     14 **/
     15 
     16 
     17 #include "Variable.h"
     18 
     19 //
     20 // Module globals
     21 //
     22 EFI_PEI_READ_ONLY_VARIABLE2_PPI mVariablePpi = {
     23   PeiGetVariable,
     24   PeiGetNextVariableName
     25 };
     26 
     27 EFI_PEI_PPI_DESCRIPTOR     mPpiListVariable = {
     28   (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
     29   &gEfiPeiReadOnlyVariable2PpiGuid,
     30   &mVariablePpi
     31 };
     32 
     33 
     34 /**
     35   Provide the functionality of the variable services.
     36 
     37   @param  FileHandle   Handle of the file being invoked.
     38                        Type EFI_PEI_FILE_HANDLE is defined in FfsFindNextFile().
     39   @param  PeiServices  General purpose services available to every PEIM.
     40 
     41   @retval EFI_SUCCESS  If the interface could be successfully installed
     42   @retval Others       Returned from PeiServicesInstallPpi()
     43 **/
     44 EFI_STATUS
     45 EFIAPI
     46 PeimInitializeVariableServices (
     47   IN       EFI_PEI_FILE_HANDLE       FileHandle,
     48   IN CONST EFI_PEI_SERVICES          **PeiServices
     49   )
     50 {
     51   return PeiServicesInstallPpi (&mPpiListVariable);
     52 }
     53 
     54 /**
     55 
     56   Gets the pointer to the first variable header in given variable store area.
     57 
     58   @param VarStoreHeader  Pointer to the Variable Store Header.
     59 
     60   @return Pointer to the first variable header
     61 
     62 **/
     63 VARIABLE_HEADER *
     64 GetStartPointer (
     65   IN VARIABLE_STORE_HEADER       *VarStoreHeader
     66   )
     67 {
     68   //
     69   // The end of variable store
     70   //
     71   return (VARIABLE_HEADER *) HEADER_ALIGN (VarStoreHeader + 1);
     72 }
     73 
     74 
     75 /**
     76   This code gets the pointer to the last variable memory pointer byte.
     77 
     78   @param  VarStoreHeader  Pointer to the Variable Store Header.
     79 
     80   @return VARIABLE_HEADER* pointer to last unavailable Variable Header.
     81 
     82 **/
     83 VARIABLE_HEADER *
     84 GetEndPointer (
     85   IN VARIABLE_STORE_HEADER       *VarStoreHeader
     86   )
     87 {
     88   //
     89   // The end of variable store
     90   //
     91   return (VARIABLE_HEADER *) HEADER_ALIGN ((UINTN) VarStoreHeader + VarStoreHeader->Size);
     92 }
     93 
     94 
     95 /**
     96   This code checks if variable header is valid or not.
     97 
     98   @param  Variable  Pointer to the Variable Header.
     99 
    100   @retval TRUE      Variable header is valid.
    101   @retval FALSE     Variable header is not valid.
    102 
    103 **/
    104 BOOLEAN
    105 IsValidVariableHeader (
    106   IN  VARIABLE_HEADER   *Variable
    107   )
    108 {
    109   if (Variable == NULL || Variable->StartId != VARIABLE_DATA ) {
    110     return FALSE;
    111   }
    112 
    113   return TRUE;
    114 }
    115 
    116 /**
    117   This code gets the size of variable header.
    118 
    119   @param AuthFlag   Authenticated variable flag.
    120 
    121   @return Size of variable header in bytes in type UINTN.
    122 
    123 **/
    124 UINTN
    125 GetVariableHeaderSize (
    126   IN  BOOLEAN       AuthFlag
    127   )
    128 {
    129   UINTN Value;
    130 
    131   if (AuthFlag) {
    132     Value = sizeof (AUTHENTICATED_VARIABLE_HEADER);
    133   } else {
    134     Value = sizeof (VARIABLE_HEADER);
    135   }
    136 
    137   return Value;
    138 }
    139 
    140 /**
    141   This code gets the size of name of variable.
    142 
    143   @param  Variable  Pointer to the Variable Header.
    144   @param  AuthFlag  Authenticated variable flag.
    145 
    146   @return Size of variable in bytes in type UINTN.
    147 
    148 **/
    149 UINTN
    150 NameSizeOfVariable (
    151   IN  VARIABLE_HEADER   *Variable,
    152   IN  BOOLEAN           AuthFlag
    153   )
    154 {
    155   AUTHENTICATED_VARIABLE_HEADER *AuthVariable;
    156 
    157   AuthVariable = (AUTHENTICATED_VARIABLE_HEADER *) Variable;
    158   if (AuthFlag) {
    159     if (AuthVariable->State == (UINT8) (-1) ||
    160        AuthVariable->DataSize == (UINT32) (-1) ||
    161        AuthVariable->NameSize == (UINT32) (-1) ||
    162        AuthVariable->Attributes == (UINT32) (-1)) {
    163       return 0;
    164     }
    165     return (UINTN) AuthVariable->NameSize;
    166   } else {
    167     if (Variable->State == (UINT8) (-1) ||
    168        Variable->DataSize == (UINT32) (-1) ||
    169        Variable->NameSize == (UINT32) (-1) ||
    170        Variable->Attributes == (UINT32) (-1)) {
    171       return 0;
    172     }
    173     return (UINTN) Variable->NameSize;
    174   }
    175 }
    176 
    177 
    178 /**
    179   This code gets the size of data of variable.
    180 
    181   @param  Variable  Pointer to the Variable Header.
    182   @param  AuthFlag  Authenticated variable flag.
    183 
    184   @return Size of variable in bytes in type UINTN.
    185 
    186 **/
    187 UINTN
    188 DataSizeOfVariable (
    189   IN  VARIABLE_HEADER   *Variable,
    190   IN  BOOLEAN           AuthFlag
    191   )
    192 {
    193   AUTHENTICATED_VARIABLE_HEADER *AuthVariable;
    194 
    195   AuthVariable = (AUTHENTICATED_VARIABLE_HEADER *) Variable;
    196   if (AuthFlag) {
    197     if (AuthVariable->State == (UINT8) (-1) ||
    198        AuthVariable->DataSize == (UINT32) (-1) ||
    199        AuthVariable->NameSize == (UINT32) (-1) ||
    200        AuthVariable->Attributes == (UINT32) (-1)) {
    201       return 0;
    202     }
    203     return (UINTN) AuthVariable->DataSize;
    204   } else {
    205     if (Variable->State == (UINT8) (-1) ||
    206        Variable->DataSize == (UINT32) (-1) ||
    207        Variable->NameSize == (UINT32) (-1) ||
    208        Variable->Attributes == (UINT32) (-1)) {
    209       return 0;
    210     }
    211     return (UINTN) Variable->DataSize;
    212   }
    213 }
    214 
    215 /**
    216   This code gets the pointer to the variable name.
    217 
    218   @param   Variable  Pointer to the Variable Header.
    219   @param   AuthFlag  Authenticated variable flag.
    220 
    221   @return  A CHAR16* pointer to Variable Name.
    222 
    223 **/
    224 CHAR16 *
    225 GetVariableNamePtr (
    226   IN VARIABLE_HEADER    *Variable,
    227   IN BOOLEAN            AuthFlag
    228   )
    229 {
    230   return (CHAR16 *) ((UINTN) Variable + GetVariableHeaderSize (AuthFlag));
    231 }
    232 
    233 /**
    234   This code gets the pointer to the variable guid.
    235 
    236   @param Variable   Pointer to the Variable Header.
    237   @param AuthFlag   Authenticated variable flag.
    238 
    239   @return A EFI_GUID* pointer to Vendor Guid.
    240 
    241 **/
    242 EFI_GUID *
    243 GetVendorGuidPtr (
    244   IN VARIABLE_HEADER    *Variable,
    245   IN BOOLEAN            AuthFlag
    246   )
    247 {
    248   AUTHENTICATED_VARIABLE_HEADER *AuthVariable;
    249 
    250   AuthVariable = (AUTHENTICATED_VARIABLE_HEADER *) Variable;
    251   if (AuthFlag) {
    252     return &AuthVariable->VendorGuid;
    253   } else {
    254     return &Variable->VendorGuid;
    255   }
    256 }
    257 
    258 /**
    259   This code gets the pointer to the variable data.
    260 
    261   @param   Variable         Pointer to the Variable Header.
    262   @param   VariableHeader   Pointer to the Variable Header that has consecutive content.
    263   @param   AuthFlag         Authenticated variable flag.
    264 
    265   @return  A UINT8* pointer to Variable Data.
    266 
    267 **/
    268 UINT8 *
    269 GetVariableDataPtr (
    270   IN  VARIABLE_HEADER   *Variable,
    271   IN  VARIABLE_HEADER   *VariableHeader,
    272   IN  BOOLEAN           AuthFlag
    273   )
    274 {
    275   UINTN Value;
    276 
    277   //
    278   // Be careful about pad size for alignment
    279   //
    280   Value =  (UINTN) GetVariableNamePtr (Variable, AuthFlag);
    281   Value += NameSizeOfVariable (VariableHeader, AuthFlag);
    282   Value += GET_PAD_SIZE (NameSizeOfVariable (VariableHeader, AuthFlag));
    283 
    284   return (UINT8 *) Value;
    285 }
    286 
    287 
    288 /**
    289   This code gets the pointer to the next variable header.
    290 
    291   @param  StoreInfo         Pointer to variable store info structure.
    292   @param  Variable          Pointer to the Variable Header.
    293   @param  VariableHeader    Pointer to the Variable Header that has consecutive content.
    294 
    295   @return  A VARIABLE_HEADER* pointer to next variable header.
    296 
    297 **/
    298 VARIABLE_HEADER *
    299 GetNextVariablePtr (
    300   IN  VARIABLE_STORE_INFO   *StoreInfo,
    301   IN  VARIABLE_HEADER       *Variable,
    302   IN  VARIABLE_HEADER       *VariableHeader
    303   )
    304 {
    305   EFI_PHYSICAL_ADDRESS  TargetAddress;
    306   EFI_PHYSICAL_ADDRESS  SpareAddress;
    307   UINTN                 Value;
    308 
    309   Value =  (UINTN) GetVariableDataPtr (Variable, VariableHeader, StoreInfo->AuthFlag);
    310   Value += DataSizeOfVariable (VariableHeader, StoreInfo->AuthFlag);
    311   Value += GET_PAD_SIZE (DataSizeOfVariable (VariableHeader, StoreInfo->AuthFlag));
    312   //
    313   // Be careful about pad size for alignment
    314   //
    315   Value = HEADER_ALIGN (Value);
    316 
    317   if (StoreInfo->FtwLastWriteData != NULL) {
    318     TargetAddress = StoreInfo->FtwLastWriteData->TargetAddress;
    319     SpareAddress = StoreInfo->FtwLastWriteData->SpareAddress;
    320     if (((UINTN) Variable < (UINTN) TargetAddress) && (Value >= (UINTN) TargetAddress)) {
    321       //
    322       // Next variable is in spare block.
    323       //
    324       Value = (UINTN) SpareAddress + (Value - (UINTN) TargetAddress);
    325     }
    326   }
    327 
    328   return (VARIABLE_HEADER *) Value;
    329 }
    330 
    331 /**
    332   Get variable store status.
    333 
    334   @param  VarStoreHeader  Pointer to the Variable Store Header.
    335 
    336   @retval  EfiRaw      Variable store is raw
    337   @retval  EfiValid    Variable store is valid
    338   @retval  EfiInvalid  Variable store is invalid
    339 
    340 **/
    341 VARIABLE_STORE_STATUS
    342 GetVariableStoreStatus (
    343   IN VARIABLE_STORE_HEADER *VarStoreHeader
    344   )
    345 {
    346   if ((CompareGuid (&VarStoreHeader->Signature, &gEfiAuthenticatedVariableGuid) ||
    347        CompareGuid (&VarStoreHeader->Signature, &gEfiVariableGuid)) &&
    348       VarStoreHeader->Format == VARIABLE_STORE_FORMATTED &&
    349       VarStoreHeader->State == VARIABLE_STORE_HEALTHY
    350       ) {
    351 
    352     return EfiValid;
    353   }
    354 
    355   if (((UINT32 *)(&VarStoreHeader->Signature))[0] == 0xffffffff &&
    356       ((UINT32 *)(&VarStoreHeader->Signature))[1] == 0xffffffff &&
    357       ((UINT32 *)(&VarStoreHeader->Signature))[2] == 0xffffffff &&
    358       ((UINT32 *)(&VarStoreHeader->Signature))[3] == 0xffffffff &&
    359       VarStoreHeader->Size == 0xffffffff &&
    360       VarStoreHeader->Format == 0xff &&
    361       VarStoreHeader->State == 0xff
    362       ) {
    363 
    364     return EfiRaw;
    365   } else {
    366     return EfiInvalid;
    367   }
    368 }
    369 
    370 /**
    371   Compare two variable names, one of them may be inconsecutive.
    372 
    373   @param StoreInfo      Pointer to variable store info structure.
    374   @param Name1          Pointer to one variable name.
    375   @param Name2          Pointer to another variable name.
    376   @param NameSize       Variable name size.
    377 
    378   @retval TRUE          Name1 and Name2 are identical.
    379   @retval FALSE         Name1 and Name2 are not identical.
    380 
    381 **/
    382 BOOLEAN
    383 CompareVariableName (
    384   IN VARIABLE_STORE_INFO    *StoreInfo,
    385   IN CONST CHAR16           *Name1,
    386   IN CONST CHAR16           *Name2,
    387   IN UINTN                  NameSize
    388   )
    389 {
    390   EFI_PHYSICAL_ADDRESS  TargetAddress;
    391   EFI_PHYSICAL_ADDRESS  SpareAddress;
    392   UINTN                 PartialNameSize;
    393 
    394   if (StoreInfo->FtwLastWriteData != NULL) {
    395     TargetAddress = StoreInfo->FtwLastWriteData->TargetAddress;
    396     SpareAddress = StoreInfo->FtwLastWriteData->SpareAddress;
    397     if (((UINTN) Name1 < (UINTN) TargetAddress) && (((UINTN) Name1 + NameSize) > (UINTN) TargetAddress)) {
    398       //
    399       // Name1 is inconsecutive.
    400       //
    401       PartialNameSize = (UINTN) TargetAddress - (UINTN) Name1;
    402       //
    403       // Partial content is in NV storage.
    404       //
    405       if (CompareMem ((UINT8 *) Name1, (UINT8 *) Name2, PartialNameSize) == 0) {
    406         //
    407         // Another partial content is in spare block.
    408         //
    409         if (CompareMem ((UINT8 *) (UINTN) SpareAddress, (UINT8 *) Name2 + PartialNameSize, NameSize - PartialNameSize) == 0) {
    410           return TRUE;
    411         }
    412       }
    413       return FALSE;
    414     } else if (((UINTN) Name2 < (UINTN) TargetAddress) && (((UINTN) Name2 + NameSize) > (UINTN) TargetAddress)) {
    415       //
    416       // Name2 is inconsecutive.
    417       //
    418       PartialNameSize = (UINTN) TargetAddress - (UINTN) Name2;
    419       //
    420       // Partial content is in NV storage.
    421       //
    422       if (CompareMem ((UINT8 *) Name2, (UINT8 *) Name1, PartialNameSize) == 0) {
    423         //
    424         // Another partial content is in spare block.
    425         //
    426         if (CompareMem ((UINT8 *) (UINTN) SpareAddress, (UINT8 *) Name1 + PartialNameSize, NameSize - PartialNameSize) == 0) {
    427           return TRUE;
    428         }
    429       }
    430       return FALSE;
    431     }
    432   }
    433 
    434   //
    435   // Both Name1 and Name2 are consecutive.
    436   //
    437   if (CompareMem ((UINT8 *) Name1, (UINT8 *) Name2, NameSize) == 0) {
    438     return TRUE;
    439   }
    440   return FALSE;
    441 }
    442 
    443 /**
    444   This function compares a variable with variable entries in database.
    445 
    446   @param  StoreInfo     Pointer to variable store info structure.
    447   @param  Variable      Pointer to the variable in our database
    448   @param  VariableHeader Pointer to the Variable Header that has consecutive content.
    449   @param  VariableName  Name of the variable to compare to 'Variable'
    450   @param  VendorGuid    GUID of the variable to compare to 'Variable'
    451   @param  PtrTrack      Variable Track Pointer structure that contains Variable Information.
    452 
    453   @retval EFI_SUCCESS    Found match variable
    454   @retval EFI_NOT_FOUND  Variable not found
    455 
    456 **/
    457 EFI_STATUS
    458 CompareWithValidVariable (
    459   IN  VARIABLE_STORE_INFO           *StoreInfo,
    460   IN  VARIABLE_HEADER               *Variable,
    461   IN  VARIABLE_HEADER               *VariableHeader,
    462   IN  CONST CHAR16                  *VariableName,
    463   IN  CONST EFI_GUID                *VendorGuid,
    464   OUT VARIABLE_POINTER_TRACK        *PtrTrack
    465   )
    466 {
    467   VOID      *Point;
    468   EFI_GUID  *TempVendorGuid;
    469 
    470   TempVendorGuid = GetVendorGuidPtr (VariableHeader, StoreInfo->AuthFlag);
    471 
    472   if (VariableName[0] == 0) {
    473     PtrTrack->CurrPtr = Variable;
    474     return EFI_SUCCESS;
    475   } else {
    476     //
    477     // Don't use CompareGuid function here for performance reasons.
    478     // Instead we compare the GUID a UINT32 at a time and branch
    479     // on the first failed comparison.
    480     //
    481     if ((((INT32 *) VendorGuid)[0] == ((INT32 *) TempVendorGuid)[0]) &&
    482         (((INT32 *) VendorGuid)[1] == ((INT32 *) TempVendorGuid)[1]) &&
    483         (((INT32 *) VendorGuid)[2] == ((INT32 *) TempVendorGuid)[2]) &&
    484         (((INT32 *) VendorGuid)[3] == ((INT32 *) TempVendorGuid)[3])
    485         ) {
    486       ASSERT (NameSizeOfVariable (VariableHeader, StoreInfo->AuthFlag) != 0);
    487       Point = (VOID *) GetVariableNamePtr (Variable, StoreInfo->AuthFlag);
    488       if (CompareVariableName (StoreInfo, VariableName, Point, NameSizeOfVariable (VariableHeader, StoreInfo->AuthFlag))) {
    489         PtrTrack->CurrPtr = Variable;
    490         return EFI_SUCCESS;
    491       }
    492     }
    493   }
    494 
    495   return EFI_NOT_FOUND;
    496 }
    497 
    498 /**
    499   Return the variable store header and the store info based on the Index.
    500 
    501   @param Type       The type of the variable store.
    502   @param StoreInfo  Return the store info.
    503 
    504   @return  Pointer to the variable store header.
    505 **/
    506 VARIABLE_STORE_HEADER *
    507 GetVariableStore (
    508   IN VARIABLE_STORE_TYPE         Type,
    509   OUT VARIABLE_STORE_INFO        *StoreInfo
    510   )
    511 {
    512   EFI_HOB_GUID_TYPE                     *GuidHob;
    513   EFI_FIRMWARE_VOLUME_HEADER            *FvHeader;
    514   VARIABLE_STORE_HEADER                 *VariableStoreHeader;
    515   EFI_PHYSICAL_ADDRESS                  NvStorageBase;
    516   UINT32                                NvStorageSize;
    517   FAULT_TOLERANT_WRITE_LAST_WRITE_DATA  *FtwLastWriteData;
    518   UINT32                                BackUpOffset;
    519 
    520   StoreInfo->IndexTable = NULL;
    521   StoreInfo->FtwLastWriteData = NULL;
    522   StoreInfo->AuthFlag = FALSE;
    523   VariableStoreHeader = NULL;
    524   switch (Type) {
    525     case VariableStoreTypeHob:
    526       GuidHob = GetFirstGuidHob (&gEfiAuthenticatedVariableGuid);
    527       if (GuidHob != NULL) {
    528         VariableStoreHeader = (VARIABLE_STORE_HEADER *) GET_GUID_HOB_DATA (GuidHob);
    529         StoreInfo->AuthFlag = TRUE;
    530       } else {
    531         GuidHob = GetFirstGuidHob (&gEfiVariableGuid);
    532         if (GuidHob != NULL) {
    533           VariableStoreHeader = (VARIABLE_STORE_HEADER *) GET_GUID_HOB_DATA (GuidHob);
    534           StoreInfo->AuthFlag = FALSE;
    535         }
    536       }
    537       break;
    538 
    539     case VariableStoreTypeNv:
    540       if (GetBootModeHob () != BOOT_IN_RECOVERY_MODE) {
    541         //
    542         // The content of NV storage for variable is not reliable in recovery boot mode.
    543         //
    544 
    545         NvStorageSize = PcdGet32 (PcdFlashNvStorageVariableSize);
    546         NvStorageBase = (EFI_PHYSICAL_ADDRESS) (PcdGet64 (PcdFlashNvStorageVariableBase64) != 0 ?
    547                                                 PcdGet64 (PcdFlashNvStorageVariableBase64) :
    548                                                 PcdGet32 (PcdFlashNvStorageVariableBase)
    549                                                );
    550         //
    551         // First let FvHeader point to NV storage base.
    552         //
    553         FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) NvStorageBase;
    554 
    555         //
    556         // Check the FTW last write data hob.
    557         //
    558         BackUpOffset = 0;
    559         GuidHob = GetFirstGuidHob (&gEdkiiFaultTolerantWriteGuid);
    560         if (GuidHob != NULL) {
    561           FtwLastWriteData = (FAULT_TOLERANT_WRITE_LAST_WRITE_DATA *) GET_GUID_HOB_DATA (GuidHob);
    562           if (FtwLastWriteData->TargetAddress == NvStorageBase) {
    563             //
    564             // Let FvHeader point to spare block.
    565             //
    566             FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) FtwLastWriteData->SpareAddress;
    567             DEBUG ((EFI_D_INFO, "PeiVariable: NV storage is backed up in spare block: 0x%x\n", (UINTN) FtwLastWriteData->SpareAddress));
    568           } else if ((FtwLastWriteData->TargetAddress > NvStorageBase) && (FtwLastWriteData->TargetAddress < (NvStorageBase + NvStorageSize))) {
    569             StoreInfo->FtwLastWriteData = FtwLastWriteData;
    570             //
    571             // Flash NV storage from the offset is backed up in spare block.
    572             //
    573             BackUpOffset = (UINT32) (FtwLastWriteData->TargetAddress - NvStorageBase);
    574             DEBUG ((EFI_D_INFO, "PeiVariable: High partial NV storage from offset: %x is backed up in spare block: 0x%x\n", BackUpOffset, (UINTN) FtwLastWriteData->SpareAddress));
    575             //
    576             // At least one block data in flash NV storage is still valid, so still leave FvHeader point to NV storage base.
    577             //
    578           }
    579         }
    580 
    581         //
    582         // Check if the Firmware Volume is not corrupted
    583         //
    584         if ((FvHeader->Signature != EFI_FVH_SIGNATURE) || (!CompareGuid (&gEfiSystemNvDataFvGuid, &FvHeader->FileSystemGuid))) {
    585           DEBUG ((EFI_D_ERROR, "Firmware Volume for Variable Store is corrupted\n"));
    586           break;
    587         }
    588 
    589         VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINT8 *) FvHeader + FvHeader->HeaderLength);
    590 
    591         StoreInfo->AuthFlag = (BOOLEAN) (CompareGuid (&VariableStoreHeader->Signature, &gEfiAuthenticatedVariableGuid));
    592 
    593         GuidHob = GetFirstGuidHob (&gEfiVariableIndexTableGuid);
    594         if (GuidHob != NULL) {
    595           StoreInfo->IndexTable = GET_GUID_HOB_DATA (GuidHob);
    596         } else {
    597           //
    598           // If it's the first time to access variable region in flash, create a guid hob to record
    599           // VAR_ADDED type variable info.
    600           // Note that as the resource of PEI phase is limited, only store the limited number of
    601           // VAR_ADDED type variables to reduce access time.
    602           //
    603           StoreInfo->IndexTable = (VARIABLE_INDEX_TABLE *) BuildGuidHob (&gEfiVariableIndexTableGuid, sizeof (VARIABLE_INDEX_TABLE));
    604           StoreInfo->IndexTable->Length      = 0;
    605           StoreInfo->IndexTable->StartPtr    = GetStartPointer (VariableStoreHeader);
    606           StoreInfo->IndexTable->EndPtr      = GetEndPointer   (VariableStoreHeader);
    607           StoreInfo->IndexTable->GoneThrough = 0;
    608         }
    609       }
    610       break;
    611 
    612     default:
    613       ASSERT (FALSE);
    614       break;
    615   }
    616 
    617   StoreInfo->VariableStoreHeader = VariableStoreHeader;
    618   return VariableStoreHeader;
    619 }
    620 
    621 /**
    622   Get variable header that has consecutive content.
    623 
    624   @param StoreInfo      Pointer to variable store info structure.
    625   @param Variable       Pointer to the Variable Header.
    626   @param VariableHeader Pointer to Pointer to the Variable Header that has consecutive content.
    627 
    628   @retval TRUE          Variable header is valid.
    629   @retval FALSE         Variable header is not valid.
    630 
    631 **/
    632 BOOLEAN
    633 GetVariableHeader (
    634   IN VARIABLE_STORE_INFO    *StoreInfo,
    635   IN VARIABLE_HEADER        *Variable,
    636   OUT VARIABLE_HEADER       **VariableHeader
    637   )
    638 {
    639   EFI_PHYSICAL_ADDRESS  TargetAddress;
    640   EFI_PHYSICAL_ADDRESS  SpareAddress;
    641   EFI_HOB_GUID_TYPE     *GuidHob;
    642   UINTN                 PartialHeaderSize;
    643 
    644   if (Variable == NULL) {
    645     return FALSE;
    646   }
    647 
    648   //
    649   // First assume variable header pointed by Variable is consecutive.
    650   //
    651   *VariableHeader = Variable;
    652 
    653   if (StoreInfo->FtwLastWriteData != NULL) {
    654     TargetAddress = StoreInfo->FtwLastWriteData->TargetAddress;
    655     SpareAddress = StoreInfo->FtwLastWriteData->SpareAddress;
    656     if (((UINTN) Variable > (UINTN) SpareAddress) &&
    657         (((UINTN) Variable - (UINTN) SpareAddress + (UINTN) TargetAddress) >= (UINTN) GetEndPointer (StoreInfo->VariableStoreHeader))) {
    658       //
    659       // Reach the end of variable store.
    660       //
    661       return FALSE;
    662     }
    663     if (((UINTN) Variable < (UINTN) TargetAddress) && (((UINTN) Variable + GetVariableHeaderSize (StoreInfo->AuthFlag)) > (UINTN) TargetAddress)) {
    664       //
    665       // Variable header pointed by Variable is inconsecutive,
    666       // create a guid hob to combine the two partial variable header content together.
    667       //
    668       GuidHob = GetFirstGuidHob (&gEfiCallerIdGuid);
    669       if (GuidHob != NULL) {
    670         *VariableHeader = (VARIABLE_HEADER *) GET_GUID_HOB_DATA (GuidHob);
    671       } else {
    672         *VariableHeader = (VARIABLE_HEADER *) BuildGuidHob (&gEfiCallerIdGuid, GetVariableHeaderSize (StoreInfo->AuthFlag));
    673         PartialHeaderSize = (UINTN) TargetAddress - (UINTN) Variable;
    674         //
    675         // Partial content is in NV storage.
    676         //
    677         CopyMem ((UINT8 *) *VariableHeader, (UINT8 *) Variable, PartialHeaderSize);
    678         //
    679         // Another partial content is in spare block.
    680         //
    681         CopyMem ((UINT8 *) *VariableHeader + PartialHeaderSize, (UINT8 *) (UINTN) SpareAddress, GetVariableHeaderSize (StoreInfo->AuthFlag) - PartialHeaderSize);
    682       }
    683     }
    684   } else {
    685     if (Variable >= GetEndPointer (StoreInfo->VariableStoreHeader)) {
    686       //
    687       // Reach the end of variable store.
    688       //
    689       return FALSE;
    690     }
    691   }
    692 
    693   return IsValidVariableHeader (*VariableHeader);
    694 }
    695 
    696 /**
    697   Get variable name or data to output buffer.
    698 
    699   @param  StoreInfo     Pointer to variable store info structure.
    700   @param  NameOrData    Pointer to the variable name/data that may be inconsecutive.
    701   @param  Size          Variable name/data size.
    702   @param  Buffer        Pointer to output buffer to hold the variable name/data.
    703 
    704 **/
    705 VOID
    706 GetVariableNameOrData (
    707   IN VARIABLE_STORE_INFO    *StoreInfo,
    708   IN UINT8                  *NameOrData,
    709   IN UINTN                  Size,
    710   OUT UINT8                 *Buffer
    711   )
    712 {
    713   EFI_PHYSICAL_ADDRESS  TargetAddress;
    714   EFI_PHYSICAL_ADDRESS  SpareAddress;
    715   UINTN                 PartialSize;
    716 
    717   if (StoreInfo->FtwLastWriteData != NULL) {
    718     TargetAddress = StoreInfo->FtwLastWriteData->TargetAddress;
    719     SpareAddress = StoreInfo->FtwLastWriteData->SpareAddress;
    720     if (((UINTN) NameOrData < (UINTN) TargetAddress) && (((UINTN) NameOrData + Size) > (UINTN) TargetAddress)) {
    721       //
    722       // Variable name/data is inconsecutive.
    723       //
    724       PartialSize = (UINTN) TargetAddress - (UINTN) NameOrData;
    725       //
    726       // Partial content is in NV storage.
    727       //
    728       CopyMem (Buffer, NameOrData, PartialSize);
    729       //
    730       // Another partial content is in spare block.
    731       //
    732       CopyMem (Buffer + PartialSize, (UINT8 *) (UINTN) SpareAddress, Size - PartialSize);
    733       return;
    734     }
    735   }
    736 
    737   //
    738   // Variable name/data is consecutive.
    739   //
    740   CopyMem (Buffer, NameOrData, Size);
    741 }
    742 
    743 /**
    744   Find the variable in the specified variable store.
    745 
    746   @param  StoreInfo           Pointer to the store info structure.
    747   @param  VariableName        Name of the variable to be found
    748   @param  VendorGuid          Vendor GUID to be found.
    749   @param  PtrTrack            Variable Track Pointer structure that contains Variable Information.
    750 
    751   @retval  EFI_SUCCESS            Variable found successfully
    752   @retval  EFI_NOT_FOUND          Variable not found
    753   @retval  EFI_INVALID_PARAMETER  Invalid variable name
    754 
    755 **/
    756 EFI_STATUS
    757 FindVariableEx (
    758   IN VARIABLE_STORE_INFO         *StoreInfo,
    759   IN CONST CHAR16                *VariableName,
    760   IN CONST EFI_GUID              *VendorGuid,
    761   OUT VARIABLE_POINTER_TRACK     *PtrTrack
    762   )
    763 {
    764   VARIABLE_HEADER         *Variable;
    765   VARIABLE_HEADER         *LastVariable;
    766   VARIABLE_HEADER         *MaxIndex;
    767   UINTN                   Index;
    768   UINTN                   Offset;
    769   BOOLEAN                 StopRecord;
    770   VARIABLE_HEADER         *InDeletedVariable;
    771   VARIABLE_STORE_HEADER   *VariableStoreHeader;
    772   VARIABLE_INDEX_TABLE    *IndexTable;
    773   VARIABLE_HEADER         *VariableHeader;
    774 
    775   VariableStoreHeader = StoreInfo->VariableStoreHeader;
    776 
    777   if (VariableStoreHeader == NULL) {
    778     return EFI_INVALID_PARAMETER;
    779   }
    780 
    781   if (GetVariableStoreStatus (VariableStoreHeader) != EfiValid) {
    782     return EFI_UNSUPPORTED;
    783   }
    784 
    785   if (~VariableStoreHeader->Size == 0) {
    786     return EFI_NOT_FOUND;
    787   }
    788 
    789   IndexTable = StoreInfo->IndexTable;
    790   PtrTrack->StartPtr = GetStartPointer (VariableStoreHeader);
    791   PtrTrack->EndPtr   = GetEndPointer   (VariableStoreHeader);
    792 
    793   InDeletedVariable = NULL;
    794 
    795   //
    796   // No Variable Address equals zero, so 0 as initial value is safe.
    797   //
    798   MaxIndex   = NULL;
    799   VariableHeader = NULL;
    800 
    801   if (IndexTable != NULL) {
    802     //
    803     // traverse the variable index table to look for varible.
    804     // The IndexTable->Index[Index] records the distance of two neighbouring VAR_ADDED type variables.
    805     //
    806     for (Offset = 0, Index = 0; Index < IndexTable->Length; Index++) {
    807       ASSERT (Index < sizeof (IndexTable->Index) / sizeof (IndexTable->Index[0]));
    808       Offset   += IndexTable->Index[Index];
    809       MaxIndex  = (VARIABLE_HEADER *) ((UINT8 *) IndexTable->StartPtr + Offset);
    810       GetVariableHeader (StoreInfo, MaxIndex, &VariableHeader);
    811       if (CompareWithValidVariable (StoreInfo, MaxIndex, VariableHeader, VariableName, VendorGuid, PtrTrack) == EFI_SUCCESS) {
    812         if (VariableHeader->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
    813           InDeletedVariable = PtrTrack->CurrPtr;
    814         } else {
    815           return EFI_SUCCESS;
    816         }
    817       }
    818     }
    819 
    820     if (IndexTable->GoneThrough != 0) {
    821       //
    822       // If the table has all the existing variables indexed, return.
    823       //
    824       PtrTrack->CurrPtr = InDeletedVariable;
    825       return (PtrTrack->CurrPtr == NULL) ? EFI_NOT_FOUND : EFI_SUCCESS;
    826     }
    827   }
    828 
    829   if (MaxIndex != NULL) {
    830     //
    831     // HOB exists but the variable cannot be found in HOB
    832     // If not found in HOB, then let's start from the MaxIndex we've found.
    833     //
    834     Variable     = GetNextVariablePtr (StoreInfo, MaxIndex, VariableHeader);
    835     LastVariable = MaxIndex;
    836   } else {
    837     //
    838     // Start Pointers for the variable.
    839     // Actual Data Pointer where data can be written.
    840     //
    841     Variable     = PtrTrack->StartPtr;
    842     LastVariable = PtrTrack->StartPtr;
    843   }
    844 
    845   //
    846   // Find the variable by walk through variable store
    847   //
    848   StopRecord = FALSE;
    849   while (GetVariableHeader (StoreInfo, Variable, &VariableHeader)) {
    850     if (VariableHeader->State == VAR_ADDED || VariableHeader->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
    851       //
    852       // Record Variable in VariableIndex HOB
    853       //
    854       if ((IndexTable != NULL) && !StopRecord) {
    855         Offset = (UINTN) Variable - (UINTN) LastVariable;
    856         if ((Offset > 0x0FFFF) || (IndexTable->Length == sizeof (IndexTable->Index) / sizeof (IndexTable->Index[0]))) {
    857           //
    858           // Stop to record if the distance of two neighbouring VAR_ADDED variable is larger than the allowable scope(UINT16),
    859           // or the record buffer is full.
    860           //
    861           StopRecord = TRUE;
    862         } else {
    863           IndexTable->Index[IndexTable->Length++] = (UINT16) Offset;
    864           LastVariable = Variable;
    865         }
    866       }
    867 
    868       if (CompareWithValidVariable (StoreInfo, Variable, VariableHeader, VariableName, VendorGuid, PtrTrack) == EFI_SUCCESS) {
    869         if (VariableHeader->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
    870           InDeletedVariable = PtrTrack->CurrPtr;
    871         } else {
    872           return EFI_SUCCESS;
    873         }
    874       }
    875     }
    876 
    877     Variable = GetNextVariablePtr (StoreInfo, Variable, VariableHeader);
    878   }
    879   //
    880   // If gone through the VariableStore, that means we never find in Firmware any more.
    881   //
    882   if ((IndexTable != NULL) && !StopRecord) {
    883     IndexTable->GoneThrough = 1;
    884   }
    885 
    886   PtrTrack->CurrPtr = InDeletedVariable;
    887 
    888   return (PtrTrack->CurrPtr == NULL) ? EFI_NOT_FOUND : EFI_SUCCESS;
    889 }
    890 
    891 /**
    892   Find the variable in HOB and Non-Volatile variable storages.
    893 
    894   @param  VariableName  Name of the variable to be found
    895   @param  VendorGuid    Vendor GUID to be found.
    896   @param  PtrTrack      Variable Track Pointer structure that contains Variable Information.
    897   @param  StoreInfo     Return the store info.
    898 
    899   @retval  EFI_SUCCESS            Variable found successfully
    900   @retval  EFI_NOT_FOUND          Variable not found
    901   @retval  EFI_INVALID_PARAMETER  Invalid variable name
    902 **/
    903 EFI_STATUS
    904 FindVariable (
    905   IN CONST  CHAR16            *VariableName,
    906   IN CONST  EFI_GUID          *VendorGuid,
    907   OUT VARIABLE_POINTER_TRACK  *PtrTrack,
    908   OUT VARIABLE_STORE_INFO     *StoreInfo
    909   )
    910 {
    911   EFI_STATUS                  Status;
    912   VARIABLE_STORE_TYPE         Type;
    913 
    914   if (VariableName[0] != 0 && VendorGuid == NULL) {
    915     return EFI_INVALID_PARAMETER;
    916   }
    917 
    918   for (Type = (VARIABLE_STORE_TYPE) 0; Type < VariableStoreTypeMax; Type++) {
    919     GetVariableStore (Type, StoreInfo);
    920     Status = FindVariableEx (
    921                StoreInfo,
    922                VariableName,
    923                VendorGuid,
    924                PtrTrack
    925                );
    926     if (!EFI_ERROR (Status)) {
    927       return Status;
    928     }
    929   }
    930 
    931   return EFI_NOT_FOUND;
    932 }
    933 
    934 /**
    935   This service retrieves a variable's value using its name and GUID.
    936 
    937   Read the specified variable from the UEFI variable store. If the Data
    938   buffer is too small to hold the contents of the variable, the error
    939   EFI_BUFFER_TOO_SMALL is returned and DataSize is set to the required buffer
    940   size to obtain the data.
    941 
    942   @param  This                  A pointer to this instance of the EFI_PEI_READ_ONLY_VARIABLE2_PPI.
    943   @param  VariableName          A pointer to a null-terminated string that is the variable's name.
    944   @param  VariableGuid          A pointer to an EFI_GUID that is the variable's GUID. The combination of
    945                                 VariableGuid and VariableName must be unique.
    946   @param  Attributes            If non-NULL, on return, points to the variable's attributes.
    947   @param  DataSize              On entry, points to the size in bytes of the Data buffer.
    948                                 On return, points to the size of the data returned in Data.
    949   @param  Data                  Points to the buffer which will hold the returned variable value.
    950 
    951   @retval EFI_SUCCESS           The variable was read successfully.
    952   @retval EFI_NOT_FOUND         The variable could not be found.
    953   @retval EFI_BUFFER_TOO_SMALL  The DataSize is too small for the resulting data.
    954                                 DataSize is updated with the size required for
    955                                 the specified variable.
    956   @retval EFI_INVALID_PARAMETER VariableName, VariableGuid, DataSize or Data is NULL.
    957   @retval EFI_DEVICE_ERROR      The variable could not be retrieved because of a device error.
    958 
    959 **/
    960 EFI_STATUS
    961 EFIAPI
    962 PeiGetVariable (
    963   IN CONST  EFI_PEI_READ_ONLY_VARIABLE2_PPI *This,
    964   IN CONST  CHAR16                          *VariableName,
    965   IN CONST  EFI_GUID                        *VariableGuid,
    966   OUT       UINT32                          *Attributes,
    967   IN OUT    UINTN                           *DataSize,
    968   OUT       VOID                            *Data
    969   )
    970 {
    971   VARIABLE_POINTER_TRACK  Variable;
    972   UINTN                   VarDataSize;
    973   EFI_STATUS              Status;
    974   VARIABLE_STORE_INFO     StoreInfo;
    975   VARIABLE_HEADER         *VariableHeader;
    976 
    977   if (VariableName == NULL || VariableGuid == NULL || DataSize == NULL) {
    978     return EFI_INVALID_PARAMETER;
    979   }
    980 
    981   if (VariableName[0] == 0) {
    982     return EFI_NOT_FOUND;
    983   }
    984 
    985   VariableHeader = NULL;
    986 
    987   //
    988   // Find existing variable
    989   //
    990   Status = FindVariable (VariableName, VariableGuid, &Variable, &StoreInfo);
    991   if (EFI_ERROR (Status)) {
    992     return Status;
    993   }
    994   GetVariableHeader (&StoreInfo, Variable.CurrPtr, &VariableHeader);
    995 
    996   //
    997   // Get data size
    998   //
    999   VarDataSize = DataSizeOfVariable (VariableHeader, StoreInfo.AuthFlag);
   1000   if (*DataSize >= VarDataSize) {
   1001     if (Data == NULL) {
   1002       return EFI_INVALID_PARAMETER;
   1003     }
   1004 
   1005     GetVariableNameOrData (&StoreInfo, GetVariableDataPtr (Variable.CurrPtr, VariableHeader, StoreInfo.AuthFlag), VarDataSize, Data);
   1006 
   1007     if (Attributes != NULL) {
   1008       *Attributes = VariableHeader->Attributes;
   1009     }
   1010 
   1011     *DataSize = VarDataSize;
   1012     return EFI_SUCCESS;
   1013   } else {
   1014     *DataSize = VarDataSize;
   1015     return EFI_BUFFER_TOO_SMALL;
   1016   }
   1017 }
   1018 
   1019 /**
   1020   Return the next variable name and GUID.
   1021 
   1022   This function is called multiple times to retrieve the VariableName
   1023   and VariableGuid of all variables currently available in the system.
   1024   On each call, the previous results are passed into the interface,
   1025   and, on return, the interface returns the data for the next
   1026   interface. When the entire variable list has been returned,
   1027   EFI_NOT_FOUND is returned.
   1028 
   1029   @param  This              A pointer to this instance of the EFI_PEI_READ_ONLY_VARIABLE2_PPI.
   1030 
   1031   @param  VariableNameSize  On entry, points to the size of the buffer pointed to by VariableName.
   1032                             On return, the size of the variable name buffer.
   1033   @param  VariableName      On entry, a pointer to a null-terminated string that is the variable's name.
   1034                             On return, points to the next variable's null-terminated name string.
   1035   @param  VariableGuid      On entry, a pointer to an EFI_GUID that is the variable's GUID.
   1036                             On return, a pointer to the next variable's GUID.
   1037 
   1038   @retval EFI_SUCCESS           The variable was read successfully.
   1039   @retval EFI_NOT_FOUND         The variable could not be found.
   1040   @retval EFI_BUFFER_TOO_SMALL  The VariableNameSize is too small for the resulting
   1041                                 data. VariableNameSize is updated with the size
   1042                                 required for the specified variable.
   1043   @retval EFI_INVALID_PARAMETER VariableName, VariableGuid or
   1044                                 VariableNameSize is NULL.
   1045   @retval EFI_DEVICE_ERROR      The variable could not be retrieved because of a device error.
   1046 
   1047 **/
   1048 EFI_STATUS
   1049 EFIAPI
   1050 PeiGetNextVariableName (
   1051   IN CONST  EFI_PEI_READ_ONLY_VARIABLE2_PPI *This,
   1052   IN OUT UINTN                              *VariableNameSize,
   1053   IN OUT CHAR16                             *VariableName,
   1054   IN OUT EFI_GUID                           *VariableGuid
   1055   )
   1056 {
   1057   VARIABLE_STORE_TYPE     Type;
   1058   VARIABLE_POINTER_TRACK  Variable;
   1059   VARIABLE_POINTER_TRACK  VariableInHob;
   1060   VARIABLE_POINTER_TRACK  VariablePtrTrack;
   1061   UINTN                   VarNameSize;
   1062   EFI_STATUS              Status;
   1063   VARIABLE_STORE_HEADER   *VariableStoreHeader[VariableStoreTypeMax];
   1064   VARIABLE_HEADER         *VariableHeader;
   1065   VARIABLE_STORE_INFO     StoreInfo;
   1066   VARIABLE_STORE_INFO     StoreInfoForNv;
   1067   VARIABLE_STORE_INFO     StoreInfoForHob;
   1068 
   1069   if (VariableName == NULL || VariableGuid == NULL || VariableNameSize == NULL) {
   1070     return EFI_INVALID_PARAMETER;
   1071   }
   1072 
   1073   VariableHeader = NULL;
   1074 
   1075   Status = FindVariable (VariableName, VariableGuid, &Variable, &StoreInfo);
   1076   if (Variable.CurrPtr == NULL || Status != EFI_SUCCESS) {
   1077     return Status;
   1078   }
   1079 
   1080   if (VariableName[0] != 0) {
   1081     //
   1082     // If variable name is not NULL, get next variable
   1083     //
   1084     GetVariableHeader (&StoreInfo, Variable.CurrPtr, &VariableHeader);
   1085     Variable.CurrPtr = GetNextVariablePtr (&StoreInfo, Variable.CurrPtr, VariableHeader);
   1086   }
   1087 
   1088   VariableStoreHeader[VariableStoreTypeHob] = GetVariableStore (VariableStoreTypeHob, &StoreInfoForHob);
   1089   VariableStoreHeader[VariableStoreTypeNv]  = GetVariableStore (VariableStoreTypeNv, &StoreInfoForNv);
   1090 
   1091   while (TRUE) {
   1092     //
   1093     // Switch from HOB to Non-Volatile.
   1094     //
   1095     while (!GetVariableHeader (&StoreInfo, Variable.CurrPtr, &VariableHeader)) {
   1096       //
   1097       // Find current storage index
   1098       //
   1099       for (Type = (VARIABLE_STORE_TYPE) 0; Type < VariableStoreTypeMax; Type++) {
   1100         if ((VariableStoreHeader[Type] != NULL) && (Variable.StartPtr == GetStartPointer (VariableStoreHeader[Type]))) {
   1101           break;
   1102         }
   1103       }
   1104       ASSERT (Type < VariableStoreTypeMax);
   1105       //
   1106       // Switch to next storage
   1107       //
   1108       for (Type++; Type < VariableStoreTypeMax; Type++) {
   1109         if (VariableStoreHeader[Type] != NULL) {
   1110           break;
   1111         }
   1112       }
   1113       //
   1114       // Capture the case that
   1115       // 1. current storage is the last one, or
   1116       // 2. no further storage
   1117       //
   1118       if (Type == VariableStoreTypeMax) {
   1119         return EFI_NOT_FOUND;
   1120       }
   1121       Variable.StartPtr = GetStartPointer (VariableStoreHeader[Type]);
   1122       Variable.EndPtr   = GetEndPointer   (VariableStoreHeader[Type]);
   1123       Variable.CurrPtr  = Variable.StartPtr;
   1124       GetVariableStore (Type, &StoreInfo);
   1125     }
   1126 
   1127     if (VariableHeader->State == VAR_ADDED || VariableHeader->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
   1128       if (VariableHeader->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
   1129         //
   1130         // If it is a IN_DELETED_TRANSITION variable,
   1131         // and there is also a same ADDED one at the same time,
   1132         // don't return it.
   1133         //
   1134         Status = FindVariableEx (
   1135                    &StoreInfo,
   1136                    GetVariableNamePtr (Variable.CurrPtr, StoreInfo.AuthFlag),
   1137                    GetVendorGuidPtr (VariableHeader, StoreInfo.AuthFlag),
   1138                    &VariablePtrTrack
   1139                    );
   1140         if (!EFI_ERROR (Status) && VariablePtrTrack.CurrPtr != Variable.CurrPtr) {
   1141           Variable.CurrPtr = GetNextVariablePtr (&StoreInfo, Variable.CurrPtr, VariableHeader);
   1142           continue;
   1143         }
   1144       }
   1145 
   1146       //
   1147       // Don't return NV variable when HOB overrides it
   1148       //
   1149       if ((VariableStoreHeader[VariableStoreTypeHob] != NULL) && (VariableStoreHeader[VariableStoreTypeNv] != NULL) &&
   1150           (Variable.StartPtr == GetStartPointer (VariableStoreHeader[VariableStoreTypeNv]))
   1151          ) {
   1152         Status = FindVariableEx (
   1153                    &StoreInfoForHob,
   1154                    GetVariableNamePtr (Variable.CurrPtr, StoreInfo.AuthFlag),
   1155                    GetVendorGuidPtr (VariableHeader, StoreInfo.AuthFlag),
   1156                    &VariableInHob
   1157                    );
   1158         if (!EFI_ERROR (Status)) {
   1159           Variable.CurrPtr = GetNextVariablePtr (&StoreInfo, Variable.CurrPtr, VariableHeader);
   1160           continue;
   1161         }
   1162       }
   1163 
   1164       VarNameSize = NameSizeOfVariable (VariableHeader, StoreInfo.AuthFlag);
   1165       ASSERT (VarNameSize != 0);
   1166 
   1167       if (VarNameSize <= *VariableNameSize) {
   1168         GetVariableNameOrData (&StoreInfo, (UINT8 *) GetVariableNamePtr (Variable.CurrPtr, StoreInfo.AuthFlag), VarNameSize, (UINT8 *) VariableName);
   1169 
   1170         CopyMem (VariableGuid, GetVendorGuidPtr (VariableHeader, StoreInfo.AuthFlag), sizeof (EFI_GUID));
   1171 
   1172         Status = EFI_SUCCESS;
   1173       } else {
   1174         Status = EFI_BUFFER_TOO_SMALL;
   1175       }
   1176 
   1177       *VariableNameSize = VarNameSize;
   1178       //
   1179       // Variable is found
   1180       //
   1181       return Status;
   1182     } else {
   1183       Variable.CurrPtr = GetNextVariablePtr (&StoreInfo, Variable.CurrPtr, VariableHeader);
   1184     }
   1185   }
   1186 }
   1187