2 Implement ReadOnly Variable Services required by PEIM and install PEI
3 ReadOnly Varaiable2 PPI. These services operates the non-volatile
6 Copyright (c) 2009 - 2013, Intel Corporation. All rights reserved.<BR>
7 This program and the accompanying materials
8 are licensed and made available under the terms and conditions of the BSD License
9 which accompanies this distribution. The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
23 EFI_PEI_READ_ONLY_VARIABLE2_PPI mVariablePpi
= {
25 PeiGetNextVariableName
28 EFI_PEI_PPI_DESCRIPTOR mPpiListVariable
= {
29 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
30 &gEfiPeiReadOnlyVariable2PpiGuid
,
35 Provide the functionality of the variable services.
37 @param FileHandle Handle of the file being invoked.
38 Type EFI_PEI_FILE_HANDLE is defined in FfsFindNextFile().
39 @param PeiServices General purpose services available to every PEIM.
41 @retval EFI_SUCCESS If the interface could be successfully installed
42 @retval Others Returned from PeiServicesInstallPpi()
46 PeimInitializeVariableServices (
47 IN EFI_PEI_FILE_HANDLE FileHandle
,
48 IN CONST EFI_PEI_SERVICES
**PeiServices
51 return PeiServicesInstallPpi (&mPpiListVariable
);
56 Gets the pointer to the first variable header in given variable store area.
58 @param VarStoreHeader Pointer to the Variable Store Header.
60 @return Pointer to the first variable header
65 IN VARIABLE_STORE_HEADER
*VarStoreHeader
69 // The end of variable store
71 return (VARIABLE_HEADER
*) HEADER_ALIGN (VarStoreHeader
+ 1);
76 This code gets the pointer to the last variable memory pointer byte.
78 @param VarStoreHeader Pointer to the Variable Store Header.
80 @return VARIABLE_HEADER* pointer to last unavailable Variable Header.
85 IN VARIABLE_STORE_HEADER
*VarStoreHeader
89 // The end of variable store
91 return (VARIABLE_HEADER
*) HEADER_ALIGN ((UINTN
) VarStoreHeader
+ VarStoreHeader
->Size
);
96 This code checks if variable header is valid or not.
98 @param Variable Pointer to the Variable Header.
100 @retval TRUE Variable header is valid.
101 @retval FALSE Variable header is not valid.
105 IsValidVariableHeader (
106 IN VARIABLE_HEADER
*Variable
109 if (Variable
== NULL
|| Variable
->StartId
!= VARIABLE_DATA
) {
118 This code gets the size of name of variable.
120 @param Variable Pointer to the Variable Header.
122 @return Size of variable in bytes in type UINTN.
127 IN VARIABLE_HEADER
*Variable
130 if (Variable
->State
== (UINT8
) (-1) ||
131 Variable
->DataSize
== (UINT32
) (-1) ||
132 Variable
->NameSize
== (UINT32
) (-1) ||
133 Variable
->Attributes
== (UINT32
) (-1)) {
136 return (UINTN
) Variable
->NameSize
;
141 This code gets the size of data of variable.
143 @param Variable Pointer to the Variable Header.
145 @return Size of variable in bytes in type UINTN.
150 IN VARIABLE_HEADER
*Variable
153 if (Variable
->State
== (UINT8
) (-1) ||
154 Variable
->DataSize
== (UINT32
) (-1) ||
155 Variable
->NameSize
== (UINT32
) (-1) ||
156 Variable
->Attributes
== (UINT32
) (-1)) {
159 return (UINTN
) Variable
->DataSize
;
163 This code gets the pointer to the variable name.
165 @param Variable Pointer to the Variable Header.
167 @return A CHAR16* pointer to Variable Name.
172 IN VARIABLE_HEADER
*Variable
175 return (CHAR16
*) (Variable
+ 1);
180 This code gets the pointer to the variable data.
182 @param Variable Pointer to the Variable Header.
183 @param VariableHeader Pointer to the Variable Header that has consecutive content.
185 @return A UINT8* pointer to Variable Data.
190 IN VARIABLE_HEADER
*Variable
,
191 IN VARIABLE_HEADER
*VariableHeader
197 // Be careful about pad size for alignment
199 Value
= (UINTN
) GetVariableNamePtr (Variable
);
200 Value
+= NameSizeOfVariable (VariableHeader
);
201 Value
+= GET_PAD_SIZE (NameSizeOfVariable (VariableHeader
));
203 return (UINT8
*) Value
;
208 This code gets the pointer to the next variable header.
210 @param StoreInfo Pointer to variable store info structure.
211 @param Variable Pointer to the Variable Header.
212 @param VariableHeader Pointer to the Variable Header that has consecutive content.
214 @return A VARIABLE_HEADER* pointer to next variable header.
219 IN VARIABLE_STORE_INFO
*StoreInfo
,
220 IN VARIABLE_HEADER
*Variable
,
221 IN VARIABLE_HEADER
*VariableHeader
224 EFI_PHYSICAL_ADDRESS TargetAddress
;
225 EFI_PHYSICAL_ADDRESS SpareAddress
;
228 Value
= (UINTN
) GetVariableDataPtr (Variable
, VariableHeader
);
229 Value
+= DataSizeOfVariable (VariableHeader
);
230 Value
+= GET_PAD_SIZE (DataSizeOfVariable (VariableHeader
));
232 // Be careful about pad size for alignment
234 Value
= HEADER_ALIGN (Value
);
236 if (StoreInfo
->FtwLastWriteData
!= NULL
) {
237 TargetAddress
= StoreInfo
->FtwLastWriteData
->TargetAddress
;
238 SpareAddress
= StoreInfo
->FtwLastWriteData
->SpareAddress
;
239 if (((UINTN
) Variable
< (UINTN
) TargetAddress
) && (Value
>= (UINTN
) TargetAddress
)) {
241 // Next variable is in spare block.
243 Value
= (UINTN
) SpareAddress
+ (Value
- (UINTN
) TargetAddress
);
247 return (VARIABLE_HEADER
*) Value
;
251 Get variable store status.
253 @param VarStoreHeader Pointer to the Variable Store Header.
255 @retval EfiRaw Variable store is raw
256 @retval EfiValid Variable store is valid
257 @retval EfiInvalid Variable store is invalid
260 VARIABLE_STORE_STATUS
261 GetVariableStoreStatus (
262 IN VARIABLE_STORE_HEADER
*VarStoreHeader
265 if (CompareGuid (&VarStoreHeader
->Signature
, &gEfiAuthenticatedVariableGuid
) &&
266 VarStoreHeader
->Format
== VARIABLE_STORE_FORMATTED
&&
267 VarStoreHeader
->State
== VARIABLE_STORE_HEALTHY
273 if (((UINT32
*)(&VarStoreHeader
->Signature
))[0] == 0xffffffff &&
274 ((UINT32
*)(&VarStoreHeader
->Signature
))[1] == 0xffffffff &&
275 ((UINT32
*)(&VarStoreHeader
->Signature
))[2] == 0xffffffff &&
276 ((UINT32
*)(&VarStoreHeader
->Signature
))[3] == 0xffffffff &&
277 VarStoreHeader
->Size
== 0xffffffff &&
278 VarStoreHeader
->Format
== 0xff &&
279 VarStoreHeader
->State
== 0xff
289 Compare two variable names, one of them may be inconsecutive.
291 @param StoreInfo Pointer to variable store info structure.
292 @param Name1 Pointer to one variable name.
293 @param Name2 Pointer to another variable name.
294 @param NameSize Variable name size.
296 @retval TRUE Name1 and Name2 are identical.
297 @retval FALSE Name1 and Name2 are not identical.
301 CompareVariableName (
302 IN VARIABLE_STORE_INFO
*StoreInfo
,
303 IN CONST CHAR16
*Name1
,
304 IN CONST CHAR16
*Name2
,
308 EFI_PHYSICAL_ADDRESS TargetAddress
;
309 EFI_PHYSICAL_ADDRESS SpareAddress
;
310 UINTN PartialNameSize
;
312 if (StoreInfo
->FtwLastWriteData
!= NULL
) {
313 TargetAddress
= StoreInfo
->FtwLastWriteData
->TargetAddress
;
314 SpareAddress
= StoreInfo
->FtwLastWriteData
->SpareAddress
;
315 if (((UINTN
) Name1
< (UINTN
) TargetAddress
) && (((UINTN
) Name1
+ NameSize
) > (UINTN
) TargetAddress
)) {
317 // Name1 is inconsecutive.
319 PartialNameSize
= (UINTN
) TargetAddress
- (UINTN
) Name1
;
321 // Partial content is in NV storage.
323 if (CompareMem ((UINT8
*) Name1
, (UINT8
*) Name2
, PartialNameSize
) == 0) {
325 // Another partial content is in spare block.
327 if (CompareMem ((UINT8
*) (UINTN
) SpareAddress
, (UINT8
*) Name2
+ PartialNameSize
, NameSize
- PartialNameSize
) == 0) {
332 } else if (((UINTN
) Name2
< (UINTN
) TargetAddress
) && (((UINTN
) Name2
+ NameSize
) > (UINTN
) TargetAddress
)) {
334 // Name2 is inconsecutive.
336 PartialNameSize
= (UINTN
) TargetAddress
- (UINTN
) Name2
;
338 // Partial content is in NV storage.
340 if (CompareMem ((UINT8
*) Name2
, (UINT8
*) Name1
, PartialNameSize
) == 0) {
342 // Another partial content is in spare block.
344 if (CompareMem ((UINT8
*) (UINTN
) SpareAddress
, (UINT8
*) Name1
+ PartialNameSize
, NameSize
- PartialNameSize
) == 0) {
353 // Both Name1 and Name2 are consecutive.
355 if (CompareMem ((UINT8
*) Name1
, (UINT8
*) Name2
, NameSize
) == 0) {
362 This function compares a variable with variable entries in database.
364 @param StoreInfo Pointer to variable store info structure.
365 @param Variable Pointer to the variable in our database
366 @param VariableHeader Pointer to the Variable Header that has consecutive content.
367 @param VariableName Name of the variable to compare to 'Variable'
368 @param VendorGuid GUID of the variable to compare to 'Variable'
369 @param PtrTrack Variable Track Pointer structure that contains Variable Information.
371 @retval EFI_SUCCESS Found match variable
372 @retval EFI_NOT_FOUND Variable not found
376 CompareWithValidVariable (
377 IN VARIABLE_STORE_INFO
*StoreInfo
,
378 IN VARIABLE_HEADER
*Variable
,
379 IN VARIABLE_HEADER
*VariableHeader
,
380 IN CONST CHAR16
*VariableName
,
381 IN CONST EFI_GUID
*VendorGuid
,
382 OUT VARIABLE_POINTER_TRACK
*PtrTrack
387 if (VariableName
[0] == 0) {
388 PtrTrack
->CurrPtr
= Variable
;
392 // Don't use CompareGuid function here for performance reasons.
393 // Instead we compare the GUID a UINT32 at a time and branch
394 // on the first failed comparison.
396 if ((((INT32
*) VendorGuid
)[0] == ((INT32
*) &VariableHeader
->VendorGuid
)[0]) &&
397 (((INT32
*) VendorGuid
)[1] == ((INT32
*) &VariableHeader
->VendorGuid
)[1]) &&
398 (((INT32
*) VendorGuid
)[2] == ((INT32
*) &VariableHeader
->VendorGuid
)[2]) &&
399 (((INT32
*) VendorGuid
)[3] == ((INT32
*) &VariableHeader
->VendorGuid
)[3])
401 ASSERT (NameSizeOfVariable (VariableHeader
) != 0);
402 Point
= (VOID
*) GetVariableNamePtr (Variable
);
403 if (CompareVariableName (StoreInfo
, VariableName
, Point
, NameSizeOfVariable (VariableHeader
))) {
404 PtrTrack
->CurrPtr
= Variable
;
410 return EFI_NOT_FOUND
;
414 Return the variable store header and the store info based on the Index.
416 @param Type The type of the variable store.
417 @param StoreInfo Return the store info.
419 @return Pointer to the variable store header.
421 VARIABLE_STORE_HEADER
*
423 IN VARIABLE_STORE_TYPE Type
,
424 OUT VARIABLE_STORE_INFO
*StoreInfo
427 EFI_HOB_GUID_TYPE
*GuidHob
;
428 EFI_FIRMWARE_VOLUME_HEADER
*FvHeader
;
429 VARIABLE_STORE_HEADER
*VariableStoreHeader
;
430 EFI_PHYSICAL_ADDRESS NvStorageBase
;
431 UINT32 NvStorageSize
;
432 FAULT_TOLERANT_WRITE_LAST_WRITE_DATA
*FtwLastWriteData
;
435 StoreInfo
->IndexTable
= NULL
;
436 StoreInfo
->FtwLastWriteData
= NULL
;
437 VariableStoreHeader
= NULL
;
439 case VariableStoreTypeHob
:
440 GuidHob
= GetFirstGuidHob (&gEfiAuthenticatedVariableGuid
);
441 if (GuidHob
!= NULL
) {
442 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) GET_GUID_HOB_DATA (GuidHob
);
446 case VariableStoreTypeNv
:
447 if (GetBootModeHob () != BOOT_IN_RECOVERY_MODE
) {
449 // The content of NV storage for variable is not reliable in recovery boot mode.
452 NvStorageSize
= PcdGet32 (PcdFlashNvStorageVariableSize
);
453 NvStorageBase
= (EFI_PHYSICAL_ADDRESS
) (PcdGet64 (PcdFlashNvStorageVariableBase64
) != 0 ?
454 PcdGet64 (PcdFlashNvStorageVariableBase64
) :
455 PcdGet32 (PcdFlashNvStorageVariableBase
)
458 // First let FvHeader point to NV storage base.
460 FvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) (UINTN
) NvStorageBase
;
463 // Check the FTW last write data hob.
466 GuidHob
= GetFirstGuidHob (&gEdkiiFaultTolerantWriteGuid
);
467 if (GuidHob
!= NULL
) {
468 FtwLastWriteData
= (FAULT_TOLERANT_WRITE_LAST_WRITE_DATA
*) GET_GUID_HOB_DATA (GuidHob
);
469 if (FtwLastWriteData
->TargetAddress
== NvStorageBase
) {
471 // Let FvHeader point to spare block.
473 FvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) (UINTN
) FtwLastWriteData
->SpareAddress
;
474 DEBUG ((EFI_D_INFO
, "PeiVariable: NV storage is backed up in spare block: 0x%x\n", (UINTN
) FtwLastWriteData
->SpareAddress
));
475 } else if ((FtwLastWriteData
->TargetAddress
> NvStorageBase
) && (FtwLastWriteData
->TargetAddress
< (NvStorageBase
+ NvStorageSize
))) {
476 StoreInfo
->FtwLastWriteData
= FtwLastWriteData
;
478 // Flash NV storage from the offset is backed up in spare block.
480 BackUpOffset
= (UINT32
) (FtwLastWriteData
->TargetAddress
- NvStorageBase
);
481 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
));
483 // At least one block data in flash NV storage is still valid, so still leave FvHeader point to NV storage base.
489 // Check if the Firmware Volume is not corrupted
491 if ((FvHeader
->Signature
!= EFI_FVH_SIGNATURE
) || (!CompareGuid (&gEfiSystemNvDataFvGuid
, &FvHeader
->FileSystemGuid
))) {
492 DEBUG ((EFI_D_ERROR
, "Firmware Volume for Variable Store is corrupted\n"));
496 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) ((UINT8
*) FvHeader
+ FvHeader
->HeaderLength
);
498 GuidHob
= GetFirstGuidHob (&gEfiVariableIndexTableGuid
);
499 if (GuidHob
!= NULL
) {
500 StoreInfo
->IndexTable
= GET_GUID_HOB_DATA (GuidHob
);
503 // If it's the first time to access variable region in flash, create a guid hob to record
504 // VAR_ADDED type variable info.
505 // Note that as the resource of PEI phase is limited, only store the limited number of
506 // VAR_ADDED type variables to reduce access time.
508 StoreInfo
->IndexTable
= (VARIABLE_INDEX_TABLE
*) BuildGuidHob (&gEfiVariableIndexTableGuid
, sizeof (VARIABLE_INDEX_TABLE
));
509 StoreInfo
->IndexTable
->Length
= 0;
510 StoreInfo
->IndexTable
->StartPtr
= GetStartPointer (VariableStoreHeader
);
511 StoreInfo
->IndexTable
->EndPtr
= GetEndPointer (VariableStoreHeader
);
512 StoreInfo
->IndexTable
->GoneThrough
= 0;
522 StoreInfo
->VariableStoreHeader
= VariableStoreHeader
;
523 return VariableStoreHeader
;
527 Get variable header that has consecutive content.
529 @param StoreInfo Pointer to variable store info structure.
530 @param Variable Pointer to the Variable Header.
531 @param VariableHeader Pointer to Pointer to the Variable Header that has consecutive content.
533 @retval TRUE Variable header is valid.
534 @retval FALSE Variable header is not valid.
539 IN VARIABLE_STORE_INFO
*StoreInfo
,
540 IN VARIABLE_HEADER
*Variable
,
541 OUT VARIABLE_HEADER
**VariableHeader
544 EFI_PHYSICAL_ADDRESS TargetAddress
;
545 EFI_PHYSICAL_ADDRESS SpareAddress
;
546 EFI_HOB_GUID_TYPE
*GuidHob
;
547 UINTN PartialHeaderSize
;
550 // First assume variable header pointed by Variable is consecutive.
552 *VariableHeader
= Variable
;
554 if ((Variable
!= NULL
) && (StoreInfo
->FtwLastWriteData
!= NULL
)) {
555 TargetAddress
= StoreInfo
->FtwLastWriteData
->TargetAddress
;
556 SpareAddress
= StoreInfo
->FtwLastWriteData
->SpareAddress
;
557 if (((UINTN
) Variable
< (UINTN
) TargetAddress
) && (((UINTN
) Variable
+ sizeof (VARIABLE_HEADER
)) > (UINTN
) TargetAddress
)) {
559 // Variable header pointed by Variable is inconsecutive,
560 // create a guid hob to combine the two partial variable header content together.
562 GuidHob
= GetFirstGuidHob (&gEfiCallerIdGuid
);
563 if (GuidHob
!= NULL
) {
564 *VariableHeader
= (VARIABLE_HEADER
*) GET_GUID_HOB_DATA (GuidHob
);
566 *VariableHeader
= (VARIABLE_HEADER
*) BuildGuidHob (&gEfiCallerIdGuid
, sizeof (VARIABLE_HEADER
));
567 PartialHeaderSize
= (UINTN
) TargetAddress
- (UINTN
) Variable
;
569 // Partial content is in NV storage.
571 CopyMem ((UINT8
*) *VariableHeader
, (UINT8
*) Variable
, PartialHeaderSize
);
573 // Another partial content is in spare block.
575 CopyMem ((UINT8
*) *VariableHeader
+ PartialHeaderSize
, (UINT8
*) (UINTN
) SpareAddress
, sizeof (VARIABLE_HEADER
) - PartialHeaderSize
);
580 return IsValidVariableHeader (*VariableHeader
);
584 Get variable name or data to output buffer.
586 @param StoreInfo Pointer to variable store info structure.
587 @param NameOrData Pointer to the variable name/data that may be inconsecutive.
588 @param Size Variable name/data size.
589 @param Buffer Pointer to output buffer to hold the variable name/data.
593 GetVariableNameOrData (
594 IN VARIABLE_STORE_INFO
*StoreInfo
,
595 IN UINT8
*NameOrData
,
600 EFI_PHYSICAL_ADDRESS TargetAddress
;
601 EFI_PHYSICAL_ADDRESS SpareAddress
;
604 if (StoreInfo
->FtwLastWriteData
!= NULL
) {
605 TargetAddress
= StoreInfo
->FtwLastWriteData
->TargetAddress
;
606 SpareAddress
= StoreInfo
->FtwLastWriteData
->SpareAddress
;
607 if (((UINTN
) NameOrData
< (UINTN
) TargetAddress
) && (((UINTN
) NameOrData
+ Size
) > (UINTN
) TargetAddress
)) {
609 // Variable name/data is inconsecutive.
611 PartialSize
= (UINTN
) TargetAddress
- (UINTN
) NameOrData
;
613 // Partial content is in NV storage.
615 CopyMem (Buffer
, NameOrData
, PartialSize
);
617 // Another partial content is in spare block.
619 CopyMem (Buffer
+ PartialSize
, (UINT8
*) (UINTN
) SpareAddress
, Size
- PartialSize
);
625 // Variable name/data is consecutive.
627 CopyMem (Buffer
, NameOrData
, Size
);
631 Find the variable in the specified variable store.
633 @param StoreInfo Pointer to the store info structure.
634 @param VariableName Name of the variable to be found
635 @param VendorGuid Vendor GUID to be found.
636 @param PtrTrack Variable Track Pointer structure that contains Variable Information.
638 @retval EFI_SUCCESS Variable found successfully
639 @retval EFI_NOT_FOUND Variable not found
640 @retval EFI_INVALID_PARAMETER Invalid variable name
645 IN VARIABLE_STORE_INFO
*StoreInfo
,
646 IN CONST CHAR16
*VariableName
,
647 IN CONST EFI_GUID
*VendorGuid
,
648 OUT VARIABLE_POINTER_TRACK
*PtrTrack
651 VARIABLE_HEADER
*Variable
;
652 VARIABLE_HEADER
*LastVariable
;
653 VARIABLE_HEADER
*MaxIndex
;
657 VARIABLE_HEADER
*InDeletedVariable
;
658 VARIABLE_STORE_HEADER
*VariableStoreHeader
;
659 VARIABLE_INDEX_TABLE
*IndexTable
;
660 VARIABLE_HEADER
*VariableHeader
;
662 VariableStoreHeader
= StoreInfo
->VariableStoreHeader
;
664 if (VariableStoreHeader
== NULL
) {
665 return EFI_INVALID_PARAMETER
;
668 if (GetVariableStoreStatus (VariableStoreHeader
) != EfiValid
) {
669 return EFI_UNSUPPORTED
;
672 if (~VariableStoreHeader
->Size
== 0) {
673 return EFI_NOT_FOUND
;
676 IndexTable
= StoreInfo
->IndexTable
;
677 PtrTrack
->StartPtr
= GetStartPointer (VariableStoreHeader
);
678 PtrTrack
->EndPtr
= GetEndPointer (VariableStoreHeader
);
680 InDeletedVariable
= NULL
;
683 // No Variable Address equals zero, so 0 as initial value is safe.
686 VariableHeader
= NULL
;
688 if (IndexTable
!= NULL
) {
690 // traverse the variable index table to look for varible.
691 // The IndexTable->Index[Index] records the distance of two neighbouring VAR_ADDED type variables.
693 for (Offset
= 0, Index
= 0; Index
< IndexTable
->Length
; Index
++) {
694 ASSERT (Index
< sizeof (IndexTable
->Index
) / sizeof (IndexTable
->Index
[0]));
695 Offset
+= IndexTable
->Index
[Index
];
696 MaxIndex
= (VARIABLE_HEADER
*) ((UINT8
*) IndexTable
->StartPtr
+ Offset
);
697 GetVariableHeader (StoreInfo
, MaxIndex
, &VariableHeader
);
698 if (CompareWithValidVariable (StoreInfo
, MaxIndex
, VariableHeader
, VariableName
, VendorGuid
, PtrTrack
) == EFI_SUCCESS
) {
699 if (VariableHeader
->State
== (VAR_IN_DELETED_TRANSITION
& VAR_ADDED
)) {
700 InDeletedVariable
= PtrTrack
->CurrPtr
;
707 if (IndexTable
->GoneThrough
!= 0) {
709 // If the table has all the existing variables indexed, return.
711 PtrTrack
->CurrPtr
= InDeletedVariable
;
712 return (PtrTrack
->CurrPtr
== NULL
) ? EFI_NOT_FOUND
: EFI_SUCCESS
;
716 if (MaxIndex
!= NULL
) {
718 // HOB exists but the variable cannot be found in HOB
719 // If not found in HOB, then let's start from the MaxIndex we've found.
721 Variable
= GetNextVariablePtr (StoreInfo
, MaxIndex
, VariableHeader
);
722 LastVariable
= MaxIndex
;
725 // Start Pointers for the variable.
726 // Actual Data Pointer where data can be written.
728 Variable
= PtrTrack
->StartPtr
;
729 LastVariable
= PtrTrack
->StartPtr
;
733 // Find the variable by walk through variable store
736 while (GetVariableHeader (StoreInfo
, Variable
, &VariableHeader
)) {
737 if (VariableHeader
->State
== VAR_ADDED
|| VariableHeader
->State
== (VAR_IN_DELETED_TRANSITION
& VAR_ADDED
)) {
739 // Record Variable in VariableIndex HOB
741 if ((IndexTable
!= NULL
) && !StopRecord
) {
742 Offset
= (UINTN
) Variable
- (UINTN
) LastVariable
;
743 if ((Offset
> 0x0FFFF) || (IndexTable
->Length
== sizeof (IndexTable
->Index
) / sizeof (IndexTable
->Index
[0]))) {
745 // Stop to record if the distance of two neighbouring VAR_ADDED variable is larger than the allowable scope(UINT16),
746 // or the record buffer is full.
750 IndexTable
->Index
[IndexTable
->Length
++] = (UINT16
) Offset
;
751 LastVariable
= Variable
;
755 if (CompareWithValidVariable (StoreInfo
, Variable
, VariableHeader
, VariableName
, VendorGuid
, PtrTrack
) == EFI_SUCCESS
) {
756 if (VariableHeader
->State
== (VAR_IN_DELETED_TRANSITION
& VAR_ADDED
)) {
757 InDeletedVariable
= PtrTrack
->CurrPtr
;
764 Variable
= GetNextVariablePtr (StoreInfo
, Variable
, VariableHeader
);
767 // If gone through the VariableStore, that means we never find in Firmware any more.
769 if ((IndexTable
!= NULL
) && !StopRecord
) {
770 IndexTable
->GoneThrough
= 1;
773 PtrTrack
->CurrPtr
= InDeletedVariable
;
775 return (PtrTrack
->CurrPtr
== NULL
) ? EFI_NOT_FOUND
: EFI_SUCCESS
;
779 Find the variable in HOB and Non-Volatile variable storages.
781 @param VariableName Name of the variable to be found
782 @param VendorGuid Vendor GUID to be found.
783 @param PtrTrack Variable Track Pointer structure that contains Variable Information.
784 @param StoreInfo Return the store info.
786 @retval EFI_SUCCESS Variable found successfully
787 @retval EFI_NOT_FOUND Variable not found
788 @retval EFI_INVALID_PARAMETER Invalid variable name
792 IN CONST CHAR16
*VariableName
,
793 IN CONST EFI_GUID
*VendorGuid
,
794 OUT VARIABLE_POINTER_TRACK
*PtrTrack
,
795 OUT VARIABLE_STORE_INFO
*StoreInfo
799 VARIABLE_STORE_TYPE Type
;
801 if (VariableName
[0] != 0 && VendorGuid
== NULL
) {
802 return EFI_INVALID_PARAMETER
;
805 for (Type
= (VARIABLE_STORE_TYPE
) 0; Type
< VariableStoreTypeMax
; Type
++) {
806 GetVariableStore (Type
, StoreInfo
);
807 Status
= FindVariableEx (
813 if (!EFI_ERROR (Status
)) {
818 return EFI_NOT_FOUND
;
822 This service retrieves a variable's value using its name and GUID.
824 Read the specified variable from the UEFI variable store. If the Data
825 buffer is too small to hold the contents of the variable, the error
826 EFI_BUFFER_TOO_SMALL is returned and DataSize is set to the required buffer
827 size to obtain the data.
829 @param This A pointer to this instance of the EFI_PEI_READ_ONLY_VARIABLE2_PPI.
830 @param VariableName A pointer to a null-terminated string that is the variable's name.
831 @param VariableGuid A pointer to an EFI_GUID that is the variable's GUID. The combination of
832 VariableGuid and VariableName must be unique.
833 @param Attributes If non-NULL, on return, points to the variable's attributes.
834 @param DataSize On entry, points to the size in bytes of the Data buffer.
835 On return, points to the size of the data returned in Data.
836 @param Data Points to the buffer which will hold the returned variable value.
838 @retval EFI_SUCCESS The variable was read successfully.
839 @retval EFI_NOT_FOUND The variable could not be found.
840 @retval EFI_BUFFER_TOO_SMALL The DataSize is too small for the resulting data.
841 DataSize is updated with the size required for
842 the specified variable.
843 @retval EFI_INVALID_PARAMETER VariableName, VariableGuid, DataSize or Data is NULL.
844 @retval EFI_DEVICE_ERROR The variable could not be retrieved because of a device error.
850 IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI
*This
,
851 IN CONST CHAR16
*VariableName
,
852 IN CONST EFI_GUID
*VariableGuid
,
853 OUT UINT32
*Attributes
,
854 IN OUT UINTN
*DataSize
,
858 VARIABLE_POINTER_TRACK Variable
;
861 VARIABLE_STORE_INFO StoreInfo
;
862 VARIABLE_HEADER
*VariableHeader
;
864 if (VariableName
== NULL
|| VariableGuid
== NULL
|| DataSize
== NULL
) {
865 return EFI_INVALID_PARAMETER
;
869 // Find existing variable
871 Status
= FindVariable (VariableName
, VariableGuid
, &Variable
, &StoreInfo
);
872 if (EFI_ERROR (Status
)) {
875 GetVariableHeader (&StoreInfo
, Variable
.CurrPtr
, &VariableHeader
);
880 VarDataSize
= DataSizeOfVariable (VariableHeader
);
881 if (*DataSize
>= VarDataSize
) {
883 return EFI_INVALID_PARAMETER
;
886 GetVariableNameOrData (&StoreInfo
, GetVariableDataPtr (Variable
.CurrPtr
, VariableHeader
), VarDataSize
, Data
);
888 if (Attributes
!= NULL
) {
889 *Attributes
= VariableHeader
->Attributes
;
892 *DataSize
= VarDataSize
;
895 *DataSize
= VarDataSize
;
896 return EFI_BUFFER_TOO_SMALL
;
901 Return the next variable name and GUID.
903 This function is called multiple times to retrieve the VariableName
904 and VariableGuid of all variables currently available in the system.
905 On each call, the previous results are passed into the interface,
906 and, on return, the interface returns the data for the next
907 interface. When the entire variable list has been returned,
908 EFI_NOT_FOUND is returned.
910 @param This A pointer to this instance of the EFI_PEI_READ_ONLY_VARIABLE2_PPI.
912 @param VariableNameSize On entry, points to the size of the buffer pointed to by VariableName.
913 On return, the size of the variable name buffer.
914 @param VariableName On entry, a pointer to a null-terminated string that is the variable's name.
915 On return, points to the next variable's null-terminated name string.
916 @param VariableGuid On entry, a pointer to an EFI_GUID that is the variable's GUID.
917 On return, a pointer to the next variable's GUID.
919 @retval EFI_SUCCESS The variable was read successfully.
920 @retval EFI_NOT_FOUND The variable could not be found.
921 @retval EFI_BUFFER_TOO_SMALL The VariableNameSize is too small for the resulting
922 data. VariableNameSize is updated with the size
923 required for the specified variable.
924 @retval EFI_INVALID_PARAMETER VariableName, VariableGuid or
925 VariableNameSize is NULL.
926 @retval EFI_DEVICE_ERROR The variable could not be retrieved because of a device error.
931 PeiGetNextVariableName (
932 IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI
*This
,
933 IN OUT UINTN
*VariableNameSize
,
934 IN OUT CHAR16
*VariableName
,
935 IN OUT EFI_GUID
*VariableGuid
938 VARIABLE_STORE_TYPE Type
;
939 VARIABLE_POINTER_TRACK Variable
;
940 VARIABLE_POINTER_TRACK VariableInHob
;
941 VARIABLE_POINTER_TRACK VariablePtrTrack
;
944 VARIABLE_STORE_HEADER
*VariableStoreHeader
[VariableStoreTypeMax
];
945 VARIABLE_HEADER
*VariableHeader
;
946 VARIABLE_STORE_INFO StoreInfo
;
947 VARIABLE_STORE_INFO StoreInfoForNv
;
948 VARIABLE_STORE_INFO StoreInfoForHob
;
950 if (VariableName
== NULL
|| VariableGuid
== NULL
|| VariableNameSize
== NULL
) {
951 return EFI_INVALID_PARAMETER
;
954 Status
= FindVariable (VariableName
, VariableGuid
, &Variable
, &StoreInfo
);
955 if (Variable
.CurrPtr
== NULL
|| Status
!= EFI_SUCCESS
) {
959 if (VariableName
[0] != 0) {
961 // If variable name is not NULL, get next variable
963 GetVariableHeader (&StoreInfo
, Variable
.CurrPtr
, &VariableHeader
);
964 Variable
.CurrPtr
= GetNextVariablePtr (&StoreInfo
, Variable
.CurrPtr
, VariableHeader
);
967 VariableStoreHeader
[VariableStoreTypeHob
] = GetVariableStore (VariableStoreTypeHob
, &StoreInfoForHob
);
968 VariableStoreHeader
[VariableStoreTypeNv
] = GetVariableStore (VariableStoreTypeNv
, &StoreInfoForNv
);
972 // Switch from HOB to Non-Volatile.
974 while (!GetVariableHeader (&StoreInfo
, Variable
.CurrPtr
, &VariableHeader
)) {
976 // Find current storage index
978 for (Type
= (VARIABLE_STORE_TYPE
) 0; Type
< VariableStoreTypeMax
; Type
++) {
979 if ((VariableStoreHeader
[Type
] != NULL
) && (Variable
.StartPtr
== GetStartPointer (VariableStoreHeader
[Type
]))) {
983 ASSERT (Type
< VariableStoreTypeMax
);
985 // Switch to next storage
987 for (Type
++; Type
< VariableStoreTypeMax
; Type
++) {
988 if (VariableStoreHeader
[Type
] != NULL
) {
993 // Capture the case that
994 // 1. current storage is the last one, or
995 // 2. no further storage
997 if (Type
== VariableStoreTypeMax
) {
998 return EFI_NOT_FOUND
;
1000 Variable
.StartPtr
= GetStartPointer (VariableStoreHeader
[Type
]);
1001 Variable
.EndPtr
= GetEndPointer (VariableStoreHeader
[Type
]);
1002 Variable
.CurrPtr
= Variable
.StartPtr
;
1003 GetVariableStore (Type
, &StoreInfo
);
1006 if (VariableHeader
->State
== VAR_ADDED
|| VariableHeader
->State
== (VAR_IN_DELETED_TRANSITION
& VAR_ADDED
)) {
1007 if (VariableHeader
->State
== (VAR_IN_DELETED_TRANSITION
& VAR_ADDED
)) {
1009 // If it is a IN_DELETED_TRANSITION variable,
1010 // and there is also a same ADDED one at the same time,
1013 Status
= FindVariableEx (
1015 GetVariableNamePtr (Variable
.CurrPtr
),
1016 &VariableHeader
->VendorGuid
,
1019 if (!EFI_ERROR (Status
) && VariablePtrTrack
.CurrPtr
!= Variable
.CurrPtr
) {
1020 Variable
.CurrPtr
= GetNextVariablePtr (&StoreInfo
, Variable
.CurrPtr
, VariableHeader
);
1026 // Don't return NV variable when HOB overrides it
1028 if ((VariableStoreHeader
[VariableStoreTypeHob
] != NULL
) && (VariableStoreHeader
[VariableStoreTypeNv
] != NULL
) &&
1029 (Variable
.StartPtr
== GetStartPointer (VariableStoreHeader
[VariableStoreTypeNv
]))
1031 Status
= FindVariableEx (
1033 GetVariableNamePtr (Variable
.CurrPtr
),
1034 &VariableHeader
->VendorGuid
,
1037 if (!EFI_ERROR (Status
)) {
1038 Variable
.CurrPtr
= GetNextVariablePtr (&StoreInfo
, Variable
.CurrPtr
, VariableHeader
);
1043 VarNameSize
= NameSizeOfVariable (VariableHeader
);
1044 ASSERT (VarNameSize
!= 0);
1046 if (VarNameSize
<= *VariableNameSize
) {
1047 GetVariableNameOrData (&StoreInfo
, (UINT8
*) GetVariableNamePtr (Variable
.CurrPtr
), VarNameSize
, (UINT8
*) VariableName
);
1049 CopyMem (VariableGuid
, &VariableHeader
->VendorGuid
, sizeof (EFI_GUID
));
1051 Status
= EFI_SUCCESS
;
1053 Status
= EFI_BUFFER_TOO_SMALL
;
1056 *VariableNameSize
= VarNameSize
;
1058 // Variable is found
1062 Variable
.CurrPtr
= GetNextVariablePtr (&StoreInfo
, Variable
.CurrPtr
, VariableHeader
);