]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Variable/Pei/Variable.c
MdeModulePkg Variable: Fix comment typo 'end' to 'start'
[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
09808bd3 5Copyright (c) 2006 - 2018, 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
587 if (GetBootModeHob () != BOOT_IN_RECOVERY_MODE) {\r
588 //\r
589 // The content of NV storage for variable is not reliable in recovery boot mode.\r
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
597 //\r
598 // First let FvHeader point to NV storage base.\r
599 //\r
600 FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) NvStorageBase;\r
601\r
602 //\r
603 // Check the FTW last write data hob.\r
604 //\r
605 BackUpOffset = 0;\r
606 GuidHob = GetFirstGuidHob (&gEdkiiFaultTolerantWriteGuid);\r
607 if (GuidHob != NULL) {\r
608 FtwLastWriteData = (FAULT_TOLERANT_WRITE_LAST_WRITE_DATA *) GET_GUID_HOB_DATA (GuidHob);\r
609 if (FtwLastWriteData->TargetAddress == NvStorageBase) {\r
610 //\r
611 // Let FvHeader point to spare block.\r
612 //\r
613 FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) FtwLastWriteData->SpareAddress;\r
614 DEBUG ((EFI_D_INFO, "PeiVariable: NV storage is backed up in spare block: 0x%x\n", (UINTN) FtwLastWriteData->SpareAddress));\r
615 } else if ((FtwLastWriteData->TargetAddress > NvStorageBase) && (FtwLastWriteData->TargetAddress < (NvStorageBase + NvStorageSize))) {\r
616 StoreInfo->FtwLastWriteData = FtwLastWriteData;\r
617 //\r
618 // Flash NV storage from the offset is backed up in spare block.\r
619 //\r
620 BackUpOffset = (UINT32) (FtwLastWriteData->TargetAddress - NvStorageBase);\r
621 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
622 //\r
623 // At least one block data in flash NV storage is still valid, so still leave FvHeader point to NV storage base.\r
624 //\r
625 }\r
626 }\r
d6550260 627\r
628 //\r
629 // Check if the Firmware Volume is not corrupted\r
630 //\r
631 if ((FvHeader->Signature != EFI_FVH_SIGNATURE) || (!CompareGuid (&gEfiSystemNvDataFvGuid, &FvHeader->FileSystemGuid))) {\r
632 DEBUG ((EFI_D_ERROR, "Firmware Volume for Variable Store is corrupted\n"));\r
633 break;\r
634 }\r
635\r
0f7aff72
RN
636 VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINT8 *) FvHeader + FvHeader->HeaderLength);\r
637\r
77ba12cc
SZ
638 StoreInfo->AuthFlag = (BOOLEAN) (CompareGuid (&VariableStoreHeader->Signature, &gEfiAuthenticatedVariableGuid));\r
639\r
3e02ebb2
SZ
640 GuidHob = GetFirstGuidHob (&gEfiVariableIndexTableGuid);\r
641 if (GuidHob != NULL) {\r
642 StoreInfo->IndexTable = GET_GUID_HOB_DATA (GuidHob);\r
643 } else {\r
644 //\r
645 // If it's the first time to access variable region in flash, create a guid hob to record\r
646 // VAR_ADDED type variable info.\r
77ba12cc 647 // Note that as the resource of PEI phase is limited, only store the limited number of\r
3e02ebb2
SZ
648 // VAR_ADDED type variables to reduce access time.\r
649 //\r
650 StoreInfo->IndexTable = (VARIABLE_INDEX_TABLE *) BuildGuidHob (&gEfiVariableIndexTableGuid, sizeof (VARIABLE_INDEX_TABLE));\r
651 StoreInfo->IndexTable->Length = 0;\r
652 StoreInfo->IndexTable->StartPtr = GetStartPointer (VariableStoreHeader);\r
653 StoreInfo->IndexTable->EndPtr = GetEndPointer (VariableStoreHeader);\r
654 StoreInfo->IndexTable->GoneThrough = 0;\r
0f7aff72
RN
655 }\r
656 }\r
657 break;\r
de2a15ee
RN
658\r
659 default:\r
660 ASSERT (FALSE);\r
661 break;\r
0f7aff72
RN
662 }\r
663\r
3e02ebb2 664 StoreInfo->VariableStoreHeader = VariableStoreHeader;\r
0f7aff72
RN
665 return VariableStoreHeader;\r
666}\r
33479ddf 667\r
3e02ebb2
SZ
668/**\r
669 Get variable header that has consecutive content.\r
670\r
671 @param StoreInfo Pointer to variable store info structure.\r
672 @param Variable Pointer to the Variable Header.\r
673 @param VariableHeader Pointer to Pointer to the Variable Header that has consecutive content.\r
674\r
675 @retval TRUE Variable header is valid.\r
676 @retval FALSE Variable header is not valid.\r
677\r
678**/\r
679BOOLEAN\r
680GetVariableHeader (\r
681 IN VARIABLE_STORE_INFO *StoreInfo,\r
682 IN VARIABLE_HEADER *Variable,\r
683 OUT VARIABLE_HEADER **VariableHeader\r
684 )\r
685{\r
686 EFI_PHYSICAL_ADDRESS TargetAddress;\r
687 EFI_PHYSICAL_ADDRESS SpareAddress;\r
688 EFI_HOB_GUID_TYPE *GuidHob;\r
689 UINTN PartialHeaderSize;\r
690\r
6ebffb67
SZ
691 if (Variable == NULL) {\r
692 return FALSE;\r
693 }\r
694\r
77ba12cc
SZ
695 //\r
696 // First assume variable header pointed by Variable is consecutive.\r
697 //\r
3e02ebb2
SZ
698 *VariableHeader = Variable;\r
699\r
6ebffb67 700 if (StoreInfo->FtwLastWriteData != NULL) {\r
3e02ebb2
SZ
701 TargetAddress = StoreInfo->FtwLastWriteData->TargetAddress;\r
702 SpareAddress = StoreInfo->FtwLastWriteData->SpareAddress;\r
6ebffb67
SZ
703 if (((UINTN) Variable > (UINTN) SpareAddress) &&\r
704 (((UINTN) Variable - (UINTN) SpareAddress + (UINTN) TargetAddress) >= (UINTN) GetEndPointer (StoreInfo->VariableStoreHeader))) {\r
705 //\r
706 // Reach the end of variable store.\r
707 //\r
708 return FALSE;\r
709 }\r
77ba12cc 710 if (((UINTN) Variable < (UINTN) TargetAddress) && (((UINTN) Variable + GetVariableHeaderSize (StoreInfo->AuthFlag)) > (UINTN) TargetAddress)) {\r
3e02ebb2
SZ
711 //\r
712 // Variable header pointed by Variable is inconsecutive,\r
713 // create a guid hob to combine the two partial variable header content together.\r
714 //\r
715 GuidHob = GetFirstGuidHob (&gEfiCallerIdGuid);\r
716 if (GuidHob != NULL) {\r
717 *VariableHeader = (VARIABLE_HEADER *) GET_GUID_HOB_DATA (GuidHob);\r
718 } else {\r
77ba12cc 719 *VariableHeader = (VARIABLE_HEADER *) BuildGuidHob (&gEfiCallerIdGuid, GetVariableHeaderSize (StoreInfo->AuthFlag));\r
3e02ebb2
SZ
720 PartialHeaderSize = (UINTN) TargetAddress - (UINTN) Variable;\r
721 //\r
722 // Partial content is in NV storage.\r
723 //\r
724 CopyMem ((UINT8 *) *VariableHeader, (UINT8 *) Variable, PartialHeaderSize);\r
725 //\r
726 // Another partial content is in spare block.\r
727 //\r
77ba12cc 728 CopyMem ((UINT8 *) *VariableHeader + PartialHeaderSize, (UINT8 *) (UINTN) SpareAddress, GetVariableHeaderSize (StoreInfo->AuthFlag) - PartialHeaderSize);\r
3e02ebb2
SZ
729 }\r
730 }\r
6ebffb67
SZ
731 } else {\r
732 if (Variable >= GetEndPointer (StoreInfo->VariableStoreHeader)) {\r
733 //\r
734 // Reach the end of variable store.\r
735 //\r
736 return FALSE;\r
737 }\r
3e02ebb2
SZ
738 }\r
739\r
740 return IsValidVariableHeader (*VariableHeader);\r
741}\r
742\r
743/**\r
744 Get variable name or data to output buffer.\r
745\r
746 @param StoreInfo Pointer to variable store info structure.\r
747 @param NameOrData Pointer to the variable name/data that may be inconsecutive.\r
748 @param Size Variable name/data size.\r
749 @param Buffer Pointer to output buffer to hold the variable name/data.\r
750\r
751**/\r
752VOID\r
753GetVariableNameOrData (\r
754 IN VARIABLE_STORE_INFO *StoreInfo,\r
755 IN UINT8 *NameOrData,\r
756 IN UINTN Size,\r
757 OUT UINT8 *Buffer\r
758 )\r
759{\r
760 EFI_PHYSICAL_ADDRESS TargetAddress;\r
761 EFI_PHYSICAL_ADDRESS SpareAddress;\r
762 UINTN PartialSize;\r
77ba12cc 763\r
3e02ebb2
SZ
764 if (StoreInfo->FtwLastWriteData != NULL) {\r
765 TargetAddress = StoreInfo->FtwLastWriteData->TargetAddress;\r
766 SpareAddress = StoreInfo->FtwLastWriteData->SpareAddress;\r
767 if (((UINTN) NameOrData < (UINTN) TargetAddress) && (((UINTN) NameOrData + Size) > (UINTN) TargetAddress)) {\r
768 //\r
769 // Variable name/data is inconsecutive.\r
770 //\r
771 PartialSize = (UINTN) TargetAddress - (UINTN) NameOrData;\r
772 //\r
773 // Partial content is in NV storage.\r
774 //\r
775 CopyMem (Buffer, NameOrData, PartialSize);\r
776 //\r
777 // Another partial content is in spare block.\r
778 //\r
779 CopyMem (Buffer + PartialSize, (UINT8 *) (UINTN) SpareAddress, Size - PartialSize);\r
780 return;\r
781 }\r
782 }\r
783\r
784 //\r
785 // Variable name/data is consecutive.\r
786 //\r
787 CopyMem (Buffer, NameOrData, Size);\r
788}\r
789\r
33479ddf 790/**\r
0f7aff72 791 Find the variable in the specified variable store.\r
33479ddf 792\r
3e02ebb2 793 @param StoreInfo Pointer to the store info structure.\r
0f7aff72
RN
794 @param VariableName Name of the variable to be found\r
795 @param VendorGuid Vendor GUID to be found.\r
796 @param PtrTrack Variable Track Pointer structure that contains Variable Information.\r
33479ddf 797\r
798 @retval EFI_SUCCESS Variable found successfully\r
799 @retval EFI_NOT_FOUND Variable not found\r
800 @retval EFI_INVALID_PARAMETER Invalid variable name\r
801\r
802**/\r
8d3a5c82 803EFI_STATUS\r
0f7aff72 804FindVariableEx (\r
3e02ebb2 805 IN VARIABLE_STORE_INFO *StoreInfo,\r
0f7aff72
RN
806 IN CONST CHAR16 *VariableName,\r
807 IN CONST EFI_GUID *VendorGuid,\r
808 OUT VARIABLE_POINTER_TRACK *PtrTrack\r
8d3a5c82 809 )\r
8d3a5c82 810{\r
8d3a5c82 811 VARIABLE_HEADER *Variable;\r
841014ba 812 VARIABLE_HEADER *LastVariable;\r
8d3a5c82 813 VARIABLE_HEADER *MaxIndex;\r
0f7aff72
RN
814 UINTN Index;\r
815 UINTN Offset;\r
841014ba 816 BOOLEAN StopRecord;\r
932e0f66 817 VARIABLE_HEADER *InDeletedVariable;\r
3e02ebb2
SZ
818 VARIABLE_STORE_HEADER *VariableStoreHeader;\r
819 VARIABLE_INDEX_TABLE *IndexTable;\r
820 VARIABLE_HEADER *VariableHeader;\r
821\r
822 VariableStoreHeader = StoreInfo->VariableStoreHeader;\r
8d3a5c82 823\r
0f7aff72 824 if (VariableStoreHeader == NULL) {\r
8d3a5c82 825 return EFI_INVALID_PARAMETER;\r
826 }\r
0f7aff72
RN
827\r
828 if (GetVariableStoreStatus (VariableStoreHeader) != EfiValid) {\r
829 return EFI_UNSUPPORTED;\r
830 }\r
831\r
832 if (~VariableStoreHeader->Size == 0) {\r
833 return EFI_NOT_FOUND;\r
834 }\r
835\r
3e02ebb2 836 IndexTable = StoreInfo->IndexTable;\r
0f7aff72
RN
837 PtrTrack->StartPtr = GetStartPointer (VariableStoreHeader);\r
838 PtrTrack->EndPtr = GetEndPointer (VariableStoreHeader);\r
839\r
932e0f66
SZ
840 InDeletedVariable = NULL;\r
841\r
8d3a5c82 842 //\r
843 // No Variable Address equals zero, so 0 as initial value is safe.\r
844 //\r
0f7aff72 845 MaxIndex = NULL;\r
3e02ebb2 846 VariableHeader = NULL;\r
8d3a5c82 847\r
0f7aff72 848 if (IndexTable != NULL) {\r
841014ba 849 //\r
0f7aff72
RN
850 // traverse the variable index table to look for varible.\r
851 // The IndexTable->Index[Index] records the distance of two neighbouring VAR_ADDED type variables.\r
841014ba 852 //\r
0f7aff72
RN
853 for (Offset = 0, Index = 0; Index < IndexTable->Length; Index++) {\r
854 ASSERT (Index < sizeof (IndexTable->Index) / sizeof (IndexTable->Index[0]));\r
855 Offset += IndexTable->Index[Index];\r
856 MaxIndex = (VARIABLE_HEADER *) ((UINT8 *) IndexTable->StartPtr + Offset);\r
3e02ebb2
SZ
857 GetVariableHeader (StoreInfo, MaxIndex, &VariableHeader);\r
858 if (CompareWithValidVariable (StoreInfo, MaxIndex, VariableHeader, VariableName, VendorGuid, PtrTrack) == EFI_SUCCESS) {\r
859 if (VariableHeader->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {\r
932e0f66
SZ
860 InDeletedVariable = PtrTrack->CurrPtr;\r
861 } else {\r
862 return EFI_SUCCESS;\r
863 }\r
8d3a5c82 864 }\r
865 }\r
866\r
33479ddf 867 if (IndexTable->GoneThrough != 0) {\r
0f7aff72 868 //\r
932e0f66 869 // If the table has all the existing variables indexed, return.\r
0f7aff72 870 //\r
932e0f66
SZ
871 PtrTrack->CurrPtr = InDeletedVariable;\r
872 return (PtrTrack->CurrPtr == NULL) ? EFI_NOT_FOUND : EFI_SUCCESS;\r
8d3a5c82 873 }\r
874 }\r
0f7aff72 875\r
8d3a5c82 876 if (MaxIndex != NULL) {\r
0f7aff72
RN
877 //\r
878 // HOB exists but the variable cannot be found in HOB\r
879 // If not found in HOB, then let's start from the MaxIndex we've found.\r
880 //\r
3e02ebb2 881 Variable = GetNextVariablePtr (StoreInfo, MaxIndex, VariableHeader);\r
841014ba 882 LastVariable = MaxIndex;\r
8d3a5c82 883 } else {\r
0f7aff72
RN
884 //\r
885 // Start Pointers for the variable.\r
886 // Actual Data Pointer where data can be written.\r
887 //\r
888 Variable = PtrTrack->StartPtr;\r
889 LastVariable = PtrTrack->StartPtr;\r
8d3a5c82 890 }\r
0f7aff72 891\r
8d3a5c82 892 //\r
932e0f66 893 // Find the variable by walk through variable store\r
8d3a5c82 894 //\r
0f7aff72 895 StopRecord = FALSE;\r
3e02ebb2
SZ
896 while (GetVariableHeader (StoreInfo, Variable, &VariableHeader)) {\r
897 if (VariableHeader->State == VAR_ADDED || VariableHeader->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {\r
8d3a5c82 898 //\r
899 // Record Variable in VariableIndex HOB\r
900 //\r
0f7aff72
RN
901 if ((IndexTable != NULL) && !StopRecord) {\r
902 Offset = (UINTN) Variable - (UINTN) LastVariable;\r
903 if ((Offset > 0x0FFFF) || (IndexTable->Length == sizeof (IndexTable->Index) / sizeof (IndexTable->Index[0]))) {\r
904 //\r
905 // Stop to record if the distance of two neighbouring VAR_ADDED variable is larger than the allowable scope(UINT16),\r
906 // or the record buffer is full.\r
907 //\r
841014ba 908 StopRecord = TRUE;\r
0f7aff72 909 } else {\r
841014ba 910 IndexTable->Index[IndexTable->Length++] = (UINT16) Offset;\r
0f7aff72 911 LastVariable = Variable;\r
841014ba 912 }\r
841014ba 913 }\r
914\r
3e02ebb2
SZ
915 if (CompareWithValidVariable (StoreInfo, Variable, VariableHeader, VariableName, VendorGuid, PtrTrack) == EFI_SUCCESS) {\r
916 if (VariableHeader->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {\r
932e0f66
SZ
917 InDeletedVariable = PtrTrack->CurrPtr;\r
918 } else {\r
919 return EFI_SUCCESS;\r
920 }\r
8d3a5c82 921 }\r
922 }\r
923\r
3e02ebb2 924 Variable = GetNextVariablePtr (StoreInfo, Variable, VariableHeader);\r
8d3a5c82 925 }\r
926 //\r
927 // If gone through the VariableStore, that means we never find in Firmware any more.\r
928 //\r
0f7aff72 929 if ((IndexTable != NULL) && !StopRecord) {\r
8d3a5c82 930 IndexTable->GoneThrough = 1;\r
931 }\r
932\r
932e0f66 933 PtrTrack->CurrPtr = InDeletedVariable;\r
8d3a5c82 934\r
932e0f66 935 return (PtrTrack->CurrPtr == NULL) ? EFI_NOT_FOUND : EFI_SUCCESS;\r
8d3a5c82 936}\r
937\r
0f7aff72
RN
938/**\r
939 Find the variable in HOB and Non-Volatile variable storages.\r
940\r
941 @param VariableName Name of the variable to be found\r
942 @param VendorGuid Vendor GUID to be found.\r
943 @param PtrTrack Variable Track Pointer structure that contains Variable Information.\r
3e02ebb2 944 @param StoreInfo Return the store info.\r
0f7aff72
RN
945\r
946 @retval EFI_SUCCESS Variable found successfully\r
947 @retval EFI_NOT_FOUND Variable not found\r
948 @retval EFI_INVALID_PARAMETER Invalid variable name\r
949**/\r
950EFI_STATUS\r
951FindVariable (\r
952 IN CONST CHAR16 *VariableName,\r
953 IN CONST EFI_GUID *VendorGuid,\r
3e02ebb2
SZ
954 OUT VARIABLE_POINTER_TRACK *PtrTrack,\r
955 OUT VARIABLE_STORE_INFO *StoreInfo\r
0f7aff72
RN
956 )\r
957{\r
958 EFI_STATUS Status;\r
0f7aff72
RN
959 VARIABLE_STORE_TYPE Type;\r
960\r
961 if (VariableName[0] != 0 && VendorGuid == NULL) {\r
962 return EFI_INVALID_PARAMETER;\r
963 }\r
964\r
965 for (Type = (VARIABLE_STORE_TYPE) 0; Type < VariableStoreTypeMax; Type++) {\r
3e02ebb2 966 GetVariableStore (Type, StoreInfo);\r
0f7aff72 967 Status = FindVariableEx (\r
3e02ebb2 968 StoreInfo,\r
0f7aff72 969 VariableName,\r
77ba12cc 970 VendorGuid,\r
0f7aff72
RN
971 PtrTrack\r
972 );\r
973 if (!EFI_ERROR (Status)) {\r
974 return Status;\r
975 }\r
976 }\r
977\r
978 return EFI_NOT_FOUND;\r
979}\r
980\r
33479ddf 981/**\r
982 This service retrieves a variable's value using its name and GUID.\r
983\r
77ba12cc 984 Read the specified variable from the UEFI variable store. If the Data\r
33479ddf 985 buffer is too small to hold the contents of the variable, the error\r
986 EFI_BUFFER_TOO_SMALL is returned and DataSize is set to the required buffer\r
987 size to obtain the data.\r
988\r
989 @param This A pointer to this instance of the EFI_PEI_READ_ONLY_VARIABLE2_PPI.\r
990 @param VariableName A pointer to a null-terminated string that is the variable's name.\r
991 @param VariableGuid A pointer to an EFI_GUID that is the variable's GUID. The combination of\r
992 VariableGuid and VariableName must be unique.\r
993 @param Attributes If non-NULL, on return, points to the variable's attributes.\r
994 @param DataSize On entry, points to the size in bytes of the Data buffer.\r
995 On return, points to the size of the data returned in Data.\r
996 @param Data Points to the buffer which will hold the returned variable value.\r
9977995e 997 May be NULL with a zero DataSize in order to determine the size of the buffer needed.\r
33479ddf 998\r
999 @retval EFI_SUCCESS The variable was read successfully.\r
9977995e 1000 @retval EFI_NOT_FOUND The variable was be found.\r
77ba12cc
SZ
1001 @retval EFI_BUFFER_TOO_SMALL The DataSize is too small for the resulting data.\r
1002 DataSize is updated with the size required for\r
33479ddf 1003 the specified variable.\r
1004 @retval EFI_INVALID_PARAMETER VariableName, VariableGuid, DataSize or Data is NULL.\r
1005 @retval EFI_DEVICE_ERROR The variable could not be retrieved because of a device error.\r
1006\r
1007**/\r
8d3a5c82 1008EFI_STATUS\r
1009EFIAPI\r
1010PeiGetVariable (\r
1011 IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI *This,\r
1012 IN CONST CHAR16 *VariableName,\r
1013 IN CONST EFI_GUID *VariableGuid,\r
1014 OUT UINT32 *Attributes,\r
1015 IN OUT UINTN *DataSize,\r
9977995e 1016 OUT VOID *Data OPTIONAL\r
8d3a5c82 1017 )\r
8d3a5c82 1018{\r
1019 VARIABLE_POINTER_TRACK Variable;\r
1020 UINTN VarDataSize;\r
1021 EFI_STATUS Status;\r
3e02ebb2
SZ
1022 VARIABLE_STORE_INFO StoreInfo;\r
1023 VARIABLE_HEADER *VariableHeader;\r
8d3a5c82 1024\r
01f352a7 1025 if (VariableName == NULL || VariableGuid == NULL || DataSize == NULL) {\r
8d3a5c82 1026 return EFI_INVALID_PARAMETER;\r
1027 }\r
4249fa76 1028\r
e19eab61
SZ
1029 if (VariableName[0] == 0) {\r
1030 return EFI_NOT_FOUND;\r
1031 }\r
1032\r
eb774e2e
SZ
1033 VariableHeader = NULL;\r
1034\r
8d3a5c82 1035 //\r
1036 // Find existing variable\r
1037 //\r
3e02ebb2 1038 Status = FindVariable (VariableName, VariableGuid, &Variable, &StoreInfo);\r
0f7aff72 1039 if (EFI_ERROR (Status)) {\r
8d3a5c82 1040 return Status;\r
1041 }\r
3e02ebb2
SZ
1042 GetVariableHeader (&StoreInfo, Variable.CurrPtr, &VariableHeader);\r
1043\r
8d3a5c82 1044 //\r
1045 // Get data size\r
1046 //\r
77ba12cc 1047 VarDataSize = DataSizeOfVariable (VariableHeader, StoreInfo.AuthFlag);\r
8d3a5c82 1048 if (*DataSize >= VarDataSize) {\r
39aea48d 1049 if (Data == NULL) {\r
1050 return EFI_INVALID_PARAMETER;\r
1051 }\r
1052\r
77ba12cc 1053 GetVariableNameOrData (&StoreInfo, GetVariableDataPtr (Variable.CurrPtr, VariableHeader, StoreInfo.AuthFlag), VarDataSize, Data);\r
8d3a5c82 1054\r
1055 if (Attributes != NULL) {\r
3e02ebb2 1056 *Attributes = VariableHeader->Attributes;\r
8d3a5c82 1057 }\r
1058\r
1059 *DataSize = VarDataSize;\r
1060 return EFI_SUCCESS;\r
1061 } else {\r
1062 *DataSize = VarDataSize;\r
1063 return EFI_BUFFER_TOO_SMALL;\r
1064 }\r
1065}\r
1066\r
33479ddf 1067/**\r
1068 Return the next variable name and GUID.\r
1069\r
77ba12cc
SZ
1070 This function is called multiple times to retrieve the VariableName\r
1071 and VariableGuid of all variables currently available in the system.\r
1072 On each call, the previous results are passed into the interface,\r
1073 and, on return, the interface returns the data for the next\r
1074 interface. When the entire variable list has been returned,\r
33479ddf 1075 EFI_NOT_FOUND is returned.\r
1076\r
1077 @param This A pointer to this instance of the EFI_PEI_READ_ONLY_VARIABLE2_PPI.\r
1078\r
1079 @param VariableNameSize On entry, points to the size of the buffer pointed to by VariableName.\r
f7dab9fa 1080 On return, the size of the variable name buffer.\r
33479ddf 1081 @param VariableName On entry, a pointer to a null-terminated string that is the variable's name.\r
1082 On return, points to the next variable's null-terminated name string.\r
77ba12cc 1083 @param VariableGuid On entry, a pointer to an EFI_GUID that is the variable's GUID.\r
33479ddf 1084 On return, a pointer to the next variable's GUID.\r
1085\r
1086 @retval EFI_SUCCESS The variable was read successfully.\r
1087 @retval EFI_NOT_FOUND The variable could not be found.\r
1088 @retval EFI_BUFFER_TOO_SMALL The VariableNameSize is too small for the resulting\r
1089 data. VariableNameSize is updated with the size\r
1090 required for the specified variable.\r
1091 @retval EFI_INVALID_PARAMETER VariableName, VariableGuid or\r
1092 VariableNameSize is NULL.\r
1093 @retval EFI_DEVICE_ERROR The variable could not be retrieved because of a device error.\r
1094\r
1095**/\r
8d3a5c82 1096EFI_STATUS\r
1097EFIAPI\r
1098PeiGetNextVariableName (\r
1099 IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI *This,\r
1100 IN OUT UINTN *VariableNameSize,\r
1101 IN OUT CHAR16 *VariableName,\r
1102 IN OUT EFI_GUID *VariableGuid\r
1103 )\r
8d3a5c82 1104{\r
0f7aff72 1105 VARIABLE_STORE_TYPE Type;\r
8d3a5c82 1106 VARIABLE_POINTER_TRACK Variable;\r
0f7aff72 1107 VARIABLE_POINTER_TRACK VariableInHob;\r
932e0f66 1108 VARIABLE_POINTER_TRACK VariablePtrTrack;\r
8d3a5c82 1109 UINTN VarNameSize;\r
1110 EFI_STATUS Status;\r
0f7aff72 1111 VARIABLE_STORE_HEADER *VariableStoreHeader[VariableStoreTypeMax];\r
3e02ebb2
SZ
1112 VARIABLE_HEADER *VariableHeader;\r
1113 VARIABLE_STORE_INFO StoreInfo;\r
1114 VARIABLE_STORE_INFO StoreInfoForNv;\r
1115 VARIABLE_STORE_INFO StoreInfoForHob;\r
8d3a5c82 1116\r
01f352a7 1117 if (VariableName == NULL || VariableGuid == NULL || VariableNameSize == NULL) {\r
8d3a5c82 1118 return EFI_INVALID_PARAMETER;\r
1119 }\r
1120\r
eb774e2e
SZ
1121 VariableHeader = NULL;\r
1122\r
3e02ebb2 1123 Status = FindVariable (VariableName, VariableGuid, &Variable, &StoreInfo);\r
8d3a5c82 1124 if (Variable.CurrPtr == NULL || Status != EFI_SUCCESS) {\r
1125 return Status;\r
1126 }\r
1127\r
1128 if (VariableName[0] != 0) {\r
1129 //\r
1130 // If variable name is not NULL, get next variable\r
1131 //\r
3e02ebb2
SZ
1132 GetVariableHeader (&StoreInfo, Variable.CurrPtr, &VariableHeader);\r
1133 Variable.CurrPtr = GetNextVariablePtr (&StoreInfo, Variable.CurrPtr, VariableHeader);\r
8d3a5c82 1134 }\r
1135\r
3e02ebb2
SZ
1136 VariableStoreHeader[VariableStoreTypeHob] = GetVariableStore (VariableStoreTypeHob, &StoreInfoForHob);\r
1137 VariableStoreHeader[VariableStoreTypeNv] = GetVariableStore (VariableStoreTypeNv, &StoreInfoForNv);\r
9cad030b 1138\r
0f7aff72
RN
1139 while (TRUE) {\r
1140 //\r
1141 // Switch from HOB to Non-Volatile.\r
1142 //\r
3e02ebb2 1143 while (!GetVariableHeader (&StoreInfo, Variable.CurrPtr, &VariableHeader)) {\r
0f7aff72
RN
1144 //\r
1145 // Find current storage index\r
1146 //\r
1147 for (Type = (VARIABLE_STORE_TYPE) 0; Type < VariableStoreTypeMax; Type++) {\r
1148 if ((VariableStoreHeader[Type] != NULL) && (Variable.StartPtr == GetStartPointer (VariableStoreHeader[Type]))) {\r
1149 break;\r
1150 }\r
1151 }\r
1152 ASSERT (Type < VariableStoreTypeMax);\r
1153 //\r
1154 // Switch to next storage\r
1155 //\r
1156 for (Type++; Type < VariableStoreTypeMax; Type++) {\r
1157 if (VariableStoreHeader[Type] != NULL) {\r
1158 break;\r
1159 }\r
1160 }\r
1161 //\r
77ba12cc 1162 // Capture the case that\r
0f7aff72
RN
1163 // 1. current storage is the last one, or\r
1164 // 2. no further storage\r
1165 //\r
1166 if (Type == VariableStoreTypeMax) {\r
1167 return EFI_NOT_FOUND;\r
1168 }\r
1169 Variable.StartPtr = GetStartPointer (VariableStoreHeader[Type]);\r
1170 Variable.EndPtr = GetEndPointer (VariableStoreHeader[Type]);\r
1171 Variable.CurrPtr = Variable.StartPtr;\r
3e02ebb2 1172 GetVariableStore (Type, &StoreInfo);\r
0f7aff72 1173 }\r
8d3a5c82 1174\r
3e02ebb2
SZ
1175 if (VariableHeader->State == VAR_ADDED || VariableHeader->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {\r
1176 if (VariableHeader->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {\r
932e0f66
SZ
1177 //\r
1178 // If it is a IN_DELETED_TRANSITION variable,\r
1179 // and there is also a same ADDED one at the same time,\r
1180 // don't return it.\r
1181 //\r
932e0f66 1182 Status = FindVariableEx (\r
3e02ebb2 1183 &StoreInfo,\r
77ba12cc
SZ
1184 GetVariableNamePtr (Variable.CurrPtr, StoreInfo.AuthFlag),\r
1185 GetVendorGuidPtr (VariableHeader, StoreInfo.AuthFlag),\r
932e0f66
SZ
1186 &VariablePtrTrack\r
1187 );\r
3e02ebb2
SZ
1188 if (!EFI_ERROR (Status) && VariablePtrTrack.CurrPtr != Variable.CurrPtr) {\r
1189 Variable.CurrPtr = GetNextVariablePtr (&StoreInfo, Variable.CurrPtr, VariableHeader);\r
932e0f66
SZ
1190 continue;\r
1191 }\r
1192 }\r
8d3a5c82 1193\r
0f7aff72
RN
1194 //\r
1195 // Don't return NV variable when HOB overrides it\r
1196 //\r
1197 if ((VariableStoreHeader[VariableStoreTypeHob] != NULL) && (VariableStoreHeader[VariableStoreTypeNv] != NULL) &&\r
1198 (Variable.StartPtr == GetStartPointer (VariableStoreHeader[VariableStoreTypeNv]))\r
1199 ) {\r
1200 Status = FindVariableEx (\r
3e02ebb2 1201 &StoreInfoForHob,\r
77ba12cc
SZ
1202 GetVariableNamePtr (Variable.CurrPtr, StoreInfo.AuthFlag),\r
1203 GetVendorGuidPtr (VariableHeader, StoreInfo.AuthFlag),\r
0f7aff72
RN
1204 &VariableInHob\r
1205 );\r
1206 if (!EFI_ERROR (Status)) {\r
3e02ebb2 1207 Variable.CurrPtr = GetNextVariablePtr (&StoreInfo, Variable.CurrPtr, VariableHeader);\r
0f7aff72 1208 continue;\r
8d3a5c82 1209 }\r
0f7aff72 1210 }\r
8d3a5c82 1211\r
77ba12cc 1212 VarNameSize = NameSizeOfVariable (VariableHeader, StoreInfo.AuthFlag);\r
0f7aff72
RN
1213 ASSERT (VarNameSize != 0);\r
1214\r
1215 if (VarNameSize <= *VariableNameSize) {\r
77ba12cc 1216 GetVariableNameOrData (&StoreInfo, (UINT8 *) GetVariableNamePtr (Variable.CurrPtr, StoreInfo.AuthFlag), VarNameSize, (UINT8 *) VariableName);\r
0f7aff72 1217\r
77ba12cc 1218 CopyMem (VariableGuid, GetVendorGuidPtr (VariableHeader, StoreInfo.AuthFlag), sizeof (EFI_GUID));\r
0f7aff72
RN
1219\r
1220 Status = EFI_SUCCESS;\r
8d3a5c82 1221 } else {\r
0f7aff72 1222 Status = EFI_BUFFER_TOO_SMALL;\r
8d3a5c82 1223 }\r
0f7aff72
RN
1224\r
1225 *VariableNameSize = VarNameSize;\r
1226 //\r
1227 // Variable is found\r
1228 //\r
1229 return Status;\r
8d3a5c82 1230 } else {\r
3e02ebb2 1231 Variable.CurrPtr = GetNextVariablePtr (&StoreInfo, Variable.CurrPtr, VariableHeader);\r
8d3a5c82 1232 }\r
1233 }\r
8d3a5c82 1234}\r