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
;
40 Determine the length of null terminated char16 array.
44 String Null-terminated CHAR16 array pointer.
48 UINT32 Number of bytes in the string, including the double NULL at the end;
60 while (0 != String
[Count
]) {
64 return (Count
* 2) + 2;
70 IsValidVariableHeader (
71 IN VARIABLE_HEADER
*Variable
77 This code checks if variable header is valid or not.
80 Variable Pointer to the Variable Header.
83 TRUE Variable header is valid.
84 FALSE Variable header is not valid.
88 if (Variable
== NULL
||
89 Variable
->StartId
!= VARIABLE_DATA
||
90 (sizeof (VARIABLE_HEADER
) + Variable
->NameSize
+ Variable
->DataSize
) > MAX_VARIABLE_SIZE
101 UpdateVariableStore (
102 IN VARIABLE_GLOBAL
*Global
,
104 IN BOOLEAN SetByIndex
,
106 IN UINTN DataPtrIndex
,
114 This function writes data to the FWH at the correct LBA even if the LBAs
119 Global Pointer to VARAIBLE_GLOBAL structure
120 Volatile If the Variable is Volatile or Non-Volatile
121 SetByIndex TRUE: Target pointer is given as index
122 FALSE: Target pointer is absolute
123 Instance Instance of FV Block services
124 DataPtrIndex Pointer to the Data from the end of VARIABLE_STORE_HEADER
126 DataSize Size of data to be written.
127 Buffer Pointer to the buffer from which data is written
135 EFI_FV_BLOCK_MAP_ENTRY
*PtrBlockMapEntry
;
143 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
144 VARIABLE_STORE_HEADER
*VolatileBase
;
145 EFI_PHYSICAL_ADDRESS FvVolHdr
;
146 EFI_PHYSICAL_ADDRESS DataPtr
;
150 DataPtr
= DataPtrIndex
;
153 // Check if the Data is Volatile
156 EfiFvbGetPhysicalAddress (Instance
, &FvVolHdr
);
157 FwVolHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) ((UINTN
) FvVolHdr
);
159 // Data Pointer should point to the actual Address where data is to be
163 DataPtr
+= Global
->NonVolatileVariableBase
;
166 if ((DataPtr
+ DataSize
) >= ((EFI_PHYSICAL_ADDRESS
) (UINTN
) ((UINT8
*) FwVolHeader
+ FwVolHeader
->FvLength
))) {
167 return EFI_INVALID_PARAMETER
;
171 // Data Pointer should point to the actual Address where data is to be
174 VolatileBase
= (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->VolatileVariableBase
);
176 DataPtr
+= Global
->VolatileVariableBase
;
179 if ((DataPtr
+ DataSize
) >= ((UINTN
) ((UINT8
*) VolatileBase
+ VolatileBase
->Size
))) {
180 return EFI_INVALID_PARAMETER
;
184 // If Volatile Variable just do a simple mem copy.
187 CopyMem ((UINT8
*) ((UINTN
) DataPtr
), Buffer
, DataSize
);
191 // If we are here we are dealing with Non-Volatile Variables
193 LinearOffset
= (UINTN
) FwVolHeader
;
194 CurrWritePtr
= (UINTN
) DataPtr
;
195 CurrWriteSize
= DataSize
;
199 if (CurrWritePtr
< LinearOffset
) {
200 return EFI_INVALID_PARAMETER
;
203 for (PtrBlockMapEntry
= FwVolHeader
->FvBlockMap
; PtrBlockMapEntry
->NumBlocks
!= 0; PtrBlockMapEntry
++) {
204 for (BlockIndex2
= 0; BlockIndex2
< PtrBlockMapEntry
->NumBlocks
; BlockIndex2
++) {
206 // Check to see if the Variable Writes are spanning through multiple
209 if ((CurrWritePtr
>= LinearOffset
) && (CurrWritePtr
< LinearOffset
+ PtrBlockMapEntry
->BlockLength
)) {
210 if ((CurrWritePtr
+ CurrWriteSize
) <= (LinearOffset
+ PtrBlockMapEntry
->BlockLength
)) {
211 Status
= EfiFvbWriteBlock (
214 (UINTN
) (CurrWritePtr
- LinearOffset
),
218 if (EFI_ERROR (Status
)) {
222 Size
= (UINT32
) (LinearOffset
+ PtrBlockMapEntry
->BlockLength
- CurrWritePtr
);
223 Status
= EfiFvbWriteBlock (
226 (UINTN
) (CurrWritePtr
- LinearOffset
),
230 if (EFI_ERROR (Status
)) {
234 CurrWritePtr
= LinearOffset
+ PtrBlockMapEntry
->BlockLength
;
235 CurrBuffer
= CurrBuffer
+ Size
;
236 CurrWriteSize
= CurrWriteSize
- Size
;
240 LinearOffset
+= PtrBlockMapEntry
->BlockLength
;
249 VARIABLE_STORE_STATUS
251 GetVariableStoreStatus (
252 IN VARIABLE_STORE_HEADER
*VarStoreHeader
258 This code gets the current status of Variable Store.
262 VarStoreHeader Pointer to the Variable Store Header.
266 EfiRaw Variable store status is raw
267 EfiValid Variable store status is valid
268 EfiInvalid Variable store status is invalid
272 if (VarStoreHeader
->Signature
== VARIABLE_STORE_SIGNATURE
&&
273 VarStoreHeader
->Format
== VARIABLE_STORE_FORMATTED
&&
274 VarStoreHeader
->State
== VARIABLE_STORE_HEALTHY
278 } else if (VarStoreHeader
->Signature
== 0xffffffff &&
279 VarStoreHeader
->Size
== 0xffffffff &&
280 VarStoreHeader
->Format
== 0xff &&
281 VarStoreHeader
->State
== 0xff
294 IN VARIABLE_HEADER
*Variable
300 This code gets the pointer to the variable data.
304 Variable Pointer to the Variable Header.
308 UINT8* Pointer to Variable Data
313 // Be careful about pad size for alignment
315 return (UINT8
*) ((UINTN
) GET_VARIABLE_NAME_PTR (Variable
) + Variable
->NameSize
+ GET_PAD_SIZE (Variable
->NameSize
));
322 IN VARIABLE_HEADER
*Variable
328 This code gets the pointer to the next variable header.
332 Variable Pointer to the Variable Header.
336 VARIABLE_HEADER* Pointer to next variable header.
340 if (!IsValidVariableHeader (Variable
)) {
344 // Be careful about pad size for alignment
346 return (VARIABLE_HEADER
*) ((UINTN
) GetVariableDataPtr (Variable
) + Variable
->DataSize
+ GET_PAD_SIZE (Variable
->DataSize
));
353 IN VARIABLE_STORE_HEADER
*VarStoreHeader
359 This code gets the pointer to the last variable memory pointer byte
363 VarStoreHeader Pointer to the Variable Store Header.
367 VARIABLE_HEADER* Pointer to last unavailable Variable Header
372 // The end of variable store
374 return (VARIABLE_HEADER
*) ((UINTN
) VarStoreHeader
+ VarStoreHeader
->Size
);
381 IN EFI_PHYSICAL_ADDRESS VariableBase
,
382 OUT UINTN
*LastVariableOffset
,
383 IN BOOLEAN IsVolatile
389 Variable store garbage collection and reclaim operation
393 VariableBase Base address of variable store
394 LastVariableOffset Offset of last variable
395 IsVolatile The variable store is volatile or not,
396 if it is non-volatile, need FTW
404 VARIABLE_HEADER
*Variable
;
405 VARIABLE_HEADER
*NextVariable
;
406 VARIABLE_STORE_HEADER
*VariableStoreHeader
;
408 UINTN ValidBufferSize
;
413 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) ((UINTN
) VariableBase
);
416 // Start Pointers for the variable.
418 Variable
= (VARIABLE_HEADER
*) (VariableStoreHeader
+ 1);
420 ValidBufferSize
= sizeof (VARIABLE_STORE_HEADER
);
422 while (IsValidVariableHeader (Variable
)) {
423 NextVariable
= GetNextVariablePtr (Variable
);
424 if (Variable
->State
== VAR_ADDED
) {
425 VariableSize
= (UINTN
) NextVariable
- (UINTN
) Variable
;
426 ValidBufferSize
+= VariableSize
;
429 Variable
= NextVariable
;
432 Status
= gBS
->AllocatePool (
435 (VOID
**) &ValidBuffer
437 if (EFI_ERROR (Status
)) {
441 SetMem (ValidBuffer
, ValidBufferSize
, 0xff);
443 CurrPtr
= ValidBuffer
;
446 // Copy variable store header
448 CopyMem (CurrPtr
, VariableStoreHeader
, sizeof (VARIABLE_STORE_HEADER
));
449 CurrPtr
+= sizeof (VARIABLE_STORE_HEADER
);
452 // Start Pointers for the variable.
454 Variable
= (VARIABLE_HEADER
*) (VariableStoreHeader
+ 1);
456 while (IsValidVariableHeader (Variable
)) {
457 NextVariable
= GetNextVariablePtr (Variable
);
458 if (Variable
->State
== VAR_ADDED
) {
459 VariableSize
= (UINTN
) NextVariable
- (UINTN
) Variable
;
460 CopyMem (CurrPtr
, (UINT8
*) Variable
, VariableSize
);
461 CurrPtr
+= VariableSize
;
464 Variable
= NextVariable
;
469 // If volatile variable store, just copy valid buffer
471 SetMem ((UINT8
*) (UINTN
) VariableBase
, VariableStoreHeader
->Size
, 0xff);
472 CopyMem ((UINT8
*) (UINTN
) VariableBase
, ValidBuffer
, ValidBufferSize
);
473 *LastVariableOffset
= ValidBufferSize
;
474 Status
= EFI_SUCCESS
;
477 // If non-volatile variable store, perform FTW here.
479 Status
= FtwVariableSpace (
484 if (!EFI_ERROR (Status
)) {
485 *LastVariableOffset
= ValidBufferSize
;
489 gBS
->FreePool (ValidBuffer
);
491 if (EFI_ERROR (Status
)) {
492 *LastVariableOffset
= 0;
502 IN CHAR16
*VariableName
,
503 IN EFI_GUID
*VendorGuid
,
504 OUT VARIABLE_POINTER_TRACK
*PtrTrack
,
505 IN VARIABLE_GLOBAL
*Global
511 This code finds variable in storage blocks (Volatile or Non-Volatile)
515 VariableName Name of the variable to be found
516 VendorGuid Vendor GUID to be found.
517 PtrTrack Variable Track Pointer structure that contains
518 Variable Information.
519 Contains the pointer of Variable header.
520 Global VARIABLE_GLOBAL pointer
528 VARIABLE_HEADER
*Variable
[2];
529 VARIABLE_STORE_HEADER
*VariableStoreHeader
[2];
533 // 0: Non-Volatile, 1: Volatile
535 VariableStoreHeader
[0] = (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->NonVolatileVariableBase
);
536 VariableStoreHeader
[1] = (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->VolatileVariableBase
);
539 // Start Pointers for the variable.
540 // Actual Data Pointer where data can be written.
542 Variable
[0] = (VARIABLE_HEADER
*) (VariableStoreHeader
[0] + 1);
543 Variable
[1] = (VARIABLE_HEADER
*) (VariableStoreHeader
[1] + 1);
545 if (VariableName
[0] != 0 && VendorGuid
== NULL
) {
546 return EFI_INVALID_PARAMETER
;
549 // Find the variable by walk through non-volatile and volatile variable store
551 for (Index
= 0; Index
< 2; Index
++) {
552 PtrTrack
->StartPtr
= (VARIABLE_HEADER
*) (VariableStoreHeader
[Index
] + 1);
553 PtrTrack
->EndPtr
= GetEndPointer (VariableStoreHeader
[Index
]);
555 while (IsValidVariableHeader (Variable
[Index
]) && (Variable
[Index
] <= GetEndPointer (VariableStoreHeader
[Index
]))) {
556 if (Variable
[Index
]->State
== VAR_ADDED
) {
557 if (!(EfiAtRuntime () && !(Variable
[Index
]->Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
))) {
558 if (VariableName
[0] == 0) {
559 PtrTrack
->CurrPtr
= Variable
[Index
];
560 PtrTrack
->Volatile
= (BOOLEAN
) Index
;
563 if (CompareGuid (VendorGuid
, &Variable
[Index
]->VendorGuid
)) {
564 if (!CompareMem (VariableName
, GET_VARIABLE_NAME_PTR (Variable
[Index
]), ArrayLength (VariableName
))) {
565 PtrTrack
->CurrPtr
= Variable
[Index
];
566 PtrTrack
->Volatile
= (BOOLEAN
) Index
;
574 Variable
[Index
] = GetNextVariablePtr (Variable
[Index
]);
583 PtrTrack
->CurrPtr
= NULL
;
584 return EFI_NOT_FOUND
;
590 IN CHAR16
*VariableName
,
591 IN EFI_GUID
* VendorGuid
,
592 OUT UINT32
*Attributes OPTIONAL
,
593 IN OUT UINTN
*DataSize
,
595 IN VARIABLE_GLOBAL
* Global
,
602 This code finds variable in storage blocks (Volatile or Non-Volatile)
606 VariableName Name of Variable to be found
607 VendorGuid Variable vendor GUID
608 Attributes OPTIONAL Attribute value of the variable found
609 DataSize Size of Data found. If size is less than the
610 data, this value contains the required size.
612 Global Pointer to VARIABLE_GLOBAL structure
613 Instance Instance of the Firmware Volume.
621 VARIABLE_POINTER_TRACK Variable
;
625 if (VariableName
== NULL
|| VendorGuid
== NULL
|| DataSize
== NULL
) {
626 return EFI_INVALID_PARAMETER
;
629 // Find existing variable
631 Status
= FindVariable (VariableName
, VendorGuid
, &Variable
, Global
);
633 if (Variable
.CurrPtr
== NULL
|| EFI_ERROR (Status
)) {
639 VarDataSize
= Variable
.CurrPtr
->DataSize
;
640 if (*DataSize
>= VarDataSize
) {
642 return EFI_INVALID_PARAMETER
;
645 CopyMem (Data
, GetVariableDataPtr (Variable
.CurrPtr
), VarDataSize
);
646 if (Attributes
!= NULL
) {
647 *Attributes
= Variable
.CurrPtr
->Attributes
;
650 *DataSize
= VarDataSize
;
653 *DataSize
= VarDataSize
;
654 return EFI_BUFFER_TOO_SMALL
;
660 GetNextVariableName (
661 IN OUT UINTN
*VariableNameSize
,
662 IN OUT CHAR16
*VariableName
,
663 IN OUT EFI_GUID
*VendorGuid
,
664 IN VARIABLE_GLOBAL
*Global
,
671 This code Finds the Next available variable
675 VariableNameSize Size of the variable
676 VariableName Pointer to variable name
677 VendorGuid Variable Vendor Guid
678 Global VARIABLE_GLOBAL structure pointer.
687 VARIABLE_POINTER_TRACK Variable
;
691 if (VariableNameSize
== NULL
|| VariableName
== NULL
|| VendorGuid
== NULL
) {
692 return EFI_INVALID_PARAMETER
;
695 Status
= FindVariable (VariableName
, VendorGuid
, &Variable
, Global
);
697 if (Variable
.CurrPtr
== NULL
|| EFI_ERROR (Status
)) {
701 if (VariableName
[0] != 0) {
703 // If variable name is not NULL, get next variable
705 Variable
.CurrPtr
= GetNextVariablePtr (Variable
.CurrPtr
);
710 // If both volatile and non-volatile variable store are parsed,
713 if (Variable
.CurrPtr
>= Variable
.EndPtr
|| Variable
.CurrPtr
== NULL
) {
714 Variable
.Volatile
= (BOOLEAN
) (Variable
.Volatile
^ ((BOOLEAN
) 0x1));
715 if (Variable
.Volatile
) {
716 Variable
.StartPtr
= (VARIABLE_HEADER
*) ((UINTN
) (Global
->VolatileVariableBase
+ sizeof (VARIABLE_STORE_HEADER
)));
717 Variable
.EndPtr
= (VARIABLE_HEADER
*) GetEndPointer ((VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->VolatileVariableBase
));
722 Variable
.CurrPtr
= Variable
.StartPtr
;
723 if (!IsValidVariableHeader (Variable
.CurrPtr
)) {
730 if (IsValidVariableHeader (Variable
.CurrPtr
) && Variable
.CurrPtr
->State
== VAR_ADDED
) {
731 if (!(EfiAtRuntime () && !(Variable
.CurrPtr
->Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
))) {
732 VarNameSize
= Variable
.CurrPtr
->NameSize
;
733 if (VarNameSize
<= *VariableNameSize
) {
736 GET_VARIABLE_NAME_PTR (Variable
.CurrPtr
),
741 &Variable
.CurrPtr
->VendorGuid
,
744 Status
= EFI_SUCCESS
;
746 Status
= EFI_BUFFER_TOO_SMALL
;
749 *VariableNameSize
= VarNameSize
;
754 Variable
.CurrPtr
= GetNextVariablePtr (Variable
.CurrPtr
);
758 return EFI_NOT_FOUND
;
764 IN CHAR16
*VariableName
,
765 IN EFI_GUID
*VendorGuid
,
766 IN UINT32 Attributes
,
769 IN VARIABLE_GLOBAL
*Global
,
770 IN UINTN
*VolatileOffset
,
771 IN UINTN
*NonVolatileOffset
,
778 This code sets variable in storage blocks (Volatile or Non-Volatile)
782 VariableName Name of Variable to be found
783 VendorGuid Variable vendor GUID
784 Attributes Attribute value of the variable found
785 DataSize Size of Data found. If size is less than the
786 data, this value contains the required size.
788 Global Pointer to VARIABLE_GLOBAL structure
789 VolatileOffset The offset of last volatile variable
790 NonVolatileOffset The offset of last non-volatile variable
791 Instance Instance of the Firmware Volume.
796 EFI_INVALID_PARAMETER - Invalid parameter
797 EFI_SUCCESS - Set successfully
798 EFI_OUT_OF_RESOURCES - Resource not enough to set variable
799 EFI_NOT_FOUND - Not found
803 VARIABLE_POINTER_TRACK Variable
;
805 VARIABLE_HEADER
*NextVariable
;
815 if (VariableName
== NULL
|| VariableName
[0] == 0 || VendorGuid
== NULL
) {
816 return EFI_INVALID_PARAMETER
;
819 Status
= FindVariable (VariableName
, VendorGuid
, &Variable
, Global
);
821 if (Status
== EFI_INVALID_PARAMETER
) {
823 } else if (!EFI_ERROR (Status
) && Variable
.Volatile
&& EfiAtRuntime()) {
825 // If EfiAtRuntime and the variable is Volatile and Runtime Access,
826 // the volatile is ReadOnly, and SetVariable should be aborted and
827 // return EFI_WRITE_PROTECTED.
829 return EFI_WRITE_PROTECTED
;
830 } else if (sizeof (VARIABLE_HEADER
) + ArrayLength (VariableName
) + DataSize
> MAX_VARIABLE_SIZE
) {
832 // The size of the VariableName, including the Unicode Null in bytes plus
833 // the DataSize is limited to maximum size of MAX_VARIABLE_SIZE (1024) bytes.
835 return EFI_INVALID_PARAMETER
;
836 } else if (Attributes
== EFI_VARIABLE_NON_VOLATILE
) {
838 // Make sure not only EFI_VARIABLE_NON_VOLATILE is set
840 return EFI_INVALID_PARAMETER
;
841 } else if ((Attributes
& (EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
)) ==
842 EFI_VARIABLE_RUNTIME_ACCESS
) {
844 // Make sure if runtime bit is set, boot service bit is set also
846 return EFI_INVALID_PARAMETER
;
847 } else if (EfiAtRuntime () && Attributes
&& !(Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
)) {
849 // Runtime but Attribute is not Runtime
851 return EFI_INVALID_PARAMETER
;
852 } else if (EfiAtRuntime () && Attributes
&& !(Attributes
& EFI_VARIABLE_NON_VOLATILE
)) {
854 // Cannot set volatile variable in Runtime
856 return EFI_INVALID_PARAMETER
;
857 } else if (DataSize
== 0 || (Attributes
& (EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
)) == 0) {
859 // Setting a data variable with no access, or zero DataSize attributes
860 // specified causes it to be deleted.
862 if (!EFI_ERROR (Status
)) {
863 State
= Variable
.CurrPtr
->State
;
864 State
&= VAR_DELETED
;
866 Status
= UpdateVariableStore (
871 (UINTN
) &Variable
.CurrPtr
->State
,
875 if (EFI_ERROR (Status
)) {
882 return EFI_NOT_FOUND
;
884 if (!EFI_ERROR (Status
)) {
886 // If the variable is marked valid and the same data has been passed in
887 // then return to the caller immediately.
889 if (Variable
.CurrPtr
->DataSize
== DataSize
&&
890 !CompareMem (Data
, GetVariableDataPtr (Variable
.CurrPtr
), DataSize
)
893 } else if (Variable
.CurrPtr
->State
== VAR_ADDED
) {
895 // Mark the old variable as in delete transition
897 State
= Variable
.CurrPtr
->State
;
898 State
&= VAR_IN_DELETED_TRANSITION
;
900 Status
= UpdateVariableStore (
905 (UINTN
) &Variable
.CurrPtr
->State
,
909 if (EFI_ERROR (Status
)) {
915 // Create a new variable and copy the data.
917 // Tricky part: Use scratch data area at the end of volatile variable store
918 // as a temporary storage.
920 NextVariable
= GetEndPointer ((VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->VolatileVariableBase
));
922 SetMem (NextVariable
, SCRATCH_SIZE
, 0xff);
924 NextVariable
->StartId
= VARIABLE_DATA
;
925 NextVariable
->Attributes
= Attributes
;
927 // NextVariable->State = VAR_ADDED;
929 NextVariable
->Reserved
= 0;
930 VarNameOffset
= sizeof (VARIABLE_HEADER
);
931 VarNameSize
= ArrayLength (VariableName
);
933 (UINT8
*) ((UINTN
) NextVariable
+ VarNameOffset
),
937 VarDataOffset
= VarNameOffset
+ VarNameSize
+ GET_PAD_SIZE (VarNameSize
);
939 (UINT8
*) ((UINTN
) NextVariable
+ VarDataOffset
),
943 CopyMem (&NextVariable
->VendorGuid
, VendorGuid
, sizeof (EFI_GUID
));
945 // There will be pad bytes after Data, the NextVariable->NameSize and
946 // NextVariable->DataSize should not include pad size so that variable
947 // service can get actual size in GetVariable
949 NextVariable
->NameSize
= (UINT32
)VarNameSize
;
950 NextVariable
->DataSize
= (UINT32
)DataSize
;
953 // The actual size of the variable that stores in storage should
956 VarSize
= VarDataOffset
+ DataSize
+ GET_PAD_SIZE (DataSize
);
957 if (Attributes
& EFI_VARIABLE_NON_VOLATILE
) {
958 if ((UINT32
) (VarSize
+*NonVolatileOffset
) >
959 ((VARIABLE_STORE_HEADER
*) ((UINTN
) (Global
->NonVolatileVariableBase
)))->Size
961 if (EfiAtRuntime ()) {
962 return EFI_OUT_OF_RESOURCES
;
965 // Perform garbage collection & reclaim operation
967 Status
= Reclaim (Global
->NonVolatileVariableBase
, NonVolatileOffset
, FALSE
);
968 if (EFI_ERROR (Status
)) {
972 // If still no enough space, return out of resources
974 if ((UINT32
) (VarSize
+*NonVolatileOffset
) >
975 ((VARIABLE_STORE_HEADER
*) ((UINTN
) (Global
->NonVolatileVariableBase
)))->Size
977 return EFI_OUT_OF_RESOURCES
;
984 // 1. Write variable header
985 // 2. Write variable data
986 // 3. Set variable state to valid
991 Status
= UpdateVariableStore (
997 sizeof (VARIABLE_HEADER
),
998 (UINT8
*) NextVariable
1001 if (EFI_ERROR (Status
)) {
1007 Status
= UpdateVariableStore (
1012 *NonVolatileOffset
+ sizeof (VARIABLE_HEADER
),
1013 (UINT32
) VarSize
- sizeof (VARIABLE_HEADER
),
1014 (UINT8
*) NextVariable
+ sizeof (VARIABLE_HEADER
)
1017 if (EFI_ERROR (Status
)) {
1023 NextVariable
->State
= VAR_ADDED
;
1024 Status
= UpdateVariableStore (
1030 sizeof (VARIABLE_HEADER
),
1031 (UINT8
*) NextVariable
1034 if (EFI_ERROR (Status
)) {
1038 *NonVolatileOffset
= *NonVolatileOffset
+ VarSize
;
1041 if (EfiAtRuntime ()) {
1042 return EFI_INVALID_PARAMETER
;
1045 if ((UINT32
) (VarSize
+*VolatileOffset
) >
1046 ((VARIABLE_STORE_HEADER
*) ((UINTN
) (Global
->VolatileVariableBase
)))->Size
1049 // Perform garbage collection & reclaim operation
1051 Status
= Reclaim (Global
->VolatileVariableBase
, VolatileOffset
, TRUE
);
1052 if (EFI_ERROR (Status
)) {
1056 // If still no enough space, return out of resources
1058 if ((UINT32
) (VarSize
+*VolatileOffset
) >
1059 ((VARIABLE_STORE_HEADER
*) ((UINTN
) (Global
->VolatileVariableBase
)))->Size
1061 return EFI_OUT_OF_RESOURCES
;
1067 NextVariable
->State
= VAR_ADDED
;
1068 Status
= UpdateVariableStore (
1075 (UINT8
*) NextVariable
1078 if (EFI_ERROR (Status
)) {
1082 *VolatileOffset
= *VolatileOffset
+ VarSize
;
1085 // Mark the old variable as deleted
1087 if (!Reclaimed
&& !EFI_ERROR (Status
) && Variable
.CurrPtr
!= NULL
) {
1088 State
= Variable
.CurrPtr
->State
;
1089 State
&= VAR_DELETED
;
1091 Status
= UpdateVariableStore (
1096 (UINTN
) &Variable
.CurrPtr
->State
,
1101 if (EFI_ERROR (Status
)) {
1110 #if (EFI_SPECIFICATION_VERSION >= 0x00020000)
1114 IN UINT32 Attributes
,
1115 OUT UINT64
*MaximumVariableStorageSize
,
1116 OUT UINT64
*RemainingVariableStorageSize
,
1117 OUT UINT64
*MaximumVariableSize
,
1118 IN VARIABLE_GLOBAL
*Global
,
1123 Routine Description:
1125 This code returns information about the EFI variables.
1129 Attributes Attributes bitmask to specify the type of variables
1130 on which to return information.
1131 MaximumVariableStorageSize Pointer to the maximum size of the storage space available
1132 for the EFI variables associated with the attributes specified.
1133 RemainingVariableStorageSize Pointer to the remaining size of the storage space available
1134 for the EFI variables associated with the attributes specified.
1135 MaximumVariableSize Pointer to the maximum size of the individual EFI variables
1136 associated with the attributes specified.
1137 Global Pointer to VARIABLE_GLOBAL structure.
1138 Instance Instance of the Firmware Volume.
1143 EFI_INVALID_PARAMETER - An invalid combination of attribute bits was supplied.
1144 EFI_SUCCESS - Query successfully.
1145 EFI_UNSUPPORTED - The attribute is not supported on this platform.
1149 VARIABLE_HEADER
*Variable
;
1150 VARIABLE_HEADER
*NextVariable
;
1151 UINT64 VariableSize
;
1152 VARIABLE_STORE_HEADER
*VariableStoreHeader
;
1154 if(MaximumVariableStorageSize
== NULL
|| RemainingVariableStorageSize
== NULL
|| MaximumVariableSize
== NULL
) {
1155 return EFI_INVALID_PARAMETER
;
1158 if((Attributes
& (EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
)) == 0) {
1160 // Make sure the Attributes combination is supported by the platform.
1162 return EFI_UNSUPPORTED
;
1163 } else if ((Attributes
& (EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
)) == EFI_VARIABLE_RUNTIME_ACCESS
) {
1165 // Make sure if runtime bit is set, boot service bit is set also.
1167 return EFI_INVALID_PARAMETER
;
1168 } else if (EfiAtRuntime () && !(Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
)) {
1170 // Make sure RT Attribute is set if we are in Runtime phase.
1172 return EFI_INVALID_PARAMETER
;
1175 if((Attributes
& EFI_VARIABLE_NON_VOLATILE
) == 0) {
1177 // Query is Volatile related.
1179 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->VolatileVariableBase
);
1182 // Query is Non-Volatile related.
1184 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->NonVolatileVariableBase
);
1188 // Now let's fill *MaximumVariableStorageSize *RemainingVariableStorageSize
1189 // with the storage size (excluding the storage header size).
1191 *MaximumVariableStorageSize
= VariableStoreHeader
->Size
- sizeof (VARIABLE_STORE_HEADER
);
1192 *RemainingVariableStorageSize
= VariableStoreHeader
->Size
- sizeof (VARIABLE_STORE_HEADER
);
1195 // Let *MaximumVariableSize be MAX_VARIABLE_SIZE.
1197 *MaximumVariableSize
= MAX_VARIABLE_SIZE
;
1200 // Point to the starting address of the variables.
1202 Variable
= (VARIABLE_HEADER
*) (VariableStoreHeader
+ 1);
1205 // Now walk through the related variable store.
1207 while (IsValidVariableHeader (Variable
) && (Variable
< GetEndPointer (VariableStoreHeader
))) {
1208 NextVariable
= GetNextVariablePtr (Variable
);
1209 VariableSize
= (UINT64
) (UINTN
) NextVariable
- (UINT64
) (UINTN
) Variable
;
1211 if (EfiAtRuntime ()) {
1213 // we don't take the state of the variables in mind
1214 // when calculating RemainingVariableStorageSize,
1215 // since the space occupied by variables not marked with
1216 // VAR_ADDED is not allowed to be reclaimed in Runtime.
1218 *RemainingVariableStorageSize
-= VariableSize
;
1221 // Only care about Variables with State VAR_ADDED,because
1222 // the space not marked as VAR_ADDED is reclaimable now.
1224 if (Variable
->State
== VAR_ADDED
) {
1225 *RemainingVariableStorageSize
-= VariableSize
;
1230 // Go to the next one
1232 Variable
= NextVariable
;
1241 VariableCommonInitialize (
1242 IN EFI_HANDLE ImageHandle
,
1243 IN EFI_SYSTEM_TABLE
*SystemTable
1247 Routine Description:
1248 This function does common initialization for variable services
1252 ImageHandle - The firmware allocated handle for the EFI image.
1253 SystemTable - A pointer to the EFI System Table.
1259 EFI_NOT_FOUND - Variable store area not found.
1260 EFI_UNSUPPORTED - Currently only one non-volatile variable store is supported.
1261 EFI_SUCCESS - Variable services successfully initialized.
1266 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
1268 VARIABLE_STORE_HEADER
*VolatileVariableStore
;
1269 VARIABLE_STORE_HEADER
*VariableStoreHeader
;
1270 VARIABLE_HEADER
*NextVariable
;
1272 EFI_PHYSICAL_ADDRESS FvVolHdr
;
1274 UINT64 TempVariableStoreHeader
;
1276 EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor
;
1277 EFI_FLASH_SUBAREA_ENTRY VariableStoreEntry
;
1283 Status
= gBS
->AllocatePool (
1284 EfiRuntimeServicesData
,
1285 sizeof (ESAL_VARIABLE_GLOBAL
),
1286 (VOID
**) &mVariableModuleGlobal
1289 if (EFI_ERROR (Status
)) {
1293 // Allocate memory for volatile variable store
1295 Status
= gBS
->AllocatePool (
1296 EfiRuntimeServicesData
,
1297 VARIABLE_STORE_SIZE
+ SCRATCH_SIZE
,
1298 (VOID
**) &VolatileVariableStore
1301 if (EFI_ERROR (Status
)) {
1302 gBS
->FreePool (mVariableModuleGlobal
);
1306 SetMem (VolatileVariableStore
, VARIABLE_STORE_SIZE
+ SCRATCH_SIZE
, 0xff);
1309 // Variable Specific Data
1311 mVariableModuleGlobal
->VariableBase
[Physical
].VolatileVariableBase
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) VolatileVariableStore
;
1312 mVariableModuleGlobal
->VolatileLastVariableOffset
= sizeof (VARIABLE_STORE_HEADER
);
1314 VolatileVariableStore
->Signature
= VARIABLE_STORE_SIGNATURE
;
1315 VolatileVariableStore
->Size
= VARIABLE_STORE_SIZE
;
1316 VolatileVariableStore
->Format
= VARIABLE_STORE_FORMATTED
;
1317 VolatileVariableStore
->State
= VARIABLE_STORE_HEALTHY
;
1318 VolatileVariableStore
->Reserved
= 0;
1319 VolatileVariableStore
->Reserved1
= 0;
1322 // Get non volatile varaible store
1325 TempVariableStoreHeader
= (UINT64
) PcdGet32 (PcdFlashNvStorageVariableBase
);
1326 VariableStoreEntry
.Base
= TempVariableStoreHeader
+ \
1327 (((EFI_FIRMWARE_VOLUME_HEADER
*) (UINTN
) (TempVariableStoreHeader
)) -> HeaderLength
);
1328 VariableStoreEntry
.Length
= (UINT64
) PcdGet32 (PcdFlashNvStorageVariableSize
) - \
1329 (((EFI_FIRMWARE_VOLUME_HEADER
*) (UINTN
) (TempVariableStoreHeader
)) -> HeaderLength
);
1331 // Mark the variable storage region of the FLASH as RUNTIME
1333 BaseAddress
= VariableStoreEntry
.Base
& (~EFI_PAGE_MASK
);
1334 Length
= VariableStoreEntry
.Length
+ (VariableStoreEntry
.Base
- BaseAddress
);
1335 Length
= (Length
+ EFI_PAGE_SIZE
- 1) & (~EFI_PAGE_MASK
);
1337 Status
= gDS
->GetMemorySpaceDescriptor (BaseAddress
, &GcdDescriptor
);
1338 if (EFI_ERROR (Status
)) {
1339 gBS
->FreePool (mVariableModuleGlobal
);
1340 gBS
->FreePool (VolatileVariableStore
);
1341 return EFI_UNSUPPORTED
;
1344 Status
= gDS
->SetMemorySpaceAttributes (
1347 GcdDescriptor
.Attributes
| EFI_MEMORY_RUNTIME
1349 if (EFI_ERROR (Status
)) {
1350 gBS
->FreePool (mVariableModuleGlobal
);
1351 gBS
->FreePool (VolatileVariableStore
);
1352 return EFI_UNSUPPORTED
;
1355 // Get address of non volatile variable store base
1357 mVariableModuleGlobal
->VariableBase
[Physical
].NonVolatileVariableBase
= VariableStoreEntry
.Base
;
1363 // Find the Correct Instance of the FV Block Service.
1366 CurrPtr
= (CHAR8
*) ((UINTN
) mVariableModuleGlobal
->VariableBase
[Physical
].NonVolatileVariableBase
);
1367 while (EfiFvbGetPhysicalAddress (Instance
, &FvVolHdr
) == EFI_SUCCESS
) {
1368 FwVolHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) ((UINTN
) FvVolHdr
);
1369 if (CurrPtr
>= (CHAR8
*) FwVolHeader
&& CurrPtr
< (((CHAR8
*) FwVolHeader
) + FwVolHeader
->FvLength
)) {
1370 mVariableModuleGlobal
->FvbInstance
= Instance
;
1377 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) CurrPtr
;
1378 if (GetVariableStoreStatus (VariableStoreHeader
) == EfiValid
) {
1379 if (~VariableStoreHeader
->Size
== 0) {
1380 Status
= UpdateVariableStore (
1381 &mVariableModuleGlobal
->VariableBase
[Physical
],
1384 mVariableModuleGlobal
->FvbInstance
,
1385 (UINTN
) &VariableStoreHeader
->Size
,
1387 (UINT8
*) &VariableStoreEntry
.Length
1390 if (EFI_ERROR (Status
)) {
1395 mVariableModuleGlobal
->VariableBase
[Physical
].NonVolatileVariableBase
= (EFI_PHYSICAL_ADDRESS
) ((UINTN
) CurrPtr
);
1397 // Parse non-volatile variable data and get last variable offset
1399 NextVariable
= (VARIABLE_HEADER
*) (CurrPtr
+ sizeof (VARIABLE_STORE_HEADER
));
1400 Status
= EFI_SUCCESS
;
1402 while (IsValidVariableHeader (NextVariable
)) {
1403 NextVariable
= GetNextVariablePtr (NextVariable
);
1406 mVariableModuleGlobal
->NonVolatileLastVariableOffset
= (UINTN
) NextVariable
- (UINTN
) CurrPtr
;
1409 // Check if the free area is blow a threshold
1411 if ((((VARIABLE_STORE_HEADER
*)((UINTN
) CurrPtr
))->Size
- mVariableModuleGlobal
->NonVolatileLastVariableOffset
) < VARIABLE_RECLAIM_THRESHOLD
) {
1413 mVariableModuleGlobal
->VariableBase
[Physical
].NonVolatileVariableBase
,
1414 &mVariableModuleGlobal
->NonVolatileLastVariableOffset
,
1419 if (EFI_ERROR (Status
)) {
1420 gBS
->FreePool (mVariableModuleGlobal
);
1421 gBS
->FreePool (VolatileVariableStore
);
1426 // Check if the free area is really free.
1428 for (Index
= mVariableModuleGlobal
->NonVolatileLastVariableOffset
; Index
< VariableStoreHeader
->Size
; Index
++) {
1429 Data
= ((UINT8
*) (UINTN
) mVariableModuleGlobal
->VariableBase
[Physical
].NonVolatileVariableBase
)[Index
];
1432 // There must be something wrong in variable store, do reclaim operation.
1435 mVariableModuleGlobal
->VariableBase
[Physical
].NonVolatileVariableBase
,
1436 &mVariableModuleGlobal
->NonVolatileLastVariableOffset
,
1444 if (EFI_ERROR (Status
)) {
1445 gBS
->FreePool (mVariableModuleGlobal
);
1446 gBS
->FreePool (VolatileVariableStore
);