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.
36 AcquireLockOnlyAtBootTime (
40 if (!EfiAtRuntime ()) {
41 EfiAcquireLock (Lock
);
46 // This is a temperary function which will be removed
47 // when EfiAcquireLock in UefiLib can handle the
48 // the call in UEFI Runtimer driver in RT phase.
51 ReleaseLockOnlyAtBootTime (
55 if (!EfiAtRuntime ()) {
56 EfiReleaseLock (Lock
);
70 Determine the length of null terminated char16 array.
74 String Null-terminated CHAR16 array pointer.
78 UINT32 Number of bytes in the string, including the double NULL at the end;
90 while (0 != String
[Count
]) {
94 return (Count
* 2) + 2;
100 IsValidVariableHeader (
101 IN VARIABLE_HEADER
*Variable
107 This code checks if variable header is valid or not.
110 Variable Pointer to the Variable Header.
113 TRUE Variable header is valid.
114 FALSE Variable header is not valid.
118 if (Variable
== NULL
||
119 Variable
->StartId
!= VARIABLE_DATA
||
120 (sizeof (VARIABLE_HEADER
) + Variable
->NameSize
+ Variable
->DataSize
) > MAX_VARIABLE_SIZE
131 UpdateVariableStore (
132 IN VARIABLE_GLOBAL
*Global
,
134 IN BOOLEAN SetByIndex
,
136 IN UINTN DataPtrIndex
,
144 This function writes data to the FWH at the correct LBA even if the LBAs
149 Global Pointer to VARAIBLE_GLOBAL structure
150 Volatile If the Variable is Volatile or Non-Volatile
151 SetByIndex TRUE: Target pointer is given as index
152 FALSE: Target pointer is absolute
153 Instance Instance of FV Block services
154 DataPtrIndex Pointer to the Data from the end of VARIABLE_STORE_HEADER
156 DataSize Size of data to be written.
157 Buffer Pointer to the buffer from which data is written
165 EFI_FV_BLOCK_MAP_ENTRY
*PtrBlockMapEntry
;
173 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
174 VARIABLE_STORE_HEADER
*VolatileBase
;
175 EFI_PHYSICAL_ADDRESS FvVolHdr
;
176 EFI_PHYSICAL_ADDRESS DataPtr
;
180 DataPtr
= DataPtrIndex
;
183 // Check if the Data is Volatile
186 EfiFvbGetPhysicalAddress (Instance
, &FvVolHdr
);
187 FwVolHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) ((UINTN
) FvVolHdr
);
189 // Data Pointer should point to the actual Address where data is to be
193 DataPtr
+= Global
->NonVolatileVariableBase
;
196 if ((DataPtr
+ DataSize
) >= ((EFI_PHYSICAL_ADDRESS
) (UINTN
) ((UINT8
*) FwVolHeader
+ FwVolHeader
->FvLength
))) {
197 return EFI_INVALID_PARAMETER
;
201 // Data Pointer should point to the actual Address where data is to be
204 VolatileBase
= (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->VolatileVariableBase
);
206 DataPtr
+= Global
->VolatileVariableBase
;
209 if ((DataPtr
+ DataSize
) >= ((UINTN
) ((UINT8
*) VolatileBase
+ VolatileBase
->Size
))) {
210 return EFI_INVALID_PARAMETER
;
214 // If Volatile Variable just do a simple mem copy.
217 CopyMem ((UINT8
*) ((UINTN
) DataPtr
), Buffer
, DataSize
);
221 // If we are here we are dealing with Non-Volatile Variables
223 LinearOffset
= (UINTN
) FwVolHeader
;
224 CurrWritePtr
= (UINTN
) DataPtr
;
225 CurrWriteSize
= DataSize
;
229 if (CurrWritePtr
< LinearOffset
) {
230 return EFI_INVALID_PARAMETER
;
233 for (PtrBlockMapEntry
= FwVolHeader
->FvBlockMap
; PtrBlockMapEntry
->NumBlocks
!= 0; PtrBlockMapEntry
++) {
234 for (BlockIndex2
= 0; BlockIndex2
< PtrBlockMapEntry
->NumBlocks
; BlockIndex2
++) {
236 // Check to see if the Variable Writes are spanning through multiple
239 if ((CurrWritePtr
>= LinearOffset
) && (CurrWritePtr
< LinearOffset
+ PtrBlockMapEntry
->BlockLength
)) {
240 if ((CurrWritePtr
+ CurrWriteSize
) <= (LinearOffset
+ PtrBlockMapEntry
->BlockLength
)) {
241 Status
= EfiFvbWriteBlock (
244 (UINTN
) (CurrWritePtr
- LinearOffset
),
248 if (EFI_ERROR (Status
)) {
252 Size
= (UINT32
) (LinearOffset
+ PtrBlockMapEntry
->BlockLength
- CurrWritePtr
);
253 Status
= EfiFvbWriteBlock (
256 (UINTN
) (CurrWritePtr
- LinearOffset
),
260 if (EFI_ERROR (Status
)) {
264 CurrWritePtr
= LinearOffset
+ PtrBlockMapEntry
->BlockLength
;
265 CurrBuffer
= CurrBuffer
+ Size
;
266 CurrWriteSize
= CurrWriteSize
- Size
;
270 LinearOffset
+= PtrBlockMapEntry
->BlockLength
;
279 VARIABLE_STORE_STATUS
281 GetVariableStoreStatus (
282 IN VARIABLE_STORE_HEADER
*VarStoreHeader
288 This code gets the current status of Variable Store.
292 VarStoreHeader Pointer to the Variable Store Header.
296 EfiRaw Variable store status is raw
297 EfiValid Variable store status is valid
298 EfiInvalid Variable store status is invalid
302 if (VarStoreHeader
->Signature
== VARIABLE_STORE_SIGNATURE
&&
303 VarStoreHeader
->Format
== VARIABLE_STORE_FORMATTED
&&
304 VarStoreHeader
->State
== VARIABLE_STORE_HEALTHY
308 } else if (VarStoreHeader
->Signature
== 0xffffffff &&
309 VarStoreHeader
->Size
== 0xffffffff &&
310 VarStoreHeader
->Format
== 0xff &&
311 VarStoreHeader
->State
== 0xff
324 IN VARIABLE_HEADER
*Variable
330 This code gets the pointer to the variable data.
334 Variable Pointer to the Variable Header.
338 UINT8* Pointer to Variable Data
343 // Be careful about pad size for alignment
345 return (UINT8
*) ((UINTN
) GET_VARIABLE_NAME_PTR (Variable
) + Variable
->NameSize
+ GET_PAD_SIZE (Variable
->NameSize
));
352 IN VARIABLE_HEADER
*Variable
358 This code gets the pointer to the next variable header.
362 Variable Pointer to the Variable Header.
366 VARIABLE_HEADER* Pointer to next variable header.
370 if (!IsValidVariableHeader (Variable
)) {
374 // Be careful about pad size for alignment
376 return (VARIABLE_HEADER
*) ((UINTN
) GetVariableDataPtr (Variable
) + Variable
->DataSize
+ GET_PAD_SIZE (Variable
->DataSize
));
383 IN VARIABLE_STORE_HEADER
*VarStoreHeader
389 This code gets the pointer to the last variable memory pointer byte
393 VarStoreHeader Pointer to the Variable Store Header.
397 VARIABLE_HEADER* Pointer to last unavailable Variable Header
402 // The end of variable store
404 return (VARIABLE_HEADER
*) ((UINTN
) VarStoreHeader
+ VarStoreHeader
->Size
);
411 IN EFI_PHYSICAL_ADDRESS VariableBase
,
412 OUT UINTN
*LastVariableOffset
,
413 IN BOOLEAN IsVolatile
419 Variable store garbage collection and reclaim operation
423 VariableBase Base address of variable store
424 LastVariableOffset Offset of last variable
425 IsVolatile The variable store is volatile or not,
426 if it is non-volatile, need FTW
434 VARIABLE_HEADER
*Variable
;
435 VARIABLE_HEADER
*NextVariable
;
436 VARIABLE_STORE_HEADER
*VariableStoreHeader
;
438 UINTN ValidBufferSize
;
443 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) ((UINTN
) VariableBase
);
446 // Start Pointers for the variable.
448 Variable
= (VARIABLE_HEADER
*) (VariableStoreHeader
+ 1);
450 ValidBufferSize
= sizeof (VARIABLE_STORE_HEADER
);
452 while (IsValidVariableHeader (Variable
)) {
453 NextVariable
= GetNextVariablePtr (Variable
);
454 if (Variable
->State
== VAR_ADDED
) {
455 VariableSize
= (UINTN
) NextVariable
- (UINTN
) Variable
;
456 ValidBufferSize
+= VariableSize
;
459 Variable
= NextVariable
;
462 Status
= gBS
->AllocatePool (
465 (VOID
**) &ValidBuffer
467 if (EFI_ERROR (Status
)) {
471 SetMem (ValidBuffer
, ValidBufferSize
, 0xff);
473 CurrPtr
= ValidBuffer
;
476 // Copy variable store header
478 CopyMem (CurrPtr
, VariableStoreHeader
, sizeof (VARIABLE_STORE_HEADER
));
479 CurrPtr
+= sizeof (VARIABLE_STORE_HEADER
);
482 // Start Pointers for the variable.
484 Variable
= (VARIABLE_HEADER
*) (VariableStoreHeader
+ 1);
486 while (IsValidVariableHeader (Variable
)) {
487 NextVariable
= GetNextVariablePtr (Variable
);
488 if (Variable
->State
== VAR_ADDED
) {
489 VariableSize
= (UINTN
) NextVariable
- (UINTN
) Variable
;
490 CopyMem (CurrPtr
, (UINT8
*) Variable
, VariableSize
);
491 CurrPtr
+= VariableSize
;
494 Variable
= NextVariable
;
499 // If volatile variable store, just copy valid buffer
501 SetMem ((UINT8
*) (UINTN
) VariableBase
, VariableStoreHeader
->Size
, 0xff);
502 CopyMem ((UINT8
*) (UINTN
) VariableBase
, ValidBuffer
, ValidBufferSize
);
503 *LastVariableOffset
= ValidBufferSize
;
504 Status
= EFI_SUCCESS
;
507 // If non-volatile variable store, perform FTW here.
509 Status
= FtwVariableSpace (
514 if (!EFI_ERROR (Status
)) {
515 *LastVariableOffset
= ValidBufferSize
;
519 gBS
->FreePool (ValidBuffer
);
521 if (EFI_ERROR (Status
)) {
522 *LastVariableOffset
= 0;
532 IN CHAR16
*VariableName
,
533 IN EFI_GUID
*VendorGuid
,
534 OUT VARIABLE_POINTER_TRACK
*PtrTrack
,
535 IN VARIABLE_GLOBAL
*Global
541 This code finds variable in storage blocks (Volatile or Non-Volatile)
545 VariableName Name of the variable to be found
546 VendorGuid Vendor GUID to be found.
547 PtrTrack Variable Track Pointer structure that contains
548 Variable Information.
549 Contains the pointer of Variable header.
550 Global VARIABLE_GLOBAL pointer
558 VARIABLE_HEADER
*Variable
[2];
559 VARIABLE_STORE_HEADER
*VariableStoreHeader
[2];
563 // We aquire the lock at the entry of FindVariable as GetVariable, GetNextVariableName
564 // SetVariable all call FindVariable at entry point. Please move "Aquire Lock" to
565 // the correct places if this assumption does not hold TRUE anymore.
567 AcquireLockOnlyAtBootTime(&Global
->VariableServicesLock
);
570 // 0: Non-Volatile, 1: Volatile
572 VariableStoreHeader
[0] = (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->NonVolatileVariableBase
);
573 VariableStoreHeader
[1] = (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->VolatileVariableBase
);
576 // Start Pointers for the variable.
577 // Actual Data Pointer where data can be written.
579 Variable
[0] = (VARIABLE_HEADER
*) (VariableStoreHeader
[0] + 1);
580 Variable
[1] = (VARIABLE_HEADER
*) (VariableStoreHeader
[1] + 1);
582 if (VariableName
[0] != 0 && VendorGuid
== NULL
) {
583 return EFI_INVALID_PARAMETER
;
586 // Find the variable by walk through non-volatile and volatile variable store
588 for (Index
= 0; Index
< 2; Index
++) {
589 PtrTrack
->StartPtr
= (VARIABLE_HEADER
*) (VariableStoreHeader
[Index
] + 1);
590 PtrTrack
->EndPtr
= GetEndPointer (VariableStoreHeader
[Index
]);
592 while (IsValidVariableHeader (Variable
[Index
]) && (Variable
[Index
] <= GetEndPointer (VariableStoreHeader
[Index
]))) {
593 if (Variable
[Index
]->State
== VAR_ADDED
) {
594 if (!(EfiAtRuntime () && !(Variable
[Index
]->Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
))) {
595 if (VariableName
[0] == 0) {
596 PtrTrack
->CurrPtr
= Variable
[Index
];
597 PtrTrack
->Volatile
= (BOOLEAN
) Index
;
600 if (CompareGuid (VendorGuid
, &Variable
[Index
]->VendorGuid
)) {
601 if (!CompareMem (VariableName
, GET_VARIABLE_NAME_PTR (Variable
[Index
]), ArrayLength (VariableName
))) {
602 PtrTrack
->CurrPtr
= Variable
[Index
];
603 PtrTrack
->Volatile
= (BOOLEAN
) Index
;
611 Variable
[Index
] = GetNextVariablePtr (Variable
[Index
]);
620 PtrTrack
->CurrPtr
= NULL
;
621 return EFI_NOT_FOUND
;
627 IN CHAR16
*VariableName
,
628 IN EFI_GUID
* VendorGuid
,
629 OUT UINT32
*Attributes OPTIONAL
,
630 IN OUT UINTN
*DataSize
,
632 IN VARIABLE_GLOBAL
* Global
,
639 This code finds variable in storage blocks (Volatile or Non-Volatile)
643 VariableName Name of Variable to be found
644 VendorGuid Variable vendor GUID
645 Attributes OPTIONAL Attribute value of the variable found
646 DataSize Size of Data found. If size is less than the
647 data, this value contains the required size.
649 Global Pointer to VARIABLE_GLOBAL structure
650 Instance Instance of the Firmware Volume.
658 VARIABLE_POINTER_TRACK Variable
;
662 if (VariableName
== NULL
|| VendorGuid
== NULL
|| DataSize
== NULL
) {
663 return EFI_INVALID_PARAMETER
;
666 // Find existing variable
668 Status
= FindVariable (VariableName
, VendorGuid
, &Variable
, Global
);
670 if (Variable
.CurrPtr
== NULL
|| EFI_ERROR (Status
)) {
676 VarDataSize
= Variable
.CurrPtr
->DataSize
;
677 if (*DataSize
>= VarDataSize
) {
679 Status
= EFI_INVALID_PARAMETER
;
683 CopyMem (Data
, GetVariableDataPtr (Variable
.CurrPtr
), VarDataSize
);
684 if (Attributes
!= NULL
) {
685 *Attributes
= Variable
.CurrPtr
->Attributes
;
688 *DataSize
= VarDataSize
;
689 Status
= EFI_SUCCESS
;
692 *DataSize
= VarDataSize
;
693 Status
= EFI_BUFFER_TOO_SMALL
;
698 ReleaseLockOnlyAtBootTime (&Global
->VariableServicesLock
);
704 GetNextVariableName (
705 IN OUT UINTN
*VariableNameSize
,
706 IN OUT CHAR16
*VariableName
,
707 IN OUT EFI_GUID
*VendorGuid
,
708 IN VARIABLE_GLOBAL
*Global
,
715 This code Finds the Next available variable
719 VariableNameSize Size of the variable
720 VariableName Pointer to variable name
721 VendorGuid Variable Vendor Guid
722 Global VARIABLE_GLOBAL structure pointer.
731 VARIABLE_POINTER_TRACK Variable
;
735 if (VariableNameSize
== NULL
|| VariableName
== NULL
|| VendorGuid
== NULL
) {
736 return EFI_INVALID_PARAMETER
;
739 Status
= FindVariable (VariableName
, VendorGuid
, &Variable
, Global
);
741 if (Variable
.CurrPtr
== NULL
|| EFI_ERROR (Status
)) {
745 if (VariableName
[0] != 0) {
747 // If variable name is not NULL, get next variable
749 Variable
.CurrPtr
= GetNextVariablePtr (Variable
.CurrPtr
);
754 // If both volatile and non-volatile variable store are parsed,
757 if (Variable
.CurrPtr
>= Variable
.EndPtr
|| Variable
.CurrPtr
== NULL
) {
758 Variable
.Volatile
= (BOOLEAN
) (Variable
.Volatile
^ ((BOOLEAN
) 0x1));
759 if (Variable
.Volatile
) {
760 Variable
.StartPtr
= (VARIABLE_HEADER
*) ((UINTN
) (Global
->VolatileVariableBase
+ sizeof (VARIABLE_STORE_HEADER
)));
761 Variable
.EndPtr
= (VARIABLE_HEADER
*) GetEndPointer ((VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->VolatileVariableBase
));
763 Status
= EFI_NOT_FOUND
;
767 Variable
.CurrPtr
= Variable
.StartPtr
;
768 if (!IsValidVariableHeader (Variable
.CurrPtr
)) {
775 if (IsValidVariableHeader (Variable
.CurrPtr
) && Variable
.CurrPtr
->State
== VAR_ADDED
) {
776 if (!(EfiAtRuntime () && !(Variable
.CurrPtr
->Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
))) {
777 VarNameSize
= Variable
.CurrPtr
->NameSize
;
778 if (VarNameSize
<= *VariableNameSize
) {
781 GET_VARIABLE_NAME_PTR (Variable
.CurrPtr
),
786 &Variable
.CurrPtr
->VendorGuid
,
789 Status
= EFI_SUCCESS
;
791 Status
= EFI_BUFFER_TOO_SMALL
;
794 *VariableNameSize
= VarNameSize
;
799 Variable
.CurrPtr
= GetNextVariablePtr (Variable
.CurrPtr
);
803 ReleaseLockOnlyAtBootTime (&Global
->VariableServicesLock
);
810 IN CHAR16
*VariableName
,
811 IN EFI_GUID
*VendorGuid
,
812 IN UINT32 Attributes
,
815 IN VARIABLE_GLOBAL
*Global
,
816 IN UINTN
*VolatileOffset
,
817 IN UINTN
*NonVolatileOffset
,
824 This code sets variable in storage blocks (Volatile or Non-Volatile)
828 VariableName Name of Variable to be found
829 VendorGuid Variable vendor GUID
830 Attributes Attribute value of the variable found
831 DataSize Size of Data found. If size is less than the
832 data, this value contains the required size.
834 Global Pointer to VARIABLE_GLOBAL structure
835 VolatileOffset The offset of last volatile variable
836 NonVolatileOffset The offset of last non-volatile variable
837 Instance Instance of the Firmware Volume.
842 EFI_INVALID_PARAMETER - Invalid parameter
843 EFI_SUCCESS - Set successfully
844 EFI_OUT_OF_RESOURCES - Resource not enough to set variable
845 EFI_NOT_FOUND - Not found
849 VARIABLE_POINTER_TRACK Variable
;
851 VARIABLE_HEADER
*NextVariable
;
861 if (VariableName
== NULL
|| VariableName
[0] == 0 || VendorGuid
== NULL
) {
862 return EFI_INVALID_PARAMETER
;
865 Status
= FindVariable (VariableName
, VendorGuid
, &Variable
, Global
);
867 if (Status
== EFI_INVALID_PARAMETER
) {
869 } else if (!EFI_ERROR (Status
) && Variable
.Volatile
&& EfiAtRuntime()) {
871 // If EfiAtRuntime and the variable is Volatile and Runtime Access,
872 // the volatile is ReadOnly, and SetVariable should be aborted and
873 // return EFI_WRITE_PROTECTED.
875 Status
= EFI_WRITE_PROTECTED
;
877 } else if (sizeof (VARIABLE_HEADER
) + ArrayLength (VariableName
) + DataSize
> MAX_VARIABLE_SIZE
) {
879 // The size of the VariableName, including the Unicode Null in bytes plus
880 // the DataSize is limited to maximum size of MAX_VARIABLE_SIZE (1024) bytes.
882 Status
= EFI_INVALID_PARAMETER
;
884 } else if (Attributes
== EFI_VARIABLE_NON_VOLATILE
) {
886 // Make sure not only EFI_VARIABLE_NON_VOLATILE is set
888 Status
= EFI_INVALID_PARAMETER
;
890 } else if ((Attributes
& (EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
)) ==
891 EFI_VARIABLE_RUNTIME_ACCESS
) {
893 // Make sure if runtime bit is set, boot service bit is set also
895 Status
= EFI_INVALID_PARAMETER
;
897 } else if (EfiAtRuntime () && Attributes
&& !(Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
)) {
899 // Runtime but Attribute is not Runtime
901 Status
= EFI_INVALID_PARAMETER
;
903 } else if (EfiAtRuntime () && Attributes
&& !(Attributes
& EFI_VARIABLE_NON_VOLATILE
)) {
905 // Cannot set volatile variable in Runtime
907 Status
= EFI_INVALID_PARAMETER
;
909 } else if (DataSize
== 0 || (Attributes
& (EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
)) == 0) {
911 // Setting a data variable with no access, or zero DataSize attributes
912 // specified causes it to be deleted.
914 if (!EFI_ERROR (Status
)) {
915 State
= Variable
.CurrPtr
->State
;
916 State
&= VAR_DELETED
;
918 Status
= UpdateVariableStore (
923 (UINTN
) &Variable
.CurrPtr
->State
,
927 if (EFI_ERROR (Status
)) {
931 Status
= EFI_SUCCESS
;
935 Status
= EFI_NOT_FOUND
;
938 if (!EFI_ERROR (Status
)) {
940 // If the variable is marked valid and the same data has been passed in
941 // then return to the caller immediately.
943 if (Variable
.CurrPtr
->DataSize
== DataSize
&&
944 !CompareMem (Data
, GetVariableDataPtr (Variable
.CurrPtr
), DataSize
)
946 Status
= EFI_SUCCESS
;
948 } else if (Variable
.CurrPtr
->State
== VAR_ADDED
) {
950 // Mark the old variable as in delete transition
952 State
= Variable
.CurrPtr
->State
;
953 State
&= VAR_IN_DELETED_TRANSITION
;
955 Status
= UpdateVariableStore (
960 (UINTN
) &Variable
.CurrPtr
->State
,
964 if (EFI_ERROR (Status
)) {
970 // Create a new variable and copy the data.
972 // Tricky part: Use scratch data area at the end of volatile variable store
973 // as a temporary storage.
975 NextVariable
= GetEndPointer ((VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->VolatileVariableBase
));
977 SetMem (NextVariable
, SCRATCH_SIZE
, 0xff);
979 NextVariable
->StartId
= VARIABLE_DATA
;
980 NextVariable
->Attributes
= Attributes
;
982 // NextVariable->State = VAR_ADDED;
984 NextVariable
->Reserved
= 0;
985 VarNameOffset
= sizeof (VARIABLE_HEADER
);
986 VarNameSize
= ArrayLength (VariableName
);
988 (UINT8
*) ((UINTN
) NextVariable
+ VarNameOffset
),
992 VarDataOffset
= VarNameOffset
+ VarNameSize
+ GET_PAD_SIZE (VarNameSize
);
994 (UINT8
*) ((UINTN
) NextVariable
+ VarDataOffset
),
998 CopyMem (&NextVariable
->VendorGuid
, VendorGuid
, sizeof (EFI_GUID
));
1000 // There will be pad bytes after Data, the NextVariable->NameSize and
1001 // NextVariable->DataSize should not include pad size so that variable
1002 // service can get actual size in GetVariable
1004 NextVariable
->NameSize
= (UINT32
)VarNameSize
;
1005 NextVariable
->DataSize
= (UINT32
)DataSize
;
1008 // The actual size of the variable that stores in storage should
1009 // include pad size.
1011 VarSize
= VarDataOffset
+ DataSize
+ GET_PAD_SIZE (DataSize
);
1012 if (Attributes
& EFI_VARIABLE_NON_VOLATILE
) {
1013 if ((UINT32
) (VarSize
+*NonVolatileOffset
) >
1014 ((VARIABLE_STORE_HEADER
*) ((UINTN
) (Global
->NonVolatileVariableBase
)))->Size
1016 if (EfiAtRuntime ()) {
1017 Status
= EFI_OUT_OF_RESOURCES
;
1021 // Perform garbage collection & reclaim operation
1023 Status
= Reclaim (Global
->NonVolatileVariableBase
, NonVolatileOffset
, FALSE
);
1024 if (EFI_ERROR (Status
)) {
1028 // If still no enough space, return out of resources
1030 if ((UINT32
) (VarSize
+*NonVolatileOffset
) >
1031 ((VARIABLE_STORE_HEADER
*) ((UINTN
) (Global
->NonVolatileVariableBase
)))->Size
1033 Status
= EFI_OUT_OF_RESOURCES
;
1041 // 1. Write variable header
1042 // 2. Write variable data
1043 // 3. Set variable state to valid
1048 Status
= UpdateVariableStore (
1054 sizeof (VARIABLE_HEADER
),
1055 (UINT8
*) NextVariable
1058 if (EFI_ERROR (Status
)) {
1064 Status
= UpdateVariableStore (
1069 *NonVolatileOffset
+ sizeof (VARIABLE_HEADER
),
1070 (UINT32
) VarSize
- sizeof (VARIABLE_HEADER
),
1071 (UINT8
*) NextVariable
+ sizeof (VARIABLE_HEADER
)
1074 if (EFI_ERROR (Status
)) {
1080 NextVariable
->State
= VAR_ADDED
;
1081 Status
= UpdateVariableStore (
1087 sizeof (VARIABLE_HEADER
),
1088 (UINT8
*) NextVariable
1091 if (EFI_ERROR (Status
)) {
1095 *NonVolatileOffset
= *NonVolatileOffset
+ VarSize
;
1098 if (EfiAtRuntime ()) {
1099 Status
= EFI_INVALID_PARAMETER
;
1103 if ((UINT32
) (VarSize
+*VolatileOffset
) >
1104 ((VARIABLE_STORE_HEADER
*) ((UINTN
) (Global
->VolatileVariableBase
)))->Size
1107 // Perform garbage collection & reclaim operation
1109 Status
= Reclaim (Global
->VolatileVariableBase
, VolatileOffset
, TRUE
);
1110 if (EFI_ERROR (Status
)) {
1114 // If still no enough space, return out of resources
1116 if ((UINT32
) (VarSize
+*VolatileOffset
) >
1117 ((VARIABLE_STORE_HEADER
*) ((UINTN
) (Global
->VolatileVariableBase
)))->Size
1119 Status
= EFI_OUT_OF_RESOURCES
;
1126 NextVariable
->State
= VAR_ADDED
;
1127 Status
= UpdateVariableStore (
1134 (UINT8
*) NextVariable
1137 if (EFI_ERROR (Status
)) {
1141 *VolatileOffset
= *VolatileOffset
+ VarSize
;
1144 // Mark the old variable as deleted
1146 if (!Reclaimed
&& !EFI_ERROR (Status
) && Variable
.CurrPtr
!= NULL
) {
1147 State
= Variable
.CurrPtr
->State
;
1148 State
&= VAR_DELETED
;
1150 Status
= UpdateVariableStore (
1155 (UINTN
) &Variable
.CurrPtr
->State
,
1160 if (EFI_ERROR (Status
)) {
1166 Status
= EFI_SUCCESS
;
1168 ReleaseLockOnlyAtBootTime (&Global
->VariableServicesLock
);
1172 #if (EFI_SPECIFICATION_VERSION >= 0x00020000)
1176 IN UINT32 Attributes
,
1177 OUT UINT64
*MaximumVariableStorageSize
,
1178 OUT UINT64
*RemainingVariableStorageSize
,
1179 OUT UINT64
*MaximumVariableSize
,
1180 IN VARIABLE_GLOBAL
*Global
,
1185 Routine Description:
1187 This code returns information about the EFI variables.
1191 Attributes Attributes bitmask to specify the type of variables
1192 on which to return information.
1193 MaximumVariableStorageSize Pointer to the maximum size of the storage space available
1194 for the EFI variables associated with the attributes specified.
1195 RemainingVariableStorageSize Pointer to the remaining size of the storage space available
1196 for the EFI variables associated with the attributes specified.
1197 MaximumVariableSize Pointer to the maximum size of the individual EFI variables
1198 associated with the attributes specified.
1199 Global Pointer to VARIABLE_GLOBAL structure.
1200 Instance Instance of the Firmware Volume.
1205 EFI_INVALID_PARAMETER - An invalid combination of attribute bits was supplied.
1206 EFI_SUCCESS - Query successfully.
1207 EFI_UNSUPPORTED - The attribute is not supported on this platform.
1211 VARIABLE_HEADER
*Variable
;
1212 VARIABLE_HEADER
*NextVariable
;
1213 UINT64 VariableSize
;
1214 VARIABLE_STORE_HEADER
*VariableStoreHeader
;
1216 if(MaximumVariableStorageSize
== NULL
|| RemainingVariableStorageSize
== NULL
|| MaximumVariableSize
== NULL
) {
1217 return EFI_INVALID_PARAMETER
;
1220 if((Attributes
& (EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
)) == 0) {
1222 // Make sure the Attributes combination is supported by the platform.
1224 return EFI_UNSUPPORTED
;
1225 } else if ((Attributes
& (EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
)) == EFI_VARIABLE_RUNTIME_ACCESS
) {
1227 // Make sure if runtime bit is set, boot service bit is set also.
1229 return EFI_INVALID_PARAMETER
;
1230 } else if (EfiAtRuntime () && !(Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
)) {
1232 // Make sure RT Attribute is set if we are in Runtime phase.
1234 return EFI_INVALID_PARAMETER
;
1237 AcquireLockOnlyAtBootTime(&Global
->VariableServicesLock
);
1239 if((Attributes
& EFI_VARIABLE_NON_VOLATILE
) == 0) {
1241 // Query is Volatile related.
1243 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->VolatileVariableBase
);
1246 // Query is Non-Volatile related.
1248 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->NonVolatileVariableBase
);
1252 // Now let's fill *MaximumVariableStorageSize *RemainingVariableStorageSize
1253 // with the storage size (excluding the storage header size).
1255 *MaximumVariableStorageSize
= VariableStoreHeader
->Size
- sizeof (VARIABLE_STORE_HEADER
);
1256 *RemainingVariableStorageSize
= VariableStoreHeader
->Size
- sizeof (VARIABLE_STORE_HEADER
);
1259 // Let *MaximumVariableSize be MAX_VARIABLE_SIZE.
1261 *MaximumVariableSize
= MAX_VARIABLE_SIZE
;
1264 // Point to the starting address of the variables.
1266 Variable
= (VARIABLE_HEADER
*) (VariableStoreHeader
+ 1);
1269 // Now walk through the related variable store.
1271 while (IsValidVariableHeader (Variable
) && (Variable
< GetEndPointer (VariableStoreHeader
))) {
1272 NextVariable
= GetNextVariablePtr (Variable
);
1273 VariableSize
= (UINT64
) (UINTN
) NextVariable
- (UINT64
) (UINTN
) Variable
;
1275 if (EfiAtRuntime ()) {
1277 // we don't take the state of the variables in mind
1278 // when calculating RemainingVariableStorageSize,
1279 // since the space occupied by variables not marked with
1280 // VAR_ADDED is not allowed to be reclaimed in Runtime.
1282 *RemainingVariableStorageSize
-= VariableSize
;
1285 // Only care about Variables with State VAR_ADDED,because
1286 // the space not marked as VAR_ADDED is reclaimable now.
1288 if (Variable
->State
== VAR_ADDED
) {
1289 *RemainingVariableStorageSize
-= VariableSize
;
1294 // Go to the next one
1296 Variable
= NextVariable
;
1299 ReleaseLockOnlyAtBootTime (&Global
->VariableServicesLock
);
1306 VariableCommonInitialize (
1307 IN EFI_HANDLE ImageHandle
,
1308 IN EFI_SYSTEM_TABLE
*SystemTable
1312 Routine Description:
1313 This function does common initialization for variable services
1317 ImageHandle - The firmware allocated handle for the EFI image.
1318 SystemTable - A pointer to the EFI System Table.
1324 EFI_NOT_FOUND - Variable store area not found.
1325 EFI_UNSUPPORTED - Currently only one non-volatile variable store is supported.
1326 EFI_SUCCESS - Variable services successfully initialized.
1331 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
1333 VARIABLE_STORE_HEADER
*VolatileVariableStore
;
1334 VARIABLE_STORE_HEADER
*VariableStoreHeader
;
1335 VARIABLE_HEADER
*NextVariable
;
1337 EFI_PHYSICAL_ADDRESS FvVolHdr
;
1339 UINT64 TempVariableStoreHeader
;
1341 EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor
;
1342 EFI_FLASH_SUBAREA_ENTRY VariableStoreEntry
;
1348 Status
= gBS
->AllocatePool (
1349 EfiRuntimeServicesData
,
1350 sizeof (ESAL_VARIABLE_GLOBAL
),
1351 (VOID
**) &mVariableModuleGlobal
1354 if (EFI_ERROR (Status
)) {
1358 EfiInitializeLock(&mVariableModuleGlobal
->VariableGlobal
[Physical
].VariableServicesLock
, EFI_TPL_CALLBACK
);
1361 // Allocate memory for volatile variable store
1363 Status
= gBS
->AllocatePool (
1364 EfiRuntimeServicesData
,
1365 VARIABLE_STORE_SIZE
+ SCRATCH_SIZE
,
1366 (VOID
**) &VolatileVariableStore
1369 if (EFI_ERROR (Status
)) {
1370 gBS
->FreePool (mVariableModuleGlobal
);
1374 SetMem (VolatileVariableStore
, VARIABLE_STORE_SIZE
+ SCRATCH_SIZE
, 0xff);
1377 // Variable Specific Data
1379 mVariableModuleGlobal
->VariableGlobal
[Physical
].VolatileVariableBase
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) VolatileVariableStore
;
1380 mVariableModuleGlobal
->VolatileLastVariableOffset
= sizeof (VARIABLE_STORE_HEADER
);
1382 VolatileVariableStore
->Signature
= VARIABLE_STORE_SIGNATURE
;
1383 VolatileVariableStore
->Size
= VARIABLE_STORE_SIZE
;
1384 VolatileVariableStore
->Format
= VARIABLE_STORE_FORMATTED
;
1385 VolatileVariableStore
->State
= VARIABLE_STORE_HEALTHY
;
1386 VolatileVariableStore
->Reserved
= 0;
1387 VolatileVariableStore
->Reserved1
= 0;
1390 // Get non volatile varaible store
1393 TempVariableStoreHeader
= (UINT64
) PcdGet32 (PcdFlashNvStorageVariableBase
);
1394 VariableStoreEntry
.Base
= TempVariableStoreHeader
+ \
1395 (((EFI_FIRMWARE_VOLUME_HEADER
*) (UINTN
) (TempVariableStoreHeader
)) -> HeaderLength
);
1396 VariableStoreEntry
.Length
= (UINT64
) PcdGet32 (PcdFlashNvStorageVariableSize
) - \
1397 (((EFI_FIRMWARE_VOLUME_HEADER
*) (UINTN
) (TempVariableStoreHeader
)) -> HeaderLength
);
1399 // Mark the variable storage region of the FLASH as RUNTIME
1401 BaseAddress
= VariableStoreEntry
.Base
& (~EFI_PAGE_MASK
);
1402 Length
= VariableStoreEntry
.Length
+ (VariableStoreEntry
.Base
- BaseAddress
);
1403 Length
= (Length
+ EFI_PAGE_SIZE
- 1) & (~EFI_PAGE_MASK
);
1405 Status
= gDS
->GetMemorySpaceDescriptor (BaseAddress
, &GcdDescriptor
);
1406 if (EFI_ERROR (Status
)) {
1407 gBS
->FreePool (mVariableModuleGlobal
);
1408 gBS
->FreePool (VolatileVariableStore
);
1409 return EFI_UNSUPPORTED
;
1412 Status
= gDS
->SetMemorySpaceAttributes (
1415 GcdDescriptor
.Attributes
| EFI_MEMORY_RUNTIME
1417 if (EFI_ERROR (Status
)) {
1418 gBS
->FreePool (mVariableModuleGlobal
);
1419 gBS
->FreePool (VolatileVariableStore
);
1420 return EFI_UNSUPPORTED
;
1423 // Get address of non volatile variable store base
1425 mVariableModuleGlobal
->VariableGlobal
[Physical
].NonVolatileVariableBase
= VariableStoreEntry
.Base
;
1431 // Find the Correct Instance of the FV Block Service.
1434 CurrPtr
= (CHAR8
*) ((UINTN
) mVariableModuleGlobal
->VariableGlobal
[Physical
].NonVolatileVariableBase
);
1435 while (EfiFvbGetPhysicalAddress (Instance
, &FvVolHdr
) == EFI_SUCCESS
) {
1436 FwVolHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) ((UINTN
) FvVolHdr
);
1437 if (CurrPtr
>= (CHAR8
*) FwVolHeader
&& CurrPtr
< (((CHAR8
*) FwVolHeader
) + FwVolHeader
->FvLength
)) {
1438 mVariableModuleGlobal
->FvbInstance
= Instance
;
1445 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) CurrPtr
;
1446 if (GetVariableStoreStatus (VariableStoreHeader
) == EfiValid
) {
1447 if (~VariableStoreHeader
->Size
== 0) {
1448 Status
= UpdateVariableStore (
1449 &mVariableModuleGlobal
->VariableGlobal
[Physical
],
1452 mVariableModuleGlobal
->FvbInstance
,
1453 (UINTN
) &VariableStoreHeader
->Size
,
1455 (UINT8
*) &VariableStoreEntry
.Length
1458 if (EFI_ERROR (Status
)) {
1463 mVariableModuleGlobal
->VariableGlobal
[Physical
].NonVolatileVariableBase
= (EFI_PHYSICAL_ADDRESS
) ((UINTN
) CurrPtr
);
1465 // Parse non-volatile variable data and get last variable offset
1467 NextVariable
= (VARIABLE_HEADER
*) (CurrPtr
+ sizeof (VARIABLE_STORE_HEADER
));
1468 Status
= EFI_SUCCESS
;
1470 while (IsValidVariableHeader (NextVariable
)) {
1471 NextVariable
= GetNextVariablePtr (NextVariable
);
1474 mVariableModuleGlobal
->NonVolatileLastVariableOffset
= (UINTN
) NextVariable
- (UINTN
) CurrPtr
;
1477 // Check if the free area is blow a threshold
1479 if ((((VARIABLE_STORE_HEADER
*)((UINTN
) CurrPtr
))->Size
- mVariableModuleGlobal
->NonVolatileLastVariableOffset
) < VARIABLE_RECLAIM_THRESHOLD
) {
1481 mVariableModuleGlobal
->VariableGlobal
[Physical
].NonVolatileVariableBase
,
1482 &mVariableModuleGlobal
->NonVolatileLastVariableOffset
,
1487 if (EFI_ERROR (Status
)) {
1488 gBS
->FreePool (mVariableModuleGlobal
);
1489 gBS
->FreePool (VolatileVariableStore
);
1494 // Check if the free area is really free.
1496 for (Index
= mVariableModuleGlobal
->NonVolatileLastVariableOffset
; Index
< VariableStoreHeader
->Size
; Index
++) {
1497 Data
= ((UINT8
*) (UINTN
) mVariableModuleGlobal
->VariableGlobal
[Physical
].NonVolatileVariableBase
)[Index
];
1500 // There must be something wrong in variable store, do reclaim operation.
1503 mVariableModuleGlobal
->VariableGlobal
[Physical
].NonVolatileVariableBase
,
1504 &mVariableModuleGlobal
->NonVolatileLastVariableOffset
,
1512 if (EFI_ERROR (Status
)) {
1513 gBS
->FreePool (mVariableModuleGlobal
);
1514 gBS
->FreePool (VolatileVariableStore
);