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.
24 #include <Common/FlashMap.h>
27 // Don't use module globals after the SetVirtualAddress map is signaled
29 ESAL_VARIABLE_GLOBAL
*mVariableModuleGlobal
;
32 // This is a temperary function which will be removed
33 // when EfiAcquireLock in UefiLib can handle the
34 // the call in UEFI Runtimer driver in RT phase.
38 AcquireLockOnlyAtBootTime (
42 if (!EfiAtRuntime ()) {
43 EfiAcquireLock (Lock
);
48 // This is a temperary function which will be removed
49 // when EfiAcquireLock in UefiLib can handle the
50 // the call in UEFI Runtimer driver in RT phase.
54 ReleaseLockOnlyAtBootTime (
58 if (!EfiAtRuntime ()) {
59 EfiReleaseLock (Lock
);
66 IsValidVariableHeader (
67 IN VARIABLE_HEADER
*Variable
73 This code checks if variable header is valid or not.
76 Variable Pointer to the Variable Header.
79 TRUE Variable header is valid.
80 FALSE Variable header is not valid.
84 if (Variable
== NULL
||
85 Variable
->StartId
!= VARIABLE_DATA
||
86 (sizeof (VARIABLE_HEADER
) + Variable
->NameSize
+ Variable
->DataSize
) > MAX_VARIABLE_SIZE
98 IN VARIABLE_GLOBAL
*Global
,
100 IN BOOLEAN SetByIndex
,
102 IN UINTN DataPtrIndex
,
110 This function writes data to the FWH at the correct LBA even if the LBAs
115 Global Pointer to VARAIBLE_GLOBAL structure
116 Volatile If the Variable is Volatile or Non-Volatile
117 SetByIndex TRUE: Target pointer is given as index
118 FALSE: Target pointer is absolute
119 Instance Instance of FV Block services
120 DataPtrIndex Pointer to the Data from the end of VARIABLE_STORE_HEADER
122 DataSize Size of data to be written.
123 Buffer Pointer to the buffer from which data is written
131 EFI_FV_BLOCK_MAP_ENTRY
*PtrBlockMapEntry
;
139 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
140 VARIABLE_STORE_HEADER
*VolatileBase
;
141 EFI_PHYSICAL_ADDRESS FvVolHdr
;
142 EFI_PHYSICAL_ADDRESS DataPtr
;
146 DataPtr
= DataPtrIndex
;
149 // Check if the Data is Volatile
152 EfiFvbGetPhysicalAddress (Instance
, &FvVolHdr
);
153 FwVolHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) ((UINTN
) FvVolHdr
);
155 // Data Pointer should point to the actual Address where data is to be
159 DataPtr
+= Global
->NonVolatileVariableBase
;
162 if ((DataPtr
+ DataSize
) >= ((EFI_PHYSICAL_ADDRESS
) (UINTN
) ((UINT8
*) FwVolHeader
+ FwVolHeader
->FvLength
))) {
163 return EFI_INVALID_PARAMETER
;
167 // Data Pointer should point to the actual Address where data is to be
170 VolatileBase
= (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->VolatileVariableBase
);
172 DataPtr
+= Global
->VolatileVariableBase
;
175 if ((DataPtr
+ DataSize
) >= ((UINTN
) ((UINT8
*) VolatileBase
+ VolatileBase
->Size
))) {
176 return EFI_INVALID_PARAMETER
;
180 // If Volatile Variable just do a simple mem copy.
183 CopyMem ((UINT8
*) ((UINTN
) DataPtr
), Buffer
, DataSize
);
187 // If we are here we are dealing with Non-Volatile Variables
189 LinearOffset
= (UINTN
) FwVolHeader
;
190 CurrWritePtr
= (UINTN
) DataPtr
;
191 CurrWriteSize
= DataSize
;
195 if (CurrWritePtr
< LinearOffset
) {
196 return EFI_INVALID_PARAMETER
;
199 for (PtrBlockMapEntry
= FwVolHeader
->BlockMap
; PtrBlockMapEntry
->NumBlocks
!= 0; PtrBlockMapEntry
++) {
200 for (BlockIndex2
= 0; BlockIndex2
< PtrBlockMapEntry
->NumBlocks
; BlockIndex2
++) {
202 // Check to see if the Variable Writes are spanning through multiple
205 if ((CurrWritePtr
>= LinearOffset
) && (CurrWritePtr
< LinearOffset
+ PtrBlockMapEntry
->Length
)) {
206 if ((CurrWritePtr
+ CurrWriteSize
) <= (LinearOffset
+ PtrBlockMapEntry
->Length
)) {
207 Status
= EfiFvbWriteBlock (
210 (UINTN
) (CurrWritePtr
- LinearOffset
),
214 if (EFI_ERROR (Status
)) {
218 Size
= (UINT32
) (LinearOffset
+ PtrBlockMapEntry
->Length
- CurrWritePtr
);
219 Status
= EfiFvbWriteBlock (
222 (UINTN
) (CurrWritePtr
- LinearOffset
),
226 if (EFI_ERROR (Status
)) {
230 CurrWritePtr
= LinearOffset
+ PtrBlockMapEntry
->Length
;
231 CurrBuffer
= CurrBuffer
+ Size
;
232 CurrWriteSize
= CurrWriteSize
- Size
;
236 LinearOffset
+= PtrBlockMapEntry
->Length
;
245 VARIABLE_STORE_STATUS
247 GetVariableStoreStatus (
248 IN VARIABLE_STORE_HEADER
*VarStoreHeader
254 This code gets the current status of Variable Store.
258 VarStoreHeader Pointer to the Variable Store Header.
262 EfiRaw Variable store status is raw
263 EfiValid Variable store status is valid
264 EfiInvalid Variable store status is invalid
268 if (VarStoreHeader
->Signature
== VARIABLE_STORE_SIGNATURE
&&
269 VarStoreHeader
->Format
== VARIABLE_STORE_FORMATTED
&&
270 VarStoreHeader
->State
== VARIABLE_STORE_HEALTHY
274 } else if (VarStoreHeader
->Signature
== 0xffffffff &&
275 VarStoreHeader
->Size
== 0xffffffff &&
276 VarStoreHeader
->Format
== 0xff &&
277 VarStoreHeader
->State
== 0xff
290 IN VARIABLE_HEADER
*Variable
296 This code gets the pointer to the variable data.
300 Variable Pointer to the Variable Header.
304 UINT8* Pointer to Variable Data
309 // Be careful about pad size for alignment
311 return (UINT8
*) ((UINTN
) GET_VARIABLE_NAME_PTR (Variable
) + Variable
->NameSize
+ GET_PAD_SIZE (Variable
->NameSize
));
318 IN VARIABLE_HEADER
*Variable
324 This code gets the pointer to the next variable header.
328 Variable Pointer to the Variable Header.
332 VARIABLE_HEADER* Pointer to next variable header.
336 if (!IsValidVariableHeader (Variable
)) {
340 // Be careful about pad size for alignment
342 return (VARIABLE_HEADER
*) ((UINTN
) GetVariableDataPtr (Variable
) + Variable
->DataSize
+ GET_PAD_SIZE (Variable
->DataSize
));
349 IN VARIABLE_STORE_HEADER
*VarStoreHeader
355 This code gets the pointer to the last variable memory pointer byte
359 VarStoreHeader Pointer to the Variable Store Header.
363 VARIABLE_HEADER* Pointer to last unavailable Variable Header
368 // The end of variable store
370 return (VARIABLE_HEADER
*) ((UINTN
) VarStoreHeader
+ VarStoreHeader
->Size
);
377 IN EFI_PHYSICAL_ADDRESS VariableBase
,
378 OUT UINTN
*LastVariableOffset
,
379 IN BOOLEAN IsVolatile
385 Variable store garbage collection and reclaim operation
389 VariableBase Base address of variable store
390 LastVariableOffset Offset of last variable
391 IsVolatile The variable store is volatile or not,
392 if it is non-volatile, need FTW
400 VARIABLE_HEADER
*Variable
;
401 VARIABLE_HEADER
*NextVariable
;
402 VARIABLE_STORE_HEADER
*VariableStoreHeader
;
404 UINTN ValidBufferSize
;
409 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) ((UINTN
) VariableBase
);
412 // Start Pointers for the variable.
414 Variable
= (VARIABLE_HEADER
*) (VariableStoreHeader
+ 1);
416 ValidBufferSize
= sizeof (VARIABLE_STORE_HEADER
);
418 while (IsValidVariableHeader (Variable
)) {
419 NextVariable
= GetNextVariablePtr (Variable
);
420 if (Variable
->State
== VAR_ADDED
) {
421 VariableSize
= (UINTN
) NextVariable
- (UINTN
) Variable
;
422 ValidBufferSize
+= VariableSize
;
425 Variable
= NextVariable
;
428 ValidBuffer
= AllocatePool (ValidBufferSize
);
429 if (ValidBuffer
== NULL
) {
430 return EFI_OUT_OF_RESOURCES
;
433 SetMem (ValidBuffer
, ValidBufferSize
, 0xff);
435 CurrPtr
= ValidBuffer
;
438 // Copy variable store header
440 CopyMem (CurrPtr
, VariableStoreHeader
, sizeof (VARIABLE_STORE_HEADER
));
441 CurrPtr
+= sizeof (VARIABLE_STORE_HEADER
);
444 // Start Pointers for the variable.
446 Variable
= (VARIABLE_HEADER
*) (VariableStoreHeader
+ 1);
448 while (IsValidVariableHeader (Variable
)) {
449 NextVariable
= GetNextVariablePtr (Variable
);
450 if (Variable
->State
== VAR_ADDED
) {
451 VariableSize
= (UINTN
) NextVariable
- (UINTN
) Variable
;
452 CopyMem (CurrPtr
, (UINT8
*) Variable
, VariableSize
);
453 CurrPtr
+= VariableSize
;
456 Variable
= NextVariable
;
461 // If volatile variable store, just copy valid buffer
463 SetMem ((UINT8
*) (UINTN
) VariableBase
, VariableStoreHeader
->Size
, 0xff);
464 CopyMem ((UINT8
*) (UINTN
) VariableBase
, ValidBuffer
, ValidBufferSize
);
465 *LastVariableOffset
= ValidBufferSize
;
466 Status
= EFI_SUCCESS
;
469 // If non-volatile variable store, perform FTW here.
471 Status
= FtwVariableSpace (
476 if (!EFI_ERROR (Status
)) {
477 *LastVariableOffset
= ValidBufferSize
;
481 FreePool (ValidBuffer
);
483 if (EFI_ERROR (Status
)) {
484 *LastVariableOffset
= 0;
494 IN CHAR16
*VariableName
,
495 IN EFI_GUID
*VendorGuid
,
496 OUT VARIABLE_POINTER_TRACK
*PtrTrack
,
497 IN VARIABLE_GLOBAL
*Global
503 This code finds variable in storage blocks (Volatile or Non-Volatile)
507 VariableName Name of the variable to be found
508 VendorGuid Vendor GUID to be found.
509 PtrTrack Variable Track Pointer structure that contains
510 Variable Information.
511 Contains the pointer of Variable header.
512 Global VARIABLE_GLOBAL pointer
520 VARIABLE_HEADER
*Variable
[2];
521 VARIABLE_STORE_HEADER
*VariableStoreHeader
[2];
525 // We aquire the lock at the entry of FindVariable as GetVariable, GetNextVariableName
526 // SetVariable all call FindVariable at entry point. Please move "Aquire Lock" to
527 // the correct places if this assumption does not hold TRUE anymore.
529 AcquireLockOnlyAtBootTime(&Global
->VariableServicesLock
);
532 // 0: Non-Volatile, 1: Volatile
534 VariableStoreHeader
[0] = (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->NonVolatileVariableBase
);
535 VariableStoreHeader
[1] = (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->VolatileVariableBase
);
538 // Start Pointers for the variable.
539 // Actual Data Pointer where data can be written.
541 Variable
[0] = (VARIABLE_HEADER
*) (VariableStoreHeader
[0] + 1);
542 Variable
[1] = (VARIABLE_HEADER
*) (VariableStoreHeader
[1] + 1);
544 if (VariableName
[0] != 0 && VendorGuid
== NULL
) {
545 return EFI_INVALID_PARAMETER
;
548 // Find the variable by walk through non-volatile and volatile variable store
550 for (Index
= 0; Index
< 2; Index
++) {
551 PtrTrack
->StartPtr
= (VARIABLE_HEADER
*) (VariableStoreHeader
[Index
] + 1);
552 PtrTrack
->EndPtr
= GetEndPointer (VariableStoreHeader
[Index
]);
554 while (IsValidVariableHeader (Variable
[Index
]) && (Variable
[Index
] <= GetEndPointer (VariableStoreHeader
[Index
]))) {
555 if (Variable
[Index
]->State
== VAR_ADDED
) {
556 if (!(EfiAtRuntime () && !(Variable
[Index
]->Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
))) {
557 if (VariableName
[0] == 0) {
558 PtrTrack
->CurrPtr
= Variable
[Index
];
559 PtrTrack
->Volatile
= (BOOLEAN
) Index
;
562 if (CompareGuid (VendorGuid
, &Variable
[Index
]->VendorGuid
)) {
563 if (!CompareMem (VariableName
, GET_VARIABLE_NAME_PTR (Variable
[Index
]), Variable
[Index
]->NameSize
)) {
564 PtrTrack
->CurrPtr
= Variable
[Index
];
565 PtrTrack
->Volatile
= (BOOLEAN
) Index
;
573 Variable
[Index
] = GetNextVariablePtr (Variable
[Index
]);
582 PtrTrack
->CurrPtr
= NULL
;
583 return EFI_NOT_FOUND
;
589 IN CHAR16
*VariableName
,
590 IN EFI_GUID
* VendorGuid
,
591 OUT UINT32
*Attributes OPTIONAL
,
592 IN OUT UINTN
*DataSize
,
594 IN VARIABLE_GLOBAL
* Global
,
601 This code finds variable in storage blocks (Volatile or Non-Volatile)
605 VariableName Name of Variable to be found
606 VendorGuid Variable vendor GUID
607 Attributes OPTIONAL Attribute value of the variable found
608 DataSize Size of Data found. If size is less than the
609 data, this value contains the required size.
611 Global Pointer to VARIABLE_GLOBAL structure
612 Instance Instance of the Firmware Volume.
620 VARIABLE_POINTER_TRACK Variable
;
624 if (VariableName
== NULL
|| VendorGuid
== NULL
|| DataSize
== NULL
) {
625 return EFI_INVALID_PARAMETER
;
628 // Find existing variable
630 Status
= FindVariable (VariableName
, VendorGuid
, &Variable
, Global
);
632 if (Variable
.CurrPtr
== NULL
|| EFI_ERROR (Status
)) {
638 VarDataSize
= Variable
.CurrPtr
->DataSize
;
639 if (*DataSize
>= VarDataSize
) {
641 Status
= EFI_INVALID_PARAMETER
;
645 CopyMem (Data
, GetVariableDataPtr (Variable
.CurrPtr
), VarDataSize
);
646 if (Attributes
!= NULL
) {
647 *Attributes
= Variable
.CurrPtr
->Attributes
;
650 *DataSize
= VarDataSize
;
651 Status
= EFI_SUCCESS
;
654 *DataSize
= VarDataSize
;
655 Status
= EFI_BUFFER_TOO_SMALL
;
660 ReleaseLockOnlyAtBootTime (&Global
->VariableServicesLock
);
666 GetNextVariableName (
667 IN OUT UINTN
*VariableNameSize
,
668 IN OUT CHAR16
*VariableName
,
669 IN OUT EFI_GUID
*VendorGuid
,
670 IN VARIABLE_GLOBAL
*Global
,
677 This code Finds the Next available variable
681 VariableNameSize Size of the variable
682 VariableName Pointer to variable name
683 VendorGuid Variable Vendor Guid
684 Global VARIABLE_GLOBAL structure pointer.
693 VARIABLE_POINTER_TRACK Variable
;
697 if (VariableNameSize
== NULL
|| VariableName
== NULL
|| VendorGuid
== NULL
) {
698 return EFI_INVALID_PARAMETER
;
701 Status
= FindVariable (VariableName
, VendorGuid
, &Variable
, Global
);
703 if (Variable
.CurrPtr
== NULL
|| EFI_ERROR (Status
)) {
707 if (VariableName
[0] != 0) {
709 // If variable name is not NULL, get next variable
711 Variable
.CurrPtr
= GetNextVariablePtr (Variable
.CurrPtr
);
716 // If both volatile and non-volatile variable store are parsed,
719 if (Variable
.CurrPtr
>= Variable
.EndPtr
|| Variable
.CurrPtr
== NULL
) {
720 Variable
.Volatile
= (BOOLEAN
) (Variable
.Volatile
^ ((BOOLEAN
) 0x1));
721 if (Variable
.Volatile
) {
722 Variable
.StartPtr
= (VARIABLE_HEADER
*) ((UINTN
) (Global
->VolatileVariableBase
+ sizeof (VARIABLE_STORE_HEADER
)));
723 Variable
.EndPtr
= (VARIABLE_HEADER
*) GetEndPointer ((VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->VolatileVariableBase
));
725 Status
= EFI_NOT_FOUND
;
729 Variable
.CurrPtr
= Variable
.StartPtr
;
730 if (!IsValidVariableHeader (Variable
.CurrPtr
)) {
737 if (IsValidVariableHeader (Variable
.CurrPtr
) && Variable
.CurrPtr
->State
== VAR_ADDED
) {
738 if (!(EfiAtRuntime () && !(Variable
.CurrPtr
->Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
))) {
739 VarNameSize
= Variable
.CurrPtr
->NameSize
;
740 if (VarNameSize
<= *VariableNameSize
) {
743 GET_VARIABLE_NAME_PTR (Variable
.CurrPtr
),
748 &Variable
.CurrPtr
->VendorGuid
,
751 Status
= EFI_SUCCESS
;
753 Status
= EFI_BUFFER_TOO_SMALL
;
756 *VariableNameSize
= VarNameSize
;
761 Variable
.CurrPtr
= GetNextVariablePtr (Variable
.CurrPtr
);
765 ReleaseLockOnlyAtBootTime (&Global
->VariableServicesLock
);
772 IN CHAR16
*VariableName
,
773 IN EFI_GUID
*VendorGuid
,
774 IN UINT32 Attributes
,
777 IN VARIABLE_GLOBAL
*Global
,
778 IN UINTN
*VolatileOffset
,
779 IN UINTN
*NonVolatileOffset
,
786 This code sets variable in storage blocks (Volatile or Non-Volatile)
790 VariableName Name of Variable to be found
791 VendorGuid Variable vendor GUID
792 Attributes Attribute value of the variable found
793 DataSize Size of Data found. If size is less than the
794 data, this value contains the required size.
796 Global Pointer to VARIABLE_GLOBAL structure
797 VolatileOffset The offset of last volatile variable
798 NonVolatileOffset The offset of last non-volatile variable
799 Instance Instance of the Firmware Volume.
804 EFI_INVALID_PARAMETER - Invalid parameter
805 EFI_SUCCESS - Set successfully
806 EFI_OUT_OF_RESOURCES - Resource not enough to set variable
807 EFI_NOT_FOUND - Not found
811 VARIABLE_POINTER_TRACK Variable
;
813 VARIABLE_HEADER
*NextVariable
;
823 if (VariableName
== NULL
|| VariableName
[0] == 0 || VendorGuid
== NULL
) {
824 return EFI_INVALID_PARAMETER
;
827 Status
= FindVariable (VariableName
, VendorGuid
, &Variable
, Global
);
829 if (Status
== EFI_INVALID_PARAMETER
) {
831 } else if (!EFI_ERROR (Status
) && Variable
.Volatile
&& EfiAtRuntime()) {
833 // If EfiAtRuntime and the variable is Volatile and Runtime Access,
834 // the volatile is ReadOnly, and SetVariable should be aborted and
835 // return EFI_WRITE_PROTECTED.
837 Status
= EFI_WRITE_PROTECTED
;
839 } else if (sizeof (VARIABLE_HEADER
) + StrSize (VariableName
) + DataSize
> MAX_VARIABLE_SIZE
) {
841 // The size of the VariableName, including the Unicode Null in bytes plus
842 // the DataSize is limited to maximum size of MAX_VARIABLE_SIZE (1024) bytes.
844 Status
= EFI_INVALID_PARAMETER
;
846 } else if (Attributes
== EFI_VARIABLE_NON_VOLATILE
) {
848 // Make sure not only EFI_VARIABLE_NON_VOLATILE is set
850 Status
= EFI_INVALID_PARAMETER
;
852 } else if ((Attributes
& (EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
)) ==
853 EFI_VARIABLE_RUNTIME_ACCESS
) {
855 // Make sure if runtime bit is set, boot service bit is set also
857 Status
= EFI_INVALID_PARAMETER
;
859 } else if (EfiAtRuntime () && Attributes
&& !(Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
)) {
861 // Runtime but Attribute is not Runtime
863 Status
= EFI_INVALID_PARAMETER
;
865 } else if (EfiAtRuntime () && Attributes
&& !(Attributes
& EFI_VARIABLE_NON_VOLATILE
)) {
867 // Cannot set volatile variable in Runtime
869 Status
= EFI_INVALID_PARAMETER
;
871 } else if (DataSize
== 0 || (Attributes
& (EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
)) == 0) {
873 // Setting a data variable with no access, or zero DataSize attributes
874 // specified causes it to be deleted.
876 if (!EFI_ERROR (Status
)) {
877 State
= Variable
.CurrPtr
->State
;
878 State
&= VAR_DELETED
;
880 Status
= UpdateVariableStore (
885 (UINTN
) &Variable
.CurrPtr
->State
,
889 if (EFI_ERROR (Status
)) {
893 Status
= EFI_SUCCESS
;
897 Status
= EFI_NOT_FOUND
;
900 if (!EFI_ERROR (Status
)) {
902 // If the variable is marked valid and the same data has been passed in
903 // then return to the caller immediately.
905 if (Variable
.CurrPtr
->DataSize
== DataSize
&&
906 !CompareMem (Data
, GetVariableDataPtr (Variable
.CurrPtr
), DataSize
)
908 Status
= EFI_SUCCESS
;
910 } else if (Variable
.CurrPtr
->State
== VAR_ADDED
) {
912 // Mark the old variable as in delete transition
914 State
= Variable
.CurrPtr
->State
;
915 State
&= VAR_IN_DELETED_TRANSITION
;
917 Status
= UpdateVariableStore (
922 (UINTN
) &Variable
.CurrPtr
->State
,
926 if (EFI_ERROR (Status
)) {
932 // Create a new variable and copy the data.
934 // Tricky part: Use scratch data area at the end of volatile variable store
935 // as a temporary storage.
937 NextVariable
= GetEndPointer ((VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->VolatileVariableBase
));
939 SetMem (NextVariable
, SCRATCH_SIZE
, 0xff);
941 NextVariable
->StartId
= VARIABLE_DATA
;
942 NextVariable
->Attributes
= Attributes
;
944 // NextVariable->State = VAR_ADDED;
946 NextVariable
->Reserved
= 0;
947 VarNameOffset
= sizeof (VARIABLE_HEADER
);
948 VarNameSize
= StrSize (VariableName
);
950 (UINT8
*) ((UINTN
) NextVariable
+ VarNameOffset
),
954 VarDataOffset
= VarNameOffset
+ VarNameSize
+ GET_PAD_SIZE (VarNameSize
);
956 (UINT8
*) ((UINTN
) NextVariable
+ VarDataOffset
),
960 CopyMem (&NextVariable
->VendorGuid
, VendorGuid
, sizeof (EFI_GUID
));
962 // There will be pad bytes after Data, the NextVariable->NameSize and
963 // NextVariable->DataSize should not include pad size so that variable
964 // service can get actual size in GetVariable
966 NextVariable
->NameSize
= (UINT32
)VarNameSize
;
967 NextVariable
->DataSize
= (UINT32
)DataSize
;
970 // The actual size of the variable that stores in storage should
973 VarSize
= VarDataOffset
+ DataSize
+ GET_PAD_SIZE (DataSize
);
974 if (Attributes
& EFI_VARIABLE_NON_VOLATILE
) {
975 if ((UINT32
) (VarSize
+*NonVolatileOffset
) >
976 ((VARIABLE_STORE_HEADER
*) ((UINTN
) (Global
->NonVolatileVariableBase
)))->Size
978 if (EfiAtRuntime ()) {
979 Status
= EFI_OUT_OF_RESOURCES
;
983 // Perform garbage collection & reclaim operation
985 Status
= Reclaim (Global
->NonVolatileVariableBase
, NonVolatileOffset
, FALSE
);
986 if (EFI_ERROR (Status
)) {
990 // If still no enough space, return out of resources
992 if ((UINT32
) (VarSize
+*NonVolatileOffset
) >
993 ((VARIABLE_STORE_HEADER
*) ((UINTN
) (Global
->NonVolatileVariableBase
)))->Size
995 Status
= EFI_OUT_OF_RESOURCES
;
1003 // 1. Write variable header
1004 // 2. Write variable data
1005 // 3. Set variable state to valid
1010 Status
= UpdateVariableStore (
1016 sizeof (VARIABLE_HEADER
),
1017 (UINT8
*) NextVariable
1020 if (EFI_ERROR (Status
)) {
1026 Status
= UpdateVariableStore (
1031 *NonVolatileOffset
+ sizeof (VARIABLE_HEADER
),
1032 (UINT32
) VarSize
- sizeof (VARIABLE_HEADER
),
1033 (UINT8
*) NextVariable
+ sizeof (VARIABLE_HEADER
)
1036 if (EFI_ERROR (Status
)) {
1042 NextVariable
->State
= VAR_ADDED
;
1043 Status
= UpdateVariableStore (
1049 sizeof (VARIABLE_HEADER
),
1050 (UINT8
*) NextVariable
1053 if (EFI_ERROR (Status
)) {
1057 *NonVolatileOffset
= *NonVolatileOffset
+ VarSize
;
1060 if (EfiAtRuntime ()) {
1061 Status
= EFI_INVALID_PARAMETER
;
1065 if ((UINT32
) (VarSize
+*VolatileOffset
) >
1066 ((VARIABLE_STORE_HEADER
*) ((UINTN
) (Global
->VolatileVariableBase
)))->Size
1069 // Perform garbage collection & reclaim operation
1071 Status
= Reclaim (Global
->VolatileVariableBase
, VolatileOffset
, TRUE
);
1072 if (EFI_ERROR (Status
)) {
1076 // If still no enough space, return out of resources
1078 if ((UINT32
) (VarSize
+*VolatileOffset
) >
1079 ((VARIABLE_STORE_HEADER
*) ((UINTN
) (Global
->VolatileVariableBase
)))->Size
1081 Status
= EFI_OUT_OF_RESOURCES
;
1088 NextVariable
->State
= VAR_ADDED
;
1089 Status
= UpdateVariableStore (
1096 (UINT8
*) NextVariable
1099 if (EFI_ERROR (Status
)) {
1103 *VolatileOffset
= *VolatileOffset
+ VarSize
;
1106 // Mark the old variable as deleted
1108 if (!Reclaimed
&& !EFI_ERROR (Status
) && Variable
.CurrPtr
!= NULL
) {
1109 State
= Variable
.CurrPtr
->State
;
1110 State
&= VAR_DELETED
;
1112 Status
= UpdateVariableStore (
1117 (UINTN
) &Variable
.CurrPtr
->State
,
1122 if (EFI_ERROR (Status
)) {
1128 Status
= EFI_SUCCESS
;
1130 ReleaseLockOnlyAtBootTime (&Global
->VariableServicesLock
);
1137 IN UINT32 Attributes
,
1138 OUT UINT64
*MaximumVariableStorageSize
,
1139 OUT UINT64
*RemainingVariableStorageSize
,
1140 OUT UINT64
*MaximumVariableSize
,
1141 IN VARIABLE_GLOBAL
*Global
,
1146 Routine Description:
1148 This code returns information about the EFI variables.
1152 Attributes Attributes bitmask to specify the type of variables
1153 on which to return information.
1154 MaximumVariableStorageSize Pointer to the maximum size of the storage space available
1155 for the EFI variables associated with the attributes specified.
1156 RemainingVariableStorageSize Pointer to the remaining size of the storage space available
1157 for the EFI variables associated with the attributes specified.
1158 MaximumVariableSize Pointer to the maximum size of the individual EFI variables
1159 associated with the attributes specified.
1160 Global Pointer to VARIABLE_GLOBAL structure.
1161 Instance Instance of the Firmware Volume.
1166 EFI_INVALID_PARAMETER - An invalid combination of attribute bits was supplied.
1167 EFI_SUCCESS - Query successfully.
1168 EFI_UNSUPPORTED - The attribute is not supported on this platform.
1172 VARIABLE_HEADER
*Variable
;
1173 VARIABLE_HEADER
*NextVariable
;
1174 UINT64 VariableSize
;
1175 VARIABLE_STORE_HEADER
*VariableStoreHeader
;
1177 if(MaximumVariableStorageSize
== NULL
|| RemainingVariableStorageSize
== NULL
|| MaximumVariableSize
== NULL
) {
1178 return EFI_INVALID_PARAMETER
;
1181 if((Attributes
& (EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
)) == 0) {
1183 // Make sure the Attributes combination is supported by the platform.
1185 return EFI_UNSUPPORTED
;
1186 } else if ((Attributes
& (EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
)) == EFI_VARIABLE_RUNTIME_ACCESS
) {
1188 // Make sure if runtime bit is set, boot service bit is set also.
1190 return EFI_INVALID_PARAMETER
;
1191 } else if (EfiAtRuntime () && !(Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
)) {
1193 // Make sure RT Attribute is set if we are in Runtime phase.
1195 return EFI_INVALID_PARAMETER
;
1198 AcquireLockOnlyAtBootTime(&Global
->VariableServicesLock
);
1200 if((Attributes
& EFI_VARIABLE_NON_VOLATILE
) == 0) {
1202 // Query is Volatile related.
1204 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->VolatileVariableBase
);
1207 // Query is Non-Volatile related.
1209 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->NonVolatileVariableBase
);
1213 // Now let's fill *MaximumVariableStorageSize *RemainingVariableStorageSize
1214 // with the storage size (excluding the storage header size).
1216 *MaximumVariableStorageSize
= VariableStoreHeader
->Size
- sizeof (VARIABLE_STORE_HEADER
);
1217 *RemainingVariableStorageSize
= VariableStoreHeader
->Size
- sizeof (VARIABLE_STORE_HEADER
);
1220 // Let *MaximumVariableSize be MAX_VARIABLE_SIZE.
1222 *MaximumVariableSize
= MAX_VARIABLE_SIZE
;
1225 // Point to the starting address of the variables.
1227 Variable
= (VARIABLE_HEADER
*) (VariableStoreHeader
+ 1);
1230 // Now walk through the related variable store.
1232 while (IsValidVariableHeader (Variable
) && (Variable
< GetEndPointer (VariableStoreHeader
))) {
1233 NextVariable
= GetNextVariablePtr (Variable
);
1234 VariableSize
= (UINT64
) (UINTN
) NextVariable
- (UINT64
) (UINTN
) Variable
;
1236 if (EfiAtRuntime ()) {
1238 // we don't take the state of the variables in mind
1239 // when calculating RemainingVariableStorageSize,
1240 // since the space occupied by variables not marked with
1241 // VAR_ADDED is not allowed to be reclaimed in Runtime.
1243 *RemainingVariableStorageSize
-= VariableSize
;
1246 // Only care about Variables with State VAR_ADDED,because
1247 // the space not marked as VAR_ADDED is reclaimable now.
1249 if (Variable
->State
== VAR_ADDED
) {
1250 *RemainingVariableStorageSize
-= VariableSize
;
1255 // Go to the next one
1257 Variable
= NextVariable
;
1260 ReleaseLockOnlyAtBootTime (&Global
->VariableServicesLock
);
1266 VariableCommonInitialize (
1267 IN EFI_HANDLE ImageHandle
,
1268 IN EFI_SYSTEM_TABLE
*SystemTable
1272 Routine Description:
1273 This function does common initialization for variable services
1277 ImageHandle - The firmware allocated handle for the EFI image.
1278 SystemTable - A pointer to the EFI System Table.
1284 EFI_NOT_FOUND - Variable store area not found.
1285 EFI_UNSUPPORTED - Currently only one non-volatile variable store is supported.
1286 EFI_SUCCESS - Variable services successfully initialized.
1291 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
1293 VARIABLE_STORE_HEADER
*VolatileVariableStore
;
1294 VARIABLE_STORE_HEADER
*VariableStoreHeader
;
1295 VARIABLE_HEADER
*NextVariable
;
1297 EFI_PHYSICAL_ADDRESS FvVolHdr
;
1299 UINT64 TempVariableStoreHeader
;
1301 EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor
;
1302 EFI_FLASH_SUBAREA_ENTRY VariableStoreEntry
;
1308 mVariableModuleGlobal
= AllocateRuntimePool (sizeof (ESAL_VARIABLE_GLOBAL
));
1309 if (mVariableModuleGlobal
== NULL
) {
1310 return EFI_OUT_OF_RESOURCES
;
1313 EfiInitializeLock(&mVariableModuleGlobal
->VariableGlobal
[Physical
].VariableServicesLock
, TPL_NOTIFY
);
1316 // Allocate memory for volatile variable store
1318 VolatileVariableStore
= AllocateRuntimePool (VARIABLE_STORE_SIZE
+ SCRATCH_SIZE
);
1319 if (VolatileVariableStore
== NULL
) {
1320 FreePool (mVariableModuleGlobal
);
1321 return EFI_OUT_OF_RESOURCES
;
1324 SetMem (VolatileVariableStore
, VARIABLE_STORE_SIZE
+ SCRATCH_SIZE
, 0xff);
1327 // Variable Specific Data
1329 mVariableModuleGlobal
->VariableGlobal
[Physical
].VolatileVariableBase
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) VolatileVariableStore
;
1330 mVariableModuleGlobal
->VolatileLastVariableOffset
= sizeof (VARIABLE_STORE_HEADER
);
1332 VolatileVariableStore
->Signature
= VARIABLE_STORE_SIGNATURE
;
1333 VolatileVariableStore
->Size
= VARIABLE_STORE_SIZE
;
1334 VolatileVariableStore
->Format
= VARIABLE_STORE_FORMATTED
;
1335 VolatileVariableStore
->State
= VARIABLE_STORE_HEALTHY
;
1336 VolatileVariableStore
->Reserved
= 0;
1337 VolatileVariableStore
->Reserved1
= 0;
1340 // Get non volatile varaible store
1343 TempVariableStoreHeader
= (UINT64
) PcdGet32 (PcdFlashNvStorageVariableBase
);
1344 VariableStoreEntry
.Base
= TempVariableStoreHeader
+ \
1345 (((EFI_FIRMWARE_VOLUME_HEADER
*) (UINTN
) (TempVariableStoreHeader
)) -> HeaderLength
);
1346 VariableStoreEntry
.Length
= (UINT64
) PcdGet32 (PcdFlashNvStorageVariableSize
) - \
1347 (((EFI_FIRMWARE_VOLUME_HEADER
*) (UINTN
) (TempVariableStoreHeader
)) -> HeaderLength
);
1349 // Mark the variable storage region of the FLASH as RUNTIME
1351 BaseAddress
= VariableStoreEntry
.Base
& (~EFI_PAGE_MASK
);
1352 Length
= VariableStoreEntry
.Length
+ (VariableStoreEntry
.Base
- BaseAddress
);
1353 Length
= (Length
+ EFI_PAGE_SIZE
- 1) & (~EFI_PAGE_MASK
);
1355 Status
= gDS
->GetMemorySpaceDescriptor (BaseAddress
, &GcdDescriptor
);
1356 if (EFI_ERROR (Status
)) {
1357 FreePool (mVariableModuleGlobal
);
1358 FreePool (VolatileVariableStore
);
1359 return EFI_UNSUPPORTED
;
1362 Status
= gDS
->SetMemorySpaceAttributes (
1365 GcdDescriptor
.Attributes
| EFI_MEMORY_RUNTIME
1367 if (EFI_ERROR (Status
)) {
1368 FreePool (mVariableModuleGlobal
);
1369 FreePool (VolatileVariableStore
);
1370 return EFI_UNSUPPORTED
;
1373 // Get address of non volatile variable store base
1375 mVariableModuleGlobal
->VariableGlobal
[Physical
].NonVolatileVariableBase
= VariableStoreEntry
.Base
;
1381 // Find the Correct Instance of the FV Block Service.
1384 CurrPtr
= (CHAR8
*) ((UINTN
) mVariableModuleGlobal
->VariableGlobal
[Physical
].NonVolatileVariableBase
);
1385 while (EfiFvbGetPhysicalAddress (Instance
, &FvVolHdr
) == EFI_SUCCESS
) {
1386 FwVolHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) ((UINTN
) FvVolHdr
);
1387 if (CurrPtr
>= (CHAR8
*) FwVolHeader
&& CurrPtr
< (((CHAR8
*) FwVolHeader
) + FwVolHeader
->FvLength
)) {
1388 mVariableModuleGlobal
->FvbInstance
= Instance
;
1395 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) CurrPtr
;
1396 if (GetVariableStoreStatus (VariableStoreHeader
) == EfiValid
) {
1397 if (~VariableStoreHeader
->Size
== 0) {
1398 Status
= UpdateVariableStore (
1399 &mVariableModuleGlobal
->VariableGlobal
[Physical
],
1402 mVariableModuleGlobal
->FvbInstance
,
1403 (UINTN
) &VariableStoreHeader
->Size
,
1405 (UINT8
*) &VariableStoreEntry
.Length
1408 // As Variables are stored in NV storage, which are slow devices,such as flash.
1409 // Variable operation may skip checking variable program result to improve performance,
1410 // We can assume Variable program is OK through some check point.
1411 // Variable Store Size Setting should be the first Variable write operation,
1412 // We can assume all Read/Write is OK if we can set Variable store size successfully.
1413 // If write fail, we will assert here
1415 ASSERT(VariableStoreHeader
->Size
== VariableStoreEntry
.Length
);
1417 if (EFI_ERROR (Status
)) {
1422 mVariableModuleGlobal
->VariableGlobal
[Physical
].NonVolatileVariableBase
= (EFI_PHYSICAL_ADDRESS
) ((UINTN
) CurrPtr
);
1424 // Parse non-volatile variable data and get last variable offset
1426 NextVariable
= (VARIABLE_HEADER
*) (CurrPtr
+ sizeof (VARIABLE_STORE_HEADER
));
1427 Status
= EFI_SUCCESS
;
1429 while (IsValidVariableHeader (NextVariable
)) {
1430 NextVariable
= GetNextVariablePtr (NextVariable
);
1433 mVariableModuleGlobal
->NonVolatileLastVariableOffset
= (UINTN
) NextVariable
- (UINTN
) CurrPtr
;
1436 // Check if the free area is blow a threshold
1438 if ((((VARIABLE_STORE_HEADER
*)((UINTN
) CurrPtr
))->Size
- mVariableModuleGlobal
->NonVolatileLastVariableOffset
) < VARIABLE_RECLAIM_THRESHOLD
) {
1440 mVariableModuleGlobal
->VariableGlobal
[Physical
].NonVolatileVariableBase
,
1441 &mVariableModuleGlobal
->NonVolatileLastVariableOffset
,
1446 if (EFI_ERROR (Status
)) {
1447 FreePool (mVariableModuleGlobal
);
1448 FreePool (VolatileVariableStore
);
1453 // Check if the free area is really free.
1455 for (Index
= mVariableModuleGlobal
->NonVolatileLastVariableOffset
; Index
< VariableStoreHeader
->Size
; Index
++) {
1456 Data
= ((UINT8
*) (UINTN
) mVariableModuleGlobal
->VariableGlobal
[Physical
].NonVolatileVariableBase
)[Index
];
1459 // There must be something wrong in variable store, do reclaim operation.
1462 mVariableModuleGlobal
->VariableGlobal
[Physical
].NonVolatileVariableBase
,
1463 &mVariableModuleGlobal
->NonVolatileLastVariableOffset
,
1471 if (EFI_ERROR (Status
)) {
1472 FreePool (mVariableModuleGlobal
);
1473 FreePool (VolatileVariableStore
);