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.
18 Provide support functions for variable services.
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
128 EFI_INVALID_PARAMETER - Parameters not valid
129 EFI_SUCCESS - Variable store successfully updated
133 EFI_FV_BLOCK_MAP_ENTRY
*PtrBlockMapEntry
;
141 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
142 VARIABLE_STORE_HEADER
*VolatileBase
;
143 EFI_PHYSICAL_ADDRESS FvVolHdr
;
144 EFI_PHYSICAL_ADDRESS DataPtr
;
148 DataPtr
= DataPtrIndex
;
151 // Check if the Data is Volatile
154 EfiFvbGetPhysicalAddress (Instance
, &FvVolHdr
);
155 FwVolHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) ((UINTN
) FvVolHdr
);
157 // Data Pointer should point to the actual Address where data is to be
161 DataPtr
+= Global
->NonVolatileVariableBase
;
164 if ((DataPtr
+ DataSize
) >= ((EFI_PHYSICAL_ADDRESS
) (UINTN
) ((UINT8
*) FwVolHeader
+ FwVolHeader
->FvLength
))) {
165 return EFI_INVALID_PARAMETER
;
169 // Data Pointer should point to the actual Address where data is to be
172 VolatileBase
= (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->VolatileVariableBase
);
174 DataPtr
+= Global
->VolatileVariableBase
;
177 if ((DataPtr
+ DataSize
) >= ((UINTN
) ((UINT8
*) VolatileBase
+ VolatileBase
->Size
))) {
178 return EFI_INVALID_PARAMETER
;
182 // 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
),
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
;
243 VARIABLE_STORE_STATUS
245 GetVariableStoreStatus (
246 IN VARIABLE_STORE_HEADER
*VarStoreHeader
252 This code gets the current status of Variable Store.
256 VarStoreHeader Pointer to the Variable Store Header.
260 EfiRaw Variable store status is raw
261 EfiValid Variable store status is valid
262 EfiInvalid Variable store status is invalid
266 if (VarStoreHeader
->Signature
== VARIABLE_STORE_SIGNATURE
&&
267 VarStoreHeader
->Format
== VARIABLE_STORE_FORMATTED
&&
268 VarStoreHeader
->State
== VARIABLE_STORE_HEALTHY
272 } else if (VarStoreHeader
->Signature
== 0xffffffff &&
273 VarStoreHeader
->Size
== 0xffffffff &&
274 VarStoreHeader
->Format
== 0xff &&
275 VarStoreHeader
->State
== 0xff
287 IN VARIABLE_HEADER
*Variable
293 This code gets the pointer to the variable data.
297 Variable Pointer to the Variable Header.
301 UINT8* Pointer to Variable Data
306 // Be careful about pad size for alignment
308 return (UINT8
*) ((UINTN
) GET_VARIABLE_NAME_PTR (Variable
) + Variable
->NameSize
+ GET_PAD_SIZE (Variable
->NameSize
));
314 IN VARIABLE_HEADER
*Variable
320 This code gets the pointer to the next variable header.
324 Variable Pointer to the Variable Header.
328 VARIABLE_HEADER* Pointer to next variable header.
332 if (!IsValidVariableHeader (Variable
)) {
336 // Be careful about pad size for alignment
338 return (VARIABLE_HEADER
*) ((UINTN
) GetVariableDataPtr (Variable
) + Variable
->DataSize
+ GET_PAD_SIZE (Variable
->DataSize
));
344 IN VARIABLE_STORE_HEADER
*VarStoreHeader
350 This code gets the pointer to the last variable memory pointer byte
354 VarStoreHeader Pointer to the Variable Store Header.
358 VARIABLE_HEADER* Pointer to last unavailable Variable Header
363 // The end of variable store
365 return (VARIABLE_HEADER
*) ((UINTN
) VarStoreHeader
+ VarStoreHeader
->Size
);
371 IN EFI_PHYSICAL_ADDRESS VariableBase
,
372 OUT UINTN
*LastVariableOffset
,
373 IN BOOLEAN IsVolatile
379 Variable store garbage collection and reclaim operation
383 VariableBase Base address of variable store
384 LastVariableOffset Offset of last variable
385 IsVolatile The variable store is volatile or not,
386 if it is non-volatile, need FTW
394 VARIABLE_HEADER
*Variable
;
395 VARIABLE_HEADER
*NextVariable
;
396 VARIABLE_STORE_HEADER
*VariableStoreHeader
;
398 UINTN ValidBufferSize
;
403 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) ((UINTN
) VariableBase
);
406 // Start Pointers for the variable.
408 Variable
= (VARIABLE_HEADER
*) (VariableStoreHeader
+ 1);
410 ValidBufferSize
= sizeof (VARIABLE_STORE_HEADER
);
412 while (IsValidVariableHeader (Variable
)) {
413 NextVariable
= GetNextVariablePtr (Variable
);
414 if (Variable
->State
== VAR_ADDED
) {
415 VariableSize
= (UINTN
) NextVariable
- (UINTN
) Variable
;
416 ValidBufferSize
+= VariableSize
;
419 Variable
= NextVariable
;
422 Status
= gBS
->AllocatePool (
425 (VOID
**) &ValidBuffer
427 if (EFI_ERROR (Status
)) {
431 SetMem (ValidBuffer
, ValidBufferSize
, 0xff);
433 CurrPtr
= ValidBuffer
;
436 // Copy variable store header
438 CopyMem (CurrPtr
, VariableStoreHeader
, sizeof (VARIABLE_STORE_HEADER
));
439 CurrPtr
+= sizeof (VARIABLE_STORE_HEADER
);
442 // Start Pointers for the variable.
444 Variable
= (VARIABLE_HEADER
*) (VariableStoreHeader
+ 1);
446 while (IsValidVariableHeader (Variable
)) {
447 NextVariable
= GetNextVariablePtr (Variable
);
448 if (Variable
->State
== VAR_ADDED
) {
449 VariableSize
= (UINTN
) NextVariable
- (UINTN
) Variable
;
450 CopyMem (CurrPtr
, (UINT8
*) Variable
, VariableSize
);
451 CurrPtr
+= VariableSize
;
454 Variable
= NextVariable
;
459 // If volatile variable store, just copy valid buffer
461 SetMem ((UINT8
*) (UINTN
) VariableBase
, VariableStoreHeader
->Size
, 0xff);
462 CopyMem ((UINT8
*) (UINTN
) VariableBase
, ValidBuffer
, ValidBufferSize
);
463 *LastVariableOffset
= ValidBufferSize
;
464 Status
= EFI_SUCCESS
;
467 // If non-volatile variable store, perform FTW here.
469 Status
= FtwVariableSpace (
474 if (!EFI_ERROR (Status
)) {
475 *LastVariableOffset
= ValidBufferSize
;
479 gBS
->FreePool (ValidBuffer
);
481 if (EFI_ERROR (Status
)) {
482 *LastVariableOffset
= 0;
491 IN CHAR16
*VariableName
,
492 IN EFI_GUID
*VendorGuid
,
493 OUT VARIABLE_POINTER_TRACK
*PtrTrack
,
494 IN VARIABLE_GLOBAL
*Global
500 This code finds variable in storage blocks (Volatile or Non-Volatile)
504 VariableName Name of the variable to be found
505 VendorGuid Vendor GUID to be found.
506 PtrTrack Variable Track Pointer structure that contains
507 Variable Information.
508 Contains the pointer of Variable header.
509 Global VARIABLE_GLOBAL pointer
517 VARIABLE_HEADER
*Variable
[2];
518 VARIABLE_STORE_HEADER
*VariableStoreHeader
[2];
522 // 0: Non-Volatile, 1: Volatile
524 VariableStoreHeader
[0] = (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->NonVolatileVariableBase
);
525 VariableStoreHeader
[1] = (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->VolatileVariableBase
);
528 // Start Pointers for the variable.
529 // Actual Data Pointer where data can be written.
531 Variable
[0] = (VARIABLE_HEADER
*) (VariableStoreHeader
[0] + 1);
532 Variable
[1] = (VARIABLE_HEADER
*) (VariableStoreHeader
[1] + 1);
534 if (VariableName
[0] != 0 && VendorGuid
== NULL
) {
535 return EFI_INVALID_PARAMETER
;
538 // Find the variable by walk through non-volatile and volatile variable store
540 for (Index
= 0; Index
< 2; Index
++) {
541 PtrTrack
->StartPtr
= (VARIABLE_HEADER
*) (VariableStoreHeader
[Index
] + 1);
542 PtrTrack
->EndPtr
= GetEndPointer (VariableStoreHeader
[Index
]);
544 while (IsValidVariableHeader (Variable
[Index
]) && (Variable
[Index
] <= GetEndPointer (VariableStoreHeader
[Index
]))) {
545 if (Variable
[Index
]->State
== VAR_ADDED
) {
546 if (!(EfiAtRuntime () && !(Variable
[Index
]->Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
))) {
547 if (VariableName
[0] == 0) {
548 PtrTrack
->CurrPtr
= Variable
[Index
];
549 PtrTrack
->Volatile
= (BOOLEAN
) Index
;
552 if (CompareGuid (VendorGuid
, &Variable
[Index
]->VendorGuid
)) {
553 if (!CompareMem (VariableName
, GET_VARIABLE_NAME_PTR (Variable
[Index
]), ArrayLength (VariableName
))) {
554 PtrTrack
->CurrPtr
= Variable
[Index
];
555 PtrTrack
->Volatile
= (BOOLEAN
) Index
;
563 Variable
[Index
] = GetNextVariablePtr (Variable
[Index
]);
572 PtrTrack
->CurrPtr
= NULL
;
573 return EFI_NOT_FOUND
;
579 IN CHAR16
*VariableName
,
580 IN EFI_GUID
* VendorGuid
,
581 OUT UINT32
*Attributes OPTIONAL
,
582 IN OUT UINTN
*DataSize
,
584 IN VARIABLE_GLOBAL
* Global
,
591 This code finds variable in storage blocks (Volatile or Non-Volatile)
595 VariableName Name of Variable to be found
596 VendorGuid Variable vendor GUID
597 Attributes OPTIONAL Attribute value of the variable found
598 DataSize Size of Data found. If size is less than the
599 data, this value contains the required size.
601 Global Pointer to VARIABLE_GLOBAL structure
602 Instance Instance of the Firmware Volume.
610 VARIABLE_POINTER_TRACK Variable
;
614 if (VariableName
== NULL
|| VendorGuid
== NULL
|| DataSize
== NULL
) {
615 return EFI_INVALID_PARAMETER
;
618 // Find existing variable
620 Status
= FindVariable (VariableName
, VendorGuid
, &Variable
, Global
);
622 if (Variable
.CurrPtr
== NULL
|| EFI_ERROR (Status
)) {
628 VarDataSize
= Variable
.CurrPtr
->DataSize
;
629 if (*DataSize
>= VarDataSize
) {
631 return EFI_INVALID_PARAMETER
;
634 CopyMem (Data
, GetVariableDataPtr (Variable
.CurrPtr
), VarDataSize
);
635 if (Attributes
!= NULL
) {
636 *Attributes
= Variable
.CurrPtr
->Attributes
;
639 *DataSize
= VarDataSize
;
642 *DataSize
= VarDataSize
;
643 return EFI_BUFFER_TOO_SMALL
;
649 GetNextVariableName (
650 IN OUT UINTN
*VariableNameSize
,
651 IN OUT CHAR16
*VariableName
,
652 IN OUT EFI_GUID
*VendorGuid
,
653 IN VARIABLE_GLOBAL
*Global
,
660 This code Finds the Next available variable
664 VariableNameSize Size of the variable
665 VariableName Pointer to variable name
666 VendorGuid Variable Vendor Guid
667 Global VARIABLE_GLOBAL structure pointer.
676 VARIABLE_POINTER_TRACK Variable
;
680 if (VariableNameSize
== NULL
|| VariableName
== NULL
|| VendorGuid
== NULL
) {
681 return EFI_INVALID_PARAMETER
;
684 Status
= FindVariable (VariableName
, VendorGuid
, &Variable
, Global
);
686 if (Variable
.CurrPtr
== NULL
|| EFI_ERROR (Status
)) {
690 if (VariableName
[0] != 0) {
692 // If variable name is not NULL, get next variable
694 Variable
.CurrPtr
= GetNextVariablePtr (Variable
.CurrPtr
);
699 // If both volatile and non-volatile variable store are parsed,
702 if (Variable
.CurrPtr
>= Variable
.EndPtr
|| Variable
.CurrPtr
== NULL
) {
703 Variable
.Volatile
= (BOOLEAN
) (Variable
.Volatile
^ ((BOOLEAN
) 0x1));
704 if (Variable
.Volatile
) {
705 Variable
.StartPtr
= (VARIABLE_HEADER
*) ((UINTN
) (Global
->VolatileVariableBase
+ sizeof (VARIABLE_STORE_HEADER
)));
706 Variable
.EndPtr
= (VARIABLE_HEADER
*) GetEndPointer ((VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->VolatileVariableBase
));
708 return EFI_NOT_FOUND
;
711 Variable
.CurrPtr
= Variable
.StartPtr
;
712 if (!IsValidVariableHeader (Variable
.CurrPtr
)) {
719 if (IsValidVariableHeader (Variable
.CurrPtr
) && Variable
.CurrPtr
->State
== VAR_ADDED
) {
720 if (!(EfiAtRuntime () && !(Variable
.CurrPtr
->Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
))) {
721 VarNameSize
= Variable
.CurrPtr
->NameSize
;
722 if (VarNameSize
<= *VariableNameSize
) {
725 GET_VARIABLE_NAME_PTR (Variable
.CurrPtr
),
730 &Variable
.CurrPtr
->VendorGuid
,
733 Status
= EFI_SUCCESS
;
735 Status
= EFI_BUFFER_TOO_SMALL
;
738 *VariableNameSize
= VarNameSize
;
743 Variable
.CurrPtr
= GetNextVariablePtr (Variable
.CurrPtr
);
746 return EFI_NOT_FOUND
;
752 IN CHAR16
*VariableName
,
753 IN EFI_GUID
*VendorGuid
,
754 IN UINT32 Attributes
,
757 IN VARIABLE_GLOBAL
*Global
,
758 IN UINTN
*VolatileOffset
,
759 IN UINTN
*NonVolatileOffset
,
766 This code sets variable in storage blocks (Volatile or Non-Volatile)
770 VariableName Name of Variable to be found
771 VendorGuid Variable vendor GUID
772 Attributes Attribute value of the variable found
773 DataSize Size of Data found. If size is less than the
774 data, this value contains the required size.
776 Global Pointer to VARIABLE_GLOBAL structure
777 VolatileOffset The offset of last volatile variable
778 NonVolatileOffset The offset of last non-volatile variable
779 Instance Instance of the Firmware Volume.
784 EFI_INVALID_PARAMETER - Invalid parameter
785 EFI_SUCCESS - Set successfully
786 EFI_OUT_OF_RESOURCES - Resource not enough to set variable
787 EFI_NOT_FOUND - Not found
791 VARIABLE_POINTER_TRACK Variable
;
793 VARIABLE_HEADER
*NextVariable
;
803 if (VariableName
== NULL
|| VariableName
[0] == 0 || VendorGuid
== NULL
) {
804 return EFI_INVALID_PARAMETER
;
807 Status
= FindVariable (VariableName
, VendorGuid
, &Variable
, Global
);
809 if (Status
== EFI_INVALID_PARAMETER
) {
813 // The size of the VariableName, including the Unicode Null in bytes plus
814 // the DataSize is limited to maximum size of MAX_VARIABLE_SIZE (1024) bytes.
816 else if (sizeof (VARIABLE_HEADER
) + ArrayLength (VariableName
) + DataSize
> MAX_VARIABLE_SIZE
) {
817 return EFI_INVALID_PARAMETER
;
820 // Make sure if runtime bit is set, boot service bit is set also
822 else if ((Attributes
& (EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
)) == EFI_VARIABLE_RUNTIME_ACCESS
824 return EFI_INVALID_PARAMETER
;
827 // Runtime but Attribute is not Runtime
829 else if (EfiAtRuntime () && Attributes
&& !(Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
)) {
830 return EFI_INVALID_PARAMETER
;
833 // Cannot set volatile variable in Runtime
835 else if (EfiAtRuntime () && Attributes
&& !(Attributes
& EFI_VARIABLE_NON_VOLATILE
)) {
836 return EFI_INVALID_PARAMETER
;
839 // Setting a data variable with no access, or zero DataSize attributes
840 // specified causes it to be deleted.
842 else if (DataSize
== 0 || Attributes
== 0) {
843 if (!EFI_ERROR (Status
)) {
844 State
= Variable
.CurrPtr
->State
;
845 State
&= VAR_DELETED
;
847 Status
= UpdateVariableStore (
852 (UINTN
) &Variable
.CurrPtr
->State
,
856 if (EFI_ERROR (Status
)) {
863 return EFI_NOT_FOUND
;
865 if (!EFI_ERROR (Status
)) {
867 // If the variable is marked valid and the same data has been passed in
868 // then return to the caller immediately.
870 if (Variable
.CurrPtr
->DataSize
== DataSize
&&
871 !CompareMem (Data
, GetVariableDataPtr (Variable
.CurrPtr
), DataSize
)
874 } else if (Variable
.CurrPtr
->State
== VAR_ADDED
) {
876 // Mark the old variable as in delete transition
878 State
= Variable
.CurrPtr
->State
;
879 State
&= VAR_IN_DELETED_TRANSITION
;
881 Status
= UpdateVariableStore (
886 (UINTN
) &Variable
.CurrPtr
->State
,
890 if (EFI_ERROR (Status
)) {
896 // Create a new variable and copy the data.
898 // Tricky part: Use scratch data area at the end of volatile variable store
899 // as a temporary storage.
901 NextVariable
= GetEndPointer ((VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->VolatileVariableBase
));
903 SetMem (NextVariable
, SCRATCH_SIZE
, 0xff);
905 NextVariable
->StartId
= VARIABLE_DATA
;
906 NextVariable
->Attributes
= Attributes
;
908 // NextVariable->State = VAR_ADDED;
910 NextVariable
->Reserved
= 0;
911 VarNameOffset
= sizeof (VARIABLE_HEADER
);
912 VarNameSize
= ArrayLength (VariableName
);
914 (UINT8
*) ((UINTN
) NextVariable
+ VarNameOffset
),
918 VarDataOffset
= VarNameOffset
+ VarNameSize
+ GET_PAD_SIZE (VarNameSize
);
920 (UINT8
*) ((UINTN
) NextVariable
+ VarDataOffset
),
924 CopyMem (&NextVariable
->VendorGuid
, VendorGuid
, sizeof (EFI_GUID
));
926 // There will be pad bytes after Data, the NextVariable->NameSize and
927 // NextVariable->DataSize should not include pad size so that variable
928 // service can get actual size in GetVariable
930 NextVariable
->NameSize
= (UINT32
)VarNameSize
;
931 NextVariable
->DataSize
= (UINT32
)DataSize
;
934 // The actual size of the variable that stores in storage should
937 VarSize
= VarDataOffset
+ DataSize
+ GET_PAD_SIZE (DataSize
);
938 if (Attributes
& EFI_VARIABLE_NON_VOLATILE
) {
939 if ((UINT32
) (VarSize
+*NonVolatileOffset
) >
940 ((VARIABLE_STORE_HEADER
*) ((UINTN
) (Global
->NonVolatileVariableBase
)))->Size
942 if (EfiAtRuntime ()) {
943 return EFI_OUT_OF_RESOURCES
;
946 // Perform garbage collection & reclaim operation
948 Status
= Reclaim (Global
->NonVolatileVariableBase
, NonVolatileOffset
, FALSE
);
949 if (EFI_ERROR (Status
)) {
953 // If still no enough space, return out of resources
955 if ((UINT32
) (VarSize
+*NonVolatileOffset
) >
956 ((VARIABLE_STORE_HEADER
*) ((UINTN
) (Global
->NonVolatileVariableBase
)))->Size
958 return EFI_OUT_OF_RESOURCES
;
965 // 1. Write variable header
966 // 2. Write variable data
967 // 3. Set variable state to valid
972 Status
= UpdateVariableStore (
978 sizeof (VARIABLE_HEADER
),
979 (UINT8
*) NextVariable
982 if (EFI_ERROR (Status
)) {
988 Status
= UpdateVariableStore (
993 *NonVolatileOffset
+ sizeof (VARIABLE_HEADER
),
994 (UINT32
) VarSize
- sizeof (VARIABLE_HEADER
),
995 (UINT8
*) NextVariable
+ sizeof (VARIABLE_HEADER
)
998 if (EFI_ERROR (Status
)) {
1004 NextVariable
->State
= VAR_ADDED
;
1005 Status
= UpdateVariableStore (
1011 sizeof (VARIABLE_HEADER
),
1012 (UINT8
*) NextVariable
1015 if (EFI_ERROR (Status
)) {
1019 *NonVolatileOffset
= *NonVolatileOffset
+ VarSize
;
1022 if (EfiAtRuntime ()) {
1023 return EFI_INVALID_PARAMETER
;
1026 if ((UINT32
) (VarSize
+*VolatileOffset
) >
1027 ((VARIABLE_STORE_HEADER
*) ((UINTN
) (Global
->VolatileVariableBase
)))->Size
1030 // Perform garbage collection & reclaim operation
1032 Status
= Reclaim (Global
->VolatileVariableBase
, VolatileOffset
, TRUE
);
1033 if (EFI_ERROR (Status
)) {
1037 // If still no enough space, return out of resources
1039 if ((UINT32
) (VarSize
+*VolatileOffset
) >
1040 ((VARIABLE_STORE_HEADER
*) ((UINTN
) (Global
->VolatileVariableBase
)))->Size
1042 return EFI_OUT_OF_RESOURCES
;
1048 NextVariable
->State
= VAR_ADDED
;
1049 Status
= UpdateVariableStore (
1056 (UINT8
*) NextVariable
1059 if (EFI_ERROR (Status
)) {
1063 *VolatileOffset
= *VolatileOffset
+ VarSize
;
1066 // Mark the old variable as deleted
1068 if (!Reclaimed
&& !EFI_ERROR (Status
) && Variable
.CurrPtr
!= NULL
) {
1069 State
= Variable
.CurrPtr
->State
;
1070 State
&= VAR_DELETED
;
1072 Status
= UpdateVariableStore (
1077 (UINTN
) &Variable
.CurrPtr
->State
,
1082 if (EFI_ERROR (Status
)) {
1091 #if (EFI_SPECIFICATION_VERSION >= 0x00020000)
1095 IN UINT32 Attributes
,
1096 OUT UINT64
*MaximumVariableStorageSize
,
1097 OUT UINT64
*RemainingVariableStorageSize
,
1098 OUT UINT64
*MaximumVariableSize
,
1099 IN VARIABLE_GLOBAL
*Global
,
1104 Routine Description:
1106 This code returns information about the EFI variables.
1110 Attributes Attributes bitmask to specify the type of variables
1111 on which to return information.
1112 MaximumVariableStorageSize Pointer to the maximum size of the storage space available
1113 for the EFI variables associated with the attributes specified.
1114 RemainingVariableStorageSize Pointer to the remaining size of the storage space available
1115 for the EFI variables associated with the attributes specified.
1116 MaximumVariableSize Pointer to the maximum size of the individual EFI variables
1117 associated with the attributes specified.
1118 Global Pointer to VARIABLE_GLOBAL structure.
1119 Instance Instance of the Firmware Volume.
1124 EFI_INVALID_PARAMETER - An invalid combination of attribute bits was supplied.
1125 EFI_SUCCESS - Query successfully.
1126 EFI_UNSUPPORTED - The attribute is not supported on this platform.
1130 VARIABLE_HEADER
*Variable
;
1131 VARIABLE_HEADER
*NextVariable
;
1132 UINT64 VariableSize
;
1133 VARIABLE_STORE_HEADER
*VariableStoreHeader
;
1135 if(MaximumVariableStorageSize
== NULL
|| RemainingVariableStorageSize
== NULL
|| MaximumVariableSize
== NULL
) {
1136 return EFI_INVALID_PARAMETER
;
1139 if((Attributes
& (EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
)) == 0) {
1141 // Make sure the Attributes combination is supported by the platform.
1143 return EFI_UNSUPPORTED
;
1144 } else if ((Attributes
& (EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
)) == EFI_VARIABLE_RUNTIME_ACCESS
) {
1146 // Make sure if runtime bit is set, boot service bit is set also.
1148 return EFI_INVALID_PARAMETER
;
1149 } else if (EfiAtRuntime () && !(Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
)) {
1151 // Make sure RT Attribute is set if we are in Runtime phase.
1153 return EFI_INVALID_PARAMETER
;
1156 if((Attributes
& EFI_VARIABLE_NON_VOLATILE
) == 0) {
1158 // Query is Volatile related.
1160 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->VolatileVariableBase
);
1163 // Query is Non-Volatile related.
1165 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->NonVolatileVariableBase
);
1169 // Now let's fill *MaximumVariableStorageSize *RemainingVariableStorageSize
1170 // with the storage size (excluding the storage header size).
1172 *MaximumVariableStorageSize
= VariableStoreHeader
->Size
- sizeof (VARIABLE_STORE_HEADER
);
1173 *RemainingVariableStorageSize
= VariableStoreHeader
->Size
- sizeof (VARIABLE_STORE_HEADER
);
1176 // Let *MaximumVariableSize be MAX_VARIABLE_SIZE.
1178 *MaximumVariableSize
= MAX_VARIABLE_SIZE
;
1181 // Point to the starting address of the variables.
1183 Variable
= (VARIABLE_HEADER
*) (VariableStoreHeader
+ 1);
1186 // Now walk through the related variable store.
1188 while (IsValidVariableHeader (Variable
) && (Variable
< GetEndPointer (VariableStoreHeader
))) {
1189 NextVariable
= GetNextVariablePtr (Variable
);
1190 VariableSize
= (UINT64
) (UINTN
) NextVariable
- (UINT64
) (UINTN
) Variable
;
1192 if (EfiAtRuntime ()) {
1194 // we don't take the state of the variables in mind
1195 // when calculating RemainingVariableStorageSize,
1196 // since the space occupied by variables not marked with
1197 // VAR_ADDED is not allowed to be reclaimed in Runtime.
1199 *RemainingVariableStorageSize
-= VariableSize
;
1202 // Only care about Variables with State VAR_ADDED,because
1203 // the space not marked as VAR_ADDED is reclaimable now.
1205 if (Variable
->State
== VAR_ADDED
) {
1206 *RemainingVariableStorageSize
-= VariableSize
;
1211 // Go to the next one
1213 Variable
= NextVariable
;
1222 VariableCommonInitialize (
1223 IN EFI_HANDLE ImageHandle
,
1224 IN EFI_SYSTEM_TABLE
*SystemTable
1228 Routine Description:
1229 This function does common initialization for variable services
1233 ImageHandle - The firmware allocated handle for the EFI image.
1234 SystemTable - A pointer to the EFI System Table.
1240 EFI_NOT_FOUND - Variable store area not found.
1241 EFI_UNSUPPORTED - Currently only one non-volatile variable store is supported.
1242 EFI_SUCCESS - Variable services successfully initialized.
1247 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
1249 VARIABLE_STORE_HEADER
*VolatileVariableStore
;
1250 VARIABLE_STORE_HEADER
*VariableStoreHeader
;
1251 VARIABLE_HEADER
*NextVariable
;
1253 EFI_PHYSICAL_ADDRESS FvVolHdr
;
1255 UINT64 TempVariableStoreHeader
;
1257 EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor
;
1258 EFI_FLASH_SUBAREA_ENTRY VariableStoreEntry
;
1264 Status
= gBS
->AllocatePool (
1265 EfiRuntimeServicesData
,
1266 sizeof (ESAL_VARIABLE_GLOBAL
),
1267 (VOID
**) &mVariableModuleGlobal
1270 if (EFI_ERROR (Status
)) {
1274 // Allocate memory for volatile variable store
1276 Status
= gBS
->AllocatePool (
1277 EfiRuntimeServicesData
,
1278 VARIABLE_STORE_SIZE
+ SCRATCH_SIZE
,
1279 (VOID
**) &VolatileVariableStore
1282 if (EFI_ERROR (Status
)) {
1283 gBS
->FreePool (mVariableModuleGlobal
);
1287 SetMem (VolatileVariableStore
, VARIABLE_STORE_SIZE
+ SCRATCH_SIZE
, 0xff);
1290 // Variable Specific Data
1292 mVariableModuleGlobal
->VariableBase
[Physical
].VolatileVariableBase
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) VolatileVariableStore
;
1293 mVariableModuleGlobal
->VolatileLastVariableOffset
= sizeof (VARIABLE_STORE_HEADER
);
1295 VolatileVariableStore
->Signature
= VARIABLE_STORE_SIGNATURE
;
1296 VolatileVariableStore
->Size
= VARIABLE_STORE_SIZE
;
1297 VolatileVariableStore
->Format
= VARIABLE_STORE_FORMATTED
;
1298 VolatileVariableStore
->State
= VARIABLE_STORE_HEALTHY
;
1299 VolatileVariableStore
->Reserved
= 0;
1300 VolatileVariableStore
->Reserved1
= 0;
1303 // Get non volatile varaible store
1306 TempVariableStoreHeader
= (UINT64
) PcdGet32 (PcdFlashNvStorageVariableBase
);
1307 VariableStoreEntry
.Base
= TempVariableStoreHeader
+ \
1308 (((EFI_FIRMWARE_VOLUME_HEADER
*) (UINTN
) (TempVariableStoreHeader
)) -> HeaderLength
);
1309 VariableStoreEntry
.Length
= (UINT64
) PcdGet32 (PcdFlashNvStorageVariableSize
) - \
1310 (((EFI_FIRMWARE_VOLUME_HEADER
*) (UINTN
) (TempVariableStoreHeader
)) -> HeaderLength
);
1312 // Mark the variable storage region of the FLASH as RUNTIME
1314 BaseAddress
= VariableStoreEntry
.Base
& (~EFI_PAGE_MASK
);
1315 Length
= VariableStoreEntry
.Length
+ (VariableStoreEntry
.Base
- BaseAddress
);
1316 Length
= (Length
+ EFI_PAGE_SIZE
- 1) & (~EFI_PAGE_MASK
);
1318 Status
= gDS
->GetMemorySpaceDescriptor (BaseAddress
, &GcdDescriptor
);
1319 if (EFI_ERROR (Status
)) {
1320 gBS
->FreePool (mVariableModuleGlobal
);
1321 gBS
->FreePool (VolatileVariableStore
);
1322 return EFI_UNSUPPORTED
;
1325 Status
= gDS
->SetMemorySpaceAttributes (
1328 GcdDescriptor
.Attributes
| EFI_MEMORY_RUNTIME
1330 if (EFI_ERROR (Status
)) {
1331 gBS
->FreePool (mVariableModuleGlobal
);
1332 gBS
->FreePool (VolatileVariableStore
);
1333 return EFI_UNSUPPORTED
;
1336 // Get address of non volatile variable store base
1338 mVariableModuleGlobal
->VariableBase
[Physical
].NonVolatileVariableBase
= VariableStoreEntry
.Base
;
1344 // Find the Correct Instance of the FV Block Service.
1347 CurrPtr
= (CHAR8
*) ((UINTN
) mVariableModuleGlobal
->VariableBase
[Physical
].NonVolatileVariableBase
);
1348 while (EfiFvbGetPhysicalAddress (Instance
, &FvVolHdr
) == EFI_SUCCESS
) {
1349 FwVolHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) ((UINTN
) FvVolHdr
);
1350 if (CurrPtr
>= (CHAR8
*) FwVolHeader
&& CurrPtr
< (((CHAR8
*) FwVolHeader
) + FwVolHeader
->FvLength
)) {
1351 mVariableModuleGlobal
->FvbInstance
= Instance
;
1358 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) CurrPtr
;
1359 if (GetVariableStoreStatus (VariableStoreHeader
) == EfiValid
) {
1360 if (~VariableStoreHeader
->Size
== 0) {
1361 Status
= UpdateVariableStore (
1362 &mVariableModuleGlobal
->VariableBase
[Physical
],
1365 mVariableModuleGlobal
->FvbInstance
,
1366 (UINTN
) &VariableStoreHeader
->Size
,
1368 (UINT8
*) &VariableStoreEntry
.Length
1371 if (EFI_ERROR (Status
)) {
1376 mVariableModuleGlobal
->VariableBase
[Physical
].NonVolatileVariableBase
= (EFI_PHYSICAL_ADDRESS
) ((UINTN
) CurrPtr
);
1378 // Parse non-volatile variable data and get last variable offset
1380 NextVariable
= (VARIABLE_HEADER
*) (CurrPtr
+ sizeof (VARIABLE_STORE_HEADER
));
1381 Status
= EFI_SUCCESS
;
1383 while (IsValidVariableHeader (NextVariable
)) {
1384 NextVariable
= GetNextVariablePtr (NextVariable
);
1387 mVariableModuleGlobal
->NonVolatileLastVariableOffset
= (UINTN
) NextVariable
- (UINTN
) CurrPtr
;
1390 // Check if the free area is blow a threshold
1392 if ((((VARIABLE_STORE_HEADER
*)((UINTN
) CurrPtr
))->Size
- mVariableModuleGlobal
->NonVolatileLastVariableOffset
) < VARIABLE_RECLAIM_THRESHOLD
) {
1394 mVariableModuleGlobal
->VariableBase
[Physical
].NonVolatileVariableBase
,
1395 &mVariableModuleGlobal
->NonVolatileLastVariableOffset
,
1400 if (EFI_ERROR (Status
)) {
1401 gBS
->FreePool (mVariableModuleGlobal
);
1402 gBS
->FreePool (VolatileVariableStore
);
1407 // Check if the free area is really free.
1409 for (Index
= mVariableModuleGlobal
->NonVolatileLastVariableOffset
; Index
< VariableStoreHeader
->Size
; Index
++) {
1410 Data
= ((UINT8
*) (UINTN
) mVariableModuleGlobal
->VariableBase
[Physical
].NonVolatileVariableBase
)[Index
];
1413 // There must be something wrong in variable store, do reclaim operation.
1416 mVariableModuleGlobal
->VariableBase
[Physical
].NonVolatileVariableBase
,
1417 &mVariableModuleGlobal
->NonVolatileLastVariableOffset
,
1425 if (EFI_ERROR (Status
)) {
1426 gBS
->FreePool (mVariableModuleGlobal
);
1427 gBS
->FreePool (VolatileVariableStore
);