3 Copyright (c) 2006 - 2007, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
26 // Don't use module globals after the SetVirtualAddress map is signaled
28 ESAL_VARIABLE_GLOBAL
*mVariableModuleGlobal
;
31 // This is a temperary function which will be removed
32 // when EfiAcquireLock in UefiLib can handle the
33 // the call in UEFI Runtimer driver in RT phase.
37 AcquireLockOnlyAtBootTime (
41 if (!EfiAtRuntime ()) {
42 EfiAcquireLock (Lock
);
47 // This is a temperary function which will be removed
48 // when EfiAcquireLock in UefiLib can handle the
49 // the call in UEFI Runtimer driver in RT phase.
53 ReleaseLockOnlyAtBootTime (
57 if (!EfiAtRuntime ()) {
58 EfiReleaseLock (Lock
);
65 IsValidVariableHeader (
66 IN VARIABLE_HEADER
*Variable
72 This code checks if variable header is valid or not.
75 Variable Pointer to the Variable Header.
78 TRUE Variable header is valid.
79 FALSE Variable header is not valid.
83 if (Variable
== NULL
||
84 Variable
->StartId
!= VARIABLE_DATA
||
85 (sizeof (VARIABLE_HEADER
) + Variable
->NameSize
+ Variable
->DataSize
) > MAX_VARIABLE_SIZE
97 IN VARIABLE_GLOBAL
*Global
,
99 IN BOOLEAN SetByIndex
,
101 IN UINTN DataPtrIndex
,
109 This function writes data to the FWH at the correct LBA even if the LBAs
114 Global Pointer to VARAIBLE_GLOBAL structure
115 Volatile If the Variable is Volatile or Non-Volatile
116 SetByIndex TRUE: Target pointer is given as index
117 FALSE: Target pointer is absolute
118 Instance Instance of FV Block services
119 DataPtrIndex Pointer to the Data from the end of VARIABLE_STORE_HEADER
121 DataSize Size of data to be written.
122 Buffer Pointer to the buffer from which data is written
130 EFI_FV_BLOCK_MAP_ENTRY
*PtrBlockMapEntry
;
138 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
139 VARIABLE_STORE_HEADER
*VolatileBase
;
140 EFI_PHYSICAL_ADDRESS FvVolHdr
;
141 EFI_PHYSICAL_ADDRESS DataPtr
;
145 DataPtr
= DataPtrIndex
;
148 // Check if the Data is Volatile
151 EfiFvbGetPhysicalAddress (Instance
, &FvVolHdr
);
152 FwVolHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) ((UINTN
) FvVolHdr
);
154 // Data Pointer should point to the actual Address where data is to be
158 DataPtr
+= Global
->NonVolatileVariableBase
;
161 if ((DataPtr
+ DataSize
) >= ((EFI_PHYSICAL_ADDRESS
) (UINTN
) ((UINT8
*) FwVolHeader
+ FwVolHeader
->FvLength
))) {
162 return EFI_INVALID_PARAMETER
;
166 // Data Pointer should point to the actual Address where data is to be
169 VolatileBase
= (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->VolatileVariableBase
);
171 DataPtr
+= Global
->VolatileVariableBase
;
174 if ((DataPtr
+ DataSize
) >= ((UINTN
) ((UINT8
*) VolatileBase
+ VolatileBase
->Size
))) {
175 return EFI_INVALID_PARAMETER
;
179 // If Volatile Variable just do a simple mem copy.
182 CopyMem ((UINT8
*) ((UINTN
) DataPtr
), Buffer
, DataSize
);
186 // If we are here we are dealing with Non-Volatile Variables
188 LinearOffset
= (UINTN
) FwVolHeader
;
189 CurrWritePtr
= (UINTN
) DataPtr
;
190 CurrWriteSize
= DataSize
;
194 if (CurrWritePtr
< LinearOffset
) {
195 return EFI_INVALID_PARAMETER
;
198 for (PtrBlockMapEntry
= FwVolHeader
->FvBlockMap
; PtrBlockMapEntry
->NumBlocks
!= 0; PtrBlockMapEntry
++) {
199 for (BlockIndex2
= 0; BlockIndex2
< PtrBlockMapEntry
->NumBlocks
; BlockIndex2
++) {
201 // Check to see if the Variable Writes are spanning through multiple
204 if ((CurrWritePtr
>= LinearOffset
) && (CurrWritePtr
< LinearOffset
+ PtrBlockMapEntry
->BlockLength
)) {
205 if ((CurrWritePtr
+ CurrWriteSize
) <= (LinearOffset
+ PtrBlockMapEntry
->BlockLength
)) {
206 Status
= EfiFvbWriteBlock (
209 (UINTN
) (CurrWritePtr
- LinearOffset
),
213 if (EFI_ERROR (Status
)) {
217 Size
= (UINT32
) (LinearOffset
+ PtrBlockMapEntry
->BlockLength
- CurrWritePtr
);
218 Status
= EfiFvbWriteBlock (
221 (UINTN
) (CurrWritePtr
- LinearOffset
),
225 if (EFI_ERROR (Status
)) {
229 CurrWritePtr
= LinearOffset
+ PtrBlockMapEntry
->BlockLength
;
230 CurrBuffer
= CurrBuffer
+ Size
;
231 CurrWriteSize
= CurrWriteSize
- Size
;
235 LinearOffset
+= PtrBlockMapEntry
->BlockLength
;
244 VARIABLE_STORE_STATUS
246 GetVariableStoreStatus (
247 IN VARIABLE_STORE_HEADER
*VarStoreHeader
253 This code gets the current status of Variable Store.
257 VarStoreHeader Pointer to the Variable Store Header.
261 EfiRaw Variable store status is raw
262 EfiValid Variable store status is valid
263 EfiInvalid Variable store status is invalid
267 if (VarStoreHeader
->Signature
== VARIABLE_STORE_SIGNATURE
&&
268 VarStoreHeader
->Format
== VARIABLE_STORE_FORMATTED
&&
269 VarStoreHeader
->State
== VARIABLE_STORE_HEALTHY
273 } else if (VarStoreHeader
->Signature
== 0xffffffff &&
274 VarStoreHeader
->Size
== 0xffffffff &&
275 VarStoreHeader
->Format
== 0xff &&
276 VarStoreHeader
->State
== 0xff
289 IN VARIABLE_HEADER
*Variable
295 This code gets the pointer to the variable data.
299 Variable Pointer to the Variable Header.
303 UINT8* Pointer to Variable Data
308 // Be careful about pad size for alignment
310 return (UINT8
*) ((UINTN
) GET_VARIABLE_NAME_PTR (Variable
) + Variable
->NameSize
+ GET_PAD_SIZE (Variable
->NameSize
));
317 IN VARIABLE_HEADER
*Variable
323 This code gets the pointer to the next variable header.
327 Variable Pointer to the Variable Header.
331 VARIABLE_HEADER* Pointer to next variable header.
335 if (!IsValidVariableHeader (Variable
)) {
339 // Be careful about pad size for alignment
341 return (VARIABLE_HEADER
*) ((UINTN
) GetVariableDataPtr (Variable
) + Variable
->DataSize
+ GET_PAD_SIZE (Variable
->DataSize
));
348 IN VARIABLE_STORE_HEADER
*VarStoreHeader
354 This code gets the pointer to the last variable memory pointer byte
358 VarStoreHeader Pointer to the Variable Store Header.
362 VARIABLE_HEADER* Pointer to last unavailable Variable Header
367 // The end of variable store
369 return (VARIABLE_HEADER
*) ((UINTN
) VarStoreHeader
+ VarStoreHeader
->Size
);
376 IN EFI_PHYSICAL_ADDRESS VariableBase
,
377 OUT UINTN
*LastVariableOffset
,
378 IN BOOLEAN IsVolatile
384 Variable store garbage collection and reclaim operation
388 VariableBase Base address of variable store
389 LastVariableOffset Offset of last variable
390 IsVolatile The variable store is volatile or not,
391 if it is non-volatile, need FTW
399 VARIABLE_HEADER
*Variable
;
400 VARIABLE_HEADER
*NextVariable
;
401 VARIABLE_STORE_HEADER
*VariableStoreHeader
;
403 UINTN ValidBufferSize
;
408 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) ((UINTN
) VariableBase
);
411 // Start Pointers for the variable.
413 Variable
= (VARIABLE_HEADER
*) (VariableStoreHeader
+ 1);
415 ValidBufferSize
= sizeof (VARIABLE_STORE_HEADER
);
417 while (IsValidVariableHeader (Variable
)) {
418 NextVariable
= GetNextVariablePtr (Variable
);
419 if (Variable
->State
== VAR_ADDED
) {
420 VariableSize
= (UINTN
) NextVariable
- (UINTN
) Variable
;
421 ValidBufferSize
+= VariableSize
;
424 Variable
= NextVariable
;
427 Status
= gBS
->AllocatePool (
430 (VOID
**) &ValidBuffer
432 if (EFI_ERROR (Status
)) {
436 SetMem (ValidBuffer
, ValidBufferSize
, 0xff);
438 CurrPtr
= ValidBuffer
;
441 // Copy variable store header
443 CopyMem (CurrPtr
, VariableStoreHeader
, sizeof (VARIABLE_STORE_HEADER
));
444 CurrPtr
+= sizeof (VARIABLE_STORE_HEADER
);
447 // Start Pointers for the variable.
449 Variable
= (VARIABLE_HEADER
*) (VariableStoreHeader
+ 1);
451 while (IsValidVariableHeader (Variable
)) {
452 NextVariable
= GetNextVariablePtr (Variable
);
453 if (Variable
->State
== VAR_ADDED
) {
454 VariableSize
= (UINTN
) NextVariable
- (UINTN
) Variable
;
455 CopyMem (CurrPtr
, (UINT8
*) Variable
, VariableSize
);
456 CurrPtr
+= VariableSize
;
459 Variable
= NextVariable
;
464 // If volatile variable store, just copy valid buffer
466 SetMem ((UINT8
*) (UINTN
) VariableBase
, VariableStoreHeader
->Size
, 0xff);
467 CopyMem ((UINT8
*) (UINTN
) VariableBase
, ValidBuffer
, ValidBufferSize
);
468 *LastVariableOffset
= ValidBufferSize
;
469 Status
= EFI_SUCCESS
;
472 // If non-volatile variable store, perform FTW here.
474 Status
= FtwVariableSpace (
479 if (!EFI_ERROR (Status
)) {
480 *LastVariableOffset
= ValidBufferSize
;
484 gBS
->FreePool (ValidBuffer
);
486 if (EFI_ERROR (Status
)) {
487 *LastVariableOffset
= 0;
497 IN CHAR16
*VariableName
,
498 IN EFI_GUID
*VendorGuid
,
499 OUT VARIABLE_POINTER_TRACK
*PtrTrack
,
500 IN VARIABLE_GLOBAL
*Global
506 This code finds variable in storage blocks (Volatile or Non-Volatile)
510 VariableName Name of the variable to be found
511 VendorGuid Vendor GUID to be found.
512 PtrTrack Variable Track Pointer structure that contains
513 Variable Information.
514 Contains the pointer of Variable header.
515 Global VARIABLE_GLOBAL pointer
523 VARIABLE_HEADER
*Variable
[2];
524 VARIABLE_STORE_HEADER
*VariableStoreHeader
[2];
528 // We aquire the lock at the entry of FindVariable as GetVariable, GetNextVariableName
529 // SetVariable all call FindVariable at entry point. Please move "Aquire Lock" to
530 // the correct places if this assumption does not hold TRUE anymore.
532 AcquireLockOnlyAtBootTime(&Global
->VariableServicesLock
);
535 // 0: Non-Volatile, 1: Volatile
537 VariableStoreHeader
[0] = (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->NonVolatileVariableBase
);
538 VariableStoreHeader
[1] = (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->VolatileVariableBase
);
541 // Start Pointers for the variable.
542 // Actual Data Pointer where data can be written.
544 Variable
[0] = (VARIABLE_HEADER
*) (VariableStoreHeader
[0] + 1);
545 Variable
[1] = (VARIABLE_HEADER
*) (VariableStoreHeader
[1] + 1);
547 if (VariableName
[0] != 0 && VendorGuid
== NULL
) {
548 return EFI_INVALID_PARAMETER
;
551 // Find the variable by walk through non-volatile and volatile variable store
553 for (Index
= 0; Index
< 2; Index
++) {
554 PtrTrack
->StartPtr
= (VARIABLE_HEADER
*) (VariableStoreHeader
[Index
] + 1);
555 PtrTrack
->EndPtr
= GetEndPointer (VariableStoreHeader
[Index
]);
557 while (IsValidVariableHeader (Variable
[Index
]) && (Variable
[Index
] <= GetEndPointer (VariableStoreHeader
[Index
]))) {
558 if (Variable
[Index
]->State
== VAR_ADDED
) {
559 if (!(EfiAtRuntime () && !(Variable
[Index
]->Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
))) {
560 if (VariableName
[0] == 0) {
561 PtrTrack
->CurrPtr
= Variable
[Index
];
562 PtrTrack
->Volatile
= (BOOLEAN
) Index
;
565 if (CompareGuid (VendorGuid
, &Variable
[Index
]->VendorGuid
)) {
566 if (!CompareMem (VariableName
, GET_VARIABLE_NAME_PTR (Variable
[Index
]), Variable
[Index
]->NameSize
)) {
567 PtrTrack
->CurrPtr
= Variable
[Index
];
568 PtrTrack
->Volatile
= (BOOLEAN
) Index
;
576 Variable
[Index
] = GetNextVariablePtr (Variable
[Index
]);
585 PtrTrack
->CurrPtr
= NULL
;
586 return EFI_NOT_FOUND
;
592 IN CHAR16
*VariableName
,
593 IN EFI_GUID
* VendorGuid
,
594 OUT UINT32
*Attributes OPTIONAL
,
595 IN OUT UINTN
*DataSize
,
597 IN VARIABLE_GLOBAL
* Global
,
604 This code finds variable in storage blocks (Volatile or Non-Volatile)
608 VariableName Name of Variable to be found
609 VendorGuid Variable vendor GUID
610 Attributes OPTIONAL Attribute value of the variable found
611 DataSize Size of Data found. If size is less than the
612 data, this value contains the required size.
614 Global Pointer to VARIABLE_GLOBAL structure
615 Instance Instance of the Firmware Volume.
623 VARIABLE_POINTER_TRACK Variable
;
627 if (VariableName
== NULL
|| VendorGuid
== NULL
|| DataSize
== NULL
) {
628 return EFI_INVALID_PARAMETER
;
631 // Find existing variable
633 Status
= FindVariable (VariableName
, VendorGuid
, &Variable
, Global
);
635 if (Variable
.CurrPtr
== NULL
|| EFI_ERROR (Status
)) {
641 VarDataSize
= Variable
.CurrPtr
->DataSize
;
642 if (*DataSize
>= VarDataSize
) {
644 Status
= EFI_INVALID_PARAMETER
;
648 CopyMem (Data
, GetVariableDataPtr (Variable
.CurrPtr
), VarDataSize
);
649 if (Attributes
!= NULL
) {
650 *Attributes
= Variable
.CurrPtr
->Attributes
;
653 *DataSize
= VarDataSize
;
654 Status
= EFI_SUCCESS
;
657 *DataSize
= VarDataSize
;
658 Status
= EFI_BUFFER_TOO_SMALL
;
663 ReleaseLockOnlyAtBootTime (&Global
->VariableServicesLock
);
669 GetNextVariableName (
670 IN OUT UINTN
*VariableNameSize
,
671 IN OUT CHAR16
*VariableName
,
672 IN OUT EFI_GUID
*VendorGuid
,
673 IN VARIABLE_GLOBAL
*Global
,
680 This code Finds the Next available variable
684 VariableNameSize Size of the variable
685 VariableName Pointer to variable name
686 VendorGuid Variable Vendor Guid
687 Global VARIABLE_GLOBAL structure pointer.
696 VARIABLE_POINTER_TRACK Variable
;
700 if (VariableNameSize
== NULL
|| VariableName
== NULL
|| VendorGuid
== NULL
) {
701 return EFI_INVALID_PARAMETER
;
704 Status
= FindVariable (VariableName
, VendorGuid
, &Variable
, Global
);
706 if (Variable
.CurrPtr
== NULL
|| EFI_ERROR (Status
)) {
710 if (VariableName
[0] != 0) {
712 // If variable name is not NULL, get next variable
714 Variable
.CurrPtr
= GetNextVariablePtr (Variable
.CurrPtr
);
719 // If both volatile and non-volatile variable store are parsed,
722 if (Variable
.CurrPtr
>= Variable
.EndPtr
|| Variable
.CurrPtr
== NULL
) {
723 Variable
.Volatile
= (BOOLEAN
) (Variable
.Volatile
^ ((BOOLEAN
) 0x1));
724 if (Variable
.Volatile
) {
725 Variable
.StartPtr
= (VARIABLE_HEADER
*) ((UINTN
) (Global
->VolatileVariableBase
+ sizeof (VARIABLE_STORE_HEADER
)));
726 Variable
.EndPtr
= (VARIABLE_HEADER
*) GetEndPointer ((VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->VolatileVariableBase
));
728 Status
= EFI_NOT_FOUND
;
732 Variable
.CurrPtr
= Variable
.StartPtr
;
733 if (!IsValidVariableHeader (Variable
.CurrPtr
)) {
740 if (IsValidVariableHeader (Variable
.CurrPtr
) && Variable
.CurrPtr
->State
== VAR_ADDED
) {
741 if (!(EfiAtRuntime () && !(Variable
.CurrPtr
->Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
))) {
742 VarNameSize
= Variable
.CurrPtr
->NameSize
;
743 if (VarNameSize
<= *VariableNameSize
) {
746 GET_VARIABLE_NAME_PTR (Variable
.CurrPtr
),
751 &Variable
.CurrPtr
->VendorGuid
,
754 Status
= EFI_SUCCESS
;
756 Status
= EFI_BUFFER_TOO_SMALL
;
759 *VariableNameSize
= VarNameSize
;
764 Variable
.CurrPtr
= GetNextVariablePtr (Variable
.CurrPtr
);
768 ReleaseLockOnlyAtBootTime (&Global
->VariableServicesLock
);
775 IN CHAR16
*VariableName
,
776 IN EFI_GUID
*VendorGuid
,
777 IN UINT32 Attributes
,
780 IN VARIABLE_GLOBAL
*Global
,
781 IN UINTN
*VolatileOffset
,
782 IN UINTN
*NonVolatileOffset
,
789 This code sets variable in storage blocks (Volatile or Non-Volatile)
793 VariableName Name of Variable to be found
794 VendorGuid Variable vendor GUID
795 Attributes Attribute value of the variable found
796 DataSize Size of Data found. If size is less than the
797 data, this value contains the required size.
799 Global Pointer to VARIABLE_GLOBAL structure
800 VolatileOffset The offset of last volatile variable
801 NonVolatileOffset The offset of last non-volatile variable
802 Instance Instance of the Firmware Volume.
807 EFI_INVALID_PARAMETER - Invalid parameter
808 EFI_SUCCESS - Set successfully
809 EFI_OUT_OF_RESOURCES - Resource not enough to set variable
810 EFI_NOT_FOUND - Not found
814 VARIABLE_POINTER_TRACK Variable
;
816 VARIABLE_HEADER
*NextVariable
;
826 if (VariableName
== NULL
|| VariableName
[0] == 0 || VendorGuid
== NULL
) {
827 return EFI_INVALID_PARAMETER
;
830 Status
= FindVariable (VariableName
, VendorGuid
, &Variable
, Global
);
832 if (Status
== EFI_INVALID_PARAMETER
) {
834 } else if (!EFI_ERROR (Status
) && Variable
.Volatile
&& EfiAtRuntime()) {
836 // If EfiAtRuntime and the variable is Volatile and Runtime Access,
837 // the volatile is ReadOnly, and SetVariable should be aborted and
838 // return EFI_WRITE_PROTECTED.
840 Status
= EFI_WRITE_PROTECTED
;
842 } else if (sizeof (VARIABLE_HEADER
) + StrSize (VariableName
) + DataSize
> MAX_VARIABLE_SIZE
) {
844 // The size of the VariableName, including the Unicode Null in bytes plus
845 // the DataSize is limited to maximum size of MAX_VARIABLE_SIZE (1024) bytes.
847 Status
= EFI_INVALID_PARAMETER
;
849 } else if (Attributes
== EFI_VARIABLE_NON_VOLATILE
) {
851 // Make sure not only EFI_VARIABLE_NON_VOLATILE is set
853 Status
= EFI_INVALID_PARAMETER
;
855 } else if ((Attributes
& (EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
)) ==
856 EFI_VARIABLE_RUNTIME_ACCESS
) {
858 // Make sure if runtime bit is set, boot service bit is set also
860 Status
= EFI_INVALID_PARAMETER
;
862 } else if (EfiAtRuntime () && Attributes
&& !(Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
)) {
864 // Runtime but Attribute is not Runtime
866 Status
= EFI_INVALID_PARAMETER
;
868 } else if (EfiAtRuntime () && Attributes
&& !(Attributes
& EFI_VARIABLE_NON_VOLATILE
)) {
870 // Cannot set volatile variable in Runtime
872 Status
= EFI_INVALID_PARAMETER
;
874 } else if (DataSize
== 0 || (Attributes
& (EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
)) == 0) {
876 // Setting a data variable with no access, or zero DataSize attributes
877 // specified causes it to be deleted.
879 if (!EFI_ERROR (Status
)) {
880 State
= Variable
.CurrPtr
->State
;
881 State
&= VAR_DELETED
;
883 Status
= UpdateVariableStore (
888 (UINTN
) &Variable
.CurrPtr
->State
,
892 if (EFI_ERROR (Status
)) {
896 Status
= EFI_SUCCESS
;
900 Status
= EFI_NOT_FOUND
;
903 if (!EFI_ERROR (Status
)) {
905 // If the variable is marked valid and the same data has been passed in
906 // then return to the caller immediately.
908 if (Variable
.CurrPtr
->DataSize
== DataSize
&&
909 !CompareMem (Data
, GetVariableDataPtr (Variable
.CurrPtr
), DataSize
)
911 Status
= EFI_SUCCESS
;
913 } else if (Variable
.CurrPtr
->State
== VAR_ADDED
) {
915 // Mark the old variable as in delete transition
917 State
= Variable
.CurrPtr
->State
;
918 State
&= VAR_IN_DELETED_TRANSITION
;
920 Status
= UpdateVariableStore (
925 (UINTN
) &Variable
.CurrPtr
->State
,
929 if (EFI_ERROR (Status
)) {
935 // Create a new variable and copy the data.
937 // Tricky part: Use scratch data area at the end of volatile variable store
938 // as a temporary storage.
940 NextVariable
= GetEndPointer ((VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->VolatileVariableBase
));
942 SetMem (NextVariable
, SCRATCH_SIZE
, 0xff);
944 NextVariable
->StartId
= VARIABLE_DATA
;
945 NextVariable
->Attributes
= Attributes
;
947 // NextVariable->State = VAR_ADDED;
949 NextVariable
->Reserved
= 0;
950 VarNameOffset
= sizeof (VARIABLE_HEADER
);
951 VarNameSize
= StrSize (VariableName
);
953 (UINT8
*) ((UINTN
) NextVariable
+ VarNameOffset
),
957 VarDataOffset
= VarNameOffset
+ VarNameSize
+ GET_PAD_SIZE (VarNameSize
);
959 (UINT8
*) ((UINTN
) NextVariable
+ VarDataOffset
),
963 CopyMem (&NextVariable
->VendorGuid
, VendorGuid
, sizeof (EFI_GUID
));
965 // There will be pad bytes after Data, the NextVariable->NameSize and
966 // NextVariable->DataSize should not include pad size so that variable
967 // service can get actual size in GetVariable
969 NextVariable
->NameSize
= (UINT32
)VarNameSize
;
970 NextVariable
->DataSize
= (UINT32
)DataSize
;
973 // The actual size of the variable that stores in storage should
976 VarSize
= VarDataOffset
+ DataSize
+ GET_PAD_SIZE (DataSize
);
977 if (Attributes
& EFI_VARIABLE_NON_VOLATILE
) {
978 if ((UINT32
) (VarSize
+*NonVolatileOffset
) >
979 ((VARIABLE_STORE_HEADER
*) ((UINTN
) (Global
->NonVolatileVariableBase
)))->Size
981 if (EfiAtRuntime ()) {
982 Status
= EFI_OUT_OF_RESOURCES
;
986 // Perform garbage collection & reclaim operation
988 Status
= Reclaim (Global
->NonVolatileVariableBase
, NonVolatileOffset
, FALSE
);
989 if (EFI_ERROR (Status
)) {
993 // If still no enough space, return out of resources
995 if ((UINT32
) (VarSize
+*NonVolatileOffset
) >
996 ((VARIABLE_STORE_HEADER
*) ((UINTN
) (Global
->NonVolatileVariableBase
)))->Size
998 Status
= EFI_OUT_OF_RESOURCES
;
1006 // 1. Write variable header
1007 // 2. Write variable data
1008 // 3. Set variable state to valid
1013 Status
= UpdateVariableStore (
1019 sizeof (VARIABLE_HEADER
),
1020 (UINT8
*) NextVariable
1023 if (EFI_ERROR (Status
)) {
1029 Status
= UpdateVariableStore (
1034 *NonVolatileOffset
+ sizeof (VARIABLE_HEADER
),
1035 (UINT32
) VarSize
- sizeof (VARIABLE_HEADER
),
1036 (UINT8
*) NextVariable
+ sizeof (VARIABLE_HEADER
)
1039 if (EFI_ERROR (Status
)) {
1045 NextVariable
->State
= VAR_ADDED
;
1046 Status
= UpdateVariableStore (
1052 sizeof (VARIABLE_HEADER
),
1053 (UINT8
*) NextVariable
1056 if (EFI_ERROR (Status
)) {
1060 *NonVolatileOffset
= *NonVolatileOffset
+ VarSize
;
1063 if (EfiAtRuntime ()) {
1064 Status
= EFI_INVALID_PARAMETER
;
1068 if ((UINT32
) (VarSize
+*VolatileOffset
) >
1069 ((VARIABLE_STORE_HEADER
*) ((UINTN
) (Global
->VolatileVariableBase
)))->Size
1072 // Perform garbage collection & reclaim operation
1074 Status
= Reclaim (Global
->VolatileVariableBase
, VolatileOffset
, TRUE
);
1075 if (EFI_ERROR (Status
)) {
1079 // If still no enough space, return out of resources
1081 if ((UINT32
) (VarSize
+*VolatileOffset
) >
1082 ((VARIABLE_STORE_HEADER
*) ((UINTN
) (Global
->VolatileVariableBase
)))->Size
1084 Status
= EFI_OUT_OF_RESOURCES
;
1091 NextVariable
->State
= VAR_ADDED
;
1092 Status
= UpdateVariableStore (
1099 (UINT8
*) NextVariable
1102 if (EFI_ERROR (Status
)) {
1106 *VolatileOffset
= *VolatileOffset
+ VarSize
;
1109 // Mark the old variable as deleted
1111 if (!Reclaimed
&& !EFI_ERROR (Status
) && Variable
.CurrPtr
!= NULL
) {
1112 State
= Variable
.CurrPtr
->State
;
1113 State
&= VAR_DELETED
;
1115 Status
= UpdateVariableStore (
1120 (UINTN
) &Variable
.CurrPtr
->State
,
1125 if (EFI_ERROR (Status
)) {
1131 Status
= EFI_SUCCESS
;
1133 ReleaseLockOnlyAtBootTime (&Global
->VariableServicesLock
);
1137 #if (EFI_SPECIFICATION_VERSION >= 0x00020000)
1141 IN UINT32 Attributes
,
1142 OUT UINT64
*MaximumVariableStorageSize
,
1143 OUT UINT64
*RemainingVariableStorageSize
,
1144 OUT UINT64
*MaximumVariableSize
,
1145 IN VARIABLE_GLOBAL
*Global
,
1150 Routine Description:
1152 This code returns information about the EFI variables.
1156 Attributes Attributes bitmask to specify the type of variables
1157 on which to return information.
1158 MaximumVariableStorageSize Pointer to the maximum size of the storage space available
1159 for the EFI variables associated with the attributes specified.
1160 RemainingVariableStorageSize Pointer to the remaining size of the storage space available
1161 for the EFI variables associated with the attributes specified.
1162 MaximumVariableSize Pointer to the maximum size of the individual EFI variables
1163 associated with the attributes specified.
1164 Global Pointer to VARIABLE_GLOBAL structure.
1165 Instance Instance of the Firmware Volume.
1170 EFI_INVALID_PARAMETER - An invalid combination of attribute bits was supplied.
1171 EFI_SUCCESS - Query successfully.
1172 EFI_UNSUPPORTED - The attribute is not supported on this platform.
1176 VARIABLE_HEADER
*Variable
;
1177 VARIABLE_HEADER
*NextVariable
;
1178 UINT64 VariableSize
;
1179 VARIABLE_STORE_HEADER
*VariableStoreHeader
;
1181 if(MaximumVariableStorageSize
== NULL
|| RemainingVariableStorageSize
== NULL
|| MaximumVariableSize
== NULL
) {
1182 return EFI_INVALID_PARAMETER
;
1185 if((Attributes
& (EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
)) == 0) {
1187 // Make sure the Attributes combination is supported by the platform.
1189 return EFI_UNSUPPORTED
;
1190 } else if ((Attributes
& (EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
)) == EFI_VARIABLE_RUNTIME_ACCESS
) {
1192 // Make sure if runtime bit is set, boot service bit is set also.
1194 return EFI_INVALID_PARAMETER
;
1195 } else if (EfiAtRuntime () && !(Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
)) {
1197 // Make sure RT Attribute is set if we are in Runtime phase.
1199 return EFI_INVALID_PARAMETER
;
1202 AcquireLockOnlyAtBootTime(&Global
->VariableServicesLock
);
1204 if((Attributes
& EFI_VARIABLE_NON_VOLATILE
) == 0) {
1206 // Query is Volatile related.
1208 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->VolatileVariableBase
);
1211 // Query is Non-Volatile related.
1213 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->NonVolatileVariableBase
);
1217 // Now let's fill *MaximumVariableStorageSize *RemainingVariableStorageSize
1218 // with the storage size (excluding the storage header size).
1220 *MaximumVariableStorageSize
= VariableStoreHeader
->Size
- sizeof (VARIABLE_STORE_HEADER
);
1221 *RemainingVariableStorageSize
= VariableStoreHeader
->Size
- sizeof (VARIABLE_STORE_HEADER
);
1224 // Let *MaximumVariableSize be MAX_VARIABLE_SIZE.
1226 *MaximumVariableSize
= MAX_VARIABLE_SIZE
;
1229 // Point to the starting address of the variables.
1231 Variable
= (VARIABLE_HEADER
*) (VariableStoreHeader
+ 1);
1234 // Now walk through the related variable store.
1236 while (IsValidVariableHeader (Variable
) && (Variable
< GetEndPointer (VariableStoreHeader
))) {
1237 NextVariable
= GetNextVariablePtr (Variable
);
1238 VariableSize
= (UINT64
) (UINTN
) NextVariable
- (UINT64
) (UINTN
) Variable
;
1240 if (EfiAtRuntime ()) {
1242 // we don't take the state of the variables in mind
1243 // when calculating RemainingVariableStorageSize,
1244 // since the space occupied by variables not marked with
1245 // VAR_ADDED is not allowed to be reclaimed in Runtime.
1247 *RemainingVariableStorageSize
-= VariableSize
;
1250 // Only care about Variables with State VAR_ADDED,because
1251 // the space not marked as VAR_ADDED is reclaimable now.
1253 if (Variable
->State
== VAR_ADDED
) {
1254 *RemainingVariableStorageSize
-= VariableSize
;
1259 // Go to the next one
1261 Variable
= NextVariable
;
1264 ReleaseLockOnlyAtBootTime (&Global
->VariableServicesLock
);
1271 VariableCommonInitialize (
1272 IN EFI_HANDLE ImageHandle
,
1273 IN EFI_SYSTEM_TABLE
*SystemTable
1277 Routine Description:
1278 This function does common initialization for variable services
1282 ImageHandle - The firmware allocated handle for the EFI image.
1283 SystemTable - A pointer to the EFI System Table.
1289 EFI_NOT_FOUND - Variable store area not found.
1290 EFI_UNSUPPORTED - Currently only one non-volatile variable store is supported.
1291 EFI_SUCCESS - Variable services successfully initialized.
1296 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
1298 VARIABLE_STORE_HEADER
*VolatileVariableStore
;
1299 VARIABLE_STORE_HEADER
*VariableStoreHeader
;
1300 VARIABLE_HEADER
*NextVariable
;
1302 EFI_PHYSICAL_ADDRESS FvVolHdr
;
1304 UINT64 TempVariableStoreHeader
;
1306 EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor
;
1307 EFI_FLASH_SUBAREA_ENTRY VariableStoreEntry
;
1313 Status
= gBS
->AllocatePool (
1314 EfiRuntimeServicesData
,
1315 sizeof (ESAL_VARIABLE_GLOBAL
),
1316 (VOID
**) &mVariableModuleGlobal
1319 if (EFI_ERROR (Status
)) {
1323 EfiInitializeLock(&mVariableModuleGlobal
->VariableGlobal
[Physical
].VariableServicesLock
, EFI_TPL_CALLBACK
);
1326 // Allocate memory for volatile variable store
1328 Status
= gBS
->AllocatePool (
1329 EfiRuntimeServicesData
,
1330 VARIABLE_STORE_SIZE
+ SCRATCH_SIZE
,
1331 (VOID
**) &VolatileVariableStore
1334 if (EFI_ERROR (Status
)) {
1335 gBS
->FreePool (mVariableModuleGlobal
);
1339 SetMem (VolatileVariableStore
, VARIABLE_STORE_SIZE
+ SCRATCH_SIZE
, 0xff);
1342 // Variable Specific Data
1344 mVariableModuleGlobal
->VariableGlobal
[Physical
].VolatileVariableBase
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) VolatileVariableStore
;
1345 mVariableModuleGlobal
->VolatileLastVariableOffset
= sizeof (VARIABLE_STORE_HEADER
);
1347 VolatileVariableStore
->Signature
= VARIABLE_STORE_SIGNATURE
;
1348 VolatileVariableStore
->Size
= VARIABLE_STORE_SIZE
;
1349 VolatileVariableStore
->Format
= VARIABLE_STORE_FORMATTED
;
1350 VolatileVariableStore
->State
= VARIABLE_STORE_HEALTHY
;
1351 VolatileVariableStore
->Reserved
= 0;
1352 VolatileVariableStore
->Reserved1
= 0;
1355 // Get non volatile varaible store
1358 TempVariableStoreHeader
= (UINT64
) PcdGet32 (PcdFlashNvStorageVariableBase
);
1359 VariableStoreEntry
.Base
= TempVariableStoreHeader
+ \
1360 (((EFI_FIRMWARE_VOLUME_HEADER
*) (UINTN
) (TempVariableStoreHeader
)) -> HeaderLength
);
1361 VariableStoreEntry
.Length
= (UINT64
) PcdGet32 (PcdFlashNvStorageVariableSize
) - \
1362 (((EFI_FIRMWARE_VOLUME_HEADER
*) (UINTN
) (TempVariableStoreHeader
)) -> HeaderLength
);
1364 // Mark the variable storage region of the FLASH as RUNTIME
1366 BaseAddress
= VariableStoreEntry
.Base
& (~EFI_PAGE_MASK
);
1367 Length
= VariableStoreEntry
.Length
+ (VariableStoreEntry
.Base
- BaseAddress
);
1368 Length
= (Length
+ EFI_PAGE_SIZE
- 1) & (~EFI_PAGE_MASK
);
1370 Status
= gDS
->GetMemorySpaceDescriptor (BaseAddress
, &GcdDescriptor
);
1371 if (EFI_ERROR (Status
)) {
1372 gBS
->FreePool (mVariableModuleGlobal
);
1373 gBS
->FreePool (VolatileVariableStore
);
1374 return EFI_UNSUPPORTED
;
1377 Status
= gDS
->SetMemorySpaceAttributes (
1380 GcdDescriptor
.Attributes
| EFI_MEMORY_RUNTIME
1382 if (EFI_ERROR (Status
)) {
1383 gBS
->FreePool (mVariableModuleGlobal
);
1384 gBS
->FreePool (VolatileVariableStore
);
1385 return EFI_UNSUPPORTED
;
1388 // Get address of non volatile variable store base
1390 mVariableModuleGlobal
->VariableGlobal
[Physical
].NonVolatileVariableBase
= VariableStoreEntry
.Base
;
1396 // Find the Correct Instance of the FV Block Service.
1399 CurrPtr
= (CHAR8
*) ((UINTN
) mVariableModuleGlobal
->VariableGlobal
[Physical
].NonVolatileVariableBase
);
1400 while (EfiFvbGetPhysicalAddress (Instance
, &FvVolHdr
) == EFI_SUCCESS
) {
1401 FwVolHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) ((UINTN
) FvVolHdr
);
1402 if (CurrPtr
>= (CHAR8
*) FwVolHeader
&& CurrPtr
< (((CHAR8
*) FwVolHeader
) + FwVolHeader
->FvLength
)) {
1403 mVariableModuleGlobal
->FvbInstance
= Instance
;
1410 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) CurrPtr
;
1411 if (GetVariableStoreStatus (VariableStoreHeader
) == EfiValid
) {
1412 if (~VariableStoreHeader
->Size
== 0) {
1413 Status
= UpdateVariableStore (
1414 &mVariableModuleGlobal
->VariableGlobal
[Physical
],
1417 mVariableModuleGlobal
->FvbInstance
,
1418 (UINTN
) &VariableStoreHeader
->Size
,
1420 (UINT8
*) &VariableStoreEntry
.Length
1423 if (EFI_ERROR (Status
)) {
1428 mVariableModuleGlobal
->VariableGlobal
[Physical
].NonVolatileVariableBase
= (EFI_PHYSICAL_ADDRESS
) ((UINTN
) CurrPtr
);
1430 // Parse non-volatile variable data and get last variable offset
1432 NextVariable
= (VARIABLE_HEADER
*) (CurrPtr
+ sizeof (VARIABLE_STORE_HEADER
));
1433 Status
= EFI_SUCCESS
;
1435 while (IsValidVariableHeader (NextVariable
)) {
1436 NextVariable
= GetNextVariablePtr (NextVariable
);
1439 mVariableModuleGlobal
->NonVolatileLastVariableOffset
= (UINTN
) NextVariable
- (UINTN
) CurrPtr
;
1442 // Check if the free area is blow a threshold
1444 if ((((VARIABLE_STORE_HEADER
*)((UINTN
) CurrPtr
))->Size
- mVariableModuleGlobal
->NonVolatileLastVariableOffset
) < VARIABLE_RECLAIM_THRESHOLD
) {
1446 mVariableModuleGlobal
->VariableGlobal
[Physical
].NonVolatileVariableBase
,
1447 &mVariableModuleGlobal
->NonVolatileLastVariableOffset
,
1452 if (EFI_ERROR (Status
)) {
1453 gBS
->FreePool (mVariableModuleGlobal
);
1454 gBS
->FreePool (VolatileVariableStore
);
1459 // Check if the free area is really free.
1461 for (Index
= mVariableModuleGlobal
->NonVolatileLastVariableOffset
; Index
< VariableStoreHeader
->Size
; Index
++) {
1462 Data
= ((UINT8
*) (UINTN
) mVariableModuleGlobal
->VariableGlobal
[Physical
].NonVolatileVariableBase
)[Index
];
1465 // There must be something wrong in variable store, do reclaim operation.
1468 mVariableModuleGlobal
->VariableGlobal
[Physical
].NonVolatileVariableBase
,
1469 &mVariableModuleGlobal
->NonVolatileLastVariableOffset
,
1477 if (EFI_ERROR (Status
)) {
1478 gBS
->FreePool (mVariableModuleGlobal
);
1479 gBS
->FreePool (VolatileVariableStore
);