3 Copyright (c) 2006, 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
;
39 Determine the length of null terminated char16 array.
43 String Null-terminated CHAR16 array pointer.
47 UINT32 Number of bytes in the string, including the double NULL at the end;
59 while (0 != String
[Count
]) {
63 return (Count
* 2) + 2;
68 IsValidVariableHeader (
69 IN VARIABLE_HEADER
*Variable
75 This code checks if variable header is valid or not.
78 Variable Pointer to the Variable Header.
81 TRUE Variable header is valid.
82 FALSE Variable header is not valid.
86 if (Variable
== NULL
||
87 Variable
->StartId
!= VARIABLE_DATA
||
88 (sizeof (VARIABLE_HEADER
) + Variable
->NameSize
+ Variable
->DataSize
) > MAX_VARIABLE_SIZE
99 IN VARIABLE_GLOBAL
*Global
,
101 IN BOOLEAN SetByIndex
,
103 IN UINTN DataPtrIndex
,
111 This function writes data to the FWH at the correct LBA even if the LBAs
116 Global Pointer to VARAIBLE_GLOBAL structure
117 Volatile If the Variable is Volatile or Non-Volatile
118 SetByIndex TRUE: Target pointer is given as index
119 FALSE: Target pointer is absolute
120 Instance Instance of FV Block services
121 DataPtrIndex Pointer to the Data from the end of VARIABLE_STORE_HEADER
123 DataSize Size of data to be written.
124 Buffer Pointer to the buffer from which data is written
132 EFI_FV_BLOCK_MAP_ENTRY
*PtrBlockMapEntry
;
140 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
141 VARIABLE_STORE_HEADER
*VolatileBase
;
142 EFI_PHYSICAL_ADDRESS FvVolHdr
;
143 EFI_PHYSICAL_ADDRESS DataPtr
;
147 DataPtr
= DataPtrIndex
;
150 // Check if the Data is Volatile
153 EfiFvbGetPhysicalAddress (Instance
, &FvVolHdr
);
154 FwVolHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) ((UINTN
) FvVolHdr
);
156 // Data Pointer should point to the actual Address where data is to be
160 DataPtr
+= Global
->NonVolatileVariableBase
;
163 if ((DataPtr
+ DataSize
) >= ((EFI_PHYSICAL_ADDRESS
) (UINTN
) ((UINT8
*) FwVolHeader
+ FwVolHeader
->FvLength
))) {
164 return EFI_INVALID_PARAMETER
;
168 // Data Pointer should point to the actual Address where data is to be
171 VolatileBase
= (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->VolatileVariableBase
);
173 DataPtr
+= Global
->VolatileVariableBase
;
176 if ((DataPtr
+ DataSize
) >= ((UINTN
) ((UINT8
*) VolatileBase
+ VolatileBase
->Size
))) {
177 return EFI_INVALID_PARAMETER
;
181 // If Volatile Variable just do a simple mem copy.
184 CopyMem ((UINT8
*) ((UINTN
) DataPtr
), Buffer
, DataSize
);
188 // If we are here we are dealing with Non-Volatile Variables
190 LinearOffset
= (UINTN
) FwVolHeader
;
191 CurrWritePtr
= (UINTN
) DataPtr
;
192 CurrWriteSize
= DataSize
;
196 if (CurrWritePtr
< LinearOffset
) {
197 return EFI_INVALID_PARAMETER
;
200 for (PtrBlockMapEntry
= FwVolHeader
->FvBlockMap
; PtrBlockMapEntry
->NumBlocks
!= 0; PtrBlockMapEntry
++) {
201 for (BlockIndex2
= 0; BlockIndex2
< PtrBlockMapEntry
->NumBlocks
; BlockIndex2
++) {
203 // Check to see if the Variable Writes are spanning through multiple
206 if ((CurrWritePtr
>= LinearOffset
) && (CurrWritePtr
< LinearOffset
+ PtrBlockMapEntry
->BlockLength
)) {
207 if ((CurrWritePtr
+ CurrWriteSize
) <= (LinearOffset
+ PtrBlockMapEntry
->BlockLength
)) {
208 Status
= EfiFvbWriteBlock (
211 (UINTN
) (CurrWritePtr
- LinearOffset
),
215 if (EFI_ERROR (Status
)) {
219 Size
= (UINT32
) (LinearOffset
+ PtrBlockMapEntry
->BlockLength
- CurrWritePtr
);
220 Status
= EfiFvbWriteBlock (
223 (UINTN
) (CurrWritePtr
- LinearOffset
),
227 if (EFI_ERROR (Status
)) {
231 CurrWritePtr
= LinearOffset
+ PtrBlockMapEntry
->BlockLength
;
232 CurrBuffer
= CurrBuffer
+ Size
;
233 CurrWriteSize
= CurrWriteSize
- Size
;
237 LinearOffset
+= PtrBlockMapEntry
->BlockLength
;
245 VARIABLE_STORE_STATUS
247 GetVariableStoreStatus (
248 IN VARIABLE_STORE_HEADER
*VarStoreHeader
254 This code gets the current status of Variable Store.
258 VarStoreHeader Pointer to the Variable Store Header.
262 EfiRaw Variable store status is raw
263 EfiValid Variable store status is valid
264 EfiInvalid Variable store status is invalid
268 if (VarStoreHeader
->Signature
== VARIABLE_STORE_SIGNATURE
&&
269 VarStoreHeader
->Format
== VARIABLE_STORE_FORMATTED
&&
270 VarStoreHeader
->State
== VARIABLE_STORE_HEALTHY
274 } else if (VarStoreHeader
->Signature
== 0xffffffff &&
275 VarStoreHeader
->Size
== 0xffffffff &&
276 VarStoreHeader
->Format
== 0xff &&
277 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
));
316 IN VARIABLE_HEADER
*Variable
322 This code gets the pointer to the next variable header.
326 Variable Pointer to the Variable Header.
330 VARIABLE_HEADER* Pointer to next variable header.
334 if (!IsValidVariableHeader (Variable
)) {
338 // Be careful about pad size for alignment
340 return (VARIABLE_HEADER
*) ((UINTN
) GetVariableDataPtr (Variable
) + Variable
->DataSize
+ GET_PAD_SIZE (Variable
->DataSize
));
346 IN VARIABLE_STORE_HEADER
*VarStoreHeader
352 This code gets the pointer to the last variable memory pointer byte
356 VarStoreHeader Pointer to the Variable Store Header.
360 VARIABLE_HEADER* Pointer to last unavailable Variable Header
365 // The end of variable store
367 return (VARIABLE_HEADER
*) ((UINTN
) VarStoreHeader
+ VarStoreHeader
->Size
);
373 IN EFI_PHYSICAL_ADDRESS VariableBase
,
374 OUT UINTN
*LastVariableOffset
,
375 IN BOOLEAN IsVolatile
381 Variable store garbage collection and reclaim operation
385 VariableBase Base address of variable store
386 LastVariableOffset Offset of last variable
387 IsVolatile The variable store is volatile or not,
388 if it is non-volatile, need FTW
396 VARIABLE_HEADER
*Variable
;
397 VARIABLE_HEADER
*NextVariable
;
398 VARIABLE_STORE_HEADER
*VariableStoreHeader
;
400 UINTN ValidBufferSize
;
405 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) ((UINTN
) VariableBase
);
408 // Start Pointers for the variable.
410 Variable
= (VARIABLE_HEADER
*) (VariableStoreHeader
+ 1);
412 ValidBufferSize
= sizeof (VARIABLE_STORE_HEADER
);
414 while (IsValidVariableHeader (Variable
)) {
415 NextVariable
= GetNextVariablePtr (Variable
);
416 if (Variable
->State
== VAR_ADDED
) {
417 VariableSize
= (UINTN
) NextVariable
- (UINTN
) Variable
;
418 ValidBufferSize
+= VariableSize
;
421 Variable
= NextVariable
;
424 Status
= gBS
->AllocatePool (
427 (VOID
**) &ValidBuffer
429 if (EFI_ERROR (Status
)) {
433 SetMem (ValidBuffer
, ValidBufferSize
, 0xff);
435 CurrPtr
= ValidBuffer
;
438 // Copy variable store header
440 CopyMem (CurrPtr
, VariableStoreHeader
, sizeof (VARIABLE_STORE_HEADER
));
441 CurrPtr
+= sizeof (VARIABLE_STORE_HEADER
);
444 // Start Pointers for the variable.
446 Variable
= (VARIABLE_HEADER
*) (VariableStoreHeader
+ 1);
448 while (IsValidVariableHeader (Variable
)) {
449 NextVariable
= GetNextVariablePtr (Variable
);
450 if (Variable
->State
== VAR_ADDED
) {
451 VariableSize
= (UINTN
) NextVariable
- (UINTN
) Variable
;
452 CopyMem (CurrPtr
, (UINT8
*) Variable
, VariableSize
);
453 CurrPtr
+= VariableSize
;
456 Variable
= NextVariable
;
461 // If volatile variable store, just copy valid buffer
463 SetMem ((UINT8
*) (UINTN
) VariableBase
, VariableStoreHeader
->Size
, 0xff);
464 CopyMem ((UINT8
*) (UINTN
) VariableBase
, ValidBuffer
, ValidBufferSize
);
465 *LastVariableOffset
= ValidBufferSize
;
466 Status
= EFI_SUCCESS
;
469 // If non-volatile variable store, perform FTW here.
471 Status
= FtwVariableSpace (
476 if (!EFI_ERROR (Status
)) {
477 *LastVariableOffset
= ValidBufferSize
;
481 gBS
->FreePool (ValidBuffer
);
483 if (EFI_ERROR (Status
)) {
484 *LastVariableOffset
= 0;
493 IN CHAR16
*VariableName
,
494 IN EFI_GUID
*VendorGuid
,
495 OUT VARIABLE_POINTER_TRACK
*PtrTrack
,
496 IN VARIABLE_GLOBAL
*Global
502 This code finds variable in storage blocks (Volatile or Non-Volatile)
506 VariableName Name of the variable to be found
507 VendorGuid Vendor GUID to be found.
508 PtrTrack Variable Track Pointer structure that contains
509 Variable Information.
510 Contains the pointer of Variable header.
511 Global VARIABLE_GLOBAL pointer
519 VARIABLE_HEADER
*Variable
[2];
520 VARIABLE_STORE_HEADER
*VariableStoreHeader
[2];
524 // 0: Non-Volatile, 1: Volatile
526 VariableStoreHeader
[0] = (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->NonVolatileVariableBase
);
527 VariableStoreHeader
[1] = (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->VolatileVariableBase
);
530 // Start Pointers for the variable.
531 // Actual Data Pointer where data can be written.
533 Variable
[0] = (VARIABLE_HEADER
*) (VariableStoreHeader
[0] + 1);
534 Variable
[1] = (VARIABLE_HEADER
*) (VariableStoreHeader
[1] + 1);
536 if (VariableName
[0] != 0 && VendorGuid
== NULL
) {
537 return EFI_INVALID_PARAMETER
;
540 // Find the variable by walk through non-volatile and volatile variable store
542 for (Index
= 0; Index
< 2; Index
++) {
543 PtrTrack
->StartPtr
= (VARIABLE_HEADER
*) (VariableStoreHeader
[Index
] + 1);
544 PtrTrack
->EndPtr
= GetEndPointer (VariableStoreHeader
[Index
]);
546 while (IsValidVariableHeader (Variable
[Index
]) && (Variable
[Index
] <= GetEndPointer (VariableStoreHeader
[Index
]))) {
547 if (Variable
[Index
]->State
== VAR_ADDED
) {
548 if (!(EfiAtRuntime () && !(Variable
[Index
]->Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
))) {
549 if (VariableName
[0] == 0) {
550 PtrTrack
->CurrPtr
= Variable
[Index
];
551 PtrTrack
->Volatile
= (BOOLEAN
) Index
;
554 if (CompareGuid (VendorGuid
, &Variable
[Index
]->VendorGuid
)) {
555 if (!CompareMem (VariableName
, GET_VARIABLE_NAME_PTR (Variable
[Index
]), ArrayLength (VariableName
))) {
556 PtrTrack
->CurrPtr
= Variable
[Index
];
557 PtrTrack
->Volatile
= (BOOLEAN
) Index
;
565 Variable
[Index
] = GetNextVariablePtr (Variable
[Index
]);
574 PtrTrack
->CurrPtr
= NULL
;
575 return EFI_NOT_FOUND
;
581 IN CHAR16
*VariableName
,
582 IN EFI_GUID
* VendorGuid
,
583 OUT UINT32
*Attributes OPTIONAL
,
584 IN OUT UINTN
*DataSize
,
586 IN VARIABLE_GLOBAL
* Global
,
593 This code finds variable in storage blocks (Volatile or Non-Volatile)
597 VariableName Name of Variable to be found
598 VendorGuid Variable vendor GUID
599 Attributes OPTIONAL Attribute value of the variable found
600 DataSize Size of Data found. If size is less than the
601 data, this value contains the required size.
603 Global Pointer to VARIABLE_GLOBAL structure
604 Instance Instance of the Firmware Volume.
612 VARIABLE_POINTER_TRACK Variable
;
616 if (VariableName
== NULL
|| VendorGuid
== NULL
|| DataSize
== NULL
) {
617 return EFI_INVALID_PARAMETER
;
620 // Find existing variable
622 Status
= FindVariable (VariableName
, VendorGuid
, &Variable
, Global
);
624 if (Variable
.CurrPtr
== NULL
|| EFI_ERROR (Status
)) {
630 VarDataSize
= Variable
.CurrPtr
->DataSize
;
631 if (*DataSize
>= VarDataSize
) {
633 return EFI_INVALID_PARAMETER
;
636 CopyMem (Data
, GetVariableDataPtr (Variable
.CurrPtr
), VarDataSize
);
637 if (Attributes
!= NULL
) {
638 *Attributes
= Variable
.CurrPtr
->Attributes
;
641 *DataSize
= VarDataSize
;
644 *DataSize
= VarDataSize
;
645 return EFI_BUFFER_TOO_SMALL
;
651 GetNextVariableName (
652 IN OUT UINTN
*VariableNameSize
,
653 IN OUT CHAR16
*VariableName
,
654 IN OUT EFI_GUID
*VendorGuid
,
655 IN VARIABLE_GLOBAL
*Global
,
662 This code Finds the Next available variable
666 VariableNameSize Size of the variable
667 VariableName Pointer to variable name
668 VendorGuid Variable Vendor Guid
669 Global VARIABLE_GLOBAL structure pointer.
678 VARIABLE_POINTER_TRACK Variable
;
682 if (VariableNameSize
== NULL
|| VariableName
== NULL
|| VendorGuid
== NULL
) {
683 return EFI_INVALID_PARAMETER
;
686 Status
= FindVariable (VariableName
, VendorGuid
, &Variable
, Global
);
688 if (Variable
.CurrPtr
== NULL
|| EFI_ERROR (Status
)) {
692 if (VariableName
[0] != 0) {
694 // If variable name is not NULL, get next variable
696 Variable
.CurrPtr
= GetNextVariablePtr (Variable
.CurrPtr
);
701 // If both volatile and non-volatile variable store are parsed,
704 if (Variable
.CurrPtr
>= Variable
.EndPtr
|| Variable
.CurrPtr
== NULL
) {
705 Variable
.Volatile
= (BOOLEAN
) (Variable
.Volatile
^ ((BOOLEAN
) 0x1));
706 if (Variable
.Volatile
) {
707 Variable
.StartPtr
= (VARIABLE_HEADER
*) ((UINTN
) (Global
->VolatileVariableBase
+ sizeof (VARIABLE_STORE_HEADER
)));
708 Variable
.EndPtr
= (VARIABLE_HEADER
*) GetEndPointer ((VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->VolatileVariableBase
));
710 return EFI_NOT_FOUND
;
713 Variable
.CurrPtr
= Variable
.StartPtr
;
714 if (!IsValidVariableHeader (Variable
.CurrPtr
)) {
721 if (IsValidVariableHeader (Variable
.CurrPtr
) && Variable
.CurrPtr
->State
== VAR_ADDED
) {
722 if (!(EfiAtRuntime () && !(Variable
.CurrPtr
->Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
))) {
723 VarNameSize
= Variable
.CurrPtr
->NameSize
;
724 if (VarNameSize
<= *VariableNameSize
) {
727 GET_VARIABLE_NAME_PTR (Variable
.CurrPtr
),
732 &Variable
.CurrPtr
->VendorGuid
,
735 Status
= EFI_SUCCESS
;
737 Status
= EFI_BUFFER_TOO_SMALL
;
740 *VariableNameSize
= VarNameSize
;
745 Variable
.CurrPtr
= GetNextVariablePtr (Variable
.CurrPtr
);
748 return EFI_NOT_FOUND
;
754 IN CHAR16
*VariableName
,
755 IN EFI_GUID
*VendorGuid
,
756 IN UINT32 Attributes
,
759 IN VARIABLE_GLOBAL
*Global
,
760 IN UINTN
*VolatileOffset
,
761 IN UINTN
*NonVolatileOffset
,
768 This code sets variable in storage blocks (Volatile or Non-Volatile)
772 VariableName Name of Variable to be found
773 VendorGuid Variable vendor GUID
774 Attributes Attribute value of the variable found
775 DataSize Size of Data found. If size is less than the
776 data, this value contains the required size.
778 Global Pointer to VARIABLE_GLOBAL structure
779 VolatileOffset The offset of last volatile variable
780 NonVolatileOffset The offset of last non-volatile variable
781 Instance Instance of the Firmware Volume.
786 EFI_INVALID_PARAMETER - Invalid parameter
787 EFI_SUCCESS - Set successfully
788 EFI_OUT_OF_RESOURCES - Resource not enough to set variable
789 EFI_NOT_FOUND - Not found
793 VARIABLE_POINTER_TRACK Variable
;
795 VARIABLE_HEADER
*NextVariable
;
805 if (VariableName
== NULL
|| VariableName
[0] == 0 || VendorGuid
== NULL
) {
806 return EFI_INVALID_PARAMETER
;
809 Status
= FindVariable (VariableName
, VendorGuid
, &Variable
, Global
);
811 if (Status
== EFI_INVALID_PARAMETER
) {
815 // The size of the VariableName, including the Unicode Null in bytes plus
816 // the DataSize is limited to maximum size of MAX_VARIABLE_SIZE (1024) bytes.
818 else if ((DataSize
> MAX_VARIABLE_SIZE
) ||
819 (sizeof (VARIABLE_HEADER
) + ArrayLength (VariableName
) + DataSize
> MAX_VARIABLE_SIZE
)) {
820 return EFI_INVALID_PARAMETER
;
823 // Make sure if runtime bit is set, boot service bit is set also
825 else if ((Attributes
& (EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
)) == EFI_VARIABLE_RUNTIME_ACCESS
827 return EFI_INVALID_PARAMETER
;
830 // Runtime but Attribute is not Runtime
832 else if (EfiAtRuntime () && Attributes
&& !(Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
)) {
833 return EFI_INVALID_PARAMETER
;
836 // Cannot set volatile variable in Runtime
838 else if (EfiAtRuntime () && Attributes
&& !(Attributes
& EFI_VARIABLE_NON_VOLATILE
)) {
839 return EFI_INVALID_PARAMETER
;
842 // Setting a data variable with no access, or zero DataSize attributes
843 // specified causes it to be deleted.
845 else if (DataSize
== 0 || Attributes
== 0) {
846 if (!EFI_ERROR (Status
)) {
847 State
= Variable
.CurrPtr
->State
;
848 State
&= VAR_DELETED
;
850 Status
= UpdateVariableStore (
855 (UINTN
) &Variable
.CurrPtr
->State
,
859 if (EFI_ERROR (Status
)) {
866 return EFI_NOT_FOUND
;
868 if (!EFI_ERROR (Status
)) {
870 // If the variable is marked valid and the same data has been passed in
871 // then return to the caller immediately.
873 if (Variable
.CurrPtr
->DataSize
== DataSize
&&
874 !CompareMem (Data
, GetVariableDataPtr (Variable
.CurrPtr
), DataSize
)
877 } else if (Variable
.CurrPtr
->State
== VAR_ADDED
) {
879 // Mark the old variable as in delete transition
881 State
= Variable
.CurrPtr
->State
;
882 State
&= VAR_IN_DELETED_TRANSITION
;
884 Status
= UpdateVariableStore (
889 (UINTN
) &Variable
.CurrPtr
->State
,
893 if (EFI_ERROR (Status
)) {
899 // Create a new variable and copy the data.
901 // Tricky part: Use scratch data area at the end of volatile variable store
902 // as a temporary storage.
904 NextVariable
= GetEndPointer ((VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->VolatileVariableBase
));
906 SetMem (NextVariable
, SCRATCH_SIZE
, 0xff);
908 NextVariable
->StartId
= VARIABLE_DATA
;
909 NextVariable
->Attributes
= Attributes
;
911 // NextVariable->State = VAR_ADDED;
913 NextVariable
->Reserved
= 0;
914 VarNameOffset
= sizeof (VARIABLE_HEADER
);
915 VarNameSize
= ArrayLength (VariableName
);
917 (UINT8
*) ((UINTN
) NextVariable
+ VarNameOffset
),
921 VarDataOffset
= VarNameOffset
+ VarNameSize
+ GET_PAD_SIZE (VarNameSize
);
923 (UINT8
*) ((UINTN
) NextVariable
+ VarDataOffset
),
927 CopyMem (&NextVariable
->VendorGuid
, VendorGuid
, sizeof (EFI_GUID
));
929 // There will be pad bytes after Data, the NextVariable->NameSize and
930 // NextVariable->DataSize should not include pad size so that variable
931 // service can get actual size in GetVariable
933 NextVariable
->NameSize
= (UINT32
)VarNameSize
;
934 NextVariable
->DataSize
= (UINT32
)DataSize
;
937 // The actual size of the variable that stores in storage should
940 VarSize
= VarDataOffset
+ DataSize
+ GET_PAD_SIZE (DataSize
);
941 if (Attributes
& EFI_VARIABLE_NON_VOLATILE
) {
942 if ((UINT32
) (VarSize
+*NonVolatileOffset
) >
943 ((VARIABLE_STORE_HEADER
*) ((UINTN
) (Global
->NonVolatileVariableBase
)))->Size
945 if (EfiAtRuntime ()) {
946 return EFI_OUT_OF_RESOURCES
;
949 // Perform garbage collection & reclaim operation
951 Status
= Reclaim (Global
->NonVolatileVariableBase
, NonVolatileOffset
, FALSE
);
952 if (EFI_ERROR (Status
)) {
956 // If still no enough space, return out of resources
958 if ((UINT32
) (VarSize
+*NonVolatileOffset
) >
959 ((VARIABLE_STORE_HEADER
*) ((UINTN
) (Global
->NonVolatileVariableBase
)))->Size
961 return EFI_OUT_OF_RESOURCES
;
968 // 1. Write variable header
969 // 2. Write variable data
970 // 3. Set variable state to valid
975 Status
= UpdateVariableStore (
981 sizeof (VARIABLE_HEADER
),
982 (UINT8
*) NextVariable
985 if (EFI_ERROR (Status
)) {
991 Status
= UpdateVariableStore (
996 *NonVolatileOffset
+ sizeof (VARIABLE_HEADER
),
997 (UINT32
) VarSize
- sizeof (VARIABLE_HEADER
),
998 (UINT8
*) NextVariable
+ sizeof (VARIABLE_HEADER
)
1001 if (EFI_ERROR (Status
)) {
1007 NextVariable
->State
= VAR_ADDED
;
1008 Status
= UpdateVariableStore (
1014 sizeof (VARIABLE_HEADER
),
1015 (UINT8
*) NextVariable
1018 if (EFI_ERROR (Status
)) {
1022 *NonVolatileOffset
= *NonVolatileOffset
+ VarSize
;
1025 if (EfiAtRuntime ()) {
1026 return EFI_INVALID_PARAMETER
;
1029 if ((UINT32
) (VarSize
+*VolatileOffset
) >
1030 ((VARIABLE_STORE_HEADER
*) ((UINTN
) (Global
->VolatileVariableBase
)))->Size
1033 // Perform garbage collection & reclaim operation
1035 Status
= Reclaim (Global
->VolatileVariableBase
, VolatileOffset
, TRUE
);
1036 if (EFI_ERROR (Status
)) {
1040 // If still no enough space, return out of resources
1042 if ((UINT32
) (VarSize
+*VolatileOffset
) >
1043 ((VARIABLE_STORE_HEADER
*) ((UINTN
) (Global
->VolatileVariableBase
)))->Size
1045 return EFI_OUT_OF_RESOURCES
;
1051 NextVariable
->State
= VAR_ADDED
;
1052 Status
= UpdateVariableStore (
1059 (UINT8
*) NextVariable
1062 if (EFI_ERROR (Status
)) {
1066 *VolatileOffset
= *VolatileOffset
+ VarSize
;
1069 // Mark the old variable as deleted
1071 if (!Reclaimed
&& !EFI_ERROR (Status
) && Variable
.CurrPtr
!= NULL
) {
1072 State
= Variable
.CurrPtr
->State
;
1073 State
&= VAR_DELETED
;
1075 Status
= UpdateVariableStore (
1080 (UINTN
) &Variable
.CurrPtr
->State
,
1085 if (EFI_ERROR (Status
)) {
1094 #if (EFI_SPECIFICATION_VERSION >= 0x00020000)
1098 IN UINT32 Attributes
,
1099 OUT UINT64
*MaximumVariableStorageSize
,
1100 OUT UINT64
*RemainingVariableStorageSize
,
1101 OUT UINT64
*MaximumVariableSize
,
1102 IN VARIABLE_GLOBAL
*Global
,
1107 Routine Description:
1109 This code returns information about the EFI variables.
1113 Attributes Attributes bitmask to specify the type of variables
1114 on which to return information.
1115 MaximumVariableStorageSize Pointer to the maximum size of the storage space available
1116 for the EFI variables associated with the attributes specified.
1117 RemainingVariableStorageSize Pointer to the remaining size of the storage space available
1118 for the EFI variables associated with the attributes specified.
1119 MaximumVariableSize Pointer to the maximum size of the individual EFI variables
1120 associated with the attributes specified.
1121 Global Pointer to VARIABLE_GLOBAL structure.
1122 Instance Instance of the Firmware Volume.
1127 EFI_INVALID_PARAMETER - An invalid combination of attribute bits was supplied.
1128 EFI_SUCCESS - Query successfully.
1129 EFI_UNSUPPORTED - The attribute is not supported on this platform.
1133 VARIABLE_HEADER
*Variable
;
1134 VARIABLE_HEADER
*NextVariable
;
1135 UINT64 VariableSize
;
1136 VARIABLE_STORE_HEADER
*VariableStoreHeader
;
1138 if(MaximumVariableStorageSize
== NULL
|| RemainingVariableStorageSize
== NULL
|| MaximumVariableSize
== NULL
) {
1139 return EFI_INVALID_PARAMETER
;
1142 if((Attributes
& (EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
)) == 0) {
1144 // Make sure the Attributes combination is supported by the platform.
1146 return EFI_UNSUPPORTED
;
1147 } else if ((Attributes
& (EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
)) == EFI_VARIABLE_RUNTIME_ACCESS
) {
1149 // Make sure if runtime bit is set, boot service bit is set also.
1151 return EFI_INVALID_PARAMETER
;
1152 } else if (EfiAtRuntime () && !(Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
)) {
1154 // Make sure RT Attribute is set if we are in Runtime phase.
1156 return EFI_INVALID_PARAMETER
;
1159 if((Attributes
& EFI_VARIABLE_NON_VOLATILE
) == 0) {
1161 // Query is Volatile related.
1163 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->VolatileVariableBase
);
1166 // Query is Non-Volatile related.
1168 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->NonVolatileVariableBase
);
1172 // Now let's fill *MaximumVariableStorageSize *RemainingVariableStorageSize
1173 // with the storage size (excluding the storage header size).
1175 *MaximumVariableStorageSize
= VariableStoreHeader
->Size
- sizeof (VARIABLE_STORE_HEADER
);
1176 *RemainingVariableStorageSize
= VariableStoreHeader
->Size
- sizeof (VARIABLE_STORE_HEADER
);
1179 // Let *MaximumVariableSize be MAX_VARIABLE_SIZE.
1181 *MaximumVariableSize
= MAX_VARIABLE_SIZE
;
1184 // Point to the starting address of the variables.
1186 Variable
= (VARIABLE_HEADER
*) (VariableStoreHeader
+ 1);
1189 // Now walk through the related variable store.
1191 while (IsValidVariableHeader (Variable
) && (Variable
< GetEndPointer (VariableStoreHeader
))) {
1192 NextVariable
= GetNextVariablePtr (Variable
);
1193 VariableSize
= (UINT64
) (UINTN
) NextVariable
- (UINT64
) (UINTN
) Variable
;
1195 if (EfiAtRuntime ()) {
1197 // we don't take the state of the variables in mind
1198 // when calculating RemainingVariableStorageSize,
1199 // since the space occupied by variables not marked with
1200 // VAR_ADDED is not allowed to be reclaimed in Runtime.
1202 *RemainingVariableStorageSize
-= VariableSize
;
1205 // Only care about Variables with State VAR_ADDED,because
1206 // the space not marked as VAR_ADDED is reclaimable now.
1208 if (Variable
->State
== VAR_ADDED
) {
1209 *RemainingVariableStorageSize
-= VariableSize
;
1214 // Go to the next one
1216 Variable
= NextVariable
;
1225 VariableCommonInitialize (
1226 IN EFI_HANDLE ImageHandle
,
1227 IN EFI_SYSTEM_TABLE
*SystemTable
1231 Routine Description:
1232 This function does common initialization for variable services
1236 ImageHandle - The firmware allocated handle for the EFI image.
1237 SystemTable - A pointer to the EFI System Table.
1243 EFI_NOT_FOUND - Variable store area not found.
1244 EFI_UNSUPPORTED - Currently only one non-volatile variable store is supported.
1245 EFI_SUCCESS - Variable services successfully initialized.
1250 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
1252 VARIABLE_STORE_HEADER
*VolatileVariableStore
;
1253 VARIABLE_STORE_HEADER
*VariableStoreHeader
;
1254 VARIABLE_HEADER
*NextVariable
;
1256 EFI_PHYSICAL_ADDRESS FvVolHdr
;
1258 UINT64 TempVariableStoreHeader
;
1260 EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor
;
1261 EFI_FLASH_SUBAREA_ENTRY VariableStoreEntry
;
1267 Status
= gBS
->AllocatePool (
1268 EfiRuntimeServicesData
,
1269 sizeof (ESAL_VARIABLE_GLOBAL
),
1270 (VOID
**) &mVariableModuleGlobal
1273 if (EFI_ERROR (Status
)) {
1277 // Allocate memory for volatile variable store
1279 Status
= gBS
->AllocatePool (
1280 EfiRuntimeServicesData
,
1281 VARIABLE_STORE_SIZE
+ SCRATCH_SIZE
,
1282 (VOID
**) &VolatileVariableStore
1285 if (EFI_ERROR (Status
)) {
1286 gBS
->FreePool (mVariableModuleGlobal
);
1290 SetMem (VolatileVariableStore
, VARIABLE_STORE_SIZE
+ SCRATCH_SIZE
, 0xff);
1293 // Variable Specific Data
1295 mVariableModuleGlobal
->VariableBase
[Physical
].VolatileVariableBase
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) VolatileVariableStore
;
1296 mVariableModuleGlobal
->VolatileLastVariableOffset
= sizeof (VARIABLE_STORE_HEADER
);
1298 VolatileVariableStore
->Signature
= VARIABLE_STORE_SIGNATURE
;
1299 VolatileVariableStore
->Size
= VARIABLE_STORE_SIZE
;
1300 VolatileVariableStore
->Format
= VARIABLE_STORE_FORMATTED
;
1301 VolatileVariableStore
->State
= VARIABLE_STORE_HEALTHY
;
1302 VolatileVariableStore
->Reserved
= 0;
1303 VolatileVariableStore
->Reserved1
= 0;
1306 // Get non volatile varaible store
1309 TempVariableStoreHeader
= (UINT64
) PcdGet32 (PcdFlashNvStorageVariableBase
);
1310 VariableStoreEntry
.Base
= TempVariableStoreHeader
+ \
1311 (((EFI_FIRMWARE_VOLUME_HEADER
*) (UINTN
) (TempVariableStoreHeader
)) -> HeaderLength
);
1312 VariableStoreEntry
.Length
= (UINT64
) PcdGet32 (PcdFlashNvStorageVariableSize
) - \
1313 (((EFI_FIRMWARE_VOLUME_HEADER
*) (UINTN
) (TempVariableStoreHeader
)) -> HeaderLength
);
1315 // Mark the variable storage region of the FLASH as RUNTIME
1317 BaseAddress
= VariableStoreEntry
.Base
& (~EFI_PAGE_MASK
);
1318 Length
= VariableStoreEntry
.Length
+ (VariableStoreEntry
.Base
- BaseAddress
);
1319 Length
= (Length
+ EFI_PAGE_SIZE
- 1) & (~EFI_PAGE_MASK
);
1321 Status
= gDS
->GetMemorySpaceDescriptor (BaseAddress
, &GcdDescriptor
);
1322 if (EFI_ERROR (Status
)) {
1323 gBS
->FreePool (mVariableModuleGlobal
);
1324 gBS
->FreePool (VolatileVariableStore
);
1325 return EFI_UNSUPPORTED
;
1328 Status
= gDS
->SetMemorySpaceAttributes (
1331 GcdDescriptor
.Attributes
| EFI_MEMORY_RUNTIME
1333 if (EFI_ERROR (Status
)) {
1334 gBS
->FreePool (mVariableModuleGlobal
);
1335 gBS
->FreePool (VolatileVariableStore
);
1336 return EFI_UNSUPPORTED
;
1339 // Get address of non volatile variable store base
1341 mVariableModuleGlobal
->VariableBase
[Physical
].NonVolatileVariableBase
= VariableStoreEntry
.Base
;
1347 // Find the Correct Instance of the FV Block Service.
1350 CurrPtr
= (CHAR8
*) ((UINTN
) mVariableModuleGlobal
->VariableBase
[Physical
].NonVolatileVariableBase
);
1351 while (EfiFvbGetPhysicalAddress (Instance
, &FvVolHdr
) == EFI_SUCCESS
) {
1352 FwVolHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) ((UINTN
) FvVolHdr
);
1353 if (CurrPtr
>= (CHAR8
*) FwVolHeader
&& CurrPtr
< (((CHAR8
*) FwVolHeader
) + FwVolHeader
->FvLength
)) {
1354 mVariableModuleGlobal
->FvbInstance
= Instance
;
1361 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) CurrPtr
;
1362 if (GetVariableStoreStatus (VariableStoreHeader
) == EfiValid
) {
1363 if (~VariableStoreHeader
->Size
== 0) {
1364 Status
= UpdateVariableStore (
1365 &mVariableModuleGlobal
->VariableBase
[Physical
],
1368 mVariableModuleGlobal
->FvbInstance
,
1369 (UINTN
) &VariableStoreHeader
->Size
,
1371 (UINT8
*) &VariableStoreEntry
.Length
1374 if (EFI_ERROR (Status
)) {
1379 mVariableModuleGlobal
->VariableBase
[Physical
].NonVolatileVariableBase
= (EFI_PHYSICAL_ADDRESS
) ((UINTN
) CurrPtr
);
1381 // Parse non-volatile variable data and get last variable offset
1383 NextVariable
= (VARIABLE_HEADER
*) (CurrPtr
+ sizeof (VARIABLE_STORE_HEADER
));
1384 Status
= EFI_SUCCESS
;
1386 while (IsValidVariableHeader (NextVariable
)) {
1387 NextVariable
= GetNextVariablePtr (NextVariable
);
1390 mVariableModuleGlobal
->NonVolatileLastVariableOffset
= (UINTN
) NextVariable
- (UINTN
) CurrPtr
;
1393 // Check if the free area is blow a threshold
1395 if ((((VARIABLE_STORE_HEADER
*)((UINTN
) CurrPtr
))->Size
- mVariableModuleGlobal
->NonVolatileLastVariableOffset
) < VARIABLE_RECLAIM_THRESHOLD
) {
1397 mVariableModuleGlobal
->VariableBase
[Physical
].NonVolatileVariableBase
,
1398 &mVariableModuleGlobal
->NonVolatileLastVariableOffset
,
1403 if (EFI_ERROR (Status
)) {
1404 gBS
->FreePool (mVariableModuleGlobal
);
1405 gBS
->FreePool (VolatileVariableStore
);
1410 // Check if the free area is really free.
1412 for (Index
= mVariableModuleGlobal
->NonVolatileLastVariableOffset
; Index
< VariableStoreHeader
->Size
; Index
++) {
1413 Data
= ((UINT8
*) (UINTN
) mVariableModuleGlobal
->VariableBase
[Physical
].NonVolatileVariableBase
)[Index
];
1416 // There must be something wrong in variable store, do reclaim operation.
1419 mVariableModuleGlobal
->VariableBase
[Physical
].NonVolatileVariableBase
,
1420 &mVariableModuleGlobal
->NonVolatileLastVariableOffset
,
1428 if (EFI_ERROR (Status
)) {
1429 gBS
->FreePool (mVariableModuleGlobal
);
1430 gBS
->FreePool (VolatileVariableStore
);