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
);
63 A temparaty function that returns the size of a Null-terminated Unicode
64 string in bytes, including the Null terminator.
66 This function returns the size, in bytes, of the Null-terminated Unicode
67 string specified by String. It duplicates the functionality of StrSize()
68 in MDE library, but avoids using PCD, because IPF currently cannot convert
69 address of global variable for runtime.
71 If String is NULL, then ASSERT().
72 If String is not aligned on a 16-bit boundary, then ASSERT().
74 @param String Pointer to a Null-terminated Unicode string.
76 @return The size of String.
81 StrSizeOfVariableName (
82 IN CONST CHAR16
*String
87 ASSERT (String
!= NULL
);
88 ASSERT (((UINTN
) String
& 0x01) == 0);
90 for (Length
= 0; *String
!= L
'\0'; String
++, Length
++);
92 return (Length
+ 1) * sizeof (*String
);
98 IsValidVariableHeader (
99 IN VARIABLE_HEADER
*Variable
105 This code checks if variable header is valid or not.
108 Variable Pointer to the Variable Header.
111 TRUE Variable header is valid.
112 FALSE Variable header is not valid.
116 if (Variable
== NULL
||
117 Variable
->StartId
!= VARIABLE_DATA
||
118 (sizeof (VARIABLE_HEADER
) + Variable
->NameSize
+ Variable
->DataSize
) > MAX_VARIABLE_SIZE
129 UpdateVariableStore (
130 IN VARIABLE_GLOBAL
*Global
,
132 IN BOOLEAN SetByIndex
,
134 IN UINTN DataPtrIndex
,
142 This function writes data to the FWH at the correct LBA even if the LBAs
147 Global Pointer to VARAIBLE_GLOBAL structure
148 Volatile If the Variable is Volatile or Non-Volatile
149 SetByIndex TRUE: Target pointer is given as index
150 FALSE: Target pointer is absolute
151 Instance Instance of FV Block services
152 DataPtrIndex Pointer to the Data from the end of VARIABLE_STORE_HEADER
154 DataSize Size of data to be written.
155 Buffer Pointer to the buffer from which data is written
163 EFI_FV_BLOCK_MAP_ENTRY
*PtrBlockMapEntry
;
171 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
172 VARIABLE_STORE_HEADER
*VolatileBase
;
173 EFI_PHYSICAL_ADDRESS FvVolHdr
;
174 EFI_PHYSICAL_ADDRESS DataPtr
;
178 DataPtr
= DataPtrIndex
;
181 // Check if the Data is Volatile
184 EfiFvbGetPhysicalAddress (Instance
, &FvVolHdr
);
185 FwVolHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) ((UINTN
) FvVolHdr
);
187 // Data Pointer should point to the actual Address where data is to be
191 DataPtr
+= Global
->NonVolatileVariableBase
;
194 if ((DataPtr
+ DataSize
) >= ((EFI_PHYSICAL_ADDRESS
) (UINTN
) ((UINT8
*) FwVolHeader
+ FwVolHeader
->FvLength
))) {
195 return EFI_INVALID_PARAMETER
;
199 // Data Pointer should point to the actual Address where data is to be
202 VolatileBase
= (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->VolatileVariableBase
);
204 DataPtr
+= Global
->VolatileVariableBase
;
207 if ((DataPtr
+ DataSize
) >= ((UINTN
) ((UINT8
*) VolatileBase
+ VolatileBase
->Size
))) {
208 return EFI_INVALID_PARAMETER
;
212 // If Volatile Variable just do a simple mem copy.
215 CopyMem ((UINT8
*) ((UINTN
) DataPtr
), Buffer
, DataSize
);
219 // If we are here we are dealing with Non-Volatile Variables
221 LinearOffset
= (UINTN
) FwVolHeader
;
222 CurrWritePtr
= (UINTN
) DataPtr
;
223 CurrWriteSize
= DataSize
;
227 if (CurrWritePtr
< LinearOffset
) {
228 return EFI_INVALID_PARAMETER
;
231 for (PtrBlockMapEntry
= FwVolHeader
->FvBlockMap
; PtrBlockMapEntry
->NumBlocks
!= 0; PtrBlockMapEntry
++) {
232 for (BlockIndex2
= 0; BlockIndex2
< PtrBlockMapEntry
->NumBlocks
; BlockIndex2
++) {
234 // Check to see if the Variable Writes are spanning through multiple
237 if ((CurrWritePtr
>= LinearOffset
) && (CurrWritePtr
< LinearOffset
+ PtrBlockMapEntry
->BlockLength
)) {
238 if ((CurrWritePtr
+ CurrWriteSize
) <= (LinearOffset
+ PtrBlockMapEntry
->BlockLength
)) {
239 Status
= EfiFvbWriteBlock (
242 (UINTN
) (CurrWritePtr
- LinearOffset
),
246 if (EFI_ERROR (Status
)) {
250 Size
= (UINT32
) (LinearOffset
+ PtrBlockMapEntry
->BlockLength
- CurrWritePtr
);
251 Status
= EfiFvbWriteBlock (
254 (UINTN
) (CurrWritePtr
- LinearOffset
),
258 if (EFI_ERROR (Status
)) {
262 CurrWritePtr
= LinearOffset
+ PtrBlockMapEntry
->BlockLength
;
263 CurrBuffer
= CurrBuffer
+ Size
;
264 CurrWriteSize
= CurrWriteSize
- Size
;
268 LinearOffset
+= PtrBlockMapEntry
->BlockLength
;
277 VARIABLE_STORE_STATUS
279 GetVariableStoreStatus (
280 IN VARIABLE_STORE_HEADER
*VarStoreHeader
286 This code gets the current status of Variable Store.
290 VarStoreHeader Pointer to the Variable Store Header.
294 EfiRaw Variable store status is raw
295 EfiValid Variable store status is valid
296 EfiInvalid Variable store status is invalid
300 if (VarStoreHeader
->Signature
== VARIABLE_STORE_SIGNATURE
&&
301 VarStoreHeader
->Format
== VARIABLE_STORE_FORMATTED
&&
302 VarStoreHeader
->State
== VARIABLE_STORE_HEALTHY
306 } else if (VarStoreHeader
->Signature
== 0xffffffff &&
307 VarStoreHeader
->Size
== 0xffffffff &&
308 VarStoreHeader
->Format
== 0xff &&
309 VarStoreHeader
->State
== 0xff
322 IN VARIABLE_HEADER
*Variable
328 This code gets the pointer to the variable data.
332 Variable Pointer to the Variable Header.
336 UINT8* Pointer to Variable Data
341 // Be careful about pad size for alignment
343 return (UINT8
*) ((UINTN
) GET_VARIABLE_NAME_PTR (Variable
) + Variable
->NameSize
+ GET_PAD_SIZE (Variable
->NameSize
));
350 IN VARIABLE_HEADER
*Variable
356 This code gets the pointer to the next variable header.
360 Variable Pointer to the Variable Header.
364 VARIABLE_HEADER* Pointer to next variable header.
368 if (!IsValidVariableHeader (Variable
)) {
372 // Be careful about pad size for alignment
374 return (VARIABLE_HEADER
*) ((UINTN
) GetVariableDataPtr (Variable
) + Variable
->DataSize
+ GET_PAD_SIZE (Variable
->DataSize
));
381 IN VARIABLE_STORE_HEADER
*VarStoreHeader
387 This code gets the pointer to the last variable memory pointer byte
391 VarStoreHeader Pointer to the Variable Store Header.
395 VARIABLE_HEADER* Pointer to last unavailable Variable Header
400 // The end of variable store
402 return (VARIABLE_HEADER
*) ((UINTN
) VarStoreHeader
+ VarStoreHeader
->Size
);
409 IN EFI_PHYSICAL_ADDRESS VariableBase
,
410 OUT UINTN
*LastVariableOffset
,
411 IN BOOLEAN IsVolatile
417 Variable store garbage collection and reclaim operation
421 VariableBase Base address of variable store
422 LastVariableOffset Offset of last variable
423 IsVolatile The variable store is volatile or not,
424 if it is non-volatile, need FTW
432 VARIABLE_HEADER
*Variable
;
433 VARIABLE_HEADER
*NextVariable
;
434 VARIABLE_STORE_HEADER
*VariableStoreHeader
;
436 UINTN ValidBufferSize
;
441 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) ((UINTN
) VariableBase
);
444 // Start Pointers for the variable.
446 Variable
= (VARIABLE_HEADER
*) (VariableStoreHeader
+ 1);
448 ValidBufferSize
= sizeof (VARIABLE_STORE_HEADER
);
450 while (IsValidVariableHeader (Variable
)) {
451 NextVariable
= GetNextVariablePtr (Variable
);
452 if (Variable
->State
== VAR_ADDED
) {
453 VariableSize
= (UINTN
) NextVariable
- (UINTN
) Variable
;
454 ValidBufferSize
+= VariableSize
;
457 Variable
= NextVariable
;
460 ValidBuffer
= AllocatePool (ValidBufferSize
);
461 if (ValidBuffer
== NULL
) {
462 return EFI_OUT_OF_RESOURCES
;
465 SetMem (ValidBuffer
, ValidBufferSize
, 0xff);
467 CurrPtr
= ValidBuffer
;
470 // Copy variable store header
472 CopyMem (CurrPtr
, VariableStoreHeader
, sizeof (VARIABLE_STORE_HEADER
));
473 CurrPtr
+= sizeof (VARIABLE_STORE_HEADER
);
476 // Start Pointers for the variable.
478 Variable
= (VARIABLE_HEADER
*) (VariableStoreHeader
+ 1);
480 while (IsValidVariableHeader (Variable
)) {
481 NextVariable
= GetNextVariablePtr (Variable
);
482 if (Variable
->State
== VAR_ADDED
) {
483 VariableSize
= (UINTN
) NextVariable
- (UINTN
) Variable
;
484 CopyMem (CurrPtr
, (UINT8
*) Variable
, VariableSize
);
485 CurrPtr
+= VariableSize
;
488 Variable
= NextVariable
;
493 // If volatile variable store, just copy valid buffer
495 SetMem ((UINT8
*) (UINTN
) VariableBase
, VariableStoreHeader
->Size
, 0xff);
496 CopyMem ((UINT8
*) (UINTN
) VariableBase
, ValidBuffer
, ValidBufferSize
);
497 *LastVariableOffset
= ValidBufferSize
;
498 Status
= EFI_SUCCESS
;
501 // If non-volatile variable store, perform FTW here.
503 Status
= FtwVariableSpace (
508 if (!EFI_ERROR (Status
)) {
509 *LastVariableOffset
= ValidBufferSize
;
513 FreePool (ValidBuffer
);
515 if (EFI_ERROR (Status
)) {
516 *LastVariableOffset
= 0;
526 IN CHAR16
*VariableName
,
527 IN EFI_GUID
*VendorGuid
,
528 OUT VARIABLE_POINTER_TRACK
*PtrTrack
,
529 IN VARIABLE_GLOBAL
*Global
535 This code finds variable in storage blocks (Volatile or Non-Volatile)
539 VariableName Name of the variable to be found
540 VendorGuid Vendor GUID to be found.
541 PtrTrack Variable Track Pointer structure that contains
542 Variable Information.
543 Contains the pointer of Variable header.
544 Global VARIABLE_GLOBAL pointer
552 VARIABLE_HEADER
*Variable
[2];
553 VARIABLE_STORE_HEADER
*VariableStoreHeader
[2];
557 // We aquire the lock at the entry of FindVariable as GetVariable, GetNextVariableName
558 // SetVariable all call FindVariable at entry point. Please move "Aquire Lock" to
559 // the correct places if this assumption does not hold TRUE anymore.
561 AcquireLockOnlyAtBootTime(&Global
->VariableServicesLock
);
564 // 0: Non-Volatile, 1: Volatile
566 VariableStoreHeader
[0] = (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->NonVolatileVariableBase
);
567 VariableStoreHeader
[1] = (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->VolatileVariableBase
);
570 // Start Pointers for the variable.
571 // Actual Data Pointer where data can be written.
573 Variable
[0] = (VARIABLE_HEADER
*) (VariableStoreHeader
[0] + 1);
574 Variable
[1] = (VARIABLE_HEADER
*) (VariableStoreHeader
[1] + 1);
576 if (VariableName
[0] != 0 && VendorGuid
== NULL
) {
577 return EFI_INVALID_PARAMETER
;
580 // Find the variable by walk through non-volatile and volatile variable store
582 for (Index
= 0; Index
< 2; Index
++) {
583 PtrTrack
->StartPtr
= (VARIABLE_HEADER
*) (VariableStoreHeader
[Index
] + 1);
584 PtrTrack
->EndPtr
= GetEndPointer (VariableStoreHeader
[Index
]);
586 while (IsValidVariableHeader (Variable
[Index
]) && (Variable
[Index
] <= GetEndPointer (VariableStoreHeader
[Index
]))) {
587 if (Variable
[Index
]->State
== VAR_ADDED
) {
588 if (!(EfiAtRuntime () && !(Variable
[Index
]->Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
))) {
589 if (VariableName
[0] == 0) {
590 PtrTrack
->CurrPtr
= Variable
[Index
];
591 PtrTrack
->Volatile
= (BOOLEAN
) Index
;
594 if (CompareGuid (VendorGuid
, &Variable
[Index
]->VendorGuid
)) {
595 if (!CompareMem (VariableName
, GET_VARIABLE_NAME_PTR (Variable
[Index
]), Variable
[Index
]->NameSize
)) {
596 PtrTrack
->CurrPtr
= Variable
[Index
];
597 PtrTrack
->Volatile
= (BOOLEAN
) Index
;
605 Variable
[Index
] = GetNextVariablePtr (Variable
[Index
]);
614 PtrTrack
->CurrPtr
= NULL
;
615 return EFI_NOT_FOUND
;
621 IN CHAR16
*VariableName
,
622 IN EFI_GUID
* VendorGuid
,
623 OUT UINT32
*Attributes OPTIONAL
,
624 IN OUT UINTN
*DataSize
,
626 IN VARIABLE_GLOBAL
* Global
,
633 This code finds variable in storage blocks (Volatile or Non-Volatile)
637 VariableName Name of Variable to be found
638 VendorGuid Variable vendor GUID
639 Attributes OPTIONAL Attribute value of the variable found
640 DataSize Size of Data found. If size is less than the
641 data, this value contains the required size.
643 Global Pointer to VARIABLE_GLOBAL structure
644 Instance Instance of the Firmware Volume.
652 VARIABLE_POINTER_TRACK Variable
;
656 if (VariableName
== NULL
|| VendorGuid
== NULL
|| DataSize
== NULL
) {
657 return EFI_INVALID_PARAMETER
;
660 // Find existing variable
662 Status
= FindVariable (VariableName
, VendorGuid
, &Variable
, Global
);
664 if (Variable
.CurrPtr
== NULL
|| EFI_ERROR (Status
)) {
670 VarDataSize
= Variable
.CurrPtr
->DataSize
;
671 if (*DataSize
>= VarDataSize
) {
673 Status
= EFI_INVALID_PARAMETER
;
677 CopyMem (Data
, GetVariableDataPtr (Variable
.CurrPtr
), VarDataSize
);
678 if (Attributes
!= NULL
) {
679 *Attributes
= Variable
.CurrPtr
->Attributes
;
682 *DataSize
= VarDataSize
;
683 Status
= EFI_SUCCESS
;
686 *DataSize
= VarDataSize
;
687 Status
= EFI_BUFFER_TOO_SMALL
;
692 ReleaseLockOnlyAtBootTime (&Global
->VariableServicesLock
);
698 GetNextVariableName (
699 IN OUT UINTN
*VariableNameSize
,
700 IN OUT CHAR16
*VariableName
,
701 IN OUT EFI_GUID
*VendorGuid
,
702 IN VARIABLE_GLOBAL
*Global
,
709 This code Finds the Next available variable
713 VariableNameSize Size of the variable
714 VariableName Pointer to variable name
715 VendorGuid Variable Vendor Guid
716 Global VARIABLE_GLOBAL structure pointer.
725 VARIABLE_POINTER_TRACK Variable
;
729 if (VariableNameSize
== NULL
|| VariableName
== NULL
|| VendorGuid
== NULL
) {
730 return EFI_INVALID_PARAMETER
;
733 Status
= FindVariable (VariableName
, VendorGuid
, &Variable
, Global
);
735 if (Variable
.CurrPtr
== NULL
|| EFI_ERROR (Status
)) {
739 if (VariableName
[0] != 0) {
741 // If variable name is not NULL, get next variable
743 Variable
.CurrPtr
= GetNextVariablePtr (Variable
.CurrPtr
);
748 // If both volatile and non-volatile variable store are parsed,
751 if (Variable
.CurrPtr
>= Variable
.EndPtr
|| Variable
.CurrPtr
== NULL
) {
752 Variable
.Volatile
= (BOOLEAN
) (Variable
.Volatile
^ ((BOOLEAN
) 0x1));
753 if (Variable
.Volatile
) {
754 Variable
.StartPtr
= (VARIABLE_HEADER
*) ((UINTN
) (Global
->VolatileVariableBase
+ sizeof (VARIABLE_STORE_HEADER
)));
755 Variable
.EndPtr
= (VARIABLE_HEADER
*) GetEndPointer ((VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->VolatileVariableBase
));
757 Status
= EFI_NOT_FOUND
;
761 Variable
.CurrPtr
= Variable
.StartPtr
;
762 if (!IsValidVariableHeader (Variable
.CurrPtr
)) {
769 if (IsValidVariableHeader (Variable
.CurrPtr
) && Variable
.CurrPtr
->State
== VAR_ADDED
) {
770 if (!(EfiAtRuntime () && !(Variable
.CurrPtr
->Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
))) {
771 VarNameSize
= Variable
.CurrPtr
->NameSize
;
772 if (VarNameSize
<= *VariableNameSize
) {
775 GET_VARIABLE_NAME_PTR (Variable
.CurrPtr
),
780 &Variable
.CurrPtr
->VendorGuid
,
783 Status
= EFI_SUCCESS
;
785 Status
= EFI_BUFFER_TOO_SMALL
;
788 *VariableNameSize
= VarNameSize
;
793 Variable
.CurrPtr
= GetNextVariablePtr (Variable
.CurrPtr
);
797 ReleaseLockOnlyAtBootTime (&Global
->VariableServicesLock
);
804 IN CHAR16
*VariableName
,
805 IN EFI_GUID
*VendorGuid
,
806 IN UINT32 Attributes
,
809 IN VARIABLE_GLOBAL
*Global
,
810 IN UINTN
*VolatileOffset
,
811 IN UINTN
*NonVolatileOffset
,
818 This code sets variable in storage blocks (Volatile or Non-Volatile)
822 VariableName Name of Variable to be found
823 VendorGuid Variable vendor GUID
824 Attributes Attribute value of the variable found
825 DataSize Size of Data found. If size is less than the
826 data, this value contains the required size.
828 Global Pointer to VARIABLE_GLOBAL structure
829 VolatileOffset The offset of last volatile variable
830 NonVolatileOffset The offset of last non-volatile variable
831 Instance Instance of the Firmware Volume.
836 EFI_INVALID_PARAMETER - Invalid parameter
837 EFI_SUCCESS - Set successfully
838 EFI_OUT_OF_RESOURCES - Resource not enough to set variable
839 EFI_NOT_FOUND - Not found
843 VARIABLE_POINTER_TRACK Variable
;
845 VARIABLE_HEADER
*NextVariable
;
855 if (VariableName
== NULL
|| VariableName
[0] == 0 || VendorGuid
== NULL
) {
856 return EFI_INVALID_PARAMETER
;
859 Status
= FindVariable (VariableName
, VendorGuid
, &Variable
, Global
);
861 if (Status
== EFI_INVALID_PARAMETER
) {
863 } else if (!EFI_ERROR (Status
) && Variable
.Volatile
&& EfiAtRuntime()) {
865 // If EfiAtRuntime and the variable is Volatile and Runtime Access,
866 // the volatile is ReadOnly, and SetVariable should be aborted and
867 // return EFI_WRITE_PROTECTED.
869 Status
= EFI_WRITE_PROTECTED
;
871 } else if (sizeof (VARIABLE_HEADER
) + StrSizeOfVariableName (VariableName
) + DataSize
> MAX_VARIABLE_SIZE
) {
873 // The size of the VariableName, including the Unicode Null in bytes plus
874 // the DataSize is limited to maximum size of MAX_VARIABLE_SIZE (1024) bytes.
876 Status
= EFI_INVALID_PARAMETER
;
878 } else if (Attributes
== EFI_VARIABLE_NON_VOLATILE
) {
880 // Make sure not only EFI_VARIABLE_NON_VOLATILE is set
882 Status
= EFI_INVALID_PARAMETER
;
884 } else if ((Attributes
& (EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
)) ==
885 EFI_VARIABLE_RUNTIME_ACCESS
) {
887 // Make sure if runtime bit is set, boot service bit is set also
889 Status
= EFI_INVALID_PARAMETER
;
891 } else if (EfiAtRuntime () && Attributes
&& !(Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
)) {
893 // Runtime but Attribute is not Runtime
895 Status
= EFI_INVALID_PARAMETER
;
897 } else if (EfiAtRuntime () && Attributes
&& !(Attributes
& EFI_VARIABLE_NON_VOLATILE
)) {
899 // Cannot set volatile variable in Runtime
901 Status
= EFI_INVALID_PARAMETER
;
903 } else if (DataSize
== 0 || (Attributes
& (EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
)) == 0) {
905 // Setting a data variable with no access, or zero DataSize attributes
906 // specified causes it to be deleted.
908 if (!EFI_ERROR (Status
)) {
909 State
= Variable
.CurrPtr
->State
;
910 State
&= VAR_DELETED
;
912 Status
= UpdateVariableStore (
917 (UINTN
) &Variable
.CurrPtr
->State
,
921 if (EFI_ERROR (Status
)) {
925 Status
= EFI_SUCCESS
;
929 Status
= EFI_NOT_FOUND
;
932 if (!EFI_ERROR (Status
)) {
934 // If the variable is marked valid and the same data has been passed in
935 // then return to the caller immediately.
937 if (Variable
.CurrPtr
->DataSize
== DataSize
&&
938 !CompareMem (Data
, GetVariableDataPtr (Variable
.CurrPtr
), DataSize
)
940 Status
= EFI_SUCCESS
;
942 } else if (Variable
.CurrPtr
->State
== VAR_ADDED
) {
944 // Mark the old variable as in delete transition
946 State
= Variable
.CurrPtr
->State
;
947 State
&= VAR_IN_DELETED_TRANSITION
;
949 Status
= UpdateVariableStore (
954 (UINTN
) &Variable
.CurrPtr
->State
,
958 if (EFI_ERROR (Status
)) {
964 // Create a new variable and copy the data.
966 // Tricky part: Use scratch data area at the end of volatile variable store
967 // as a temporary storage.
969 NextVariable
= GetEndPointer ((VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->VolatileVariableBase
));
971 SetMem (NextVariable
, SCRATCH_SIZE
, 0xff);
973 NextVariable
->StartId
= VARIABLE_DATA
;
974 NextVariable
->Attributes
= Attributes
;
976 // NextVariable->State = VAR_ADDED;
978 NextVariable
->Reserved
= 0;
979 VarNameOffset
= sizeof (VARIABLE_HEADER
);
980 VarNameSize
= StrSizeOfVariableName (VariableName
);
982 (UINT8
*) ((UINTN
) NextVariable
+ VarNameOffset
),
986 VarDataOffset
= VarNameOffset
+ VarNameSize
+ GET_PAD_SIZE (VarNameSize
);
988 (UINT8
*) ((UINTN
) NextVariable
+ VarDataOffset
),
992 CopyMem (&NextVariable
->VendorGuid
, VendorGuid
, sizeof (EFI_GUID
));
994 // There will be pad bytes after Data, the NextVariable->NameSize and
995 // NextVariable->DataSize should not include pad size so that variable
996 // service can get actual size in GetVariable
998 NextVariable
->NameSize
= (UINT32
)VarNameSize
;
999 NextVariable
->DataSize
= (UINT32
)DataSize
;
1002 // The actual size of the variable that stores in storage should
1003 // include pad size.
1005 VarSize
= VarDataOffset
+ DataSize
+ GET_PAD_SIZE (DataSize
);
1006 if (Attributes
& EFI_VARIABLE_NON_VOLATILE
) {
1007 if ((UINT32
) (VarSize
+*NonVolatileOffset
) >
1008 ((VARIABLE_STORE_HEADER
*) ((UINTN
) (Global
->NonVolatileVariableBase
)))->Size
1010 if (EfiAtRuntime ()) {
1011 Status
= EFI_OUT_OF_RESOURCES
;
1015 // Perform garbage collection & reclaim operation
1017 Status
= Reclaim (Global
->NonVolatileVariableBase
, NonVolatileOffset
, FALSE
);
1018 if (EFI_ERROR (Status
)) {
1022 // If still no enough space, return out of resources
1024 if ((UINT32
) (VarSize
+*NonVolatileOffset
) >
1025 ((VARIABLE_STORE_HEADER
*) ((UINTN
) (Global
->NonVolatileVariableBase
)))->Size
1027 Status
= EFI_OUT_OF_RESOURCES
;
1035 // 1. Write variable header
1036 // 2. Write variable data
1037 // 3. Set variable state to valid
1042 Status
= UpdateVariableStore (
1048 sizeof (VARIABLE_HEADER
),
1049 (UINT8
*) NextVariable
1052 if (EFI_ERROR (Status
)) {
1058 Status
= UpdateVariableStore (
1063 *NonVolatileOffset
+ sizeof (VARIABLE_HEADER
),
1064 (UINT32
) VarSize
- sizeof (VARIABLE_HEADER
),
1065 (UINT8
*) NextVariable
+ sizeof (VARIABLE_HEADER
)
1068 if (EFI_ERROR (Status
)) {
1074 NextVariable
->State
= VAR_ADDED
;
1075 Status
= UpdateVariableStore (
1081 sizeof (VARIABLE_HEADER
),
1082 (UINT8
*) NextVariable
1085 if (EFI_ERROR (Status
)) {
1089 *NonVolatileOffset
= *NonVolatileOffset
+ VarSize
;
1092 if (EfiAtRuntime ()) {
1093 Status
= EFI_INVALID_PARAMETER
;
1097 if ((UINT32
) (VarSize
+*VolatileOffset
) >
1098 ((VARIABLE_STORE_HEADER
*) ((UINTN
) (Global
->VolatileVariableBase
)))->Size
1101 // Perform garbage collection & reclaim operation
1103 Status
= Reclaim (Global
->VolatileVariableBase
, VolatileOffset
, TRUE
);
1104 if (EFI_ERROR (Status
)) {
1108 // If still no enough space, return out of resources
1110 if ((UINT32
) (VarSize
+*VolatileOffset
) >
1111 ((VARIABLE_STORE_HEADER
*) ((UINTN
) (Global
->VolatileVariableBase
)))->Size
1113 Status
= EFI_OUT_OF_RESOURCES
;
1120 NextVariable
->State
= VAR_ADDED
;
1121 Status
= UpdateVariableStore (
1128 (UINT8
*) NextVariable
1131 if (EFI_ERROR (Status
)) {
1135 *VolatileOffset
= *VolatileOffset
+ VarSize
;
1138 // Mark the old variable as deleted
1140 if (!Reclaimed
&& !EFI_ERROR (Status
) && Variable
.CurrPtr
!= NULL
) {
1141 State
= Variable
.CurrPtr
->State
;
1142 State
&= VAR_DELETED
;
1144 Status
= UpdateVariableStore (
1149 (UINTN
) &Variable
.CurrPtr
->State
,
1154 if (EFI_ERROR (Status
)) {
1160 Status
= EFI_SUCCESS
;
1162 ReleaseLockOnlyAtBootTime (&Global
->VariableServicesLock
);
1169 IN UINT32 Attributes
,
1170 OUT UINT64
*MaximumVariableStorageSize
,
1171 OUT UINT64
*RemainingVariableStorageSize
,
1172 OUT UINT64
*MaximumVariableSize
,
1173 IN VARIABLE_GLOBAL
*Global
,
1178 Routine Description:
1180 This code returns information about the EFI variables.
1184 Attributes Attributes bitmask to specify the type of variables
1185 on which to return information.
1186 MaximumVariableStorageSize Pointer to the maximum size of the storage space available
1187 for the EFI variables associated with the attributes specified.
1188 RemainingVariableStorageSize Pointer to the remaining size of the storage space available
1189 for the EFI variables associated with the attributes specified.
1190 MaximumVariableSize Pointer to the maximum size of the individual EFI variables
1191 associated with the attributes specified.
1192 Global Pointer to VARIABLE_GLOBAL structure.
1193 Instance Instance of the Firmware Volume.
1198 EFI_INVALID_PARAMETER - An invalid combination of attribute bits was supplied.
1199 EFI_SUCCESS - Query successfully.
1200 EFI_UNSUPPORTED - The attribute is not supported on this platform.
1204 VARIABLE_HEADER
*Variable
;
1205 VARIABLE_HEADER
*NextVariable
;
1206 UINT64 VariableSize
;
1207 VARIABLE_STORE_HEADER
*VariableStoreHeader
;
1209 if(MaximumVariableStorageSize
== NULL
|| RemainingVariableStorageSize
== NULL
|| MaximumVariableSize
== NULL
) {
1210 return EFI_INVALID_PARAMETER
;
1213 if((Attributes
& (EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
)) == 0) {
1215 // Make sure the Attributes combination is supported by the platform.
1217 return EFI_UNSUPPORTED
;
1218 } else if ((Attributes
& (EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
)) == EFI_VARIABLE_RUNTIME_ACCESS
) {
1220 // Make sure if runtime bit is set, boot service bit is set also.
1222 return EFI_INVALID_PARAMETER
;
1223 } else if (EfiAtRuntime () && !(Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
)) {
1225 // Make sure RT Attribute is set if we are in Runtime phase.
1227 return EFI_INVALID_PARAMETER
;
1230 AcquireLockOnlyAtBootTime(&Global
->VariableServicesLock
);
1232 if((Attributes
& EFI_VARIABLE_NON_VOLATILE
) == 0) {
1234 // Query is Volatile related.
1236 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->VolatileVariableBase
);
1239 // Query is Non-Volatile related.
1241 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->NonVolatileVariableBase
);
1245 // Now let's fill *MaximumVariableStorageSize *RemainingVariableStorageSize
1246 // with the storage size (excluding the storage header size).
1248 *MaximumVariableStorageSize
= VariableStoreHeader
->Size
- sizeof (VARIABLE_STORE_HEADER
);
1249 *RemainingVariableStorageSize
= VariableStoreHeader
->Size
- sizeof (VARIABLE_STORE_HEADER
);
1252 // Let *MaximumVariableSize be MAX_VARIABLE_SIZE.
1254 *MaximumVariableSize
= MAX_VARIABLE_SIZE
;
1257 // Point to the starting address of the variables.
1259 Variable
= (VARIABLE_HEADER
*) (VariableStoreHeader
+ 1);
1262 // Now walk through the related variable store.
1264 while (IsValidVariableHeader (Variable
) && (Variable
< GetEndPointer (VariableStoreHeader
))) {
1265 NextVariable
= GetNextVariablePtr (Variable
);
1266 VariableSize
= (UINT64
) (UINTN
) NextVariable
- (UINT64
) (UINTN
) Variable
;
1268 if (EfiAtRuntime ()) {
1270 // we don't take the state of the variables in mind
1271 // when calculating RemainingVariableStorageSize,
1272 // since the space occupied by variables not marked with
1273 // VAR_ADDED is not allowed to be reclaimed in Runtime.
1275 *RemainingVariableStorageSize
-= VariableSize
;
1278 // Only care about Variables with State VAR_ADDED,because
1279 // the space not marked as VAR_ADDED is reclaimable now.
1281 if (Variable
->State
== VAR_ADDED
) {
1282 *RemainingVariableStorageSize
-= VariableSize
;
1287 // Go to the next one
1289 Variable
= NextVariable
;
1292 ReleaseLockOnlyAtBootTime (&Global
->VariableServicesLock
);
1298 VariableCommonInitialize (
1299 IN EFI_HANDLE ImageHandle
,
1300 IN EFI_SYSTEM_TABLE
*SystemTable
1304 Routine Description:
1305 This function does common initialization for variable services
1309 ImageHandle - The firmware allocated handle for the EFI image.
1310 SystemTable - A pointer to the EFI System Table.
1316 EFI_NOT_FOUND - Variable store area not found.
1317 EFI_UNSUPPORTED - Currently only one non-volatile variable store is supported.
1318 EFI_SUCCESS - Variable services successfully initialized.
1323 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
1325 VARIABLE_STORE_HEADER
*VolatileVariableStore
;
1326 VARIABLE_STORE_HEADER
*VariableStoreHeader
;
1327 VARIABLE_HEADER
*NextVariable
;
1329 EFI_PHYSICAL_ADDRESS FvVolHdr
;
1331 UINT64 TempVariableStoreHeader
;
1333 EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor
;
1334 EFI_FLASH_SUBAREA_ENTRY VariableStoreEntry
;
1340 mVariableModuleGlobal
= AllocateRuntimePool (sizeof (ESAL_VARIABLE_GLOBAL
));
1341 if (mVariableModuleGlobal
== NULL
) {
1342 return EFI_OUT_OF_RESOURCES
;
1345 EfiInitializeLock(&mVariableModuleGlobal
->VariableGlobal
[Physical
].VariableServicesLock
, EFI_TPL_NOTIFY
);
1348 // Allocate memory for volatile variable store
1350 VolatileVariableStore
= AllocateRuntimePool (VARIABLE_STORE_SIZE
+ SCRATCH_SIZE
);
1351 if (VolatileVariableStore
== NULL
) {
1352 FreePool (mVariableModuleGlobal
);
1353 return EFI_OUT_OF_RESOURCES
;
1356 SetMem (VolatileVariableStore
, VARIABLE_STORE_SIZE
+ SCRATCH_SIZE
, 0xff);
1359 // Variable Specific Data
1361 mVariableModuleGlobal
->VariableGlobal
[Physical
].VolatileVariableBase
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) VolatileVariableStore
;
1362 mVariableModuleGlobal
->VolatileLastVariableOffset
= sizeof (VARIABLE_STORE_HEADER
);
1364 VolatileVariableStore
->Signature
= VARIABLE_STORE_SIGNATURE
;
1365 VolatileVariableStore
->Size
= VARIABLE_STORE_SIZE
;
1366 VolatileVariableStore
->Format
= VARIABLE_STORE_FORMATTED
;
1367 VolatileVariableStore
->State
= VARIABLE_STORE_HEALTHY
;
1368 VolatileVariableStore
->Reserved
= 0;
1369 VolatileVariableStore
->Reserved1
= 0;
1372 // Get non volatile varaible store
1375 TempVariableStoreHeader
= (UINT64
) PcdGet32 (PcdFlashNvStorageVariableBase
);
1376 VariableStoreEntry
.Base
= TempVariableStoreHeader
+ \
1377 (((EFI_FIRMWARE_VOLUME_HEADER
*) (UINTN
) (TempVariableStoreHeader
)) -> HeaderLength
);
1378 VariableStoreEntry
.Length
= (UINT64
) PcdGet32 (PcdFlashNvStorageVariableSize
) - \
1379 (((EFI_FIRMWARE_VOLUME_HEADER
*) (UINTN
) (TempVariableStoreHeader
)) -> HeaderLength
);
1381 // Mark the variable storage region of the FLASH as RUNTIME
1383 BaseAddress
= VariableStoreEntry
.Base
& (~EFI_PAGE_MASK
);
1384 Length
= VariableStoreEntry
.Length
+ (VariableStoreEntry
.Base
- BaseAddress
);
1385 Length
= (Length
+ EFI_PAGE_SIZE
- 1) & (~EFI_PAGE_MASK
);
1387 Status
= gDS
->GetMemorySpaceDescriptor (BaseAddress
, &GcdDescriptor
);
1388 if (EFI_ERROR (Status
)) {
1389 FreePool (mVariableModuleGlobal
);
1390 FreePool (VolatileVariableStore
);
1391 return EFI_UNSUPPORTED
;
1394 Status
= gDS
->SetMemorySpaceAttributes (
1397 GcdDescriptor
.Attributes
| EFI_MEMORY_RUNTIME
1399 if (EFI_ERROR (Status
)) {
1400 FreePool (mVariableModuleGlobal
);
1401 FreePool (VolatileVariableStore
);
1402 return EFI_UNSUPPORTED
;
1405 // Get address of non volatile variable store base
1407 mVariableModuleGlobal
->VariableGlobal
[Physical
].NonVolatileVariableBase
= VariableStoreEntry
.Base
;
1413 // Find the Correct Instance of the FV Block Service.
1416 CurrPtr
= (CHAR8
*) ((UINTN
) mVariableModuleGlobal
->VariableGlobal
[Physical
].NonVolatileVariableBase
);
1417 while (EfiFvbGetPhysicalAddress (Instance
, &FvVolHdr
) == EFI_SUCCESS
) {
1418 FwVolHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) ((UINTN
) FvVolHdr
);
1419 if (CurrPtr
>= (CHAR8
*) FwVolHeader
&& CurrPtr
< (((CHAR8
*) FwVolHeader
) + FwVolHeader
->FvLength
)) {
1420 mVariableModuleGlobal
->FvbInstance
= Instance
;
1427 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) CurrPtr
;
1428 if (GetVariableStoreStatus (VariableStoreHeader
) == EfiValid
) {
1429 if (~VariableStoreHeader
->Size
== 0) {
1430 Status
= UpdateVariableStore (
1431 &mVariableModuleGlobal
->VariableGlobal
[Physical
],
1434 mVariableModuleGlobal
->FvbInstance
,
1435 (UINTN
) &VariableStoreHeader
->Size
,
1437 (UINT8
*) &VariableStoreEntry
.Length
1440 // As Variables are stored in NV storage, which are slow devices,such as flash.
1441 // Variable operation may skip checking variable program result to improve performance,
1442 // We can assume Variable program is OK through some check point.
1443 // Variable Store Size Setting should be the first Variable write operation,
1444 // We can assume all Read/Write is OK if we can set Variable store size successfully.
1445 // If write fail, we will assert here
1447 ASSERT(VariableStoreHeader
->Size
== VariableStoreEntry
.Length
);
1449 if (EFI_ERROR (Status
)) {
1454 mVariableModuleGlobal
->VariableGlobal
[Physical
].NonVolatileVariableBase
= (EFI_PHYSICAL_ADDRESS
) ((UINTN
) CurrPtr
);
1456 // Parse non-volatile variable data and get last variable offset
1458 NextVariable
= (VARIABLE_HEADER
*) (CurrPtr
+ sizeof (VARIABLE_STORE_HEADER
));
1459 Status
= EFI_SUCCESS
;
1461 while (IsValidVariableHeader (NextVariable
)) {
1462 NextVariable
= GetNextVariablePtr (NextVariable
);
1465 mVariableModuleGlobal
->NonVolatileLastVariableOffset
= (UINTN
) NextVariable
- (UINTN
) CurrPtr
;
1468 // Check if the free area is blow a threshold
1470 if ((((VARIABLE_STORE_HEADER
*)((UINTN
) CurrPtr
))->Size
- mVariableModuleGlobal
->NonVolatileLastVariableOffset
) < VARIABLE_RECLAIM_THRESHOLD
) {
1472 mVariableModuleGlobal
->VariableGlobal
[Physical
].NonVolatileVariableBase
,
1473 &mVariableModuleGlobal
->NonVolatileLastVariableOffset
,
1478 if (EFI_ERROR (Status
)) {
1479 FreePool (mVariableModuleGlobal
);
1480 FreePool (VolatileVariableStore
);
1485 // Check if the free area is really free.
1487 for (Index
= mVariableModuleGlobal
->NonVolatileLastVariableOffset
; Index
< VariableStoreHeader
->Size
; Index
++) {
1488 Data
= ((UINT8
*) (UINTN
) mVariableModuleGlobal
->VariableGlobal
[Physical
].NonVolatileVariableBase
)[Index
];
1491 // There must be something wrong in variable store, do reclaim operation.
1494 mVariableModuleGlobal
->VariableGlobal
[Physical
].NonVolatileVariableBase
,
1495 &mVariableModuleGlobal
->NonVolatileLastVariableOffset
,
1503 if (EFI_ERROR (Status
)) {
1504 FreePool (mVariableModuleGlobal
);
1505 FreePool (VolatileVariableStore
);