2 Implement ReadOnly Variable Services required by PEIM and install
3 PEI ReadOnly Varaiable2 PPI. These services operates the non volatile storage space.
5 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
22 EFI_PEI_READ_ONLY_VARIABLE2_PPI mVariablePpi
= {
24 PeiGetNextVariableName
27 EFI_PEI_PPI_DESCRIPTOR mPpiListVariable
= {
28 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
29 &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
) {
117 This code gets the size of variable header.
119 @param AuthFlag Authenticated variable flag.
121 @return Size of variable header in bytes in type UINTN.
125 GetVariableHeaderSize (
132 Value
= sizeof (AUTHENTICATED_VARIABLE_HEADER
);
134 Value
= sizeof (VARIABLE_HEADER
);
141 This code gets the size of name of variable.
143 @param Variable Pointer to the Variable Header.
144 @param AuthFlag Authenticated variable flag.
146 @return Size of variable in bytes in type UINTN.
151 IN VARIABLE_HEADER
*Variable
,
155 AUTHENTICATED_VARIABLE_HEADER
*AuthVariable
;
157 AuthVariable
= (AUTHENTICATED_VARIABLE_HEADER
*) Variable
;
159 if (AuthVariable
->State
== (UINT8
) (-1) ||
160 AuthVariable
->DataSize
== (UINT32
) (-1) ||
161 AuthVariable
->NameSize
== (UINT32
) (-1) ||
162 AuthVariable
->Attributes
== (UINT32
) (-1)) {
165 return (UINTN
) AuthVariable
->NameSize
;
167 if (Variable
->State
== (UINT8
) (-1) ||
168 Variable
->DataSize
== (UINT32
) (-1) ||
169 Variable
->NameSize
== (UINT32
) (-1) ||
170 Variable
->Attributes
== (UINT32
) (-1)) {
173 return (UINTN
) Variable
->NameSize
;
179 This code gets the size of data of variable.
181 @param Variable Pointer to the Variable Header.
182 @param AuthFlag Authenticated variable flag.
184 @return Size of variable in bytes in type UINTN.
189 IN VARIABLE_HEADER
*Variable
,
193 AUTHENTICATED_VARIABLE_HEADER
*AuthVariable
;
195 AuthVariable
= (AUTHENTICATED_VARIABLE_HEADER
*) Variable
;
197 if (AuthVariable
->State
== (UINT8
) (-1) ||
198 AuthVariable
->DataSize
== (UINT32
) (-1) ||
199 AuthVariable
->NameSize
== (UINT32
) (-1) ||
200 AuthVariable
->Attributes
== (UINT32
) (-1)) {
203 return (UINTN
) AuthVariable
->DataSize
;
205 if (Variable
->State
== (UINT8
) (-1) ||
206 Variable
->DataSize
== (UINT32
) (-1) ||
207 Variable
->NameSize
== (UINT32
) (-1) ||
208 Variable
->Attributes
== (UINT32
) (-1)) {
211 return (UINTN
) Variable
->DataSize
;
216 This code gets the pointer to the variable name.
218 @param Variable Pointer to the Variable Header.
219 @param AuthFlag Authenticated variable flag.
221 @return A CHAR16* pointer to Variable Name.
226 IN VARIABLE_HEADER
*Variable
,
230 return (CHAR16
*) ((UINTN
) Variable
+ GetVariableHeaderSize (AuthFlag
));
234 This code gets the pointer to the variable guid.
236 @param Variable Pointer to the Variable Header.
237 @param AuthFlag Authenticated variable flag.
239 @return A EFI_GUID* pointer to Vendor Guid.
244 IN VARIABLE_HEADER
*Variable
,
248 AUTHENTICATED_VARIABLE_HEADER
*AuthVariable
;
250 AuthVariable
= (AUTHENTICATED_VARIABLE_HEADER
*) Variable
;
252 return &AuthVariable
->VendorGuid
;
254 return &Variable
->VendorGuid
;
259 This code gets the pointer to the variable data.
261 @param Variable Pointer to the Variable Header.
262 @param VariableHeader Pointer to the Variable Header that has consecutive content.
263 @param AuthFlag Authenticated variable flag.
265 @return A UINT8* pointer to Variable Data.
270 IN VARIABLE_HEADER
*Variable
,
271 IN VARIABLE_HEADER
*VariableHeader
,
278 // Be careful about pad size for alignment
280 Value
= (UINTN
) GetVariableNamePtr (Variable
, AuthFlag
);
281 Value
+= NameSizeOfVariable (VariableHeader
, AuthFlag
);
282 Value
+= GET_PAD_SIZE (NameSizeOfVariable (VariableHeader
, AuthFlag
));
284 return (UINT8
*) Value
;
289 This code gets the pointer to the next variable header.
291 @param StoreInfo Pointer to variable store info structure.
292 @param Variable Pointer to the Variable Header.
293 @param VariableHeader Pointer to the Variable Header that has consecutive content.
295 @return A VARIABLE_HEADER* pointer to next variable header.
300 IN VARIABLE_STORE_INFO
*StoreInfo
,
301 IN VARIABLE_HEADER
*Variable
,
302 IN VARIABLE_HEADER
*VariableHeader
305 EFI_PHYSICAL_ADDRESS TargetAddress
;
306 EFI_PHYSICAL_ADDRESS SpareAddress
;
309 Value
= (UINTN
) GetVariableDataPtr (Variable
, VariableHeader
, StoreInfo
->AuthFlag
);
310 Value
+= DataSizeOfVariable (VariableHeader
, StoreInfo
->AuthFlag
);
311 Value
+= GET_PAD_SIZE (DataSizeOfVariable (VariableHeader
, StoreInfo
->AuthFlag
));
313 // Be careful about pad size for alignment
315 Value
= HEADER_ALIGN (Value
);
317 if (StoreInfo
->FtwLastWriteData
!= NULL
) {
318 TargetAddress
= StoreInfo
->FtwLastWriteData
->TargetAddress
;
319 SpareAddress
= StoreInfo
->FtwLastWriteData
->SpareAddress
;
320 if (((UINTN
) Variable
< (UINTN
) TargetAddress
) && (Value
>= (UINTN
) TargetAddress
)) {
322 // Next variable is in spare block.
324 Value
= (UINTN
) SpareAddress
+ (Value
- (UINTN
) TargetAddress
);
328 return (VARIABLE_HEADER
*) Value
;
332 Get variable store status.
334 @param VarStoreHeader Pointer to the Variable Store Header.
336 @retval EfiRaw Variable store is raw
337 @retval EfiValid Variable store is valid
338 @retval EfiInvalid Variable store is invalid
341 VARIABLE_STORE_STATUS
342 GetVariableStoreStatus (
343 IN VARIABLE_STORE_HEADER
*VarStoreHeader
346 if ((CompareGuid (&VarStoreHeader
->Signature
, &gEfiAuthenticatedVariableGuid
) ||
347 CompareGuid (&VarStoreHeader
->Signature
, &gEfiVariableGuid
)) &&
348 VarStoreHeader
->Format
== VARIABLE_STORE_FORMATTED
&&
349 VarStoreHeader
->State
== VARIABLE_STORE_HEALTHY
355 if (((UINT32
*)(&VarStoreHeader
->Signature
))[0] == 0xffffffff &&
356 ((UINT32
*)(&VarStoreHeader
->Signature
))[1] == 0xffffffff &&
357 ((UINT32
*)(&VarStoreHeader
->Signature
))[2] == 0xffffffff &&
358 ((UINT32
*)(&VarStoreHeader
->Signature
))[3] == 0xffffffff &&
359 VarStoreHeader
->Size
== 0xffffffff &&
360 VarStoreHeader
->Format
== 0xff &&
361 VarStoreHeader
->State
== 0xff
371 Compare two variable names, one of them may be inconsecutive.
373 @param StoreInfo Pointer to variable store info structure.
374 @param Name1 Pointer to one variable name.
375 @param Name2 Pointer to another variable name.
376 @param NameSize Variable name size.
378 @retval TRUE Name1 and Name2 are identical.
379 @retval FALSE Name1 and Name2 are not identical.
383 CompareVariableName (
384 IN VARIABLE_STORE_INFO
*StoreInfo
,
385 IN CONST CHAR16
*Name1
,
386 IN CONST CHAR16
*Name2
,
390 EFI_PHYSICAL_ADDRESS TargetAddress
;
391 EFI_PHYSICAL_ADDRESS SpareAddress
;
392 UINTN PartialNameSize
;
394 if (StoreInfo
->FtwLastWriteData
!= NULL
) {
395 TargetAddress
= StoreInfo
->FtwLastWriteData
->TargetAddress
;
396 SpareAddress
= StoreInfo
->FtwLastWriteData
->SpareAddress
;
397 if (((UINTN
) Name1
< (UINTN
) TargetAddress
) && (((UINTN
) Name1
+ NameSize
) > (UINTN
) TargetAddress
)) {
399 // Name1 is inconsecutive.
401 PartialNameSize
= (UINTN
) TargetAddress
- (UINTN
) Name1
;
403 // Partial content is in NV storage.
405 if (CompareMem ((UINT8
*) Name1
, (UINT8
*) Name2
, PartialNameSize
) == 0) {
407 // Another partial content is in spare block.
409 if (CompareMem ((UINT8
*) (UINTN
) SpareAddress
, (UINT8
*) Name2
+ PartialNameSize
, NameSize
- PartialNameSize
) == 0) {
414 } else if (((UINTN
) Name2
< (UINTN
) TargetAddress
) && (((UINTN
) Name2
+ NameSize
) > (UINTN
) TargetAddress
)) {
416 // Name2 is inconsecutive.
418 PartialNameSize
= (UINTN
) TargetAddress
- (UINTN
) Name2
;
420 // Partial content is in NV storage.
422 if (CompareMem ((UINT8
*) Name2
, (UINT8
*) Name1
, PartialNameSize
) == 0) {
424 // Another partial content is in spare block.
426 if (CompareMem ((UINT8
*) (UINTN
) SpareAddress
, (UINT8
*) Name1
+ PartialNameSize
, NameSize
- PartialNameSize
) == 0) {
435 // Both Name1 and Name2 are consecutive.
437 if (CompareMem ((UINT8
*) Name1
, (UINT8
*) Name2
, NameSize
) == 0) {
444 This function compares a variable with variable entries in database.
446 @param StoreInfo Pointer to variable store info structure.
447 @param Variable Pointer to the variable in our database
448 @param VariableHeader Pointer to the Variable Header that has consecutive content.
449 @param VariableName Name of the variable to compare to 'Variable'
450 @param VendorGuid GUID of the variable to compare to 'Variable'
451 @param PtrTrack Variable Track Pointer structure that contains Variable Information.
453 @retval EFI_SUCCESS Found match variable
454 @retval EFI_NOT_FOUND Variable not found
458 CompareWithValidVariable (
459 IN VARIABLE_STORE_INFO
*StoreInfo
,
460 IN VARIABLE_HEADER
*Variable
,
461 IN VARIABLE_HEADER
*VariableHeader
,
462 IN CONST CHAR16
*VariableName
,
463 IN CONST EFI_GUID
*VendorGuid
,
464 OUT VARIABLE_POINTER_TRACK
*PtrTrack
468 EFI_GUID
*TempVendorGuid
;
470 TempVendorGuid
= GetVendorGuidPtr (VariableHeader
, StoreInfo
->AuthFlag
);
472 if (VariableName
[0] == 0) {
473 PtrTrack
->CurrPtr
= Variable
;
477 // Don't use CompareGuid function here for performance reasons.
478 // Instead we compare the GUID a UINT32 at a time and branch
479 // on the first failed comparison.
481 if ((((INT32
*) VendorGuid
)[0] == ((INT32
*) TempVendorGuid
)[0]) &&
482 (((INT32
*) VendorGuid
)[1] == ((INT32
*) TempVendorGuid
)[1]) &&
483 (((INT32
*) VendorGuid
)[2] == ((INT32
*) TempVendorGuid
)[2]) &&
484 (((INT32
*) VendorGuid
)[3] == ((INT32
*) TempVendorGuid
)[3])
486 ASSERT (NameSizeOfVariable (VariableHeader
, StoreInfo
->AuthFlag
) != 0);
487 Point
= (VOID
*) GetVariableNamePtr (Variable
, StoreInfo
->AuthFlag
);
488 if (CompareVariableName (StoreInfo
, VariableName
, Point
, NameSizeOfVariable (VariableHeader
, StoreInfo
->AuthFlag
))) {
489 PtrTrack
->CurrPtr
= Variable
;
495 return EFI_NOT_FOUND
;
499 Get HOB variable store.
501 @param[out] StoreInfo Return the store info.
502 @param[out] VariableStoreHeader Return variable store header.
506 GetHobVariableStore (
507 OUT VARIABLE_STORE_INFO
*StoreInfo
,
508 OUT VARIABLE_STORE_HEADER
**VariableStoreHeader
511 EFI_HOB_GUID_TYPE
*GuidHob
;
514 // Make sure there is no more than one Variable HOB.
517 GuidHob
= GetFirstGuidHob (&gEfiAuthenticatedVariableGuid
);
518 if (GuidHob
!= NULL
) {
519 if ((GetNextGuidHob (&gEfiAuthenticatedVariableGuid
, GET_NEXT_HOB (GuidHob
)) != NULL
)) {
520 DEBUG ((DEBUG_ERROR
, "ERROR: Found two Auth Variable HOBs\n"));
522 } else if (GetFirstGuidHob (&gEfiVariableGuid
) != NULL
) {
523 DEBUG ((DEBUG_ERROR
, "ERROR: Found one Auth + one Normal Variable HOBs\n"));
527 GuidHob
= GetFirstGuidHob (&gEfiVariableGuid
);
528 if (GuidHob
!= NULL
) {
529 if ((GetNextGuidHob (&gEfiVariableGuid
, GET_NEXT_HOB (GuidHob
)) != NULL
)) {
530 DEBUG ((DEBUG_ERROR
, "ERROR: Found two Normal Variable HOBs\n"));
537 GuidHob
= GetFirstGuidHob (&gEfiAuthenticatedVariableGuid
);
538 if (GuidHob
!= NULL
) {
539 *VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) GET_GUID_HOB_DATA (GuidHob
);
540 StoreInfo
->AuthFlag
= TRUE
;
542 GuidHob
= GetFirstGuidHob (&gEfiVariableGuid
);
543 if (GuidHob
!= NULL
) {
544 *VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) GET_GUID_HOB_DATA (GuidHob
);
545 StoreInfo
->AuthFlag
= FALSE
;
551 Return the variable store header and the store info based on the Index.
553 @param Type The type of the variable store.
554 @param StoreInfo Return the store info.
556 @return Pointer to the variable store header.
558 VARIABLE_STORE_HEADER
*
560 IN VARIABLE_STORE_TYPE Type
,
561 OUT VARIABLE_STORE_INFO
*StoreInfo
564 EFI_HOB_GUID_TYPE
*GuidHob
;
565 EFI_FIRMWARE_VOLUME_HEADER
*FvHeader
;
566 VARIABLE_STORE_HEADER
*VariableStoreHeader
;
567 EFI_PHYSICAL_ADDRESS NvStorageBase
;
568 UINT32 NvStorageSize
;
569 FAULT_TOLERANT_WRITE_LAST_WRITE_DATA
*FtwLastWriteData
;
572 StoreInfo
->IndexTable
= NULL
;
573 StoreInfo
->FtwLastWriteData
= NULL
;
574 StoreInfo
->AuthFlag
= FALSE
;
575 VariableStoreHeader
= NULL
;
577 case VariableStoreTypeHob
:
578 GetHobVariableStore (StoreInfo
, &VariableStoreHeader
);
582 case VariableStoreTypeNv
:
583 if (GetBootModeHob () != BOOT_IN_RECOVERY_MODE
) {
585 // The content of NV storage for variable is not reliable in recovery boot mode.
588 NvStorageSize
= PcdGet32 (PcdFlashNvStorageVariableSize
);
589 NvStorageBase
= (EFI_PHYSICAL_ADDRESS
) (PcdGet64 (PcdFlashNvStorageVariableBase64
) != 0 ?
590 PcdGet64 (PcdFlashNvStorageVariableBase64
) :
591 PcdGet32 (PcdFlashNvStorageVariableBase
)
594 // First let FvHeader point to NV storage base.
596 FvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) (UINTN
) NvStorageBase
;
599 // Check the FTW last write data hob.
602 GuidHob
= GetFirstGuidHob (&gEdkiiFaultTolerantWriteGuid
);
603 if (GuidHob
!= NULL
) {
604 FtwLastWriteData
= (FAULT_TOLERANT_WRITE_LAST_WRITE_DATA
*) GET_GUID_HOB_DATA (GuidHob
);
605 if (FtwLastWriteData
->TargetAddress
== NvStorageBase
) {
607 // Let FvHeader point to spare block.
609 FvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) (UINTN
) FtwLastWriteData
->SpareAddress
;
610 DEBUG ((EFI_D_INFO
, "PeiVariable: NV storage is backed up in spare block: 0x%x\n", (UINTN
) FtwLastWriteData
->SpareAddress
));
611 } else if ((FtwLastWriteData
->TargetAddress
> NvStorageBase
) && (FtwLastWriteData
->TargetAddress
< (NvStorageBase
+ NvStorageSize
))) {
612 StoreInfo
->FtwLastWriteData
= FtwLastWriteData
;
614 // Flash NV storage from the offset is backed up in spare block.
616 BackUpOffset
= (UINT32
) (FtwLastWriteData
->TargetAddress
- NvStorageBase
);
617 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
));
619 // At least one block data in flash NV storage is still valid, so still leave FvHeader point to NV storage base.
625 // Check if the Firmware Volume is not corrupted
627 if ((FvHeader
->Signature
!= EFI_FVH_SIGNATURE
) || (!CompareGuid (&gEfiSystemNvDataFvGuid
, &FvHeader
->FileSystemGuid
))) {
628 DEBUG ((EFI_D_ERROR
, "Firmware Volume for Variable Store is corrupted\n"));
632 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) ((UINT8
*) FvHeader
+ FvHeader
->HeaderLength
);
634 StoreInfo
->AuthFlag
= (BOOLEAN
) (CompareGuid (&VariableStoreHeader
->Signature
, &gEfiAuthenticatedVariableGuid
));
636 GuidHob
= GetFirstGuidHob (&gEfiVariableIndexTableGuid
);
637 if (GuidHob
!= NULL
) {
638 StoreInfo
->IndexTable
= GET_GUID_HOB_DATA (GuidHob
);
641 // If it's the first time to access variable region in flash, create a guid hob to record
642 // VAR_ADDED type variable info.
643 // Note that as the resource of PEI phase is limited, only store the limited number of
644 // VAR_ADDED type variables to reduce access time.
646 StoreInfo
->IndexTable
= (VARIABLE_INDEX_TABLE
*) BuildGuidHob (&gEfiVariableIndexTableGuid
, sizeof (VARIABLE_INDEX_TABLE
));
647 StoreInfo
->IndexTable
->Length
= 0;
648 StoreInfo
->IndexTable
->StartPtr
= GetStartPointer (VariableStoreHeader
);
649 StoreInfo
->IndexTable
->EndPtr
= GetEndPointer (VariableStoreHeader
);
650 StoreInfo
->IndexTable
->GoneThrough
= 0;
660 StoreInfo
->VariableStoreHeader
= VariableStoreHeader
;
661 return VariableStoreHeader
;
665 Get variable header that has consecutive content.
667 @param StoreInfo Pointer to variable store info structure.
668 @param Variable Pointer to the Variable Header.
669 @param VariableHeader Pointer to Pointer to the Variable Header that has consecutive content.
671 @retval TRUE Variable header is valid.
672 @retval FALSE Variable header is not valid.
677 IN VARIABLE_STORE_INFO
*StoreInfo
,
678 IN VARIABLE_HEADER
*Variable
,
679 OUT VARIABLE_HEADER
**VariableHeader
682 EFI_PHYSICAL_ADDRESS TargetAddress
;
683 EFI_PHYSICAL_ADDRESS SpareAddress
;
684 EFI_HOB_GUID_TYPE
*GuidHob
;
685 UINTN PartialHeaderSize
;
687 if (Variable
== NULL
) {
692 // First assume variable header pointed by Variable is consecutive.
694 *VariableHeader
= Variable
;
696 if (StoreInfo
->FtwLastWriteData
!= NULL
) {
697 TargetAddress
= StoreInfo
->FtwLastWriteData
->TargetAddress
;
698 SpareAddress
= StoreInfo
->FtwLastWriteData
->SpareAddress
;
699 if (((UINTN
) Variable
> (UINTN
) SpareAddress
) &&
700 (((UINTN
) Variable
- (UINTN
) SpareAddress
+ (UINTN
) TargetAddress
) >= (UINTN
) GetEndPointer (StoreInfo
->VariableStoreHeader
))) {
702 // Reach the end of variable store.
706 if (((UINTN
) Variable
< (UINTN
) TargetAddress
) && (((UINTN
) Variable
+ GetVariableHeaderSize (StoreInfo
->AuthFlag
)) > (UINTN
) TargetAddress
)) {
708 // Variable header pointed by Variable is inconsecutive,
709 // create a guid hob to combine the two partial variable header content together.
711 GuidHob
= GetFirstGuidHob (&gEfiCallerIdGuid
);
712 if (GuidHob
!= NULL
) {
713 *VariableHeader
= (VARIABLE_HEADER
*) GET_GUID_HOB_DATA (GuidHob
);
715 *VariableHeader
= (VARIABLE_HEADER
*) BuildGuidHob (&gEfiCallerIdGuid
, GetVariableHeaderSize (StoreInfo
->AuthFlag
));
716 PartialHeaderSize
= (UINTN
) TargetAddress
- (UINTN
) Variable
;
718 // Partial content is in NV storage.
720 CopyMem ((UINT8
*) *VariableHeader
, (UINT8
*) Variable
, PartialHeaderSize
);
722 // Another partial content is in spare block.
724 CopyMem ((UINT8
*) *VariableHeader
+ PartialHeaderSize
, (UINT8
*) (UINTN
) SpareAddress
, GetVariableHeaderSize (StoreInfo
->AuthFlag
) - PartialHeaderSize
);
728 if (Variable
>= GetEndPointer (StoreInfo
->VariableStoreHeader
)) {
730 // Reach the end of variable store.
736 return IsValidVariableHeader (*VariableHeader
);
740 Get variable name or data to output buffer.
742 @param StoreInfo Pointer to variable store info structure.
743 @param NameOrData Pointer to the variable name/data that may be inconsecutive.
744 @param Size Variable name/data size.
745 @param Buffer Pointer to output buffer to hold the variable name/data.
749 GetVariableNameOrData (
750 IN VARIABLE_STORE_INFO
*StoreInfo
,
751 IN UINT8
*NameOrData
,
756 EFI_PHYSICAL_ADDRESS TargetAddress
;
757 EFI_PHYSICAL_ADDRESS SpareAddress
;
760 if (StoreInfo
->FtwLastWriteData
!= NULL
) {
761 TargetAddress
= StoreInfo
->FtwLastWriteData
->TargetAddress
;
762 SpareAddress
= StoreInfo
->FtwLastWriteData
->SpareAddress
;
763 if (((UINTN
) NameOrData
< (UINTN
) TargetAddress
) && (((UINTN
) NameOrData
+ Size
) > (UINTN
) TargetAddress
)) {
765 // Variable name/data is inconsecutive.
767 PartialSize
= (UINTN
) TargetAddress
- (UINTN
) NameOrData
;
769 // Partial content is in NV storage.
771 CopyMem (Buffer
, NameOrData
, PartialSize
);
773 // Another partial content is in spare block.
775 CopyMem (Buffer
+ PartialSize
, (UINT8
*) (UINTN
) SpareAddress
, Size
- PartialSize
);
781 // Variable name/data is consecutive.
783 CopyMem (Buffer
, NameOrData
, Size
);
787 Find the variable in the specified variable store.
789 @param StoreInfo Pointer to the store info structure.
790 @param VariableName Name of the variable to be found
791 @param VendorGuid Vendor GUID to be found.
792 @param PtrTrack Variable Track Pointer structure that contains Variable Information.
794 @retval EFI_SUCCESS Variable found successfully
795 @retval EFI_NOT_FOUND Variable not found
796 @retval EFI_INVALID_PARAMETER Invalid variable name
801 IN VARIABLE_STORE_INFO
*StoreInfo
,
802 IN CONST CHAR16
*VariableName
,
803 IN CONST EFI_GUID
*VendorGuid
,
804 OUT VARIABLE_POINTER_TRACK
*PtrTrack
807 VARIABLE_HEADER
*Variable
;
808 VARIABLE_HEADER
*LastVariable
;
809 VARIABLE_HEADER
*MaxIndex
;
813 VARIABLE_HEADER
*InDeletedVariable
;
814 VARIABLE_STORE_HEADER
*VariableStoreHeader
;
815 VARIABLE_INDEX_TABLE
*IndexTable
;
816 VARIABLE_HEADER
*VariableHeader
;
818 VariableStoreHeader
= StoreInfo
->VariableStoreHeader
;
820 if (VariableStoreHeader
== NULL
) {
821 return EFI_INVALID_PARAMETER
;
824 if (GetVariableStoreStatus (VariableStoreHeader
) != EfiValid
) {
825 return EFI_UNSUPPORTED
;
828 if (~VariableStoreHeader
->Size
== 0) {
829 return EFI_NOT_FOUND
;
832 IndexTable
= StoreInfo
->IndexTable
;
833 PtrTrack
->StartPtr
= GetStartPointer (VariableStoreHeader
);
834 PtrTrack
->EndPtr
= GetEndPointer (VariableStoreHeader
);
836 InDeletedVariable
= NULL
;
839 // No Variable Address equals zero, so 0 as initial value is safe.
842 VariableHeader
= NULL
;
844 if (IndexTable
!= NULL
) {
846 // traverse the variable index table to look for varible.
847 // The IndexTable->Index[Index] records the distance of two neighbouring VAR_ADDED type variables.
849 for (Offset
= 0, Index
= 0; Index
< IndexTable
->Length
; Index
++) {
850 ASSERT (Index
< sizeof (IndexTable
->Index
) / sizeof (IndexTable
->Index
[0]));
851 Offset
+= IndexTable
->Index
[Index
];
852 MaxIndex
= (VARIABLE_HEADER
*) ((UINT8
*) IndexTable
->StartPtr
+ Offset
);
853 GetVariableHeader (StoreInfo
, MaxIndex
, &VariableHeader
);
854 if (CompareWithValidVariable (StoreInfo
, MaxIndex
, VariableHeader
, VariableName
, VendorGuid
, PtrTrack
) == EFI_SUCCESS
) {
855 if (VariableHeader
->State
== (VAR_IN_DELETED_TRANSITION
& VAR_ADDED
)) {
856 InDeletedVariable
= PtrTrack
->CurrPtr
;
863 if (IndexTable
->GoneThrough
!= 0) {
865 // If the table has all the existing variables indexed, return.
867 PtrTrack
->CurrPtr
= InDeletedVariable
;
868 return (PtrTrack
->CurrPtr
== NULL
) ? EFI_NOT_FOUND
: EFI_SUCCESS
;
872 if (MaxIndex
!= NULL
) {
874 // HOB exists but the variable cannot be found in HOB
875 // If not found in HOB, then let's start from the MaxIndex we've found.
877 Variable
= GetNextVariablePtr (StoreInfo
, MaxIndex
, VariableHeader
);
878 LastVariable
= MaxIndex
;
881 // Start Pointers for the variable.
882 // Actual Data Pointer where data can be written.
884 Variable
= PtrTrack
->StartPtr
;
885 LastVariable
= PtrTrack
->StartPtr
;
889 // Find the variable by walk through variable store
892 while (GetVariableHeader (StoreInfo
, Variable
, &VariableHeader
)) {
893 if (VariableHeader
->State
== VAR_ADDED
|| VariableHeader
->State
== (VAR_IN_DELETED_TRANSITION
& VAR_ADDED
)) {
895 // Record Variable in VariableIndex HOB
897 if ((IndexTable
!= NULL
) && !StopRecord
) {
898 Offset
= (UINTN
) Variable
- (UINTN
) LastVariable
;
899 if ((Offset
> 0x0FFFF) || (IndexTable
->Length
== sizeof (IndexTable
->Index
) / sizeof (IndexTable
->Index
[0]))) {
901 // Stop to record if the distance of two neighbouring VAR_ADDED variable is larger than the allowable scope(UINT16),
902 // or the record buffer is full.
906 IndexTable
->Index
[IndexTable
->Length
++] = (UINT16
) Offset
;
907 LastVariable
= Variable
;
911 if (CompareWithValidVariable (StoreInfo
, Variable
, VariableHeader
, VariableName
, VendorGuid
, PtrTrack
) == EFI_SUCCESS
) {
912 if (VariableHeader
->State
== (VAR_IN_DELETED_TRANSITION
& VAR_ADDED
)) {
913 InDeletedVariable
= PtrTrack
->CurrPtr
;
920 Variable
= GetNextVariablePtr (StoreInfo
, Variable
, VariableHeader
);
923 // If gone through the VariableStore, that means we never find in Firmware any more.
925 if ((IndexTable
!= NULL
) && !StopRecord
) {
926 IndexTable
->GoneThrough
= 1;
929 PtrTrack
->CurrPtr
= InDeletedVariable
;
931 return (PtrTrack
->CurrPtr
== NULL
) ? EFI_NOT_FOUND
: EFI_SUCCESS
;
935 Find the variable in HOB and Non-Volatile variable storages.
937 @param VariableName Name of the variable to be found
938 @param VendorGuid Vendor GUID to be found.
939 @param PtrTrack Variable Track Pointer structure that contains Variable Information.
940 @param StoreInfo Return the store info.
942 @retval EFI_SUCCESS Variable found successfully
943 @retval EFI_NOT_FOUND Variable not found
944 @retval EFI_INVALID_PARAMETER Invalid variable name
948 IN CONST CHAR16
*VariableName
,
949 IN CONST EFI_GUID
*VendorGuid
,
950 OUT VARIABLE_POINTER_TRACK
*PtrTrack
,
951 OUT VARIABLE_STORE_INFO
*StoreInfo
955 VARIABLE_STORE_TYPE Type
;
957 if (VariableName
[0] != 0 && VendorGuid
== NULL
) {
958 return EFI_INVALID_PARAMETER
;
961 for (Type
= (VARIABLE_STORE_TYPE
) 0; Type
< VariableStoreTypeMax
; Type
++) {
962 GetVariableStore (Type
, StoreInfo
);
963 Status
= FindVariableEx (
969 if (!EFI_ERROR (Status
)) {
974 return EFI_NOT_FOUND
;
978 This service retrieves a variable's value using its name and GUID.
980 Read the specified variable from the UEFI variable store. If the Data
981 buffer is too small to hold the contents of the variable, the error
982 EFI_BUFFER_TOO_SMALL is returned and DataSize is set to the required buffer
983 size to obtain the data.
985 @param This A pointer to this instance of the EFI_PEI_READ_ONLY_VARIABLE2_PPI.
986 @param VariableName A pointer to a null-terminated string that is the variable's name.
987 @param VariableGuid A pointer to an EFI_GUID that is the variable's GUID. The combination of
988 VariableGuid and VariableName must be unique.
989 @param Attributes If non-NULL, on return, points to the variable's attributes.
990 @param DataSize On entry, points to the size in bytes of the Data buffer.
991 On return, points to the size of the data returned in Data.
992 @param Data Points to the buffer which will hold the returned variable value.
993 May be NULL with a zero DataSize in order to determine the size of the buffer needed.
995 @retval EFI_SUCCESS The variable was read successfully.
996 @retval EFI_NOT_FOUND The variable was be found.
997 @retval EFI_BUFFER_TOO_SMALL The DataSize is too small for the resulting data.
998 DataSize is updated with the size required for
999 the specified variable.
1000 @retval EFI_INVALID_PARAMETER VariableName, VariableGuid, DataSize or Data is NULL.
1001 @retval EFI_DEVICE_ERROR The variable could not be retrieved because of a device error.
1007 IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI
*This
,
1008 IN CONST CHAR16
*VariableName
,
1009 IN CONST EFI_GUID
*VariableGuid
,
1010 OUT UINT32
*Attributes
,
1011 IN OUT UINTN
*DataSize
,
1012 OUT VOID
*Data OPTIONAL
1015 VARIABLE_POINTER_TRACK Variable
;
1018 VARIABLE_STORE_INFO StoreInfo
;
1019 VARIABLE_HEADER
*VariableHeader
;
1021 if (VariableName
== NULL
|| VariableGuid
== NULL
|| DataSize
== NULL
) {
1022 return EFI_INVALID_PARAMETER
;
1025 if (VariableName
[0] == 0) {
1026 return EFI_NOT_FOUND
;
1029 VariableHeader
= NULL
;
1032 // Find existing variable
1034 Status
= FindVariable (VariableName
, VariableGuid
, &Variable
, &StoreInfo
);
1035 if (EFI_ERROR (Status
)) {
1038 GetVariableHeader (&StoreInfo
, Variable
.CurrPtr
, &VariableHeader
);
1043 VarDataSize
= DataSizeOfVariable (VariableHeader
, StoreInfo
.AuthFlag
);
1044 if (*DataSize
>= VarDataSize
) {
1046 return EFI_INVALID_PARAMETER
;
1049 GetVariableNameOrData (&StoreInfo
, GetVariableDataPtr (Variable
.CurrPtr
, VariableHeader
, StoreInfo
.AuthFlag
), VarDataSize
, Data
);
1051 if (Attributes
!= NULL
) {
1052 *Attributes
= VariableHeader
->Attributes
;
1055 *DataSize
= VarDataSize
;
1058 *DataSize
= VarDataSize
;
1059 return EFI_BUFFER_TOO_SMALL
;
1064 Return the next variable name and GUID.
1066 This function is called multiple times to retrieve the VariableName
1067 and VariableGuid of all variables currently available in the system.
1068 On each call, the previous results are passed into the interface,
1069 and, on return, the interface returns the data for the next
1070 interface. When the entire variable list has been returned,
1071 EFI_NOT_FOUND is returned.
1073 @param This A pointer to this instance of the EFI_PEI_READ_ONLY_VARIABLE2_PPI.
1075 @param VariableNameSize On entry, points to the size of the buffer pointed to by VariableName.
1076 On return, the size of the variable name buffer.
1077 @param VariableName On entry, a pointer to a null-terminated string that is the variable's name.
1078 On return, points to the next variable's null-terminated name string.
1079 @param VariableGuid On entry, a pointer to an EFI_GUID that is the variable's GUID.
1080 On return, a pointer to the next variable's GUID.
1082 @retval EFI_SUCCESS The variable was read successfully.
1083 @retval EFI_NOT_FOUND The variable could not be found.
1084 @retval EFI_BUFFER_TOO_SMALL The VariableNameSize is too small for the resulting
1085 data. VariableNameSize is updated with the size
1086 required for the specified variable.
1087 @retval EFI_INVALID_PARAMETER VariableName, VariableGuid or
1088 VariableNameSize is NULL.
1089 @retval EFI_DEVICE_ERROR The variable could not be retrieved because of a device error.
1094 PeiGetNextVariableName (
1095 IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI
*This
,
1096 IN OUT UINTN
*VariableNameSize
,
1097 IN OUT CHAR16
*VariableName
,
1098 IN OUT EFI_GUID
*VariableGuid
1101 VARIABLE_STORE_TYPE Type
;
1102 VARIABLE_POINTER_TRACK Variable
;
1103 VARIABLE_POINTER_TRACK VariableInHob
;
1104 VARIABLE_POINTER_TRACK VariablePtrTrack
;
1107 VARIABLE_STORE_HEADER
*VariableStoreHeader
[VariableStoreTypeMax
];
1108 VARIABLE_HEADER
*VariableHeader
;
1109 VARIABLE_STORE_INFO StoreInfo
;
1110 VARIABLE_STORE_INFO StoreInfoForNv
;
1111 VARIABLE_STORE_INFO StoreInfoForHob
;
1113 if (VariableName
== NULL
|| VariableGuid
== NULL
|| VariableNameSize
== NULL
) {
1114 return EFI_INVALID_PARAMETER
;
1117 VariableHeader
= NULL
;
1119 Status
= FindVariable (VariableName
, VariableGuid
, &Variable
, &StoreInfo
);
1120 if (Variable
.CurrPtr
== NULL
|| Status
!= EFI_SUCCESS
) {
1124 if (VariableName
[0] != 0) {
1126 // If variable name is not NULL, get next variable
1128 GetVariableHeader (&StoreInfo
, Variable
.CurrPtr
, &VariableHeader
);
1129 Variable
.CurrPtr
= GetNextVariablePtr (&StoreInfo
, Variable
.CurrPtr
, VariableHeader
);
1132 VariableStoreHeader
[VariableStoreTypeHob
] = GetVariableStore (VariableStoreTypeHob
, &StoreInfoForHob
);
1133 VariableStoreHeader
[VariableStoreTypeNv
] = GetVariableStore (VariableStoreTypeNv
, &StoreInfoForNv
);
1137 // Switch from HOB to Non-Volatile.
1139 while (!GetVariableHeader (&StoreInfo
, Variable
.CurrPtr
, &VariableHeader
)) {
1141 // Find current storage index
1143 for (Type
= (VARIABLE_STORE_TYPE
) 0; Type
< VariableStoreTypeMax
; Type
++) {
1144 if ((VariableStoreHeader
[Type
] != NULL
) && (Variable
.StartPtr
== GetStartPointer (VariableStoreHeader
[Type
]))) {
1148 ASSERT (Type
< VariableStoreTypeMax
);
1150 // Switch to next storage
1152 for (Type
++; Type
< VariableStoreTypeMax
; Type
++) {
1153 if (VariableStoreHeader
[Type
] != NULL
) {
1158 // Capture the case that
1159 // 1. current storage is the last one, or
1160 // 2. no further storage
1162 if (Type
== VariableStoreTypeMax
) {
1163 return EFI_NOT_FOUND
;
1165 Variable
.StartPtr
= GetStartPointer (VariableStoreHeader
[Type
]);
1166 Variable
.EndPtr
= GetEndPointer (VariableStoreHeader
[Type
]);
1167 Variable
.CurrPtr
= Variable
.StartPtr
;
1168 GetVariableStore (Type
, &StoreInfo
);
1171 if (VariableHeader
->State
== VAR_ADDED
|| VariableHeader
->State
== (VAR_IN_DELETED_TRANSITION
& VAR_ADDED
)) {
1172 if (VariableHeader
->State
== (VAR_IN_DELETED_TRANSITION
& VAR_ADDED
)) {
1174 // If it is a IN_DELETED_TRANSITION variable,
1175 // and there is also a same ADDED one at the same time,
1178 Status
= FindVariableEx (
1180 GetVariableNamePtr (Variable
.CurrPtr
, StoreInfo
.AuthFlag
),
1181 GetVendorGuidPtr (VariableHeader
, StoreInfo
.AuthFlag
),
1184 if (!EFI_ERROR (Status
) && VariablePtrTrack
.CurrPtr
!= Variable
.CurrPtr
) {
1185 Variable
.CurrPtr
= GetNextVariablePtr (&StoreInfo
, Variable
.CurrPtr
, VariableHeader
);
1191 // Don't return NV variable when HOB overrides it
1193 if ((VariableStoreHeader
[VariableStoreTypeHob
] != NULL
) && (VariableStoreHeader
[VariableStoreTypeNv
] != NULL
) &&
1194 (Variable
.StartPtr
== GetStartPointer (VariableStoreHeader
[VariableStoreTypeNv
]))
1196 Status
= FindVariableEx (
1198 GetVariableNamePtr (Variable
.CurrPtr
, StoreInfo
.AuthFlag
),
1199 GetVendorGuidPtr (VariableHeader
, StoreInfo
.AuthFlag
),
1202 if (!EFI_ERROR (Status
)) {
1203 Variable
.CurrPtr
= GetNextVariablePtr (&StoreInfo
, Variable
.CurrPtr
, VariableHeader
);
1208 VarNameSize
= NameSizeOfVariable (VariableHeader
, StoreInfo
.AuthFlag
);
1209 ASSERT (VarNameSize
!= 0);
1211 if (VarNameSize
<= *VariableNameSize
) {
1212 GetVariableNameOrData (&StoreInfo
, (UINT8
*) GetVariableNamePtr (Variable
.CurrPtr
, StoreInfo
.AuthFlag
), VarNameSize
, (UINT8
*) VariableName
);
1214 CopyMem (VariableGuid
, GetVendorGuidPtr (VariableHeader
, StoreInfo
.AuthFlag
), sizeof (EFI_GUID
));
1216 Status
= EFI_SUCCESS
;
1218 Status
= EFI_BUFFER_TOO_SMALL
;
1221 *VariableNameSize
= VarNameSize
;
1223 // Variable is found
1227 Variable
.CurrPtr
= GetNextVariablePtr (&StoreInfo
, Variable
.CurrPtr
, VariableHeader
);