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