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