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 #include <Common/FlashMap.h>
29 // Don't use module globals after the SetVirtualAddress map is signaled
31 ESAL_VARIABLE_GLOBAL
*mVariableModuleGlobal
;
34 // This is a temperary function which will be removed
35 // when EfiAcquireLock in UefiLib can handle the
36 // the call in UEFI Runtimer driver in RT phase.
40 AcquireLockOnlyAtBootTime (
44 if (!EfiAtRuntime ()) {
45 EfiAcquireLock (Lock
);
50 // This is a temperary function which will be removed
51 // when EfiAcquireLock in UefiLib can handle the
52 // the call in UEFI Runtimer driver in RT phase.
56 ReleaseLockOnlyAtBootTime (
60 if (!EfiAtRuntime ()) {
61 EfiReleaseLock (Lock
);
68 IsValidVariableHeader (
69 IN VARIABLE_HEADER
*Variable
75 This code checks if variable header is valid or not.
78 Variable Pointer to the Variable Header.
81 TRUE Variable header is valid.
82 FALSE Variable header is not valid.
86 if (Variable
== NULL
||
87 Variable
->StartId
!= VARIABLE_DATA
||
88 (sizeof (VARIABLE_HEADER
) + Variable
->NameSize
+ Variable
->DataSize
) > MAX_VARIABLE_SIZE
100 IN VARIABLE_GLOBAL
*Global
,
102 IN BOOLEAN SetByIndex
,
104 IN UINTN DataPtrIndex
,
112 This function writes data to the FWH at the correct LBA even if the LBAs
117 Global Pointer to VARAIBLE_GLOBAL structure
118 Volatile If the Variable is Volatile or Non-Volatile
119 SetByIndex TRUE: Target pointer is given as index
120 FALSE: Target pointer is absolute
121 Instance Instance of FV Block services
122 DataPtrIndex Pointer to the Data from the end of VARIABLE_STORE_HEADER
124 DataSize Size of data to be written.
125 Buffer Pointer to the buffer from which data is written
133 EFI_FV_BLOCK_MAP_ENTRY
*PtrBlockMapEntry
;
141 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
142 VARIABLE_STORE_HEADER
*VolatileBase
;
143 EFI_PHYSICAL_ADDRESS FvVolHdr
;
144 EFI_PHYSICAL_ADDRESS DataPtr
;
148 DataPtr
= DataPtrIndex
;
151 // Check if the Data is Volatile
154 EfiFvbGetPhysicalAddress (Instance
, &FvVolHdr
);
155 FwVolHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) ((UINTN
) FvVolHdr
);
157 // Data Pointer should point to the actual Address where data is to be
161 DataPtr
+= Global
->NonVolatileVariableBase
;
164 if ((DataPtr
+ DataSize
) >= ((EFI_PHYSICAL_ADDRESS
) (UINTN
) ((UINT8
*) FwVolHeader
+ FwVolHeader
->FvLength
))) {
165 return EFI_INVALID_PARAMETER
;
169 // Data Pointer should point to the actual Address where data is to be
172 VolatileBase
= (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->VolatileVariableBase
);
174 DataPtr
+= Global
->VolatileVariableBase
;
177 if ((DataPtr
+ DataSize
) >= ((UINTN
) ((UINT8
*) VolatileBase
+ VolatileBase
->Size
))) {
178 return EFI_INVALID_PARAMETER
;
182 // If Volatile Variable just do a simple mem copy.
185 CopyMem ((UINT8
*) ((UINTN
) DataPtr
), Buffer
, DataSize
);
189 // If we are here we are dealing with Non-Volatile Variables
191 LinearOffset
= (UINTN
) FwVolHeader
;
192 CurrWritePtr
= (UINTN
) DataPtr
;
193 CurrWriteSize
= DataSize
;
197 if (CurrWritePtr
< LinearOffset
) {
198 return EFI_INVALID_PARAMETER
;
201 for (PtrBlockMapEntry
= FwVolHeader
->BlockMap
; PtrBlockMapEntry
->NumBlocks
!= 0; PtrBlockMapEntry
++) {
202 for (BlockIndex2
= 0; BlockIndex2
< PtrBlockMapEntry
->NumBlocks
; BlockIndex2
++) {
204 // Check to see if the Variable Writes are spanning through multiple
207 if ((CurrWritePtr
>= LinearOffset
) && (CurrWritePtr
< LinearOffset
+ PtrBlockMapEntry
->Length
)) {
208 if ((CurrWritePtr
+ CurrWriteSize
) <= (LinearOffset
+ PtrBlockMapEntry
->Length
)) {
209 Status
= EfiFvbWriteBlock (
212 (UINTN
) (CurrWritePtr
- LinearOffset
),
216 if (EFI_ERROR (Status
)) {
220 Size
= (UINT32
) (LinearOffset
+ PtrBlockMapEntry
->Length
- CurrWritePtr
);
221 Status
= EfiFvbWriteBlock (
224 (UINTN
) (CurrWritePtr
- LinearOffset
),
228 if (EFI_ERROR (Status
)) {
232 CurrWritePtr
= LinearOffset
+ PtrBlockMapEntry
->Length
;
233 CurrBuffer
= CurrBuffer
+ Size
;
234 CurrWriteSize
= CurrWriteSize
- Size
;
238 LinearOffset
+= PtrBlockMapEntry
->Length
;
247 VARIABLE_STORE_STATUS
249 GetVariableStoreStatus (
250 IN VARIABLE_STORE_HEADER
*VarStoreHeader
256 This code gets the current status of Variable Store.
260 VarStoreHeader Pointer to the Variable Store Header.
264 EfiRaw Variable store status is raw
265 EfiValid Variable store status is valid
266 EfiInvalid Variable store status is invalid
270 if (VarStoreHeader
->Signature
== VARIABLE_STORE_SIGNATURE
&&
271 VarStoreHeader
->Format
== VARIABLE_STORE_FORMATTED
&&
272 VarStoreHeader
->State
== VARIABLE_STORE_HEALTHY
276 } else if (VarStoreHeader
->Signature
== 0xffffffff &&
277 VarStoreHeader
->Size
== 0xffffffff &&
278 VarStoreHeader
->Format
== 0xff &&
279 VarStoreHeader
->State
== 0xff
292 IN VARIABLE_HEADER
*Variable
298 This code gets the pointer to the variable data.
302 Variable Pointer to the Variable Header.
306 UINT8* Pointer to Variable Data
311 // Be careful about pad size for alignment
313 return (UINT8
*) ((UINTN
) GET_VARIABLE_NAME_PTR (Variable
) + Variable
->NameSize
+ GET_PAD_SIZE (Variable
->NameSize
));
320 IN VARIABLE_HEADER
*Variable
326 This code gets the pointer to the next variable header.
330 Variable Pointer to the Variable Header.
334 VARIABLE_HEADER* Pointer to next variable header.
338 if (!IsValidVariableHeader (Variable
)) {
342 // Be careful about pad size for alignment
344 return (VARIABLE_HEADER
*) ((UINTN
) GetVariableDataPtr (Variable
) + Variable
->DataSize
+ GET_PAD_SIZE (Variable
->DataSize
));
351 IN VARIABLE_STORE_HEADER
*VarStoreHeader
357 This code gets the pointer to the last variable memory pointer byte
361 VarStoreHeader Pointer to the Variable Store Header.
365 VARIABLE_HEADER* Pointer to last unavailable Variable Header
370 // The end of variable store
372 return (VARIABLE_HEADER
*) ((UINTN
) VarStoreHeader
+ VarStoreHeader
->Size
);
379 IN EFI_PHYSICAL_ADDRESS VariableBase
,
380 OUT UINTN
*LastVariableOffset
,
381 IN BOOLEAN IsVolatile
387 Variable store garbage collection and reclaim operation
391 VariableBase Base address of variable store
392 LastVariableOffset Offset of last variable
393 IsVolatile The variable store is volatile or not,
394 if it is non-volatile, need FTW
402 VARIABLE_HEADER
*Variable
;
403 VARIABLE_HEADER
*NextVariable
;
404 VARIABLE_STORE_HEADER
*VariableStoreHeader
;
406 UINTN ValidBufferSize
;
411 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) ((UINTN
) VariableBase
);
414 // Start Pointers for the variable.
416 Variable
= (VARIABLE_HEADER
*) (VariableStoreHeader
+ 1);
418 ValidBufferSize
= sizeof (VARIABLE_STORE_HEADER
);
420 while (IsValidVariableHeader (Variable
)) {
421 NextVariable
= GetNextVariablePtr (Variable
);
422 if (Variable
->State
== VAR_ADDED
) {
423 VariableSize
= (UINTN
) NextVariable
- (UINTN
) Variable
;
424 ValidBufferSize
+= VariableSize
;
427 Variable
= NextVariable
;
430 ValidBuffer
= AllocatePool (ValidBufferSize
);
431 if (ValidBuffer
== NULL
) {
432 return EFI_OUT_OF_RESOURCES
;
435 SetMem (ValidBuffer
, ValidBufferSize
, 0xff);
437 CurrPtr
= ValidBuffer
;
440 // Copy variable store header
442 CopyMem (CurrPtr
, VariableStoreHeader
, sizeof (VARIABLE_STORE_HEADER
));
443 CurrPtr
+= sizeof (VARIABLE_STORE_HEADER
);
446 // Start Pointers for the variable.
448 Variable
= (VARIABLE_HEADER
*) (VariableStoreHeader
+ 1);
450 while (IsValidVariableHeader (Variable
)) {
451 NextVariable
= GetNextVariablePtr (Variable
);
452 if (Variable
->State
== VAR_ADDED
) {
453 VariableSize
= (UINTN
) NextVariable
- (UINTN
) Variable
;
454 CopyMem (CurrPtr
, (UINT8
*) Variable
, VariableSize
);
455 CurrPtr
+= VariableSize
;
458 Variable
= NextVariable
;
463 // If volatile variable store, just copy valid buffer
465 SetMem ((UINT8
*) (UINTN
) VariableBase
, VariableStoreHeader
->Size
, 0xff);
466 CopyMem ((UINT8
*) (UINTN
) VariableBase
, ValidBuffer
, ValidBufferSize
);
467 *LastVariableOffset
= ValidBufferSize
;
468 Status
= EFI_SUCCESS
;
471 // If non-volatile variable store, perform FTW here.
473 Status
= FtwVariableSpace (
478 if (!EFI_ERROR (Status
)) {
479 *LastVariableOffset
= ValidBufferSize
;
483 FreePool (ValidBuffer
);
485 if (EFI_ERROR (Status
)) {
486 *LastVariableOffset
= 0;
496 IN CHAR16
*VariableName
,
497 IN EFI_GUID
*VendorGuid
,
498 OUT VARIABLE_POINTER_TRACK
*PtrTrack
,
499 IN VARIABLE_GLOBAL
*Global
505 This code finds variable in storage blocks (Volatile or Non-Volatile)
509 VariableName Name of the variable to be found
510 VendorGuid Vendor GUID to be found.
511 PtrTrack Variable Track Pointer structure that contains
512 Variable Information.
513 Contains the pointer of Variable header.
514 Global VARIABLE_GLOBAL pointer
522 VARIABLE_HEADER
*Variable
[2];
523 VARIABLE_STORE_HEADER
*VariableStoreHeader
[2];
527 // We aquire the lock at the entry of FindVariable as GetVariable, GetNextVariableName
528 // SetVariable all call FindVariable at entry point. Please move "Aquire Lock" to
529 // the correct places if this assumption does not hold TRUE anymore.
531 AcquireLockOnlyAtBootTime(&Global
->VariableServicesLock
);
534 // 0: Non-Volatile, 1: Volatile
536 VariableStoreHeader
[0] = (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->NonVolatileVariableBase
);
537 VariableStoreHeader
[1] = (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->VolatileVariableBase
);
540 // Start Pointers for the variable.
541 // Actual Data Pointer where data can be written.
543 Variable
[0] = (VARIABLE_HEADER
*) (VariableStoreHeader
[0] + 1);
544 Variable
[1] = (VARIABLE_HEADER
*) (VariableStoreHeader
[1] + 1);
546 if (VariableName
[0] != 0 && VendorGuid
== NULL
) {
547 return EFI_INVALID_PARAMETER
;
550 // Find the variable by walk through non-volatile and volatile variable store
552 for (Index
= 0; Index
< 2; Index
++) {
553 PtrTrack
->StartPtr
= (VARIABLE_HEADER
*) (VariableStoreHeader
[Index
] + 1);
554 PtrTrack
->EndPtr
= GetEndPointer (VariableStoreHeader
[Index
]);
556 while (IsValidVariableHeader (Variable
[Index
]) && (Variable
[Index
] <= GetEndPointer (VariableStoreHeader
[Index
]))) {
557 if (Variable
[Index
]->State
== VAR_ADDED
) {
558 if (!(EfiAtRuntime () && !(Variable
[Index
]->Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
))) {
559 if (VariableName
[0] == 0) {
560 PtrTrack
->CurrPtr
= Variable
[Index
];
561 PtrTrack
->Volatile
= (BOOLEAN
) Index
;
564 if (CompareGuid (VendorGuid
, &Variable
[Index
]->VendorGuid
)) {
565 if (!CompareMem (VariableName
, GET_VARIABLE_NAME_PTR (Variable
[Index
]), Variable
[Index
]->NameSize
)) {
566 PtrTrack
->CurrPtr
= Variable
[Index
];
567 PtrTrack
->Volatile
= (BOOLEAN
) Index
;
575 Variable
[Index
] = GetNextVariablePtr (Variable
[Index
]);
584 PtrTrack
->CurrPtr
= NULL
;
585 return EFI_NOT_FOUND
;
591 IN CHAR16
*VariableName
,
592 IN EFI_GUID
* VendorGuid
,
593 OUT UINT32
*Attributes OPTIONAL
,
594 IN OUT UINTN
*DataSize
,
596 IN VARIABLE_GLOBAL
* Global
,
603 This code finds variable in storage blocks (Volatile or Non-Volatile)
607 VariableName Name of Variable to be found
608 VendorGuid Variable vendor GUID
609 Attributes OPTIONAL Attribute value of the variable found
610 DataSize Size of Data found. If size is less than the
611 data, this value contains the required size.
613 Global Pointer to VARIABLE_GLOBAL structure
614 Instance Instance of the Firmware Volume.
622 VARIABLE_POINTER_TRACK Variable
;
626 if (VariableName
== NULL
|| VendorGuid
== NULL
|| DataSize
== NULL
) {
627 return EFI_INVALID_PARAMETER
;
630 // Find existing variable
632 Status
= FindVariable (VariableName
, VendorGuid
, &Variable
, Global
);
634 if (Variable
.CurrPtr
== NULL
|| EFI_ERROR (Status
)) {
640 VarDataSize
= Variable
.CurrPtr
->DataSize
;
641 if (*DataSize
>= VarDataSize
) {
643 Status
= EFI_INVALID_PARAMETER
;
647 CopyMem (Data
, GetVariableDataPtr (Variable
.CurrPtr
), VarDataSize
);
648 if (Attributes
!= NULL
) {
649 *Attributes
= Variable
.CurrPtr
->Attributes
;
652 *DataSize
= VarDataSize
;
653 Status
= EFI_SUCCESS
;
656 *DataSize
= VarDataSize
;
657 Status
= EFI_BUFFER_TOO_SMALL
;
662 ReleaseLockOnlyAtBootTime (&Global
->VariableServicesLock
);
668 GetNextVariableName (
669 IN OUT UINTN
*VariableNameSize
,
670 IN OUT CHAR16
*VariableName
,
671 IN OUT EFI_GUID
*VendorGuid
,
672 IN VARIABLE_GLOBAL
*Global
,
679 This code Finds the Next available variable
683 VariableNameSize Size of the variable
684 VariableName Pointer to variable name
685 VendorGuid Variable Vendor Guid
686 Global VARIABLE_GLOBAL structure pointer.
695 VARIABLE_POINTER_TRACK Variable
;
699 if (VariableNameSize
== NULL
|| VariableName
== NULL
|| VendorGuid
== NULL
) {
700 return EFI_INVALID_PARAMETER
;
703 Status
= FindVariable (VariableName
, VendorGuid
, &Variable
, Global
);
705 if (Variable
.CurrPtr
== NULL
|| EFI_ERROR (Status
)) {
709 if (VariableName
[0] != 0) {
711 // If variable name is not NULL, get next variable
713 Variable
.CurrPtr
= GetNextVariablePtr (Variable
.CurrPtr
);
718 // If both volatile and non-volatile variable store are parsed,
721 if (Variable
.CurrPtr
>= Variable
.EndPtr
|| Variable
.CurrPtr
== NULL
) {
722 Variable
.Volatile
= (BOOLEAN
) (Variable
.Volatile
^ ((BOOLEAN
) 0x1));
723 if (Variable
.Volatile
) {
724 Variable
.StartPtr
= (VARIABLE_HEADER
*) ((UINTN
) (Global
->VolatileVariableBase
+ sizeof (VARIABLE_STORE_HEADER
)));
725 Variable
.EndPtr
= (VARIABLE_HEADER
*) GetEndPointer ((VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->VolatileVariableBase
));
727 Status
= EFI_NOT_FOUND
;
731 Variable
.CurrPtr
= Variable
.StartPtr
;
732 if (!IsValidVariableHeader (Variable
.CurrPtr
)) {
739 if (IsValidVariableHeader (Variable
.CurrPtr
) && Variable
.CurrPtr
->State
== VAR_ADDED
) {
740 if (!(EfiAtRuntime () && !(Variable
.CurrPtr
->Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
))) {
741 VarNameSize
= Variable
.CurrPtr
->NameSize
;
742 if (VarNameSize
<= *VariableNameSize
) {
745 GET_VARIABLE_NAME_PTR (Variable
.CurrPtr
),
750 &Variable
.CurrPtr
->VendorGuid
,
753 Status
= EFI_SUCCESS
;
755 Status
= EFI_BUFFER_TOO_SMALL
;
758 *VariableNameSize
= VarNameSize
;
763 Variable
.CurrPtr
= GetNextVariablePtr (Variable
.CurrPtr
);
767 ReleaseLockOnlyAtBootTime (&Global
->VariableServicesLock
);
774 IN CHAR16
*VariableName
,
775 IN EFI_GUID
*VendorGuid
,
776 IN UINT32 Attributes
,
779 IN VARIABLE_GLOBAL
*Global
,
780 IN UINTN
*VolatileOffset
,
781 IN UINTN
*NonVolatileOffset
,
788 This code sets variable in storage blocks (Volatile or Non-Volatile)
792 VariableName Name of Variable to be found
793 VendorGuid Variable vendor GUID
794 Attributes Attribute value of the variable found
795 DataSize Size of Data found. If size is less than the
796 data, this value contains the required size.
798 Global Pointer to VARIABLE_GLOBAL structure
799 VolatileOffset The offset of last volatile variable
800 NonVolatileOffset The offset of last non-volatile variable
801 Instance Instance of the Firmware Volume.
806 EFI_INVALID_PARAMETER - Invalid parameter
807 EFI_SUCCESS - Set successfully
808 EFI_OUT_OF_RESOURCES - Resource not enough to set variable
809 EFI_NOT_FOUND - Not found
813 VARIABLE_POINTER_TRACK Variable
;
815 VARIABLE_HEADER
*NextVariable
;
825 if (VariableName
== NULL
|| VariableName
[0] == 0 || VendorGuid
== NULL
) {
826 return EFI_INVALID_PARAMETER
;
829 Status
= FindVariable (VariableName
, VendorGuid
, &Variable
, Global
);
831 if (Status
== EFI_INVALID_PARAMETER
) {
833 } else if (!EFI_ERROR (Status
) && Variable
.Volatile
&& EfiAtRuntime()) {
835 // If EfiAtRuntime and the variable is Volatile and Runtime Access,
836 // the volatile is ReadOnly, and SetVariable should be aborted and
837 // return EFI_WRITE_PROTECTED.
839 Status
= EFI_WRITE_PROTECTED
;
841 } else if (sizeof (VARIABLE_HEADER
) + StrSize (VariableName
) + DataSize
> MAX_VARIABLE_SIZE
) {
843 // The size of the VariableName, including the Unicode Null in bytes plus
844 // the DataSize is limited to maximum size of MAX_VARIABLE_SIZE (1024) bytes.
846 Status
= EFI_INVALID_PARAMETER
;
848 } else if (Attributes
== EFI_VARIABLE_NON_VOLATILE
) {
850 // Make sure not only EFI_VARIABLE_NON_VOLATILE is set
852 Status
= EFI_INVALID_PARAMETER
;
854 } else if ((Attributes
& (EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
)) ==
855 EFI_VARIABLE_RUNTIME_ACCESS
) {
857 // Make sure if runtime bit is set, boot service bit is set also
859 Status
= EFI_INVALID_PARAMETER
;
861 } else if (EfiAtRuntime () && Attributes
&& !(Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
)) {
863 // Runtime but Attribute is not Runtime
865 Status
= EFI_INVALID_PARAMETER
;
867 } else if (EfiAtRuntime () && Attributes
&& !(Attributes
& EFI_VARIABLE_NON_VOLATILE
)) {
869 // Cannot set volatile variable in Runtime
871 Status
= EFI_INVALID_PARAMETER
;
873 } else if (DataSize
== 0 || (Attributes
& (EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
)) == 0) {
875 // Setting a data variable with no access, or zero DataSize attributes
876 // specified causes it to be deleted.
878 if (!EFI_ERROR (Status
)) {
879 State
= Variable
.CurrPtr
->State
;
880 State
&= VAR_DELETED
;
882 Status
= UpdateVariableStore (
887 (UINTN
) &Variable
.CurrPtr
->State
,
891 if (EFI_ERROR (Status
)) {
895 Status
= EFI_SUCCESS
;
899 Status
= EFI_NOT_FOUND
;
902 if (!EFI_ERROR (Status
)) {
904 // If the variable is marked valid and the same data has been passed in
905 // then return to the caller immediately.
907 if (Variable
.CurrPtr
->DataSize
== DataSize
&&
908 !CompareMem (Data
, GetVariableDataPtr (Variable
.CurrPtr
), DataSize
)
910 Status
= EFI_SUCCESS
;
912 } else if (Variable
.CurrPtr
->State
== VAR_ADDED
) {
914 // Mark the old variable as in delete transition
916 State
= Variable
.CurrPtr
->State
;
917 State
&= VAR_IN_DELETED_TRANSITION
;
919 Status
= UpdateVariableStore (
924 (UINTN
) &Variable
.CurrPtr
->State
,
928 if (EFI_ERROR (Status
)) {
934 // Create a new variable and copy the data.
936 // Tricky part: Use scratch data area at the end of volatile variable store
937 // as a temporary storage.
939 NextVariable
= GetEndPointer ((VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->VolatileVariableBase
));
941 SetMem (NextVariable
, SCRATCH_SIZE
, 0xff);
943 NextVariable
->StartId
= VARIABLE_DATA
;
944 NextVariable
->Attributes
= Attributes
;
946 // NextVariable->State = VAR_ADDED;
948 NextVariable
->Reserved
= 0;
949 VarNameOffset
= sizeof (VARIABLE_HEADER
);
950 VarNameSize
= StrSize (VariableName
);
952 (UINT8
*) ((UINTN
) NextVariable
+ VarNameOffset
),
956 VarDataOffset
= VarNameOffset
+ VarNameSize
+ GET_PAD_SIZE (VarNameSize
);
958 (UINT8
*) ((UINTN
) NextVariable
+ VarDataOffset
),
962 CopyMem (&NextVariable
->VendorGuid
, VendorGuid
, sizeof (EFI_GUID
));
964 // There will be pad bytes after Data, the NextVariable->NameSize and
965 // NextVariable->DataSize should not include pad size so that variable
966 // service can get actual size in GetVariable
968 NextVariable
->NameSize
= (UINT32
)VarNameSize
;
969 NextVariable
->DataSize
= (UINT32
)DataSize
;
972 // The actual size of the variable that stores in storage should
975 VarSize
= VarDataOffset
+ DataSize
+ GET_PAD_SIZE (DataSize
);
976 if (Attributes
& EFI_VARIABLE_NON_VOLATILE
) {
977 if ((UINT32
) (VarSize
+*NonVolatileOffset
) >
978 ((VARIABLE_STORE_HEADER
*) ((UINTN
) (Global
->NonVolatileVariableBase
)))->Size
980 if (EfiAtRuntime ()) {
981 Status
= EFI_OUT_OF_RESOURCES
;
985 // Perform garbage collection & reclaim operation
987 Status
= Reclaim (Global
->NonVolatileVariableBase
, NonVolatileOffset
, FALSE
);
988 if (EFI_ERROR (Status
)) {
992 // If still no enough space, return out of resources
994 if ((UINT32
) (VarSize
+*NonVolatileOffset
) >
995 ((VARIABLE_STORE_HEADER
*) ((UINTN
) (Global
->NonVolatileVariableBase
)))->Size
997 Status
= EFI_OUT_OF_RESOURCES
;
1005 // 1. Write variable header
1006 // 2. Write variable data
1007 // 3. Set variable state to valid
1012 Status
= UpdateVariableStore (
1018 sizeof (VARIABLE_HEADER
),
1019 (UINT8
*) NextVariable
1022 if (EFI_ERROR (Status
)) {
1028 Status
= UpdateVariableStore (
1033 *NonVolatileOffset
+ sizeof (VARIABLE_HEADER
),
1034 (UINT32
) VarSize
- sizeof (VARIABLE_HEADER
),
1035 (UINT8
*) NextVariable
+ sizeof (VARIABLE_HEADER
)
1038 if (EFI_ERROR (Status
)) {
1044 NextVariable
->State
= VAR_ADDED
;
1045 Status
= UpdateVariableStore (
1051 sizeof (VARIABLE_HEADER
),
1052 (UINT8
*) NextVariable
1055 if (EFI_ERROR (Status
)) {
1059 *NonVolatileOffset
= *NonVolatileOffset
+ VarSize
;
1062 if (EfiAtRuntime ()) {
1063 Status
= EFI_INVALID_PARAMETER
;
1067 if ((UINT32
) (VarSize
+*VolatileOffset
) >
1068 ((VARIABLE_STORE_HEADER
*) ((UINTN
) (Global
->VolatileVariableBase
)))->Size
1071 // Perform garbage collection & reclaim operation
1073 Status
= Reclaim (Global
->VolatileVariableBase
, VolatileOffset
, TRUE
);
1074 if (EFI_ERROR (Status
)) {
1078 // If still no enough space, return out of resources
1080 if ((UINT32
) (VarSize
+*VolatileOffset
) >
1081 ((VARIABLE_STORE_HEADER
*) ((UINTN
) (Global
->VolatileVariableBase
)))->Size
1083 Status
= EFI_OUT_OF_RESOURCES
;
1090 NextVariable
->State
= VAR_ADDED
;
1091 Status
= UpdateVariableStore (
1098 (UINT8
*) NextVariable
1101 if (EFI_ERROR (Status
)) {
1105 *VolatileOffset
= *VolatileOffset
+ VarSize
;
1108 // Mark the old variable as deleted
1110 if (!Reclaimed
&& !EFI_ERROR (Status
) && Variable
.CurrPtr
!= NULL
) {
1111 State
= Variable
.CurrPtr
->State
;
1112 State
&= VAR_DELETED
;
1114 Status
= UpdateVariableStore (
1119 (UINTN
) &Variable
.CurrPtr
->State
,
1124 if (EFI_ERROR (Status
)) {
1130 Status
= EFI_SUCCESS
;
1132 ReleaseLockOnlyAtBootTime (&Global
->VariableServicesLock
);
1139 IN UINT32 Attributes
,
1140 OUT UINT64
*MaximumVariableStorageSize
,
1141 OUT UINT64
*RemainingVariableStorageSize
,
1142 OUT UINT64
*MaximumVariableSize
,
1143 IN VARIABLE_GLOBAL
*Global
,
1148 Routine Description:
1150 This code returns information about the EFI variables.
1154 Attributes Attributes bitmask to specify the type of variables
1155 on which to return information.
1156 MaximumVariableStorageSize Pointer to the maximum size of the storage space available
1157 for the EFI variables associated with the attributes specified.
1158 RemainingVariableStorageSize Pointer to the remaining size of the storage space available
1159 for the EFI variables associated with the attributes specified.
1160 MaximumVariableSize Pointer to the maximum size of the individual EFI variables
1161 associated with the attributes specified.
1162 Global Pointer to VARIABLE_GLOBAL structure.
1163 Instance Instance of the Firmware Volume.
1168 EFI_INVALID_PARAMETER - An invalid combination of attribute bits was supplied.
1169 EFI_SUCCESS - Query successfully.
1170 EFI_UNSUPPORTED - The attribute is not supported on this platform.
1174 VARIABLE_HEADER
*Variable
;
1175 VARIABLE_HEADER
*NextVariable
;
1176 UINT64 VariableSize
;
1177 VARIABLE_STORE_HEADER
*VariableStoreHeader
;
1179 if(MaximumVariableStorageSize
== NULL
|| RemainingVariableStorageSize
== NULL
|| MaximumVariableSize
== NULL
) {
1180 return EFI_INVALID_PARAMETER
;
1183 if((Attributes
& (EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
)) == 0) {
1185 // Make sure the Attributes combination is supported by the platform.
1187 return EFI_UNSUPPORTED
;
1188 } else if ((Attributes
& (EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
)) == EFI_VARIABLE_RUNTIME_ACCESS
) {
1190 // Make sure if runtime bit is set, boot service bit is set also.
1192 return EFI_INVALID_PARAMETER
;
1193 } else if (EfiAtRuntime () && !(Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
)) {
1195 // Make sure RT Attribute is set if we are in Runtime phase.
1197 return EFI_INVALID_PARAMETER
;
1200 AcquireLockOnlyAtBootTime(&Global
->VariableServicesLock
);
1202 if((Attributes
& EFI_VARIABLE_NON_VOLATILE
) == 0) {
1204 // Query is Volatile related.
1206 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->VolatileVariableBase
);
1209 // Query is Non-Volatile related.
1211 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->NonVolatileVariableBase
);
1215 // Now let's fill *MaximumVariableStorageSize *RemainingVariableStorageSize
1216 // with the storage size (excluding the storage header size).
1218 *MaximumVariableStorageSize
= VariableStoreHeader
->Size
- sizeof (VARIABLE_STORE_HEADER
);
1219 *RemainingVariableStorageSize
= VariableStoreHeader
->Size
- sizeof (VARIABLE_STORE_HEADER
);
1222 // Let *MaximumVariableSize be MAX_VARIABLE_SIZE.
1224 *MaximumVariableSize
= MAX_VARIABLE_SIZE
;
1227 // Point to the starting address of the variables.
1229 Variable
= (VARIABLE_HEADER
*) (VariableStoreHeader
+ 1);
1232 // Now walk through the related variable store.
1234 while (IsValidVariableHeader (Variable
) && (Variable
< GetEndPointer (VariableStoreHeader
))) {
1235 NextVariable
= GetNextVariablePtr (Variable
);
1236 VariableSize
= (UINT64
) (UINTN
) NextVariable
- (UINT64
) (UINTN
) Variable
;
1238 if (EfiAtRuntime ()) {
1240 // we don't take the state of the variables in mind
1241 // when calculating RemainingVariableStorageSize,
1242 // since the space occupied by variables not marked with
1243 // VAR_ADDED is not allowed to be reclaimed in Runtime.
1245 *RemainingVariableStorageSize
-= VariableSize
;
1248 // Only care about Variables with State VAR_ADDED,because
1249 // the space not marked as VAR_ADDED is reclaimable now.
1251 if (Variable
->State
== VAR_ADDED
) {
1252 *RemainingVariableStorageSize
-= VariableSize
;
1257 // Go to the next one
1259 Variable
= NextVariable
;
1262 ReleaseLockOnlyAtBootTime (&Global
->VariableServicesLock
);
1268 VariableCommonInitialize (
1269 IN EFI_HANDLE ImageHandle
,
1270 IN EFI_SYSTEM_TABLE
*SystemTable
1274 Routine Description:
1275 This function does common initialization for variable services
1279 ImageHandle - The firmware allocated handle for the EFI image.
1280 SystemTable - A pointer to the EFI System Table.
1286 EFI_NOT_FOUND - Variable store area not found.
1287 EFI_UNSUPPORTED - Currently only one non-volatile variable store is supported.
1288 EFI_SUCCESS - Variable services successfully initialized.
1293 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
1295 VARIABLE_STORE_HEADER
*VolatileVariableStore
;
1296 VARIABLE_STORE_HEADER
*VariableStoreHeader
;
1297 VARIABLE_HEADER
*NextVariable
;
1299 EFI_PHYSICAL_ADDRESS FvVolHdr
;
1301 UINT64 TempVariableStoreHeader
;
1303 EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor
;
1304 EFI_FLASH_SUBAREA_ENTRY VariableStoreEntry
;
1310 mVariableModuleGlobal
= AllocateRuntimePool (sizeof (ESAL_VARIABLE_GLOBAL
));
1311 if (mVariableModuleGlobal
== NULL
) {
1312 return EFI_OUT_OF_RESOURCES
;
1315 EfiInitializeLock(&mVariableModuleGlobal
->VariableGlobal
[Physical
].VariableServicesLock
, TPL_NOTIFY
);
1318 // Allocate memory for volatile variable store
1320 VolatileVariableStore
= AllocateRuntimePool (VARIABLE_STORE_SIZE
+ SCRATCH_SIZE
);
1321 if (VolatileVariableStore
== NULL
) {
1322 FreePool (mVariableModuleGlobal
);
1323 return EFI_OUT_OF_RESOURCES
;
1326 SetMem (VolatileVariableStore
, VARIABLE_STORE_SIZE
+ SCRATCH_SIZE
, 0xff);
1329 // Variable Specific Data
1331 mVariableModuleGlobal
->VariableGlobal
[Physical
].VolatileVariableBase
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) VolatileVariableStore
;
1332 mVariableModuleGlobal
->VolatileLastVariableOffset
= sizeof (VARIABLE_STORE_HEADER
);
1334 VolatileVariableStore
->Signature
= VARIABLE_STORE_SIGNATURE
;
1335 VolatileVariableStore
->Size
= VARIABLE_STORE_SIZE
;
1336 VolatileVariableStore
->Format
= VARIABLE_STORE_FORMATTED
;
1337 VolatileVariableStore
->State
= VARIABLE_STORE_HEALTHY
;
1338 VolatileVariableStore
->Reserved
= 0;
1339 VolatileVariableStore
->Reserved1
= 0;
1342 // Get non volatile varaible store
1345 TempVariableStoreHeader
= (UINT64
) PcdGet32 (PcdFlashNvStorageVariableBase
);
1346 VariableStoreEntry
.Base
= TempVariableStoreHeader
+ \
1347 (((EFI_FIRMWARE_VOLUME_HEADER
*) (UINTN
) (TempVariableStoreHeader
)) -> HeaderLength
);
1348 VariableStoreEntry
.Length
= (UINT64
) PcdGet32 (PcdFlashNvStorageVariableSize
) - \
1349 (((EFI_FIRMWARE_VOLUME_HEADER
*) (UINTN
) (TempVariableStoreHeader
)) -> HeaderLength
);
1351 // Mark the variable storage region of the FLASH as RUNTIME
1353 BaseAddress
= VariableStoreEntry
.Base
& (~EFI_PAGE_MASK
);
1354 Length
= VariableStoreEntry
.Length
+ (VariableStoreEntry
.Base
- BaseAddress
);
1355 Length
= (Length
+ EFI_PAGE_SIZE
- 1) & (~EFI_PAGE_MASK
);
1357 Status
= gDS
->GetMemorySpaceDescriptor (BaseAddress
, &GcdDescriptor
);
1358 if (EFI_ERROR (Status
)) {
1359 FreePool (mVariableModuleGlobal
);
1360 FreePool (VolatileVariableStore
);
1361 return EFI_UNSUPPORTED
;
1364 Status
= gDS
->SetMemorySpaceAttributes (
1367 GcdDescriptor
.Attributes
| EFI_MEMORY_RUNTIME
1369 if (EFI_ERROR (Status
)) {
1370 FreePool (mVariableModuleGlobal
);
1371 FreePool (VolatileVariableStore
);
1372 return EFI_UNSUPPORTED
;
1375 // Get address of non volatile variable store base
1377 mVariableModuleGlobal
->VariableGlobal
[Physical
].NonVolatileVariableBase
= VariableStoreEntry
.Base
;
1383 // Find the Correct Instance of the FV Block Service.
1386 CurrPtr
= (CHAR8
*) ((UINTN
) mVariableModuleGlobal
->VariableGlobal
[Physical
].NonVolatileVariableBase
);
1387 while (EfiFvbGetPhysicalAddress (Instance
, &FvVolHdr
) == EFI_SUCCESS
) {
1388 FwVolHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) ((UINTN
) FvVolHdr
);
1389 if (CurrPtr
>= (CHAR8
*) FwVolHeader
&& CurrPtr
< (((CHAR8
*) FwVolHeader
) + FwVolHeader
->FvLength
)) {
1390 mVariableModuleGlobal
->FvbInstance
= Instance
;
1397 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) CurrPtr
;
1398 if (GetVariableStoreStatus (VariableStoreHeader
) == EfiValid
) {
1399 if (~VariableStoreHeader
->Size
== 0) {
1400 Status
= UpdateVariableStore (
1401 &mVariableModuleGlobal
->VariableGlobal
[Physical
],
1404 mVariableModuleGlobal
->FvbInstance
,
1405 (UINTN
) &VariableStoreHeader
->Size
,
1407 (UINT8
*) &VariableStoreEntry
.Length
1410 // As Variables are stored in NV storage, which are slow devices,such as flash.
1411 // Variable operation may skip checking variable program result to improve performance,
1412 // We can assume Variable program is OK through some check point.
1413 // Variable Store Size Setting should be the first Variable write operation,
1414 // We can assume all Read/Write is OK if we can set Variable store size successfully.
1415 // If write fail, we will assert here
1417 ASSERT(VariableStoreHeader
->Size
== VariableStoreEntry
.Length
);
1419 if (EFI_ERROR (Status
)) {
1424 mVariableModuleGlobal
->VariableGlobal
[Physical
].NonVolatileVariableBase
= (EFI_PHYSICAL_ADDRESS
) ((UINTN
) CurrPtr
);
1426 // Parse non-volatile variable data and get last variable offset
1428 NextVariable
= (VARIABLE_HEADER
*) (CurrPtr
+ sizeof (VARIABLE_STORE_HEADER
));
1429 Status
= EFI_SUCCESS
;
1431 while (IsValidVariableHeader (NextVariable
)) {
1432 NextVariable
= GetNextVariablePtr (NextVariable
);
1435 mVariableModuleGlobal
->NonVolatileLastVariableOffset
= (UINTN
) NextVariable
- (UINTN
) CurrPtr
;
1438 // Check if the free area is blow a threshold
1440 if ((((VARIABLE_STORE_HEADER
*)((UINTN
) CurrPtr
))->Size
- mVariableModuleGlobal
->NonVolatileLastVariableOffset
) < VARIABLE_RECLAIM_THRESHOLD
) {
1442 mVariableModuleGlobal
->VariableGlobal
[Physical
].NonVolatileVariableBase
,
1443 &mVariableModuleGlobal
->NonVolatileLastVariableOffset
,
1448 if (EFI_ERROR (Status
)) {
1449 FreePool (mVariableModuleGlobal
);
1450 FreePool (VolatileVariableStore
);
1455 // Check if the free area is really free.
1457 for (Index
= mVariableModuleGlobal
->NonVolatileLastVariableOffset
; Index
< VariableStoreHeader
->Size
; Index
++) {
1458 Data
= ((UINT8
*) (UINTN
) mVariableModuleGlobal
->VariableGlobal
[Physical
].NonVolatileVariableBase
)[Index
];
1461 // There must be something wrong in variable store, do reclaim operation.
1464 mVariableModuleGlobal
->VariableGlobal
[Physical
].NonVolatileVariableBase
,
1465 &mVariableModuleGlobal
->NonVolatileLastVariableOffset
,
1473 if (EFI_ERROR (Status
)) {
1474 FreePool (mVariableModuleGlobal
);
1475 FreePool (VolatileVariableStore
);