3 Implement all four UEFI Runtime Variable services for the nonvolatile
4 and volatile storage space and install variable architecture protocol.
6 Copyright (c) 2006 - 2009, Intel Corporation
7 All rights reserved. This program and the accompanying materials
8 are licensed and made available under the terms and conditions of the BSD License
9 which accompanies this distribution. The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 VARIABLE_MODULE_GLOBAL
*mVariableModuleGlobal
;
20 EFI_EVENT mVirtualAddressChangeEvent
= NULL
;
21 EFI_HANDLE mHandle
= NULL
;
24 /// The current Hii implementation accesses this variable many times on every boot.
25 /// Other common variables are only accessed once. This is why this cache algorithm
26 /// only targets a single variable. Probably to get an performance improvement out of
27 /// a Cache you would need a cache that improves the search performance for a variable.
29 VARIABLE_CACHE_ENTRY mVariableCache
[] = {
31 &gEfiGlobalVariableGuid
,
39 VARIABLE_INFO_ENTRY
*gVariableInfo
= NULL
;
40 EFI_EVENT mFvbRegistration
= NULL
;
44 Acquires lock only at boot time. Simply returns at runtime.
46 This is a temperary function which will be removed when
47 EfiAcquireLock() in UefiLib can handle the call in UEFI
48 Runtimer driver in RT phase.
49 It calls EfiAcquireLock() at boot time, and simply returns
52 @param Lock A pointer to the lock to acquire
56 AcquireLockOnlyAtBootTime (
60 if (!EfiAtRuntime ()) {
61 EfiAcquireLock (Lock
);
66 Releases lock only at boot time. Simply returns at runtime.
68 This is a temperary function which will be removed when
69 EfiReleaseLock() in UefiLib can handle the call in UEFI
70 Runtimer driver in RT phase.
71 It calls EfiReleaseLock() at boot time, and simply returns
74 @param Lock A pointer to the lock to release
78 ReleaseLockOnlyAtBootTime (
82 if (!EfiAtRuntime ()) {
83 EfiReleaseLock (Lock
);
89 Routine used to track statistical information about variable usage.
90 The data is stored in the EFI system table so it can be accessed later.
91 VariableInfo.efi can dump out the table. Only Boot Services variable
92 accesses are tracked by this code. The PcdVariableCollectStatistics
93 build flag controls if this feature is enabled.
95 A read that hits in the cache will have Read and Cache true for
96 the transaction. Data is allocated by this routine, but never
99 @param[in] VariableName Name of the Variable to track
100 @param[in] VendorGuid Guid of the Variable to track
101 @param[in] Volatile TRUE if volatile FALSE if non-volatile
102 @param[in] Read TRUE if GetVariable() was called
103 @param[in] Write TRUE if SetVariable() was called
104 @param[in] Delete TRUE if deleted via SetVariable()
105 @param[in] Cache TRUE for a cache hit.
110 IN CHAR16
*VariableName
,
111 IN EFI_GUID
*VendorGuid
,
119 VARIABLE_INFO_ENTRY
*Entry
;
121 if (FeaturePcdGet (PcdVariableCollectStatistics
)) {
123 if (EfiAtRuntime ()) {
124 // Don't collect statistics at runtime
128 if (gVariableInfo
== NULL
) {
130 // on the first call allocate a entry and place a pointer to it in
131 // the EFI System Table
133 gVariableInfo
= AllocateZeroPool (sizeof (VARIABLE_INFO_ENTRY
));
134 ASSERT (gVariableInfo
!= NULL
);
136 CopyGuid (&gVariableInfo
->VendorGuid
, VendorGuid
);
137 gVariableInfo
->Name
= AllocatePool (StrLen (VariableName
));
138 ASSERT (gVariableInfo
->Name
!= NULL
);
139 StrCpy (gVariableInfo
->Name
, VariableName
);
140 gVariableInfo
->Volatile
= Volatile
;
142 gBS
->InstallConfigurationTable (&gEfiVariableGuid
, gVariableInfo
);
146 for (Entry
= gVariableInfo
; Entry
!= NULL
; Entry
= Entry
->Next
) {
147 if (CompareGuid (VendorGuid
, &Entry
->VendorGuid
)) {
148 if (StrCmp (VariableName
, Entry
->Name
) == 0) {
156 Entry
->DeleteCount
++;
166 if (Entry
->Next
== NULL
) {
168 // If the entry is not in the table add it.
169 // Next iteration of the loop will fill in the data
171 Entry
->Next
= AllocateZeroPool (sizeof (VARIABLE_INFO_ENTRY
));
172 ASSERT (Entry
->Next
!= NULL
);
174 CopyGuid (&Entry
->Next
->VendorGuid
, VendorGuid
);
175 Entry
->Next
->Name
= AllocatePool (StrLen (VariableName
));
176 ASSERT (Entry
->Next
->Name
!= NULL
);
177 StrCpy (Entry
->Next
->Name
, VariableName
);
178 Entry
->Next
->Volatile
= Volatile
;
188 This code checks if variable header is valid or not.
190 @param Variable Pointer to the Variable Header.
192 @retval TRUE Variable header is valid.
193 @retval FALSE Variable header is not valid.
197 IsValidVariableHeader (
198 IN VARIABLE_HEADER
*Variable
201 if (Variable
== NULL
|| Variable
->StartId
!= VARIABLE_DATA
) {
211 This function writes data to the FWH at the correct LBA even if the LBAs
214 @param Global Pointer to VARAIBLE_GLOBAL structure
215 @param Volatile Point out the Variable is Volatile or Non-Volatile
216 @param SetByIndex TRUE if target pointer is given as index
217 FALSE if target pointer is absolute
218 @param Fvb Pointer to the writable FVB protocol
219 @param DataPtrIndex Pointer to the Data from the end of VARIABLE_STORE_HEADER
221 @param DataSize Size of data to be written
222 @param Buffer Pointer to the buffer from which data is written
224 @retval EFI_INVALID_PARAMETER Parameters not valid
225 @retval EFI_SUCCESS Variable store successfully updated
229 UpdateVariableStore (
230 IN VARIABLE_GLOBAL
*Global
,
232 IN BOOLEAN SetByIndex
,
233 IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*Fvb
,
234 IN UINTN DataPtrIndex
,
239 EFI_FV_BLOCK_MAP_ENTRY
*PtrBlockMapEntry
;
247 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
248 VARIABLE_STORE_HEADER
*VolatileBase
;
249 EFI_PHYSICAL_ADDRESS FvVolHdr
;
250 EFI_PHYSICAL_ADDRESS DataPtr
;
254 DataPtr
= DataPtrIndex
;
257 // Check if the Data is Volatile
260 Status
= Fvb
->GetPhysicalAddress(Fvb
, &FvVolHdr
);
261 ASSERT_EFI_ERROR (Status
);
263 FwVolHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) ((UINTN
) FvVolHdr
);
265 // Data Pointer should point to the actual Address where data is to be
269 DataPtr
+= mVariableModuleGlobal
->VariableGlobal
.NonVolatileVariableBase
;
272 if ((DataPtr
+ DataSize
) >= ((EFI_PHYSICAL_ADDRESS
) (UINTN
) ((UINT8
*) FwVolHeader
+ FwVolHeader
->FvLength
))) {
273 return EFI_INVALID_PARAMETER
;
277 // Data Pointer should point to the actual Address where data is to be
280 VolatileBase
= (VARIABLE_STORE_HEADER
*) ((UINTN
) mVariableModuleGlobal
->VariableGlobal
.VolatileVariableBase
);
282 DataPtr
+= mVariableModuleGlobal
->VariableGlobal
.VolatileVariableBase
;
285 if ((DataPtr
+ DataSize
) >= ((UINTN
) ((UINT8
*) VolatileBase
+ VolatileBase
->Size
))) {
286 return EFI_INVALID_PARAMETER
;
290 // If Volatile Variable just do a simple mem copy.
292 CopyMem ((UINT8
*)(UINTN
)DataPtr
, Buffer
, DataSize
);
297 // If we are here we are dealing with Non-Volatile Variables
299 LinearOffset
= (UINTN
) FwVolHeader
;
300 CurrWritePtr
= (UINTN
) DataPtr
;
301 CurrWriteSize
= DataSize
;
305 if (CurrWritePtr
< LinearOffset
) {
306 return EFI_INVALID_PARAMETER
;
309 for (PtrBlockMapEntry
= FwVolHeader
->BlockMap
; PtrBlockMapEntry
->NumBlocks
!= 0; PtrBlockMapEntry
++) {
310 for (BlockIndex2
= 0; BlockIndex2
< PtrBlockMapEntry
->NumBlocks
; BlockIndex2
++) {
312 // Check to see if the Variable Writes are spanning through multiple
315 if ((CurrWritePtr
>= LinearOffset
) && (CurrWritePtr
< LinearOffset
+ PtrBlockMapEntry
->Length
)) {
316 if ((CurrWritePtr
+ CurrWriteSize
) <= (LinearOffset
+ PtrBlockMapEntry
->Length
)) {
317 Status
= Fvb
->Write (
320 (UINTN
) (CurrWritePtr
- LinearOffset
),
326 Size
= (UINT32
) (LinearOffset
+ PtrBlockMapEntry
->Length
- CurrWritePtr
);
327 Status
= Fvb
->Write (
330 (UINTN
) (CurrWritePtr
- LinearOffset
),
334 if (EFI_ERROR (Status
)) {
338 CurrWritePtr
= LinearOffset
+ PtrBlockMapEntry
->Length
;
339 CurrBuffer
= CurrBuffer
+ Size
;
340 CurrWriteSize
= CurrWriteSize
- Size
;
344 LinearOffset
+= PtrBlockMapEntry
->Length
;
355 This code gets the current status of Variable Store.
357 @param VarStoreHeader Pointer to the Variable Store Header.
359 @retval EfiRaw Variable store status is raw
360 @retval EfiValid Variable store status is valid
361 @retval EfiInvalid Variable store status is invalid
364 VARIABLE_STORE_STATUS
365 GetVariableStoreStatus (
366 IN VARIABLE_STORE_HEADER
*VarStoreHeader
369 if (CompareGuid (&VarStoreHeader
->Signature
, &gEfiVariableGuid
) &&
370 VarStoreHeader
->Format
== VARIABLE_STORE_FORMATTED
&&
371 VarStoreHeader
->State
== VARIABLE_STORE_HEALTHY
375 } else if (((UINT32
*)(&VarStoreHeader
->Signature
))[0] == 0xffffffff &&
376 ((UINT32
*)(&VarStoreHeader
->Signature
))[1] == 0xffffffff &&
377 ((UINT32
*)(&VarStoreHeader
->Signature
))[2] == 0xffffffff &&
378 ((UINT32
*)(&VarStoreHeader
->Signature
))[3] == 0xffffffff &&
379 VarStoreHeader
->Size
== 0xffffffff &&
380 VarStoreHeader
->Format
== 0xff &&
381 VarStoreHeader
->State
== 0xff
393 This code gets the size of name of variable.
395 @param Variable Pointer to the Variable Header
397 @return UINTN Size of variable in bytes
402 IN VARIABLE_HEADER
*Variable
405 if (Variable
->State
== (UINT8
) (-1) ||
406 Variable
->DataSize
== (UINT32
) (-1) ||
407 Variable
->NameSize
== (UINT32
) (-1) ||
408 Variable
->Attributes
== (UINT32
) (-1)) {
411 return (UINTN
) Variable
->NameSize
;
416 This code gets the size of variable data.
418 @param Variable Pointer to the Variable Header
420 @return Size of variable in bytes
425 IN VARIABLE_HEADER
*Variable
428 if (Variable
->State
== (UINT8
) (-1) ||
429 Variable
->DataSize
== (UINT32
) (-1) ||
430 Variable
->NameSize
== (UINT32
) (-1) ||
431 Variable
->Attributes
== (UINT32
) (-1)) {
434 return (UINTN
) Variable
->DataSize
;
439 This code gets the pointer to the variable name.
441 @param Variable Pointer to the Variable Header
443 @return Pointer to Variable Name which is Unicode encoding
448 IN VARIABLE_HEADER
*Variable
452 return (CHAR16
*) (Variable
+ 1);
457 This code gets the pointer to the variable data.
459 @param Variable Pointer to the Variable Header
461 @return Pointer to Variable Data
466 IN VARIABLE_HEADER
*Variable
472 // Be careful about pad size for alignment
474 Value
= (UINTN
) GetVariableNamePtr (Variable
);
475 Value
+= NameSizeOfVariable (Variable
);
476 Value
+= GET_PAD_SIZE (NameSizeOfVariable (Variable
));
478 return (UINT8
*) Value
;
484 This code gets the pointer to the next variable header.
486 @param Variable Pointer to the Variable Header
488 @return Pointer to next variable header
493 IN VARIABLE_HEADER
*Variable
498 if (!IsValidVariableHeader (Variable
)) {
502 Value
= (UINTN
) GetVariableDataPtr (Variable
);
503 Value
+= DataSizeOfVariable (Variable
);
504 Value
+= GET_PAD_SIZE (DataSizeOfVariable (Variable
));
507 // Be careful about pad size for alignment
509 return (VARIABLE_HEADER
*) HEADER_ALIGN (Value
);
514 Gets the pointer to the first variable header in given variable store area.
516 @param VarStoreHeader Pointer to the Variable Store Header.
518 @return Pointer to the first variable header
523 IN VARIABLE_STORE_HEADER
*VarStoreHeader
527 // The end of variable store
529 return (VARIABLE_HEADER
*) HEADER_ALIGN (VarStoreHeader
+ 1);
534 Gets the pointer to the end of the variable storage area.
536 This function gets pointer to the end of the variable storage
537 area, according to the input variable store header.
539 @param VarStoreHeader Pointer to the Variable Store Header
541 @return Pointer to the end of the variable storage area
546 IN VARIABLE_STORE_HEADER
*VarStoreHeader
550 // The end of variable store
552 return (VARIABLE_HEADER
*) HEADER_ALIGN ((UINTN
) VarStoreHeader
+ VarStoreHeader
->Size
);
558 Variable store garbage collection and reclaim operation.
560 @param VariableBase Base address of variable store
561 @param LastVariableOffset Offset of last variable
562 @param IsVolatile The variable store is volatile or not,
563 if it is non-volatile, need FTW
564 @param UpdatingVariable Pointer to updateing variable.
566 @return EFI_OUT_OF_RESOURCES
573 IN EFI_PHYSICAL_ADDRESS VariableBase
,
574 OUT UINTN
*LastVariableOffset
,
575 IN BOOLEAN IsVolatile
,
576 IN VARIABLE_HEADER
*UpdatingVariable
579 VARIABLE_HEADER
*Variable
;
580 VARIABLE_HEADER
*AddedVariable
;
581 VARIABLE_HEADER
*NextVariable
;
582 VARIABLE_HEADER
*NextAddedVariable
;
583 VARIABLE_STORE_HEADER
*VariableStoreHeader
;
585 UINTN MaximumBufferSize
;
587 UINTN VariableNameSize
;
588 UINTN UpdatingVariableNameSize
;
595 CHAR16
*VariableNamePtr
;
596 CHAR16
*UpdatingVariableNamePtr
;
598 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) ((UINTN
) VariableBase
);
600 // recaluate the total size of Common/HwErr type variables in non-volatile area.
603 mVariableModuleGlobal
->CommonVariableTotalSize
= 0;
604 mVariableModuleGlobal
->HwErrVariableTotalSize
= 0;
608 // Start Pointers for the variable.
610 Variable
= GetStartPointer (VariableStoreHeader
);
611 MaximumBufferSize
= sizeof (VARIABLE_STORE_HEADER
);
613 while (IsValidVariableHeader (Variable
)) {
614 NextVariable
= GetNextVariablePtr (Variable
);
615 if (Variable
->State
== VAR_ADDED
||
616 Variable
->State
== (VAR_IN_DELETED_TRANSITION
& VAR_ADDED
)
618 VariableSize
= (UINTN
) NextVariable
- (UINTN
) Variable
;
619 MaximumBufferSize
+= VariableSize
;
622 Variable
= NextVariable
;
626 // Reserve the 1 Bytes with Oxff to identify the
627 // end of the variable buffer.
629 MaximumBufferSize
+= 1;
630 ValidBuffer
= AllocatePool (MaximumBufferSize
);
631 if (ValidBuffer
== NULL
) {
632 return EFI_OUT_OF_RESOURCES
;
635 SetMem (ValidBuffer
, MaximumBufferSize
, 0xff);
638 // Copy variable store header
640 CopyMem (ValidBuffer
, VariableStoreHeader
, sizeof (VARIABLE_STORE_HEADER
));
641 CurrPtr
= (UINT8
*) GetStartPointer ((VARIABLE_STORE_HEADER
*) ValidBuffer
);
644 // Reinstall all ADDED variables as long as they are not identical to Updating Variable
646 Variable
= GetStartPointer (VariableStoreHeader
);
647 while (IsValidVariableHeader (Variable
)) {
648 NextVariable
= GetNextVariablePtr (Variable
);
649 if (Variable
->State
== VAR_ADDED
) {
650 if (UpdatingVariable
!= NULL
) {
651 if (UpdatingVariable
== Variable
) {
652 Variable
= NextVariable
;
656 VariableNameSize
= NameSizeOfVariable(Variable
);
657 UpdatingVariableNameSize
= NameSizeOfVariable(UpdatingVariable
);
659 VariableNamePtr
= GetVariableNamePtr (Variable
);
660 UpdatingVariableNamePtr
= GetVariableNamePtr (UpdatingVariable
);
661 if (CompareGuid (&Variable
->VendorGuid
, &UpdatingVariable
->VendorGuid
) &&
662 VariableNameSize
== UpdatingVariableNameSize
&&
663 CompareMem (VariableNamePtr
, UpdatingVariableNamePtr
, VariableNameSize
) == 0 ) {
664 Variable
= NextVariable
;
668 VariableSize
= (UINTN
) NextVariable
- (UINTN
) Variable
;
669 CopyMem (CurrPtr
, (UINT8
*) Variable
, VariableSize
);
670 CurrPtr
+= VariableSize
;
671 if ((!IsVolatile
) && ((Variable
->Attributes
& EFI_VARIABLE_HARDWARE_ERROR_RECORD
) == EFI_VARIABLE_HARDWARE_ERROR_RECORD
)) {
672 mVariableModuleGlobal
->HwErrVariableTotalSize
+= VariableSize
;
673 } else if ((!IsVolatile
) && ((Variable
->Attributes
& EFI_VARIABLE_HARDWARE_ERROR_RECORD
) != EFI_VARIABLE_HARDWARE_ERROR_RECORD
)) {
674 mVariableModuleGlobal
->CommonVariableTotalSize
+= VariableSize
;
677 Variable
= NextVariable
;
681 // Reinstall the variable being updated if it is not NULL
683 if (UpdatingVariable
!= NULL
) {
684 VariableSize
= (UINTN
)(GetNextVariablePtr (UpdatingVariable
)) - (UINTN
)UpdatingVariable
;
685 CopyMem (CurrPtr
, (UINT8
*) UpdatingVariable
, VariableSize
);
686 CurrPtr
+= VariableSize
;
687 if ((!IsVolatile
) && ((UpdatingVariable
->Attributes
& EFI_VARIABLE_HARDWARE_ERROR_RECORD
) == EFI_VARIABLE_HARDWARE_ERROR_RECORD
)) {
688 mVariableModuleGlobal
->HwErrVariableTotalSize
+= VariableSize
;
689 } else if ((!IsVolatile
) && ((UpdatingVariable
->Attributes
& EFI_VARIABLE_HARDWARE_ERROR_RECORD
) != EFI_VARIABLE_HARDWARE_ERROR_RECORD
)) {
690 mVariableModuleGlobal
->CommonVariableTotalSize
+= VariableSize
;
695 // Reinstall all in delete transition variables
697 Variable
= GetStartPointer (VariableStoreHeader
);
698 while (IsValidVariableHeader (Variable
)) {
699 NextVariable
= GetNextVariablePtr (Variable
);
700 if (Variable
!= UpdatingVariable
&& Variable
->State
== (VAR_IN_DELETED_TRANSITION
& VAR_ADDED
)) {
703 // Buffer has cached all ADDED variable.
704 // Per IN_DELETED variable, we have to guarantee that
705 // no ADDED one in previous buffer.
709 AddedVariable
= GetStartPointer ((VARIABLE_STORE_HEADER
*) ValidBuffer
);
710 while (IsValidVariableHeader (AddedVariable
)) {
711 NextAddedVariable
= GetNextVariablePtr (AddedVariable
);
712 NameSize
= NameSizeOfVariable (AddedVariable
);
713 if (CompareGuid (&AddedVariable
->VendorGuid
, &Variable
->VendorGuid
) &&
714 NameSize
== NameSizeOfVariable (Variable
)
716 Point0
= (VOID
*) GetVariableNamePtr (AddedVariable
);
717 Point1
= (VOID
*) GetVariableNamePtr (Variable
);
718 if (CompareMem (Point0
, Point1
, NameSizeOfVariable (AddedVariable
)) == 0) {
723 AddedVariable
= NextAddedVariable
;
727 // Promote VAR_IN_DELETED_TRANSITION to VAR_ADDED
729 VariableSize
= (UINTN
) NextVariable
- (UINTN
) Variable
;
730 CopyMem (CurrPtr
, (UINT8
*) Variable
, VariableSize
);
731 ((VARIABLE_HEADER
*) CurrPtr
)->State
= VAR_ADDED
;
732 CurrPtr
+= VariableSize
;
733 if ((!IsVolatile
) && ((Variable
->Attributes
& EFI_VARIABLE_HARDWARE_ERROR_RECORD
) == EFI_VARIABLE_HARDWARE_ERROR_RECORD
)) {
734 mVariableModuleGlobal
->HwErrVariableTotalSize
+= VariableSize
;
735 } else if ((!IsVolatile
) && ((Variable
->Attributes
& EFI_VARIABLE_HARDWARE_ERROR_RECORD
) != EFI_VARIABLE_HARDWARE_ERROR_RECORD
)) {
736 mVariableModuleGlobal
->CommonVariableTotalSize
+= VariableSize
;
741 Variable
= NextVariable
;
746 // If volatile variable store, just copy valid buffer
748 SetMem ((UINT8
*) (UINTN
) VariableBase
, VariableStoreHeader
->Size
, 0xff);
749 CopyMem ((UINT8
*) (UINTN
) VariableBase
, ValidBuffer
, (UINTN
) (CurrPtr
- (UINT8
*) ValidBuffer
));
750 Status
= EFI_SUCCESS
;
753 // If non-volatile variable store, perform FTW here.
755 Status
= FtwVariableSpace (
758 (UINTN
) (CurrPtr
- (UINT8
*) ValidBuffer
)
761 if (!EFI_ERROR (Status
)) {
762 *LastVariableOffset
= (UINTN
) (CurrPtr
- (UINT8
*) ValidBuffer
);
764 *LastVariableOffset
= 0;
767 FreePool (ValidBuffer
);
774 Update the Cache with Variable information. These are the same
775 arguments as the EFI Variable services.
777 @param[in] VariableName Name of variable
778 @param[in] VendorGuid Guid of variable
779 @param[in] Attributes Attribues of the variable
780 @param[in] DataSize Size of data. 0 means delete
781 @param[in] Data Variable data
785 UpdateVariableCache (
786 IN CHAR16
*VariableName
,
787 IN EFI_GUID
*VendorGuid
,
788 IN UINT32 Attributes
,
793 VARIABLE_CACHE_ENTRY
*Entry
;
796 if (EfiAtRuntime ()) {
798 // Don't use the cache at runtime
803 for (Index
= 0, Entry
= mVariableCache
; Index
< sizeof (mVariableCache
)/sizeof (VARIABLE_CACHE_ENTRY
); Index
++, Entry
++) {
804 if (CompareGuid (VendorGuid
, Entry
->Guid
)) {
805 if (StrCmp (VariableName
, Entry
->Name
) == 0) {
806 Entry
->Attributes
= Attributes
;
811 if (Entry
->DataSize
!= 0) {
812 FreePool (Entry
->Data
);
814 Entry
->DataSize
= DataSize
;
815 } else if (DataSize
== Entry
->DataSize
) {
816 CopyMem (Entry
->Data
, Data
, DataSize
);
818 Entry
->Data
= AllocatePool (DataSize
);
819 ASSERT (Entry
->Data
!= NULL
);
821 Entry
->DataSize
= DataSize
;
822 CopyMem (Entry
->Data
, Data
, DataSize
);
831 Search the cache to check if the variable is in it.
833 This function searches the variable cache. If the variable to find exists, return its data
836 @param VariableName A Null-terminated Unicode string that is the name of the vendor's
837 variable. Each VariableName is unique for each
839 @param VendorGuid A unique identifier for the vendor
840 @param Attributes Pointer to the attributes bitmask of the variable for output.
841 @param DataSize On input, size of the buffer of Data.
842 On output, size of the variable's data.
843 @param Data Pointer to the data buffer for output.
845 @retval EFI_SUCCESS VariableGuid & VariableName data was returned.
846 @retval EFI_NOT_FOUND No matching variable found in cache.
847 @retval EFI_BUFFER_TOO_SMALL *DataSize is smaller than size of the variable's data to return.
851 FindVariableInCache (
852 IN CHAR16
*VariableName
,
853 IN EFI_GUID
*VendorGuid
,
854 OUT UINT32
*Attributes OPTIONAL
,
855 IN OUT UINTN
*DataSize
,
859 VARIABLE_CACHE_ENTRY
*Entry
;
862 if (EfiAtRuntime ()) {
863 // Don't use the cache at runtime
864 return EFI_NOT_FOUND
;
867 for (Index
= 0, Entry
= mVariableCache
; Index
< sizeof (mVariableCache
)/sizeof (VARIABLE_CACHE_ENTRY
); Index
++, Entry
++) {
868 if (CompareGuid (VendorGuid
, Entry
->Guid
)) {
869 if (StrCmp (VariableName
, Entry
->Name
) == 0) {
870 if (Entry
->DataSize
== 0) {
871 // Variable was deleted so return not found
872 return EFI_NOT_FOUND
;
873 } else if (Entry
->DataSize
> *DataSize
) {
874 // If the buffer is too small return correct size
875 *DataSize
= Entry
->DataSize
;
876 return EFI_BUFFER_TOO_SMALL
;
878 *DataSize
= Entry
->DataSize
;
880 CopyMem (Data
, Entry
->Data
, Entry
->DataSize
);
881 if (Attributes
!= NULL
) {
882 *Attributes
= Entry
->Attributes
;
890 return EFI_NOT_FOUND
;
894 Finds variable in storage blocks of volatile and non-volatile storage areas.
896 This code finds variable in storage blocks of volatile and non-volatile storage areas.
897 If VariableName is an empty string, then we just return the first
898 qualified variable without comparing VariableName and VendorGuid.
899 Otherwise, VariableName and VendorGuid are compared.
901 @param VariableName Name of the variable to be found
902 @param VendorGuid Vendor GUID to be found.
903 @param PtrTrack VARIABLE_POINTER_TRACK structure for output,
904 including the range searched and the target position.
905 @param Global Pointer to VARIABLE_GLOBAL structure, including
906 base of volatile variable storage area, base of
907 NV variable storage area, and a lock.
909 @retval EFI_INVALID_PARAMETER If VariableName is not an empty string, while
911 @retval EFI_SUCCESS Variable successfully found
912 @retval EFI_INVALID_PARAMETER Variable not found
917 IN CHAR16
*VariableName
,
918 IN EFI_GUID
*VendorGuid
,
919 OUT VARIABLE_POINTER_TRACK
*PtrTrack
,
920 IN VARIABLE_GLOBAL
*Global
923 VARIABLE_HEADER
*Variable
[2];
924 VARIABLE_HEADER
*InDeletedVariable
;
925 VARIABLE_STORE_HEADER
*VariableStoreHeader
[2];
926 UINTN InDeletedStorageIndex
;
931 // 0: Volatile, 1: Non-Volatile
932 // The index and attributes mapping must be kept in this order as RuntimeServiceGetNextVariableName
933 // make use of this mapping to implement search algorithme.
935 VariableStoreHeader
[0] = (VARIABLE_STORE_HEADER
*) ((UINTN
) mVariableModuleGlobal
->VariableGlobal
.VolatileVariableBase
);
936 VariableStoreHeader
[1] = (VARIABLE_STORE_HEADER
*) ((UINTN
) mVariableModuleGlobal
->VariableGlobal
.NonVolatileVariableBase
);
939 // Start Pointers for the variable.
940 // Actual Data Pointer where data can be written.
942 Variable
[0] = GetStartPointer (VariableStoreHeader
[0]);
943 Variable
[1] = GetStartPointer (VariableStoreHeader
[1]);
945 if (VariableName
[0] != 0 && VendorGuid
== NULL
) {
946 return EFI_INVALID_PARAMETER
;
950 // Find the variable by walk through volatile and then non-volatile variable store
952 InDeletedVariable
= NULL
;
953 InDeletedStorageIndex
= 0;
954 for (Index
= 0; Index
< 2; Index
++) {
955 while ((Variable
[Index
] < GetEndPointer (VariableStoreHeader
[Index
])) && IsValidVariableHeader (Variable
[Index
])) {
956 if (Variable
[Index
]->State
== VAR_ADDED
||
957 Variable
[Index
]->State
== (VAR_IN_DELETED_TRANSITION
& VAR_ADDED
)
959 if (!EfiAtRuntime () || ((Variable
[Index
]->Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
) != 0)) {
960 if (VariableName
[0] == 0) {
961 if (Variable
[Index
]->State
== (VAR_IN_DELETED_TRANSITION
& VAR_ADDED
)) {
962 InDeletedVariable
= Variable
[Index
];
963 InDeletedStorageIndex
= Index
;
965 PtrTrack
->StartPtr
= GetStartPointer (VariableStoreHeader
[Index
]);
966 PtrTrack
->EndPtr
= GetEndPointer (VariableStoreHeader
[Index
]);
967 PtrTrack
->CurrPtr
= Variable
[Index
];
968 PtrTrack
->Volatile
= (BOOLEAN
)(Index
== 0);
973 if (CompareGuid (VendorGuid
, &Variable
[Index
]->VendorGuid
)) {
974 Point
= (VOID
*) GetVariableNamePtr (Variable
[Index
]);
976 ASSERT (NameSizeOfVariable (Variable
[Index
]) != 0);
977 if (CompareMem (VariableName
, Point
, NameSizeOfVariable (Variable
[Index
])) == 0) {
978 if (Variable
[Index
]->State
== (VAR_IN_DELETED_TRANSITION
& VAR_ADDED
)) {
979 InDeletedVariable
= Variable
[Index
];
980 InDeletedStorageIndex
= Index
;
982 PtrTrack
->StartPtr
= GetStartPointer (VariableStoreHeader
[Index
]);
983 PtrTrack
->EndPtr
= GetEndPointer (VariableStoreHeader
[Index
]);
984 PtrTrack
->CurrPtr
= Variable
[Index
];
985 PtrTrack
->Volatile
= (BOOLEAN
)(Index
== 0);
995 Variable
[Index
] = GetNextVariablePtr (Variable
[Index
]);
997 if (InDeletedVariable
!= NULL
) {
998 PtrTrack
->StartPtr
= GetStartPointer (VariableStoreHeader
[InDeletedStorageIndex
]);
999 PtrTrack
->EndPtr
= GetEndPointer (VariableStoreHeader
[InDeletedStorageIndex
]);
1000 PtrTrack
->CurrPtr
= InDeletedVariable
;
1001 PtrTrack
->Volatile
= (BOOLEAN
)(InDeletedStorageIndex
== 0);
1005 PtrTrack
->CurrPtr
= NULL
;
1006 return EFI_NOT_FOUND
;
1012 This code finds variable in storage blocks (Volatile or Non-Volatile).
1014 @param VariableName Name of Variable to be found.
1015 @param VendorGuid Variable vendor GUID.
1016 @param Attributes Attribute value of the variable found.
1017 @param DataSize Size of Data found. If size is less than the
1018 data, this value contains the required size.
1019 @param Data Data pointer.
1021 @return EFI_INVALID_PARAMETER Invalid parameter
1022 @return EFI_SUCCESS Find the specified variable
1023 @return EFI_NOT_FOUND Not found
1024 @return EFI_BUFFER_TO_SMALL DataSize is too small for the result
1029 RuntimeServiceGetVariable (
1030 IN CHAR16
*VariableName
,
1031 IN EFI_GUID
*VendorGuid
,
1032 OUT UINT32
*Attributes OPTIONAL
,
1033 IN OUT UINTN
*DataSize
,
1038 VARIABLE_POINTER_TRACK Variable
;
1041 if (VariableName
== NULL
|| VendorGuid
== NULL
|| DataSize
== NULL
) {
1042 return EFI_INVALID_PARAMETER
;
1045 AcquireLockOnlyAtBootTime(&mVariableModuleGlobal
->VariableGlobal
.VariableServicesLock
);
1048 // Find existing variable
1050 Status
= FindVariableInCache (VariableName
, VendorGuid
, Attributes
, DataSize
, Data
);
1051 if ((Status
== EFI_BUFFER_TOO_SMALL
) || (Status
== EFI_SUCCESS
)){
1053 UpdateVariableInfo (VariableName
, VendorGuid
, FALSE
, TRUE
, FALSE
, FALSE
, TRUE
);
1057 Status
= FindVariable (VariableName
, VendorGuid
, &Variable
, &mVariableModuleGlobal
->VariableGlobal
);
1058 if (Variable
.CurrPtr
== NULL
|| EFI_ERROR (Status
)) {
1065 VarDataSize
= DataSizeOfVariable (Variable
.CurrPtr
);
1066 ASSERT (VarDataSize
!= 0);
1068 if (*DataSize
>= VarDataSize
) {
1070 Status
= EFI_INVALID_PARAMETER
;
1074 CopyMem (Data
, GetVariableDataPtr (Variable
.CurrPtr
), VarDataSize
);
1075 if (Attributes
!= NULL
) {
1076 *Attributes
= Variable
.CurrPtr
->Attributes
;
1079 *DataSize
= VarDataSize
;
1080 UpdateVariableInfo (VariableName
, VendorGuid
, Variable
.Volatile
, TRUE
, FALSE
, FALSE
, FALSE
);
1081 UpdateVariableCache (VariableName
, VendorGuid
, Variable
.CurrPtr
->Attributes
, VarDataSize
, Data
);
1083 Status
= EFI_SUCCESS
;
1086 *DataSize
= VarDataSize
;
1087 Status
= EFI_BUFFER_TOO_SMALL
;
1092 ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal
->VariableGlobal
.VariableServicesLock
);
1100 This code Finds the Next available variable.
1102 @param VariableNameSize Size of the variable name
1103 @param VariableName Pointer to variable name
1104 @param VendorGuid Variable Vendor Guid
1106 @return EFI_INVALID_PARAMETER Invalid parameter
1107 @return EFI_SUCCESS Find the specified variable
1108 @return EFI_NOT_FOUND Not found
1109 @return EFI_BUFFER_TO_SMALL DataSize is too small for the result
1114 RuntimeServiceGetNextVariableName (
1115 IN OUT UINTN
*VariableNameSize
,
1116 IN OUT CHAR16
*VariableName
,
1117 IN OUT EFI_GUID
*VendorGuid
1120 VARIABLE_POINTER_TRACK Variable
;
1124 if (VariableNameSize
== NULL
|| VariableName
== NULL
|| VendorGuid
== NULL
) {
1125 return EFI_INVALID_PARAMETER
;
1128 AcquireLockOnlyAtBootTime(&mVariableModuleGlobal
->VariableGlobal
.VariableServicesLock
);
1130 Status
= FindVariable (VariableName
, VendorGuid
, &Variable
, &mVariableModuleGlobal
->VariableGlobal
);
1131 if (Variable
.CurrPtr
== NULL
|| EFI_ERROR (Status
)) {
1135 if (VariableName
[0] != 0) {
1137 // If variable name is not NULL, get next variable
1139 Variable
.CurrPtr
= GetNextVariablePtr (Variable
.CurrPtr
);
1144 // If both volatile and non-volatile variable store are parsed,
1147 if (Variable
.CurrPtr
>= Variable
.EndPtr
|| Variable
.CurrPtr
== NULL
) {
1148 Variable
.Volatile
= (BOOLEAN
) (Variable
.Volatile
^ ((BOOLEAN
) 0x1));
1149 if (!Variable
.Volatile
) {
1150 Variable
.StartPtr
= GetStartPointer ((VARIABLE_STORE_HEADER
*) (UINTN
) mVariableModuleGlobal
->VariableGlobal
.NonVolatileVariableBase
);
1151 Variable
.EndPtr
= GetEndPointer ((VARIABLE_STORE_HEADER
*) ((UINTN
) mVariableModuleGlobal
->VariableGlobal
.NonVolatileVariableBase
));
1153 Status
= EFI_NOT_FOUND
;
1157 Variable
.CurrPtr
= Variable
.StartPtr
;
1158 if (!IsValidVariableHeader (Variable
.CurrPtr
)) {
1163 // Variable is found
1165 if (IsValidVariableHeader (Variable
.CurrPtr
) && Variable
.CurrPtr
->State
== VAR_ADDED
) {
1166 if ((EfiAtRuntime () && ((Variable
.CurrPtr
->Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
) == 0)) == 0) {
1167 VarNameSize
= NameSizeOfVariable (Variable
.CurrPtr
);
1168 ASSERT (VarNameSize
!= 0);
1170 if (VarNameSize
<= *VariableNameSize
) {
1173 GetVariableNamePtr (Variable
.CurrPtr
),
1178 &Variable
.CurrPtr
->VendorGuid
,
1181 Status
= EFI_SUCCESS
;
1183 Status
= EFI_BUFFER_TOO_SMALL
;
1186 *VariableNameSize
= VarNameSize
;
1191 Variable
.CurrPtr
= GetNextVariablePtr (Variable
.CurrPtr
);
1195 ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal
->VariableGlobal
.VariableServicesLock
);
1201 This code sets variable in storage blocks (Volatile or Non-Volatile).
1203 @param VariableName Name of Variable to be found
1204 @param VendorGuid Variable vendor GUID
1205 @param Attributes Attribute value of the variable found
1206 @param DataSize Size of Data found. If size is less than the
1207 data, this value contains the required size.
1208 @param Data Data pointer
1210 @return EFI_INVALID_PARAMETER Invalid parameter
1211 @return EFI_SUCCESS Set successfully
1212 @return EFI_OUT_OF_RESOURCES Resource not enough to set variable
1213 @return EFI_NOT_FOUND Not found
1214 @return EFI_WRITE_PROTECTED Variable is read-only
1219 RuntimeServiceSetVariable (
1220 IN CHAR16
*VariableName
,
1221 IN EFI_GUID
*VendorGuid
,
1222 IN UINT32 Attributes
,
1227 VARIABLE_POINTER_TRACK Variable
;
1229 VARIABLE_HEADER
*NextVariable
;
1231 UINTN VarNameOffset
;
1232 UINTN VarDataOffset
;
1236 UINTN
*VolatileOffset
;
1237 UINTN
*NonVolatileOffset
;
1238 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*Fvb
;
1240 EFI_PHYSICAL_ADDRESS Point
;
1242 UINTN NonVolatileVarableStoreSize
;
1245 // Check input parameters
1247 if (VariableName
== NULL
|| VariableName
[0] == 0 || VendorGuid
== NULL
) {
1248 return EFI_INVALID_PARAMETER
;
1251 // Make sure if runtime bit is set, boot service bit is set also
1253 if ((Attributes
& (EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
)) == EFI_VARIABLE_RUNTIME_ACCESS
) {
1254 return EFI_INVALID_PARAMETER
;
1258 // The size of the VariableName, including the Unicode Null in bytes plus
1259 // the DataSize is limited to maximum size of FixedPcdGet32(PcdMaxHardwareErrorVariableSize)
1260 // bytes for HwErrRec, and FixedPcdGet32(PcdMaxVariableSize) bytes for the others.
1262 if ((Attributes
& EFI_VARIABLE_HARDWARE_ERROR_RECORD
) == EFI_VARIABLE_HARDWARE_ERROR_RECORD
) {
1263 if ((DataSize
> FixedPcdGet32(PcdMaxHardwareErrorVariableSize
)) ||
1264 (sizeof (VARIABLE_HEADER
) + StrSize (VariableName
) + DataSize
> FixedPcdGet32(PcdMaxHardwareErrorVariableSize
))) {
1265 return EFI_INVALID_PARAMETER
;
1269 // The size of the VariableName, including the Unicode Null in bytes plus
1270 // the DataSize is limited to maximum size of FixedPcdGet32(PcdMaxVariableSize) bytes.
1272 if ((DataSize
> FixedPcdGet32(PcdMaxVariableSize
)) ||
1273 (sizeof (VARIABLE_HEADER
) + StrSize (VariableName
) + DataSize
> FixedPcdGet32(PcdMaxVariableSize
))) {
1274 return EFI_INVALID_PARAMETER
;
1278 AcquireLockOnlyAtBootTime(&mVariableModuleGlobal
->VariableGlobal
.VariableServicesLock
);
1281 Fvb
= mVariableModuleGlobal
->FvbInstance
;
1282 VolatileOffset
= &mVariableModuleGlobal
->VolatileLastVariableOffset
;
1285 // Consider reentrant in MCA/INIT/NMI. It needs be reupdated;
1287 if (1 < InterlockedIncrement (&mVariableModuleGlobal
->VariableGlobal
.ReentrantState
)) {
1288 Point
= mVariableModuleGlobal
->VariableGlobal
.NonVolatileVariableBase
;;
1290 // Parse non-volatile variable data and get last variable offset
1292 NextVariable
= GetStartPointer ((VARIABLE_STORE_HEADER
*) (UINTN
) Point
);
1293 while (IsValidVariableHeader (NextVariable
)) {
1294 NextVariable
= GetNextVariablePtr (NextVariable
);
1296 mVariableModuleGlobal
->NonVolatileLastVariableOffset
= (UINTN
) NextVariable
- (UINTN
) Point
;
1299 NonVolatileOffset
= &mVariableModuleGlobal
->NonVolatileLastVariableOffset
;
1303 // Check whether the input variable is already existed
1306 Status
= FindVariable (VariableName
, VendorGuid
, &Variable
, &mVariableModuleGlobal
->VariableGlobal
);
1307 if (Status
== EFI_SUCCESS
&& Variable
.CurrPtr
!= NULL
) {
1309 // Update/Delete existing variable
1311 Volatile
= Variable
.Volatile
;
1313 if (EfiAtRuntime ()) {
1315 // If EfiAtRuntime and the variable is Volatile and Runtime Access,
1316 // the volatile is ReadOnly, and SetVariable should be aborted and
1317 // return EFI_WRITE_PROTECTED.
1319 if (Variable
.Volatile
) {
1320 Status
= EFI_WRITE_PROTECTED
;
1324 // Only variable have NV attribute can be updated/deleted in Runtime
1326 if ((Variable
.CurrPtr
->Attributes
& EFI_VARIABLE_NON_VOLATILE
) == 0) {
1327 Status
= EFI_INVALID_PARAMETER
;
1332 // Setting a data variable with no access, or zero DataSize attributes
1333 // specified causes it to be deleted.
1335 if (DataSize
== 0 || (Attributes
& (EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
)) == 0) {
1336 State
= Variable
.CurrPtr
->State
;
1337 State
&= VAR_DELETED
;
1339 Status
= UpdateVariableStore (
1340 &mVariableModuleGlobal
->VariableGlobal
,
1344 (UINTN
) &Variable
.CurrPtr
->State
,
1348 if (!EFI_ERROR (Status
)) {
1349 UpdateVariableInfo (VariableName
, VendorGuid
, Volatile
, FALSE
, FALSE
, TRUE
, FALSE
);
1350 UpdateVariableCache (VariableName
, VendorGuid
, Attributes
, DataSize
, Data
);
1355 // If the variable is marked valid and the same data has been passed in
1356 // then return to the caller immediately.
1358 if (DataSizeOfVariable (Variable
.CurrPtr
) == DataSize
&&
1359 (CompareMem (Data
, GetVariableDataPtr (Variable
.CurrPtr
), DataSize
) == 0)) {
1361 UpdateVariableInfo (VariableName
, VendorGuid
, Volatile
, FALSE
, TRUE
, FALSE
, FALSE
);
1362 Status
= EFI_SUCCESS
;
1364 } else if ((Variable
.CurrPtr
->State
== VAR_ADDED
) ||
1365 (Variable
.CurrPtr
->State
== (VAR_ADDED
& VAR_IN_DELETED_TRANSITION
))) {
1368 // Mark the old variable as in delete transition
1370 State
= Variable
.CurrPtr
->State
;
1371 State
&= VAR_IN_DELETED_TRANSITION
;
1373 Status
= UpdateVariableStore (
1374 &mVariableModuleGlobal
->VariableGlobal
,
1378 (UINTN
) &Variable
.CurrPtr
->State
,
1382 if (EFI_ERROR (Status
)) {
1386 } else if (Status
== EFI_NOT_FOUND
) {
1388 // Create a new variable
1392 // Make sure we are trying to create a new variable.
1393 // Setting a data variable with no access, or zero DataSize attributes means to delete it.
1395 if (DataSize
== 0 || (Attributes
& (EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
)) == 0) {
1396 Status
= EFI_NOT_FOUND
;
1401 // Only variable have NV|RT attribute can be created in Runtime
1403 if (EfiAtRuntime () &&
1404 (((Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
) == 0) || ((Attributes
& EFI_VARIABLE_NON_VOLATILE
) == 0))) {
1405 Status
= EFI_INVALID_PARAMETER
;
1410 // Status should be EFI_INVALID_PARAMETER here according to return status of FindVariable().
1412 ASSERT (Status
== EFI_INVALID_PARAMETER
);
1417 // Function part - create a new variable and copy the data.
1418 // Both update a variable and create a variable will come here.
1420 // Tricky part: Use scratch data area at the end of volatile variable store
1421 // as a temporary storage.
1423 NextVariable
= GetEndPointer ((VARIABLE_STORE_HEADER
*) ((UINTN
) mVariableModuleGlobal
->VariableGlobal
.VolatileVariableBase
));
1424 ScratchSize
= MAX(FixedPcdGet32(PcdMaxVariableSize
), FixedPcdGet32(PcdMaxHardwareErrorVariableSize
));
1426 SetMem (NextVariable
, ScratchSize
, 0xff);
1428 NextVariable
->StartId
= VARIABLE_DATA
;
1429 NextVariable
->Attributes
= Attributes
;
1431 // NextVariable->State = VAR_ADDED;
1433 NextVariable
->Reserved
= 0;
1434 VarNameOffset
= sizeof (VARIABLE_HEADER
);
1435 VarNameSize
= StrSize (VariableName
);
1437 (UINT8
*) ((UINTN
) NextVariable
+ VarNameOffset
),
1441 VarDataOffset
= VarNameOffset
+ VarNameSize
+ GET_PAD_SIZE (VarNameSize
);
1443 (UINT8
*) ((UINTN
) NextVariable
+ VarDataOffset
),
1447 CopyMem (&NextVariable
->VendorGuid
, VendorGuid
, sizeof (EFI_GUID
));
1449 // There will be pad bytes after Data, the NextVariable->NameSize and
1450 // NextVariable->DataSize should not include pad size so that variable
1451 // service can get actual size in GetVariable
1453 NextVariable
->NameSize
= (UINT32
)VarNameSize
;
1454 NextVariable
->DataSize
= (UINT32
)DataSize
;
1457 // The actual size of the variable that stores in storage should
1458 // include pad size.
1460 VarSize
= VarDataOffset
+ DataSize
+ GET_PAD_SIZE (DataSize
);
1461 if ((Attributes
& EFI_VARIABLE_NON_VOLATILE
) != 0) {
1463 // Create a nonvolatile variable
1466 NonVolatileVarableStoreSize
= ((VARIABLE_STORE_HEADER
*)(UINTN
)(mVariableModuleGlobal
->VariableGlobal
.NonVolatileVariableBase
))->Size
;
1467 if ((((Attributes
& EFI_VARIABLE_HARDWARE_ERROR_RECORD
) != 0)
1468 && ((VarSize
+ mVariableModuleGlobal
->HwErrVariableTotalSize
) > FixedPcdGet32(PcdHwErrStorageSize
)))
1469 || (((Attributes
& EFI_VARIABLE_HARDWARE_ERROR_RECORD
) == 0)
1470 && ((VarSize
+ mVariableModuleGlobal
->CommonVariableTotalSize
) > NonVolatileVarableStoreSize
- sizeof (VARIABLE_STORE_HEADER
) - FixedPcdGet32(PcdHwErrStorageSize
)))) {
1471 if (EfiAtRuntime ()) {
1472 Status
= EFI_OUT_OF_RESOURCES
;
1476 // Perform garbage collection & reclaim operation
1478 Status
= Reclaim (mVariableModuleGlobal
->VariableGlobal
.NonVolatileVariableBase
, NonVolatileOffset
, FALSE
, Variable
.CurrPtr
);
1479 if (EFI_ERROR (Status
)) {
1483 // If still no enough space, return out of resources
1485 if ((((Attributes
& EFI_VARIABLE_HARDWARE_ERROR_RECORD
) != 0)
1486 && ((VarSize
+ mVariableModuleGlobal
->HwErrVariableTotalSize
) > FixedPcdGet32(PcdHwErrStorageSize
)))
1487 || (((Attributes
& EFI_VARIABLE_HARDWARE_ERROR_RECORD
) == 0)
1488 && ((VarSize
+ mVariableModuleGlobal
->CommonVariableTotalSize
) > NonVolatileVarableStoreSize
- sizeof (VARIABLE_STORE_HEADER
) - FixedPcdGet32(PcdHwErrStorageSize
)))) {
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
);
1572 if ((Attributes
& EFI_VARIABLE_HARDWARE_ERROR_RECORD
) != 0) {
1573 mVariableModuleGlobal
->HwErrVariableTotalSize
+= HEADER_ALIGN (VarSize
);
1575 mVariableModuleGlobal
->CommonVariableTotalSize
+= HEADER_ALIGN (VarSize
);
1579 // Create a volatile variable
1583 if ((UINT32
) (VarSize
+*VolatileOffset
) >
1584 ((VARIABLE_STORE_HEADER
*) ((UINTN
) (mVariableModuleGlobal
->VariableGlobal
.VolatileVariableBase
)))->Size
) {
1586 // Perform garbage collection & reclaim operation
1588 Status
= Reclaim (mVariableModuleGlobal
->VariableGlobal
.VolatileVariableBase
, VolatileOffset
, TRUE
, Variable
.CurrPtr
);
1589 if (EFI_ERROR (Status
)) {
1593 // If still no enough space, return out of resources
1595 if ((UINT32
) (VarSize
+*VolatileOffset
) >
1596 ((VARIABLE_STORE_HEADER
*) ((UINTN
) (mVariableModuleGlobal
->VariableGlobal
.VolatileVariableBase
)))->Size
1598 Status
= EFI_OUT_OF_RESOURCES
;
1605 NextVariable
->State
= VAR_ADDED
;
1606 Status
= UpdateVariableStore (
1607 &mVariableModuleGlobal
->VariableGlobal
,
1613 (UINT8
*) NextVariable
1616 if (EFI_ERROR (Status
)) {
1620 *VolatileOffset
= HEADER_ALIGN (*VolatileOffset
+ VarSize
);
1623 // Mark the old variable as deleted
1625 if (!Reclaimed
&& !EFI_ERROR (Status
) && Variable
.CurrPtr
!= NULL
) {
1626 State
= Variable
.CurrPtr
->State
;
1627 State
&= VAR_DELETED
;
1629 Status
= UpdateVariableStore (
1630 &mVariableModuleGlobal
->VariableGlobal
,
1634 (UINTN
) &Variable
.CurrPtr
->State
,
1639 if (!EFI_ERROR (Status
)) {
1640 UpdateVariableInfo (VariableName
, VendorGuid
, Volatile
, FALSE
, TRUE
, FALSE
, FALSE
);
1641 UpdateVariableCache (VariableName
, VendorGuid
, Attributes
, DataSize
, Data
);
1646 Status
= EFI_SUCCESS
;
1647 UpdateVariableInfo (VariableName
, VendorGuid
, Volatile
, FALSE
, TRUE
, FALSE
, FALSE
);
1648 UpdateVariableCache (VariableName
, VendorGuid
, Attributes
, DataSize
, Data
);
1651 InterlockedDecrement (&mVariableModuleGlobal
->VariableGlobal
.ReentrantState
);
1652 ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal
->VariableGlobal
.VariableServicesLock
);
1659 This code returns information about the EFI variables.
1661 @param Attributes Attributes bitmask to specify the type of variables
1662 on which to return information.
1663 @param MaximumVariableStorageSize Pointer to the maximum size of the storage space available
1664 for the EFI variables associated with the attributes specified.
1665 @param RemainingVariableStorageSize Pointer to the remaining size of the storage space available
1666 for EFI variables associated with the attributes specified.
1667 @param MaximumVariableSize Pointer to the maximum size of an individual EFI variables
1668 associated with the attributes specified.
1670 @return EFI_INVALID_PARAMETER An invalid combination of attribute bits was supplied.
1671 @return EFI_SUCCESS Query successfully.
1672 @return EFI_UNSUPPORTED The attribute is not supported on this platform.
1677 RuntimeServiceQueryVariableInfo (
1678 IN UINT32 Attributes
,
1679 OUT UINT64
*MaximumVariableStorageSize
,
1680 OUT UINT64
*RemainingVariableStorageSize
,
1681 OUT UINT64
*MaximumVariableSize
1684 VARIABLE_HEADER
*Variable
;
1685 VARIABLE_HEADER
*NextVariable
;
1686 UINT64 VariableSize
;
1687 VARIABLE_STORE_HEADER
*VariableStoreHeader
;
1688 UINT64 CommonVariableTotalSize
;
1689 UINT64 HwErrVariableTotalSize
;
1691 CommonVariableTotalSize
= 0;
1692 HwErrVariableTotalSize
= 0;
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
) == 0)) {
1710 // Make sure RT Attribute is set if we are in Runtime phase.
1712 return EFI_INVALID_PARAMETER
;
1713 } else if ((Attributes
& (EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_HARDWARE_ERROR_RECORD
)) == EFI_VARIABLE_HARDWARE_ERROR_RECORD
) {
1715 // Make sure Hw Attribute is set with NV.
1717 return EFI_INVALID_PARAMETER
;
1720 AcquireLockOnlyAtBootTime(&mVariableModuleGlobal
->VariableGlobal
.VariableServicesLock
);
1722 if((Attributes
& EFI_VARIABLE_NON_VOLATILE
) == 0) {
1724 // Query is Volatile related.
1726 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) ((UINTN
) mVariableModuleGlobal
->VariableGlobal
.VolatileVariableBase
);
1729 // Query is Non-Volatile related.
1731 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) ((UINTN
) mVariableModuleGlobal
->VariableGlobal
.NonVolatileVariableBase
);
1735 // Now let's fill *MaximumVariableStorageSize *RemainingVariableStorageSize
1736 // with the storage size (excluding the storage header size).
1738 *MaximumVariableStorageSize
= VariableStoreHeader
->Size
- sizeof (VARIABLE_STORE_HEADER
);
1741 // Harware error record variable needs larger size.
1743 if ((Attributes
& (EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_HARDWARE_ERROR_RECORD
)) == (EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_HARDWARE_ERROR_RECORD
)) {
1744 *MaximumVariableStorageSize
= FixedPcdGet32(PcdHwErrStorageSize
);
1745 *MaximumVariableSize
= FixedPcdGet32(PcdMaxHardwareErrorVariableSize
) - sizeof (VARIABLE_HEADER
);
1747 if ((Attributes
& EFI_VARIABLE_NON_VOLATILE
) != 0) {
1748 ASSERT (FixedPcdGet32(PcdHwErrStorageSize
) < VariableStoreHeader
->Size
);
1749 *MaximumVariableStorageSize
= VariableStoreHeader
->Size
- sizeof (VARIABLE_STORE_HEADER
) - FixedPcdGet32(PcdHwErrStorageSize
);
1753 // Let *MaximumVariableSize be FixedPcdGet32(PcdMaxVariableSize) with the exception of the variable header size.
1755 *MaximumVariableSize
= FixedPcdGet32(PcdMaxVariableSize
) - sizeof (VARIABLE_HEADER
);
1759 // Point to the starting address of the variables.
1761 Variable
= GetStartPointer (VariableStoreHeader
);
1764 // Now walk through the related variable store.
1766 while ((Variable
< GetEndPointer (VariableStoreHeader
)) && IsValidVariableHeader (Variable
)) {
1767 NextVariable
= GetNextVariablePtr (Variable
);
1768 VariableSize
= (UINT64
) (UINTN
) NextVariable
- (UINT64
) (UINTN
) Variable
;
1770 if (EfiAtRuntime ()) {
1772 // we don't take the state of the variables in mind
1773 // when calculating RemainingVariableStorageSize,
1774 // since the space occupied by variables not marked with
1775 // VAR_ADDED is not allowed to be reclaimed in Runtime.
1777 if ((NextVariable
->Attributes
& EFI_VARIABLE_HARDWARE_ERROR_RECORD
) == EFI_VARIABLE_HARDWARE_ERROR_RECORD
) {
1778 HwErrVariableTotalSize
+= VariableSize
;
1780 CommonVariableTotalSize
+= VariableSize
;
1784 // Only care about Variables with State VAR_ADDED,because
1785 // the space not marked as VAR_ADDED is reclaimable now.
1787 if (Variable
->State
== VAR_ADDED
) {
1788 if ((NextVariable
->Attributes
& EFI_VARIABLE_HARDWARE_ERROR_RECORD
) == EFI_VARIABLE_HARDWARE_ERROR_RECORD
) {
1789 HwErrVariableTotalSize
+= VariableSize
;
1791 CommonVariableTotalSize
+= VariableSize
;
1797 // Go to the next one
1799 Variable
= NextVariable
;
1802 if ((Attributes
& EFI_VARIABLE_HARDWARE_ERROR_RECORD
) == EFI_VARIABLE_HARDWARE_ERROR_RECORD
){
1803 *RemainingVariableStorageSize
= *MaximumVariableStorageSize
- HwErrVariableTotalSize
;
1805 *RemainingVariableStorageSize
= *MaximumVariableStorageSize
- CommonVariableTotalSize
;
1808 if (*RemainingVariableStorageSize
< sizeof (VARIABLE_HEADER
)) {
1809 *MaximumVariableSize
= 0;
1810 } else if ((*RemainingVariableStorageSize
- sizeof (VARIABLE_HEADER
)) < *MaximumVariableSize
) {
1811 *MaximumVariableSize
= *RemainingVariableStorageSize
- sizeof (VARIABLE_HEADER
);
1814 ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal
->VariableGlobal
.VariableServicesLock
);
1820 Notification function of EVT_GROUP_READY_TO_BOOT event group.
1822 This is a notification function registered on EVT_GROUP_READY_TO_BOOT event group.
1823 When the Boot Manager is about to load and execute a boot option, it reclaims variable
1824 storage if free size is below the threshold.
1826 @param Event Event whose notification function is being invoked
1827 @param Context Pointer to the notification function's context
1838 UINTN CommonVariableSpace
;
1839 UINTN RemainingCommonVariableSpace
;
1840 UINTN RemainingHwErrVariableSpace
;
1842 Status
= EFI_SUCCESS
;
1844 CommonVariableSpace
= ((VARIABLE_STORE_HEADER
*) ((UINTN
) (mVariableModuleGlobal
->VariableGlobal
.NonVolatileVariableBase
)))->Size
- sizeof (VARIABLE_STORE_HEADER
) - PcdGet32(PcdHwErrStorageSize
); //Allowable max size of common variable storage space
1846 RemainingCommonVariableSpace
= CommonVariableSpace
- mVariableModuleGlobal
->CommonVariableTotalSize
;
1848 RemainingHwErrVariableSpace
= PcdGet32 (PcdHwErrStorageSize
) - mVariableModuleGlobal
->HwErrVariableTotalSize
;
1850 // Check if the free area is blow a threshold
1852 if ((RemainingCommonVariableSpace
< PcdGet32 (PcdMaxVariableSize
))
1853 || (RemainingHwErrVariableSpace
< PcdGet32 (PcdMaxHardwareErrorVariableSize
))){
1855 mVariableModuleGlobal
->VariableGlobal
.NonVolatileVariableBase
,
1856 &mVariableModuleGlobal
->NonVolatileLastVariableOffset
,
1860 ASSERT_EFI_ERROR (Status
);
1865 Initializes variable store area for non-volatile and volatile variable.
1867 @param SystemTable The pointer of EFI_SYSTEM_TABLE.
1869 @retval EFI_SUCCESS Function successfully executed.
1870 @retval EFI_OUT_OF_RESOURCES Fail to allocate enough memory resource.
1874 VariableCommonInitialize (
1875 IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*FvbProtocol
1879 VARIABLE_STORE_HEADER
*VolatileVariableStore
;
1880 VARIABLE_STORE_HEADER
*VariableStoreHeader
;
1881 VARIABLE_HEADER
*NextVariable
;
1882 EFI_PHYSICAL_ADDRESS TempVariableStoreHeader
;
1883 EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor
;
1884 EFI_PHYSICAL_ADDRESS BaseAddress
;
1888 EFI_PHYSICAL_ADDRESS VariableStoreBase
;
1889 UINT64 VariableStoreLength
;
1890 EFI_EVENT ReadyToBootEvent
;
1893 Status
= EFI_SUCCESS
;
1895 // Allocate runtime memory for variable driver global structure.
1897 mVariableModuleGlobal
= AllocateRuntimePool (sizeof (VARIABLE_MODULE_GLOBAL
));
1898 if (mVariableModuleGlobal
== NULL
) {
1899 return EFI_OUT_OF_RESOURCES
;
1902 EfiInitializeLock(&mVariableModuleGlobal
->VariableGlobal
.VariableServicesLock
, TPL_NOTIFY
);
1903 mVariableModuleGlobal
->VariableGlobal
.ReentrantState
= 0;
1904 mVariableModuleGlobal
->CommonVariableTotalSize
= 0;
1905 mVariableModuleGlobal
->HwErrVariableTotalSize
= 0;
1908 // Allocate memory for volatile variable store, note that there is a scratch space to store scratch data.
1910 ScratchSize
= MAX(FixedPcdGet32(PcdMaxVariableSize
), FixedPcdGet32(PcdMaxHardwareErrorVariableSize
));
1911 VolatileVariableStore
= AllocateRuntimePool (FixedPcdGet32(PcdVariableStoreSize
) + ScratchSize
);
1912 if (VolatileVariableStore
== NULL
) {
1913 FreePool (mVariableModuleGlobal
);
1914 return EFI_OUT_OF_RESOURCES
;
1917 SetMem (VolatileVariableStore
, FixedPcdGet32(PcdVariableStoreSize
) + ScratchSize
, 0xff);
1920 // Variable Specific Data
1922 mVariableModuleGlobal
->VariableGlobal
.VolatileVariableBase
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) VolatileVariableStore
;
1923 mVariableModuleGlobal
->VolatileLastVariableOffset
= (UINTN
) GetStartPointer (VolatileVariableStore
) - (UINTN
) VolatileVariableStore
;
1924 mVariableModuleGlobal
->FvbInstance
= FvbProtocol
;
1926 CopyGuid (&VolatileVariableStore
->Signature
, &gEfiVariableGuid
);
1927 VolatileVariableStore
->Size
= FixedPcdGet32(PcdVariableStoreSize
);
1928 VolatileVariableStore
->Format
= VARIABLE_STORE_FORMATTED
;
1929 VolatileVariableStore
->State
= VARIABLE_STORE_HEALTHY
;
1930 VolatileVariableStore
->Reserved
= 0;
1931 VolatileVariableStore
->Reserved1
= 0;
1934 // Get non volatile varaible store
1937 TempVariableStoreHeader
= (EFI_PHYSICAL_ADDRESS
) PcdGet32 (PcdFlashNvStorageVariableBase
);
1938 VariableStoreBase
= TempVariableStoreHeader
+ \
1939 (((EFI_FIRMWARE_VOLUME_HEADER
*)(UINTN
)(TempVariableStoreHeader
)) -> HeaderLength
);
1940 VariableStoreLength
= (UINT64
) PcdGet32 (PcdFlashNvStorageVariableSize
) - \
1941 (((EFI_FIRMWARE_VOLUME_HEADER
*)(UINTN
)(TempVariableStoreHeader
)) -> HeaderLength
);
1943 // Mark the variable storage region of the FLASH as RUNTIME
1945 BaseAddress
= VariableStoreBase
& (~EFI_PAGE_MASK
);
1946 Length
= VariableStoreLength
+ (VariableStoreBase
- BaseAddress
);
1947 Length
= (Length
+ EFI_PAGE_SIZE
- 1) & (~EFI_PAGE_MASK
);
1949 Status
= gDS
->GetMemorySpaceDescriptor (BaseAddress
, &GcdDescriptor
);
1950 if (EFI_ERROR (Status
)) {
1954 Status
= gDS
->SetMemorySpaceAttributes (
1957 GcdDescriptor
.Attributes
| EFI_MEMORY_RUNTIME
1959 if (EFI_ERROR (Status
)) {
1963 // Get address of non volatile variable store base
1965 mVariableModuleGlobal
->VariableGlobal
.NonVolatileVariableBase
= VariableStoreBase
;
1966 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*)(UINTN
)VariableStoreBase
;
1967 if (GetVariableStoreStatus (VariableStoreHeader
) == EfiValid
) {
1968 if (~VariableStoreHeader
->Size
== 0) {
1969 Status
= UpdateVariableStore (
1970 &mVariableModuleGlobal
->VariableGlobal
,
1973 mVariableModuleGlobal
->FvbInstance
,
1974 (UINTN
) &VariableStoreHeader
->Size
,
1976 (UINT8
*) &VariableStoreLength
1979 // As Variables are stored in NV storage, which are slow devices,such as flash.
1980 // Variable operation may skip checking variable program result to improve performance,
1981 // We can assume Variable program is OK through some check point.
1982 // Variable Store Size Setting should be the first Variable write operation,
1983 // We can assume all Read/Write is OK if we can set Variable store size successfully.
1984 // If write fail, we will assert here
1986 ASSERT(VariableStoreHeader
->Size
== VariableStoreLength
);
1988 if (EFI_ERROR (Status
)) {
1994 // Parse non-volatile variable data and get last variable offset
1996 NextVariable
= GetStartPointer ((VARIABLE_STORE_HEADER
*)(UINTN
)VariableStoreBase
);
1997 Status
= EFI_SUCCESS
;
1999 while (IsValidVariableHeader (NextVariable
)) {
2000 UINTN VariableSize
= 0;
2001 VariableSize
= NextVariable
->NameSize
+ NextVariable
->DataSize
+ sizeof (VARIABLE_HEADER
);
2002 if ((NextVariable
->Attributes
& (EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_HARDWARE_ERROR_RECORD
)) == (EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_HARDWARE_ERROR_RECORD
)) {
2003 mVariableModuleGlobal
->HwErrVariableTotalSize
+= HEADER_ALIGN (VariableSize
);
2005 mVariableModuleGlobal
->CommonVariableTotalSize
+= HEADER_ALIGN (VariableSize
);
2008 NextVariable
= GetNextVariablePtr (NextVariable
);
2011 mVariableModuleGlobal
->NonVolatileLastVariableOffset
= (UINTN
) NextVariable
- (UINTN
) VariableStoreBase
;
2014 // Check if the free area is really free.
2016 for (Index
= mVariableModuleGlobal
->NonVolatileLastVariableOffset
; Index
< VariableStoreHeader
->Size
; Index
++) {
2017 Data
= ((UINT8
*) (UINTN
) mVariableModuleGlobal
->VariableGlobal
.NonVolatileVariableBase
)[Index
];
2020 // There must be something wrong in variable store, do reclaim operation.
2023 mVariableModuleGlobal
->VariableGlobal
.NonVolatileVariableBase
,
2024 &mVariableModuleGlobal
->NonVolatileLastVariableOffset
,
2029 if (EFI_ERROR (Status
)) {
2038 // Register the event handling function to reclaim variable for OS usage.
2040 Status
= EfiCreateEventReadyToBootEx (
2047 Status
= EFI_VOLUME_CORRUPTED
;
2048 DEBUG((EFI_D_INFO
, "Variable Store header is corrupted\n"));
2052 if (EFI_ERROR (Status
)) {
2053 FreePool (mVariableModuleGlobal
);
2054 FreePool (VolatileVariableStore
);
2061 Notification function of EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE
2063 This is a notification function registered on EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.
2064 It convers pointer to new virtual address.
2066 @param Event Event whose notification function is being invoked
2067 @param Context Pointer to the notification function's context
2072 VariableClassAddressChangeEvent (
2077 EfiConvertPointer (0x0, (VOID
**) &mVariableModuleGlobal
->FvbInstance
->GetBlockSize
);
2078 EfiConvertPointer (0x0, (VOID
**) &mVariableModuleGlobal
->FvbInstance
->GetPhysicalAddress
);
2079 EfiConvertPointer (0x0, (VOID
**) &mVariableModuleGlobal
->FvbInstance
->GetAttributes
);
2080 EfiConvertPointer (0x0, (VOID
**) &mVariableModuleGlobal
->FvbInstance
->SetAttributes
);
2081 EfiConvertPointer (0x0, (VOID
**) &mVariableModuleGlobal
->FvbInstance
->Read
);
2082 EfiConvertPointer (0x0, (VOID
**) &mVariableModuleGlobal
->FvbInstance
->Write
);
2083 EfiConvertPointer (0x0, (VOID
**) &mVariableModuleGlobal
->FvbInstance
->EraseBlocks
);
2084 EfiConvertPointer (0x0, (VOID
**) &mVariableModuleGlobal
->FvbInstance
);
2087 (VOID
**) &mVariableModuleGlobal
->VariableGlobal
.NonVolatileVariableBase
2091 (VOID
**) &mVariableModuleGlobal
->VariableGlobal
.VolatileVariableBase
2093 EfiConvertPointer (0x0, (VOID
**) &mVariableModuleGlobal
);
2098 FvbNotificationEvent (
2104 EFI_HANDLE
*HandleBuffer
;
2107 EFI_PHYSICAL_ADDRESS FvbBaseAddress
;
2108 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*Fvb
;
2109 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
2110 EFI_FVB_ATTRIBUTES_2 Attributes
;
2111 EFI_SYSTEM_TABLE
*SystemTable
;
2112 EFI_PHYSICAL_ADDRESS NvStorageVariableBase
;
2114 SystemTable
= (EFI_SYSTEM_TABLE
*)Context
;
2118 // Locate all handles of Fvb protocol
2120 Status
= gBS
->LocateHandleBuffer (
2122 &gEfiFirmwareVolumeBlockProtocolGuid
,
2127 if (EFI_ERROR (Status
)) {
2132 // Get the FVB to access variable store
2134 for (Index
= 0; Index
< HandleCount
; Index
+= 1, Status
= EFI_NOT_FOUND
, Fvb
= NULL
) {
2135 Status
= gBS
->HandleProtocol (
2136 HandleBuffer
[Index
],
2137 &gEfiFirmwareVolumeBlockProtocolGuid
,
2140 if (EFI_ERROR (Status
)) {
2141 Status
= EFI_NOT_FOUND
;
2146 // Ensure this FVB protocol supported Write operation.
2148 Status
= Fvb
->GetAttributes (Fvb
, &Attributes
);
2149 if (EFI_ERROR (Status
) || ((Attributes
& EFI_FVB2_WRITE_STATUS
) == 0)) {
2153 // Compare the address and select the right one
2155 Status
= Fvb
->GetPhysicalAddress (Fvb
, &FvbBaseAddress
);
2156 if (EFI_ERROR (Status
)) {
2160 FwVolHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) ((UINTN
) FvbBaseAddress
);
2161 NvStorageVariableBase
= (EFI_PHYSICAL_ADDRESS
) PcdGet32 (PcdFlashNvStorageVariableBase
);
2162 if ((NvStorageVariableBase
>= FvbBaseAddress
) && (NvStorageVariableBase
< (FvbBaseAddress
+ FwVolHeader
->FvLength
))) {
2163 Status
= EFI_SUCCESS
;
2168 FreePool (HandleBuffer
);
2169 if (!EFI_ERROR (Status
) && Fvb
!= NULL
) {
2171 // Close the notify event to avoid install gEfiVariableArchProtocolGuid & gEfiVariableWriteArchProtocolGuid again.
2173 Status
= gBS
->CloseEvent (Event
);
2174 ASSERT_EFI_ERROR (Status
);
2176 Status
= VariableCommonInitialize (Fvb
);
2177 ASSERT_EFI_ERROR (Status
);
2179 SystemTable
->RuntimeServices
->GetVariable
= RuntimeServiceGetVariable
;
2180 SystemTable
->RuntimeServices
->GetNextVariableName
= RuntimeServiceGetNextVariableName
;
2181 SystemTable
->RuntimeServices
->SetVariable
= RuntimeServiceSetVariable
;
2182 SystemTable
->RuntimeServices
->QueryVariableInfo
= RuntimeServiceQueryVariableInfo
;
2185 // Now install the Variable Runtime Architectural Protocol on a new handle
2187 Status
= gBS
->InstallMultipleProtocolInterfaces (
2189 &gEfiVariableArchProtocolGuid
, NULL
,
2190 &gEfiVariableWriteArchProtocolGuid
, NULL
,
2193 ASSERT_EFI_ERROR (Status
);
2195 Status
= gBS
->CreateEventEx (
2198 VariableClassAddressChangeEvent
,
2200 &gEfiEventVirtualAddressChangeGuid
,
2201 &mVirtualAddressChangeEvent
2203 ASSERT_EFI_ERROR (Status
);
2209 Variable Driver main entry point. The Variable driver places the 4 EFI
2210 runtime services in the EFI System Table and installs arch protocols
2211 for variable read and write services being availible. It also registers
2212 notification function for EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.
2214 @param[in] ImageHandle The firmware allocated handle for the EFI image.
2215 @param[in] SystemTable A pointer to the EFI System Table.
2217 @retval EFI_SUCCESS Variable service successfully initialized.
2222 VariableServiceInitialize (
2223 IN EFI_HANDLE ImageHandle
,
2224 IN EFI_SYSTEM_TABLE
*SystemTable
2228 // Register FvbNotificationEvent () notify function.
2230 EfiCreateProtocolNotifyEvent (
2231 &gEfiFirmwareVolumeBlockProtocolGuid
,
2233 FvbNotificationEvent
,
2234 (VOID
*)SystemTable
,