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
);
1140 IN UINT32 Attributes
,
1141 OUT UINT64
*MaximumVariableStorageSize
,
1142 OUT UINT64
*RemainingVariableStorageSize
,
1143 OUT UINT64
*MaximumVariableSize
,
1144 IN VARIABLE_GLOBAL
*Global
,
1149 Routine Description:
1151 This code returns information about the EFI variables.
1155 Attributes Attributes bitmask to specify the type of variables
1156 on which to return information.
1157 MaximumVariableStorageSize Pointer to the maximum size of the storage space available
1158 for the EFI variables associated with the attributes specified.
1159 RemainingVariableStorageSize Pointer to the remaining size of the storage space available
1160 for the EFI variables associated with the attributes specified.
1161 MaximumVariableSize Pointer to the maximum size of the individual EFI variables
1162 associated with the attributes specified.
1163 Global Pointer to VARIABLE_GLOBAL structure.
1164 Instance Instance of the Firmware Volume.
1169 EFI_INVALID_PARAMETER - An invalid combination of attribute bits was supplied.
1170 EFI_SUCCESS - Query successfully.
1171 EFI_UNSUPPORTED - The attribute is not supported on this platform.
1175 VARIABLE_HEADER
*Variable
;
1176 VARIABLE_HEADER
*NextVariable
;
1177 UINT64 VariableSize
;
1178 VARIABLE_STORE_HEADER
*VariableStoreHeader
;
1180 if(MaximumVariableStorageSize
== NULL
|| RemainingVariableStorageSize
== NULL
|| MaximumVariableSize
== NULL
) {
1181 return EFI_INVALID_PARAMETER
;
1184 if((Attributes
& (EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
)) == 0) {
1186 // Make sure the Attributes combination is supported by the platform.
1188 return EFI_UNSUPPORTED
;
1189 } else if ((Attributes
& (EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
)) == EFI_VARIABLE_RUNTIME_ACCESS
) {
1191 // Make sure if runtime bit is set, boot service bit is set also.
1193 return EFI_INVALID_PARAMETER
;
1194 } else if (EfiAtRuntime () && !(Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
)) {
1196 // Make sure RT Attribute is set if we are in Runtime phase.
1198 return EFI_INVALID_PARAMETER
;
1201 AcquireLockOnlyAtBootTime(&Global
->VariableServicesLock
);
1203 if((Attributes
& EFI_VARIABLE_NON_VOLATILE
) == 0) {
1205 // Query is Volatile related.
1207 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->VolatileVariableBase
);
1210 // Query is Non-Volatile related.
1212 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->NonVolatileVariableBase
);
1216 // Now let's fill *MaximumVariableStorageSize *RemainingVariableStorageSize
1217 // with the storage size (excluding the storage header size).
1219 *MaximumVariableStorageSize
= VariableStoreHeader
->Size
- sizeof (VARIABLE_STORE_HEADER
);
1220 *RemainingVariableStorageSize
= VariableStoreHeader
->Size
- sizeof (VARIABLE_STORE_HEADER
);
1223 // Let *MaximumVariableSize be MAX_VARIABLE_SIZE.
1225 *MaximumVariableSize
= MAX_VARIABLE_SIZE
;
1228 // Point to the starting address of the variables.
1230 Variable
= (VARIABLE_HEADER
*) (VariableStoreHeader
+ 1);
1233 // Now walk through the related variable store.
1235 while (IsValidVariableHeader (Variable
) && (Variable
< GetEndPointer (VariableStoreHeader
))) {
1236 NextVariable
= GetNextVariablePtr (Variable
);
1237 VariableSize
= (UINT64
) (UINTN
) NextVariable
- (UINT64
) (UINTN
) Variable
;
1239 if (EfiAtRuntime ()) {
1241 // we don't take the state of the variables in mind
1242 // when calculating RemainingVariableStorageSize,
1243 // since the space occupied by variables not marked with
1244 // VAR_ADDED is not allowed to be reclaimed in Runtime.
1246 *RemainingVariableStorageSize
-= VariableSize
;
1249 // Only care about Variables with State VAR_ADDED,because
1250 // the space not marked as VAR_ADDED is reclaimable now.
1252 if (Variable
->State
== VAR_ADDED
) {
1253 *RemainingVariableStorageSize
-= VariableSize
;
1258 // Go to the next one
1260 Variable
= NextVariable
;
1263 ReleaseLockOnlyAtBootTime (&Global
->VariableServicesLock
);
1269 VariableCommonInitialize (
1270 IN EFI_HANDLE ImageHandle
,
1271 IN EFI_SYSTEM_TABLE
*SystemTable
1275 Routine Description:
1276 This function does common initialization for variable services
1280 ImageHandle - The firmware allocated handle for the EFI image.
1281 SystemTable - A pointer to the EFI System Table.
1287 EFI_NOT_FOUND - Variable store area not found.
1288 EFI_UNSUPPORTED - Currently only one non-volatile variable store is supported.
1289 EFI_SUCCESS - Variable services successfully initialized.
1294 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
1296 VARIABLE_STORE_HEADER
*VolatileVariableStore
;
1297 VARIABLE_STORE_HEADER
*VariableStoreHeader
;
1298 VARIABLE_HEADER
*NextVariable
;
1300 EFI_PHYSICAL_ADDRESS FvVolHdr
;
1302 UINT64 TempVariableStoreHeader
;
1304 EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor
;
1305 EFI_FLASH_SUBAREA_ENTRY VariableStoreEntry
;
1311 Status
= gBS
->AllocatePool (
1312 EfiRuntimeServicesData
,
1313 sizeof (ESAL_VARIABLE_GLOBAL
),
1314 (VOID
**) &mVariableModuleGlobal
1317 if (EFI_ERROR (Status
)) {
1321 EfiInitializeLock(&mVariableModuleGlobal
->VariableGlobal
[Physical
].VariableServicesLock
, EFI_TPL_NOTIFY
);
1324 // Allocate memory for volatile variable store
1326 Status
= gBS
->AllocatePool (
1327 EfiRuntimeServicesData
,
1328 VARIABLE_STORE_SIZE
+ SCRATCH_SIZE
,
1329 (VOID
**) &VolatileVariableStore
1332 if (EFI_ERROR (Status
)) {
1333 gBS
->FreePool (mVariableModuleGlobal
);
1337 SetMem (VolatileVariableStore
, VARIABLE_STORE_SIZE
+ SCRATCH_SIZE
, 0xff);
1340 // Variable Specific Data
1342 mVariableModuleGlobal
->VariableGlobal
[Physical
].VolatileVariableBase
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) VolatileVariableStore
;
1343 mVariableModuleGlobal
->VolatileLastVariableOffset
= sizeof (VARIABLE_STORE_HEADER
);
1345 VolatileVariableStore
->Signature
= VARIABLE_STORE_SIGNATURE
;
1346 VolatileVariableStore
->Size
= VARIABLE_STORE_SIZE
;
1347 VolatileVariableStore
->Format
= VARIABLE_STORE_FORMATTED
;
1348 VolatileVariableStore
->State
= VARIABLE_STORE_HEALTHY
;
1349 VolatileVariableStore
->Reserved
= 0;
1350 VolatileVariableStore
->Reserved1
= 0;
1353 // Get non volatile varaible store
1356 TempVariableStoreHeader
= (UINT64
) PcdGet32 (PcdFlashNvStorageVariableBase
);
1357 VariableStoreEntry
.Base
= TempVariableStoreHeader
+ \
1358 (((EFI_FIRMWARE_VOLUME_HEADER
*) (UINTN
) (TempVariableStoreHeader
)) -> HeaderLength
);
1359 VariableStoreEntry
.Length
= (UINT64
) PcdGet32 (PcdFlashNvStorageVariableSize
) - \
1360 (((EFI_FIRMWARE_VOLUME_HEADER
*) (UINTN
) (TempVariableStoreHeader
)) -> HeaderLength
);
1362 // Mark the variable storage region of the FLASH as RUNTIME
1364 BaseAddress
= VariableStoreEntry
.Base
& (~EFI_PAGE_MASK
);
1365 Length
= VariableStoreEntry
.Length
+ (VariableStoreEntry
.Base
- BaseAddress
);
1366 Length
= (Length
+ EFI_PAGE_SIZE
- 1) & (~EFI_PAGE_MASK
);
1368 Status
= gDS
->GetMemorySpaceDescriptor (BaseAddress
, &GcdDescriptor
);
1369 if (EFI_ERROR (Status
)) {
1370 gBS
->FreePool (mVariableModuleGlobal
);
1371 gBS
->FreePool (VolatileVariableStore
);
1372 return EFI_UNSUPPORTED
;
1375 Status
= gDS
->SetMemorySpaceAttributes (
1378 GcdDescriptor
.Attributes
| EFI_MEMORY_RUNTIME
1380 if (EFI_ERROR (Status
)) {
1381 gBS
->FreePool (mVariableModuleGlobal
);
1382 gBS
->FreePool (VolatileVariableStore
);
1383 return EFI_UNSUPPORTED
;
1386 // Get address of non volatile variable store base
1388 mVariableModuleGlobal
->VariableGlobal
[Physical
].NonVolatileVariableBase
= VariableStoreEntry
.Base
;
1394 // Find the Correct Instance of the FV Block Service.
1397 CurrPtr
= (CHAR8
*) ((UINTN
) mVariableModuleGlobal
->VariableGlobal
[Physical
].NonVolatileVariableBase
);
1398 while (EfiFvbGetPhysicalAddress (Instance
, &FvVolHdr
) == EFI_SUCCESS
) {
1399 FwVolHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) ((UINTN
) FvVolHdr
);
1400 if (CurrPtr
>= (CHAR8
*) FwVolHeader
&& CurrPtr
< (((CHAR8
*) FwVolHeader
) + FwVolHeader
->FvLength
)) {
1401 mVariableModuleGlobal
->FvbInstance
= Instance
;
1408 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) CurrPtr
;
1409 if (GetVariableStoreStatus (VariableStoreHeader
) == EfiValid
) {
1410 if (~VariableStoreHeader
->Size
== 0) {
1411 Status
= UpdateVariableStore (
1412 &mVariableModuleGlobal
->VariableGlobal
[Physical
],
1415 mVariableModuleGlobal
->FvbInstance
,
1416 (UINTN
) &VariableStoreHeader
->Size
,
1418 (UINT8
*) &VariableStoreEntry
.Length
1421 if (EFI_ERROR (Status
)) {
1426 mVariableModuleGlobal
->VariableGlobal
[Physical
].NonVolatileVariableBase
= (EFI_PHYSICAL_ADDRESS
) ((UINTN
) CurrPtr
);
1428 // Parse non-volatile variable data and get last variable offset
1430 NextVariable
= (VARIABLE_HEADER
*) (CurrPtr
+ sizeof (VARIABLE_STORE_HEADER
));
1431 Status
= EFI_SUCCESS
;
1433 while (IsValidVariableHeader (NextVariable
)) {
1434 NextVariable
= GetNextVariablePtr (NextVariable
);
1437 mVariableModuleGlobal
->NonVolatileLastVariableOffset
= (UINTN
) NextVariable
- (UINTN
) CurrPtr
;
1440 // Check if the free area is blow a threshold
1442 if ((((VARIABLE_STORE_HEADER
*)((UINTN
) CurrPtr
))->Size
- mVariableModuleGlobal
->NonVolatileLastVariableOffset
) < VARIABLE_RECLAIM_THRESHOLD
) {
1444 mVariableModuleGlobal
->VariableGlobal
[Physical
].NonVolatileVariableBase
,
1445 &mVariableModuleGlobal
->NonVolatileLastVariableOffset
,
1450 if (EFI_ERROR (Status
)) {
1451 gBS
->FreePool (mVariableModuleGlobal
);
1452 gBS
->FreePool (VolatileVariableStore
);
1457 // Check if the free area is really free.
1459 for (Index
= mVariableModuleGlobal
->NonVolatileLastVariableOffset
; Index
< VariableStoreHeader
->Size
; Index
++) {
1460 Data
= ((UINT8
*) (UINTN
) mVariableModuleGlobal
->VariableGlobal
[Physical
].NonVolatileVariableBase
)[Index
];
1463 // There must be something wrong in variable store, do reclaim operation.
1466 mVariableModuleGlobal
->VariableGlobal
[Physical
].NonVolatileVariableBase
,
1467 &mVariableModuleGlobal
->NonVolatileLastVariableOffset
,
1475 if (EFI_ERROR (Status
)) {
1476 gBS
->FreePool (mVariableModuleGlobal
);
1477 gBS
->FreePool (VolatileVariableStore
);