2 EFI Runtime Variable services.
4 Copyright (c) 2006 - 2008, Intel Corporation
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 VARIABLE_MODULE_GLOBAL
*mVariableModuleGlobal
;
19 EFI_EVENT mVirtualAddressChangeEvent
= NULL
;
20 EFI_HANDLE mHandle
= NULL
;
24 // This is a temperary function which will be removed
25 // when EfiAcquireLock in UefiLib can handle the
26 // the call in UEFI Runtimer driver in RT phase.
29 AcquireLockOnlyAtBootTime (
33 if (!EfiAtRuntime ()) {
34 EfiAcquireLock (Lock
);
39 // This is a temperary function which will be removed
40 // when EfiAcquireLock in UefiLib can handle the
41 // the call in UEFI Runtimer driver in RT phase.
44 ReleaseLockOnlyAtBootTime (
48 if (!EfiAtRuntime ()) {
49 EfiReleaseLock (Lock
);
54 GLOBAL_REMOVE_IF_UNREFERENCED VARIABLE_INFO_ENTRY
*gVariableInfo
= NULL
;
58 Routine used to track statistical information about variable usage.
59 The data is stored in the EFI system table so it can be accessed later.
60 VariableInfo.efi can dump out the table. Only Boot Services variable
61 accesses are tracked by this code. The PcdVariableCollectStatistics
62 build flag controls if this feature is enabled.
64 A read that hits in the cache will have Read and Cache true for
65 the transaction. Data is allocated by this routine, but never
68 @param[in] VariableName Name of the Variable to track
69 @param[in] VendorGuid Guid of the Variable to track
70 @param[in] Volatile TRUE if volatile FALSE if non-volatile
71 @param[in] Read TRUE if GetVariable() was called
72 @param[in] Write TRUE if SetVariable() was called
73 @param[in] Delete TRUE if deleted via SetVariable()
74 @param[in] Cache TRUE for a cache hit.
79 IN CHAR16
*VariableName
,
80 IN EFI_GUID
*VendorGuid
,
88 VARIABLE_INFO_ENTRY
*Entry
;
90 if (FeaturePcdGet (PcdVariableCollectStatistics
)) {
92 if (EfiAtRuntime ()) {
93 // Don't collect statistics at runtime
97 if (gVariableInfo
== NULL
) {
99 // on the first call allocate a entry and place a pointer to it in
100 // the EFI System Table
102 gVariableInfo
= AllocateZeroPool (sizeof (VARIABLE_INFO_ENTRY
));
103 ASSERT (gVariableInfo
!= NULL
);
105 CopyGuid (&gVariableInfo
->VendorGuid
, VendorGuid
);
106 gVariableInfo
->Name
= AllocatePool (StrLen (VariableName
));
107 StrCpy (gVariableInfo
->Name
, VariableName
);
108 gVariableInfo
->Volatile
= Volatile
;
110 gBS
->InstallConfigurationTable (&gEfiVariableInfoGuid
, gVariableInfo
);
114 for (Entry
= gVariableInfo
; Entry
!= NULL
; Entry
= Entry
->Next
) {
115 if (CompareGuid (VendorGuid
, &Entry
->VendorGuid
)) {
116 if (StrCmp (VariableName
, Entry
->Name
) == 0) {
124 Entry
->DeleteCount
++;
134 if (Entry
->Next
== NULL
) {
136 // If the entry is not in the table add it.
137 // Next iteration of the loop will fill in the data
139 Entry
->Next
= AllocateZeroPool (sizeof (VARIABLE_INFO_ENTRY
));
140 ASSERT (Entry
->Next
!= NULL
);
142 CopyGuid (&Entry
->Next
->VendorGuid
, VendorGuid
);
143 Entry
->Next
->Name
= AllocatePool (StrLen (VariableName
));
144 StrCpy (Entry
->Next
->Name
, VariableName
);
145 Entry
->Next
->Volatile
= Volatile
;
154 IsValidVariableHeader (
155 IN VARIABLE_HEADER
*Variable
161 This code checks if variable header is valid or not.
164 Variable Pointer to the Variable Header.
167 TRUE Variable header is valid.
168 FALSE Variable header is not valid.
172 if (Variable
== NULL
|| Variable
->StartId
!= VARIABLE_DATA
) {
181 UpdateVariableStore (
182 IN VARIABLE_GLOBAL
*Global
,
184 IN BOOLEAN SetByIndex
,
186 IN UINTN DataPtrIndex
,
194 This function writes data to the FWH at the correct LBA even if the LBAs
199 Global - Pointer to VARAIBLE_GLOBAL structure
200 Volatile - If the Variable is Volatile or Non-Volatile
201 SetByIndex - TRUE: Target pointer is given as index
202 FALSE: Target pointer is absolute
203 Instance - Instance of FV Block services
204 DataPtrIndex - Pointer to the Data from the end of VARIABLE_STORE_HEADER
206 DataSize - Size of data to be written.
207 Buffer - Pointer to the buffer from which data is written
211 EFI_INVALID_PARAMETER - Parameters not valid
212 EFI_SUCCESS - Variable store successfully updated
216 EFI_FV_BLOCK_MAP_ENTRY
*PtrBlockMapEntry
;
224 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
225 VARIABLE_STORE_HEADER
*VolatileBase
;
226 EFI_PHYSICAL_ADDRESS FvVolHdr
;
227 EFI_PHYSICAL_ADDRESS DataPtr
;
231 DataPtr
= DataPtrIndex
;
234 // Check if the Data is Volatile
237 EfiFvbGetPhysicalAddress (Instance
, &FvVolHdr
);
238 FwVolHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) ((UINTN
) FvVolHdr
);
240 // Data Pointer should point to the actual Address where data is to be
244 DataPtr
+= mVariableModuleGlobal
->VariableGlobal
.NonVolatileVariableBase
;
247 if ((DataPtr
+ DataSize
) >= ((EFI_PHYSICAL_ADDRESS
) (UINTN
) ((UINT8
*) FwVolHeader
+ FwVolHeader
->FvLength
))) {
248 return EFI_INVALID_PARAMETER
;
252 // Data Pointer should point to the actual Address where data is to be
255 VolatileBase
= (VARIABLE_STORE_HEADER
*) ((UINTN
) mVariableModuleGlobal
->VariableGlobal
.VolatileVariableBase
);
257 DataPtr
+= mVariableModuleGlobal
->VariableGlobal
.VolatileVariableBase
;
260 if ((DataPtr
+ DataSize
) >= ((UINTN
) ((UINT8
*) VolatileBase
+ VolatileBase
->Size
))) {
261 return EFI_INVALID_PARAMETER
;
265 // If Volatile Variable just do a simple mem copy.
267 CopyMem ((UINT8
*)(UINTN
)DataPtr
, Buffer
, DataSize
);
272 // If we are here we are dealing with Non-Volatile Variables
274 LinearOffset
= (UINTN
) FwVolHeader
;
275 CurrWritePtr
= (UINTN
) DataPtr
;
276 CurrWriteSize
= DataSize
;
280 if (CurrWritePtr
< LinearOffset
) {
281 return EFI_INVALID_PARAMETER
;
284 for (PtrBlockMapEntry
= FwVolHeader
->BlockMap
; PtrBlockMapEntry
->NumBlocks
!= 0; PtrBlockMapEntry
++) {
285 for (BlockIndex2
= 0; BlockIndex2
< PtrBlockMapEntry
->NumBlocks
; BlockIndex2
++) {
287 // Check to see if the Variable Writes are spanning through multiple
290 if ((CurrWritePtr
>= LinearOffset
) && (CurrWritePtr
< LinearOffset
+ PtrBlockMapEntry
->Length
)) {
291 if ((CurrWritePtr
+ CurrWriteSize
) <= (LinearOffset
+ PtrBlockMapEntry
->Length
)) {
292 Status
= EfiFvbWriteBlock (
295 (UINTN
) (CurrWritePtr
- LinearOffset
),
301 Size
= (UINT32
) (LinearOffset
+ PtrBlockMapEntry
->Length
- CurrWritePtr
);
302 Status
= EfiFvbWriteBlock (
305 (UINTN
) (CurrWritePtr
- LinearOffset
),
309 if (EFI_ERROR (Status
)) {
313 CurrWritePtr
= LinearOffset
+ PtrBlockMapEntry
->Length
;
314 CurrBuffer
= CurrBuffer
+ Size
;
315 CurrWriteSize
= CurrWriteSize
- Size
;
319 LinearOffset
+= PtrBlockMapEntry
->Length
;
328 VARIABLE_STORE_STATUS
329 GetVariableStoreStatus (
330 IN VARIABLE_STORE_HEADER
*VarStoreHeader
336 This code gets the current status of Variable Store.
340 VarStoreHeader Pointer to the Variable Store Header.
344 EfiRaw Variable store status is raw
345 EfiValid Variable store status is valid
346 EfiInvalid Variable store status is invalid
350 if (VarStoreHeader
->Signature
== VARIABLE_STORE_SIGNATURE
&&
351 VarStoreHeader
->Format
== VARIABLE_STORE_FORMATTED
&&
352 VarStoreHeader
->State
== VARIABLE_STORE_HEALTHY
356 } else if (VarStoreHeader
->Signature
== 0xffffffff &&
357 VarStoreHeader
->Size
== 0xffffffff &&
358 VarStoreHeader
->Format
== 0xff &&
359 VarStoreHeader
->State
== 0xff
371 IN VARIABLE_HEADER
*Variable
377 This code gets the size of name of variable.
381 Variable Pointer to the Variable Header.
385 UINTN Size of variable in bytes
389 if (Variable
->State
== (UINT8
) (-1) ||
390 Variable
->DataSize
== (UINT32
) -1 ||
391 Variable
->NameSize
== (UINT32
) -1 ||
392 Variable
->Attributes
== (UINT32
) -1) {
395 return (UINTN
) Variable
->NameSize
;
400 IN VARIABLE_HEADER
*Variable
406 This code gets the size of name of variable.
410 Variable Pointer to the Variable Header.
414 UINTN Size of variable in bytes
418 if (Variable
->State
== (UINT8
) -1 ||
419 Variable
->DataSize
== (UINT32
) -1 ||
420 Variable
->NameSize
== (UINT32
) -1 ||
421 Variable
->Attributes
== (UINT32
) -1) {
424 return (UINTN
) Variable
->DataSize
;
429 IN VARIABLE_HEADER
*Variable
435 This code gets the pointer to the variable name.
439 Variable Pointer to the Variable Header.
443 CHAR16* Pointer to Variable Name
448 return (CHAR16
*) (Variable
+ 1);
453 IN VARIABLE_HEADER
*Variable
459 This code gets the pointer to the variable data.
463 Variable Pointer to the Variable Header.
467 UINT8* Pointer to Variable Data
474 // Be careful about pad size for alignment
476 Value
= (UINTN
) GetVariableNamePtr (Variable
);
477 Value
+= NameSizeOfVariable (Variable
);
478 Value
+= GET_PAD_SIZE (NameSizeOfVariable (Variable
));
480 return (UINT8
*) Value
;
486 IN VARIABLE_HEADER
*Variable
492 This code gets the pointer to the next variable header.
496 Variable Pointer to the Variable Header.
500 VARIABLE_HEADER* Pointer to next variable header.
506 if (!IsValidVariableHeader (Variable
)) {
510 Value
= (UINTN
) GetVariableDataPtr (Variable
);
511 Value
+= DataSizeOfVariable (Variable
);
512 Value
+= GET_PAD_SIZE (DataSizeOfVariable (Variable
));
515 // Be careful about pad size for alignment
517 return (VARIABLE_HEADER
*) HEADER_ALIGN (Value
);
522 IN VARIABLE_STORE_HEADER
*VarStoreHeader
528 This code gets the pointer to the first variable memory pointer byte
532 VarStoreHeader Pointer to the Variable Store Header.
536 VARIABLE_HEADER* Pointer to last unavailable Variable Header
541 // The end of variable store
543 return (VARIABLE_HEADER
*) HEADER_ALIGN (VarStoreHeader
+ 1);
548 IN VARIABLE_STORE_HEADER
*VarStoreHeader
554 This code gets the pointer to the last variable memory pointer byte
558 VarStoreHeader Pointer to the Variable Store Header.
562 VARIABLE_HEADER* Pointer to last unavailable Variable Header
567 // The end of variable store
569 return (VARIABLE_HEADER
*) HEADER_ALIGN ((UINTN
) VarStoreHeader
+ VarStoreHeader
->Size
);
575 IN EFI_PHYSICAL_ADDRESS VariableBase
,
576 OUT UINTN
*LastVariableOffset
,
577 IN BOOLEAN IsVolatile
,
578 IN VARIABLE_HEADER
*UpdatingVariable
584 Variable store garbage collection and reclaim operation
588 VariableBase Base address of variable store
589 LastVariableOffset Offset of last variable
590 IsVolatile The variable store is volatile or not,
591 if it is non-volatile, need FTW
599 VARIABLE_HEADER
*Variable
;
600 VARIABLE_HEADER
*AddedVariable
;
601 VARIABLE_HEADER
*NextVariable
;
602 VARIABLE_HEADER
*NextAddedVariable
;
603 VARIABLE_STORE_HEADER
*VariableStoreHeader
;
605 UINTN MaximumBufferSize
;
614 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) ((UINTN
) VariableBase
);
617 // Start Pointers for the variable.
619 Variable
= GetStartPointer (VariableStoreHeader
);
620 MaximumBufferSize
= sizeof (VARIABLE_STORE_HEADER
);
622 while (IsValidVariableHeader (Variable
)) {
623 NextVariable
= GetNextVariablePtr (Variable
);
624 if (Variable
->State
== VAR_ADDED
||
625 Variable
->State
== (VAR_IN_DELETED_TRANSITION
& VAR_ADDED
)
627 VariableSize
= (UINTN
) NextVariable
- (UINTN
) Variable
;
628 MaximumBufferSize
+= VariableSize
;
631 Variable
= NextVariable
;
635 // Reserve the 1 Bytes with Oxff to identify the
636 // end of the variable buffer.
638 MaximumBufferSize
+= 1;
639 ValidBuffer
= AllocatePool (MaximumBufferSize
);
640 if (ValidBuffer
== NULL
) {
641 return EFI_OUT_OF_RESOURCES
;
644 SetMem (ValidBuffer
, MaximumBufferSize
, 0xff);
647 // Copy variable store header
649 CopyMem (ValidBuffer
, VariableStoreHeader
, sizeof (VARIABLE_STORE_HEADER
));
650 CurrPtr
= (UINT8
*) GetStartPointer ((VARIABLE_STORE_HEADER
*) ValidBuffer
);
653 // Start Pointers for the variable.
657 // Reinstall all ADDED variables
659 Variable
= GetStartPointer (VariableStoreHeader
);
660 while (IsValidVariableHeader (Variable
)) {
661 NextVariable
= GetNextVariablePtr (Variable
);
662 if (Variable
->State
== VAR_ADDED
) {
663 VariableSize
= (UINTN
) NextVariable
- (UINTN
) Variable
;
664 CopyMem (CurrPtr
, (UINT8
*) Variable
, VariableSize
);
665 CurrPtr
+= VariableSize
;
668 Variable
= NextVariable
;
671 // Reinstall all in delete transition variables
673 Variable
= GetStartPointer (VariableStoreHeader
);
674 while (IsValidVariableHeader (Variable
)) {
675 NextVariable
= GetNextVariablePtr (Variable
);
676 if (Variable
->State
== (VAR_IN_DELETED_TRANSITION
& VAR_ADDED
)) {
679 // Buffer has cached all ADDED variable.
680 // Per IN_DELETED variable, we have to guarantee that
681 // no ADDED one in previous buffer.
685 AddedVariable
= GetStartPointer ((VARIABLE_STORE_HEADER
*) ValidBuffer
);
686 while (IsValidVariableHeader (AddedVariable
)) {
687 NextAddedVariable
= GetNextVariablePtr (AddedVariable
);
688 NameSize
= NameSizeOfVariable (AddedVariable
);
689 if (CompareGuid (&AddedVariable
->VendorGuid
, &Variable
->VendorGuid
) &&
690 NameSize
== NameSizeOfVariable (Variable
)
692 Point0
= (VOID
*) GetVariableNamePtr (AddedVariable
);
693 Point1
= (VOID
*) GetVariableNamePtr (Variable
);
697 NameSizeOfVariable (AddedVariable
)
704 AddedVariable
= NextAddedVariable
;
707 VariableSize
= (UINTN
) NextVariable
- (UINTN
) Variable
;
708 CopyMem (CurrPtr
, (UINT8
*) Variable
, VariableSize
);
709 if (Variable
!= UpdatingVariable
) {
710 ((VARIABLE_HEADER
*) CurrPtr
)->State
= VAR_ADDED
;
712 CurrPtr
+= VariableSize
;
716 Variable
= NextVariable
;
721 // If volatile variable store, just copy valid buffer
723 SetMem ((UINT8
*) (UINTN
) VariableBase
, VariableStoreHeader
->Size
, 0xff);
724 CopyMem ((UINT8
*) (UINTN
) VariableBase
, ValidBuffer
, (UINTN
) (CurrPtr
- (UINT8
*) ValidBuffer
));
725 Status
= EFI_SUCCESS
;
728 // If non-volatile variable store, perform FTW here.
730 Status
= FtwVariableSpace (
733 (UINTN
) (CurrPtr
- (UINT8
*) ValidBuffer
)
736 if (!EFI_ERROR (Status
)) {
737 *LastVariableOffset
= (UINTN
) (CurrPtr
- (UINT8
*) ValidBuffer
);
739 *LastVariableOffset
= 0;
742 FreePool (ValidBuffer
);
749 // The current Hii implementation accesses this variable a larg # of times on every boot.
750 // Other common variables are only accessed a single time. This is why this cache algorithm
751 // only targets a single variable. Probably to get an performance improvement out of
752 // a Cache you would need a cache that improves the search performance for a variable.
754 VARIABLE_CACHE_ENTRY mVariableCache
[] = {
756 &gEfiGlobalVariableGuid
,
766 Update the Cache with Variable information. These are the same
767 arguments as the EFI Variable services.
769 @param[in] VariableName Name of variable
770 @param[in] VendorGuid Guid of variable
771 @param[in] Attribute Attribue of the variable
772 @param[in] DataSize Size of data. 0 means delete
773 @param[in] Data Variable data
777 UpdateVariableCache (
778 IN CHAR16
*VariableName
,
779 IN EFI_GUID
*VendorGuid
,
780 IN UINT32 Attributes
,
785 VARIABLE_CACHE_ENTRY
*Entry
;
788 if (EfiAtRuntime ()) {
789 // Don't use the cache at runtime
793 for (Index
= 0, Entry
= mVariableCache
; Index
< sizeof (mVariableCache
)/sizeof (VARIABLE_CACHE_ENTRY
); Index
++, Entry
++) {
794 if (CompareGuid (VendorGuid
, Entry
->Guid
)) {
795 if (StrCmp (VariableName
, Entry
->Name
) == 0) {
796 Entry
->Attributes
= Attributes
;
799 if (Entry
->DataSize
!= 0) {
800 FreePool (Entry
->Data
);
802 Entry
->DataSize
= DataSize
;
803 } else if (DataSize
== Entry
->DataSize
) {
804 CopyMem (Entry
->Data
, Data
, DataSize
);
806 Entry
->Data
= AllocatePool (DataSize
);
807 Entry
->DataSize
= DataSize
;
808 CopyMem (Entry
->Data
, Data
, DataSize
);
817 Search the cache to see if the variable is in the cache.
819 @param[in] VariableName Name of variable
820 @param[in] VendorGuid Guid of variable
821 @param[in] Attribute Attribue returned
822 @param[in] DataSize Size of data returned
823 @param[in] Data Variable data returned
825 @retval EFI_SUCCESS VariableGuid & VariableName data was returned.
826 @retval other Not found.
830 FindVariableInCache (
831 IN CHAR16
*VariableName
,
832 IN EFI_GUID
*VendorGuid
,
833 OUT UINT32
*Attributes OPTIONAL
,
834 IN OUT UINTN
*DataSize
,
838 VARIABLE_CACHE_ENTRY
*Entry
;
841 if (EfiAtRuntime ()) {
842 // Don't use the cache at runtime
843 return EFI_NOT_FOUND
;
846 for (Index
= 0, Entry
= mVariableCache
; Index
< sizeof (mVariableCache
)/sizeof (VARIABLE_CACHE_ENTRY
); Index
++, Entry
++) {
847 if (CompareGuid (VendorGuid
, Entry
->Guid
)) {
848 if (StrCmp (VariableName
, Entry
->Name
) == 0) {
849 if (Entry
->DataSize
== 0) {
850 // Variable was deleted so return not found
851 return EFI_NOT_FOUND
;
852 } else if (Entry
->DataSize
> *DataSize
) {
853 // If the buffer is too small return correct size
854 *DataSize
= Entry
->DataSize
;
855 return EFI_BUFFER_TOO_SMALL
;
857 *DataSize
= Entry
->DataSize
;
859 CopyMem (Data
, Entry
->Data
, Entry
->DataSize
);
860 if (Attributes
!= NULL
) {
861 *Attributes
= Entry
->Attributes
;
869 return EFI_NOT_FOUND
;
875 IN CHAR16
*VariableName
,
876 IN EFI_GUID
*VendorGuid
,
877 OUT VARIABLE_POINTER_TRACK
*PtrTrack
,
878 IN VARIABLE_GLOBAL
*Global
884 This code finds variable in storage blocks (Volatile or Non-Volatile)
888 VariableName Name of the variable to be found
889 VendorGuid Vendor GUID to be found.
890 PtrTrack Variable Track Pointer structure that contains
891 Variable Information.
892 Contains the pointer of Variable header.
893 Global VARIABLE_GLOBAL pointer
901 VARIABLE_HEADER
*Variable
[2];
902 VARIABLE_HEADER
*InDeletedVariable
;
903 VARIABLE_STORE_HEADER
*VariableStoreHeader
[2];
904 UINTN InDeletedStorageIndex
;
909 // 0: Volatile, 1: Non-Volatile
910 // The index and attributes mapping must be kept in this order as RuntimeServiceGetNextVariableName
911 // make use of this mapping to implement search algorithme.
913 VariableStoreHeader
[0] = (VARIABLE_STORE_HEADER
*) ((UINTN
) mVariableModuleGlobal
->VariableGlobal
.VolatileVariableBase
);
914 VariableStoreHeader
[1] = (VARIABLE_STORE_HEADER
*) ((UINTN
) mVariableModuleGlobal
->VariableGlobal
.NonVolatileVariableBase
);
917 // Start Pointers for the variable.
918 // Actual Data Pointer where data can be written.
920 Variable
[0] = GetStartPointer (VariableStoreHeader
[0]);
921 Variable
[1] = GetStartPointer (VariableStoreHeader
[1]);
923 if (VariableName
[0] != 0 && VendorGuid
== NULL
) {
924 return EFI_INVALID_PARAMETER
;
928 // Find the variable by walk through volatile and then non-volatile variable store
930 InDeletedVariable
= NULL
;
931 InDeletedStorageIndex
= 0;
932 for (Index
= 0; Index
< 2; Index
++) {
933 while (IsValidVariableHeader (Variable
[Index
]) && (Variable
[Index
] <= GetEndPointer (VariableStoreHeader
[Index
]))) {
934 if (Variable
[Index
]->State
== VAR_ADDED
||
935 Variable
[Index
]->State
== (VAR_IN_DELETED_TRANSITION
& VAR_ADDED
)
937 if (!EfiAtRuntime () || (Variable
[Index
]->Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
)) {
938 if (VariableName
[0] == 0) {
939 if (Variable
[Index
]->State
== (VAR_IN_DELETED_TRANSITION
& VAR_ADDED
)) {
940 InDeletedVariable
= Variable
[Index
];
941 InDeletedStorageIndex
= Index
;
943 PtrTrack
->StartPtr
= GetStartPointer (VariableStoreHeader
[Index
]);
944 PtrTrack
->EndPtr
= GetEndPointer (VariableStoreHeader
[Index
]);
945 PtrTrack
->CurrPtr
= Variable
[Index
];
946 PtrTrack
->Volatile
= (BOOLEAN
)(Index
== 0);
951 if (CompareGuid (VendorGuid
, &Variable
[Index
]->VendorGuid
)) {
952 Point
= (VOID
*) GetVariableNamePtr (Variable
[Index
]);
954 ASSERT (NameSizeOfVariable (Variable
[Index
]) != 0);
955 if (!CompareMem (VariableName
, Point
, NameSizeOfVariable (Variable
[Index
]))) {
956 if (Variable
[Index
]->State
== (VAR_IN_DELETED_TRANSITION
& VAR_ADDED
)) {
957 InDeletedVariable
= Variable
[Index
];
958 InDeletedStorageIndex
= Index
;
960 PtrTrack
->StartPtr
= GetStartPointer (VariableStoreHeader
[Index
]);
961 PtrTrack
->EndPtr
= GetEndPointer (VariableStoreHeader
[Index
]);
962 PtrTrack
->CurrPtr
= Variable
[Index
];
963 PtrTrack
->Volatile
= (BOOLEAN
)(Index
== 0);
973 Variable
[Index
] = GetNextVariablePtr (Variable
[Index
]);
975 if (InDeletedVariable
!= NULL
) {
976 PtrTrack
->StartPtr
= GetStartPointer (VariableStoreHeader
[InDeletedStorageIndex
]);
977 PtrTrack
->EndPtr
= GetEndPointer (VariableStoreHeader
[InDeletedStorageIndex
]);
978 PtrTrack
->CurrPtr
= InDeletedVariable
;
979 PtrTrack
->Volatile
= (BOOLEAN
)(InDeletedStorageIndex
== 0);
983 PtrTrack
->CurrPtr
= NULL
;
984 return EFI_NOT_FOUND
;
993 This code finds variable in storage blocks (Volatile or Non-Volatile)
997 VariableName Name of Variable to be found
998 VendorGuid Variable vendor GUID
999 Attributes OPTIONAL Attribute value of the variable found
1000 DataSize Size of Data found. If size is less than the
1001 data, this value contains the required size.
1003 Global Pointer to VARIABLE_GLOBAL structure
1004 Instance Instance of the Firmware Volume.
1008 EFI_INVALID_PARAMETER - Invalid parameter
1009 EFI_SUCCESS - Find the specified variable
1010 EFI_NOT_FOUND - Not found
1011 EFI_BUFFER_TO_SMALL - DataSize is too small for the result
1017 RuntimeServiceGetVariable (
1018 IN CHAR16
*VariableName
,
1019 IN EFI_GUID
*VendorGuid
,
1020 OUT UINT32
*Attributes OPTIONAL
,
1021 IN OUT UINTN
*DataSize
,
1026 VARIABLE_POINTER_TRACK Variable
;
1029 if (VariableName
== NULL
|| VendorGuid
== NULL
|| DataSize
== NULL
) {
1030 return EFI_INVALID_PARAMETER
;
1033 AcquireLockOnlyAtBootTime(&mVariableModuleGlobal
->VariableGlobal
.VariableServicesLock
);
1036 // Find existing variable
1038 Status
= FindVariableInCache (VariableName
, VendorGuid
, Attributes
, DataSize
, Data
);
1039 if ((Status
== EFI_BUFFER_TOO_SMALL
) || (Status
== EFI_SUCCESS
)){
1041 UpdateVariableInfo (VariableName
, VendorGuid
, FALSE
, TRUE
, FALSE
, FALSE
, TRUE
);
1045 Status
= FindVariable (VariableName
, VendorGuid
, &Variable
, &mVariableModuleGlobal
->VariableGlobal
);
1046 if (Variable
.CurrPtr
== NULL
|| EFI_ERROR (Status
)) {
1053 VarDataSize
= DataSizeOfVariable (Variable
.CurrPtr
);
1054 ASSERT (VarDataSize
!= 0);
1056 if (*DataSize
>= VarDataSize
) {
1058 Status
= EFI_INVALID_PARAMETER
;
1062 CopyMem (Data
, GetVariableDataPtr (Variable
.CurrPtr
), VarDataSize
);
1063 if (Attributes
!= NULL
) {
1064 *Attributes
= Variable
.CurrPtr
->Attributes
;
1067 *DataSize
= VarDataSize
;
1068 UpdateVariableInfo (VariableName
, VendorGuid
, Variable
.Volatile
, TRUE
, FALSE
, FALSE
, FALSE
);
1069 UpdateVariableCache (VariableName
, VendorGuid
, Variable
.CurrPtr
->Attributes
, VarDataSize
, Data
);
1071 Status
= EFI_SUCCESS
;
1074 *DataSize
= VarDataSize
;
1075 Status
= EFI_BUFFER_TOO_SMALL
;
1080 ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal
->VariableGlobal
.VariableServicesLock
);
1088 Routine Description:
1090 This code Finds the Next available variable
1094 VariableNameSize Size of the variable
1095 VariableName Pointer to variable name
1096 VendorGuid Variable Vendor Guid
1097 Global VARIABLE_GLOBAL structure pointer.
1098 Instance FV instance
1107 RuntimeServiceGetNextVariableName (
1108 IN OUT UINTN
*VariableNameSize
,
1109 IN OUT CHAR16
*VariableName
,
1110 IN OUT EFI_GUID
*VendorGuid
1113 VARIABLE_POINTER_TRACK Variable
;
1117 if (VariableNameSize
== NULL
|| VariableName
== NULL
|| VendorGuid
== NULL
) {
1118 return EFI_INVALID_PARAMETER
;
1121 AcquireLockOnlyAtBootTime(&mVariableModuleGlobal
->VariableGlobal
.VariableServicesLock
);
1123 Status
= FindVariable (VariableName
, VendorGuid
, &Variable
, &mVariableModuleGlobal
->VariableGlobal
);
1124 if (Variable
.CurrPtr
== NULL
|| EFI_ERROR (Status
)) {
1128 if (VariableName
[0] != 0) {
1130 // If variable name is not NULL, get next variable
1132 Variable
.CurrPtr
= GetNextVariablePtr (Variable
.CurrPtr
);
1137 // If both volatile and non-volatile variable store are parsed,
1140 if (Variable
.CurrPtr
>= Variable
.EndPtr
|| Variable
.CurrPtr
== NULL
) {
1141 Variable
.Volatile
= (BOOLEAN
) (Variable
.Volatile
^ ((BOOLEAN
) 0x1));
1142 if (!Variable
.Volatile
) {
1143 Variable
.StartPtr
= GetStartPointer ((VARIABLE_STORE_HEADER
*) (UINTN
) mVariableModuleGlobal
->VariableGlobal
.NonVolatileVariableBase
);
1144 Variable
.EndPtr
= GetEndPointer ((VARIABLE_STORE_HEADER
*) ((UINTN
) mVariableModuleGlobal
->VariableGlobal
.NonVolatileVariableBase
));
1146 Status
= EFI_NOT_FOUND
;
1150 Variable
.CurrPtr
= Variable
.StartPtr
;
1151 if (!IsValidVariableHeader (Variable
.CurrPtr
)) {
1156 // Variable is found
1158 if (IsValidVariableHeader (Variable
.CurrPtr
) && Variable
.CurrPtr
->State
== VAR_ADDED
) {
1159 if (!(EfiAtRuntime () && !(Variable
.CurrPtr
->Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
))) {
1160 VarNameSize
= NameSizeOfVariable (Variable
.CurrPtr
);
1161 ASSERT (VarNameSize
!= 0);
1163 if (VarNameSize
<= *VariableNameSize
) {
1166 GetVariableNamePtr (Variable
.CurrPtr
),
1171 &Variable
.CurrPtr
->VendorGuid
,
1174 Status
= EFI_SUCCESS
;
1176 Status
= EFI_BUFFER_TOO_SMALL
;
1179 *VariableNameSize
= VarNameSize
;
1184 Variable
.CurrPtr
= GetNextVariablePtr (Variable
.CurrPtr
);
1188 ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal
->VariableGlobal
.VariableServicesLock
);
1195 Routine Description:
1197 This code sets variable in storage blocks (Volatile or Non-Volatile)
1201 VariableName Name of Variable to be found
1202 VendorGuid Variable vendor GUID
1203 Attributes Attribute value of the variable found
1204 DataSize Size of Data found. If size is less than the
1205 data, this value contains the required size.
1207 Global Pointer to VARIABLE_GLOBAL structure
1208 VolatileOffset The offset of last volatile variable
1209 NonVolatileOffset The offset of last non-volatile variable
1210 Instance Instance of the Firmware Volume.
1214 EFI_INVALID_PARAMETER - Invalid parameter
1215 EFI_SUCCESS - Set successfully
1216 EFI_OUT_OF_RESOURCES - Resource not enough to set variable
1217 EFI_NOT_FOUND - Not found
1218 EFI_DEVICE_ERROR - Variable can not be saved due to hardware failure
1219 EFI_WRITE_PROTECTED - Variable is read-only
1224 RuntimeServiceSetVariable (
1225 IN CHAR16
*VariableName
,
1226 IN EFI_GUID
*VendorGuid
,
1227 IN UINT32 Attributes
,
1232 VARIABLE_POINTER_TRACK Variable
;
1234 VARIABLE_HEADER
*NextVariable
;
1236 UINTN VarNameOffset
;
1237 UINTN VarDataOffset
;
1241 UINTN
*VolatileOffset
;
1242 UINTN
*NonVolatileOffset
;
1245 EFI_PHYSICAL_ADDRESS Point
;
1248 // Check input parameters
1250 if (VariableName
== NULL
|| VariableName
[0] == 0 || VendorGuid
== NULL
) {
1251 return EFI_INVALID_PARAMETER
;
1254 // Make sure if runtime bit is set, boot service bit is set also
1256 if ((Attributes
& (EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
)) == EFI_VARIABLE_RUNTIME_ACCESS
) {
1257 return EFI_INVALID_PARAMETER
;
1261 // The size of the VariableName, including the Unicode Null in bytes plus
1262 // the DataSize is limited to maximum size of MAX_HARDWARE_ERROR_VARIABLE_SIZE (32K)
1263 // bytes for HwErrRec, and MAX_VARIABLE_SIZE (1024) bytes for the others.
1265 if ((Attributes
& EFI_VARIABLE_HARDWARE_ERROR_RECORD
) == EFI_VARIABLE_HARDWARE_ERROR_RECORD
) {
1266 if ((DataSize
> MAX_HARDWARE_ERROR_VARIABLE_SIZE
) ||
1267 (sizeof (VARIABLE_HEADER
) + StrSize (VariableName
) + DataSize
> MAX_HARDWARE_ERROR_VARIABLE_SIZE
)) {
1268 return EFI_INVALID_PARAMETER
;
1272 // The size of the VariableName, including the Unicode Null in bytes plus
1273 // the DataSize is limited to maximum size of MAX_VARIABLE_SIZE (1024) bytes.
1275 if ((DataSize
> MAX_VARIABLE_SIZE
) ||
1276 (sizeof (VARIABLE_HEADER
) + StrSize (VariableName
) + DataSize
> MAX_VARIABLE_SIZE
)) {
1277 return EFI_INVALID_PARAMETER
;
1281 AcquireLockOnlyAtBootTime(&mVariableModuleGlobal
->VariableGlobal
.VariableServicesLock
);
1284 Instance
= mVariableModuleGlobal
->FvbInstance
;
1285 VolatileOffset
= &mVariableModuleGlobal
->VolatileLastVariableOffset
;
1288 // Consider reentrant in MCA/INIT/NMI. It needs be reupdated;
1290 if (1 < InterlockedIncrement (&mVariableModuleGlobal
->VariableGlobal
.ReentrantState
)) {
1291 Point
= mVariableModuleGlobal
->VariableGlobal
.NonVolatileVariableBase
;;
1293 // Parse non-volatile variable data and get last variable offset
1295 NextVariable
= GetStartPointer ((VARIABLE_STORE_HEADER
*) (UINTN
) Point
);
1296 while (IsValidVariableHeader (NextVariable
)) {
1297 NextVariable
= GetNextVariablePtr (NextVariable
);
1299 mVariableModuleGlobal
->NonVolatileLastVariableOffset
= (UINTN
) NextVariable
- (UINTN
) Point
;
1302 NonVolatileOffset
= &mVariableModuleGlobal
->NonVolatileLastVariableOffset
;
1306 // Check whether the input variable is already existed
1309 Status
= FindVariable (VariableName
, VendorGuid
, &Variable
, &mVariableModuleGlobal
->VariableGlobal
);
1310 if (Status
== EFI_SUCCESS
&& Variable
.CurrPtr
!= NULL
) {
1312 // Update/Delete existing variable
1314 Volatile
= Variable
.Volatile
;
1316 if (EfiAtRuntime ()) {
1318 // If EfiAtRuntime and the variable is Volatile and Runtime Access,
1319 // the volatile is ReadOnly, and SetVariable should be aborted and
1320 // return EFI_WRITE_PROTECTED.
1322 if (Variable
.Volatile
) {
1323 Status
= EFI_WRITE_PROTECTED
;
1327 // Only variable have NV attribute can be updated/deleted in Runtime
1329 if (!(Variable
.CurrPtr
->Attributes
& EFI_VARIABLE_NON_VOLATILE
)) {
1330 Status
= EFI_INVALID_PARAMETER
;
1335 // Setting a data variable with no access, or zero DataSize attributes
1336 // specified causes it to be deleted.
1338 if (DataSize
== 0 || (Attributes
& (EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
)) == 0) {
1339 State
= Variable
.CurrPtr
->State
;
1340 State
&= VAR_DELETED
;
1342 Status
= UpdateVariableStore (
1343 &mVariableModuleGlobal
->VariableGlobal
,
1347 (UINTN
) &Variable
.CurrPtr
->State
,
1351 if (!EFI_ERROR (Status
)) {
1352 UpdateVariableInfo (VariableName
, VendorGuid
, Volatile
, FALSE
, FALSE
, TRUE
, FALSE
);
1353 UpdateVariableCache (VariableName
, VendorGuid
, Attributes
, DataSize
, Data
);
1358 // If the variable is marked valid and the same data has been passed in
1359 // then return to the caller immediately.
1361 if (DataSizeOfVariable (Variable
.CurrPtr
) == DataSize
&&
1362 (CompareMem (Data
, GetVariableDataPtr (Variable
.CurrPtr
), DataSize
) == 0)) {
1364 UpdateVariableInfo (VariableName
, VendorGuid
, Volatile
, FALSE
, TRUE
, FALSE
, FALSE
);
1365 Status
= EFI_SUCCESS
;
1367 } else if ((Variable
.CurrPtr
->State
== VAR_ADDED
) ||
1368 (Variable
.CurrPtr
->State
== (VAR_ADDED
& VAR_IN_DELETED_TRANSITION
))) {
1371 // Mark the old variable as in delete transition
1373 State
= Variable
.CurrPtr
->State
;
1374 State
&= VAR_IN_DELETED_TRANSITION
;
1376 Status
= UpdateVariableStore (
1377 &mVariableModuleGlobal
->VariableGlobal
,
1381 (UINTN
) &Variable
.CurrPtr
->State
,
1385 if (EFI_ERROR (Status
)) {
1389 } else if (Status
== EFI_NOT_FOUND
) {
1391 // Create a new variable
1395 // Make sure we are trying to create a new variable.
1396 // Setting a data variable with no access, or zero DataSize attributes means to delete it.
1398 if (DataSize
== 0 || (Attributes
& (EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
)) == 0) {
1399 Status
= EFI_NOT_FOUND
;
1404 // Only variable have NV|RT attribute can be created in Runtime
1406 if (EfiAtRuntime () &&
1407 (!(Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
) || !(Attributes
& EFI_VARIABLE_NON_VOLATILE
))) {
1408 Status
= EFI_INVALID_PARAMETER
;
1413 // Status should be EFI_INVALID_PARAMETER here according to return status of FindVariable().
1415 ASSERT (Status
== EFI_INVALID_PARAMETER
);
1420 // Function part - create a new variable and copy the data.
1421 // Both update a variable and create a variable will come here.
1423 // Tricky part: Use scratch data area at the end of volatile variable store
1424 // as a temporary storage.
1426 NextVariable
= GetEndPointer ((VARIABLE_STORE_HEADER
*) ((UINTN
) mVariableModuleGlobal
->VariableGlobal
.VolatileVariableBase
));
1428 SetMem (NextVariable
, SCRATCH_SIZE
, 0xff);
1430 NextVariable
->StartId
= VARIABLE_DATA
;
1431 NextVariable
->Attributes
= Attributes
;
1433 // NextVariable->State = VAR_ADDED;
1435 NextVariable
->Reserved
= 0;
1436 VarNameOffset
= sizeof (VARIABLE_HEADER
);
1437 VarNameSize
= StrSize (VariableName
);
1439 (UINT8
*) ((UINTN
) NextVariable
+ VarNameOffset
),
1443 VarDataOffset
= VarNameOffset
+ VarNameSize
+ GET_PAD_SIZE (VarNameSize
);
1445 (UINT8
*) ((UINTN
) NextVariable
+ VarDataOffset
),
1449 CopyMem (&NextVariable
->VendorGuid
, VendorGuid
, sizeof (EFI_GUID
));
1451 // There will be pad bytes after Data, the NextVariable->NameSize and
1452 // NextVariable->DataSize should not include pad size so that variable
1453 // service can get actual size in GetVariable
1455 NextVariable
->NameSize
= (UINT32
)VarNameSize
;
1456 NextVariable
->DataSize
= (UINT32
)DataSize
;
1459 // The actual size of the variable that stores in storage should
1460 // include pad size.
1462 VarSize
= VarDataOffset
+ DataSize
+ GET_PAD_SIZE (DataSize
);
1463 if (Attributes
& EFI_VARIABLE_NON_VOLATILE
) {
1465 // Create a nonvolatile variable
1469 if ((UINT32
) (VarSize
+*NonVolatileOffset
) >
1470 ((VARIABLE_STORE_HEADER
*) ((UINTN
) (mVariableModuleGlobal
->VariableGlobal
.NonVolatileVariableBase
)))->Size
1472 if (EfiAtRuntime ()) {
1473 Status
= EFI_OUT_OF_RESOURCES
;
1477 // Perform garbage collection & reclaim operation
1479 Status
= Reclaim (mVariableModuleGlobal
->VariableGlobal
.NonVolatileVariableBase
, NonVolatileOffset
, FALSE
, Variable
.CurrPtr
);
1480 if (EFI_ERROR (Status
)) {
1484 // If still no enough space, return out of resources
1486 if ((UINT32
) (VarSize
+*NonVolatileOffset
) >
1487 ((VARIABLE_STORE_HEADER
*) ((UINTN
) (mVariableModuleGlobal
->VariableGlobal
.NonVolatileVariableBase
)))->Size
1489 Status
= EFI_OUT_OF_RESOURCES
;
1497 // 1. Write variable header
1498 // 2. Set variable state to header valid
1499 // 3. Write variable data
1500 // 4. Set variable state to valid
1505 Status
= UpdateVariableStore (
1506 &mVariableModuleGlobal
->VariableGlobal
,
1511 sizeof (VARIABLE_HEADER
),
1512 (UINT8
*) NextVariable
1515 if (EFI_ERROR (Status
)) {
1522 NextVariable
->State
= VAR_HEADER_VALID_ONLY
;
1523 Status
= UpdateVariableStore (
1524 &mVariableModuleGlobal
->VariableGlobal
,
1529 sizeof (VARIABLE_HEADER
),
1530 (UINT8
*) NextVariable
1533 if (EFI_ERROR (Status
)) {
1539 Status
= UpdateVariableStore (
1540 &mVariableModuleGlobal
->VariableGlobal
,
1544 *NonVolatileOffset
+ sizeof (VARIABLE_HEADER
),
1545 (UINT32
) VarSize
- sizeof (VARIABLE_HEADER
),
1546 (UINT8
*) NextVariable
+ sizeof (VARIABLE_HEADER
)
1549 if (EFI_ERROR (Status
)) {
1555 NextVariable
->State
= VAR_ADDED
;
1556 Status
= UpdateVariableStore (
1557 &mVariableModuleGlobal
->VariableGlobal
,
1562 sizeof (VARIABLE_HEADER
),
1563 (UINT8
*) NextVariable
1566 if (EFI_ERROR (Status
)) {
1570 *NonVolatileOffset
= HEADER_ALIGN (*NonVolatileOffset
+ VarSize
);
1574 // Create a volatile variable
1578 if ((UINT32
) (VarSize
+*VolatileOffset
) >
1579 ((VARIABLE_STORE_HEADER
*) ((UINTN
) (mVariableModuleGlobal
->VariableGlobal
.VolatileVariableBase
)))->Size
) {
1581 // Perform garbage collection & reclaim operation
1583 Status
= Reclaim (mVariableModuleGlobal
->VariableGlobal
.VolatileVariableBase
, VolatileOffset
, TRUE
, Variable
.CurrPtr
);
1584 if (EFI_ERROR (Status
)) {
1588 // If still no enough space, return out of resources
1590 if ((UINT32
) (VarSize
+*VolatileOffset
) >
1591 ((VARIABLE_STORE_HEADER
*) ((UINTN
) (mVariableModuleGlobal
->VariableGlobal
.VolatileVariableBase
)))->Size
1593 Status
= EFI_OUT_OF_RESOURCES
;
1600 NextVariable
->State
= VAR_ADDED
;
1601 Status
= UpdateVariableStore (
1602 &mVariableModuleGlobal
->VariableGlobal
,
1608 (UINT8
*) NextVariable
1611 if (EFI_ERROR (Status
)) {
1615 *VolatileOffset
= HEADER_ALIGN (*VolatileOffset
+ VarSize
);
1618 // Mark the old variable as deleted
1620 if (!Reclaimed
&& !EFI_ERROR (Status
) && Variable
.CurrPtr
!= NULL
) {
1621 State
= Variable
.CurrPtr
->State
;
1622 State
&= VAR_DELETED
;
1624 Status
= UpdateVariableStore (
1625 &mVariableModuleGlobal
->VariableGlobal
,
1629 (UINTN
) &Variable
.CurrPtr
->State
,
1634 if (!EFI_ERROR (Status
)) {
1635 UpdateVariableInfo (VariableName
, VendorGuid
, Volatile
, FALSE
, TRUE
, FALSE
, FALSE
);
1636 UpdateVariableCache (VariableName
, VendorGuid
, Attributes
, DataSize
, Data
);
1641 Status
= EFI_SUCCESS
;
1642 UpdateVariableInfo (VariableName
, VendorGuid
, Volatile
, FALSE
, TRUE
, FALSE
, FALSE
);
1643 UpdateVariableCache (VariableName
, VendorGuid
, Attributes
, DataSize
, Data
);
1646 InterlockedDecrement (&mVariableModuleGlobal
->VariableGlobal
.ReentrantState
);
1647 ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal
->VariableGlobal
.VariableServicesLock
);
1655 Routine Description:
1657 This code returns information about the EFI variables.
1661 Attributes Attributes bitmask to specify the type of variables
1662 on which to return information.
1663 MaximumVariableStorageSize Pointer to the maximum size of the storage space available
1664 for the EFI variables associated with the attributes specified.
1665 RemainingVariableStorageSize Pointer to the remaining size of the storage space available
1666 for EFI variables associated with the attributes specified.
1667 MaximumVariableSize Pointer to the maximum size of an individual EFI variables
1668 associated with the attributes specified.
1669 Global Pointer to VARIABLE_GLOBAL structure.
1670 Instance Instance of the Firmware Volume.
1675 EFI_INVALID_PARAMETER - An invalid combination of attribute bits was supplied.
1676 EFI_SUCCESS - Query successfully.
1677 EFI_UNSUPPORTED - The attribute is not supported on this platform.
1682 RuntimeServiceQueryVariableInfo (
1683 IN UINT32 Attributes
,
1684 OUT UINT64
*MaximumVariableStorageSize
,
1685 OUT UINT64
*RemainingVariableStorageSize
,
1686 OUT UINT64
*MaximumVariableSize
1689 VARIABLE_HEADER
*Variable
;
1690 VARIABLE_HEADER
*NextVariable
;
1691 UINT64 VariableSize
;
1692 VARIABLE_STORE_HEADER
*VariableStoreHeader
;
1694 if(MaximumVariableStorageSize
== NULL
|| RemainingVariableStorageSize
== NULL
|| MaximumVariableSize
== NULL
|| Attributes
== 0) {
1695 return EFI_INVALID_PARAMETER
;
1698 if((Attributes
& (EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_HARDWARE_ERROR_RECORD
)) == 0) {
1700 // Make sure the Attributes combination is supported by the platform.
1702 return EFI_UNSUPPORTED
;
1703 } else if ((Attributes
& (EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
)) == EFI_VARIABLE_RUNTIME_ACCESS
) {
1705 // Make sure if runtime bit is set, boot service bit is set also.
1707 return EFI_INVALID_PARAMETER
;
1708 } else if (EfiAtRuntime () && !(Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
)) {
1710 // Make sure RT Attribute is set if we are in Runtime phase.
1712 return EFI_INVALID_PARAMETER
;
1715 AcquireLockOnlyAtBootTime(&mVariableModuleGlobal
->VariableGlobal
.VariableServicesLock
);
1717 if((Attributes
& EFI_VARIABLE_NON_VOLATILE
) == 0) {
1719 // Query is Volatile related.
1721 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) ((UINTN
) mVariableModuleGlobal
->VariableGlobal
.VolatileVariableBase
);
1724 // Query is Non-Volatile related.
1726 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) ((UINTN
) mVariableModuleGlobal
->VariableGlobal
.NonVolatileVariableBase
);
1730 // Now let's fill *MaximumVariableStorageSize *RemainingVariableStorageSize
1731 // with the storage size (excluding the storage header size).
1733 *MaximumVariableStorageSize
= VariableStoreHeader
->Size
- sizeof (VARIABLE_STORE_HEADER
);
1734 *RemainingVariableStorageSize
= VariableStoreHeader
->Size
- sizeof (VARIABLE_STORE_HEADER
);
1737 // Let *MaximumVariableSize be MAX_VARIABLE_SIZE with the exception of the variable header size.
1739 *MaximumVariableSize
= MAX_VARIABLE_SIZE
- sizeof (VARIABLE_HEADER
);
1742 // Harware error record variable needs larger size.
1744 if ((Attributes
& EFI_VARIABLE_HARDWARE_ERROR_RECORD
) == EFI_VARIABLE_HARDWARE_ERROR_RECORD
) {
1745 *MaximumVariableSize
= MAX_HARDWARE_ERROR_VARIABLE_SIZE
- sizeof (VARIABLE_HEADER
);
1749 // Point to the starting address of the variables.
1751 Variable
= GetStartPointer (VariableStoreHeader
);
1754 // Now walk through the related variable store.
1756 while (IsValidVariableHeader (Variable
) && (Variable
< GetEndPointer (VariableStoreHeader
))) {
1757 NextVariable
= GetNextVariablePtr (Variable
);
1758 VariableSize
= (UINT64
) (UINTN
) NextVariable
- (UINT64
) (UINTN
) Variable
;
1760 if (EfiAtRuntime ()) {
1762 // we don't take the state of the variables in mind
1763 // when calculating RemainingVariableStorageSize,
1764 // since the space occupied by variables not marked with
1765 // VAR_ADDED is not allowed to be reclaimed in Runtime.
1767 *RemainingVariableStorageSize
-= VariableSize
;
1770 // Only care about Variables with State VAR_ADDED,because
1771 // the space not marked as VAR_ADDED is reclaimable now.
1773 if (Variable
->State
== VAR_ADDED
) {
1774 *RemainingVariableStorageSize
-= VariableSize
;
1779 // Go to the next one
1781 Variable
= NextVariable
;
1784 if (*RemainingVariableStorageSize
< sizeof (VARIABLE_HEADER
)) {
1785 *MaximumVariableSize
= 0;
1786 } else if ((*RemainingVariableStorageSize
- sizeof (VARIABLE_HEADER
)) < *MaximumVariableSize
) {
1787 *MaximumVariableSize
= *RemainingVariableStorageSize
- sizeof (VARIABLE_HEADER
);
1790 ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal
->VariableGlobal
.VariableServicesLock
);
1804 VarSize
= ((VARIABLE_STORE_HEADER
*) ((UINTN
) mVariableModuleGlobal
->VariableGlobal
.NonVolatileVariableBase
))->Size
;
1805 Status
= EFI_SUCCESS
;
1808 // Check if the free area is blow a threshold
1810 if ((VarSize
- mVariableModuleGlobal
->NonVolatileLastVariableOffset
) < VARIABLE_RECLAIM_THRESHOLD
) {
1812 mVariableModuleGlobal
->VariableGlobal
.NonVolatileVariableBase
,
1813 &mVariableModuleGlobal
->NonVolatileLastVariableOffset
,
1817 ASSERT_EFI_ERROR (Status
);
1822 VariableCommonInitialize (
1823 IN EFI_HANDLE ImageHandle
,
1824 IN EFI_SYSTEM_TABLE
*SystemTable
1828 Routine Description:
1829 This function does common initialization for variable services
1833 ImageHandle - The firmware allocated handle for the EFI image.
1834 SystemTable - A pointer to the EFI System Table.
1840 EFI_NOT_FOUND - Variable store area not found.
1841 EFI_UNSUPPORTED - Currently only one non-volatile variable store is supported.
1842 EFI_SUCCESS - Variable services successfully initialized.
1847 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
1849 VARIABLE_STORE_HEADER
*VolatileVariableStore
;
1850 VARIABLE_STORE_HEADER
*VariableStoreHeader
;
1851 VARIABLE_HEADER
*NextVariable
;
1853 EFI_PHYSICAL_ADDRESS FvVolHdr
;
1854 UINT64 TempVariableStoreHeader
;
1855 EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor
;
1860 UINT64 VariableStoreBase
;
1861 UINT64 VariableStoreLength
;
1862 EFI_EVENT ReadyToBootEvent
;
1864 Status
= EFI_SUCCESS
;
1866 // Allocate runtime memory for variable driver global structure.
1868 mVariableModuleGlobal
= AllocateRuntimePool (sizeof (VARIABLE_MODULE_GLOBAL
));
1869 if (mVariableModuleGlobal
== NULL
) {
1870 return EFI_OUT_OF_RESOURCES
;
1873 EfiInitializeLock(&mVariableModuleGlobal
->VariableGlobal
.VariableServicesLock
, TPL_NOTIFY
);
1874 mVariableModuleGlobal
->VariableGlobal
.ReentrantState
= 0;
1877 // Allocate memory for volatile variable store
1879 VolatileVariableStore
= AllocateRuntimePool (VARIABLE_STORE_SIZE
+ SCRATCH_SIZE
);
1880 if (VolatileVariableStore
== NULL
) {
1881 FreePool (mVariableModuleGlobal
);
1882 return EFI_OUT_OF_RESOURCES
;
1885 SetMem (VolatileVariableStore
, VARIABLE_STORE_SIZE
+ SCRATCH_SIZE
, 0xff);
1888 // Variable Specific Data
1890 mVariableModuleGlobal
->VariableGlobal
.VolatileVariableBase
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) VolatileVariableStore
;
1891 mVariableModuleGlobal
->VolatileLastVariableOffset
= (UINTN
) GetStartPointer (VolatileVariableStore
) - (UINTN
) VolatileVariableStore
;
1893 VolatileVariableStore
->Signature
= VARIABLE_STORE_SIGNATURE
;
1894 VolatileVariableStore
->Size
= VARIABLE_STORE_SIZE
;
1895 VolatileVariableStore
->Format
= VARIABLE_STORE_FORMATTED
;
1896 VolatileVariableStore
->State
= VARIABLE_STORE_HEALTHY
;
1897 VolatileVariableStore
->Reserved
= 0;
1898 VolatileVariableStore
->Reserved1
= 0;
1901 // Get non volatile varaible store
1904 TempVariableStoreHeader
= (UINT64
) PcdGet32 (PcdFlashNvStorageVariableBase
);
1905 VariableStoreBase
= TempVariableStoreHeader
+ \
1906 (((EFI_FIRMWARE_VOLUME_HEADER
*) (UINTN
) (TempVariableStoreHeader
)) -> HeaderLength
);
1907 VariableStoreLength
= (UINT64
) PcdGet32 (PcdFlashNvStorageVariableSize
) - \
1908 (((EFI_FIRMWARE_VOLUME_HEADER
*) (UINTN
) (TempVariableStoreHeader
)) -> HeaderLength
);
1910 // Mark the variable storage region of the FLASH as RUNTIME
1912 BaseAddress
= VariableStoreBase
& (~EFI_PAGE_MASK
);
1913 Length
= VariableStoreLength
+ (VariableStoreBase
- BaseAddress
);
1914 Length
= (Length
+ EFI_PAGE_SIZE
- 1) & (~EFI_PAGE_MASK
);
1916 Status
= gDS
->GetMemorySpaceDescriptor (BaseAddress
, &GcdDescriptor
);
1917 if (EFI_ERROR (Status
)) {
1921 Status
= gDS
->SetMemorySpaceAttributes (
1924 GcdDescriptor
.Attributes
| EFI_MEMORY_RUNTIME
1926 if (EFI_ERROR (Status
)) {
1930 // Get address of non volatile variable store base
1932 mVariableModuleGlobal
->VariableGlobal
.NonVolatileVariableBase
= VariableStoreBase
;
1938 // Find the Correct Instance of the FV Block Service.
1941 CurrPtr
= (CHAR8
*) ((UINTN
) mVariableModuleGlobal
->VariableGlobal
.NonVolatileVariableBase
);
1942 while (EfiFvbGetPhysicalAddress (Instance
, &FvVolHdr
) == EFI_SUCCESS
) {
1943 FwVolHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) ((UINTN
) FvVolHdr
);
1944 if (CurrPtr
>= (CHAR8
*) FwVolHeader
&& CurrPtr
< (((CHAR8
*) FwVolHeader
) + FwVolHeader
->FvLength
)) {
1945 mVariableModuleGlobal
->FvbInstance
= Instance
;
1952 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) CurrPtr
;
1953 if (GetVariableStoreStatus (VariableStoreHeader
) == EfiValid
) {
1954 if (~VariableStoreHeader
->Size
== 0) {
1955 Status
= UpdateVariableStore (
1956 &mVariableModuleGlobal
->VariableGlobal
,
1959 mVariableModuleGlobal
->FvbInstance
,
1960 (UINTN
) &VariableStoreHeader
->Size
,
1962 (UINT8
*) &VariableStoreLength
1965 // As Variables are stored in NV storage, which are slow devices,such as flash.
1966 // Variable operation may skip checking variable program result to improve performance,
1967 // We can assume Variable program is OK through some check point.
1968 // Variable Store Size Setting should be the first Variable write operation,
1969 // We can assume all Read/Write is OK if we can set Variable store size successfully.
1970 // If write fail, we will assert here
1972 ASSERT(VariableStoreHeader
->Size
== VariableStoreLength
);
1974 if (EFI_ERROR (Status
)) {
1979 mVariableModuleGlobal
->VariableGlobal
.NonVolatileVariableBase
= (EFI_PHYSICAL_ADDRESS
) ((UINTN
) CurrPtr
);
1981 // Parse non-volatile variable data and get last variable offset
1983 NextVariable
= GetStartPointer ((VARIABLE_STORE_HEADER
*) CurrPtr
);
1984 Status
= EFI_SUCCESS
;
1986 while (IsValidVariableHeader (NextVariable
)) {
1987 NextVariable
= GetNextVariablePtr (NextVariable
);
1990 mVariableModuleGlobal
->NonVolatileLastVariableOffset
= (UINTN
) NextVariable
- (UINTN
) CurrPtr
;
1993 // Check if the free area is really free.
1995 for (Index
= mVariableModuleGlobal
->NonVolatileLastVariableOffset
; Index
< VariableStoreHeader
->Size
; Index
++) {
1996 Data
= ((UINT8
*) (UINTN
) mVariableModuleGlobal
->VariableGlobal
.NonVolatileVariableBase
)[Index
];
1999 // There must be something wrong in variable store, do reclaim operation.
2002 mVariableModuleGlobal
->VariableGlobal
.NonVolatileVariableBase
,
2003 &mVariableModuleGlobal
->NonVolatileLastVariableOffset
,
2008 if (EFI_ERROR (Status
)) {
2017 // Register the event handling function to reclaim variable for OS usage.
2019 Status
= EfiCreateEventReadyToBootEx (
2028 if (EFI_ERROR (Status
)) {
2029 FreePool (mVariableModuleGlobal
);
2030 FreePool (VolatileVariableStore
);
2038 VariableClassAddressChangeEvent (
2045 (VOID
**) &mVariableModuleGlobal
->VariableGlobal
.NonVolatileVariableBase
2049 (VOID
**) &mVariableModuleGlobal
->VariableGlobal
.VolatileVariableBase
2051 EfiConvertPointer (0x0, (VOID
**) &mVariableModuleGlobal
);
2056 Variable Driver main entry point. The Variable driver places the 4 EFI
2057 runtime services in the EFI System Table and installs arch protocols
2058 for variable read and write services being availible.
2060 @param[in] ImageHandle The firmware allocated handle for the EFI image.
2061 @param[in] SystemTable A pointer to the EFI System Table.
2063 @retval EFI_SUCCESS The entry point is executed successfully.
2064 @retval other Some error occurs when executing this entry point.
2069 VariableServiceInitialize (
2070 IN EFI_HANDLE ImageHandle
,
2071 IN EFI_SYSTEM_TABLE
*SystemTable
2076 Status
= VariableCommonInitialize (ImageHandle
, SystemTable
);
2077 ASSERT_EFI_ERROR (Status
);
2079 SystemTable
->RuntimeServices
->GetVariable
= RuntimeServiceGetVariable
;
2080 SystemTable
->RuntimeServices
->GetNextVariableName
= RuntimeServiceGetNextVariableName
;
2081 SystemTable
->RuntimeServices
->SetVariable
= RuntimeServiceSetVariable
;
2082 SystemTable
->RuntimeServices
->QueryVariableInfo
= RuntimeServiceQueryVariableInfo
;
2085 // Now install the Variable Runtime Architectural Protocol on a new handle
2087 Status
= gBS
->InstallMultipleProtocolInterfaces (
2089 &gEfiVariableArchProtocolGuid
, NULL
,
2090 &gEfiVariableWriteArchProtocolGuid
, NULL
,
2093 ASSERT_EFI_ERROR (Status
);
2095 Status
= gBS
->CreateEvent (
2096 EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE
,
2098 VariableClassAddressChangeEvent
,
2100 &mVirtualAddressChangeEvent
2102 ASSERT_EFI_ERROR (Status
);