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