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 - 2015, 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
PeimInitializeVariableServices(IN EFI_PEI_FILE_HANDLE FileHandle,IN CONST EFI_PEI_SERVICES ** PeiServices)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 *
GetStartPointer(IN VARIABLE_STORE_HEADER * VarStoreHeader)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 *
GetEndPointer(IN VARIABLE_STORE_HEADER * VarStoreHeader)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
IsValidVariableHeader(IN VARIABLE_HEADER * Variable)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
GetVariableHeaderSize(IN BOOLEAN AuthFlag)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
NameSizeOfVariable(IN VARIABLE_HEADER * Variable,IN BOOLEAN AuthFlag)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
DataSizeOfVariable(IN VARIABLE_HEADER * Variable,IN BOOLEAN AuthFlag)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 *
GetVariableNamePtr(IN VARIABLE_HEADER * Variable,IN BOOLEAN AuthFlag)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 *
GetVendorGuidPtr(IN VARIABLE_HEADER * Variable,IN BOOLEAN AuthFlag)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 *
GetVariableDataPtr(IN VARIABLE_HEADER * Variable,IN VARIABLE_HEADER * VariableHeader,IN BOOLEAN AuthFlag)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 *
GetNextVariablePtr(IN VARIABLE_STORE_INFO * StoreInfo,IN VARIABLE_HEADER * Variable,IN VARIABLE_HEADER * VariableHeader)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
GetVariableStoreStatus(IN VARIABLE_STORE_HEADER * VarStoreHeader)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
CompareVariableName(IN VARIABLE_STORE_INFO * StoreInfo,IN CONST CHAR16 * Name1,IN CONST CHAR16 * Name2,IN UINTN NameSize)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
CompareWithValidVariable(IN VARIABLE_STORE_INFO * StoreInfo,IN VARIABLE_HEADER * Variable,IN VARIABLE_HEADER * VariableHeader,IN CONST CHAR16 * VariableName,IN CONST EFI_GUID * VendorGuid,OUT VARIABLE_POINTER_TRACK * PtrTrack)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 *
GetVariableStore(IN VARIABLE_STORE_TYPE Type,OUT VARIABLE_STORE_INFO * StoreInfo)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
GetVariableHeader(IN VARIABLE_STORE_INFO * StoreInfo,IN VARIABLE_HEADER * Variable,OUT VARIABLE_HEADER ** VariableHeader)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
GetVariableNameOrData(IN VARIABLE_STORE_INFO * StoreInfo,IN UINT8 * NameOrData,IN UINTN Size,OUT UINT8 * Buffer)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
FindVariableEx(IN VARIABLE_STORE_INFO * StoreInfo,IN CONST CHAR16 * VariableName,IN CONST EFI_GUID * VendorGuid,OUT VARIABLE_POINTER_TRACK * PtrTrack)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
FindVariable(IN CONST CHAR16 * VariableName,IN CONST EFI_GUID * VendorGuid,OUT VARIABLE_POINTER_TRACK * PtrTrack,OUT VARIABLE_STORE_INFO * StoreInfo)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
PeiGetVariable(IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI * This,IN CONST CHAR16 * VariableName,IN CONST EFI_GUID * VariableGuid,OUT UINT32 * Attributes,IN OUT UINTN * DataSize,OUT VOID * Data)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   VariableHeader = NULL;
982 
983   //
984   // Find existing variable
985   //
986   Status = FindVariable (VariableName, VariableGuid, &Variable, &StoreInfo);
987   if (EFI_ERROR (Status)) {
988     return Status;
989   }
990   GetVariableHeader (&StoreInfo, Variable.CurrPtr, &VariableHeader);
991 
992   //
993   // Get data size
994   //
995   VarDataSize = DataSizeOfVariable (VariableHeader, StoreInfo.AuthFlag);
996   if (*DataSize >= VarDataSize) {
997     if (Data == NULL) {
998       return EFI_INVALID_PARAMETER;
999     }
1000 
1001     GetVariableNameOrData (&StoreInfo, GetVariableDataPtr (Variable.CurrPtr, VariableHeader, StoreInfo.AuthFlag), VarDataSize, Data);
1002 
1003     if (Attributes != NULL) {
1004       *Attributes = VariableHeader->Attributes;
1005     }
1006 
1007     *DataSize = VarDataSize;
1008     return EFI_SUCCESS;
1009   } else {
1010     *DataSize = VarDataSize;
1011     return EFI_BUFFER_TOO_SMALL;
1012   }
1013 }
1014 
1015 /**
1016   Return the next variable name and GUID.
1017 
1018   This function is called multiple times to retrieve the VariableName
1019   and VariableGuid of all variables currently available in the system.
1020   On each call, the previous results are passed into the interface,
1021   and, on return, the interface returns the data for the next
1022   interface. When the entire variable list has been returned,
1023   EFI_NOT_FOUND is returned.
1024 
1025   @param  This              A pointer to this instance of the EFI_PEI_READ_ONLY_VARIABLE2_PPI.
1026 
1027   @param  VariableNameSize  On entry, points to the size of the buffer pointed to by VariableName.
1028                             On return, the size of the variable name buffer.
1029   @param  VariableName      On entry, a pointer to a null-terminated string that is the variable's name.
1030                             On return, points to the next variable's null-terminated name string.
1031   @param  VariableGuid      On entry, a pointer to an EFI_GUID that is the variable's GUID.
1032                             On return, a pointer to the next variable's GUID.
1033 
1034   @retval EFI_SUCCESS           The variable was read successfully.
1035   @retval EFI_NOT_FOUND         The variable could not be found.
1036   @retval EFI_BUFFER_TOO_SMALL  The VariableNameSize is too small for the resulting
1037                                 data. VariableNameSize is updated with the size
1038                                 required for the specified variable.
1039   @retval EFI_INVALID_PARAMETER VariableName, VariableGuid or
1040                                 VariableNameSize is NULL.
1041   @retval EFI_DEVICE_ERROR      The variable could not be retrieved because of a device error.
1042 
1043 **/
1044 EFI_STATUS
1045 EFIAPI
PeiGetNextVariableName(IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI * This,IN OUT UINTN * VariableNameSize,IN OUT CHAR16 * VariableName,IN OUT EFI_GUID * VariableGuid)1046 PeiGetNextVariableName (
1047   IN CONST  EFI_PEI_READ_ONLY_VARIABLE2_PPI *This,
1048   IN OUT UINTN                              *VariableNameSize,
1049   IN OUT CHAR16                             *VariableName,
1050   IN OUT EFI_GUID                           *VariableGuid
1051   )
1052 {
1053   VARIABLE_STORE_TYPE     Type;
1054   VARIABLE_POINTER_TRACK  Variable;
1055   VARIABLE_POINTER_TRACK  VariableInHob;
1056   VARIABLE_POINTER_TRACK  VariablePtrTrack;
1057   UINTN                   VarNameSize;
1058   EFI_STATUS              Status;
1059   VARIABLE_STORE_HEADER   *VariableStoreHeader[VariableStoreTypeMax];
1060   VARIABLE_HEADER         *VariableHeader;
1061   VARIABLE_STORE_INFO     StoreInfo;
1062   VARIABLE_STORE_INFO     StoreInfoForNv;
1063   VARIABLE_STORE_INFO     StoreInfoForHob;
1064 
1065   if (VariableName == NULL || VariableGuid == NULL || VariableNameSize == NULL) {
1066     return EFI_INVALID_PARAMETER;
1067   }
1068 
1069   VariableHeader = NULL;
1070 
1071   Status = FindVariable (VariableName, VariableGuid, &Variable, &StoreInfo);
1072   if (Variable.CurrPtr == NULL || Status != EFI_SUCCESS) {
1073     return Status;
1074   }
1075 
1076   if (VariableName[0] != 0) {
1077     //
1078     // If variable name is not NULL, get next variable
1079     //
1080     GetVariableHeader (&StoreInfo, Variable.CurrPtr, &VariableHeader);
1081     Variable.CurrPtr = GetNextVariablePtr (&StoreInfo, Variable.CurrPtr, VariableHeader);
1082   }
1083 
1084   VariableStoreHeader[VariableStoreTypeHob] = GetVariableStore (VariableStoreTypeHob, &StoreInfoForHob);
1085   VariableStoreHeader[VariableStoreTypeNv]  = GetVariableStore (VariableStoreTypeNv, &StoreInfoForNv);
1086 
1087   while (TRUE) {
1088     //
1089     // Switch from HOB to Non-Volatile.
1090     //
1091     while (!GetVariableHeader (&StoreInfo, Variable.CurrPtr, &VariableHeader)) {
1092       //
1093       // Find current storage index
1094       //
1095       for (Type = (VARIABLE_STORE_TYPE) 0; Type < VariableStoreTypeMax; Type++) {
1096         if ((VariableStoreHeader[Type] != NULL) && (Variable.StartPtr == GetStartPointer (VariableStoreHeader[Type]))) {
1097           break;
1098         }
1099       }
1100       ASSERT (Type < VariableStoreTypeMax);
1101       //
1102       // Switch to next storage
1103       //
1104       for (Type++; Type < VariableStoreTypeMax; Type++) {
1105         if (VariableStoreHeader[Type] != NULL) {
1106           break;
1107         }
1108       }
1109       //
1110       // Capture the case that
1111       // 1. current storage is the last one, or
1112       // 2. no further storage
1113       //
1114       if (Type == VariableStoreTypeMax) {
1115         return EFI_NOT_FOUND;
1116       }
1117       Variable.StartPtr = GetStartPointer (VariableStoreHeader[Type]);
1118       Variable.EndPtr   = GetEndPointer   (VariableStoreHeader[Type]);
1119       Variable.CurrPtr  = Variable.StartPtr;
1120       GetVariableStore (Type, &StoreInfo);
1121     }
1122 
1123     if (VariableHeader->State == VAR_ADDED || VariableHeader->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
1124       if (VariableHeader->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
1125         //
1126         // If it is a IN_DELETED_TRANSITION variable,
1127         // and there is also a same ADDED one at the same time,
1128         // don't return it.
1129         //
1130         Status = FindVariableEx (
1131                    &StoreInfo,
1132                    GetVariableNamePtr (Variable.CurrPtr, StoreInfo.AuthFlag),
1133                    GetVendorGuidPtr (VariableHeader, StoreInfo.AuthFlag),
1134                    &VariablePtrTrack
1135                    );
1136         if (!EFI_ERROR (Status) && VariablePtrTrack.CurrPtr != Variable.CurrPtr) {
1137           Variable.CurrPtr = GetNextVariablePtr (&StoreInfo, Variable.CurrPtr, VariableHeader);
1138           continue;
1139         }
1140       }
1141 
1142       //
1143       // Don't return NV variable when HOB overrides it
1144       //
1145       if ((VariableStoreHeader[VariableStoreTypeHob] != NULL) && (VariableStoreHeader[VariableStoreTypeNv] != NULL) &&
1146           (Variable.StartPtr == GetStartPointer (VariableStoreHeader[VariableStoreTypeNv]))
1147          ) {
1148         Status = FindVariableEx (
1149                    &StoreInfoForHob,
1150                    GetVariableNamePtr (Variable.CurrPtr, StoreInfo.AuthFlag),
1151                    GetVendorGuidPtr (VariableHeader, StoreInfo.AuthFlag),
1152                    &VariableInHob
1153                    );
1154         if (!EFI_ERROR (Status)) {
1155           Variable.CurrPtr = GetNextVariablePtr (&StoreInfo, Variable.CurrPtr, VariableHeader);
1156           continue;
1157         }
1158       }
1159 
1160       VarNameSize = NameSizeOfVariable (VariableHeader, StoreInfo.AuthFlag);
1161       ASSERT (VarNameSize != 0);
1162 
1163       if (VarNameSize <= *VariableNameSize) {
1164         GetVariableNameOrData (&StoreInfo, (UINT8 *) GetVariableNamePtr (Variable.CurrPtr, StoreInfo.AuthFlag), VarNameSize, (UINT8 *) VariableName);
1165 
1166         CopyMem (VariableGuid, GetVendorGuidPtr (VariableHeader, StoreInfo.AuthFlag), sizeof (EFI_GUID));
1167 
1168         Status = EFI_SUCCESS;
1169       } else {
1170         Status = EFI_BUFFER_TOO_SMALL;
1171       }
1172 
1173       *VariableNameSize = VarNameSize;
1174       //
1175       // Variable is found
1176       //
1177       return Status;
1178     } else {
1179       Variable.CurrPtr = GetNextVariablePtr (&StoreInfo, Variable.CurrPtr, VariableHeader);
1180     }
1181   }
1182 }
1183