]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Variable/Pei/Variable.c
judge recovery mode at ReadOnlyVariable2Ppi interface. if yes, then return EFI_NOT_FOUND
[mirror_edk2.git] / MdeModulePkg / Universal / Variable / Pei / Variable.c
CommitLineData
504214c4
LG
1/** @file\r
2\r
3 Implement ReadOnly Variable Services required by PEIM and install\r
02c57ded 4 PEI ReadOnly Varaiable2 PPI. These services operates the non volatile storage space.\r
8d3a5c82 5\r
27ee669c 6Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>\r
e5eed7d3 7This program and the accompanying materials\r
8d3a5c82 8are licensed and made available under the terms and conditions of the BSD License\r
9which accompanies this distribution. The full text of the license may be found at\r
10http://opensource.org/licenses/bsd-license.php\r
11\r
12THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
13WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
14Module Name:\r
15\r
504214c4 16**/\r
8d3a5c82 17\r
18\r
19#include "Variable.h"\r
20\r
21//\r
22// Module globals\r
23//\r
fe1e36e5 24EFI_PEI_READ_ONLY_VARIABLE2_PPI mVariablePpi = {\r
8d3a5c82 25 PeiGetVariable,\r
26 PeiGetNextVariableName\r
27};\r
28\r
fe1e36e5 29EFI_PEI_PPI_DESCRIPTOR mPpiListVariable = {\r
8d3a5c82 30 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
31 &gEfiPeiReadOnlyVariable2PpiGuid,\r
32 &mVariablePpi\r
33};\r
34\r
4249fa76 35EFI_GUID mEfiVariableIndexTableGuid = EFI_VARIABLE_INDEX_TABLE_GUID;\r
27ee669c 36\r
27ee669c 37\r
4249fa76 38/**\r
39 Check if it runs in Recovery mode.\r
40 \r
41 @param PeiServices General purpose services available to every PEIM.\r
42\r
43 @retval TRUE It's in Recovery mode.\r
44 @retval FALSE It's not in Recovery mode.\r
8d3a5c82 45\r
4249fa76 46**/\r
47BOOLEAN\r
48IsInRecoveryMode (\r
49 IN CONST EFI_PEI_SERVICES **PeiServices\r
50 )\r
51{\r
52 EFI_STATUS Status;\r
53 EFI_BOOT_MODE BootMode;\r
54\r
55 Status = (*PeiServices)->GetBootMode (PeiServices, &BootMode);\r
56 ASSERT_EFI_ERROR (Status);\r
57 \r
58 if (BootMode == BOOT_IN_RECOVERY_MODE) {\r
59 return TRUE;\r
60 }\r
61 return FALSE;\r
62}\r
8d3a5c82 63\r
33479ddf 64/**\r
8d3a5c82 65 Provide the functionality of the variable services.\r
33479ddf 66 \r
721dfef3 67 @param FileHandle Handle of the file being invoked. \r
68 Type EFI_PEI_FILE_HANDLE is defined in FfsFindNextFile().\r
33479ddf 69 @param PeiServices General purpose services available to every PEIM.\r
8d3a5c82 70\r
33479ddf 71 @retval EFI_SUCCESS If the interface could be successfully installed\r
72 @retval Others Returned from PeiServicesInstallPpi()\r
8d3a5c82 73\r
33479ddf 74**/\r
75EFI_STATUS\r
76EFIAPI\r
77PeimInitializeVariableServices (\r
78 IN EFI_PEI_FILE_HANDLE FileHandle,\r
79 IN CONST EFI_PEI_SERVICES **PeiServices\r
80 )\r
8d3a5c82 81{\r
33479ddf 82 return PeiServicesInstallPpi (&mPpiListVariable);\r
8d3a5c82 83}\r
84\r
33479ddf 85/**\r
9cad030b 86\r
7c80e839 87 Gets the pointer to the first variable header in given variable store area.\r
9cad030b 88\r
7c80e839 89 @param VarStoreHeader Pointer to the Variable Store Header.\r
90\r
91 @return Pointer to the first variable header\r
9cad030b 92\r
33479ddf 93**/\r
94VARIABLE_HEADER *\r
95GetStartPointer (\r
96 IN VARIABLE_STORE_HEADER *VarStoreHeader\r
97 )\r
9cad030b 98{\r
99 //\r
100 // The end of variable store\r
101 //\r
102 return (VARIABLE_HEADER *) HEADER_ALIGN (VarStoreHeader + 1);\r
103}\r
104\r
9cad030b 105\r
33479ddf 106/**\r
107 This code gets the pointer to the last variable memory pointer byte.\r
9cad030b 108\r
33479ddf 109 @param VarStoreHeader Pointer to the Variable Store Header.\r
9cad030b 110\r
33479ddf 111 @return VARIABLE_HEADER* pointer to last unavailable Variable Header.\r
9cad030b 112\r
33479ddf 113**/\r
114VARIABLE_HEADER *\r
115GetEndPointer (\r
116 IN VARIABLE_STORE_HEADER *VarStoreHeader\r
117 )\r
9cad030b 118{\r
119 //\r
120 // The end of variable store\r
121 //\r
122 return (VARIABLE_HEADER *) HEADER_ALIGN ((UINTN) VarStoreHeader + VarStoreHeader->Size);\r
123}\r
124\r
8d3a5c82 125\r
33479ddf 126/**\r
8d3a5c82 127 This code checks if variable header is valid or not.\r
128\r
33479ddf 129 @param Variable Pointer to the Variable Header.\r
8d3a5c82 130\r
33479ddf 131 @retval TRUE Variable header is valid.\r
132 @retval FALSE Variable header is not valid.\r
8d3a5c82 133\r
33479ddf 134**/\r
135BOOLEAN\r
136IsValidVariableHeader (\r
137 IN VARIABLE_HEADER *Variable\r
138 )\r
8d3a5c82 139{\r
130e2569 140 if (Variable == NULL || Variable->StartId != VARIABLE_DATA ) {\r
141 return FALSE;\r
142 }\r
143\r
144 return TRUE;\r
8d3a5c82 145}\r
146\r
130e2569 147\r
33479ddf 148/**\r
130e2569 149 This code gets the size of name of variable.\r
150\r
33479ddf 151 @param Variable Pointer to the Variable Header.\r
130e2569 152\r
33479ddf 153 @return Size of variable in bytes in type UINTN.\r
130e2569 154\r
33479ddf 155**/\r
156UINTN\r
157NameSizeOfVariable (\r
158 IN VARIABLE_HEADER *Variable\r
159 )\r
130e2569 160{\r
161 if (Variable->State == (UINT8) (-1) ||\r
7c80e839 162 Variable->DataSize == (UINT32) (-1) ||\r
163 Variable->NameSize == (UINT32) (-1) ||\r
164 Variable->Attributes == (UINT32) (-1)) {\r
130e2569 165 return 0;\r
166 }\r
167 return (UINTN) Variable->NameSize;\r
168}\r
169\r
130e2569 170\r
33479ddf 171/**\r
172 This code gets the size of data of variable.\r
130e2569 173\r
33479ddf 174 @param Variable Pointer to the Variable Header.\r
130e2569 175\r
33479ddf 176 @return Size of variable in bytes in type UINTN.\r
130e2569 177\r
33479ddf 178**/\r
179UINTN\r
180DataSizeOfVariable (\r
181 IN VARIABLE_HEADER *Variable\r
182 )\r
130e2569 183{\r
7c80e839 184 if (Variable->State == (UINT8) (-1) ||\r
185 Variable->DataSize == (UINT32) (-1) ||\r
186 Variable->NameSize == (UINT32) (-1) ||\r
187 Variable->Attributes == (UINT32) (-1)) {\r
130e2569 188 return 0;\r
189 }\r
190 return (UINTN) Variable->DataSize;\r
191}\r
192\r
33479ddf 193/**\r
130e2569 194 This code gets the pointer to the variable name.\r
8d3a5c82 195\r
33479ddf 196 @param Variable Pointer to the Variable Header.\r
130e2569 197\r
33479ddf 198 @return A CHAR16* pointer to Variable Name.\r
130e2569 199\r
33479ddf 200**/\r
201CHAR16 *\r
202GetVariableNamePtr (\r
203 IN VARIABLE_HEADER *Variable\r
204 )\r
130e2569 205{\r
206\r
207 return (CHAR16 *) (Variable + 1);\r
208}\r
209\r
210\r
33479ddf 211/**\r
130e2569 212 This code gets the pointer to the variable data.\r
213\r
33479ddf 214 @param Variable Pointer to the Variable Header.\r
130e2569 215\r
33479ddf 216 @return A UINT8* pointer to Variable Data.\r
130e2569 217\r
33479ddf 218**/\r
219UINT8 *\r
220GetVariableDataPtr (\r
221 IN VARIABLE_HEADER *Variable\r
222 )\r
130e2569 223{\r
224 UINTN Value;\r
225 \r
226 //\r
227 // Be careful about pad size for alignment\r
228 //\r
229 Value = (UINTN) GetVariableNamePtr (Variable);\r
230 Value += NameSizeOfVariable (Variable);\r
231 Value += GET_PAD_SIZE (NameSizeOfVariable (Variable));\r
232\r
233 return (UINT8 *) Value;\r
234}\r
235\r
130e2569 236\r
33479ddf 237/**\r
130e2569 238 This code gets the pointer to the next variable header.\r
239\r
33479ddf 240 @param Variable Pointer to the Variable Header.\r
130e2569 241\r
33479ddf 242 @return A VARIABLE_HEADER* pointer to next variable header.\r
8d3a5c82 243\r
33479ddf 244**/\r
245VARIABLE_HEADER *\r
246GetNextVariablePtr (\r
247 IN VARIABLE_HEADER *Variable\r
248 )\r
8d3a5c82 249{\r
130e2569 250 UINTN Value;\r
251\r
252 if (!IsValidVariableHeader (Variable)) {\r
253 return NULL;\r
8d3a5c82 254 }\r
255\r
130e2569 256 Value = (UINTN) GetVariableDataPtr (Variable);\r
257 Value += DataSizeOfVariable (Variable);\r
258 Value += GET_PAD_SIZE (DataSizeOfVariable (Variable));\r
259\r
260 //\r
261 // Be careful about pad size for alignment\r
262 //\r
263 return (VARIABLE_HEADER *) HEADER_ALIGN (Value);\r
8d3a5c82 264}\r
265\r
33479ddf 266/**\r
267 This code gets the pointer to the variable name.\r
268\r
269 @param VarStoreHeader Pointer to the Variable Store Header.\r
270\r
271 @retval EfiRaw Variable store is raw\r
272 @retval EfiValid Variable store is valid\r
273 @retval EfiInvalid Variable store is invalid\r
130e2569 274\r
33479ddf 275**/\r
8d3a5c82 276VARIABLE_STORE_STATUS\r
8d3a5c82 277GetVariableStoreStatus (\r
278 IN VARIABLE_STORE_HEADER *VarStoreHeader\r
279 )\r
8d3a5c82 280{\r
3709c4cd 281 \r
282 if (CompareGuid (&VarStoreHeader->Signature, &gEfiVariableGuid) &&\r
8d3a5c82 283 VarStoreHeader->Format == VARIABLE_STORE_FORMATTED &&\r
284 VarStoreHeader->State == VARIABLE_STORE_HEALTHY\r
285 ) {\r
286\r
287 return EfiValid;\r
288 }\r
289\r
3709c4cd 290 if (((UINT32 *)(&VarStoreHeader->Signature))[0] == 0xffffffff &&\r
291 ((UINT32 *)(&VarStoreHeader->Signature))[1] == 0xffffffff &&\r
292 ((UINT32 *)(&VarStoreHeader->Signature))[2] == 0xffffffff &&\r
293 ((UINT32 *)(&VarStoreHeader->Signature))[3] == 0xffffffff &&\r
8d3a5c82 294 VarStoreHeader->Size == 0xffffffff &&\r
295 VarStoreHeader->Format == 0xff &&\r
296 VarStoreHeader->State == 0xff\r
297 ) {\r
298\r
299 return EfiRaw;\r
300 } else {\r
301 return EfiInvalid;\r
302 }\r
303}\r
304\r
33479ddf 305\r
306/**\r
307 This function compares a variable with variable entries in database.\r
308\r
309 @param Variable Pointer to the variable in our database\r
310 @param VariableName Name of the variable to compare to 'Variable'\r
311 @param VendorGuid GUID of the variable to compare to 'Variable'\r
312 @param PtrTrack Variable Track Pointer structure that contains Variable Information.\r
313\r
314 @retval EFI_SUCCESS Found match variable\r
315 @retval EFI_NOT_FOUND Variable not found\r
316\r
317**/\r
8d3a5c82 318EFI_STATUS\r
319CompareWithValidVariable (\r
320 IN VARIABLE_HEADER *Variable,\r
321 IN CONST CHAR16 *VariableName,\r
322 IN CONST EFI_GUID *VendorGuid,\r
323 OUT VARIABLE_POINTER_TRACK *PtrTrack\r
324 )\r
8d3a5c82 325{\r
130e2569 326 VOID *Point;\r
327\r
8d3a5c82 328 if (VariableName[0] == 0) {\r
329 PtrTrack->CurrPtr = Variable;\r
330 return EFI_SUCCESS;\r
331 } else {\r
332 //\r
333 // Don't use CompareGuid function here for performance reasons.\r
334 // Instead we compare the GUID a UINT32 at a time and branch\r
335 // on the first failed comparison.\r
336 //\r
337 if ((((INT32 *) VendorGuid)[0] == ((INT32 *) &Variable->VendorGuid)[0]) &&\r
338 (((INT32 *) VendorGuid)[1] == ((INT32 *) &Variable->VendorGuid)[1]) &&\r
339 (((INT32 *) VendorGuid)[2] == ((INT32 *) &Variable->VendorGuid)[2]) &&\r
340 (((INT32 *) VendorGuid)[3] == ((INT32 *) &Variable->VendorGuid)[3])\r
341 ) {\r
130e2569 342 ASSERT (NameSizeOfVariable (Variable) != 0);\r
343 Point = (VOID *) GetVariableNamePtr (Variable);\r
dfc005c3 344 if (CompareMem (VariableName, Point, NameSizeOfVariable (Variable)) == 0) {\r
8d3a5c82 345 PtrTrack->CurrPtr = Variable;\r
346 return EFI_SUCCESS;\r
347 }\r
348 }\r
349 }\r
350\r
351 return EFI_NOT_FOUND;\r
352}\r
353\r
33479ddf 354\r
355/**\r
356 This code finds variable in storage blocks (Non-Volatile).\r
357\r
358 @param PeiServices General purpose services available to every PEIM.\r
359 @param VariableName Name of the variable to be found\r
360 @param VendorGuid Vendor GUID to be found.\r
361 @param PtrTrack Variable Track Pointer structure that contains Variable Information.\r
362\r
363 @retval EFI_SUCCESS Variable found successfully\r
364 @retval EFI_NOT_FOUND Variable not found\r
365 @retval EFI_INVALID_PARAMETER Invalid variable name\r
366\r
367**/\r
8d3a5c82 368EFI_STATUS\r
8d3a5c82 369FindVariable (\r
284c8400 370 IN CONST EFI_PEI_SERVICES **PeiServices,\r
8d3a5c82 371 IN CONST CHAR16 *VariableName,\r
372 IN CONST EFI_GUID *VendorGuid,\r
373 OUT VARIABLE_POINTER_TRACK *PtrTrack\r
374 )\r
8d3a5c82 375{\r
376 EFI_HOB_GUID_TYPE *GuidHob;\r
377 VARIABLE_STORE_HEADER *VariableStoreHeader;\r
378 VARIABLE_HEADER *Variable;\r
841014ba 379 VARIABLE_HEADER *LastVariable;\r
8d3a5c82 380 VARIABLE_HEADER *MaxIndex;\r
381 VARIABLE_INDEX_TABLE *IndexTable;\r
382 UINT32 Count;\r
841014ba 383 UINT32 Offset;\r
8d3a5c82 384 UINT8 *VariableBase;\r
841014ba 385 BOOLEAN StopRecord;\r
8d3a5c82 386\r
6041576e 387 if (VariableName[0] != 0 && VendorGuid == NULL) {\r
8d3a5c82 388 return EFI_INVALID_PARAMETER;\r
389 }\r
390 //\r
391 // No Variable Address equals zero, so 0 as initial value is safe.\r
392 //\r
393 MaxIndex = 0;\r
841014ba 394 StopRecord = FALSE;\r
8d3a5c82 395\r
396 GuidHob = GetFirstGuidHob (&mEfiVariableIndexTableGuid);\r
397 if (GuidHob == NULL) {\r
841014ba 398 //\r
399 // If it's the first time to access variable region in flash, create a guid hob to record\r
400 // VAR_ADDED type variable info.\r
401 // Note that as the resource of PEI phase is limited, only store the number of \r
402 // VARIABLE_INDEX_TABLE_VOLUME of VAR_ADDED type variables to reduce access time.\r
403 //\r
8d3a5c82 404 IndexTable = BuildGuidHob (&mEfiVariableIndexTableGuid, sizeof (VARIABLE_INDEX_TABLE));\r
405 IndexTable->Length = 0;\r
406 IndexTable->StartPtr = NULL;\r
407 IndexTable->EndPtr = NULL;\r
408 IndexTable->GoneThrough = 0;\r
409 } else {\r
410 IndexTable = GET_GUID_HOB_DATA (GuidHob);\r
841014ba 411 for (Offset = 0, Count = 0; Count < IndexTable->Length; Count++) {\r
412 //\r
413 // traverse the variable info list to look for varible.\r
414 // The IndexTable->Index[Count] records the distance of two neighbouring VAR_ADDED type variables.\r
415 //\r
f2a06473 416 ASSERT (Count < VARIABLE_INDEX_TABLE_VOLUME);\r
841014ba 417 Offset += IndexTable->Index[Count];\r
418 MaxIndex = (VARIABLE_HEADER *)((CHAR8 *)(IndexTable->StartPtr) + Offset);\r
8d3a5c82 419 if (CompareWithValidVariable (MaxIndex, VariableName, VendorGuid, PtrTrack) == EFI_SUCCESS) {\r
420 PtrTrack->StartPtr = IndexTable->StartPtr;\r
421 PtrTrack->EndPtr = IndexTable->EndPtr;\r
422\r
423 return EFI_SUCCESS;\r
424 }\r
425 }\r
426\r
33479ddf 427 if (IndexTable->GoneThrough != 0) {\r
8d3a5c82 428 return EFI_NOT_FOUND;\r
429 }\r
430 }\r
431 //\r
432 // If not found in HOB, then let's start from the MaxIndex we've found.\r
433 //\r
434 if (MaxIndex != NULL) {\r
841014ba 435 Variable = GetNextVariablePtr (MaxIndex);\r
436 LastVariable = MaxIndex;\r
8d3a5c82 437 } else {\r
33479ddf 438 if ((IndexTable->StartPtr != NULL) || (IndexTable->EndPtr != NULL)) {\r
8d3a5c82 439 Variable = IndexTable->StartPtr;\r
440 } else {\r
92a4f6f3 441 VariableBase = (UINT8 *) (UINTN) PcdGet64 (PcdFlashNvStorageVariableBase64);\r
442 if (VariableBase == NULL) {\r
443 VariableBase = (UINT8 *) (UINTN) PcdGet32 (PcdFlashNvStorageVariableBase);\r
444 }\r
445 \r
8d3a5c82 446 VariableStoreHeader = (VARIABLE_STORE_HEADER *) (VariableBase + \\r
447 ((EFI_FIRMWARE_VOLUME_HEADER *) (VariableBase)) -> HeaderLength);\r
448\r
449 if (GetVariableStoreStatus (VariableStoreHeader) != EfiValid) {\r
450 return EFI_UNSUPPORTED;\r
451 }\r
452\r
453 if (~VariableStoreHeader->Size == 0) {\r
454 return EFI_NOT_FOUND;\r
455 }\r
456 //\r
457 // Find the variable by walk through non-volatile variable store\r
458 //\r
9cad030b 459 IndexTable->StartPtr = GetStartPointer (VariableStoreHeader);\r
460 IndexTable->EndPtr = GetEndPointer (VariableStoreHeader);\r
8d3a5c82 461\r
462 //\r
463 // Start Pointers for the variable.\r
464 // Actual Data Pointer where data can be written.\r
465 //\r
466 Variable = IndexTable->StartPtr;\r
467 }\r
841014ba 468\r
469 LastVariable = IndexTable->StartPtr;\r
8d3a5c82 470 }\r
471 //\r
472 // Find the variable by walk through non-volatile variable store\r
473 //\r
474 PtrTrack->StartPtr = IndexTable->StartPtr;\r
475 PtrTrack->EndPtr = IndexTable->EndPtr;\r
476\r
fba0ee1f 477 while ((Variable < IndexTable->EndPtr) && IsValidVariableHeader (Variable)) {\r
8d3a5c82 478 if (Variable->State == VAR_ADDED) {\r
479 //\r
480 // Record Variable in VariableIndex HOB\r
481 //\r
aa75dfec 482 if (IndexTable->Length < VARIABLE_INDEX_TABLE_VOLUME && !StopRecord) {\r
841014ba 483 Offset = (UINT32)((UINTN)Variable - (UINTN)LastVariable);\r
484 //\r
485 // The distance of two neighbouring VAR_ADDED variable is larger than 2^16, \r
486 // which is beyond the allowable scope(UINT16) of record. In such case, need not to\r
487 // record the subsequent VAR_ADDED type variables again.\r
488 //\r
489 if ((Offset & 0xFFFF0000UL) != 0) {\r
490 StopRecord = TRUE;\r
491 }\r
492\r
aa75dfec 493 if (!StopRecord) {\r
841014ba 494 IndexTable->Index[IndexTable->Length++] = (UINT16) Offset;\r
495 }\r
496 LastVariable = Variable;\r
497 }\r
498\r
8d3a5c82 499 if (CompareWithValidVariable (Variable, VariableName, VendorGuid, PtrTrack) == EFI_SUCCESS) {\r
500 return EFI_SUCCESS;\r
501 }\r
502 }\r
503\r
504 Variable = GetNextVariablePtr (Variable);\r
505 }\r
506 //\r
507 // If gone through the VariableStore, that means we never find in Firmware any more.\r
508 //\r
2ad29d0f 509 if ((IndexTable->Length < VARIABLE_INDEX_TABLE_VOLUME) && (!StopRecord)) {\r
8d3a5c82 510 IndexTable->GoneThrough = 1;\r
511 }\r
512\r
513 PtrTrack->CurrPtr = NULL;\r
514\r
515 return EFI_NOT_FOUND;\r
516}\r
517\r
33479ddf 518/**\r
519 This service retrieves a variable's value using its name and GUID.\r
520\r
521 Read the specified variable from the UEFI variable store. If the Data \r
522 buffer is too small to hold the contents of the variable, the error\r
523 EFI_BUFFER_TOO_SMALL is returned and DataSize is set to the required buffer\r
524 size to obtain the data.\r
525\r
526 @param This A pointer to this instance of the EFI_PEI_READ_ONLY_VARIABLE2_PPI.\r
527 @param VariableName A pointer to a null-terminated string that is the variable's name.\r
528 @param VariableGuid A pointer to an EFI_GUID that is the variable's GUID. The combination of\r
529 VariableGuid and VariableName must be unique.\r
530 @param Attributes If non-NULL, on return, points to the variable's attributes.\r
531 @param DataSize On entry, points to the size in bytes of the Data buffer.\r
532 On return, points to the size of the data returned in Data.\r
533 @param Data Points to the buffer which will hold the returned variable value.\r
534\r
535 @retval EFI_SUCCESS The variable was read successfully.\r
536 @retval EFI_NOT_FOUND The variable could not be found.\r
537 @retval EFI_BUFFER_TOO_SMALL The DataSize is too small for the resulting data. \r
538 DataSize is updated with the size required for \r
539 the specified variable.\r
540 @retval EFI_INVALID_PARAMETER VariableName, VariableGuid, DataSize or Data is NULL.\r
541 @retval EFI_DEVICE_ERROR The variable could not be retrieved because of a device error.\r
542\r
543**/\r
8d3a5c82 544EFI_STATUS\r
545EFIAPI\r
546PeiGetVariable (\r
547 IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI *This,\r
548 IN CONST CHAR16 *VariableName,\r
549 IN CONST EFI_GUID *VariableGuid,\r
550 OUT UINT32 *Attributes,\r
551 IN OUT UINTN *DataSize,\r
552 OUT VOID *Data\r
553 )\r
8d3a5c82 554{\r
555 VARIABLE_POINTER_TRACK Variable;\r
556 UINTN VarDataSize;\r
557 EFI_STATUS Status;\r
284c8400 558 CONST EFI_PEI_SERVICES **PeiServices;\r
8d3a5c82 559\r
560 PeiServices = GetPeiServicesTablePointer ();\r
01f352a7 561 if (VariableName == NULL || VariableGuid == NULL || DataSize == NULL) {\r
8d3a5c82 562 return EFI_INVALID_PARAMETER;\r
563 }\r
4249fa76 564\r
565 //\r
566 // Check if this is recovery boot path.\r
567 // If yes, the content of variable area is not reliable. Therefore we directly\r
568 // return EFI_NOT_FOUND. \r
569 // \r
570 if (IsInRecoveryMode(PeiServices)) {\r
571 return EFI_NOT_FOUND;\r
572 }\r
573\r
8d3a5c82 574 //\r
575 // Find existing variable\r
576 //\r
577 Status = FindVariable (PeiServices, VariableName, VariableGuid, &Variable);\r
578 if (Variable.CurrPtr == NULL || Status != EFI_SUCCESS) {\r
579 return Status;\r
580 }\r
581 //\r
582 // Get data size\r
583 //\r
130e2569 584 VarDataSize = DataSizeOfVariable (Variable.CurrPtr);\r
8d3a5c82 585 if (*DataSize >= VarDataSize) {\r
39aea48d 586 if (Data == NULL) {\r
587 return EFI_INVALID_PARAMETER;\r
588 }\r
589\r
33479ddf 590 CopyMem (Data, GetVariableDataPtr (Variable.CurrPtr), VarDataSize);\r
8d3a5c82 591\r
592 if (Attributes != NULL) {\r
593 *Attributes = Variable.CurrPtr->Attributes;\r
594 }\r
595\r
596 *DataSize = VarDataSize;\r
597 return EFI_SUCCESS;\r
598 } else {\r
599 *DataSize = VarDataSize;\r
600 return EFI_BUFFER_TOO_SMALL;\r
601 }\r
602}\r
603\r
33479ddf 604/**\r
605 Return the next variable name and GUID.\r
606\r
607 This function is called multiple times to retrieve the VariableName \r
608 and VariableGuid of all variables currently available in the system. \r
609 On each call, the previous results are passed into the interface, \r
610 and, on return, the interface returns the data for the next \r
611 interface. When the entire variable list has been returned, \r
612 EFI_NOT_FOUND is returned.\r
613\r
614 @param This A pointer to this instance of the EFI_PEI_READ_ONLY_VARIABLE2_PPI.\r
615\r
616 @param VariableNameSize On entry, points to the size of the buffer pointed to by VariableName.\r
f7dab9fa 617 On return, the size of the variable name buffer.\r
33479ddf 618 @param VariableName On entry, a pointer to a null-terminated string that is the variable's name.\r
619 On return, points to the next variable's null-terminated name string.\r
255f993d 620 @param VariableGuid On entry, a pointer to an EFI_GUID that is the variable's GUID. \r
33479ddf 621 On return, a pointer to the next variable's GUID.\r
622\r
623 @retval EFI_SUCCESS The variable was read successfully.\r
624 @retval EFI_NOT_FOUND The variable could not be found.\r
625 @retval EFI_BUFFER_TOO_SMALL The VariableNameSize is too small for the resulting\r
626 data. VariableNameSize is updated with the size\r
627 required for the specified variable.\r
628 @retval EFI_INVALID_PARAMETER VariableName, VariableGuid or\r
629 VariableNameSize is NULL.\r
630 @retval EFI_DEVICE_ERROR The variable could not be retrieved because of a device error.\r
631\r
632**/\r
8d3a5c82 633EFI_STATUS\r
634EFIAPI\r
635PeiGetNextVariableName (\r
636 IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI *This,\r
637 IN OUT UINTN *VariableNameSize,\r
638 IN OUT CHAR16 *VariableName,\r
639 IN OUT EFI_GUID *VariableGuid\r
640 )\r
8d3a5c82 641{\r
642 VARIABLE_POINTER_TRACK Variable;\r
643 UINTN VarNameSize;\r
644 EFI_STATUS Status;\r
284c8400 645 CONST EFI_PEI_SERVICES **PeiServices;\r
8d3a5c82 646\r
647 PeiServices = GetPeiServicesTablePointer ();\r
01f352a7 648 if (VariableName == NULL || VariableGuid == NULL || VariableNameSize == NULL) {\r
8d3a5c82 649 return EFI_INVALID_PARAMETER;\r
650 }\r
651\r
4249fa76 652 //\r
653 // Check if this is recovery boot path.\r
654 // If yes, the content of variable area is not reliable. Therefore we directly\r
655 // return EFI_NOT_FOUND. \r
656 // \r
657 if (IsInRecoveryMode(PeiServices)) {\r
658 return EFI_NOT_FOUND;\r
659 }\r
660\r
8d3a5c82 661 Status = FindVariable (PeiServices, VariableName, VariableGuid, &Variable);\r
662 if (Variable.CurrPtr == NULL || Status != EFI_SUCCESS) {\r
663 return Status;\r
664 }\r
665\r
666 if (VariableName[0] != 0) {\r
667 //\r
668 // If variable name is not NULL, get next variable\r
669 //\r
670 Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);\r
671 }\r
672\r
673 while (!(Variable.CurrPtr >= Variable.EndPtr || Variable.CurrPtr == NULL)) {\r
674 if (IsValidVariableHeader (Variable.CurrPtr)) {\r
675 if (Variable.CurrPtr->State == VAR_ADDED) {\r
130e2569 676 ASSERT (NameSizeOfVariable (Variable.CurrPtr) != 0);\r
9cad030b 677\r
130e2569 678 VarNameSize = (UINTN) NameSizeOfVariable (Variable.CurrPtr);\r
8d3a5c82 679 if (VarNameSize <= *VariableNameSize) {\r
33479ddf 680 CopyMem (VariableName, GetVariableNamePtr (Variable.CurrPtr), VarNameSize);\r
8d3a5c82 681\r
33479ddf 682 CopyMem (VariableGuid, &Variable.CurrPtr->VendorGuid, sizeof (EFI_GUID));\r
8d3a5c82 683\r
684 Status = EFI_SUCCESS;\r
685 } else {\r
686 Status = EFI_BUFFER_TOO_SMALL;\r
687 }\r
688\r
689 *VariableNameSize = VarNameSize;\r
690 return Status;\r
691 //\r
692 // Variable is found\r
693 //\r
694 } else {\r
695 Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);\r
696 }\r
697 } else {\r
698 break;\r
699 }\r
700 }\r
701\r
702 return EFI_NOT_FOUND;\r
703}\r