2 EFI Runtime Variable services.
4 Copyright (c) 2006 - 2007, 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.
19 VARIABLE_MODULE_GLOBAL mRuntimeData
;
20 VARIABLE_MODULE_GLOBAL
*mVariableModuleGlobal
= &mRuntimeData
;
21 EFI_EVENT mVirtualAddressChangeEvent
= NULL
;
22 EFI_HANDLE mHandle
= NULL
;
26 // This is a temperary function which will be removed
27 // when EfiAcquireLock in UefiLib can handle the
28 // the call in UEFI Runtimer driver in RT phase.
31 AcquireLockOnlyAtBootTime (
35 if (!EfiAtRuntime ()) {
36 EfiAcquireLock (Lock
);
41 // This is a temperary function which will be removed
42 // when EfiAcquireLock in UefiLib can handle the
43 // the call in UEFI Runtimer driver in RT phase.
46 ReleaseLockOnlyAtBootTime (
50 if (!EfiAtRuntime ()) {
51 EfiReleaseLock (Lock
);
56 GLOBAL_REMOVE_IF_UNREFERENCED VARIABLE_INFO_ENTRY
*gVariableInfo
= NULL
;
60 Routine used to track statistical information about variable usage.
61 The data is stored in the EFI system table so it can be accessed later.
62 VariableInfo.efi can dump out the table. Only Boot Services variable
63 accesses are tracked by this code. The PcdVariableCollectStatistics
64 build flag controls if this feature is enabled.
66 A read that hits in the cache will have Read and Cache true for
67 the transaction. Data is allocated by this routine, but never
70 @param[in] VariableName Name of the Variable to track
71 @param[in] VendorGuid Guid of the Variable to track
72 @param[in] Volatile TRUE if volatile FALSE if non-volatile
73 @param[in] Read TRUE if GetVariable() was called
74 @param[in] Write TRUE if SetVariable() was called
75 @param[in] Delete TRUE if deleted via SetVariable()
76 @param[in] Cache TRUE for a cache hit.
81 IN CHAR16
*VariableName
,
82 IN EFI_GUID
*VendorGuid
,
90 VARIABLE_INFO_ENTRY
*Entry
;
92 if (FeaturePcdGet (PcdVariableCollectStatistics
)) {
94 if (EfiAtRuntime ()) {
95 // Don't collect statistics at runtime
99 if (gVariableInfo
== NULL
) {
101 // on the first call allocate a entry and place a pointer to it in
102 // the EFI System Table
104 gVariableInfo
= AllocateZeroPool (sizeof (VARIABLE_INFO_ENTRY
));
105 ASSERT (gVariableInfo
!= NULL
);
107 CopyGuid (&gVariableInfo
->VendorGuid
, VendorGuid
);
108 gVariableInfo
->Name
= AllocatePool (StrLen (VariableName
));
109 StrCpy (gVariableInfo
->Name
, VariableName
);
110 gVariableInfo
->Volatile
= Volatile
;
112 gBS
->InstallConfigurationTable (&gEfiVariableInfoGuid
, gVariableInfo
);
116 for (Entry
= gVariableInfo
; Entry
!= NULL
; Entry
= Entry
->Next
) {
117 if (CompareGuid (VendorGuid
, &Entry
->VendorGuid
)) {
118 if (StrCmp (VariableName
, Entry
->Name
) == 0) {
126 Entry
->DeleteCount
++;
136 if (Entry
->Next
== NULL
) {
138 // If the entry is not in the table add it.
139 // Next iteration of the loop will fill in the data
141 Entry
->Next
= AllocateZeroPool (sizeof (VARIABLE_INFO_ENTRY
));
142 ASSERT (Entry
->Next
!= NULL
);
144 CopyGuid (&Entry
->Next
->VendorGuid
, VendorGuid
);
145 Entry
->Next
->Name
= AllocatePool (StrLen (VariableName
));
146 StrCpy (Entry
->Next
->Name
, VariableName
);
147 Entry
->Next
->Volatile
= Volatile
;
157 IsValidVariableHeader (
158 IN VARIABLE_HEADER
*Variable
164 This code checks if variable header is valid or not.
167 Variable Pointer to the Variable Header.
170 TRUE Variable header is valid.
171 FALSE Variable header is not valid.
175 if (Variable
== NULL
|| Variable
->StartId
!= VARIABLE_DATA
) {
184 UpdateVariableStore (
185 IN VARIABLE_GLOBAL
*Global
,
187 IN BOOLEAN SetByIndex
,
189 IN UINTN DataPtrIndex
,
197 This function writes data to the FWH at the correct LBA even if the LBAs
202 Global - Pointer to VARAIBLE_GLOBAL structure
203 Volatile - If the Variable is Volatile or Non-Volatile
204 SetByIndex - TRUE: Target pointer is given as index
205 FALSE: Target pointer is absolute
206 Instance - Instance of FV Block services
207 DataPtrIndex - Pointer to the Data from the end of VARIABLE_STORE_HEADER
209 DataSize - Size of data to be written.
210 Buffer - Pointer to the buffer from which data is written
214 EFI_INVALID_PARAMETER - Parameters not valid
215 EFI_SUCCESS - Variable store successfully updated
219 EFI_FV_BLOCK_MAP_ENTRY
*PtrBlockMapEntry
;
227 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
228 VARIABLE_STORE_HEADER
*VolatileBase
;
229 EFI_PHYSICAL_ADDRESS FvVolHdr
;
230 EFI_PHYSICAL_ADDRESS DataPtr
;
234 DataPtr
= DataPtrIndex
;
237 // Check if the Data is Volatile
240 EfiFvbGetPhysicalAddress (Instance
, &FvVolHdr
);
241 FwVolHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) ((UINTN
) FvVolHdr
);
243 // Data Pointer should point to the actual Address where data is to be
247 DataPtr
+= mVariableModuleGlobal
->VariableGlobal
.NonVolatileVariableBase
;
250 if ((DataPtr
+ DataSize
) >= ((EFI_PHYSICAL_ADDRESS
) (UINTN
) ((UINT8
*) FwVolHeader
+ FwVolHeader
->FvLength
))) {
251 return EFI_INVALID_PARAMETER
;
255 // Data Pointer should point to the actual Address where data is to be
258 VolatileBase
= (VARIABLE_STORE_HEADER
*) ((UINTN
) mVariableModuleGlobal
->VariableGlobal
.VolatileVariableBase
);
260 DataPtr
+= mVariableModuleGlobal
->VariableGlobal
.VolatileVariableBase
;
263 if ((DataPtr
+ DataSize
) >= ((UINTN
) ((UINT8
*) VolatileBase
+ VolatileBase
->Size
))) {
264 return EFI_INVALID_PARAMETER
;
268 // If Volatile Variable just do a simple mem copy.
270 CopyMem ((UINT8
*)(UINTN
)DataPtr
, Buffer
, DataSize
);
275 // If we are here we are dealing with Non-Volatile Variables
277 LinearOffset
= (UINTN
) FwVolHeader
;
278 CurrWritePtr
= (UINTN
) DataPtr
;
279 CurrWriteSize
= DataSize
;
283 if (CurrWritePtr
< LinearOffset
) {
284 return EFI_INVALID_PARAMETER
;
287 for (PtrBlockMapEntry
= FwVolHeader
->BlockMap
; PtrBlockMapEntry
->NumBlocks
!= 0; PtrBlockMapEntry
++) {
288 for (BlockIndex2
= 0; BlockIndex2
< PtrBlockMapEntry
->NumBlocks
; BlockIndex2
++) {
290 // Check to see if the Variable Writes are spanning through multiple
293 if ((CurrWritePtr
>= LinearOffset
) && (CurrWritePtr
< LinearOffset
+ PtrBlockMapEntry
->Length
)) {
294 if ((CurrWritePtr
+ CurrWriteSize
) <= (LinearOffset
+ PtrBlockMapEntry
->Length
)) {
295 Status
= EfiFvbWriteBlock (
298 (UINTN
) (CurrWritePtr
- LinearOffset
),
304 Size
= (UINT32
) (LinearOffset
+ PtrBlockMapEntry
->Length
- CurrWritePtr
);
305 Status
= EfiFvbWriteBlock (
308 (UINTN
) (CurrWritePtr
- LinearOffset
),
312 if (EFI_ERROR (Status
)) {
316 CurrWritePtr
= LinearOffset
+ PtrBlockMapEntry
->Length
;
317 CurrBuffer
= CurrBuffer
+ Size
;
318 CurrWriteSize
= CurrWriteSize
- Size
;
322 LinearOffset
+= PtrBlockMapEntry
->Length
;
331 VARIABLE_STORE_STATUS
332 GetVariableStoreStatus (
333 IN VARIABLE_STORE_HEADER
*VarStoreHeader
339 This code gets the current status of Variable Store.
343 VarStoreHeader Pointer to the Variable Store Header.
347 EfiRaw Variable store status is raw
348 EfiValid Variable store status is valid
349 EfiInvalid Variable store status is invalid
353 if (VarStoreHeader
->Signature
== VARIABLE_STORE_SIGNATURE
&&
354 VarStoreHeader
->Format
== VARIABLE_STORE_FORMATTED
&&
355 VarStoreHeader
->State
== VARIABLE_STORE_HEALTHY
359 } else if (VarStoreHeader
->Signature
== 0xffffffff &&
360 VarStoreHeader
->Size
== 0xffffffff &&
361 VarStoreHeader
->Format
== 0xff &&
362 VarStoreHeader
->State
== 0xff
374 IN VARIABLE_HEADER
*Variable
378 // Check whether the header is valid fully;
379 // Tricky: The unprogramed data in FLASH equals 0xff.
381 if (Variable
->DataSize
== (UINT32
) -1 ||
382 Variable
->Attributes
== (UINT32
) -1 ||
383 Variable
->NameSize
== (UINT32
) -1) {
386 return Variable
->NameSize
;
391 IN VARIABLE_HEADER
*Variable
395 // Check whether the header is valid fully;
396 // Tricky: The unprogramed data in FLASH equals 0xff.
398 if (Variable
->DataSize
== (UINT32
) -1 ||
399 Variable
->Attributes
== (UINT32
) -1 ||
400 Variable
->NameSize
== (UINT32
) -1) {
403 return Variable
->DataSize
;
407 AttributesOfVariable (
408 IN VARIABLE_HEADER
*Variable
413 // Check whether the header is valid fully;
414 // Tricky: The unprogramed data in FLASH equals 0xff.
416 if (Variable
->DataSize
== (UINT32
) -1 ||
417 Variable
->Attributes
== (UINT32
) -1 ||
418 Variable
->NameSize
== (UINT32
) -1) {
421 return Variable
->Attributes
;
427 IN VARIABLE_HEADER
*Variable
433 This code gets the pointer to the variable data.
437 Variable Pointer to the Variable Header.
441 UINT8* Pointer to Variable Data
446 // Be careful about pad size for alignment
448 return (UINT8
*) ((UINTN
) GET_VARIABLE_NAME_PTR (Variable
) + NameSizeOfVariable (Variable
) + GET_PAD_SIZE (NameSizeOfVariable (Variable
)));
454 IN VARIABLE_HEADER
*Variable
460 This code gets the pointer to the next variable header.
464 Variable Pointer to the Variable Header.
468 VARIABLE_HEADER* Pointer to next variable header.
472 if (!IsValidVariableHeader (Variable
)) {
476 // Be careful about pad size for alignment
478 return (VARIABLE_HEADER
*) ((UINTN
) GetVariableDataPtr (Variable
) + DataSizeOfVariable (Variable
) + GET_PAD_SIZE (DataSizeOfVariable (Variable
)));
484 IN VARIABLE_STORE_HEADER
*VarStoreHeader
490 This code gets the pointer to the last variable memory pointer byte
494 VarStoreHeader Pointer to the Variable Store Header.
498 VARIABLE_HEADER* Pointer to last unavailable Variable Header
503 // The end of variable store
505 return (VARIABLE_HEADER
*) ((UINTN
) VarStoreHeader
+ VarStoreHeader
->Size
);
511 IN EFI_PHYSICAL_ADDRESS VariableBase
,
512 OUT UINTN
*LastVariableOffset
,
513 IN BOOLEAN IsVolatile
519 Variable store garbage collection and reclaim operation
523 VariableBase Base address of variable store
524 LastVariableOffset Offset of last variable
525 IsVolatile The variable store is volatile or not,
526 if it is non-volatile, need FTW
534 VARIABLE_HEADER
*Variable
;
535 VARIABLE_HEADER
*NextVariable
;
536 VARIABLE_STORE_HEADER
*VariableStoreHeader
;
538 UINTN ValidBufferSize
;
543 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) ((UINTN
) VariableBase
);
546 // Start Pointers for the variable.
548 Variable
= (VARIABLE_HEADER
*) (VariableStoreHeader
+ 1);
550 ValidBufferSize
= sizeof (VARIABLE_STORE_HEADER
);
552 while (IsValidVariableHeader (Variable
)) {
553 NextVariable
= GetNextVariablePtr (Variable
);
554 if (Variable
->State
== VAR_ADDED
) {
555 VariableSize
= (UINTN
) NextVariable
- (UINTN
) Variable
;
556 ValidBufferSize
+= VariableSize
;
559 Variable
= NextVariable
;
562 ValidBuffer
= AllocatePool (ValidBufferSize
);
563 if (ValidBuffer
== NULL
) {
564 return EFI_OUT_OF_RESOURCES
;
567 SetMem (ValidBuffer
, ValidBufferSize
, 0xff);
569 CurrPtr
= ValidBuffer
;
572 // Copy variable store header
574 CopyMem (CurrPtr
, VariableStoreHeader
, sizeof (VARIABLE_STORE_HEADER
));
575 CurrPtr
+= sizeof (VARIABLE_STORE_HEADER
);
578 // Start Pointers for the variable.
580 Variable
= (VARIABLE_HEADER
*) (VariableStoreHeader
+ 1);
582 while (IsValidVariableHeader (Variable
)) {
583 NextVariable
= GetNextVariablePtr (Variable
);
584 if (Variable
->State
== VAR_ADDED
) {
585 VariableSize
= (UINTN
) NextVariable
- (UINTN
) Variable
;
586 CopyMem (CurrPtr
, (UINT8
*) Variable
, VariableSize
);
587 CurrPtr
+= VariableSize
;
590 Variable
= NextVariable
;
595 // If volatile variable store, just copy valid buffer
597 SetMem ((UINT8
*) (UINTN
) VariableBase
, VariableStoreHeader
->Size
, 0xff);
598 CopyMem ((UINT8
*) (UINTN
) VariableBase
, ValidBuffer
, ValidBufferSize
);
599 *LastVariableOffset
= ValidBufferSize
;
600 Status
= EFI_SUCCESS
;
603 // If non-volatile variable store, perform FTW here.
605 Status
= FtwVariableSpace (
610 if (!EFI_ERROR (Status
)) {
611 *LastVariableOffset
= ValidBufferSize
;
615 FreePool (ValidBuffer
);
617 if (EFI_ERROR (Status
)) {
618 *LastVariableOffset
= 0;
626 // The current Hii implementation accesses this variable a larg # of times on every boot.
627 // Other common variables are only accessed a single time. This is why this cache algorithm
628 // only targets a single variable. Probably to get an performance improvement out of
629 // a Cache you would need a cache that improves the search performance for a variable.
631 VARIABLE_CACHE_ENTRY mVariableCache
[] = {
633 &gEfiGlobalVariableGuid
,
643 Update the Cache with Variable information. These are the same
644 arguments as the EFI Variable services.
646 @param[in] VariableName Name of variable
647 @param[in] VendorGuid Guid of variable
648 @param[in] Attribute Attribue of the variable
649 @param[in] DataSize Size of data. 0 means delete
650 @param[in] Data Variable data
654 UpdateVariableCache (
655 IN CHAR16
*VariableName
,
656 IN EFI_GUID
*VendorGuid
,
657 IN UINT32 Attributes
,
662 VARIABLE_CACHE_ENTRY
*Entry
;
665 if (EfiAtRuntime ()) {
666 // Don't use the cache at runtime
670 for (Index
= 0, Entry
= mVariableCache
; Index
< sizeof (mVariableCache
)/sizeof (VARIABLE_CACHE_ENTRY
); Index
++, Entry
++) {
671 if (CompareGuid (VendorGuid
, Entry
->Guid
)) {
672 if (StrCmp (VariableName
, Entry
->Name
) == 0) {
673 Entry
->Attributes
= Attributes
;
676 if (Entry
->DataSize
!= 0) {
677 FreePool (Entry
->Data
);
679 Entry
->DataSize
= DataSize
;
680 } else if (DataSize
== Entry
->DataSize
) {
681 CopyMem (Entry
->Data
, Data
, DataSize
);
683 Entry
->Data
= AllocatePool (DataSize
);
684 Entry
->DataSize
= DataSize
;
685 CopyMem (Entry
->Data
, Data
, DataSize
);
694 Search the cache to see if the variable is in the cache.
696 @param[in] VariableName Name of variable
697 @param[in] VendorGuid Guid of variable
698 @param[in] Attribute Attribue returned
699 @param[in] DataSize Size of data returned
700 @param[in] Data Variable data returned
702 @retval EFI_SUCCESS VariableGuid & VariableName data was returned.
703 @retval other Not found.
707 FindVariableInCache (
708 IN CHAR16
*VariableName
,
709 IN EFI_GUID
*VendorGuid
,
710 OUT UINT32
*Attributes OPTIONAL
,
711 IN OUT UINTN
*DataSize
,
715 VARIABLE_CACHE_ENTRY
*Entry
;
718 if (EfiAtRuntime ()) {
719 // Don't use the cache at runtime
720 return EFI_NOT_FOUND
;
723 for (Index
= 0, Entry
= mVariableCache
; Index
< sizeof (mVariableCache
)/sizeof (VARIABLE_CACHE_ENTRY
); Index
++, Entry
++) {
724 if (CompareGuid (VendorGuid
, Entry
->Guid
)) {
725 if (StrCmp (VariableName
, Entry
->Name
) == 0) {
726 if (Entry
->DataSize
== 0) {
727 // Variable was deleted so return not found
728 return EFI_NOT_FOUND
;
729 } else if (Entry
->DataSize
> *DataSize
) {
730 // If the buffer is too small return correct size
731 *DataSize
= Entry
->DataSize
;
732 return EFI_BUFFER_TOO_SMALL
;
734 *DataSize
= Entry
->DataSize
;
736 CopyMem (Data
, Entry
->Data
, Entry
->DataSize
);
737 if (Attributes
!= NULL
) {
738 *Attributes
= Entry
->Attributes
;
746 return EFI_NOT_FOUND
;
752 IN CHAR16
*VariableName
,
753 IN EFI_GUID
*VendorGuid
,
754 OUT VARIABLE_POINTER_TRACK
*PtrTrack
,
755 IN VARIABLE_GLOBAL
*Global
761 This code finds variable in storage blocks (Volatile or Non-Volatile)
765 VariableName Name of the variable to be found
766 VendorGuid Vendor GUID to be found.
767 PtrTrack Variable Track Pointer structure that contains
768 Variable Information.
769 Contains the pointer of Variable header.
770 Global VARIABLE_GLOBAL pointer
778 VARIABLE_HEADER
*Variable
[2];
779 VARIABLE_STORE_HEADER
*VariableStoreHeader
[2];
783 // 0: Volatile, 1: Non-Volatile
784 // The index and attributes mapping must be kept in this order as RuntimeServiceGetNextVariableName
785 // make use of this mapping to implement search algorithme.
787 VariableStoreHeader
[0] = (VARIABLE_STORE_HEADER
*) ((UINTN
) mVariableModuleGlobal
->VariableGlobal
.VolatileVariableBase
);
788 VariableStoreHeader
[1] = (VARIABLE_STORE_HEADER
*) ((UINTN
) mVariableModuleGlobal
->VariableGlobal
.NonVolatileVariableBase
);
791 // Start Pointers for the variable.
792 // Actual Data Pointer where data can be written.
794 Variable
[0] = (VARIABLE_HEADER
*) (VariableStoreHeader
[0] + 1);
795 Variable
[1] = (VARIABLE_HEADER
*) (VariableStoreHeader
[1] + 1);
797 if (VariableName
[0] != 0 && VendorGuid
== NULL
) {
798 return EFI_INVALID_PARAMETER
;
801 // Find the variable by walk through volatile and then non-volatile variable store
803 for (Index
= 0; Index
< 2; Index
++) {
804 PtrTrack
->StartPtr
= (VARIABLE_HEADER
*) (VariableStoreHeader
[Index
] + 1);
805 PtrTrack
->EndPtr
= GetEndPointer (VariableStoreHeader
[Index
]);
807 while (IsValidVariableHeader (Variable
[Index
]) && (Variable
[Index
] <= GetEndPointer (VariableStoreHeader
[Index
]))) {
808 if (Variable
[Index
]->State
== VAR_ADDED
) {
809 if (!EfiAtRuntime () || (Variable
[Index
]->Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
)) {
810 if (VariableName
[0] == 0) {
811 PtrTrack
->CurrPtr
= Variable
[Index
];
812 PtrTrack
->Volatile
= (BOOLEAN
)(Index
== 0);
815 if (CompareGuid (VendorGuid
, &Variable
[Index
]->VendorGuid
)) {
816 ASSERT (NameSizeOfVariable (Variable
[Index
]) != 0);
817 if (!CompareMem (VariableName
, GET_VARIABLE_NAME_PTR (Variable
[Index
]), NameSizeOfVariable (Variable
[Index
]))) {
818 PtrTrack
->CurrPtr
= Variable
[Index
];
819 PtrTrack
->Volatile
= (BOOLEAN
)(Index
== 0);
827 Variable
[Index
] = GetNextVariablePtr (Variable
[Index
]);
830 PtrTrack
->CurrPtr
= NULL
;
831 return EFI_NOT_FOUND
;
840 This code finds variable in storage blocks (Volatile or Non-Volatile)
844 VariableName Name of Variable to be found
845 VendorGuid Variable vendor GUID
846 Attributes OPTIONAL Attribute value of the variable found
847 DataSize Size of Data found. If size is less than the
848 data, this value contains the required size.
850 Global Pointer to VARIABLE_GLOBAL structure
851 Instance Instance of the Firmware Volume.
855 EFI_INVALID_PARAMETER - Invalid parameter
856 EFI_SUCCESS - Find the specified variable
857 EFI_NOT_FOUND - Not found
858 EFI_BUFFER_TO_SMALL - DataSize is too small for the result
864 RuntimeServiceGetVariable (
865 IN CHAR16
*VariableName
,
866 IN EFI_GUID
*VendorGuid
,
867 OUT UINT32
*Attributes OPTIONAL
,
868 IN OUT UINTN
*DataSize
,
873 VARIABLE_POINTER_TRACK Variable
;
876 if (VariableName
== NULL
|| VendorGuid
== NULL
|| DataSize
== NULL
) {
877 return EFI_INVALID_PARAMETER
;
880 AcquireLockOnlyAtBootTime(&mVariableModuleGlobal
->VariableGlobal
.VariableServicesLock
);
883 // Find existing variable
885 Status
= FindVariableInCache (VariableName
, VendorGuid
, Attributes
, DataSize
, Data
);
886 if ((Status
== EFI_BUFFER_TOO_SMALL
) || (Status
== EFI_SUCCESS
)){
888 UpdateVariableInfo (VariableName
, VendorGuid
, FALSE
, TRUE
, FALSE
, FALSE
, TRUE
);
892 Status
= FindVariable (VariableName
, VendorGuid
, &Variable
, &mVariableModuleGlobal
->VariableGlobal
);
893 if (Variable
.CurrPtr
== NULL
|| EFI_ERROR (Status
)) {
900 VarDataSize
= DataSizeOfVariable (Variable
.CurrPtr
);
901 ASSERT (VarDataSize
!= 0);
903 if (*DataSize
>= VarDataSize
) {
905 Status
= EFI_INVALID_PARAMETER
;
909 CopyMem (Data
, GetVariableDataPtr (Variable
.CurrPtr
), VarDataSize
);
910 if (Attributes
!= NULL
) {
911 *Attributes
= Variable
.CurrPtr
->Attributes
;
914 *DataSize
= VarDataSize
;
915 UpdateVariableInfo (VariableName
, VendorGuid
, Variable
.Volatile
, TRUE
, FALSE
, FALSE
, FALSE
);
916 UpdateVariableCache (VariableName
, VendorGuid
, Variable
.CurrPtr
->Attributes
, VarDataSize
, Data
);
918 Status
= EFI_SUCCESS
;
921 *DataSize
= VarDataSize
;
922 Status
= EFI_BUFFER_TOO_SMALL
;
927 ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal
->VariableGlobal
.VariableServicesLock
);
937 This code Finds the Next available variable
941 VariableNameSize Size of the variable
942 VariableName Pointer to variable name
943 VendorGuid Variable Vendor Guid
944 Global VARIABLE_GLOBAL structure pointer.
954 RuntimeServiceGetNextVariableName (
955 IN OUT UINTN
*VariableNameSize
,
956 IN OUT CHAR16
*VariableName
,
957 IN OUT EFI_GUID
*VendorGuid
960 VARIABLE_POINTER_TRACK Variable
;
964 if (VariableNameSize
== NULL
|| VariableName
== NULL
|| VendorGuid
== NULL
) {
965 return EFI_INVALID_PARAMETER
;
968 AcquireLockOnlyAtBootTime(&mVariableModuleGlobal
->VariableGlobal
.VariableServicesLock
);
970 Status
= FindVariable (VariableName
, VendorGuid
, &Variable
, &mVariableModuleGlobal
->VariableGlobal
);
971 if (Variable
.CurrPtr
== NULL
|| EFI_ERROR (Status
)) {
975 if (VariableName
[0] != 0) {
977 // If variable name is not NULL, get next variable
979 Variable
.CurrPtr
= GetNextVariablePtr (Variable
.CurrPtr
);
984 // If both volatile and non-volatile variable store are parsed,
987 if (Variable
.CurrPtr
>= Variable
.EndPtr
|| Variable
.CurrPtr
== NULL
) {
988 Variable
.Volatile
= (BOOLEAN
) (Variable
.Volatile
^ ((BOOLEAN
) 0x1));
989 if (!Variable
.Volatile
) {
990 Variable
.StartPtr
= (VARIABLE_HEADER
*) ((UINTN
) (mVariableModuleGlobal
->VariableGlobal
.NonVolatileVariableBase
+ sizeof (VARIABLE_STORE_HEADER
)));
991 Variable
.EndPtr
= (VARIABLE_HEADER
*) GetEndPointer ((VARIABLE_STORE_HEADER
*) ((UINTN
) mVariableModuleGlobal
->VariableGlobal
.NonVolatileVariableBase
));
993 Status
= EFI_NOT_FOUND
;
997 Variable
.CurrPtr
= Variable
.StartPtr
;
998 if (!IsValidVariableHeader (Variable
.CurrPtr
)) {
1003 // Variable is found
1005 if (IsValidVariableHeader (Variable
.CurrPtr
) && Variable
.CurrPtr
->State
== VAR_ADDED
) {
1006 if (!(EfiAtRuntime () && !(Variable
.CurrPtr
->Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
))) {
1007 VarNameSize
= NameSizeOfVariable (Variable
.CurrPtr
);
1008 ASSERT (VarNameSize
!= 0);
1010 if (VarNameSize
<= *VariableNameSize
) {
1013 GET_VARIABLE_NAME_PTR (Variable
.CurrPtr
),
1018 &Variable
.CurrPtr
->VendorGuid
,
1021 Status
= EFI_SUCCESS
;
1023 Status
= EFI_BUFFER_TOO_SMALL
;
1026 *VariableNameSize
= VarNameSize
;
1031 Variable
.CurrPtr
= GetNextVariablePtr (Variable
.CurrPtr
);
1035 ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal
->VariableGlobal
.VariableServicesLock
);
1042 Routine Description:
1044 This code sets variable in storage blocks (Volatile or Non-Volatile)
1048 VariableName Name of Variable to be found
1049 VendorGuid Variable vendor GUID
1050 Attributes Attribute value of the variable found
1051 DataSize Size of Data found. If size is less than the
1052 data, this value contains the required size.
1054 Global Pointer to VARIABLE_GLOBAL structure
1055 VolatileOffset The offset of last volatile variable
1056 NonVolatileOffset The offset of last non-volatile variable
1057 Instance Instance of the Firmware Volume.
1061 EFI_INVALID_PARAMETER - Invalid parameter
1062 EFI_SUCCESS - Set successfully
1063 EFI_OUT_OF_RESOURCES - Resource not enough to set variable
1064 EFI_NOT_FOUND - Not found
1065 EFI_DEVICE_ERROR - Variable can not be saved due to hardware failure
1066 EFI_WRITE_PROTECTED - Variable is read-only
1071 RuntimeServiceSetVariable (
1072 IN CHAR16
*VariableName
,
1073 IN EFI_GUID
*VendorGuid
,
1074 IN UINT32 Attributes
,
1079 VARIABLE_POINTER_TRACK Variable
;
1081 VARIABLE_HEADER
*NextVariable
;
1083 UINTN VarNameOffset
;
1084 UINTN VarDataOffset
;
1088 UINTN
*VolatileOffset
;
1089 UINTN
*NonVolatileOffset
;
1092 EFI_PHYSICAL_ADDRESS Point
;
1095 // Check input parameters
1097 if (VariableName
== NULL
|| VariableName
[0] == 0 || VendorGuid
== NULL
) {
1098 return EFI_INVALID_PARAMETER
;
1101 // Make sure if runtime bit is set, boot service bit is set also
1103 if ((Attributes
& (EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
)) == EFI_VARIABLE_RUNTIME_ACCESS
) {
1104 return EFI_INVALID_PARAMETER
;
1108 // The size of the VariableName, including the Unicode Null in bytes plus
1109 // the DataSize is limited to maximum size of MAX_HARDWARE_ERROR_VARIABLE_SIZE (32K)
1110 // bytes for HwErrRec, and MAX_VARIABLE_SIZE (1024) bytes for the others.
1112 if ((Attributes
& EFI_VARIABLE_HARDWARE_ERROR_RECORD
) == EFI_VARIABLE_HARDWARE_ERROR_RECORD
) {
1113 if ((DataSize
> MAX_HARDWARE_ERROR_VARIABLE_SIZE
) ||
1114 (sizeof (VARIABLE_HEADER
) + StrSize (VariableName
) + DataSize
> MAX_HARDWARE_ERROR_VARIABLE_SIZE
)) {
1115 return EFI_INVALID_PARAMETER
;
1119 // The size of the VariableName, including the Unicode Null in bytes plus
1120 // the DataSize is limited to maximum size of MAX_VARIABLE_SIZE (1024) bytes.
1122 if ((DataSize
> MAX_VARIABLE_SIZE
) ||
1123 (sizeof (VARIABLE_HEADER
) + StrSize (VariableName
) + DataSize
> MAX_VARIABLE_SIZE
)) {
1124 return EFI_INVALID_PARAMETER
;
1128 AcquireLockOnlyAtBootTime(&mVariableModuleGlobal
->VariableGlobal
.VariableServicesLock
);
1131 Instance
= mVariableModuleGlobal
->FvbInstance
;
1132 VolatileOffset
= &mVariableModuleGlobal
->VolatileLastVariableOffset
;
1135 // Consider reentrant in MCA/INIT/NMI. It needs be reupdated;
1137 if (1 < InterlockedIncrement (&mVariableModuleGlobal
->VariableGlobal
.ReentrantState
)) {
1139 volatile int tt
= 1;
1143 Point
= mVariableModuleGlobal
->VariableGlobal
.NonVolatileVariableBase
;;
1145 // Parse non-volatile variable data and get last variable offset
1147 NextVariable
= (VARIABLE_HEADER
*) (UINTN
) (Point
+ sizeof (VARIABLE_STORE_HEADER
));
1148 while (IsValidVariableHeader (NextVariable
)) {
1149 NextVariable
= GetNextVariablePtr (NextVariable
);
1151 mVariableModuleGlobal
->NonVolatileLastVariableOffset
= (UINTN
) NextVariable
- (UINTN
) Point
;
1154 NonVolatileOffset
= &mVariableModuleGlobal
->NonVolatileLastVariableOffset
;
1158 // Check whether the input variable is already existed
1161 Status
= FindVariable (VariableName
, VendorGuid
, &Variable
, &mVariableModuleGlobal
->VariableGlobal
);
1162 if (Status
== EFI_SUCCESS
&& Variable
.CurrPtr
!= NULL
) {
1164 // Update/Delete existing variable
1166 Volatile
= Variable
.Volatile
;
1168 if (EfiAtRuntime ()) {
1170 // If EfiAtRuntime and the variable is Volatile and Runtime Access,
1171 // the volatile is ReadOnly, and SetVariable should be aborted and
1172 // return EFI_WRITE_PROTECTED.
1174 if (Variable
.Volatile
) {
1175 Status
= EFI_WRITE_PROTECTED
;
1179 // Only variable have NV attribute can be updated/deleted in Runtime
1181 if (!(Variable
.CurrPtr
->Attributes
& EFI_VARIABLE_NON_VOLATILE
)) {
1182 Status
= EFI_INVALID_PARAMETER
;
1187 // Setting a data variable with no access, or zero DataSize attributes
1188 // specified causes it to be deleted.
1190 if (DataSize
== 0 || (Attributes
& (EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
)) == 0) {
1191 State
= Variable
.CurrPtr
->State
;
1192 State
&= VAR_DELETED
;
1194 Status
= UpdateVariableStore (
1195 &mVariableModuleGlobal
->VariableGlobal
,
1199 (UINTN
) &Variable
.CurrPtr
->State
,
1203 if (!EFI_ERROR (Status
)) {
1204 UpdateVariableInfo (VariableName
, VendorGuid
, Volatile
, FALSE
, FALSE
, TRUE
, FALSE
);
1205 UpdateVariableCache (VariableName
, VendorGuid
, Attributes
, DataSize
, Data
);
1210 // If the variable is marked valid and the same data has been passed in
1211 // then return to the caller immediately.
1213 if (DataSizeOfVariable (Variable
.CurrPtr
) == DataSize
&&
1214 (CompareMem (Data
, GetVariableDataPtr (Variable
.CurrPtr
), DataSize
) == 0)) {
1216 UpdateVariableInfo (VariableName
, VendorGuid
, Volatile
, FALSE
, TRUE
, FALSE
, FALSE
);
1217 Status
= EFI_SUCCESS
;
1219 } else if ((Variable
.CurrPtr
->State
== VAR_ADDED
) ||
1220 (Variable
.CurrPtr
->State
== (VAR_ADDED
& VAR_IN_DELETED_TRANSITION
))) {
1222 // Mark the old variable as in delete transition
1224 State
= Variable
.CurrPtr
->State
;
1225 State
&= VAR_IN_DELETED_TRANSITION
;
1227 Status
= UpdateVariableStore (
1228 &mVariableModuleGlobal
->VariableGlobal
,
1232 (UINTN
) &Variable
.CurrPtr
->State
,
1236 if (EFI_ERROR (Status
)) {
1240 } else if (Status
== EFI_NOT_FOUND
) {
1242 // Create a new variable
1246 // Make sure we are trying to create a new variable.
1247 // Setting a data variable with no access, or zero DataSize attributes means to delete it.
1249 if (DataSize
== 0 || (Attributes
& (EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
)) == 0) {
1250 Status
= EFI_NOT_FOUND
;
1255 // Only variable have NV|RT attribute can be created in Runtime
1257 if (EfiAtRuntime () &&
1258 (!(Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
) || !(Attributes
& EFI_VARIABLE_NON_VOLATILE
))) {
1259 Status
= EFI_INVALID_PARAMETER
;
1264 // Status should be EFI_INVALID_PARAMETER here according to return status of FindVariable().
1266 ASSERT (Status
== EFI_INVALID_PARAMETER
);
1271 // Function part - create a new variable and copy the data.
1272 // Both update a variable and create a variable will come here.
1274 // Tricky part: Use scratch data area at the end of volatile variable store
1275 // as a temporary storage.
1277 NextVariable
= GetEndPointer ((VARIABLE_STORE_HEADER
*) ((UINTN
) mVariableModuleGlobal
->VariableGlobal
.VolatileVariableBase
));
1279 SetMem (NextVariable
, SCRATCH_SIZE
, 0xff);
1281 NextVariable
->StartId
= VARIABLE_DATA
;
1282 NextVariable
->Attributes
= Attributes
;
1284 // NextVariable->State = VAR_ADDED;
1286 NextVariable
->Reserved
= 0;
1287 VarNameOffset
= sizeof (VARIABLE_HEADER
);
1288 VarNameSize
= StrSize (VariableName
);
1290 (UINT8
*) ((UINTN
) NextVariable
+ VarNameOffset
),
1294 VarDataOffset
= VarNameOffset
+ VarNameSize
+ GET_PAD_SIZE (VarNameSize
);
1296 (UINT8
*) ((UINTN
) NextVariable
+ VarDataOffset
),
1300 CopyMem (&NextVariable
->VendorGuid
, VendorGuid
, sizeof (EFI_GUID
));
1302 // There will be pad bytes after Data, the NextVariable->NameSize and
1303 // NextVariable->DataSize should not include pad size so that variable
1304 // service can get actual size in GetVariable
1306 NextVariable
->NameSize
= (UINT32
)VarNameSize
;
1307 NextVariable
->DataSize
= (UINT32
)DataSize
;
1310 // The actual size of the variable that stores in storage should
1311 // include pad size.
1313 VarSize
= VarDataOffset
+ DataSize
+ GET_PAD_SIZE (DataSize
);
1314 if (Attributes
& EFI_VARIABLE_NON_VOLATILE
) {
1316 // Create a nonvolatile variable
1320 if ((UINT32
) (VarSize
+*NonVolatileOffset
) >
1321 ((VARIABLE_STORE_HEADER
*) ((UINTN
) (mVariableModuleGlobal
->VariableGlobal
.NonVolatileVariableBase
)))->Size
1323 if (EfiAtRuntime ()) {
1324 Status
= EFI_OUT_OF_RESOURCES
;
1328 // Perform garbage collection & reclaim operation
1330 Status
= Reclaim (mVariableModuleGlobal
->VariableGlobal
.NonVolatileVariableBase
, NonVolatileOffset
, FALSE
);
1331 if (EFI_ERROR (Status
)) {
1335 // If still no enough space, return out of resources
1337 if ((UINT32
) (VarSize
+*NonVolatileOffset
) >
1338 ((VARIABLE_STORE_HEADER
*) ((UINTN
) (mVariableModuleGlobal
->VariableGlobal
.NonVolatileVariableBase
)))->Size
1340 Status
= EFI_OUT_OF_RESOURCES
;
1348 // 1. Write variable header
1349 // 2. Write variable data
1350 // 3. Set variable state to valid
1355 Status
= UpdateVariableStore (
1356 &mVariableModuleGlobal
->VariableGlobal
,
1361 sizeof (VARIABLE_HEADER
),
1362 (UINT8
*) NextVariable
1365 if (EFI_ERROR (Status
)) {
1371 Status
= UpdateVariableStore (
1372 &mVariableModuleGlobal
->VariableGlobal
,
1376 *NonVolatileOffset
+ sizeof (VARIABLE_HEADER
),
1377 (UINT32
) VarSize
- sizeof (VARIABLE_HEADER
),
1378 (UINT8
*) NextVariable
+ sizeof (VARIABLE_HEADER
)
1381 if (EFI_ERROR (Status
)) {
1387 NextVariable
->State
= VAR_ADDED
;
1388 Status
= UpdateVariableStore (
1389 &mVariableModuleGlobal
->VariableGlobal
,
1394 sizeof (VARIABLE_HEADER
),
1395 (UINT8
*) NextVariable
1398 if (EFI_ERROR (Status
)) {
1402 *NonVolatileOffset
= *NonVolatileOffset
+ VarSize
;
1406 // Create a volatile variable
1410 if ((UINT32
) (VarSize
+*VolatileOffset
) >
1411 ((VARIABLE_STORE_HEADER
*) ((UINTN
) (mVariableModuleGlobal
->VariableGlobal
.VolatileVariableBase
)))->Size
) {
1413 // Perform garbage collection & reclaim operation
1415 Status
= Reclaim (mVariableModuleGlobal
->VariableGlobal
.VolatileVariableBase
, VolatileOffset
, TRUE
);
1416 if (EFI_ERROR (Status
)) {
1420 // If still no enough space, return out of resources
1422 if ((UINT32
) (VarSize
+*VolatileOffset
) >
1423 ((VARIABLE_STORE_HEADER
*) ((UINTN
) (mVariableModuleGlobal
->VariableGlobal
.VolatileVariableBase
)))->Size
1425 Status
= EFI_OUT_OF_RESOURCES
;
1432 NextVariable
->State
= VAR_ADDED
;
1433 Status
= UpdateVariableStore (
1434 &mVariableModuleGlobal
->VariableGlobal
,
1440 (UINT8
*) NextVariable
1443 if (EFI_ERROR (Status
)) {
1447 *VolatileOffset
= *VolatileOffset
+ VarSize
;
1450 // Mark the old variable as deleted
1452 if (!Reclaimed
&& !EFI_ERROR (Status
) && Variable
.CurrPtr
!= NULL
) {
1453 State
= Variable
.CurrPtr
->State
;
1454 State
&= VAR_DELETED
;
1456 Status
= UpdateVariableStore (
1457 &mVariableModuleGlobal
->VariableGlobal
,
1461 (UINTN
) &Variable
.CurrPtr
->State
,
1466 if (!EFI_ERROR (Status
)) {
1467 UpdateVariableInfo (VariableName
, VendorGuid
, Volatile
, FALSE
, TRUE
, FALSE
, FALSE
);
1468 UpdateVariableCache (VariableName
, VendorGuid
, Attributes
, DataSize
, Data
);
1473 Status
= EFI_SUCCESS
;
1474 UpdateVariableInfo (VariableName
, VendorGuid
, Volatile
, FALSE
, TRUE
, FALSE
, FALSE
);
1475 UpdateVariableCache (VariableName
, VendorGuid
, Attributes
, DataSize
, Data
);
1478 InterlockedDecrement (&mVariableModuleGlobal
->VariableGlobal
.ReentrantState
);
1479 ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal
->VariableGlobal
.VariableServicesLock
);
1487 Routine Description:
1489 This code returns information about the EFI variables.
1493 Attributes Attributes bitmask to specify the type of variables
1494 on which to return information.
1495 MaximumVariableStorageSize Pointer to the maximum size of the storage space available
1496 for the EFI variables associated with the attributes specified.
1497 RemainingVariableStorageSize Pointer to the remaining size of the storage space available
1498 for EFI variables associated with the attributes specified.
1499 MaximumVariableSize Pointer to the maximum size of an individual EFI variables
1500 associated with the attributes specified.
1501 Global Pointer to VARIABLE_GLOBAL structure.
1502 Instance Instance of the Firmware Volume.
1507 EFI_INVALID_PARAMETER - An invalid combination of attribute bits was supplied.
1508 EFI_SUCCESS - Query successfully.
1509 EFI_UNSUPPORTED - The attribute is not supported on this platform.
1514 RuntimeServiceQueryVariableInfo (
1515 IN UINT32 Attributes
,
1516 OUT UINT64
*MaximumVariableStorageSize
,
1517 OUT UINT64
*RemainingVariableStorageSize
,
1518 OUT UINT64
*MaximumVariableSize
1521 VARIABLE_HEADER
*Variable
;
1522 VARIABLE_HEADER
*NextVariable
;
1523 UINT64 VariableSize
;
1524 VARIABLE_STORE_HEADER
*VariableStoreHeader
;
1526 if(MaximumVariableStorageSize
== NULL
|| RemainingVariableStorageSize
== NULL
|| MaximumVariableSize
== NULL
|| Attributes
== 0) {
1527 return EFI_INVALID_PARAMETER
;
1530 if((Attributes
& (EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_HARDWARE_ERROR_RECORD
)) == 0) {
1532 // Make sure the Attributes combination is supported by the platform.
1534 return EFI_UNSUPPORTED
;
1535 } else if ((Attributes
& (EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
)) == EFI_VARIABLE_RUNTIME_ACCESS
) {
1537 // Make sure if runtime bit is set, boot service bit is set also.
1539 return EFI_INVALID_PARAMETER
;
1540 } else if (EfiAtRuntime () && !(Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
)) {
1542 // Make sure RT Attribute is set if we are in Runtime phase.
1544 return EFI_INVALID_PARAMETER
;
1547 AcquireLockOnlyAtBootTime(&mVariableModuleGlobal
->VariableGlobal
.VariableServicesLock
);
1549 if((Attributes
& EFI_VARIABLE_NON_VOLATILE
) == 0) {
1551 // Query is Volatile related.
1553 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) ((UINTN
) mVariableModuleGlobal
->VariableGlobal
.VolatileVariableBase
);
1556 // Query is Non-Volatile related.
1558 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) ((UINTN
) mVariableModuleGlobal
->VariableGlobal
.NonVolatileVariableBase
);
1562 // Now let's fill *MaximumVariableStorageSize *RemainingVariableStorageSize
1563 // with the storage size (excluding the storage header size).
1565 *MaximumVariableStorageSize
= VariableStoreHeader
->Size
- sizeof (VARIABLE_STORE_HEADER
);
1566 *RemainingVariableStorageSize
= VariableStoreHeader
->Size
- sizeof (VARIABLE_STORE_HEADER
);
1569 // Let *MaximumVariableSize be MAX_VARIABLE_SIZE with the exception of the variable header size.
1571 *MaximumVariableSize
= MAX_VARIABLE_SIZE
- sizeof (VARIABLE_HEADER
);
1574 // Harware error record variable needs larger size.
1576 if ((Attributes
& EFI_VARIABLE_HARDWARE_ERROR_RECORD
) == EFI_VARIABLE_HARDWARE_ERROR_RECORD
) {
1577 *MaximumVariableSize
= MAX_HARDWARE_ERROR_VARIABLE_SIZE
- sizeof (VARIABLE_HEADER
);
1581 // Point to the starting address of the variables.
1583 Variable
= (VARIABLE_HEADER
*) (VariableStoreHeader
+ 1);
1586 // Now walk through the related variable store.
1588 while (IsValidVariableHeader (Variable
) && (Variable
< GetEndPointer (VariableStoreHeader
))) {
1589 NextVariable
= GetNextVariablePtr (Variable
);
1590 VariableSize
= (UINT64
) (UINTN
) NextVariable
- (UINT64
) (UINTN
) Variable
;
1592 if (EfiAtRuntime ()) {
1594 // we don't take the state of the variables in mind
1595 // when calculating RemainingVariableStorageSize,
1596 // since the space occupied by variables not marked with
1597 // VAR_ADDED is not allowed to be reclaimed in Runtime.
1599 *RemainingVariableStorageSize
-= VariableSize
;
1602 // Only care about Variables with State VAR_ADDED,because
1603 // the space not marked as VAR_ADDED is reclaimable now.
1605 if (Variable
->State
== VAR_ADDED
) {
1606 *RemainingVariableStorageSize
-= VariableSize
;
1611 // Go to the next one
1613 Variable
= NextVariable
;
1616 if (*RemainingVariableStorageSize
< sizeof (VARIABLE_HEADER
)) {
1617 *MaximumVariableSize
= 0;
1618 } else if ((*RemainingVariableStorageSize
- sizeof (VARIABLE_HEADER
)) < *MaximumVariableSize
) {
1619 *MaximumVariableSize
= *RemainingVariableStorageSize
- sizeof (VARIABLE_HEADER
);
1622 ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal
->VariableGlobal
.VariableServicesLock
);
1627 VariableCommonInitialize (
1628 IN EFI_HANDLE ImageHandle
,
1629 IN EFI_SYSTEM_TABLE
*SystemTable
1633 Routine Description:
1634 This function does common initialization for variable services
1638 ImageHandle - The firmware allocated handle for the EFI image.
1639 SystemTable - A pointer to the EFI System Table.
1645 EFI_NOT_FOUND - Variable store area not found.
1646 EFI_UNSUPPORTED - Currently only one non-volatile variable store is supported.
1647 EFI_SUCCESS - Variable services successfully initialized.
1652 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
1654 VARIABLE_STORE_HEADER
*VolatileVariableStore
;
1655 VARIABLE_STORE_HEADER
*VariableStoreHeader
;
1656 VARIABLE_HEADER
*NextVariable
;
1658 EFI_PHYSICAL_ADDRESS FvVolHdr
;
1659 UINT64 TempVariableStoreHeader
;
1660 EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor
;
1665 UINT64 VariableStoreBase
;
1666 UINT64 VariableStoreLength
;
1669 EfiInitializeLock(&mVariableModuleGlobal
->VariableGlobal
.VariableServicesLock
, TPL_NOTIFY
);
1670 mVariableModuleGlobal
->VariableGlobal
.ReentrantState
= 0;
1673 // Allocate memory for volatile variable store
1675 VolatileVariableStore
= AllocateRuntimePool (VARIABLE_STORE_SIZE
+ SCRATCH_SIZE
);
1676 if (VolatileVariableStore
== NULL
) {
1677 FreePool (mVariableModuleGlobal
);
1678 return EFI_OUT_OF_RESOURCES
;
1681 SetMem (VolatileVariableStore
, VARIABLE_STORE_SIZE
+ SCRATCH_SIZE
, 0xff);
1684 // Variable Specific Data
1686 mVariableModuleGlobal
->VariableGlobal
.VolatileVariableBase
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) VolatileVariableStore
;
1687 mVariableModuleGlobal
->VolatileLastVariableOffset
= sizeof (VARIABLE_STORE_HEADER
);
1689 VolatileVariableStore
->Signature
= VARIABLE_STORE_SIGNATURE
;
1690 VolatileVariableStore
->Size
= VARIABLE_STORE_SIZE
;
1691 VolatileVariableStore
->Format
= VARIABLE_STORE_FORMATTED
;
1692 VolatileVariableStore
->State
= VARIABLE_STORE_HEALTHY
;
1693 VolatileVariableStore
->Reserved
= 0;
1694 VolatileVariableStore
->Reserved1
= 0;
1697 // Get non volatile varaible store
1700 TempVariableStoreHeader
= (UINT64
) PcdGet32 (PcdFlashNvStorageVariableBase
);
1701 VariableStoreBase
= TempVariableStoreHeader
+ \
1702 (((EFI_FIRMWARE_VOLUME_HEADER
*) (UINTN
) (TempVariableStoreHeader
)) -> HeaderLength
);
1703 VariableStoreLength
= (UINT64
) PcdGet32 (PcdFlashNvStorageVariableSize
) - \
1704 (((EFI_FIRMWARE_VOLUME_HEADER
*) (UINTN
) (TempVariableStoreHeader
)) -> HeaderLength
);
1706 // Mark the variable storage region of the FLASH as RUNTIME
1708 BaseAddress
= VariableStoreBase
& (~EFI_PAGE_MASK
);
1709 Length
= VariableStoreLength
+ (VariableStoreBase
- BaseAddress
);
1710 Length
= (Length
+ EFI_PAGE_SIZE
- 1) & (~EFI_PAGE_MASK
);
1712 Status
= gDS
->GetMemorySpaceDescriptor (BaseAddress
, &GcdDescriptor
);
1713 if (EFI_ERROR (Status
)) {
1714 FreePool (mVariableModuleGlobal
);
1715 FreePool (VolatileVariableStore
);
1716 return EFI_UNSUPPORTED
;
1719 Status
= gDS
->SetMemorySpaceAttributes (
1722 GcdDescriptor
.Attributes
| EFI_MEMORY_RUNTIME
1724 if (EFI_ERROR (Status
)) {
1725 FreePool (mVariableModuleGlobal
);
1726 FreePool (VolatileVariableStore
);
1727 return EFI_UNSUPPORTED
;
1730 // Get address of non volatile variable store base
1732 mVariableModuleGlobal
->VariableGlobal
.NonVolatileVariableBase
= VariableStoreBase
;
1738 // Find the Correct Instance of the FV Block Service.
1741 CurrPtr
= (CHAR8
*) ((UINTN
) mVariableModuleGlobal
->VariableGlobal
.NonVolatileVariableBase
);
1742 while (EfiFvbGetPhysicalAddress (Instance
, &FvVolHdr
) == EFI_SUCCESS
) {
1743 FwVolHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) ((UINTN
) FvVolHdr
);
1744 if (CurrPtr
>= (CHAR8
*) FwVolHeader
&& CurrPtr
< (((CHAR8
*) FwVolHeader
) + FwVolHeader
->FvLength
)) {
1745 mVariableModuleGlobal
->FvbInstance
= Instance
;
1752 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) CurrPtr
;
1753 if (GetVariableStoreStatus (VariableStoreHeader
) == EfiValid
) {
1754 if (~VariableStoreHeader
->Size
== 0) {
1755 Status
= UpdateVariableStore (
1756 &mVariableModuleGlobal
->VariableGlobal
,
1759 mVariableModuleGlobal
->FvbInstance
,
1760 (UINTN
) &VariableStoreHeader
->Size
,
1762 (UINT8
*) &VariableStoreLength
1765 // As Variables are stored in NV storage, which are slow devices,such as flash.
1766 // Variable operation may skip checking variable program result to improve performance,
1767 // We can assume Variable program is OK through some check point.
1768 // Variable Store Size Setting should be the first Variable write operation,
1769 // We can assume all Read/Write is OK if we can set Variable store size successfully.
1770 // If write fail, we will assert here
1772 ASSERT(VariableStoreHeader
->Size
== VariableStoreLength
);
1774 if (EFI_ERROR (Status
)) {
1779 mVariableModuleGlobal
->VariableGlobal
.NonVolatileVariableBase
= (EFI_PHYSICAL_ADDRESS
) ((UINTN
) CurrPtr
);
1781 // Parse non-volatile variable data and get last variable offset
1783 NextVariable
= (VARIABLE_HEADER
*) (CurrPtr
+ sizeof (VARIABLE_STORE_HEADER
));
1784 Status
= EFI_SUCCESS
;
1786 while (IsValidVariableHeader (NextVariable
)) {
1787 NextVariable
= GetNextVariablePtr (NextVariable
);
1790 mVariableModuleGlobal
->NonVolatileLastVariableOffset
= (UINTN
) NextVariable
- (UINTN
) CurrPtr
;
1793 // Check if the free area is blow a threshold
1795 if ((((VARIABLE_STORE_HEADER
*)((UINTN
) CurrPtr
))->Size
- mVariableModuleGlobal
->NonVolatileLastVariableOffset
) < VARIABLE_RECLAIM_THRESHOLD
) {
1797 mVariableModuleGlobal
->VariableGlobal
.NonVolatileVariableBase
,
1798 &mVariableModuleGlobal
->NonVolatileLastVariableOffset
,
1803 if (EFI_ERROR (Status
)) {
1804 FreePool (mVariableModuleGlobal
);
1805 FreePool (VolatileVariableStore
);
1810 // Check if the free area is really free.
1812 for (Index
= mVariableModuleGlobal
->NonVolatileLastVariableOffset
; Index
< VariableStoreHeader
->Size
; Index
++) {
1813 Data
= ((UINT8
*) (UINTN
) mVariableModuleGlobal
->VariableGlobal
.NonVolatileVariableBase
)[Index
];
1816 // There must be something wrong in variable store, do reclaim operation.
1819 mVariableModuleGlobal
->VariableGlobal
.NonVolatileVariableBase
,
1820 &mVariableModuleGlobal
->NonVolatileLastVariableOffset
,
1828 if (EFI_ERROR (Status
)) {
1829 FreePool (mVariableModuleGlobal
);
1830 FreePool (VolatileVariableStore
);
1841 VariableClassAddressChangeEvent (
1848 (VOID
**) &mVariableModuleGlobal
->VariableGlobal
.NonVolatileVariableBase
1852 (VOID
**) &mVariableModuleGlobal
->VariableGlobal
.VolatileVariableBase
1854 EfiConvertPointer (0x0, (VOID
**) &mVariableModuleGlobal
);
1859 Variable Driver main entry point. The Variable driver places the 4 EFI
1860 runtime services in the EFI System Table and installs arch protocols
1861 for variable read and write services being availible.
1863 @param[in] ImageHandle The firmware allocated handle for the EFI image.
1864 @param[in] SystemTable A pointer to the EFI System Table.
1866 @retval EFI_SUCCESS The entry point is executed successfully.
1867 @retval other Some error occurs when executing this entry point.
1872 VariableServiceInitialize (
1873 IN EFI_HANDLE ImageHandle
,
1874 IN EFI_SYSTEM_TABLE
*SystemTable
1879 Status
= VariableCommonInitialize (ImageHandle
, SystemTable
);
1880 ASSERT_EFI_ERROR (Status
);
1882 SystemTable
->RuntimeServices
->GetVariable
= RuntimeServiceGetVariable
;
1883 SystemTable
->RuntimeServices
->GetNextVariableName
= RuntimeServiceGetNextVariableName
;
1884 SystemTable
->RuntimeServices
->SetVariable
= RuntimeServiceSetVariable
;
1885 SystemTable
->RuntimeServices
->QueryVariableInfo
= RuntimeServiceQueryVariableInfo
;
1888 // Now install the Variable Runtime Architectural Protocol on a new handle
1890 Status
= gBS
->InstallMultipleProtocolInterfaces (
1892 &gEfiVariableArchProtocolGuid
, NULL
,
1893 &gEfiVariableWriteArchProtocolGuid
, NULL
,
1896 ASSERT_EFI_ERROR (Status
);
1898 Status
= gBS
->CreateEvent (
1899 EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE
,
1901 VariableClassAddressChangeEvent
,
1903 &mVirtualAddressChangeEvent
1905 ASSERT_EFI_ERROR (Status
);