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.
37 AcquireLockOnlyAtBootTime (
41 if (!EfiAtRuntime ()) {
42 EfiAcquireLock (Lock
);
47 // This is a temperary function which will be removed
48 // when EfiAcquireLock in UefiLib can handle the
49 // the call in UEFI Runtimer driver in RT phase.
53 ReleaseLockOnlyAtBootTime (
57 if (!EfiAtRuntime ()) {
58 EfiReleaseLock (Lock
);
65 IsValidVariableHeader (
66 IN VARIABLE_HEADER
*Variable
72 This code checks if variable header is valid or not.
75 Variable Pointer to the Variable Header.
78 TRUE Variable header is valid.
79 FALSE Variable header is not valid.
83 if (Variable
== NULL
||
84 Variable
->StartId
!= VARIABLE_DATA
||
85 (sizeof (VARIABLE_HEADER
) + Variable
->NameSize
+ Variable
->DataSize
) > MAX_VARIABLE_SIZE
97 IN VARIABLE_GLOBAL
*Global
,
99 IN BOOLEAN SetByIndex
,
101 IN UINTN DataPtrIndex
,
109 This function writes data to the FWH at the correct LBA even if the LBAs
114 Global Pointer to VARAIBLE_GLOBAL structure
115 Volatile If the Variable is Volatile or Non-Volatile
116 SetByIndex TRUE: Target pointer is given as index
117 FALSE: Target pointer is absolute
118 Instance Instance of FV Block services
119 DataPtrIndex Pointer to the Data from the end of VARIABLE_STORE_HEADER
121 DataSize Size of data to be written.
122 Buffer Pointer to the buffer from which data is written
130 EFI_FV_BLOCK_MAP_ENTRY
*PtrBlockMapEntry
;
138 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
139 VARIABLE_STORE_HEADER
*VolatileBase
;
140 EFI_PHYSICAL_ADDRESS FvVolHdr
;
141 EFI_PHYSICAL_ADDRESS DataPtr
;
145 DataPtr
= DataPtrIndex
;
148 // Check if the Data is Volatile
151 EfiFvbGetPhysicalAddress (Instance
, &FvVolHdr
);
152 FwVolHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) ((UINTN
) FvVolHdr
);
154 // Data Pointer should point to the actual Address where data is to be
158 DataPtr
+= Global
->NonVolatileVariableBase
;
161 if ((DataPtr
+ DataSize
) >= ((EFI_PHYSICAL_ADDRESS
) (UINTN
) ((UINT8
*) FwVolHeader
+ FwVolHeader
->FvLength
))) {
162 return EFI_INVALID_PARAMETER
;
166 // Data Pointer should point to the actual Address where data is to be
169 VolatileBase
= (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->VolatileVariableBase
);
171 DataPtr
+= Global
->VolatileVariableBase
;
174 if ((DataPtr
+ DataSize
) >= ((UINTN
) ((UINT8
*) VolatileBase
+ VolatileBase
->Size
))) {
175 return EFI_INVALID_PARAMETER
;
179 // If Volatile Variable just do a simple mem copy.
182 CopyMem ((UINT8
*) ((UINTN
) DataPtr
), Buffer
, DataSize
);
186 // If we are here we are dealing with Non-Volatile Variables
188 LinearOffset
= (UINTN
) FwVolHeader
;
189 CurrWritePtr
= (UINTN
) DataPtr
;
190 CurrWriteSize
= DataSize
;
194 if (CurrWritePtr
< LinearOffset
) {
195 return EFI_INVALID_PARAMETER
;
198 for (PtrBlockMapEntry
= FwVolHeader
->FvBlockMap
; PtrBlockMapEntry
->NumBlocks
!= 0; PtrBlockMapEntry
++) {
199 for (BlockIndex2
= 0; BlockIndex2
< PtrBlockMapEntry
->NumBlocks
; BlockIndex2
++) {
201 // Check to see if the Variable Writes are spanning through multiple
204 if ((CurrWritePtr
>= LinearOffset
) && (CurrWritePtr
< LinearOffset
+ PtrBlockMapEntry
->BlockLength
)) {
205 if ((CurrWritePtr
+ CurrWriteSize
) <= (LinearOffset
+ PtrBlockMapEntry
->BlockLength
)) {
206 Status
= EfiFvbWriteBlock (
209 (UINTN
) (CurrWritePtr
- LinearOffset
),
213 if (EFI_ERROR (Status
)) {
217 Size
= (UINT32
) (LinearOffset
+ PtrBlockMapEntry
->BlockLength
- CurrWritePtr
);
218 Status
= EfiFvbWriteBlock (
221 (UINTN
) (CurrWritePtr
- LinearOffset
),
225 if (EFI_ERROR (Status
)) {
229 CurrWritePtr
= LinearOffset
+ PtrBlockMapEntry
->BlockLength
;
230 CurrBuffer
= CurrBuffer
+ Size
;
231 CurrWriteSize
= CurrWriteSize
- Size
;
235 LinearOffset
+= PtrBlockMapEntry
->BlockLength
;
244 VARIABLE_STORE_STATUS
246 GetVariableStoreStatus (
247 IN VARIABLE_STORE_HEADER
*VarStoreHeader
253 This code gets the current status of Variable Store.
257 VarStoreHeader Pointer to the Variable Store Header.
261 EfiRaw Variable store status is raw
262 EfiValid Variable store status is valid
263 EfiInvalid Variable store status is invalid
267 if (VarStoreHeader
->Signature
== VARIABLE_STORE_SIGNATURE
&&
268 VarStoreHeader
->Format
== VARIABLE_STORE_FORMATTED
&&
269 VarStoreHeader
->State
== VARIABLE_STORE_HEALTHY
273 } else if (VarStoreHeader
->Signature
== 0xffffffff &&
274 VarStoreHeader
->Size
== 0xffffffff &&
275 VarStoreHeader
->Format
== 0xff &&
276 VarStoreHeader
->State
== 0xff
289 IN VARIABLE_HEADER
*Variable
295 This code gets the pointer to the variable data.
299 Variable Pointer to the Variable Header.
303 UINT8* Pointer to Variable Data
308 // Be careful about pad size for alignment
310 return (UINT8
*) ((UINTN
) GET_VARIABLE_NAME_PTR (Variable
) + Variable
->NameSize
+ GET_PAD_SIZE (Variable
->NameSize
));
317 IN VARIABLE_HEADER
*Variable
323 This code gets the pointer to the next variable header.
327 Variable Pointer to the Variable Header.
331 VARIABLE_HEADER* Pointer to next variable header.
335 if (!IsValidVariableHeader (Variable
)) {
339 // Be careful about pad size for alignment
341 return (VARIABLE_HEADER
*) ((UINTN
) GetVariableDataPtr (Variable
) + Variable
->DataSize
+ GET_PAD_SIZE (Variable
->DataSize
));
348 IN VARIABLE_STORE_HEADER
*VarStoreHeader
354 This code gets the pointer to the last variable memory pointer byte
358 VarStoreHeader Pointer to the Variable Store Header.
362 VARIABLE_HEADER* Pointer to last unavailable Variable Header
367 // The end of variable store
369 return (VARIABLE_HEADER
*) ((UINTN
) VarStoreHeader
+ VarStoreHeader
->Size
);
376 IN EFI_PHYSICAL_ADDRESS VariableBase
,
377 OUT UINTN
*LastVariableOffset
,
378 IN BOOLEAN IsVolatile
384 Variable store garbage collection and reclaim operation
388 VariableBase Base address of variable store
389 LastVariableOffset Offset of last variable
390 IsVolatile The variable store is volatile or not,
391 if it is non-volatile, need FTW
399 VARIABLE_HEADER
*Variable
;
400 VARIABLE_HEADER
*NextVariable
;
401 VARIABLE_STORE_HEADER
*VariableStoreHeader
;
403 UINTN ValidBufferSize
;
408 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) ((UINTN
) VariableBase
);
411 // Start Pointers for the variable.
413 Variable
= (VARIABLE_HEADER
*) (VariableStoreHeader
+ 1);
415 ValidBufferSize
= sizeof (VARIABLE_STORE_HEADER
);
417 while (IsValidVariableHeader (Variable
)) {
418 NextVariable
= GetNextVariablePtr (Variable
);
419 if (Variable
->State
== VAR_ADDED
) {
420 VariableSize
= (UINTN
) NextVariable
- (UINTN
) Variable
;
421 ValidBufferSize
+= VariableSize
;
424 Variable
= NextVariable
;
427 ValidBuffer
= AllocatePool (ValidBufferSize
);
428 if (ValidBuffer
== NULL
) {
429 return EFI_OUT_OF_RESOURCES
;
432 SetMem (ValidBuffer
, ValidBufferSize
, 0xff);
434 CurrPtr
= ValidBuffer
;
437 // Copy variable store header
439 CopyMem (CurrPtr
, VariableStoreHeader
, sizeof (VARIABLE_STORE_HEADER
));
440 CurrPtr
+= sizeof (VARIABLE_STORE_HEADER
);
443 // Start Pointers for the variable.
445 Variable
= (VARIABLE_HEADER
*) (VariableStoreHeader
+ 1);
447 while (IsValidVariableHeader (Variable
)) {
448 NextVariable
= GetNextVariablePtr (Variable
);
449 if (Variable
->State
== VAR_ADDED
) {
450 VariableSize
= (UINTN
) NextVariable
- (UINTN
) Variable
;
451 CopyMem (CurrPtr
, (UINT8
*) Variable
, VariableSize
);
452 CurrPtr
+= VariableSize
;
455 Variable
= NextVariable
;
460 // If volatile variable store, just copy valid buffer
462 SetMem ((UINT8
*) (UINTN
) VariableBase
, VariableStoreHeader
->Size
, 0xff);
463 CopyMem ((UINT8
*) (UINTN
) VariableBase
, ValidBuffer
, ValidBufferSize
);
464 *LastVariableOffset
= ValidBufferSize
;
465 Status
= EFI_SUCCESS
;
468 // If non-volatile variable store, perform FTW here.
470 Status
= FtwVariableSpace (
475 if (!EFI_ERROR (Status
)) {
476 *LastVariableOffset
= ValidBufferSize
;
480 FreePool (ValidBuffer
);
482 if (EFI_ERROR (Status
)) {
483 *LastVariableOffset
= 0;
493 IN CHAR16
*VariableName
,
494 IN EFI_GUID
*VendorGuid
,
495 OUT VARIABLE_POINTER_TRACK
*PtrTrack
,
496 IN VARIABLE_GLOBAL
*Global
502 This code finds variable in storage blocks (Volatile or Non-Volatile)
506 VariableName Name of the variable to be found
507 VendorGuid Vendor GUID to be found.
508 PtrTrack Variable Track Pointer structure that contains
509 Variable Information.
510 Contains the pointer of Variable header.
511 Global VARIABLE_GLOBAL pointer
519 VARIABLE_HEADER
*Variable
[2];
520 VARIABLE_STORE_HEADER
*VariableStoreHeader
[2];
524 // We aquire the lock at the entry of FindVariable as GetVariable, GetNextVariableName
525 // SetVariable all call FindVariable at entry point. Please move "Aquire Lock" to
526 // the correct places if this assumption does not hold TRUE anymore.
528 AcquireLockOnlyAtBootTime(&Global
->VariableServicesLock
);
531 // 0: Non-Volatile, 1: Volatile
533 VariableStoreHeader
[0] = (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->NonVolatileVariableBase
);
534 VariableStoreHeader
[1] = (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->VolatileVariableBase
);
537 // Start Pointers for the variable.
538 // Actual Data Pointer where data can be written.
540 Variable
[0] = (VARIABLE_HEADER
*) (VariableStoreHeader
[0] + 1);
541 Variable
[1] = (VARIABLE_HEADER
*) (VariableStoreHeader
[1] + 1);
543 if (VariableName
[0] != 0 && VendorGuid
== NULL
) {
544 return EFI_INVALID_PARAMETER
;
547 // Find the variable by walk through non-volatile and volatile variable store
549 for (Index
= 0; Index
< 2; Index
++) {
550 PtrTrack
->StartPtr
= (VARIABLE_HEADER
*) (VariableStoreHeader
[Index
] + 1);
551 PtrTrack
->EndPtr
= GetEndPointer (VariableStoreHeader
[Index
]);
553 while (IsValidVariableHeader (Variable
[Index
]) && (Variable
[Index
] <= GetEndPointer (VariableStoreHeader
[Index
]))) {
554 if (Variable
[Index
]->State
== VAR_ADDED
) {
555 if (!(EfiAtRuntime () && !(Variable
[Index
]->Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
))) {
556 if (VariableName
[0] == 0) {
557 PtrTrack
->CurrPtr
= Variable
[Index
];
558 PtrTrack
->Volatile
= (BOOLEAN
) Index
;
561 if (CompareGuid (VendorGuid
, &Variable
[Index
]->VendorGuid
)) {
562 if (!CompareMem (VariableName
, GET_VARIABLE_NAME_PTR (Variable
[Index
]), Variable
[Index
]->NameSize
)) {
563 PtrTrack
->CurrPtr
= Variable
[Index
];
564 PtrTrack
->Volatile
= (BOOLEAN
) Index
;
572 Variable
[Index
] = GetNextVariablePtr (Variable
[Index
]);
581 PtrTrack
->CurrPtr
= NULL
;
582 return EFI_NOT_FOUND
;
588 IN CHAR16
*VariableName
,
589 IN EFI_GUID
* VendorGuid
,
590 OUT UINT32
*Attributes OPTIONAL
,
591 IN OUT UINTN
*DataSize
,
593 IN VARIABLE_GLOBAL
* Global
,
600 This code finds variable in storage blocks (Volatile or Non-Volatile)
604 VariableName Name of Variable to be found
605 VendorGuid Variable vendor GUID
606 Attributes OPTIONAL Attribute value of the variable found
607 DataSize Size of Data found. If size is less than the
608 data, this value contains the required size.
610 Global Pointer to VARIABLE_GLOBAL structure
611 Instance Instance of the Firmware Volume.
619 VARIABLE_POINTER_TRACK Variable
;
623 if (VariableName
== NULL
|| VendorGuid
== NULL
|| DataSize
== NULL
) {
624 return EFI_INVALID_PARAMETER
;
627 // Find existing variable
629 Status
= FindVariable (VariableName
, VendorGuid
, &Variable
, Global
);
631 if (Variable
.CurrPtr
== NULL
|| EFI_ERROR (Status
)) {
637 VarDataSize
= Variable
.CurrPtr
->DataSize
;
638 if (*DataSize
>= VarDataSize
) {
640 Status
= EFI_INVALID_PARAMETER
;
644 CopyMem (Data
, GetVariableDataPtr (Variable
.CurrPtr
), VarDataSize
);
645 if (Attributes
!= NULL
) {
646 *Attributes
= Variable
.CurrPtr
->Attributes
;
649 *DataSize
= VarDataSize
;
650 Status
= EFI_SUCCESS
;
653 *DataSize
= VarDataSize
;
654 Status
= EFI_BUFFER_TOO_SMALL
;
659 ReleaseLockOnlyAtBootTime (&Global
->VariableServicesLock
);
665 GetNextVariableName (
666 IN OUT UINTN
*VariableNameSize
,
667 IN OUT CHAR16
*VariableName
,
668 IN OUT EFI_GUID
*VendorGuid
,
669 IN VARIABLE_GLOBAL
*Global
,
676 This code Finds the Next available variable
680 VariableNameSize Size of the variable
681 VariableName Pointer to variable name
682 VendorGuid Variable Vendor Guid
683 Global VARIABLE_GLOBAL structure pointer.
692 VARIABLE_POINTER_TRACK Variable
;
696 if (VariableNameSize
== NULL
|| VariableName
== NULL
|| VendorGuid
== NULL
) {
697 return EFI_INVALID_PARAMETER
;
700 Status
= FindVariable (VariableName
, VendorGuid
, &Variable
, Global
);
702 if (Variable
.CurrPtr
== NULL
|| EFI_ERROR (Status
)) {
706 if (VariableName
[0] != 0) {
708 // If variable name is not NULL, get next variable
710 Variable
.CurrPtr
= GetNextVariablePtr (Variable
.CurrPtr
);
715 // If both volatile and non-volatile variable store are parsed,
718 if (Variable
.CurrPtr
>= Variable
.EndPtr
|| Variable
.CurrPtr
== NULL
) {
719 Variable
.Volatile
= (BOOLEAN
) (Variable
.Volatile
^ ((BOOLEAN
) 0x1));
720 if (Variable
.Volatile
) {
721 Variable
.StartPtr
= (VARIABLE_HEADER
*) ((UINTN
) (Global
->VolatileVariableBase
+ sizeof (VARIABLE_STORE_HEADER
)));
722 Variable
.EndPtr
= (VARIABLE_HEADER
*) GetEndPointer ((VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->VolatileVariableBase
));
724 Status
= EFI_NOT_FOUND
;
728 Variable
.CurrPtr
= Variable
.StartPtr
;
729 if (!IsValidVariableHeader (Variable
.CurrPtr
)) {
736 if (IsValidVariableHeader (Variable
.CurrPtr
) && Variable
.CurrPtr
->State
== VAR_ADDED
) {
737 if (!(EfiAtRuntime () && !(Variable
.CurrPtr
->Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
))) {
738 VarNameSize
= Variable
.CurrPtr
->NameSize
;
739 if (VarNameSize
<= *VariableNameSize
) {
742 GET_VARIABLE_NAME_PTR (Variable
.CurrPtr
),
747 &Variable
.CurrPtr
->VendorGuid
,
750 Status
= EFI_SUCCESS
;
752 Status
= EFI_BUFFER_TOO_SMALL
;
755 *VariableNameSize
= VarNameSize
;
760 Variable
.CurrPtr
= GetNextVariablePtr (Variable
.CurrPtr
);
764 ReleaseLockOnlyAtBootTime (&Global
->VariableServicesLock
);
771 IN CHAR16
*VariableName
,
772 IN EFI_GUID
*VendorGuid
,
773 IN UINT32 Attributes
,
776 IN VARIABLE_GLOBAL
*Global
,
777 IN UINTN
*VolatileOffset
,
778 IN UINTN
*NonVolatileOffset
,
785 This code sets variable in storage blocks (Volatile or Non-Volatile)
789 VariableName Name of Variable to be found
790 VendorGuid Variable vendor GUID
791 Attributes Attribute value of the variable found
792 DataSize Size of Data found. If size is less than the
793 data, this value contains the required size.
795 Global Pointer to VARIABLE_GLOBAL structure
796 VolatileOffset The offset of last volatile variable
797 NonVolatileOffset The offset of last non-volatile variable
798 Instance Instance of the Firmware Volume.
803 EFI_INVALID_PARAMETER - Invalid parameter
804 EFI_SUCCESS - Set successfully
805 EFI_OUT_OF_RESOURCES - Resource not enough to set variable
806 EFI_NOT_FOUND - Not found
810 VARIABLE_POINTER_TRACK Variable
;
812 VARIABLE_HEADER
*NextVariable
;
822 if (VariableName
== NULL
|| VariableName
[0] == 0 || VendorGuid
== NULL
) {
823 return EFI_INVALID_PARAMETER
;
826 Status
= FindVariable (VariableName
, VendorGuid
, &Variable
, Global
);
828 if (Status
== EFI_INVALID_PARAMETER
) {
830 } else if (!EFI_ERROR (Status
) && Variable
.Volatile
&& EfiAtRuntime()) {
832 // If EfiAtRuntime and the variable is Volatile and Runtime Access,
833 // the volatile is ReadOnly, and SetVariable should be aborted and
834 // return EFI_WRITE_PROTECTED.
836 Status
= EFI_WRITE_PROTECTED
;
838 } else if (sizeof (VARIABLE_HEADER
) + StrSize (VariableName
) + DataSize
> MAX_VARIABLE_SIZE
) {
840 // The size of the VariableName, including the Unicode Null in bytes plus
841 // the DataSize is limited to maximum size of MAX_VARIABLE_SIZE (1024) bytes.
843 Status
= EFI_INVALID_PARAMETER
;
845 } else if (Attributes
== EFI_VARIABLE_NON_VOLATILE
) {
847 // Make sure not only EFI_VARIABLE_NON_VOLATILE is set
849 Status
= EFI_INVALID_PARAMETER
;
851 } else if ((Attributes
& (EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
)) ==
852 EFI_VARIABLE_RUNTIME_ACCESS
) {
854 // Make sure if runtime bit is set, boot service bit is set also
856 Status
= EFI_INVALID_PARAMETER
;
858 } else if (EfiAtRuntime () && Attributes
&& !(Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
)) {
860 // Runtime but Attribute is not Runtime
862 Status
= EFI_INVALID_PARAMETER
;
864 } else if (EfiAtRuntime () && Attributes
&& !(Attributes
& EFI_VARIABLE_NON_VOLATILE
)) {
866 // Cannot set volatile variable in Runtime
868 Status
= EFI_INVALID_PARAMETER
;
870 } else if (DataSize
== 0 || (Attributes
& (EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
)) == 0) {
872 // Setting a data variable with no access, or zero DataSize attributes
873 // specified causes it to be deleted.
875 if (!EFI_ERROR (Status
)) {
876 State
= Variable
.CurrPtr
->State
;
877 State
&= VAR_DELETED
;
879 Status
= UpdateVariableStore (
884 (UINTN
) &Variable
.CurrPtr
->State
,
888 if (EFI_ERROR (Status
)) {
892 Status
= EFI_SUCCESS
;
896 Status
= EFI_NOT_FOUND
;
899 if (!EFI_ERROR (Status
)) {
901 // If the variable is marked valid and the same data has been passed in
902 // then return to the caller immediately.
904 if (Variable
.CurrPtr
->DataSize
== DataSize
&&
905 !CompareMem (Data
, GetVariableDataPtr (Variable
.CurrPtr
), DataSize
)
907 Status
= EFI_SUCCESS
;
909 } else if (Variable
.CurrPtr
->State
== VAR_ADDED
) {
911 // Mark the old variable as in delete transition
913 State
= Variable
.CurrPtr
->State
;
914 State
&= VAR_IN_DELETED_TRANSITION
;
916 Status
= UpdateVariableStore (
921 (UINTN
) &Variable
.CurrPtr
->State
,
925 if (EFI_ERROR (Status
)) {
931 // Create a new variable and copy the data.
933 // Tricky part: Use scratch data area at the end of volatile variable store
934 // as a temporary storage.
936 NextVariable
= GetEndPointer ((VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->VolatileVariableBase
));
938 SetMem (NextVariable
, SCRATCH_SIZE
, 0xff);
940 NextVariable
->StartId
= VARIABLE_DATA
;
941 NextVariable
->Attributes
= Attributes
;
943 // NextVariable->State = VAR_ADDED;
945 NextVariable
->Reserved
= 0;
946 VarNameOffset
= sizeof (VARIABLE_HEADER
);
947 VarNameSize
= StrSize (VariableName
);
949 (UINT8
*) ((UINTN
) NextVariable
+ VarNameOffset
),
953 VarDataOffset
= VarNameOffset
+ VarNameSize
+ GET_PAD_SIZE (VarNameSize
);
955 (UINT8
*) ((UINTN
) NextVariable
+ VarDataOffset
),
959 CopyMem (&NextVariable
->VendorGuid
, VendorGuid
, sizeof (EFI_GUID
));
961 // There will be pad bytes after Data, the NextVariable->NameSize and
962 // NextVariable->DataSize should not include pad size so that variable
963 // service can get actual size in GetVariable
965 NextVariable
->NameSize
= (UINT32
)VarNameSize
;
966 NextVariable
->DataSize
= (UINT32
)DataSize
;
969 // The actual size of the variable that stores in storage should
972 VarSize
= VarDataOffset
+ DataSize
+ GET_PAD_SIZE (DataSize
);
973 if (Attributes
& EFI_VARIABLE_NON_VOLATILE
) {
974 if ((UINT32
) (VarSize
+*NonVolatileOffset
) >
975 ((VARIABLE_STORE_HEADER
*) ((UINTN
) (Global
->NonVolatileVariableBase
)))->Size
977 if (EfiAtRuntime ()) {
978 Status
= EFI_OUT_OF_RESOURCES
;
982 // Perform garbage collection & reclaim operation
984 Status
= Reclaim (Global
->NonVolatileVariableBase
, NonVolatileOffset
, FALSE
);
985 if (EFI_ERROR (Status
)) {
989 // If still no enough space, return out of resources
991 if ((UINT32
) (VarSize
+*NonVolatileOffset
) >
992 ((VARIABLE_STORE_HEADER
*) ((UINTN
) (Global
->NonVolatileVariableBase
)))->Size
994 Status
= EFI_OUT_OF_RESOURCES
;
1002 // 1. Write variable header
1003 // 2. Write variable data
1004 // 3. Set variable state to valid
1009 Status
= UpdateVariableStore (
1015 sizeof (VARIABLE_HEADER
),
1016 (UINT8
*) NextVariable
1019 if (EFI_ERROR (Status
)) {
1025 Status
= UpdateVariableStore (
1030 *NonVolatileOffset
+ sizeof (VARIABLE_HEADER
),
1031 (UINT32
) VarSize
- sizeof (VARIABLE_HEADER
),
1032 (UINT8
*) NextVariable
+ sizeof (VARIABLE_HEADER
)
1035 if (EFI_ERROR (Status
)) {
1041 NextVariable
->State
= VAR_ADDED
;
1042 Status
= UpdateVariableStore (
1048 sizeof (VARIABLE_HEADER
),
1049 (UINT8
*) NextVariable
1052 if (EFI_ERROR (Status
)) {
1056 *NonVolatileOffset
= *NonVolatileOffset
+ VarSize
;
1059 if (EfiAtRuntime ()) {
1060 Status
= EFI_INVALID_PARAMETER
;
1064 if ((UINT32
) (VarSize
+*VolatileOffset
) >
1065 ((VARIABLE_STORE_HEADER
*) ((UINTN
) (Global
->VolatileVariableBase
)))->Size
1068 // Perform garbage collection & reclaim operation
1070 Status
= Reclaim (Global
->VolatileVariableBase
, VolatileOffset
, TRUE
);
1071 if (EFI_ERROR (Status
)) {
1075 // If still no enough space, return out of resources
1077 if ((UINT32
) (VarSize
+*VolatileOffset
) >
1078 ((VARIABLE_STORE_HEADER
*) ((UINTN
) (Global
->VolatileVariableBase
)))->Size
1080 Status
= EFI_OUT_OF_RESOURCES
;
1087 NextVariable
->State
= VAR_ADDED
;
1088 Status
= UpdateVariableStore (
1095 (UINT8
*) NextVariable
1098 if (EFI_ERROR (Status
)) {
1102 *VolatileOffset
= *VolatileOffset
+ VarSize
;
1105 // Mark the old variable as deleted
1107 if (!Reclaimed
&& !EFI_ERROR (Status
) && Variable
.CurrPtr
!= NULL
) {
1108 State
= Variable
.CurrPtr
->State
;
1109 State
&= VAR_DELETED
;
1111 Status
= UpdateVariableStore (
1116 (UINTN
) &Variable
.CurrPtr
->State
,
1121 if (EFI_ERROR (Status
)) {
1127 Status
= EFI_SUCCESS
;
1129 ReleaseLockOnlyAtBootTime (&Global
->VariableServicesLock
);
1136 IN UINT32 Attributes
,
1137 OUT UINT64
*MaximumVariableStorageSize
,
1138 OUT UINT64
*RemainingVariableStorageSize
,
1139 OUT UINT64
*MaximumVariableSize
,
1140 IN VARIABLE_GLOBAL
*Global
,
1145 Routine Description:
1147 This code returns information about the EFI variables.
1151 Attributes Attributes bitmask to specify the type of variables
1152 on which to return information.
1153 MaximumVariableStorageSize Pointer to the maximum size of the storage space available
1154 for the EFI variables associated with the attributes specified.
1155 RemainingVariableStorageSize Pointer to the remaining size of the storage space available
1156 for the EFI variables associated with the attributes specified.
1157 MaximumVariableSize Pointer to the maximum size of the individual EFI variables
1158 associated with the attributes specified.
1159 Global Pointer to VARIABLE_GLOBAL structure.
1160 Instance Instance of the Firmware Volume.
1165 EFI_INVALID_PARAMETER - An invalid combination of attribute bits was supplied.
1166 EFI_SUCCESS - Query successfully.
1167 EFI_UNSUPPORTED - The attribute is not supported on this platform.
1171 VARIABLE_HEADER
*Variable
;
1172 VARIABLE_HEADER
*NextVariable
;
1173 UINT64 VariableSize
;
1174 VARIABLE_STORE_HEADER
*VariableStoreHeader
;
1176 if(MaximumVariableStorageSize
== NULL
|| RemainingVariableStorageSize
== NULL
|| MaximumVariableSize
== NULL
) {
1177 return EFI_INVALID_PARAMETER
;
1180 if((Attributes
& (EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
)) == 0) {
1182 // Make sure the Attributes combination is supported by the platform.
1184 return EFI_UNSUPPORTED
;
1185 } else if ((Attributes
& (EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
)) == EFI_VARIABLE_RUNTIME_ACCESS
) {
1187 // Make sure if runtime bit is set, boot service bit is set also.
1189 return EFI_INVALID_PARAMETER
;
1190 } else if (EfiAtRuntime () && !(Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
)) {
1192 // Make sure RT Attribute is set if we are in Runtime phase.
1194 return EFI_INVALID_PARAMETER
;
1197 AcquireLockOnlyAtBootTime(&Global
->VariableServicesLock
);
1199 if((Attributes
& EFI_VARIABLE_NON_VOLATILE
) == 0) {
1201 // Query is Volatile related.
1203 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->VolatileVariableBase
);
1206 // Query is Non-Volatile related.
1208 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->NonVolatileVariableBase
);
1212 // Now let's fill *MaximumVariableStorageSize *RemainingVariableStorageSize
1213 // with the storage size (excluding the storage header size).
1215 *MaximumVariableStorageSize
= VariableStoreHeader
->Size
- sizeof (VARIABLE_STORE_HEADER
);
1216 *RemainingVariableStorageSize
= VariableStoreHeader
->Size
- sizeof (VARIABLE_STORE_HEADER
);
1219 // Let *MaximumVariableSize be MAX_VARIABLE_SIZE.
1221 *MaximumVariableSize
= MAX_VARIABLE_SIZE
;
1224 // Point to the starting address of the variables.
1226 Variable
= (VARIABLE_HEADER
*) (VariableStoreHeader
+ 1);
1229 // Now walk through the related variable store.
1231 while (IsValidVariableHeader (Variable
) && (Variable
< GetEndPointer (VariableStoreHeader
))) {
1232 NextVariable
= GetNextVariablePtr (Variable
);
1233 VariableSize
= (UINT64
) (UINTN
) NextVariable
- (UINT64
) (UINTN
) Variable
;
1235 if (EfiAtRuntime ()) {
1237 // we don't take the state of the variables in mind
1238 // when calculating RemainingVariableStorageSize,
1239 // since the space occupied by variables not marked with
1240 // VAR_ADDED is not allowed to be reclaimed in Runtime.
1242 *RemainingVariableStorageSize
-= VariableSize
;
1245 // Only care about Variables with State VAR_ADDED,because
1246 // the space not marked as VAR_ADDED is reclaimable now.
1248 if (Variable
->State
== VAR_ADDED
) {
1249 *RemainingVariableStorageSize
-= VariableSize
;
1254 // Go to the next one
1256 Variable
= NextVariable
;
1259 ReleaseLockOnlyAtBootTime (&Global
->VariableServicesLock
);
1265 VariableCommonInitialize (
1266 IN EFI_HANDLE ImageHandle
,
1267 IN EFI_SYSTEM_TABLE
*SystemTable
1271 Routine Description:
1272 This function does common initialization for variable services
1276 ImageHandle - The firmware allocated handle for the EFI image.
1277 SystemTable - A pointer to the EFI System Table.
1283 EFI_NOT_FOUND - Variable store area not found.
1284 EFI_UNSUPPORTED - Currently only one non-volatile variable store is supported.
1285 EFI_SUCCESS - Variable services successfully initialized.
1290 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
1292 VARIABLE_STORE_HEADER
*VolatileVariableStore
;
1293 VARIABLE_STORE_HEADER
*VariableStoreHeader
;
1294 VARIABLE_HEADER
*NextVariable
;
1296 EFI_PHYSICAL_ADDRESS FvVolHdr
;
1298 UINT64 TempVariableStoreHeader
;
1300 EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor
;
1301 EFI_FLASH_SUBAREA_ENTRY VariableStoreEntry
;
1307 mVariableModuleGlobal
= AllocateRuntimePool (sizeof (ESAL_VARIABLE_GLOBAL
));
1308 if (mVariableModuleGlobal
== NULL
) {
1309 return EFI_OUT_OF_RESOURCES
;
1312 EfiInitializeLock(&mVariableModuleGlobal
->VariableGlobal
[Physical
].VariableServicesLock
, TPL_NOTIFY
);
1315 // Allocate memory for volatile variable store
1317 VolatileVariableStore
= AllocateRuntimePool (VARIABLE_STORE_SIZE
+ SCRATCH_SIZE
);
1318 if (VolatileVariableStore
== NULL
) {
1319 FreePool (mVariableModuleGlobal
);
1320 return EFI_OUT_OF_RESOURCES
;
1323 SetMem (VolatileVariableStore
, VARIABLE_STORE_SIZE
+ SCRATCH_SIZE
, 0xff);
1326 // Variable Specific Data
1328 mVariableModuleGlobal
->VariableGlobal
[Physical
].VolatileVariableBase
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) VolatileVariableStore
;
1329 mVariableModuleGlobal
->VolatileLastVariableOffset
= sizeof (VARIABLE_STORE_HEADER
);
1331 VolatileVariableStore
->Signature
= VARIABLE_STORE_SIGNATURE
;
1332 VolatileVariableStore
->Size
= VARIABLE_STORE_SIZE
;
1333 VolatileVariableStore
->Format
= VARIABLE_STORE_FORMATTED
;
1334 VolatileVariableStore
->State
= VARIABLE_STORE_HEALTHY
;
1335 VolatileVariableStore
->Reserved
= 0;
1336 VolatileVariableStore
->Reserved1
= 0;
1339 // Get non volatile varaible store
1342 TempVariableStoreHeader
= (UINT64
) PcdGet32 (PcdFlashNvStorageVariableBase
);
1343 VariableStoreEntry
.Base
= TempVariableStoreHeader
+ \
1344 (((EFI_FIRMWARE_VOLUME_HEADER
*) (UINTN
) (TempVariableStoreHeader
)) -> HeaderLength
);
1345 VariableStoreEntry
.Length
= (UINT64
) PcdGet32 (PcdFlashNvStorageVariableSize
) - \
1346 (((EFI_FIRMWARE_VOLUME_HEADER
*) (UINTN
) (TempVariableStoreHeader
)) -> HeaderLength
);
1348 // Mark the variable storage region of the FLASH as RUNTIME
1350 BaseAddress
= VariableStoreEntry
.Base
& (~EFI_PAGE_MASK
);
1351 Length
= VariableStoreEntry
.Length
+ (VariableStoreEntry
.Base
- BaseAddress
);
1352 Length
= (Length
+ EFI_PAGE_SIZE
- 1) & (~EFI_PAGE_MASK
);
1354 Status
= gDS
->GetMemorySpaceDescriptor (BaseAddress
, &GcdDescriptor
);
1355 if (EFI_ERROR (Status
)) {
1356 FreePool (mVariableModuleGlobal
);
1357 FreePool (VolatileVariableStore
);
1358 return EFI_UNSUPPORTED
;
1361 Status
= gDS
->SetMemorySpaceAttributes (
1364 GcdDescriptor
.Attributes
| EFI_MEMORY_RUNTIME
1366 if (EFI_ERROR (Status
)) {
1367 FreePool (mVariableModuleGlobal
);
1368 FreePool (VolatileVariableStore
);
1369 return EFI_UNSUPPORTED
;
1372 // Get address of non volatile variable store base
1374 mVariableModuleGlobal
->VariableGlobal
[Physical
].NonVolatileVariableBase
= VariableStoreEntry
.Base
;
1380 // Find the Correct Instance of the FV Block Service.
1383 CurrPtr
= (CHAR8
*) ((UINTN
) mVariableModuleGlobal
->VariableGlobal
[Physical
].NonVolatileVariableBase
);
1384 while (EfiFvbGetPhysicalAddress (Instance
, &FvVolHdr
) == EFI_SUCCESS
) {
1385 FwVolHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) ((UINTN
) FvVolHdr
);
1386 if (CurrPtr
>= (CHAR8
*) FwVolHeader
&& CurrPtr
< (((CHAR8
*) FwVolHeader
) + FwVolHeader
->FvLength
)) {
1387 mVariableModuleGlobal
->FvbInstance
= Instance
;
1394 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) CurrPtr
;
1395 if (GetVariableStoreStatus (VariableStoreHeader
) == EfiValid
) {
1396 if (~VariableStoreHeader
->Size
== 0) {
1397 Status
= UpdateVariableStore (
1398 &mVariableModuleGlobal
->VariableGlobal
[Physical
],
1401 mVariableModuleGlobal
->FvbInstance
,
1402 (UINTN
) &VariableStoreHeader
->Size
,
1404 (UINT8
*) &VariableStoreEntry
.Length
1407 // As Variables are stored in NV storage, which are slow devices,such as flash.
1408 // Variable operation may skip checking variable program result to improve performance,
1409 // We can assume Variable program is OK through some check point.
1410 // Variable Store Size Setting should be the first Variable write operation,
1411 // We can assume all Read/Write is OK if we can set Variable store size successfully.
1412 // If write fail, we will assert here
1414 ASSERT(VariableStoreHeader
->Size
== VariableStoreEntry
.Length
);
1416 if (EFI_ERROR (Status
)) {
1421 mVariableModuleGlobal
->VariableGlobal
[Physical
].NonVolatileVariableBase
= (EFI_PHYSICAL_ADDRESS
) ((UINTN
) CurrPtr
);
1423 // Parse non-volatile variable data and get last variable offset
1425 NextVariable
= (VARIABLE_HEADER
*) (CurrPtr
+ sizeof (VARIABLE_STORE_HEADER
));
1426 Status
= EFI_SUCCESS
;
1428 while (IsValidVariableHeader (NextVariable
)) {
1429 NextVariable
= GetNextVariablePtr (NextVariable
);
1432 mVariableModuleGlobal
->NonVolatileLastVariableOffset
= (UINTN
) NextVariable
- (UINTN
) CurrPtr
;
1435 // Check if the free area is blow a threshold
1437 if ((((VARIABLE_STORE_HEADER
*)((UINTN
) CurrPtr
))->Size
- mVariableModuleGlobal
->NonVolatileLastVariableOffset
) < VARIABLE_RECLAIM_THRESHOLD
) {
1439 mVariableModuleGlobal
->VariableGlobal
[Physical
].NonVolatileVariableBase
,
1440 &mVariableModuleGlobal
->NonVolatileLastVariableOffset
,
1445 if (EFI_ERROR (Status
)) {
1446 FreePool (mVariableModuleGlobal
);
1447 FreePool (VolatileVariableStore
);
1452 // Check if the free area is really free.
1454 for (Index
= mVariableModuleGlobal
->NonVolatileLastVariableOffset
; Index
< VariableStoreHeader
->Size
; Index
++) {
1455 Data
= ((UINT8
*) (UINTN
) mVariableModuleGlobal
->VariableGlobal
[Physical
].NonVolatileVariableBase
)[Index
];
1458 // There must be something wrong in variable store, do reclaim operation.
1461 mVariableModuleGlobal
->VariableGlobal
[Physical
].NonVolatileVariableBase
,
1462 &mVariableModuleGlobal
->NonVolatileLastVariableOffset
,
1470 if (EFI_ERROR (Status
)) {
1471 FreePool (mVariableModuleGlobal
);
1472 FreePool (VolatileVariableStore
);