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
);
72 Determine the length of null terminated char16 array.
76 String Null-terminated CHAR16 array pointer.
80 UINT32 Number of bytes in the string, including the double NULL at the end;
92 while (0 != String
[Count
]) {
96 return (Count
* 2) + 2;
102 IsValidVariableHeader (
103 IN VARIABLE_HEADER
*Variable
109 This code checks if variable header is valid or not.
112 Variable Pointer to the Variable Header.
115 TRUE Variable header is valid.
116 FALSE Variable header is not valid.
120 if (Variable
== NULL
||
121 Variable
->StartId
!= VARIABLE_DATA
||
122 (sizeof (VARIABLE_HEADER
) + Variable
->NameSize
+ Variable
->DataSize
) > MAX_VARIABLE_SIZE
133 UpdateVariableStore (
134 IN VARIABLE_GLOBAL
*Global
,
136 IN BOOLEAN SetByIndex
,
138 IN UINTN DataPtrIndex
,
146 This function writes data to the FWH at the correct LBA even if the LBAs
151 Global Pointer to VARAIBLE_GLOBAL structure
152 Volatile If the Variable is Volatile or Non-Volatile
153 SetByIndex TRUE: Target pointer is given as index
154 FALSE: Target pointer is absolute
155 Instance Instance of FV Block services
156 DataPtrIndex Pointer to the Data from the end of VARIABLE_STORE_HEADER
158 DataSize Size of data to be written.
159 Buffer Pointer to the buffer from which data is written
167 EFI_FV_BLOCK_MAP_ENTRY
*PtrBlockMapEntry
;
175 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
176 VARIABLE_STORE_HEADER
*VolatileBase
;
177 EFI_PHYSICAL_ADDRESS FvVolHdr
;
178 EFI_PHYSICAL_ADDRESS DataPtr
;
182 DataPtr
= DataPtrIndex
;
185 // Check if the Data is Volatile
188 EfiFvbGetPhysicalAddress (Instance
, &FvVolHdr
);
189 FwVolHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) ((UINTN
) FvVolHdr
);
191 // Data Pointer should point to the actual Address where data is to be
195 DataPtr
+= Global
->NonVolatileVariableBase
;
198 if ((DataPtr
+ DataSize
) >= ((EFI_PHYSICAL_ADDRESS
) (UINTN
) ((UINT8
*) FwVolHeader
+ FwVolHeader
->FvLength
))) {
199 return EFI_INVALID_PARAMETER
;
203 // Data Pointer should point to the actual Address where data is to be
206 VolatileBase
= (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->VolatileVariableBase
);
208 DataPtr
+= Global
->VolatileVariableBase
;
211 if ((DataPtr
+ DataSize
) >= ((UINTN
) ((UINT8
*) VolatileBase
+ VolatileBase
->Size
))) {
212 return EFI_INVALID_PARAMETER
;
216 // If Volatile Variable just do a simple mem copy.
219 CopyMem ((UINT8
*) ((UINTN
) DataPtr
), Buffer
, DataSize
);
223 // If we are here we are dealing with Non-Volatile Variables
225 LinearOffset
= (UINTN
) FwVolHeader
;
226 CurrWritePtr
= (UINTN
) DataPtr
;
227 CurrWriteSize
= DataSize
;
231 if (CurrWritePtr
< LinearOffset
) {
232 return EFI_INVALID_PARAMETER
;
235 for (PtrBlockMapEntry
= FwVolHeader
->FvBlockMap
; PtrBlockMapEntry
->NumBlocks
!= 0; PtrBlockMapEntry
++) {
236 for (BlockIndex2
= 0; BlockIndex2
< PtrBlockMapEntry
->NumBlocks
; BlockIndex2
++) {
238 // Check to see if the Variable Writes are spanning through multiple
241 if ((CurrWritePtr
>= LinearOffset
) && (CurrWritePtr
< LinearOffset
+ PtrBlockMapEntry
->BlockLength
)) {
242 if ((CurrWritePtr
+ CurrWriteSize
) <= (LinearOffset
+ PtrBlockMapEntry
->BlockLength
)) {
243 Status
= EfiFvbWriteBlock (
246 (UINTN
) (CurrWritePtr
- LinearOffset
),
250 if (EFI_ERROR (Status
)) {
254 Size
= (UINT32
) (LinearOffset
+ PtrBlockMapEntry
->BlockLength
- CurrWritePtr
);
255 Status
= EfiFvbWriteBlock (
258 (UINTN
) (CurrWritePtr
- LinearOffset
),
262 if (EFI_ERROR (Status
)) {
266 CurrWritePtr
= LinearOffset
+ PtrBlockMapEntry
->BlockLength
;
267 CurrBuffer
= CurrBuffer
+ Size
;
268 CurrWriteSize
= CurrWriteSize
- Size
;
272 LinearOffset
+= PtrBlockMapEntry
->BlockLength
;
281 VARIABLE_STORE_STATUS
283 GetVariableStoreStatus (
284 IN VARIABLE_STORE_HEADER
*VarStoreHeader
290 This code gets the current status of Variable Store.
294 VarStoreHeader Pointer to the Variable Store Header.
298 EfiRaw Variable store status is raw
299 EfiValid Variable store status is valid
300 EfiInvalid Variable store status is invalid
304 if (VarStoreHeader
->Signature
== VARIABLE_STORE_SIGNATURE
&&
305 VarStoreHeader
->Format
== VARIABLE_STORE_FORMATTED
&&
306 VarStoreHeader
->State
== VARIABLE_STORE_HEALTHY
310 } else if (VarStoreHeader
->Signature
== 0xffffffff &&
311 VarStoreHeader
->Size
== 0xffffffff &&
312 VarStoreHeader
->Format
== 0xff &&
313 VarStoreHeader
->State
== 0xff
326 IN VARIABLE_HEADER
*Variable
332 This code gets the pointer to the variable data.
336 Variable Pointer to the Variable Header.
340 UINT8* Pointer to Variable Data
345 // Be careful about pad size for alignment
347 return (UINT8
*) ((UINTN
) GET_VARIABLE_NAME_PTR (Variable
) + Variable
->NameSize
+ GET_PAD_SIZE (Variable
->NameSize
));
354 IN VARIABLE_HEADER
*Variable
360 This code gets the pointer to the next variable header.
364 Variable Pointer to the Variable Header.
368 VARIABLE_HEADER* Pointer to next variable header.
372 if (!IsValidVariableHeader (Variable
)) {
376 // Be careful about pad size for alignment
378 return (VARIABLE_HEADER
*) ((UINTN
) GetVariableDataPtr (Variable
) + Variable
->DataSize
+ GET_PAD_SIZE (Variable
->DataSize
));
385 IN VARIABLE_STORE_HEADER
*VarStoreHeader
391 This code gets the pointer to the last variable memory pointer byte
395 VarStoreHeader Pointer to the Variable Store Header.
399 VARIABLE_HEADER* Pointer to last unavailable Variable Header
404 // The end of variable store
406 return (VARIABLE_HEADER
*) ((UINTN
) VarStoreHeader
+ VarStoreHeader
->Size
);
413 IN EFI_PHYSICAL_ADDRESS VariableBase
,
414 OUT UINTN
*LastVariableOffset
,
415 IN BOOLEAN IsVolatile
421 Variable store garbage collection and reclaim operation
425 VariableBase Base address of variable store
426 LastVariableOffset Offset of last variable
427 IsVolatile The variable store is volatile or not,
428 if it is non-volatile, need FTW
436 VARIABLE_HEADER
*Variable
;
437 VARIABLE_HEADER
*NextVariable
;
438 VARIABLE_STORE_HEADER
*VariableStoreHeader
;
440 UINTN ValidBufferSize
;
445 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) ((UINTN
) VariableBase
);
448 // Start Pointers for the variable.
450 Variable
= (VARIABLE_HEADER
*) (VariableStoreHeader
+ 1);
452 ValidBufferSize
= sizeof (VARIABLE_STORE_HEADER
);
454 while (IsValidVariableHeader (Variable
)) {
455 NextVariable
= GetNextVariablePtr (Variable
);
456 if (Variable
->State
== VAR_ADDED
) {
457 VariableSize
= (UINTN
) NextVariable
- (UINTN
) Variable
;
458 ValidBufferSize
+= VariableSize
;
461 Variable
= NextVariable
;
464 Status
= gBS
->AllocatePool (
467 (VOID
**) &ValidBuffer
469 if (EFI_ERROR (Status
)) {
473 SetMem (ValidBuffer
, ValidBufferSize
, 0xff);
475 CurrPtr
= ValidBuffer
;
478 // Copy variable store header
480 CopyMem (CurrPtr
, VariableStoreHeader
, sizeof (VARIABLE_STORE_HEADER
));
481 CurrPtr
+= sizeof (VARIABLE_STORE_HEADER
);
484 // Start Pointers for the variable.
486 Variable
= (VARIABLE_HEADER
*) (VariableStoreHeader
+ 1);
488 while (IsValidVariableHeader (Variable
)) {
489 NextVariable
= GetNextVariablePtr (Variable
);
490 if (Variable
->State
== VAR_ADDED
) {
491 VariableSize
= (UINTN
) NextVariable
- (UINTN
) Variable
;
492 CopyMem (CurrPtr
, (UINT8
*) Variable
, VariableSize
);
493 CurrPtr
+= VariableSize
;
496 Variable
= NextVariable
;
501 // If volatile variable store, just copy valid buffer
503 SetMem ((UINT8
*) (UINTN
) VariableBase
, VariableStoreHeader
->Size
, 0xff);
504 CopyMem ((UINT8
*) (UINTN
) VariableBase
, ValidBuffer
, ValidBufferSize
);
505 *LastVariableOffset
= ValidBufferSize
;
506 Status
= EFI_SUCCESS
;
509 // If non-volatile variable store, perform FTW here.
511 Status
= FtwVariableSpace (
516 if (!EFI_ERROR (Status
)) {
517 *LastVariableOffset
= ValidBufferSize
;
521 gBS
->FreePool (ValidBuffer
);
523 if (EFI_ERROR (Status
)) {
524 *LastVariableOffset
= 0;
534 IN CHAR16
*VariableName
,
535 IN EFI_GUID
*VendorGuid
,
536 OUT VARIABLE_POINTER_TRACK
*PtrTrack
,
537 IN VARIABLE_GLOBAL
*Global
543 This code finds variable in storage blocks (Volatile or Non-Volatile)
547 VariableName Name of the variable to be found
548 VendorGuid Vendor GUID to be found.
549 PtrTrack Variable Track Pointer structure that contains
550 Variable Information.
551 Contains the pointer of Variable header.
552 Global VARIABLE_GLOBAL pointer
560 VARIABLE_HEADER
*Variable
[2];
561 VARIABLE_STORE_HEADER
*VariableStoreHeader
[2];
565 // We aquire the lock at the entry of FindVariable as GetVariable, GetNextVariableName
566 // SetVariable all call FindVariable at entry point. Please move "Aquire Lock" to
567 // the correct places if this assumption does not hold TRUE anymore.
569 AcquireLockOnlyAtBootTime(&Global
->VariableServicesLock
);
572 // 0: Non-Volatile, 1: Volatile
574 VariableStoreHeader
[0] = (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->NonVolatileVariableBase
);
575 VariableStoreHeader
[1] = (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->VolatileVariableBase
);
578 // Start Pointers for the variable.
579 // Actual Data Pointer where data can be written.
581 Variable
[0] = (VARIABLE_HEADER
*) (VariableStoreHeader
[0] + 1);
582 Variable
[1] = (VARIABLE_HEADER
*) (VariableStoreHeader
[1] + 1);
584 if (VariableName
[0] != 0 && VendorGuid
== NULL
) {
585 return EFI_INVALID_PARAMETER
;
588 // Find the variable by walk through non-volatile and volatile variable store
590 for (Index
= 0; Index
< 2; Index
++) {
591 PtrTrack
->StartPtr
= (VARIABLE_HEADER
*) (VariableStoreHeader
[Index
] + 1);
592 PtrTrack
->EndPtr
= GetEndPointer (VariableStoreHeader
[Index
]);
594 while (IsValidVariableHeader (Variable
[Index
]) && (Variable
[Index
] <= GetEndPointer (VariableStoreHeader
[Index
]))) {
595 if (Variable
[Index
]->State
== VAR_ADDED
) {
596 if (!(EfiAtRuntime () && !(Variable
[Index
]->Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
))) {
597 if (VariableName
[0] == 0) {
598 PtrTrack
->CurrPtr
= Variable
[Index
];
599 PtrTrack
->Volatile
= (BOOLEAN
) Index
;
602 if (CompareGuid (VendorGuid
, &Variable
[Index
]->VendorGuid
)) {
603 if (!CompareMem (VariableName
, GET_VARIABLE_NAME_PTR (Variable
[Index
]), ArrayLength (VariableName
))) {
604 PtrTrack
->CurrPtr
= Variable
[Index
];
605 PtrTrack
->Volatile
= (BOOLEAN
) Index
;
613 Variable
[Index
] = GetNextVariablePtr (Variable
[Index
]);
622 PtrTrack
->CurrPtr
= NULL
;
623 return EFI_NOT_FOUND
;
629 IN CHAR16
*VariableName
,
630 IN EFI_GUID
* VendorGuid
,
631 OUT UINT32
*Attributes OPTIONAL
,
632 IN OUT UINTN
*DataSize
,
634 IN VARIABLE_GLOBAL
* Global
,
641 This code finds variable in storage blocks (Volatile or Non-Volatile)
645 VariableName Name of Variable to be found
646 VendorGuid Variable vendor GUID
647 Attributes OPTIONAL Attribute value of the variable found
648 DataSize Size of Data found. If size is less than the
649 data, this value contains the required size.
651 Global Pointer to VARIABLE_GLOBAL structure
652 Instance Instance of the Firmware Volume.
660 VARIABLE_POINTER_TRACK Variable
;
664 if (VariableName
== NULL
|| VendorGuid
== NULL
|| DataSize
== NULL
) {
665 return EFI_INVALID_PARAMETER
;
668 // Find existing variable
670 Status
= FindVariable (VariableName
, VendorGuid
, &Variable
, Global
);
672 if (Variable
.CurrPtr
== NULL
|| EFI_ERROR (Status
)) {
678 VarDataSize
= Variable
.CurrPtr
->DataSize
;
679 if (*DataSize
>= VarDataSize
) {
681 Status
= EFI_INVALID_PARAMETER
;
685 CopyMem (Data
, GetVariableDataPtr (Variable
.CurrPtr
), VarDataSize
);
686 if (Attributes
!= NULL
) {
687 *Attributes
= Variable
.CurrPtr
->Attributes
;
690 *DataSize
= VarDataSize
;
691 Status
= EFI_SUCCESS
;
694 *DataSize
= VarDataSize
;
695 Status
= EFI_BUFFER_TOO_SMALL
;
700 ReleaseLockOnlyAtBootTime (&Global
->VariableServicesLock
);
706 GetNextVariableName (
707 IN OUT UINTN
*VariableNameSize
,
708 IN OUT CHAR16
*VariableName
,
709 IN OUT EFI_GUID
*VendorGuid
,
710 IN VARIABLE_GLOBAL
*Global
,
717 This code Finds the Next available variable
721 VariableNameSize Size of the variable
722 VariableName Pointer to variable name
723 VendorGuid Variable Vendor Guid
724 Global VARIABLE_GLOBAL structure pointer.
733 VARIABLE_POINTER_TRACK Variable
;
737 if (VariableNameSize
== NULL
|| VariableName
== NULL
|| VendorGuid
== NULL
) {
738 return EFI_INVALID_PARAMETER
;
741 Status
= FindVariable (VariableName
, VendorGuid
, &Variable
, Global
);
743 if (Variable
.CurrPtr
== NULL
|| EFI_ERROR (Status
)) {
747 if (VariableName
[0] != 0) {
749 // If variable name is not NULL, get next variable
751 Variable
.CurrPtr
= GetNextVariablePtr (Variable
.CurrPtr
);
756 // If both volatile and non-volatile variable store are parsed,
759 if (Variable
.CurrPtr
>= Variable
.EndPtr
|| Variable
.CurrPtr
== NULL
) {
760 Variable
.Volatile
= (BOOLEAN
) (Variable
.Volatile
^ ((BOOLEAN
) 0x1));
761 if (Variable
.Volatile
) {
762 Variable
.StartPtr
= (VARIABLE_HEADER
*) ((UINTN
) (Global
->VolatileVariableBase
+ sizeof (VARIABLE_STORE_HEADER
)));
763 Variable
.EndPtr
= (VARIABLE_HEADER
*) GetEndPointer ((VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->VolatileVariableBase
));
765 Status
= EFI_NOT_FOUND
;
769 Variable
.CurrPtr
= Variable
.StartPtr
;
770 if (!IsValidVariableHeader (Variable
.CurrPtr
)) {
777 if (IsValidVariableHeader (Variable
.CurrPtr
) && Variable
.CurrPtr
->State
== VAR_ADDED
) {
778 if (!(EfiAtRuntime () && !(Variable
.CurrPtr
->Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
))) {
779 VarNameSize
= Variable
.CurrPtr
->NameSize
;
780 if (VarNameSize
<= *VariableNameSize
) {
783 GET_VARIABLE_NAME_PTR (Variable
.CurrPtr
),
788 &Variable
.CurrPtr
->VendorGuid
,
791 Status
= EFI_SUCCESS
;
793 Status
= EFI_BUFFER_TOO_SMALL
;
796 *VariableNameSize
= VarNameSize
;
801 Variable
.CurrPtr
= GetNextVariablePtr (Variable
.CurrPtr
);
805 ReleaseLockOnlyAtBootTime (&Global
->VariableServicesLock
);
812 IN CHAR16
*VariableName
,
813 IN EFI_GUID
*VendorGuid
,
814 IN UINT32 Attributes
,
817 IN VARIABLE_GLOBAL
*Global
,
818 IN UINTN
*VolatileOffset
,
819 IN UINTN
*NonVolatileOffset
,
826 This code sets variable in storage blocks (Volatile or Non-Volatile)
830 VariableName Name of Variable to be found
831 VendorGuid Variable vendor GUID
832 Attributes Attribute value of the variable found
833 DataSize Size of Data found. If size is less than the
834 data, this value contains the required size.
836 Global Pointer to VARIABLE_GLOBAL structure
837 VolatileOffset The offset of last volatile variable
838 NonVolatileOffset The offset of last non-volatile variable
839 Instance Instance of the Firmware Volume.
844 EFI_INVALID_PARAMETER - Invalid parameter
845 EFI_SUCCESS - Set successfully
846 EFI_OUT_OF_RESOURCES - Resource not enough to set variable
847 EFI_NOT_FOUND - Not found
851 VARIABLE_POINTER_TRACK Variable
;
853 VARIABLE_HEADER
*NextVariable
;
863 if (VariableName
== NULL
|| VariableName
[0] == 0 || VendorGuid
== NULL
) {
864 return EFI_INVALID_PARAMETER
;
867 Status
= FindVariable (VariableName
, VendorGuid
, &Variable
, Global
);
869 if (Status
== EFI_INVALID_PARAMETER
) {
871 } else if (!EFI_ERROR (Status
) && Variable
.Volatile
&& EfiAtRuntime()) {
873 // If EfiAtRuntime and the variable is Volatile and Runtime Access,
874 // the volatile is ReadOnly, and SetVariable should be aborted and
875 // return EFI_WRITE_PROTECTED.
877 Status
= EFI_WRITE_PROTECTED
;
879 } else if (sizeof (VARIABLE_HEADER
) + ArrayLength (VariableName
) + DataSize
> MAX_VARIABLE_SIZE
) {
881 // The size of the VariableName, including the Unicode Null in bytes plus
882 // the DataSize is limited to maximum size of MAX_VARIABLE_SIZE (1024) bytes.
884 Status
= EFI_INVALID_PARAMETER
;
886 } else if (Attributes
== EFI_VARIABLE_NON_VOLATILE
) {
888 // Make sure not only EFI_VARIABLE_NON_VOLATILE is set
890 Status
= EFI_INVALID_PARAMETER
;
892 } else if ((Attributes
& (EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
)) ==
893 EFI_VARIABLE_RUNTIME_ACCESS
) {
895 // Make sure if runtime bit is set, boot service bit is set also
897 Status
= EFI_INVALID_PARAMETER
;
899 } else if (EfiAtRuntime () && Attributes
&& !(Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
)) {
901 // Runtime but Attribute is not Runtime
903 Status
= EFI_INVALID_PARAMETER
;
905 } else if (EfiAtRuntime () && Attributes
&& !(Attributes
& EFI_VARIABLE_NON_VOLATILE
)) {
907 // Cannot set volatile variable in Runtime
909 Status
= EFI_INVALID_PARAMETER
;
911 } else if (DataSize
== 0 || (Attributes
& (EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
)) == 0) {
913 // Setting a data variable with no access, or zero DataSize attributes
914 // specified causes it to be deleted.
916 if (!EFI_ERROR (Status
)) {
917 State
= Variable
.CurrPtr
->State
;
918 State
&= VAR_DELETED
;
920 Status
= UpdateVariableStore (
925 (UINTN
) &Variable
.CurrPtr
->State
,
929 if (EFI_ERROR (Status
)) {
933 Status
= EFI_SUCCESS
;
937 Status
= EFI_NOT_FOUND
;
940 if (!EFI_ERROR (Status
)) {
942 // If the variable is marked valid and the same data has been passed in
943 // then return to the caller immediately.
945 if (Variable
.CurrPtr
->DataSize
== DataSize
&&
946 !CompareMem (Data
, GetVariableDataPtr (Variable
.CurrPtr
), DataSize
)
948 Status
= EFI_SUCCESS
;
950 } else if (Variable
.CurrPtr
->State
== VAR_ADDED
) {
952 // Mark the old variable as in delete transition
954 State
= Variable
.CurrPtr
->State
;
955 State
&= VAR_IN_DELETED_TRANSITION
;
957 Status
= UpdateVariableStore (
962 (UINTN
) &Variable
.CurrPtr
->State
,
966 if (EFI_ERROR (Status
)) {
972 // Create a new variable and copy the data.
974 // Tricky part: Use scratch data area at the end of volatile variable store
975 // as a temporary storage.
977 NextVariable
= GetEndPointer ((VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->VolatileVariableBase
));
979 SetMem (NextVariable
, SCRATCH_SIZE
, 0xff);
981 NextVariable
->StartId
= VARIABLE_DATA
;
982 NextVariable
->Attributes
= Attributes
;
984 // NextVariable->State = VAR_ADDED;
986 NextVariable
->Reserved
= 0;
987 VarNameOffset
= sizeof (VARIABLE_HEADER
);
988 VarNameSize
= ArrayLength (VariableName
);
990 (UINT8
*) ((UINTN
) NextVariable
+ VarNameOffset
),
994 VarDataOffset
= VarNameOffset
+ VarNameSize
+ GET_PAD_SIZE (VarNameSize
);
996 (UINT8
*) ((UINTN
) NextVariable
+ VarDataOffset
),
1000 CopyMem (&NextVariable
->VendorGuid
, VendorGuid
, sizeof (EFI_GUID
));
1002 // There will be pad bytes after Data, the NextVariable->NameSize and
1003 // NextVariable->DataSize should not include pad size so that variable
1004 // service can get actual size in GetVariable
1006 NextVariable
->NameSize
= (UINT32
)VarNameSize
;
1007 NextVariable
->DataSize
= (UINT32
)DataSize
;
1010 // The actual size of the variable that stores in storage should
1011 // include pad size.
1013 VarSize
= VarDataOffset
+ DataSize
+ GET_PAD_SIZE (DataSize
);
1014 if (Attributes
& EFI_VARIABLE_NON_VOLATILE
) {
1015 if ((UINT32
) (VarSize
+*NonVolatileOffset
) >
1016 ((VARIABLE_STORE_HEADER
*) ((UINTN
) (Global
->NonVolatileVariableBase
)))->Size
1018 if (EfiAtRuntime ()) {
1019 Status
= EFI_OUT_OF_RESOURCES
;
1023 // Perform garbage collection & reclaim operation
1025 Status
= Reclaim (Global
->NonVolatileVariableBase
, NonVolatileOffset
, FALSE
);
1026 if (EFI_ERROR (Status
)) {
1030 // If still no enough space, return out of resources
1032 if ((UINT32
) (VarSize
+*NonVolatileOffset
) >
1033 ((VARIABLE_STORE_HEADER
*) ((UINTN
) (Global
->NonVolatileVariableBase
)))->Size
1035 Status
= EFI_OUT_OF_RESOURCES
;
1043 // 1. Write variable header
1044 // 2. Write variable data
1045 // 3. Set variable state to valid
1050 Status
= UpdateVariableStore (
1056 sizeof (VARIABLE_HEADER
),
1057 (UINT8
*) NextVariable
1060 if (EFI_ERROR (Status
)) {
1066 Status
= UpdateVariableStore (
1071 *NonVolatileOffset
+ sizeof (VARIABLE_HEADER
),
1072 (UINT32
) VarSize
- sizeof (VARIABLE_HEADER
),
1073 (UINT8
*) NextVariable
+ sizeof (VARIABLE_HEADER
)
1076 if (EFI_ERROR (Status
)) {
1082 NextVariable
->State
= VAR_ADDED
;
1083 Status
= UpdateVariableStore (
1089 sizeof (VARIABLE_HEADER
),
1090 (UINT8
*) NextVariable
1093 if (EFI_ERROR (Status
)) {
1097 *NonVolatileOffset
= *NonVolatileOffset
+ VarSize
;
1100 if (EfiAtRuntime ()) {
1101 Status
= EFI_INVALID_PARAMETER
;
1105 if ((UINT32
) (VarSize
+*VolatileOffset
) >
1106 ((VARIABLE_STORE_HEADER
*) ((UINTN
) (Global
->VolatileVariableBase
)))->Size
1109 // Perform garbage collection & reclaim operation
1111 Status
= Reclaim (Global
->VolatileVariableBase
, VolatileOffset
, TRUE
);
1112 if (EFI_ERROR (Status
)) {
1116 // If still no enough space, return out of resources
1118 if ((UINT32
) (VarSize
+*VolatileOffset
) >
1119 ((VARIABLE_STORE_HEADER
*) ((UINTN
) (Global
->VolatileVariableBase
)))->Size
1121 Status
= EFI_OUT_OF_RESOURCES
;
1128 NextVariable
->State
= VAR_ADDED
;
1129 Status
= UpdateVariableStore (
1136 (UINT8
*) NextVariable
1139 if (EFI_ERROR (Status
)) {
1143 *VolatileOffset
= *VolatileOffset
+ VarSize
;
1146 // Mark the old variable as deleted
1148 if (!Reclaimed
&& !EFI_ERROR (Status
) && Variable
.CurrPtr
!= NULL
) {
1149 State
= Variable
.CurrPtr
->State
;
1150 State
&= VAR_DELETED
;
1152 Status
= UpdateVariableStore (
1157 (UINTN
) &Variable
.CurrPtr
->State
,
1162 if (EFI_ERROR (Status
)) {
1168 Status
= EFI_SUCCESS
;
1170 ReleaseLockOnlyAtBootTime (&Global
->VariableServicesLock
);
1174 #if (EFI_SPECIFICATION_VERSION >= 0x00020000)
1178 IN UINT32 Attributes
,
1179 OUT UINT64
*MaximumVariableStorageSize
,
1180 OUT UINT64
*RemainingVariableStorageSize
,
1181 OUT UINT64
*MaximumVariableSize
,
1182 IN VARIABLE_GLOBAL
*Global
,
1187 Routine Description:
1189 This code returns information about the EFI variables.
1193 Attributes Attributes bitmask to specify the type of variables
1194 on which to return information.
1195 MaximumVariableStorageSize Pointer to the maximum size of the storage space available
1196 for the EFI variables associated with the attributes specified.
1197 RemainingVariableStorageSize Pointer to the remaining size of the storage space available
1198 for the EFI variables associated with the attributes specified.
1199 MaximumVariableSize Pointer to the maximum size of the individual EFI variables
1200 associated with the attributes specified.
1201 Global Pointer to VARIABLE_GLOBAL structure.
1202 Instance Instance of the Firmware Volume.
1207 EFI_INVALID_PARAMETER - An invalid combination of attribute bits was supplied.
1208 EFI_SUCCESS - Query successfully.
1209 EFI_UNSUPPORTED - The attribute is not supported on this platform.
1213 VARIABLE_HEADER
*Variable
;
1214 VARIABLE_HEADER
*NextVariable
;
1215 UINT64 VariableSize
;
1216 VARIABLE_STORE_HEADER
*VariableStoreHeader
;
1218 if(MaximumVariableStorageSize
== NULL
|| RemainingVariableStorageSize
== NULL
|| MaximumVariableSize
== NULL
) {
1219 return EFI_INVALID_PARAMETER
;
1222 if((Attributes
& (EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
)) == 0) {
1224 // Make sure the Attributes combination is supported by the platform.
1226 return EFI_UNSUPPORTED
;
1227 } else if ((Attributes
& (EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
)) == EFI_VARIABLE_RUNTIME_ACCESS
) {
1229 // Make sure if runtime bit is set, boot service bit is set also.
1231 return EFI_INVALID_PARAMETER
;
1232 } else if (EfiAtRuntime () && !(Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
)) {
1234 // Make sure RT Attribute is set if we are in Runtime phase.
1236 return EFI_INVALID_PARAMETER
;
1239 AcquireLockOnlyAtBootTime(&Global
->VariableServicesLock
);
1241 if((Attributes
& EFI_VARIABLE_NON_VOLATILE
) == 0) {
1243 // Query is Volatile related.
1245 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->VolatileVariableBase
);
1248 // Query is Non-Volatile related.
1250 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->NonVolatileVariableBase
);
1254 // Now let's fill *MaximumVariableStorageSize *RemainingVariableStorageSize
1255 // with the storage size (excluding the storage header size).
1257 *MaximumVariableStorageSize
= VariableStoreHeader
->Size
- sizeof (VARIABLE_STORE_HEADER
);
1258 *RemainingVariableStorageSize
= VariableStoreHeader
->Size
- sizeof (VARIABLE_STORE_HEADER
);
1261 // Let *MaximumVariableSize be MAX_VARIABLE_SIZE.
1263 *MaximumVariableSize
= MAX_VARIABLE_SIZE
;
1266 // Point to the starting address of the variables.
1268 Variable
= (VARIABLE_HEADER
*) (VariableStoreHeader
+ 1);
1271 // Now walk through the related variable store.
1273 while (IsValidVariableHeader (Variable
) && (Variable
< GetEndPointer (VariableStoreHeader
))) {
1274 NextVariable
= GetNextVariablePtr (Variable
);
1275 VariableSize
= (UINT64
) (UINTN
) NextVariable
- (UINT64
) (UINTN
) Variable
;
1277 if (EfiAtRuntime ()) {
1279 // we don't take the state of the variables in mind
1280 // when calculating RemainingVariableStorageSize,
1281 // since the space occupied by variables not marked with
1282 // VAR_ADDED is not allowed to be reclaimed in Runtime.
1284 *RemainingVariableStorageSize
-= VariableSize
;
1287 // Only care about Variables with State VAR_ADDED,because
1288 // the space not marked as VAR_ADDED is reclaimable now.
1290 if (Variable
->State
== VAR_ADDED
) {
1291 *RemainingVariableStorageSize
-= VariableSize
;
1296 // Go to the next one
1298 Variable
= NextVariable
;
1301 ReleaseLockOnlyAtBootTime (&Global
->VariableServicesLock
);
1308 VariableCommonInitialize (
1309 IN EFI_HANDLE ImageHandle
,
1310 IN EFI_SYSTEM_TABLE
*SystemTable
1314 Routine Description:
1315 This function does common initialization for variable services
1319 ImageHandle - The firmware allocated handle for the EFI image.
1320 SystemTable - A pointer to the EFI System Table.
1326 EFI_NOT_FOUND - Variable store area not found.
1327 EFI_UNSUPPORTED - Currently only one non-volatile variable store is supported.
1328 EFI_SUCCESS - Variable services successfully initialized.
1333 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
1335 VARIABLE_STORE_HEADER
*VolatileVariableStore
;
1336 VARIABLE_STORE_HEADER
*VariableStoreHeader
;
1337 VARIABLE_HEADER
*NextVariable
;
1339 EFI_PHYSICAL_ADDRESS FvVolHdr
;
1341 UINT64 TempVariableStoreHeader
;
1343 EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor
;
1344 EFI_FLASH_SUBAREA_ENTRY VariableStoreEntry
;
1350 Status
= gBS
->AllocatePool (
1351 EfiRuntimeServicesData
,
1352 sizeof (ESAL_VARIABLE_GLOBAL
),
1353 (VOID
**) &mVariableModuleGlobal
1356 if (EFI_ERROR (Status
)) {
1360 EfiInitializeLock(&mVariableModuleGlobal
->VariableGlobal
[Physical
].VariableServicesLock
, EFI_TPL_CALLBACK
);
1363 // Allocate memory for volatile variable store
1365 Status
= gBS
->AllocatePool (
1366 EfiRuntimeServicesData
,
1367 VARIABLE_STORE_SIZE
+ SCRATCH_SIZE
,
1368 (VOID
**) &VolatileVariableStore
1371 if (EFI_ERROR (Status
)) {
1372 gBS
->FreePool (mVariableModuleGlobal
);
1376 SetMem (VolatileVariableStore
, VARIABLE_STORE_SIZE
+ SCRATCH_SIZE
, 0xff);
1379 // Variable Specific Data
1381 mVariableModuleGlobal
->VariableGlobal
[Physical
].VolatileVariableBase
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) VolatileVariableStore
;
1382 mVariableModuleGlobal
->VolatileLastVariableOffset
= sizeof (VARIABLE_STORE_HEADER
);
1384 VolatileVariableStore
->Signature
= VARIABLE_STORE_SIGNATURE
;
1385 VolatileVariableStore
->Size
= VARIABLE_STORE_SIZE
;
1386 VolatileVariableStore
->Format
= VARIABLE_STORE_FORMATTED
;
1387 VolatileVariableStore
->State
= VARIABLE_STORE_HEALTHY
;
1388 VolatileVariableStore
->Reserved
= 0;
1389 VolatileVariableStore
->Reserved1
= 0;
1392 // Get non volatile varaible store
1395 TempVariableStoreHeader
= (UINT64
) PcdGet32 (PcdFlashNvStorageVariableBase
);
1396 VariableStoreEntry
.Base
= TempVariableStoreHeader
+ \
1397 (((EFI_FIRMWARE_VOLUME_HEADER
*) (UINTN
) (TempVariableStoreHeader
)) -> HeaderLength
);
1398 VariableStoreEntry
.Length
= (UINT64
) PcdGet32 (PcdFlashNvStorageVariableSize
) - \
1399 (((EFI_FIRMWARE_VOLUME_HEADER
*) (UINTN
) (TempVariableStoreHeader
)) -> HeaderLength
);
1401 // Mark the variable storage region of the FLASH as RUNTIME
1403 BaseAddress
= VariableStoreEntry
.Base
& (~EFI_PAGE_MASK
);
1404 Length
= VariableStoreEntry
.Length
+ (VariableStoreEntry
.Base
- BaseAddress
);
1405 Length
= (Length
+ EFI_PAGE_SIZE
- 1) & (~EFI_PAGE_MASK
);
1407 Status
= gDS
->GetMemorySpaceDescriptor (BaseAddress
, &GcdDescriptor
);
1408 if (EFI_ERROR (Status
)) {
1409 gBS
->FreePool (mVariableModuleGlobal
);
1410 gBS
->FreePool (VolatileVariableStore
);
1411 return EFI_UNSUPPORTED
;
1414 Status
= gDS
->SetMemorySpaceAttributes (
1417 GcdDescriptor
.Attributes
| EFI_MEMORY_RUNTIME
1419 if (EFI_ERROR (Status
)) {
1420 gBS
->FreePool (mVariableModuleGlobal
);
1421 gBS
->FreePool (VolatileVariableStore
);
1422 return EFI_UNSUPPORTED
;
1425 // Get address of non volatile variable store base
1427 mVariableModuleGlobal
->VariableGlobal
[Physical
].NonVolatileVariableBase
= VariableStoreEntry
.Base
;
1433 // Find the Correct Instance of the FV Block Service.
1436 CurrPtr
= (CHAR8
*) ((UINTN
) mVariableModuleGlobal
->VariableGlobal
[Physical
].NonVolatileVariableBase
);
1437 while (EfiFvbGetPhysicalAddress (Instance
, &FvVolHdr
) == EFI_SUCCESS
) {
1438 FwVolHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) ((UINTN
) FvVolHdr
);
1439 if (CurrPtr
>= (CHAR8
*) FwVolHeader
&& CurrPtr
< (((CHAR8
*) FwVolHeader
) + FwVolHeader
->FvLength
)) {
1440 mVariableModuleGlobal
->FvbInstance
= Instance
;
1447 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) CurrPtr
;
1448 if (GetVariableStoreStatus (VariableStoreHeader
) == EfiValid
) {
1449 if (~VariableStoreHeader
->Size
== 0) {
1450 Status
= UpdateVariableStore (
1451 &mVariableModuleGlobal
->VariableGlobal
[Physical
],
1454 mVariableModuleGlobal
->FvbInstance
,
1455 (UINTN
) &VariableStoreHeader
->Size
,
1457 (UINT8
*) &VariableStoreEntry
.Length
1460 if (EFI_ERROR (Status
)) {
1465 mVariableModuleGlobal
->VariableGlobal
[Physical
].NonVolatileVariableBase
= (EFI_PHYSICAL_ADDRESS
) ((UINTN
) CurrPtr
);
1467 // Parse non-volatile variable data and get last variable offset
1469 NextVariable
= (VARIABLE_HEADER
*) (CurrPtr
+ sizeof (VARIABLE_STORE_HEADER
));
1470 Status
= EFI_SUCCESS
;
1472 while (IsValidVariableHeader (NextVariable
)) {
1473 NextVariable
= GetNextVariablePtr (NextVariable
);
1476 mVariableModuleGlobal
->NonVolatileLastVariableOffset
= (UINTN
) NextVariable
- (UINTN
) CurrPtr
;
1479 // Check if the free area is blow a threshold
1481 if ((((VARIABLE_STORE_HEADER
*)((UINTN
) CurrPtr
))->Size
- mVariableModuleGlobal
->NonVolatileLastVariableOffset
) < VARIABLE_RECLAIM_THRESHOLD
) {
1483 mVariableModuleGlobal
->VariableGlobal
[Physical
].NonVolatileVariableBase
,
1484 &mVariableModuleGlobal
->NonVolatileLastVariableOffset
,
1489 if (EFI_ERROR (Status
)) {
1490 gBS
->FreePool (mVariableModuleGlobal
);
1491 gBS
->FreePool (VolatileVariableStore
);
1496 // Check if the free area is really free.
1498 for (Index
= mVariableModuleGlobal
->NonVolatileLastVariableOffset
; Index
< VariableStoreHeader
->Size
; Index
++) {
1499 Data
= ((UINT8
*) (UINTN
) mVariableModuleGlobal
->VariableGlobal
[Physical
].NonVolatileVariableBase
)[Index
];
1502 // There must be something wrong in variable store, do reclaim operation.
1505 mVariableModuleGlobal
->VariableGlobal
[Physical
].NonVolatileVariableBase
,
1506 &mVariableModuleGlobal
->NonVolatileLastVariableOffset
,
1514 if (EFI_ERROR (Status
)) {
1515 gBS
->FreePool (mVariableModuleGlobal
);
1516 gBS
->FreePool (VolatileVariableStore
);