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