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