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