2 The common variable operation routines shared by DXE_RUNTIME variable
3 module and DXE_SMM variable module.
5 Copyright (c) 2009 - 2012, 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.
17 #include "AuthService.h"
19 VARIABLE_MODULE_GLOBAL
*mVariableModuleGlobal
;
22 /// Define a memory cache that improves the search performance for a variable.
24 VARIABLE_STORE_HEADER
*mNvVariableCache
= NULL
;
27 /// The memory entry used for variable statistics data.
29 VARIABLE_INFO_ENTRY
*gVariableInfo
= NULL
;
33 Routine used to track statistical information about variable usage.
34 The data is stored in the EFI system table so it can be accessed later.
35 VariableInfo.efi can dump out the table. Only Boot Services variable
36 accesses are tracked by this code. The PcdVariableCollectStatistics
37 build flag controls if this feature is enabled.
39 A read that hits in the cache will have Read and Cache true for
40 the transaction. Data is allocated by this routine, but never
43 @param[in] VariableName Name of the Variable to track.
44 @param[in] VendorGuid Guid of the Variable to track.
45 @param[in] Volatile TRUE if volatile FALSE if non-volatile.
46 @param[in] Read TRUE if GetVariable() was called.
47 @param[in] Write TRUE if SetVariable() was called.
48 @param[in] Delete TRUE if deleted via SetVariable().
49 @param[in] Cache TRUE for a cache hit.
54 IN CHAR16
*VariableName
,
55 IN EFI_GUID
*VendorGuid
,
63 VARIABLE_INFO_ENTRY
*Entry
;
65 if (FeaturePcdGet (PcdVariableCollectStatistics
)) {
68 // Don't collect statistics at runtime.
72 if (gVariableInfo
== NULL
) {
74 // On the first call allocate a entry and place a pointer to it in
75 // the EFI System Table.
77 gVariableInfo
= AllocateZeroPool (sizeof (VARIABLE_INFO_ENTRY
));
78 ASSERT (gVariableInfo
!= NULL
);
80 CopyGuid (&gVariableInfo
->VendorGuid
, VendorGuid
);
81 gVariableInfo
->Name
= AllocatePool (StrSize (VariableName
));
82 ASSERT (gVariableInfo
->Name
!= NULL
);
83 StrCpy (gVariableInfo
->Name
, VariableName
);
84 gVariableInfo
->Volatile
= Volatile
;
88 for (Entry
= gVariableInfo
; Entry
!= NULL
; Entry
= Entry
->Next
) {
89 if (CompareGuid (VendorGuid
, &Entry
->VendorGuid
)) {
90 if (StrCmp (VariableName
, Entry
->Name
) == 0) {
108 if (Entry
->Next
== NULL
) {
110 // If the entry is not in the table add it.
111 // Next iteration of the loop will fill in the data.
113 Entry
->Next
= AllocateZeroPool (sizeof (VARIABLE_INFO_ENTRY
));
114 ASSERT (Entry
->Next
!= NULL
);
116 CopyGuid (&Entry
->Next
->VendorGuid
, VendorGuid
);
117 Entry
->Next
->Name
= AllocatePool (StrSize (VariableName
));
118 ASSERT (Entry
->Next
->Name
!= NULL
);
119 StrCpy (Entry
->Next
->Name
, VariableName
);
120 Entry
->Next
->Volatile
= Volatile
;
130 This code checks if variable header is valid or not.
132 @param Variable Pointer to the Variable Header.
134 @retval TRUE Variable header is valid.
135 @retval FALSE Variable header is not valid.
139 IsValidVariableHeader (
140 IN VARIABLE_HEADER
*Variable
143 if (Variable
== NULL
|| Variable
->StartId
!= VARIABLE_DATA
) {
153 This function writes data to the FWH at the correct LBA even if the LBAs
156 @param Global Pointer to VARAIBLE_GLOBAL structure.
157 @param Volatile Point out the Variable is Volatile or Non-Volatile.
158 @param SetByIndex TRUE if target pointer is given as index.
159 FALSE if target pointer is absolute.
160 @param Fvb Pointer to the writable FVB protocol.
161 @param DataPtrIndex Pointer to the Data from the end of VARIABLE_STORE_HEADER
163 @param DataSize Size of data to be written.
164 @param Buffer Pointer to the buffer from which data is written.
166 @retval EFI_INVALID_PARAMETER Parameters not valid.
167 @retval EFI_SUCCESS Variable store successfully updated.
171 UpdateVariableStore (
172 IN VARIABLE_GLOBAL
*Global
,
174 IN BOOLEAN SetByIndex
,
175 IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*Fvb
,
176 IN UINTN DataPtrIndex
,
181 EFI_FV_BLOCK_MAP_ENTRY
*PtrBlockMapEntry
;
189 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
190 VARIABLE_STORE_HEADER
*VolatileBase
;
191 EFI_PHYSICAL_ADDRESS FvVolHdr
;
192 EFI_PHYSICAL_ADDRESS DataPtr
;
196 DataPtr
= DataPtrIndex
;
199 // Check if the Data is Volatile.
203 return EFI_INVALID_PARAMETER
;
205 Status
= Fvb
->GetPhysicalAddress(Fvb
, &FvVolHdr
);
206 ASSERT_EFI_ERROR (Status
);
208 FwVolHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) ((UINTN
) FvVolHdr
);
210 // Data Pointer should point to the actual Address where data is to be
214 DataPtr
+= mVariableModuleGlobal
->VariableGlobal
.NonVolatileVariableBase
;
217 if ((DataPtr
+ DataSize
) >= ((EFI_PHYSICAL_ADDRESS
) (UINTN
) ((UINT8
*) FwVolHeader
+ FwVolHeader
->FvLength
))) {
218 return EFI_INVALID_PARAMETER
;
222 // Data Pointer should point to the actual Address where data is to be
225 VolatileBase
= (VARIABLE_STORE_HEADER
*) ((UINTN
) mVariableModuleGlobal
->VariableGlobal
.VolatileVariableBase
);
227 DataPtr
+= mVariableModuleGlobal
->VariableGlobal
.VolatileVariableBase
;
230 if ((DataPtr
+ DataSize
) >= ((UINTN
) ((UINT8
*) VolatileBase
+ VolatileBase
->Size
))) {
231 return EFI_INVALID_PARAMETER
;
235 // If Volatile Variable just do a simple mem copy.
237 CopyMem ((UINT8
*)(UINTN
)DataPtr
, Buffer
, DataSize
);
242 // If we are here we are dealing with Non-Volatile Variables.
244 LinearOffset
= (UINTN
) FwVolHeader
;
245 CurrWritePtr
= (UINTN
) DataPtr
;
246 CurrWriteSize
= DataSize
;
250 if (CurrWritePtr
< LinearOffset
) {
251 return EFI_INVALID_PARAMETER
;
254 for (PtrBlockMapEntry
= FwVolHeader
->BlockMap
; PtrBlockMapEntry
->NumBlocks
!= 0; PtrBlockMapEntry
++) {
255 for (BlockIndex2
= 0; BlockIndex2
< PtrBlockMapEntry
->NumBlocks
; BlockIndex2
++) {
257 // Check to see if the Variable Writes are spanning through multiple
260 if ((CurrWritePtr
>= LinearOffset
) && (CurrWritePtr
< LinearOffset
+ PtrBlockMapEntry
->Length
)) {
261 if ((CurrWritePtr
+ CurrWriteSize
) <= (LinearOffset
+ PtrBlockMapEntry
->Length
)) {
262 Status
= Fvb
->Write (
265 (UINTN
) (CurrWritePtr
- LinearOffset
),
271 Size
= (UINT32
) (LinearOffset
+ PtrBlockMapEntry
->Length
- CurrWritePtr
);
272 Status
= Fvb
->Write (
275 (UINTN
) (CurrWritePtr
- LinearOffset
),
279 if (EFI_ERROR (Status
)) {
283 CurrWritePtr
= LinearOffset
+ PtrBlockMapEntry
->Length
;
284 CurrBuffer
= CurrBuffer
+ Size
;
285 CurrWriteSize
= CurrWriteSize
- Size
;
289 LinearOffset
+= PtrBlockMapEntry
->Length
;
300 This code gets the current status of Variable Store.
302 @param VarStoreHeader Pointer to the Variable Store Header.
304 @retval EfiRaw Variable store status is raw.
305 @retval EfiValid Variable store status is valid.
306 @retval EfiInvalid Variable store status is invalid.
309 VARIABLE_STORE_STATUS
310 GetVariableStoreStatus (
311 IN VARIABLE_STORE_HEADER
*VarStoreHeader
314 if (CompareGuid (&VarStoreHeader
->Signature
, &gEfiAuthenticatedVariableGuid
) &&
315 VarStoreHeader
->Format
== VARIABLE_STORE_FORMATTED
&&
316 VarStoreHeader
->State
== VARIABLE_STORE_HEALTHY
320 } else if (((UINT32
*)(&VarStoreHeader
->Signature
))[0] == 0xffffffff &&
321 ((UINT32
*)(&VarStoreHeader
->Signature
))[1] == 0xffffffff &&
322 ((UINT32
*)(&VarStoreHeader
->Signature
))[2] == 0xffffffff &&
323 ((UINT32
*)(&VarStoreHeader
->Signature
))[3] == 0xffffffff &&
324 VarStoreHeader
->Size
== 0xffffffff &&
325 VarStoreHeader
->Format
== 0xff &&
326 VarStoreHeader
->State
== 0xff
338 This code gets the size of name of variable.
340 @param Variable Pointer to the Variable Header.
342 @return UINTN Size of variable in bytes.
347 IN VARIABLE_HEADER
*Variable
350 if (Variable
->State
== (UINT8
) (-1) ||
351 Variable
->DataSize
== (UINT32
) (-1) ||
352 Variable
->NameSize
== (UINT32
) (-1) ||
353 Variable
->Attributes
== (UINT32
) (-1)) {
356 return (UINTN
) Variable
->NameSize
;
361 This code gets the size of variable data.
363 @param Variable Pointer to the Variable Header.
365 @return Size of variable in bytes.
370 IN VARIABLE_HEADER
*Variable
373 if (Variable
->State
== (UINT8
) (-1) ||
374 Variable
->DataSize
== (UINT32
) (-1) ||
375 Variable
->NameSize
== (UINT32
) (-1) ||
376 Variable
->Attributes
== (UINT32
) (-1)) {
379 return (UINTN
) Variable
->DataSize
;
384 This code gets the pointer to the variable name.
386 @param Variable Pointer to the Variable Header.
388 @return Pointer to Variable Name which is Unicode encoding.
393 IN VARIABLE_HEADER
*Variable
397 return (CHAR16
*) (Variable
+ 1);
402 This code gets the pointer to the variable data.
404 @param Variable Pointer to the Variable Header.
406 @return Pointer to Variable Data.
411 IN VARIABLE_HEADER
*Variable
417 // Be careful about pad size for alignment.
419 Value
= (UINTN
) GetVariableNamePtr (Variable
);
420 Value
+= NameSizeOfVariable (Variable
);
421 Value
+= GET_PAD_SIZE (NameSizeOfVariable (Variable
));
423 return (UINT8
*) Value
;
429 This code gets the pointer to the next variable header.
431 @param Variable Pointer to the Variable Header.
433 @return Pointer to next variable header.
438 IN VARIABLE_HEADER
*Variable
443 if (!IsValidVariableHeader (Variable
)) {
447 Value
= (UINTN
) GetVariableDataPtr (Variable
);
448 Value
+= DataSizeOfVariable (Variable
);
449 Value
+= GET_PAD_SIZE (DataSizeOfVariable (Variable
));
452 // Be careful about pad size for alignment.
454 return (VARIABLE_HEADER
*) HEADER_ALIGN (Value
);
459 Gets the pointer to the first variable header in given variable store area.
461 @param VarStoreHeader Pointer to the Variable Store Header.
463 @return Pointer to the first variable header.
468 IN VARIABLE_STORE_HEADER
*VarStoreHeader
472 // The end of variable store.
474 return (VARIABLE_HEADER
*) HEADER_ALIGN (VarStoreHeader
+ 1);
479 Gets the pointer to the end of the variable storage area.
481 This function gets pointer to the end of the variable storage
482 area, according to the input variable store header.
484 @param VarStoreHeader Pointer to the Variable Store Header.
486 @return Pointer to the end of the variable storage area.
491 IN VARIABLE_STORE_HEADER
*VarStoreHeader
495 // The end of variable store
497 return (VARIABLE_HEADER
*) HEADER_ALIGN ((UINTN
) VarStoreHeader
+ VarStoreHeader
->Size
);
503 Variable store garbage collection and reclaim operation.
505 @param VariableBase Base address of variable store.
506 @param LastVariableOffset Offset of last variable.
507 @param IsVolatile The variable store is volatile or not;
508 if it is non-volatile, need FTW.
509 @param UpdatingVariable Pointer to updating variable.
511 @return EFI_OUT_OF_RESOURCES
518 IN EFI_PHYSICAL_ADDRESS VariableBase
,
519 OUT UINTN
*LastVariableOffset
,
520 IN BOOLEAN IsVolatile
,
521 IN VARIABLE_HEADER
*UpdatingVariable
524 VARIABLE_HEADER
*Variable
;
525 VARIABLE_HEADER
*AddedVariable
;
526 VARIABLE_HEADER
*NextVariable
;
527 VARIABLE_HEADER
*NextAddedVariable
;
528 VARIABLE_STORE_HEADER
*VariableStoreHeader
;
530 UINTN MaximumBufferSize
;
532 UINTN VariableNameSize
;
533 UINTN UpdatingVariableNameSize
;
540 CHAR16
*VariableNamePtr
;
541 CHAR16
*UpdatingVariableNamePtr
;
543 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) ((UINTN
) VariableBase
);
545 // Recalculate the total size of Common/HwErr type variables in non-volatile area.
548 mVariableModuleGlobal
->CommonVariableTotalSize
= 0;
549 mVariableModuleGlobal
->HwErrVariableTotalSize
= 0;
553 // Start Pointers for the variable.
555 Variable
= GetStartPointer (VariableStoreHeader
);
556 MaximumBufferSize
= sizeof (VARIABLE_STORE_HEADER
);
558 while (IsValidVariableHeader (Variable
)) {
559 NextVariable
= GetNextVariablePtr (Variable
);
560 if (Variable
->State
== VAR_ADDED
||
561 Variable
->State
== (VAR_IN_DELETED_TRANSITION
& VAR_ADDED
)
563 VariableSize
= (UINTN
) NextVariable
- (UINTN
) Variable
;
564 MaximumBufferSize
+= VariableSize
;
567 Variable
= NextVariable
;
571 // Reserve the 1 Bytes with Oxff to identify the
572 // end of the variable buffer.
574 MaximumBufferSize
+= 1;
575 ValidBuffer
= AllocatePool (MaximumBufferSize
);
576 if (ValidBuffer
== NULL
) {
577 return EFI_OUT_OF_RESOURCES
;
580 SetMem (ValidBuffer
, MaximumBufferSize
, 0xff);
583 // Copy variable store header.
585 CopyMem (ValidBuffer
, VariableStoreHeader
, sizeof (VARIABLE_STORE_HEADER
));
586 CurrPtr
= (UINT8
*) GetStartPointer ((VARIABLE_STORE_HEADER
*) ValidBuffer
);
589 // Reinstall all ADDED variables as long as they are not identical to Updating Variable.
591 Variable
= GetStartPointer (VariableStoreHeader
);
592 while (IsValidVariableHeader (Variable
)) {
593 NextVariable
= GetNextVariablePtr (Variable
);
594 if (Variable
->State
== VAR_ADDED
) {
595 if (UpdatingVariable
!= NULL
) {
596 if (UpdatingVariable
== Variable
) {
597 Variable
= NextVariable
;
601 VariableNameSize
= NameSizeOfVariable(Variable
);
602 UpdatingVariableNameSize
= NameSizeOfVariable(UpdatingVariable
);
604 VariableNamePtr
= GetVariableNamePtr (Variable
);
605 UpdatingVariableNamePtr
= GetVariableNamePtr (UpdatingVariable
);
606 if (CompareGuid (&Variable
->VendorGuid
, &UpdatingVariable
->VendorGuid
) &&
607 VariableNameSize
== UpdatingVariableNameSize
&&
608 CompareMem (VariableNamePtr
, UpdatingVariableNamePtr
, VariableNameSize
) == 0 ) {
609 Variable
= NextVariable
;
613 VariableSize
= (UINTN
) NextVariable
- (UINTN
) Variable
;
614 CopyMem (CurrPtr
, (UINT8
*) Variable
, VariableSize
);
615 CurrPtr
+= VariableSize
;
616 if ((!IsVolatile
) && ((Variable
->Attributes
& EFI_VARIABLE_HARDWARE_ERROR_RECORD
) == EFI_VARIABLE_HARDWARE_ERROR_RECORD
)) {
617 mVariableModuleGlobal
->HwErrVariableTotalSize
+= VariableSize
;
618 } else if ((!IsVolatile
) && ((Variable
->Attributes
& EFI_VARIABLE_HARDWARE_ERROR_RECORD
) != EFI_VARIABLE_HARDWARE_ERROR_RECORD
)) {
619 mVariableModuleGlobal
->CommonVariableTotalSize
+= VariableSize
;
622 Variable
= NextVariable
;
626 // Reinstall the variable being updated if it is not NULL.
628 if (UpdatingVariable
!= NULL
) {
629 VariableSize
= (UINTN
)(GetNextVariablePtr (UpdatingVariable
)) - (UINTN
)UpdatingVariable
;
630 CopyMem (CurrPtr
, (UINT8
*) UpdatingVariable
, VariableSize
);
631 CurrPtr
+= VariableSize
;
632 if ((!IsVolatile
) && ((UpdatingVariable
->Attributes
& EFI_VARIABLE_HARDWARE_ERROR_RECORD
) == EFI_VARIABLE_HARDWARE_ERROR_RECORD
)) {
633 mVariableModuleGlobal
->HwErrVariableTotalSize
+= VariableSize
;
634 } else if ((!IsVolatile
) && ((UpdatingVariable
->Attributes
& EFI_VARIABLE_HARDWARE_ERROR_RECORD
) != EFI_VARIABLE_HARDWARE_ERROR_RECORD
)) {
635 mVariableModuleGlobal
->CommonVariableTotalSize
+= VariableSize
;
640 // Reinstall all in delete transition variables.
642 Variable
= GetStartPointer (VariableStoreHeader
);
643 while (IsValidVariableHeader (Variable
)) {
644 NextVariable
= GetNextVariablePtr (Variable
);
645 if (Variable
!= UpdatingVariable
&& Variable
->State
== (VAR_IN_DELETED_TRANSITION
& VAR_ADDED
)) {
648 // Buffer has cached all ADDED variable.
649 // Per IN_DELETED variable, we have to guarantee that
650 // no ADDED one in previous buffer.
654 AddedVariable
= GetStartPointer ((VARIABLE_STORE_HEADER
*) ValidBuffer
);
655 while (IsValidVariableHeader (AddedVariable
)) {
656 NextAddedVariable
= GetNextVariablePtr (AddedVariable
);
657 NameSize
= NameSizeOfVariable (AddedVariable
);
658 if (CompareGuid (&AddedVariable
->VendorGuid
, &Variable
->VendorGuid
) &&
659 NameSize
== NameSizeOfVariable (Variable
)
661 Point0
= (VOID
*) GetVariableNamePtr (AddedVariable
);
662 Point1
= (VOID
*) GetVariableNamePtr (Variable
);
663 if (CompareMem (Point0
, Point1
, NameSizeOfVariable (AddedVariable
)) == 0) {
668 AddedVariable
= NextAddedVariable
;
672 // Promote VAR_IN_DELETED_TRANSITION to VAR_ADDED.
674 VariableSize
= (UINTN
) NextVariable
- (UINTN
) Variable
;
675 CopyMem (CurrPtr
, (UINT8
*) Variable
, VariableSize
);
676 ((VARIABLE_HEADER
*) CurrPtr
)->State
= VAR_ADDED
;
677 CurrPtr
+= VariableSize
;
678 if ((!IsVolatile
) && ((Variable
->Attributes
& EFI_VARIABLE_HARDWARE_ERROR_RECORD
) == EFI_VARIABLE_HARDWARE_ERROR_RECORD
)) {
679 mVariableModuleGlobal
->HwErrVariableTotalSize
+= VariableSize
;
680 } else if ((!IsVolatile
) && ((Variable
->Attributes
& EFI_VARIABLE_HARDWARE_ERROR_RECORD
) != EFI_VARIABLE_HARDWARE_ERROR_RECORD
)) {
681 mVariableModuleGlobal
->CommonVariableTotalSize
+= VariableSize
;
686 Variable
= NextVariable
;
691 // If volatile variable store, just copy valid buffer.
693 SetMem ((UINT8
*) (UINTN
) VariableBase
, VariableStoreHeader
->Size
, 0xff);
694 CopyMem ((UINT8
*) (UINTN
) VariableBase
, ValidBuffer
, (UINTN
) (CurrPtr
- (UINT8
*) ValidBuffer
));
695 Status
= EFI_SUCCESS
;
698 // If non-volatile variable store, perform FTW here.
700 Status
= FtwVariableSpace (
703 (UINTN
) (CurrPtr
- (UINT8
*) ValidBuffer
)
705 CopyMem (mNvVariableCache
, (CHAR8
*)(UINTN
)VariableBase
, VariableStoreHeader
->Size
);
707 if (!EFI_ERROR (Status
)) {
708 *LastVariableOffset
= (UINTN
) (CurrPtr
- (UINT8
*) ValidBuffer
);
710 *LastVariableOffset
= 0;
713 FreePool (ValidBuffer
);
719 Find the variable in the specified variable store.
721 @param[in] VariableName Name of the variable to be found
722 @param[in] VendorGuid Vendor GUID to be found.
723 @param[in] IgnoreRtCheck Ignore EFI_VARIABLE_RUNTIME_ACCESS attribute
724 check at runtime when searching variable.
725 @param[in, out] PtrTrack Variable Track Pointer structure that contains Variable Information.
727 @retval EFI_SUCCESS Variable found successfully
728 @retval EFI_NOT_FOUND Variable not found
732 IN CHAR16
*VariableName
,
733 IN EFI_GUID
*VendorGuid
,
734 IN BOOLEAN IgnoreRtCheck
,
735 IN OUT VARIABLE_POINTER_TRACK
*PtrTrack
738 VARIABLE_HEADER
*InDeletedVariable
;
742 // Find the variable by walk through HOB, volatile and non-volatile variable store.
744 InDeletedVariable
= NULL
;
746 for ( PtrTrack
->CurrPtr
= PtrTrack
->StartPtr
747 ; (PtrTrack
->CurrPtr
< PtrTrack
->EndPtr
) && IsValidVariableHeader (PtrTrack
->CurrPtr
)
748 ; PtrTrack
->CurrPtr
= GetNextVariablePtr (PtrTrack
->CurrPtr
)
750 if (PtrTrack
->CurrPtr
->State
== VAR_ADDED
||
751 PtrTrack
->CurrPtr
->State
== (VAR_IN_DELETED_TRANSITION
& VAR_ADDED
)
753 if (IgnoreRtCheck
|| !AtRuntime () || ((PtrTrack
->CurrPtr
->Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
) != 0)) {
754 if (VariableName
[0] == 0) {
755 if (PtrTrack
->CurrPtr
->State
== (VAR_IN_DELETED_TRANSITION
& VAR_ADDED
)) {
756 InDeletedVariable
= PtrTrack
->CurrPtr
;
761 if (CompareGuid (VendorGuid
, &PtrTrack
->CurrPtr
->VendorGuid
)) {
762 Point
= (VOID
*) GetVariableNamePtr (PtrTrack
->CurrPtr
);
764 ASSERT (NameSizeOfVariable (PtrTrack
->CurrPtr
) != 0);
765 if (CompareMem (VariableName
, Point
, NameSizeOfVariable (PtrTrack
->CurrPtr
)) == 0) {
766 if (PtrTrack
->CurrPtr
->State
== (VAR_IN_DELETED_TRANSITION
& VAR_ADDED
)) {
767 InDeletedVariable
= PtrTrack
->CurrPtr
;
778 PtrTrack
->CurrPtr
= InDeletedVariable
;
779 return (PtrTrack
->CurrPtr
== NULL
) ? EFI_NOT_FOUND
: EFI_SUCCESS
;
784 Finds variable in storage blocks of volatile and non-volatile storage areas.
786 This code finds variable in storage blocks of volatile and non-volatile storage areas.
787 If VariableName is an empty string, then we just return the first
788 qualified variable without comparing VariableName and VendorGuid.
789 If IgnoreRtCheck is TRUE, then we ignore the EFI_VARIABLE_RUNTIME_ACCESS attribute check
790 at runtime when searching existing variable, only VariableName and VendorGuid are compared.
791 Otherwise, variables without EFI_VARIABLE_RUNTIME_ACCESS are not visible at runtime.
793 @param[in] VariableName Name of the variable to be found.
794 @param[in] VendorGuid Vendor GUID to be found.
795 @param[out] PtrTrack VARIABLE_POINTER_TRACK structure for output,
796 including the range searched and the target position.
797 @param[in] Global Pointer to VARIABLE_GLOBAL structure, including
798 base of volatile variable storage area, base of
799 NV variable storage area, and a lock.
800 @param[in] IgnoreRtCheck Ignore EFI_VARIABLE_RUNTIME_ACCESS attribute
801 check at runtime when searching variable.
803 @retval EFI_INVALID_PARAMETER If VariableName is not an empty string, while
805 @retval EFI_SUCCESS Variable successfully found.
806 @retval EFI_NOT_FOUND Variable not found
811 IN CHAR16
*VariableName
,
812 IN EFI_GUID
*VendorGuid
,
813 OUT VARIABLE_POINTER_TRACK
*PtrTrack
,
814 IN VARIABLE_GLOBAL
*Global
,
815 IN BOOLEAN IgnoreRtCheck
819 VARIABLE_STORE_HEADER
*VariableStoreHeader
[VariableStoreTypeMax
];
820 VARIABLE_STORE_TYPE Type
;
822 if (VariableName
[0] != 0 && VendorGuid
== NULL
) {
823 return EFI_INVALID_PARAMETER
;
827 // 0: Volatile, 1: HOB, 2: Non-Volatile.
828 // The index and attributes mapping must be kept in this order as RuntimeServiceGetNextVariableName
829 // make use of this mapping to implement search algorithm.
831 VariableStoreHeader
[VariableStoreTypeVolatile
] = (VARIABLE_STORE_HEADER
*) (UINTN
) Global
->VolatileVariableBase
;
832 VariableStoreHeader
[VariableStoreTypeHob
] = (VARIABLE_STORE_HEADER
*) (UINTN
) Global
->HobVariableBase
;
833 VariableStoreHeader
[VariableStoreTypeNv
] = mNvVariableCache
;
836 // Find the variable by walk through HOB, volatile and non-volatile variable store.
838 for (Type
= (VARIABLE_STORE_TYPE
) 0; Type
< VariableStoreTypeMax
; Type
++) {
839 if (VariableStoreHeader
[Type
] == NULL
) {
843 PtrTrack
->StartPtr
= GetStartPointer (VariableStoreHeader
[Type
]);
844 PtrTrack
->EndPtr
= GetEndPointer (VariableStoreHeader
[Type
]);
845 PtrTrack
->Volatile
= (BOOLEAN
) (Type
== VariableStoreTypeVolatile
);
847 Status
= FindVariableEx (VariableName
, VendorGuid
, IgnoreRtCheck
, PtrTrack
);
848 if (!EFI_ERROR (Status
)) {
852 return EFI_NOT_FOUND
;
856 Get index from supported language codes according to language string.
858 This code is used to get corresponding index in supported language codes. It can handle
859 RFC4646 and ISO639 language tags.
860 In ISO639 language tags, take 3-characters as a delimitation to find matched string and calculate the index.
861 In RFC4646 language tags, take semicolon as a delimitation to find matched string and calculate the index.
864 SupportedLang = "engfraengfra"
866 Iso639Language = TRUE
867 The return value is "0".
869 SupportedLang = "en;fr;en-US;fr-FR"
871 Iso639Language = FALSE
872 The return value is "3".
874 @param SupportedLang Platform supported language codes.
875 @param Lang Configured language.
876 @param Iso639Language A bool value to signify if the handler is operated on ISO639 or RFC4646.
878 @retval The index of language in the language codes.
882 GetIndexFromSupportedLangCodes(
883 IN CHAR8
*SupportedLang
,
885 IN BOOLEAN Iso639Language
890 UINTN LanguageLength
;
892 if (Iso639Language
) {
893 CompareLength
= ISO_639_2_ENTRY_SIZE
;
894 for (Index
= 0; Index
< AsciiStrLen (SupportedLang
); Index
+= CompareLength
) {
895 if (AsciiStrnCmp (Lang
, SupportedLang
+ Index
, CompareLength
) == 0) {
897 // Successfully find the index of Lang string in SupportedLang string.
899 Index
= Index
/ CompareLength
;
907 // Compare RFC4646 language code
910 for (LanguageLength
= 0; Lang
[LanguageLength
] != '\0'; LanguageLength
++);
912 for (Index
= 0; *SupportedLang
!= '\0'; Index
++, SupportedLang
+= CompareLength
) {
914 // Skip ';' characters in SupportedLang
916 for (; *SupportedLang
!= '\0' && *SupportedLang
== ';'; SupportedLang
++);
918 // Determine the length of the next language code in SupportedLang
920 for (CompareLength
= 0; SupportedLang
[CompareLength
] != '\0' && SupportedLang
[CompareLength
] != ';'; CompareLength
++);
922 if ((CompareLength
== LanguageLength
) &&
923 (AsciiStrnCmp (Lang
, SupportedLang
, CompareLength
) == 0)) {
925 // Successfully find the index of Lang string in SupportedLang string.
936 Get language string from supported language codes according to index.
938 This code is used to get corresponding language strings in supported language codes. It can handle
939 RFC4646 and ISO639 language tags.
940 In ISO639 language tags, take 3-characters as a delimitation. Find language string according to the index.
941 In RFC4646 language tags, take semicolon as a delimitation. Find language string according to the index.
944 SupportedLang = "engfraengfra"
946 Iso639Language = TRUE
947 The return value is "fra".
949 SupportedLang = "en;fr;en-US;fr-FR"
951 Iso639Language = FALSE
952 The return value is "fr".
954 @param SupportedLang Platform supported language codes.
955 @param Index The index in supported language codes.
956 @param Iso639Language A bool value to signify if the handler is operated on ISO639 or RFC4646.
958 @retval The language string in the language codes.
962 GetLangFromSupportedLangCodes (
963 IN CHAR8
*SupportedLang
,
965 IN BOOLEAN Iso639Language
973 Supported
= SupportedLang
;
974 if (Iso639Language
) {
976 // According to the index of Lang string in SupportedLang string to get the language.
977 // This code will be invoked in RUNTIME, therefore there is not a memory allocate/free operation.
978 // In driver entry, it pre-allocates a runtime attribute memory to accommodate this string.
980 CompareLength
= ISO_639_2_ENTRY_SIZE
;
981 mVariableModuleGlobal
->Lang
[CompareLength
] = '\0';
982 return CopyMem (mVariableModuleGlobal
->Lang
, SupportedLang
+ Index
* CompareLength
, CompareLength
);
987 // Take semicolon as delimitation, sequentially traverse supported language codes.
989 for (CompareLength
= 0; *Supported
!= ';' && *Supported
!= '\0'; CompareLength
++) {
992 if ((*Supported
== '\0') && (SubIndex
!= Index
)) {
994 // Have completed the traverse, but not find corrsponding string.
995 // This case is not allowed to happen.
1000 if (SubIndex
== Index
) {
1002 // According to the index of Lang string in SupportedLang string to get the language.
1003 // As this code will be invoked in RUNTIME, therefore there is not memory allocate/free operation.
1004 // In driver entry, it pre-allocates a runtime attribute memory to accommodate this string.
1006 mVariableModuleGlobal
->PlatformLang
[CompareLength
] = '\0';
1007 return CopyMem (mVariableModuleGlobal
->PlatformLang
, Supported
- CompareLength
, CompareLength
);
1012 // Skip ';' characters in Supported
1014 for (; *Supported
!= '\0' && *Supported
== ';'; Supported
++);
1020 Returns a pointer to an allocated buffer that contains the best matching language
1021 from a set of supported languages.
1023 This function supports both ISO 639-2 and RFC 4646 language codes, but language
1024 code types may not be mixed in a single call to this function. This function
1025 supports a variable argument list that allows the caller to pass in a prioritized
1026 list of language codes to test against all the language codes in SupportedLanguages.
1028 If SupportedLanguages is NULL, then ASSERT().
1030 @param[in] SupportedLanguages A pointer to a Null-terminated ASCII string that
1031 contains a set of language codes in the format
1032 specified by Iso639Language.
1033 @param[in] Iso639Language If TRUE, then all language codes are assumed to be
1034 in ISO 639-2 format. If FALSE, then all language
1035 codes are assumed to be in RFC 4646 language format
1036 @param[in] ... A variable argument list that contains pointers to
1037 Null-terminated ASCII strings that contain one or more
1038 language codes in the format specified by Iso639Language.
1039 The first language code from each of these language
1040 code lists is used to determine if it is an exact or
1041 close match to any of the language codes in
1042 SupportedLanguages. Close matches only apply to RFC 4646
1043 language codes, and the matching algorithm from RFC 4647
1044 is used to determine if a close match is present. If
1045 an exact or close match is found, then the matching
1046 language code from SupportedLanguages is returned. If
1047 no matches are found, then the next variable argument
1048 parameter is evaluated. The variable argument list
1049 is terminated by a NULL.
1051 @retval NULL The best matching language could not be found in SupportedLanguages.
1052 @retval NULL There are not enough resources available to return the best matching
1054 @retval Other A pointer to a Null-terminated ASCII string that is the best matching
1055 language in SupportedLanguages.
1060 VariableGetBestLanguage (
1061 IN CONST CHAR8
*SupportedLanguages
,
1062 IN BOOLEAN Iso639Language
,
1068 UINTN CompareLength
;
1069 UINTN LanguageLength
;
1070 CONST CHAR8
*Supported
;
1073 if (SupportedLanguages
== NULL
) {
1077 VA_START (Args
, Iso639Language
);
1078 while ((Language
= VA_ARG (Args
, CHAR8
*)) != NULL
) {
1080 // Default to ISO 639-2 mode
1083 LanguageLength
= MIN (3, AsciiStrLen (Language
));
1086 // If in RFC 4646 mode, then determine the length of the first RFC 4646 language code in Language
1088 if (!Iso639Language
) {
1089 for (LanguageLength
= 0; Language
[LanguageLength
] != 0 && Language
[LanguageLength
] != ';'; LanguageLength
++);
1093 // Trim back the length of Language used until it is empty
1095 while (LanguageLength
> 0) {
1097 // Loop through all language codes in SupportedLanguages
1099 for (Supported
= SupportedLanguages
; *Supported
!= '\0'; Supported
+= CompareLength
) {
1101 // In RFC 4646 mode, then Loop through all language codes in SupportedLanguages
1103 if (!Iso639Language
) {
1105 // Skip ';' characters in Supported
1107 for (; *Supported
!= '\0' && *Supported
== ';'; Supported
++);
1109 // Determine the length of the next language code in Supported
1111 for (CompareLength
= 0; Supported
[CompareLength
] != 0 && Supported
[CompareLength
] != ';'; CompareLength
++);
1113 // If Language is longer than the Supported, then skip to the next language
1115 if (LanguageLength
> CompareLength
) {
1120 // See if the first LanguageLength characters in Supported match Language
1122 if (AsciiStrnCmp (Supported
, Language
, LanguageLength
) == 0) {
1125 Buffer
= Iso639Language
? mVariableModuleGlobal
->Lang
: mVariableModuleGlobal
->PlatformLang
;
1126 Buffer
[CompareLength
] = '\0';
1127 return CopyMem (Buffer
, Supported
, CompareLength
);
1131 if (Iso639Language
) {
1133 // If ISO 639 mode, then each language can only be tested once
1138 // If RFC 4646 mode, then trim Language from the right to the next '-' character
1140 for (LanguageLength
--; LanguageLength
> 0 && Language
[LanguageLength
] != '-'; LanguageLength
--);
1147 // No matches were found
1153 Hook the operations in PlatformLangCodes, LangCodes, PlatformLang and Lang.
1155 When setting Lang/LangCodes, simultaneously update PlatformLang/PlatformLangCodes.
1157 According to UEFI spec, PlatformLangCodes/LangCodes are only set once in firmware initialization,
1158 and are read-only. Therefore, in variable driver, only store the original value for other use.
1160 @param[in] VariableName Name of variable.
1162 @param[in] Data Variable data.
1164 @param[in] DataSize Size of data. 0 means delete.
1168 AutoUpdateLangVariable (
1169 IN CHAR16
*VariableName
,
1175 CHAR8
*BestPlatformLang
;
1179 VARIABLE_POINTER_TRACK Variable
;
1180 BOOLEAN SetLanguageCodes
;
1183 // Don't do updates for delete operation
1185 if (DataSize
== 0) {
1189 SetLanguageCodes
= FALSE
;
1191 if (StrCmp (VariableName
, L
"PlatformLangCodes") == 0) {
1193 // PlatformLangCodes is a volatile variable, so it can not be updated at runtime.
1199 SetLanguageCodes
= TRUE
;
1202 // According to UEFI spec, PlatformLangCodes is only set once in firmware initialization, and is read-only
1203 // Therefore, in variable driver, only store the original value for other use.
1205 if (mVariableModuleGlobal
->PlatformLangCodes
!= NULL
) {
1206 FreePool (mVariableModuleGlobal
->PlatformLangCodes
);
1208 mVariableModuleGlobal
->PlatformLangCodes
= AllocateRuntimeCopyPool (DataSize
, Data
);
1209 ASSERT (mVariableModuleGlobal
->PlatformLangCodes
!= NULL
);
1212 // PlatformLang holds a single language from PlatformLangCodes,
1213 // so the size of PlatformLangCodes is enough for the PlatformLang.
1215 if (mVariableModuleGlobal
->PlatformLang
!= NULL
) {
1216 FreePool (mVariableModuleGlobal
->PlatformLang
);
1218 mVariableModuleGlobal
->PlatformLang
= AllocateRuntimePool (DataSize
);
1219 ASSERT (mVariableModuleGlobal
->PlatformLang
!= NULL
);
1221 } else if (StrCmp (VariableName
, L
"LangCodes") == 0) {
1223 // LangCodes is a volatile variable, so it can not be updated at runtime.
1229 SetLanguageCodes
= TRUE
;
1232 // According to UEFI spec, LangCodes is only set once in firmware initialization, and is read-only
1233 // Therefore, in variable driver, only store the original value for other use.
1235 if (mVariableModuleGlobal
->LangCodes
!= NULL
) {
1236 FreePool (mVariableModuleGlobal
->LangCodes
);
1238 mVariableModuleGlobal
->LangCodes
= AllocateRuntimeCopyPool (DataSize
, Data
);
1239 ASSERT (mVariableModuleGlobal
->LangCodes
!= NULL
);
1242 if (SetLanguageCodes
1243 && (mVariableModuleGlobal
->PlatformLangCodes
!= NULL
)
1244 && (mVariableModuleGlobal
->LangCodes
!= NULL
)) {
1246 // Update Lang if PlatformLang is already set
1247 // Update PlatformLang if Lang is already set
1249 Status
= FindVariable (L
"PlatformLang", &gEfiGlobalVariableGuid
, &Variable
, &mVariableModuleGlobal
->VariableGlobal
, FALSE
);
1250 if (!EFI_ERROR (Status
)) {
1254 VariableName
= L
"PlatformLang";
1255 Data
= GetVariableDataPtr (Variable
.CurrPtr
);
1256 DataSize
= Variable
.CurrPtr
->DataSize
;
1258 Status
= FindVariable (L
"Lang", &gEfiGlobalVariableGuid
, &Variable
, &mVariableModuleGlobal
->VariableGlobal
, FALSE
);
1259 if (!EFI_ERROR (Status
)) {
1261 // Update PlatformLang
1263 VariableName
= L
"Lang";
1264 Data
= GetVariableDataPtr (Variable
.CurrPtr
);
1265 DataSize
= Variable
.CurrPtr
->DataSize
;
1268 // Neither PlatformLang nor Lang is set, directly return
1276 // According to UEFI spec, "Lang" and "PlatformLang" is NV|BS|RT attributions.
1278 Attributes
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
;
1280 if (StrCmp (VariableName
, L
"PlatformLang") == 0) {
1282 // Update Lang when PlatformLangCodes/LangCodes were set.
1284 if ((mVariableModuleGlobal
->PlatformLangCodes
!= NULL
) && (mVariableModuleGlobal
->LangCodes
!= NULL
)) {
1286 // When setting PlatformLang, firstly get most matched language string from supported language codes.
1288 BestPlatformLang
= VariableGetBestLanguage (mVariableModuleGlobal
->PlatformLangCodes
, FALSE
, Data
, NULL
);
1289 if (BestPlatformLang
!= NULL
) {
1291 // Get the corresponding index in language codes.
1293 Index
= GetIndexFromSupportedLangCodes (mVariableModuleGlobal
->PlatformLangCodes
, BestPlatformLang
, FALSE
);
1296 // Get the corresponding ISO639 language tag according to RFC4646 language tag.
1298 BestLang
= GetLangFromSupportedLangCodes (mVariableModuleGlobal
->LangCodes
, Index
, TRUE
);
1301 // Successfully convert PlatformLang to Lang, and set the BestLang value into Lang variable simultaneously.
1303 FindVariable (L
"Lang", &gEfiGlobalVariableGuid
, &Variable
, &mVariableModuleGlobal
->VariableGlobal
, FALSE
);
1305 Status
= UpdateVariable (L
"Lang", &gEfiGlobalVariableGuid
, BestLang
,
1306 ISO_639_2_ENTRY_SIZE
+ 1, Attributes
, 0, 0, &Variable
, NULL
);
1308 DEBUG ((EFI_D_INFO
, "Variable Driver Auto Update PlatformLang, PlatformLang:%a, Lang:%a\n", BestPlatformLang
, BestLang
));
1310 ASSERT_EFI_ERROR(Status
);
1314 } else if (StrCmp (VariableName
, L
"Lang") == 0) {
1316 // Update PlatformLang when PlatformLangCodes/LangCodes were set.
1318 if ((mVariableModuleGlobal
->PlatformLangCodes
!= NULL
) && (mVariableModuleGlobal
->LangCodes
!= NULL
)) {
1320 // When setting Lang, firstly get most matched language string from supported language codes.
1322 BestLang
= VariableGetBestLanguage (mVariableModuleGlobal
->LangCodes
, TRUE
, Data
, NULL
);
1323 if (BestLang
!= NULL
) {
1325 // Get the corresponding index in language codes.
1327 Index
= GetIndexFromSupportedLangCodes (mVariableModuleGlobal
->LangCodes
, BestLang
, TRUE
);
1330 // Get the corresponding RFC4646 language tag according to ISO639 language tag.
1332 BestPlatformLang
= GetLangFromSupportedLangCodes (mVariableModuleGlobal
->PlatformLangCodes
, Index
, FALSE
);
1335 // Successfully convert Lang to PlatformLang, and set the BestPlatformLang value into PlatformLang variable simultaneously.
1337 FindVariable (L
"PlatformLang", &gEfiGlobalVariableGuid
, &Variable
, &mVariableModuleGlobal
->VariableGlobal
, FALSE
);
1339 Status
= UpdateVariable (L
"PlatformLang", &gEfiGlobalVariableGuid
, BestPlatformLang
,
1340 AsciiStrSize (BestPlatformLang
), Attributes
, 0, 0, &Variable
, NULL
);
1342 DEBUG ((EFI_D_INFO
, "Variable Driver Auto Update Lang, Lang:%a, PlatformLang:%a\n", BestLang
, BestPlatformLang
));
1343 ASSERT_EFI_ERROR (Status
);
1350 Update the variable region with Variable information. If EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS is set,
1351 index of associated public key is needed.
1353 @param[in] VariableName Name of variable.
1354 @param[in] VendorGuid Guid of variable.
1355 @param[in] Data Variable data.
1356 @param[in] DataSize Size of data. 0 means delete.
1357 @param[in] Attributes Attributes of the variable.
1358 @param[in] KeyIndex Index of associated public key.
1359 @param[in] MonotonicCount Value of associated monotonic count.
1360 @param[in] CacheVariable The variable information which is used to keep track of variable usage.
1361 @param[in] TimeStamp Value of associated TimeStamp.
1363 @retval EFI_SUCCESS The update operation is success.
1364 @retval EFI_OUT_OF_RESOURCES Variable region is full, can not write other data into this region.
1369 IN CHAR16
*VariableName
,
1370 IN EFI_GUID
*VendorGuid
,
1373 IN UINT32 Attributes OPTIONAL
,
1374 IN UINT32 KeyIndex OPTIONAL
,
1375 IN UINT64 MonotonicCount OPTIONAL
,
1376 IN VARIABLE_POINTER_TRACK
*CacheVariable
,
1377 IN EFI_TIME
*TimeStamp OPTIONAL
1381 VARIABLE_HEADER
*NextVariable
;
1383 UINTN ScratchDataSize
;
1384 UINTN NonVolatileVarableStoreSize
;
1385 UINTN VarNameOffset
;
1386 UINTN VarDataOffset
;
1390 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*Fvb
;
1393 VARIABLE_POINTER_TRACK
*Variable
;
1394 VARIABLE_POINTER_TRACK NvVariable
;
1395 VARIABLE_STORE_HEADER
*VariableStoreHeader
;
1401 if (mVariableModuleGlobal
->FvbInstance
== NULL
) {
1403 // The FVB protocol is not installed, so the EFI_VARIABLE_WRITE_ARCH_PROTOCOL is not installed.
1405 if ((Attributes
& EFI_VARIABLE_NON_VOLATILE
) != 0) {
1407 // Trying to update NV variable prior to the installation of EFI_VARIABLE_WRITE_ARCH_PROTOCOL
1409 return EFI_NOT_AVAILABLE_YET
;
1410 } else if ((Attributes
& EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
) != 0) {
1412 // Trying to update volatile authenticated variable prior to the installation of EFI_VARIABLE_WRITE_ARCH_PROTOCOL
1413 // The authenticated variable perhaps is not initialized, just return here.
1415 return EFI_NOT_AVAILABLE_YET
;
1419 if ((CacheVariable
->CurrPtr
== NULL
) || CacheVariable
->Volatile
) {
1420 Variable
= CacheVariable
;
1423 // Update/Delete existing NV variable.
1424 // CacheVariable points to the variable in the memory copy of Flash area
1425 // Now let Variable points to the same variable in Flash area.
1427 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) ((UINTN
) mVariableModuleGlobal
->VariableGlobal
.NonVolatileVariableBase
);
1428 Variable
= &NvVariable
;
1429 Variable
->StartPtr
= GetStartPointer (VariableStoreHeader
);
1430 Variable
->EndPtr
= GetEndPointer (VariableStoreHeader
);
1431 Variable
->CurrPtr
= (VARIABLE_HEADER
*)((UINTN
)Variable
->StartPtr
+ ((UINTN
)CacheVariable
->CurrPtr
- (UINTN
)CacheVariable
->StartPtr
));
1432 Variable
->Volatile
= FALSE
;
1435 Fvb
= mVariableModuleGlobal
->FvbInstance
;
1439 // Tricky part: Use scratch data area at the end of volatile variable store
1440 // as a temporary storage.
1442 NextVariable
= GetEndPointer ((VARIABLE_STORE_HEADER
*) ((UINTN
) mVariableModuleGlobal
->VariableGlobal
.VolatileVariableBase
));
1443 ScratchSize
= MAX (PcdGet32 (PcdMaxVariableSize
), PcdGet32 (PcdMaxHardwareErrorVariableSize
));
1444 ScratchDataSize
= ScratchSize
- sizeof (VARIABLE_HEADER
) - StrSize (VariableName
) - GET_PAD_SIZE (StrSize (VariableName
));
1446 if (Variable
->CurrPtr
!= NULL
) {
1448 // Update/Delete existing variable.
1452 // If AtRuntime and the variable is Volatile and Runtime Access,
1453 // the volatile is ReadOnly, and SetVariable should be aborted and
1454 // return EFI_WRITE_PROTECTED.
1456 if (Variable
->Volatile
) {
1457 Status
= EFI_WRITE_PROTECTED
;
1461 // Only variable that have NV attributes can be updated/deleted in Runtime.
1463 if ((Variable
->CurrPtr
->Attributes
& EFI_VARIABLE_NON_VOLATILE
) == 0) {
1464 Status
= EFI_INVALID_PARAMETER
;
1469 // Only variable that have RT attributes can be updated/deleted in Runtime.
1471 if ((Variable
->CurrPtr
->Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
) == 0) {
1472 Status
= EFI_INVALID_PARAMETER
;
1478 // Setting a data variable with no access, or zero DataSize attributes
1479 // causes it to be deleted.
1480 // When the EFI_VARIABLE_APPEND_WRITE attribute is set, DataSize of zero will
1481 // not delete the variable.
1483 if ((((Attributes
& EFI_VARIABLE_APPEND_WRITE
) == 0) && (DataSize
== 0))|| ((Attributes
& (EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
)) == 0)) {
1484 State
= Variable
->CurrPtr
->State
;
1485 State
&= VAR_DELETED
;
1487 Status
= UpdateVariableStore (
1488 &mVariableModuleGlobal
->VariableGlobal
,
1492 (UINTN
) &Variable
->CurrPtr
->State
,
1496 if (!EFI_ERROR (Status
)) {
1497 UpdateVariableInfo (VariableName
, VendorGuid
, Variable
->Volatile
, FALSE
, FALSE
, TRUE
, FALSE
);
1498 if (!Variable
->Volatile
) {
1499 CacheVariable
->CurrPtr
->State
= State
;
1505 // If the variable is marked valid, and the same data has been passed in,
1506 // then return to the caller immediately.
1508 if (DataSizeOfVariable (Variable
->CurrPtr
) == DataSize
&&
1509 (CompareMem (Data
, GetVariableDataPtr (Variable
->CurrPtr
), DataSize
) == 0) &&
1510 ((Attributes
& EFI_VARIABLE_APPEND_WRITE
) == 0) &&
1511 (TimeStamp
== NULL
)) {
1513 // Variable content unchanged and no need to update timestamp, just return.
1515 UpdateVariableInfo (VariableName
, VendorGuid
, Variable
->Volatile
, FALSE
, TRUE
, FALSE
, FALSE
);
1516 Status
= EFI_SUCCESS
;
1518 } else if ((Variable
->CurrPtr
->State
== VAR_ADDED
) ||
1519 (Variable
->CurrPtr
->State
== (VAR_ADDED
& VAR_IN_DELETED_TRANSITION
))) {
1522 // EFI_VARIABLE_APPEND_WRITE attribute only effects for existing variable
1524 if ((Attributes
& EFI_VARIABLE_APPEND_WRITE
) != 0) {
1526 // Cache the previous variable data into StorageArea.
1528 DataOffset
= sizeof (VARIABLE_HEADER
) + Variable
->CurrPtr
->NameSize
+ GET_PAD_SIZE (Variable
->CurrPtr
->NameSize
);
1529 CopyMem (mStorageArea
, (UINT8
*)((UINTN
) Variable
->CurrPtr
+ DataOffset
), Variable
->CurrPtr
->DataSize
);
1531 if (CompareGuid (VendorGuid
, &gEfiImageSecurityDatabaseGuid
) ||
1532 (CompareGuid (VendorGuid
, &gEfiGlobalVariableGuid
) && (StrCmp (VariableName
, EFI_KEY_EXCHANGE_KEY_NAME
) == 0))) {
1534 // For variables with the GUID EFI_IMAGE_SECURITY_DATABASE_GUID (i.e. where the data
1535 // buffer is formatted as EFI_SIGNATURE_LIST), the driver shall not perform an append of
1536 // EFI_SIGNATURE_DATA values that are already part of the existing variable value.
1538 BufSize
= AppendSignatureList (mStorageArea
, Variable
->CurrPtr
->DataSize
, Data
, DataSize
);
1539 if (BufSize
== Variable
->CurrPtr
->DataSize
) {
1540 if ((TimeStamp
== NULL
) || CompareTimeStamp (TimeStamp
, &Variable
->CurrPtr
->TimeStamp
)) {
1542 // New EFI_SIGNATURE_DATA is not found and timestamp is not later
1543 // than current timestamp, return EFI_SUCCESS directly.
1545 UpdateVariableInfo (VariableName
, VendorGuid
, Variable
->Volatile
, FALSE
, TRUE
, FALSE
, FALSE
);
1546 Status
= EFI_SUCCESS
;
1552 // For other Variables, append the new data to the end of previous data.
1554 CopyMem ((UINT8
*)((UINTN
) mStorageArea
+ Variable
->CurrPtr
->DataSize
), Data
, DataSize
);
1555 BufSize
= Variable
->CurrPtr
->DataSize
+ DataSize
;
1558 RevBufSize
= MIN (PcdGet32 (PcdMaxVariableSize
), ScratchDataSize
);
1559 if (BufSize
> RevBufSize
) {
1561 // If variable size (previous + current) is bigger than reserved buffer in runtime,
1562 // return EFI_OUT_OF_RESOURCES.
1564 return EFI_OUT_OF_RESOURCES
;
1568 // Override Data and DataSize which are used for combined data area including previous and new data.
1570 Data
= mStorageArea
;
1575 // Mark the old variable as in delete transition.
1577 State
= Variable
->CurrPtr
->State
;
1578 State
&= VAR_IN_DELETED_TRANSITION
;
1580 Status
= UpdateVariableStore (
1581 &mVariableModuleGlobal
->VariableGlobal
,
1585 (UINTN
) &Variable
->CurrPtr
->State
,
1589 if (EFI_ERROR (Status
)) {
1592 if (!Variable
->Volatile
) {
1593 CacheVariable
->CurrPtr
->State
= State
;
1598 // Not found existing variable. Create a new variable.
1601 if ((DataSize
== 0) && ((Attributes
& EFI_VARIABLE_APPEND_WRITE
) != 0)) {
1602 Status
= EFI_SUCCESS
;
1607 // Make sure we are trying to create a new variable.
1608 // Setting a data variable with zero DataSize or no access attributes means to delete it.
1610 if (DataSize
== 0 || (Attributes
& (EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
)) == 0) {
1611 Status
= EFI_NOT_FOUND
;
1616 // Only variable have NV|RT attribute can be created in Runtime.
1619 (((Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
) == 0) || ((Attributes
& EFI_VARIABLE_NON_VOLATILE
) == 0))) {
1620 Status
= EFI_INVALID_PARAMETER
;
1626 // Function part - create a new variable and copy the data.
1627 // Both update a variable and create a variable will come here.
1629 SetMem (NextVariable
, ScratchSize
, 0xff);
1631 NextVariable
->StartId
= VARIABLE_DATA
;
1633 // NextVariable->State = VAR_ADDED;
1635 NextVariable
->Reserved
= 0;
1636 NextVariable
->PubKeyIndex
= KeyIndex
;
1637 NextVariable
->MonotonicCount
= MonotonicCount
;
1638 ZeroMem (&NextVariable
->TimeStamp
, sizeof (EFI_TIME
));
1640 if (((Attributes
& EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
) != 0) &&
1641 (TimeStamp
!= NULL
)) {
1642 if ((Attributes
& EFI_VARIABLE_APPEND_WRITE
) == 0) {
1643 CopyMem (&NextVariable
->TimeStamp
, TimeStamp
, sizeof (EFI_TIME
));
1646 // In the case when the EFI_VARIABLE_APPEND_WRITE attribute is set, only
1647 // when the new TimeStamp value is later than the current timestamp associated
1648 // with the variable, we need associate the new timestamp with the updated value.
1650 if (Variable
->CurrPtr
!= NULL
) {
1651 if (CompareTimeStamp (&Variable
->CurrPtr
->TimeStamp
, TimeStamp
)) {
1652 CopyMem (&NextVariable
->TimeStamp
, TimeStamp
, sizeof (EFI_TIME
));
1659 // The EFI_VARIABLE_APPEND_WRITE attribute will never be set in the returned
1660 // Attributes bitmask parameter of a GetVariable() call.
1662 NextVariable
->Attributes
= Attributes
& (~EFI_VARIABLE_APPEND_WRITE
);
1664 VarNameOffset
= sizeof (VARIABLE_HEADER
);
1665 VarNameSize
= StrSize (VariableName
);
1667 (UINT8
*) ((UINTN
) NextVariable
+ VarNameOffset
),
1671 VarDataOffset
= VarNameOffset
+ VarNameSize
+ GET_PAD_SIZE (VarNameSize
);
1673 (UINT8
*) ((UINTN
) NextVariable
+ VarDataOffset
),
1677 CopyMem (&NextVariable
->VendorGuid
, VendorGuid
, sizeof (EFI_GUID
));
1679 // There will be pad bytes after Data, the NextVariable->NameSize and
1680 // NextVariable->DataSize should not include pad size so that variable
1681 // service can get actual size in GetVariable.
1683 NextVariable
->NameSize
= (UINT32
)VarNameSize
;
1684 NextVariable
->DataSize
= (UINT32
)DataSize
;
1687 // The actual size of the variable that stores in storage should
1688 // include pad size.
1690 VarSize
= VarDataOffset
+ DataSize
+ GET_PAD_SIZE (DataSize
);
1691 if ((Attributes
& EFI_VARIABLE_NON_VOLATILE
) != 0) {
1693 // Create a nonvolatile variable.
1696 NonVolatileVarableStoreSize
= ((VARIABLE_STORE_HEADER
*)(UINTN
)(mVariableModuleGlobal
->VariableGlobal
.NonVolatileVariableBase
))->Size
;
1697 if ((((Attributes
& EFI_VARIABLE_HARDWARE_ERROR_RECORD
) != 0)
1698 && ((VarSize
+ mVariableModuleGlobal
->HwErrVariableTotalSize
) > PcdGet32 (PcdHwErrStorageSize
)))
1699 || (((Attributes
& EFI_VARIABLE_HARDWARE_ERROR_RECORD
) == 0)
1700 && ((VarSize
+ mVariableModuleGlobal
->CommonVariableTotalSize
) > NonVolatileVarableStoreSize
- sizeof (VARIABLE_STORE_HEADER
) - PcdGet32 (PcdHwErrStorageSize
)))) {
1702 Status
= EFI_OUT_OF_RESOURCES
;
1706 // Perform garbage collection & reclaim operation.
1708 Status
= Reclaim (mVariableModuleGlobal
->VariableGlobal
.NonVolatileVariableBase
,
1709 &mVariableModuleGlobal
->NonVolatileLastVariableOffset
, FALSE
, Variable
->CurrPtr
);
1710 if (EFI_ERROR (Status
)) {
1714 // If still no enough space, return out of resources.
1716 if ((((Attributes
& EFI_VARIABLE_HARDWARE_ERROR_RECORD
) != 0)
1717 && ((VarSize
+ mVariableModuleGlobal
->HwErrVariableTotalSize
) > PcdGet32 (PcdHwErrStorageSize
)))
1718 || (((Attributes
& EFI_VARIABLE_HARDWARE_ERROR_RECORD
) == 0)
1719 && ((VarSize
+ mVariableModuleGlobal
->CommonVariableTotalSize
) > NonVolatileVarableStoreSize
- sizeof (VARIABLE_STORE_HEADER
) - PcdGet32 (PcdHwErrStorageSize
)))) {
1720 Status
= EFI_OUT_OF_RESOURCES
;
1727 // 1. Write variable header
1728 // 2. Set variable state to header valid
1729 // 3. Write variable data
1730 // 4. Set variable state to valid
1735 CacheOffset
= mVariableModuleGlobal
->NonVolatileLastVariableOffset
;
1736 Status
= UpdateVariableStore (
1737 &mVariableModuleGlobal
->VariableGlobal
,
1741 mVariableModuleGlobal
->NonVolatileLastVariableOffset
,
1742 sizeof (VARIABLE_HEADER
),
1743 (UINT8
*) NextVariable
1746 if (EFI_ERROR (Status
)) {
1753 NextVariable
->State
= VAR_HEADER_VALID_ONLY
;
1754 Status
= UpdateVariableStore (
1755 &mVariableModuleGlobal
->VariableGlobal
,
1759 mVariableModuleGlobal
->NonVolatileLastVariableOffset
+ OFFSET_OF (VARIABLE_HEADER
, State
),
1761 &NextVariable
->State
1764 if (EFI_ERROR (Status
)) {
1770 Status
= UpdateVariableStore (
1771 &mVariableModuleGlobal
->VariableGlobal
,
1775 mVariableModuleGlobal
->NonVolatileLastVariableOffset
+ sizeof (VARIABLE_HEADER
),
1776 (UINT32
) VarSize
- sizeof (VARIABLE_HEADER
),
1777 (UINT8
*) NextVariable
+ sizeof (VARIABLE_HEADER
)
1780 if (EFI_ERROR (Status
)) {
1786 NextVariable
->State
= VAR_ADDED
;
1787 Status
= UpdateVariableStore (
1788 &mVariableModuleGlobal
->VariableGlobal
,
1792 mVariableModuleGlobal
->NonVolatileLastVariableOffset
+ OFFSET_OF (VARIABLE_HEADER
, State
),
1794 &NextVariable
->State
1797 if (EFI_ERROR (Status
)) {
1801 mVariableModuleGlobal
->NonVolatileLastVariableOffset
+= HEADER_ALIGN (VarSize
);
1803 if ((Attributes
& EFI_VARIABLE_HARDWARE_ERROR_RECORD
) != 0) {
1804 mVariableModuleGlobal
->HwErrVariableTotalSize
+= HEADER_ALIGN (VarSize
);
1806 mVariableModuleGlobal
->CommonVariableTotalSize
+= HEADER_ALIGN (VarSize
);
1809 // update the memory copy of Flash region.
1811 CopyMem ((UINT8
*)mNvVariableCache
+ CacheOffset
, (UINT8
*)NextVariable
, VarSize
);
1814 // Create a volatile variable.
1818 if ((UINT32
) (VarSize
+ mVariableModuleGlobal
->VolatileLastVariableOffset
) >
1819 ((VARIABLE_STORE_HEADER
*) ((UINTN
) (mVariableModuleGlobal
->VariableGlobal
.VolatileVariableBase
)))->Size
) {
1821 // Perform garbage collection & reclaim operation.
1823 Status
= Reclaim (mVariableModuleGlobal
->VariableGlobal
.VolatileVariableBase
,
1824 &mVariableModuleGlobal
->VolatileLastVariableOffset
, TRUE
, Variable
->CurrPtr
);
1825 if (EFI_ERROR (Status
)) {
1829 // If still no enough space, return out of resources.
1831 if ((UINT32
) (VarSize
+ mVariableModuleGlobal
->VolatileLastVariableOffset
) >
1832 ((VARIABLE_STORE_HEADER
*) ((UINTN
) (mVariableModuleGlobal
->VariableGlobal
.VolatileVariableBase
)))->Size
1834 Status
= EFI_OUT_OF_RESOURCES
;
1840 NextVariable
->State
= VAR_ADDED
;
1841 Status
= UpdateVariableStore (
1842 &mVariableModuleGlobal
->VariableGlobal
,
1846 mVariableModuleGlobal
->VolatileLastVariableOffset
,
1848 (UINT8
*) NextVariable
1851 if (EFI_ERROR (Status
)) {
1855 mVariableModuleGlobal
->VolatileLastVariableOffset
+= HEADER_ALIGN (VarSize
);
1859 // Mark the old variable as deleted.
1861 if (!Reclaimed
&& !EFI_ERROR (Status
) && Variable
->CurrPtr
!= NULL
) {
1862 State
= Variable
->CurrPtr
->State
;
1863 State
&= VAR_DELETED
;
1865 Status
= UpdateVariableStore (
1866 &mVariableModuleGlobal
->VariableGlobal
,
1870 (UINTN
) &Variable
->CurrPtr
->State
,
1874 if (!EFI_ERROR (Status
) && !Variable
->Volatile
) {
1875 CacheVariable
->CurrPtr
->State
= State
;
1879 if (!EFI_ERROR (Status
)) {
1880 UpdateVariableInfo (VariableName
, VendorGuid
, Volatile
, FALSE
, TRUE
, FALSE
, FALSE
);
1888 Check if a Unicode character is a hexadecimal character.
1890 This function checks if a Unicode character is a
1891 hexadecimal character. The valid hexadecimal character is
1892 L'0' to L'9', L'a' to L'f', or L'A' to L'F'.
1895 @param Char The character to check against.
1897 @retval TRUE If the Char is a hexadecmial character.
1898 @retval FALSE If the Char is not a hexadecmial character.
1903 IsHexaDecimalDigitCharacter (
1907 return (BOOLEAN
) ((Char
>= L
'0' && Char
<= L
'9') || (Char
>= L
'A' && Char
<= L
'F') || (Char
>= L
'a' && Char
<= L
'f'));
1912 This code checks if variable is hardware error record variable or not.
1914 According to UEFI spec, hardware error record variable should use the EFI_HARDWARE_ERROR_VARIABLE VendorGuid
1915 and have the L"HwErrRec####" name convention, #### is a printed hex value and no 0x or h is included in the hex value.
1917 @param VariableName Pointer to variable name.
1918 @param VendorGuid Variable Vendor Guid.
1920 @retval TRUE Variable is hardware error record variable.
1921 @retval FALSE Variable is not hardware error record variable.
1926 IsHwErrRecVariable (
1927 IN CHAR16
*VariableName
,
1928 IN EFI_GUID
*VendorGuid
1931 if (!CompareGuid (VendorGuid
, &gEfiHardwareErrorVariableGuid
) ||
1932 (StrLen (VariableName
) != StrLen (L
"HwErrRec####")) ||
1933 (StrnCmp(VariableName
, L
"HwErrRec", StrLen (L
"HwErrRec")) != 0) ||
1934 !IsHexaDecimalDigitCharacter (VariableName
[0x8]) ||
1935 !IsHexaDecimalDigitCharacter (VariableName
[0x9]) ||
1936 !IsHexaDecimalDigitCharacter (VariableName
[0xA]) ||
1937 !IsHexaDecimalDigitCharacter (VariableName
[0xB])) {
1946 This code finds variable in storage blocks (Volatile or Non-Volatile).
1948 @param VariableName Name of Variable to be found.
1949 @param VendorGuid Variable vendor GUID.
1950 @param Attributes Attribute value of the variable found.
1951 @param DataSize Size of Data found. If size is less than the
1952 data, this value contains the required size.
1953 @param Data Data pointer.
1955 @return EFI_INVALID_PARAMETER Invalid parameter.
1956 @return EFI_SUCCESS Find the specified variable.
1957 @return EFI_NOT_FOUND Not found.
1958 @return EFI_BUFFER_TO_SMALL DataSize is too small for the result.
1963 VariableServiceGetVariable (
1964 IN CHAR16
*VariableName
,
1965 IN EFI_GUID
*VendorGuid
,
1966 OUT UINT32
*Attributes OPTIONAL
,
1967 IN OUT UINTN
*DataSize
,
1972 VARIABLE_POINTER_TRACK Variable
;
1975 if (VariableName
== NULL
|| VendorGuid
== NULL
|| DataSize
== NULL
) {
1976 return EFI_INVALID_PARAMETER
;
1979 AcquireLockOnlyAtBootTime(&mVariableModuleGlobal
->VariableGlobal
.VariableServicesLock
);
1981 Status
= FindVariable (VariableName
, VendorGuid
, &Variable
, &mVariableModuleGlobal
->VariableGlobal
, FALSE
);
1982 if (Variable
.CurrPtr
== NULL
|| EFI_ERROR (Status
)) {
1989 VarDataSize
= DataSizeOfVariable (Variable
.CurrPtr
);
1990 ASSERT (VarDataSize
!= 0);
1992 if (*DataSize
>= VarDataSize
) {
1994 Status
= EFI_INVALID_PARAMETER
;
1998 CopyMem (Data
, GetVariableDataPtr (Variable
.CurrPtr
), VarDataSize
);
1999 if (Attributes
!= NULL
) {
2000 *Attributes
= Variable
.CurrPtr
->Attributes
;
2003 *DataSize
= VarDataSize
;
2004 UpdateVariableInfo (VariableName
, VendorGuid
, Variable
.Volatile
, TRUE
, FALSE
, FALSE
, FALSE
);
2006 Status
= EFI_SUCCESS
;
2009 *DataSize
= VarDataSize
;
2010 Status
= EFI_BUFFER_TOO_SMALL
;
2015 ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal
->VariableGlobal
.VariableServicesLock
);
2023 This code Finds the Next available variable.
2025 @param VariableNameSize Size of the variable name.
2026 @param VariableName Pointer to variable name.
2027 @param VendorGuid Variable Vendor Guid.
2029 @return EFI_INVALID_PARAMETER Invalid parameter.
2030 @return EFI_SUCCESS Find the specified variable.
2031 @return EFI_NOT_FOUND Not found.
2032 @return EFI_BUFFER_TO_SMALL DataSize is too small for the result.
2037 VariableServiceGetNextVariableName (
2038 IN OUT UINTN
*VariableNameSize
,
2039 IN OUT CHAR16
*VariableName
,
2040 IN OUT EFI_GUID
*VendorGuid
2043 VARIABLE_STORE_TYPE Type
;
2044 VARIABLE_POINTER_TRACK Variable
;
2045 VARIABLE_POINTER_TRACK VariableInHob
;
2048 VARIABLE_STORE_HEADER
*VariableStoreHeader
[VariableStoreTypeMax
];
2050 if (VariableNameSize
== NULL
|| VariableName
== NULL
|| VendorGuid
== NULL
) {
2051 return EFI_INVALID_PARAMETER
;
2054 AcquireLockOnlyAtBootTime(&mVariableModuleGlobal
->VariableGlobal
.VariableServicesLock
);
2056 Status
= FindVariable (VariableName
, VendorGuid
, &Variable
, &mVariableModuleGlobal
->VariableGlobal
, FALSE
);
2057 if (Variable
.CurrPtr
== NULL
|| EFI_ERROR (Status
)) {
2061 if (VariableName
[0] != 0) {
2063 // If variable name is not NULL, get next variable.
2065 Variable
.CurrPtr
= GetNextVariablePtr (Variable
.CurrPtr
);
2069 // 0: Volatile, 1: HOB, 2: Non-Volatile.
2070 // The index and attributes mapping must be kept in this order as FindVariable
2071 // makes use of this mapping to implement search algorithm.
2073 VariableStoreHeader
[VariableStoreTypeVolatile
] = (VARIABLE_STORE_HEADER
*) (UINTN
) mVariableModuleGlobal
->VariableGlobal
.VolatileVariableBase
;
2074 VariableStoreHeader
[VariableStoreTypeHob
] = (VARIABLE_STORE_HEADER
*) (UINTN
) mVariableModuleGlobal
->VariableGlobal
.HobVariableBase
;
2075 VariableStoreHeader
[VariableStoreTypeNv
] = mNvVariableCache
;
2079 // Switch from Volatile to HOB, to Non-Volatile.
2081 while ((Variable
.CurrPtr
>= Variable
.EndPtr
) ||
2082 (Variable
.CurrPtr
== NULL
) ||
2083 !IsValidVariableHeader (Variable
.CurrPtr
)
2086 // Find current storage index
2088 for (Type
= (VARIABLE_STORE_TYPE
) 0; Type
< VariableStoreTypeMax
; Type
++) {
2089 if ((VariableStoreHeader
[Type
] != NULL
) && (Variable
.StartPtr
== GetStartPointer (VariableStoreHeader
[Type
]))) {
2093 ASSERT (Type
< VariableStoreTypeMax
);
2095 // Switch to next storage
2097 for (Type
++; Type
< VariableStoreTypeMax
; Type
++) {
2098 if (VariableStoreHeader
[Type
] != NULL
) {
2103 // Capture the case that
2104 // 1. current storage is the last one, or
2105 // 2. no further storage
2107 if (Type
== VariableStoreTypeMax
) {
2108 Status
= EFI_NOT_FOUND
;
2111 Variable
.StartPtr
= GetStartPointer (VariableStoreHeader
[Type
]);
2112 Variable
.EndPtr
= GetEndPointer (VariableStoreHeader
[Type
]);
2113 Variable
.CurrPtr
= Variable
.StartPtr
;
2117 // Variable is found
2119 if (Variable
.CurrPtr
->State
== VAR_ADDED
) {
2120 if ((AtRuntime () && ((Variable
.CurrPtr
->Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
) == 0)) == 0) {
2123 // Don't return NV variable when HOB overrides it
2125 if ((VariableStoreHeader
[VariableStoreTypeHob
] != NULL
) && (VariableStoreHeader
[VariableStoreTypeNv
] != NULL
) &&
2126 (Variable
.StartPtr
== GetStartPointer (VariableStoreHeader
[VariableStoreTypeNv
]))
2128 VariableInHob
.StartPtr
= GetStartPointer (VariableStoreHeader
[VariableStoreTypeHob
]);
2129 VariableInHob
.EndPtr
= GetEndPointer (VariableStoreHeader
[VariableStoreTypeHob
]);
2130 Status
= FindVariableEx (
2131 GetVariableNamePtr (Variable
.CurrPtr
),
2132 &Variable
.CurrPtr
->VendorGuid
,
2136 if (!EFI_ERROR (Status
)) {
2137 Variable
.CurrPtr
= GetNextVariablePtr (Variable
.CurrPtr
);
2142 VarNameSize
= NameSizeOfVariable (Variable
.CurrPtr
);
2143 ASSERT (VarNameSize
!= 0);
2145 if (VarNameSize
<= *VariableNameSize
) {
2146 CopyMem (VariableName
, GetVariableNamePtr (Variable
.CurrPtr
), VarNameSize
);
2147 CopyMem (VendorGuid
, &Variable
.CurrPtr
->VendorGuid
, sizeof (EFI_GUID
));
2148 Status
= EFI_SUCCESS
;
2150 Status
= EFI_BUFFER_TOO_SMALL
;
2153 *VariableNameSize
= VarNameSize
;
2158 Variable
.CurrPtr
= GetNextVariablePtr (Variable
.CurrPtr
);
2162 ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal
->VariableGlobal
.VariableServicesLock
);
2168 This code sets variable in storage blocks (Volatile or Non-Volatile).
2170 @param VariableName Name of Variable to be found.
2171 @param VendorGuid Variable vendor GUID.
2172 @param Attributes Attribute value of the variable found
2173 @param DataSize Size of Data found. If size is less than the
2174 data, this value contains the required size.
2175 @param Data Data pointer.
2177 @return EFI_INVALID_PARAMETER Invalid parameter.
2178 @return EFI_SUCCESS Set successfully.
2179 @return EFI_OUT_OF_RESOURCES Resource not enough to set variable.
2180 @return EFI_NOT_FOUND Not found.
2181 @return EFI_WRITE_PROTECTED Variable is read-only.
2186 VariableServiceSetVariable (
2187 IN CHAR16
*VariableName
,
2188 IN EFI_GUID
*VendorGuid
,
2189 IN UINT32 Attributes
,
2194 VARIABLE_POINTER_TRACK Variable
;
2196 VARIABLE_HEADER
*NextVariable
;
2197 EFI_PHYSICAL_ADDRESS Point
;
2201 // Check input parameters.
2203 if (VariableName
== NULL
|| VariableName
[0] == 0 || VendorGuid
== NULL
) {
2204 return EFI_INVALID_PARAMETER
;
2207 if (DataSize
!= 0 && Data
== NULL
) {
2208 return EFI_INVALID_PARAMETER
;
2212 // Make sure if runtime bit is set, boot service bit is set also.
2214 if ((Attributes
& (EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
)) == EFI_VARIABLE_RUNTIME_ACCESS
) {
2215 return EFI_INVALID_PARAMETER
;
2219 // EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS and EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS attribute
2220 // cannot be set both.
2222 if (((Attributes
& EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
) == EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
)
2223 && ((Attributes
& EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
) == EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
)) {
2224 return EFI_INVALID_PARAMETER
;
2227 if ((Attributes
& EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
) == EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
) {
2228 if (DataSize
< AUTHINFO_SIZE
) {
2230 // Try to write Authenticated Variable without AuthInfo.
2232 return EFI_SECURITY_VIOLATION
;
2234 PayloadSize
= DataSize
- AUTHINFO_SIZE
;
2235 } else if ((Attributes
& EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
) == EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
) {
2237 // Sanity check for EFI_VARIABLE_AUTHENTICATION_2 descriptor.
2239 if (DataSize
< OFFSET_OF_AUTHINFO2_CERT_DATA
||
2240 ((EFI_VARIABLE_AUTHENTICATION_2
*) Data
)->AuthInfo
.Hdr
.dwLength
> DataSize
- (OFFSET_OF (EFI_VARIABLE_AUTHENTICATION_2
, AuthInfo
)) ||
2241 ((EFI_VARIABLE_AUTHENTICATION_2
*) Data
)->AuthInfo
.Hdr
.dwLength
< OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID
, CertData
)) {
2242 return EFI_SECURITY_VIOLATION
;
2244 PayloadSize
= DataSize
- AUTHINFO2_SIZE (Data
);
2246 PayloadSize
= DataSize
;
2250 // The size of the VariableName, including the Unicode Null in bytes plus
2251 // the DataSize is limited to maximum size of PcdGet32 (PcdMaxHardwareErrorVariableSize)
2252 // bytes for HwErrRec, and PcdGet32 (PcdMaxVariableSize) bytes for the others.
2254 if ((Attributes
& EFI_VARIABLE_HARDWARE_ERROR_RECORD
) == EFI_VARIABLE_HARDWARE_ERROR_RECORD
) {
2255 if ((PayloadSize
> PcdGet32 (PcdMaxHardwareErrorVariableSize
)) ||
2256 (sizeof (VARIABLE_HEADER
) + StrSize (VariableName
) + PayloadSize
> PcdGet32 (PcdMaxHardwareErrorVariableSize
))) {
2257 return EFI_INVALID_PARAMETER
;
2259 if (!IsHwErrRecVariable(VariableName
, VendorGuid
)) {
2260 return EFI_INVALID_PARAMETER
;
2264 // The size of the VariableName, including the Unicode Null in bytes plus
2265 // the DataSize is limited to maximum size of PcdGet32 (PcdMaxVariableSize) bytes.
2267 if ((PayloadSize
> PcdGet32 (PcdMaxVariableSize
)) ||
2268 (sizeof (VARIABLE_HEADER
) + StrSize (VariableName
) + PayloadSize
> PcdGet32 (PcdMaxVariableSize
))) {
2269 return EFI_INVALID_PARAMETER
;
2275 // HwErrRecSupport Global Variable identifies the level of hardware error record persistence
2276 // support implemented by the platform. This variable is only modified by firmware and is read-only to the OS.
2278 if (CompareGuid (VendorGuid
, &gEfiGlobalVariableGuid
) && (StrCmp (VariableName
, L
"HwErrRecSupport") == 0)) {
2279 return EFI_WRITE_PROTECTED
;
2283 AcquireLockOnlyAtBootTime(&mVariableModuleGlobal
->VariableGlobal
.VariableServicesLock
);
2286 // Consider reentrant in MCA/INIT/NMI. It needs be reupdated.
2288 if (1 < InterlockedIncrement (&mVariableModuleGlobal
->VariableGlobal
.ReentrantState
)) {
2289 Point
= mVariableModuleGlobal
->VariableGlobal
.NonVolatileVariableBase
;
2291 // Parse non-volatile variable data and get last variable offset.
2293 NextVariable
= GetStartPointer ((VARIABLE_STORE_HEADER
*) (UINTN
) Point
);
2294 while ((NextVariable
< GetEndPointer ((VARIABLE_STORE_HEADER
*) (UINTN
) Point
))
2295 && IsValidVariableHeader (NextVariable
)) {
2296 NextVariable
= GetNextVariablePtr (NextVariable
);
2298 mVariableModuleGlobal
->NonVolatileLastVariableOffset
= (UINTN
) NextVariable
- (UINTN
) Point
;
2302 // Check whether the input variable is already existed.
2304 Status
= FindVariable (VariableName
, VendorGuid
, &Variable
, &mVariableModuleGlobal
->VariableGlobal
, TRUE
);
2305 if (!EFI_ERROR (Status
)) {
2306 if (((Variable
.CurrPtr
->Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
) == 0) && AtRuntime ()) {
2307 return EFI_WRITE_PROTECTED
;
2312 // Hook the operation of setting PlatformLangCodes/PlatformLang and LangCodes/Lang.
2314 AutoUpdateLangVariable (VariableName
, Data
, DataSize
);
2316 // Process PK, KEK, Sigdb seperately.
2318 if (CompareGuid (VendorGuid
, &gEfiGlobalVariableGuid
) && (StrCmp (VariableName
, EFI_PLATFORM_KEY_NAME
) == 0)){
2319 Status
= ProcessVarWithPk (VariableName
, VendorGuid
, Data
, DataSize
, &Variable
, Attributes
, TRUE
);
2320 } else if (CompareGuid (VendorGuid
, &gEfiGlobalVariableGuid
) && (StrCmp (VariableName
, EFI_KEY_EXCHANGE_KEY_NAME
) == 0)) {
2321 Status
= ProcessVarWithPk (VariableName
, VendorGuid
, Data
, DataSize
, &Variable
, Attributes
, FALSE
);
2322 } else if (CompareGuid (VendorGuid
, &gEfiImageSecurityDatabaseGuid
) &&
2323 ((StrCmp (VariableName
, EFI_IMAGE_SECURITY_DATABASE
) == 0) || (StrCmp (VariableName
, EFI_IMAGE_SECURITY_DATABASE1
) == 0))) {
2324 Status
= ProcessVarWithKek (VariableName
, VendorGuid
, Data
, DataSize
, &Variable
, Attributes
);
2326 Status
= ProcessVariable (VariableName
, VendorGuid
, Data
, DataSize
, &Variable
, Attributes
);
2329 InterlockedDecrement (&mVariableModuleGlobal
->VariableGlobal
.ReentrantState
);
2330 ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal
->VariableGlobal
.VariableServicesLock
);
2337 This code returns information about the EFI variables.
2339 @param Attributes Attributes bitmask to specify the type of variables
2340 on which to return information.
2341 @param MaximumVariableStorageSize Pointer to the maximum size of the storage space available
2342 for the EFI variables associated with the attributes specified.
2343 @param RemainingVariableStorageSize Pointer to the remaining size of the storage space available
2344 for EFI variables associated with the attributes specified.
2345 @param MaximumVariableSize Pointer to the maximum size of an individual EFI variables
2346 associated with the attributes specified.
2348 @return EFI_INVALID_PARAMETER An invalid combination of attribute bits was supplied.
2349 @return EFI_SUCCESS Query successfully.
2350 @return EFI_UNSUPPORTED The attribute is not supported on this platform.
2355 VariableServiceQueryVariableInfo (
2356 IN UINT32 Attributes
,
2357 OUT UINT64
*MaximumVariableStorageSize
,
2358 OUT UINT64
*RemainingVariableStorageSize
,
2359 OUT UINT64
*MaximumVariableSize
2362 VARIABLE_HEADER
*Variable
;
2363 VARIABLE_HEADER
*NextVariable
;
2364 UINT64 VariableSize
;
2365 VARIABLE_STORE_HEADER
*VariableStoreHeader
;
2366 UINT64 CommonVariableTotalSize
;
2367 UINT64 HwErrVariableTotalSize
;
2369 CommonVariableTotalSize
= 0;
2370 HwErrVariableTotalSize
= 0;
2372 if(MaximumVariableStorageSize
== NULL
|| RemainingVariableStorageSize
== NULL
|| MaximumVariableSize
== NULL
|| Attributes
== 0) {
2373 return EFI_INVALID_PARAMETER
;
2376 if((Attributes
& (EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_HARDWARE_ERROR_RECORD
)) == 0) {
2378 // Make sure the Attributes combination is supported by the platform.
2380 return EFI_UNSUPPORTED
;
2381 } else if ((Attributes
& (EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
)) == EFI_VARIABLE_RUNTIME_ACCESS
) {
2383 // Make sure if runtime bit is set, boot service bit is set also.
2385 return EFI_INVALID_PARAMETER
;
2386 } else if (AtRuntime () && ((Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
) == 0)) {
2388 // Make sure RT Attribute is set if we are in Runtime phase.
2390 return EFI_INVALID_PARAMETER
;
2391 } else if ((Attributes
& (EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_HARDWARE_ERROR_RECORD
)) == EFI_VARIABLE_HARDWARE_ERROR_RECORD
) {
2393 // Make sure Hw Attribute is set with NV.
2395 return EFI_INVALID_PARAMETER
;
2398 AcquireLockOnlyAtBootTime(&mVariableModuleGlobal
->VariableGlobal
.VariableServicesLock
);
2400 if((Attributes
& EFI_VARIABLE_NON_VOLATILE
) == 0) {
2402 // Query is Volatile related.
2404 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) ((UINTN
) mVariableModuleGlobal
->VariableGlobal
.VolatileVariableBase
);
2407 // Query is Non-Volatile related.
2409 VariableStoreHeader
= mNvVariableCache
;
2413 // Now let's fill *MaximumVariableStorageSize *RemainingVariableStorageSize
2414 // with the storage size (excluding the storage header size).
2416 *MaximumVariableStorageSize
= VariableStoreHeader
->Size
- sizeof (VARIABLE_STORE_HEADER
);
2419 // Harware error record variable needs larger size.
2421 if ((Attributes
& (EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_HARDWARE_ERROR_RECORD
)) == (EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_HARDWARE_ERROR_RECORD
)) {
2422 *MaximumVariableStorageSize
= PcdGet32 (PcdHwErrStorageSize
);
2423 *MaximumVariableSize
= PcdGet32 (PcdMaxHardwareErrorVariableSize
) - sizeof (VARIABLE_HEADER
);
2425 if ((Attributes
& EFI_VARIABLE_NON_VOLATILE
) != 0) {
2426 ASSERT (PcdGet32 (PcdHwErrStorageSize
) < VariableStoreHeader
->Size
);
2427 *MaximumVariableStorageSize
= VariableStoreHeader
->Size
- sizeof (VARIABLE_STORE_HEADER
) - PcdGet32 (PcdHwErrStorageSize
);
2431 // Let *MaximumVariableSize be PcdGet32 (PcdMaxVariableSize) with the exception of the variable header size.
2433 *MaximumVariableSize
= PcdGet32 (PcdMaxVariableSize
) - sizeof (VARIABLE_HEADER
);
2437 // Point to the starting address of the variables.
2439 Variable
= GetStartPointer (VariableStoreHeader
);
2442 // Now walk through the related variable store.
2444 while ((Variable
< GetEndPointer (VariableStoreHeader
)) && IsValidVariableHeader (Variable
)) {
2445 NextVariable
= GetNextVariablePtr (Variable
);
2446 VariableSize
= (UINT64
) (UINTN
) NextVariable
- (UINT64
) (UINTN
) Variable
;
2450 // We don't take the state of the variables in mind
2451 // when calculating RemainingVariableStorageSize,
2452 // since the space occupied by variables not marked with
2453 // VAR_ADDED is not allowed to be reclaimed in Runtime.
2455 if ((Variable
->Attributes
& EFI_VARIABLE_HARDWARE_ERROR_RECORD
) == EFI_VARIABLE_HARDWARE_ERROR_RECORD
) {
2456 HwErrVariableTotalSize
+= VariableSize
;
2458 CommonVariableTotalSize
+= VariableSize
;
2462 // Only care about Variables with State VAR_ADDED, because
2463 // the space not marked as VAR_ADDED is reclaimable now.
2465 if (Variable
->State
== VAR_ADDED
) {
2466 if ((Variable
->Attributes
& EFI_VARIABLE_HARDWARE_ERROR_RECORD
) == EFI_VARIABLE_HARDWARE_ERROR_RECORD
) {
2467 HwErrVariableTotalSize
+= VariableSize
;
2469 CommonVariableTotalSize
+= VariableSize
;
2475 // Go to the next one.
2477 Variable
= NextVariable
;
2480 if ((Attributes
& EFI_VARIABLE_HARDWARE_ERROR_RECORD
) == EFI_VARIABLE_HARDWARE_ERROR_RECORD
){
2481 *RemainingVariableStorageSize
= *MaximumVariableStorageSize
- HwErrVariableTotalSize
;
2483 *RemainingVariableStorageSize
= *MaximumVariableStorageSize
- CommonVariableTotalSize
;
2486 if (*RemainingVariableStorageSize
< sizeof (VARIABLE_HEADER
)) {
2487 *MaximumVariableSize
= 0;
2488 } else if ((*RemainingVariableStorageSize
- sizeof (VARIABLE_HEADER
)) < *MaximumVariableSize
) {
2489 *MaximumVariableSize
= *RemainingVariableStorageSize
- sizeof (VARIABLE_HEADER
);
2492 ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal
->VariableGlobal
.VariableServicesLock
);
2498 This function reclaims variable storage if free size is below the threshold.
2507 UINTN CommonVariableSpace
;
2508 UINTN RemainingCommonVariableSpace
;
2509 UINTN RemainingHwErrVariableSpace
;
2511 Status
= EFI_SUCCESS
;
2513 CommonVariableSpace
= ((VARIABLE_STORE_HEADER
*) ((UINTN
) (mVariableModuleGlobal
->VariableGlobal
.NonVolatileVariableBase
)))->Size
- sizeof (VARIABLE_STORE_HEADER
) - PcdGet32(PcdHwErrStorageSize
); //Allowable max size of common variable storage space
2515 RemainingCommonVariableSpace
= CommonVariableSpace
- mVariableModuleGlobal
->CommonVariableTotalSize
;
2517 RemainingHwErrVariableSpace
= PcdGet32 (PcdHwErrStorageSize
) - mVariableModuleGlobal
->HwErrVariableTotalSize
;
2519 // Check if the free area is blow a threshold.
2521 if ((RemainingCommonVariableSpace
< PcdGet32 (PcdMaxVariableSize
))
2522 || ((PcdGet32 (PcdHwErrStorageSize
) != 0) &&
2523 (RemainingHwErrVariableSpace
< PcdGet32 (PcdMaxHardwareErrorVariableSize
)))){
2525 mVariableModuleGlobal
->VariableGlobal
.NonVolatileVariableBase
,
2526 &mVariableModuleGlobal
->NonVolatileLastVariableOffset
,
2530 ASSERT_EFI_ERROR (Status
);
2536 Initializes variable write service after FVB was ready.
2538 @retval EFI_SUCCESS Function successfully executed.
2539 @retval Others Fail to initialize the variable service.
2543 VariableWriteServiceInitialize (
2548 VARIABLE_STORE_HEADER
*VariableStoreHeader
;
2551 EFI_PHYSICAL_ADDRESS VariableStoreBase
;
2552 VARIABLE_HEADER
*Variable
;
2555 VariableStoreBase
= mVariableModuleGlobal
->VariableGlobal
.NonVolatileVariableBase
;
2556 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*)(UINTN
)VariableStoreBase
;
2559 // Check if the free area is really free.
2561 for (Index
= mVariableModuleGlobal
->NonVolatileLastVariableOffset
; Index
< VariableStoreHeader
->Size
; Index
++) {
2562 Data
= ((UINT8
*) mNvVariableCache
)[Index
];
2565 // There must be something wrong in variable store, do reclaim operation.
2568 mVariableModuleGlobal
->VariableGlobal
.NonVolatileVariableBase
,
2569 &mVariableModuleGlobal
->NonVolatileLastVariableOffset
,
2573 if (EFI_ERROR (Status
)) {
2582 // Flush the HOB variable to flash and invalidate HOB variable.
2584 if (mVariableModuleGlobal
->VariableGlobal
.HobVariableBase
!= 0) {
2586 // Clear the HobVariableBase to avoid SetVariable() updating the variable in HOB
2588 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) (UINTN
) mVariableModuleGlobal
->VariableGlobal
.HobVariableBase
;
2589 mVariableModuleGlobal
->VariableGlobal
.HobVariableBase
= 0;
2591 for ( Variable
= GetStartPointer (VariableStoreHeader
)
2592 ; (Variable
< GetEndPointer (VariableStoreHeader
) && IsValidVariableHeader (Variable
))
2593 ; Variable
= GetNextVariablePtr (Variable
)
2595 ASSERT (Variable
->State
== VAR_ADDED
);
2596 ASSERT ((Variable
->Attributes
& EFI_VARIABLE_NON_VOLATILE
) != 0);
2597 VariableData
= GetVariableDataPtr (Variable
);
2598 Status
= VariableServiceSetVariable (
2599 GetVariableNamePtr (Variable
),
2600 &Variable
->VendorGuid
,
2601 Variable
->Attributes
,
2605 ASSERT_EFI_ERROR (Status
);
2610 // Authenticated variable initialize.
2612 Status
= AutenticatedVariableServiceInitialize ();
2619 Initializes variable store area for non-volatile and volatile variable.
2621 @retval EFI_SUCCESS Function successfully executed.
2622 @retval EFI_OUT_OF_RESOURCES Fail to allocate enough memory resource.
2626 VariableCommonInitialize (
2631 VARIABLE_STORE_HEADER
*VolatileVariableStore
;
2632 VARIABLE_STORE_HEADER
*VariableStoreHeader
;
2633 VARIABLE_HEADER
*NextVariable
;
2634 EFI_PHYSICAL_ADDRESS TempVariableStoreHeader
;
2635 EFI_PHYSICAL_ADDRESS VariableStoreBase
;
2636 UINT64 VariableStoreLength
;
2639 EFI_HOB_GUID_TYPE
*GuidHob
;
2642 // Allocate runtime memory for variable driver global structure.
2644 mVariableModuleGlobal
= AllocateRuntimeZeroPool (sizeof (VARIABLE_MODULE_GLOBAL
));
2645 if (mVariableModuleGlobal
== NULL
) {
2646 return EFI_OUT_OF_RESOURCES
;
2649 InitializeLock (&mVariableModuleGlobal
->VariableGlobal
.VariableServicesLock
, TPL_NOTIFY
);
2652 // Note that in EdkII variable driver implementation, Hardware Error Record type variable
2653 // is stored with common variable in the same NV region. So the platform integrator should
2654 // ensure that the value of PcdHwErrStorageSize is less than or equal to the value of
2655 // PcdFlashNvStorageVariableSize.
2657 ASSERT (PcdGet32 (PcdHwErrStorageSize
) <= PcdGet32 (PcdFlashNvStorageVariableSize
));
2660 // Get HOB variable store.
2662 GuidHob
= GetFirstGuidHob (&gEfiAuthenticatedVariableGuid
);
2663 if (GuidHob
!= NULL
) {
2664 VariableStoreHeader
= GET_GUID_HOB_DATA (GuidHob
);
2665 if (GetVariableStoreStatus (VariableStoreHeader
) == EfiValid
) {
2666 mVariableModuleGlobal
->VariableGlobal
.HobVariableBase
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) VariableStoreHeader
;
2668 DEBUG ((EFI_D_ERROR
, "HOB Variable Store header is corrupted!\n"));
2673 // Allocate memory for volatile variable store, note that there is a scratch space to store scratch data.
2675 ScratchSize
= MAX (PcdGet32 (PcdMaxVariableSize
), PcdGet32 (PcdMaxHardwareErrorVariableSize
));
2676 VolatileVariableStore
= AllocateRuntimePool (PcdGet32 (PcdVariableStoreSize
) + ScratchSize
);
2677 if (VolatileVariableStore
== NULL
) {
2678 FreePool (mVariableModuleGlobal
);
2679 return EFI_OUT_OF_RESOURCES
;
2682 SetMem (VolatileVariableStore
, PcdGet32 (PcdVariableStoreSize
) + ScratchSize
, 0xff);
2685 // Initialize Variable Specific Data.
2687 mVariableModuleGlobal
->VariableGlobal
.VolatileVariableBase
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) VolatileVariableStore
;
2688 mVariableModuleGlobal
->VolatileLastVariableOffset
= (UINTN
) GetStartPointer (VolatileVariableStore
) - (UINTN
) VolatileVariableStore
;
2689 mVariableModuleGlobal
->FvbInstance
= NULL
;
2691 CopyGuid (&VolatileVariableStore
->Signature
, &gEfiAuthenticatedVariableGuid
);
2692 VolatileVariableStore
->Size
= PcdGet32 (PcdVariableStoreSize
);
2693 VolatileVariableStore
->Format
= VARIABLE_STORE_FORMATTED
;
2694 VolatileVariableStore
->State
= VARIABLE_STORE_HEALTHY
;
2695 VolatileVariableStore
->Reserved
= 0;
2696 VolatileVariableStore
->Reserved1
= 0;
2699 // Get non-volatile variable store.
2702 TempVariableStoreHeader
= (EFI_PHYSICAL_ADDRESS
) PcdGet64 (PcdFlashNvStorageVariableBase64
);
2703 if (TempVariableStoreHeader
== 0) {
2704 TempVariableStoreHeader
= (EFI_PHYSICAL_ADDRESS
) PcdGet32 (PcdFlashNvStorageVariableBase
);
2708 // Check if the Firmware Volume is not corrupted
2710 if ((((EFI_FIRMWARE_VOLUME_HEADER
*)(UINTN
)(TempVariableStoreHeader
))->Signature
!= EFI_FVH_SIGNATURE
) ||
2711 (!CompareGuid (&gEfiSystemNvDataFvGuid
, &((EFI_FIRMWARE_VOLUME_HEADER
*)(UINTN
)(TempVariableStoreHeader
))->FileSystemGuid
))) {
2712 Status
= EFI_VOLUME_CORRUPTED
;
2713 DEBUG ((EFI_D_ERROR
, "Firmware Volume for Variable Store is corrupted\n"));
2717 VariableStoreBase
= TempVariableStoreHeader
+ \
2718 (((EFI_FIRMWARE_VOLUME_HEADER
*)(UINTN
)(TempVariableStoreHeader
)) -> HeaderLength
);
2719 VariableStoreLength
= (UINT64
) PcdGet32 (PcdFlashNvStorageVariableSize
) - \
2720 (((EFI_FIRMWARE_VOLUME_HEADER
*)(UINTN
)(TempVariableStoreHeader
)) -> HeaderLength
);
2722 mVariableModuleGlobal
->VariableGlobal
.NonVolatileVariableBase
= VariableStoreBase
;
2723 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*)(UINTN
)VariableStoreBase
;
2724 if (GetVariableStoreStatus (VariableStoreHeader
) != EfiValid
) {
2725 Status
= EFI_VOLUME_CORRUPTED
;
2726 DEBUG((EFI_D_INFO
, "Variable Store header is corrupted\n"));
2729 ASSERT(VariableStoreHeader
->Size
== VariableStoreLength
);
2732 // Parse non-volatile variable data and get last variable offset.
2734 NextVariable
= GetStartPointer ((VARIABLE_STORE_HEADER
*)(UINTN
)VariableStoreBase
);
2735 while (IsValidVariableHeader (NextVariable
)) {
2736 VariableSize
= NextVariable
->NameSize
+ NextVariable
->DataSize
+ sizeof (VARIABLE_HEADER
);
2737 if ((NextVariable
->Attributes
& (EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_HARDWARE_ERROR_RECORD
)) == (EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_HARDWARE_ERROR_RECORD
)) {
2738 mVariableModuleGlobal
->HwErrVariableTotalSize
+= HEADER_ALIGN (VariableSize
);
2740 mVariableModuleGlobal
->CommonVariableTotalSize
+= HEADER_ALIGN (VariableSize
);
2743 NextVariable
= GetNextVariablePtr (NextVariable
);
2746 mVariableModuleGlobal
->NonVolatileLastVariableOffset
= (UINTN
) NextVariable
- (UINTN
) VariableStoreBase
;
2749 // Allocate runtime memory used for a memory copy of the FLASH region.
2750 // Keep the memory and the FLASH in sync as updates occur
2752 mNvVariableCache
= AllocateRuntimeZeroPool ((UINTN
)VariableStoreLength
);
2753 if (mNvVariableCache
== NULL
) {
2754 Status
= EFI_OUT_OF_RESOURCES
;
2757 CopyMem (mNvVariableCache
, (CHAR8
*)(UINTN
)VariableStoreBase
, (UINTN
)VariableStoreLength
);
2758 Status
= EFI_SUCCESS
;
2761 if (EFI_ERROR (Status
)) {
2762 FreePool (mVariableModuleGlobal
);
2763 FreePool (VolatileVariableStore
);
2771 Get the proper fvb handle and/or fvb protocol by the given Flash address.
2773 @param[in] Address The Flash address.
2774 @param[out] FvbHandle In output, if it is not NULL, it points to the proper FVB handle.
2775 @param[out] FvbProtocol In output, if it is not NULL, it points to the proper FVB protocol.
2779 GetFvbInfoByAddress (
2780 IN EFI_PHYSICAL_ADDRESS Address
,
2781 OUT EFI_HANDLE
*FvbHandle OPTIONAL
,
2782 OUT EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
**FvbProtocol OPTIONAL
2786 EFI_HANDLE
*HandleBuffer
;
2789 EFI_PHYSICAL_ADDRESS FvbBaseAddress
;
2790 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*Fvb
;
2791 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
2792 EFI_FVB_ATTRIBUTES_2 Attributes
;
2795 // Get all FVB handles.
2797 Status
= GetFvbCountAndBuffer (&HandleCount
, &HandleBuffer
);
2798 if (EFI_ERROR (Status
)) {
2799 return EFI_NOT_FOUND
;
2803 // Get the FVB to access variable store.
2806 for (Index
= 0; Index
< HandleCount
; Index
+= 1, Status
= EFI_NOT_FOUND
, Fvb
= NULL
) {
2807 Status
= GetFvbByHandle (HandleBuffer
[Index
], &Fvb
);
2808 if (EFI_ERROR (Status
)) {
2809 Status
= EFI_NOT_FOUND
;
2814 // Ensure this FVB protocol supported Write operation.
2816 Status
= Fvb
->GetAttributes (Fvb
, &Attributes
);
2817 if (EFI_ERROR (Status
) || ((Attributes
& EFI_FVB2_WRITE_STATUS
) == 0)) {
2822 // Compare the address and select the right one.
2824 Status
= Fvb
->GetPhysicalAddress (Fvb
, &FvbBaseAddress
);
2825 if (EFI_ERROR (Status
)) {
2829 FwVolHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) ((UINTN
) FvbBaseAddress
);
2830 if ((Address
>= FvbBaseAddress
) && (Address
< (FvbBaseAddress
+ FwVolHeader
->FvLength
))) {
2831 if (FvbHandle
!= NULL
) {
2832 *FvbHandle
= HandleBuffer
[Index
];
2834 if (FvbProtocol
!= NULL
) {
2837 Status
= EFI_SUCCESS
;
2841 FreePool (HandleBuffer
);
2844 Status
= EFI_NOT_FOUND
;