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.
25 // Don't use module globals after the SetVirtualAddress map is signaled
27 ESAL_VARIABLE_GLOBAL
*mVariableModuleGlobal
;
30 // This is a temperary function which will be removed
31 // when EfiAcquireLock in UefiLib can handle the
32 // the call in UEFI Runtimer driver in RT phase.
36 AcquireLockOnlyAtBootTime (
40 if (!EfiAtRuntime ()) {
41 EfiAcquireLock (Lock
);
46 // This is a temperary function which will be removed
47 // when EfiAcquireLock in UefiLib can handle the
48 // the call in UEFI Runtimer driver in RT phase.
52 ReleaseLockOnlyAtBootTime (
56 if (!EfiAtRuntime ()) {
57 EfiReleaseLock (Lock
);
65 IN VARIABLE_HEADER
*Variable
71 This code gets the pointer to the variable data.
75 Variable Pointer to the Variable Header.
79 UINT8* Pointer to Variable Data
83 if (Variable
->StartId
!= VARIABLE_DATA
) {
87 // Be careful about pad size for alignment
89 return (UINT8
*) ((UINTN
) GET_VARIABLE_NAME_PTR (Variable
) + Variable
->NameSize
+ GET_PAD_SIZE (Variable
->NameSize
));
96 IN VARIABLE_HEADER
*Variable
102 This code gets the pointer to the next variable header.
106 Variable Pointer to the Variable Header.
110 VARIABLE_HEADER* Pointer to next variable header.
114 VARIABLE_HEADER
*VarHeader
;
116 if (Variable
->StartId
!= VARIABLE_DATA
) {
120 // Be careful about pad size for alignment
122 VarHeader
= (VARIABLE_HEADER
*) (GetVariableDataPtr (Variable
) + Variable
->DataSize
+ GET_PAD_SIZE (Variable
->DataSize
));
124 if (VarHeader
->StartId
!= VARIABLE_DATA
||
125 (sizeof (VARIABLE_HEADER
) + VarHeader
->DataSize
+ VarHeader
->NameSize
) > MAX_VARIABLE_SIZE
137 IN VARIABLE_STORE_HEADER
*VolHeader
143 This code gets the pointer to the last variable memory pointer byte
147 Variable Pointer to the Variable Header.
151 VARIABLE_HEADER* Pointer to last unavailable Variable Header
156 // The end of variable store
158 return (VARIABLE_HEADER
*) ((UINTN
) VolHeader
+ VolHeader
->Size
);
165 IN CHAR16
*VariableName
,
166 IN EFI_GUID
*VendorGuid
,
167 OUT VARIABLE_POINTER_TRACK
*PtrTrack
,
168 IN VARIABLE_GLOBAL
*Global
174 This code finds variable in storage blocks (Volatile or Non-Volatile)
178 VariableName Name of the variable to be found
179 VendorGuid Vendor GUID to be found.
180 PtrTrack Variable Track Pointer structure that contains
181 Variable Information.
182 Contains the pointer of Variable header.
183 Global VARIABLE_GLOBAL pointer
191 VARIABLE_HEADER
*Variable
[2];
192 VARIABLE_STORE_HEADER
*VariableStoreHeader
[2];
196 // We aquire the lock at the entry of FindVariable as GetVariable, GetNextVariableName
197 // SetVariable all call FindVariable at entry point. Please move "Aquire Lock" to
198 // the correct places if this assumption does not hold TRUE anymore.
200 AcquireLockOnlyAtBootTime(&Global
->VariableServicesLock
);
203 // 0: Non-Volatile, 1: Volatile
205 VariableStoreHeader
[0] = (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->NonVolatileVariableBase
);
206 VariableStoreHeader
[1] = (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->VolatileVariableBase
);
209 // Start Pointers for the variable.
210 // Actual Data Pointer where data can be written.
212 Variable
[0] = (VARIABLE_HEADER
*) (VariableStoreHeader
[0] + 1);
213 Variable
[1] = (VARIABLE_HEADER
*) (VariableStoreHeader
[1] + 1);
215 if (VariableName
[0] != 0 && VendorGuid
== NULL
) {
216 return EFI_INVALID_PARAMETER
;
219 // Find the variable by walk through non-volatile and volatile variable store
221 for (Index
= 0; Index
< 2; Index
++) {
222 PtrTrack
->StartPtr
= (VARIABLE_HEADER
*) (VariableStoreHeader
[Index
] + 1);
223 PtrTrack
->EndPtr
= GetEndPointer (VariableStoreHeader
[Index
]);
225 while ((Variable
[Index
] != NULL
) && (Variable
[Index
] <= GetEndPointer (VariableStoreHeader
[Index
]))) {
226 if (Variable
[Index
]->StartId
== VARIABLE_DATA
&& Variable
[Index
]->State
== VAR_ADDED
) {
227 if (!(EfiAtRuntime () && !(Variable
[Index
]->Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
))) {
228 if (VariableName
[0] == 0) {
229 PtrTrack
->CurrPtr
= Variable
[Index
];
230 PtrTrack
->Volatile
= (BOOLEAN
) Index
;
233 if (CompareGuid (VendorGuid
, &Variable
[Index
]->VendorGuid
)) {
234 if (!CompareMem (VariableName
, GET_VARIABLE_NAME_PTR (Variable
[Index
]), Variable
[Index
]->NameSize
)) {
235 PtrTrack
->CurrPtr
= Variable
[Index
];
236 PtrTrack
->Volatile
= (BOOLEAN
) Index
;
244 Variable
[Index
] = GetNextVariablePtr (Variable
[Index
]);
247 PtrTrack
->CurrPtr
= NULL
;
248 return EFI_NOT_FOUND
;
254 IN CHAR16
*VariableName
,
255 IN EFI_GUID
* VendorGuid
,
256 OUT UINT32
*Attributes OPTIONAL
,
257 IN OUT UINTN
*DataSize
,
259 IN VARIABLE_GLOBAL
* Global
,
266 This code finds variable in storage blocks (Volatile or Non-Volatile)
270 VariableName Name of Variable to be found
271 VendorGuid Variable vendor GUID
272 Attributes OPTIONAL Attribute value of the variable found
273 DataSize Size of Data found. If size is less than the
274 data, this value contains the required size.
276 Global Pointer to VARIABLE_GLOBAL structure
277 Instance Instance of the Firmware Volume.
285 VARIABLE_POINTER_TRACK Variable
;
289 if (VariableName
== NULL
|| VendorGuid
== NULL
|| DataSize
== NULL
) {
290 return EFI_INVALID_PARAMETER
;
293 // Find existing variable
295 Status
= FindVariable (VariableName
, VendorGuid
, &Variable
, Global
);
297 if (Variable
.CurrPtr
== NULL
|| EFI_ERROR (Status
)) {
303 VarDataSize
= Variable
.CurrPtr
->DataSize
;
304 if (*DataSize
>= VarDataSize
) {
306 Status
= EFI_INVALID_PARAMETER
;
310 CopyMem (Data
, GetVariableDataPtr (Variable
.CurrPtr
), VarDataSize
);
311 if (Attributes
!= NULL
) {
312 *Attributes
= Variable
.CurrPtr
->Attributes
;
315 *DataSize
= VarDataSize
;
316 Status
= EFI_SUCCESS
;
319 *DataSize
= VarDataSize
;
320 Status
= EFI_BUFFER_TOO_SMALL
;
325 ReleaseLockOnlyAtBootTime (&Global
->VariableServicesLock
);
331 GetNextVariableName (
332 IN OUT UINTN
*VariableNameSize
,
333 IN OUT CHAR16
*VariableName
,
334 IN OUT EFI_GUID
*VendorGuid
,
335 IN VARIABLE_GLOBAL
*Global
,
342 This code Finds the Next available variable
346 VariableNameSize Size of the variable
347 VariableName Pointer to variable name
348 VendorGuid Variable Vendor Guid
349 Global VARIABLE_GLOBAL structure pointer.
358 VARIABLE_POINTER_TRACK Variable
;
362 if (VariableNameSize
== NULL
|| VariableName
== NULL
|| VendorGuid
== NULL
) {
363 return EFI_INVALID_PARAMETER
;
366 Status
= FindVariable (VariableName
, VendorGuid
, &Variable
, Global
);
368 if (Variable
.CurrPtr
== NULL
|| EFI_ERROR (Status
)) {
373 if (VariableName
[0] != 0) {
375 // If variable name is not NULL, get next variable
377 Variable
.CurrPtr
= GetNextVariablePtr (Variable
.CurrPtr
);
380 // If both volatile and non-volatile variable store are parsed,
383 if (Variable
.CurrPtr
>= Variable
.EndPtr
|| Variable
.CurrPtr
== NULL
) {
384 Variable
.Volatile
= (BOOLEAN
) (Variable
.Volatile
^ ((BOOLEAN
) 0x1));
385 if (Variable
.Volatile
) {
386 Variable
.StartPtr
= (VARIABLE_HEADER
*) ((UINTN
) (Global
->VolatileVariableBase
+ sizeof (VARIABLE_STORE_HEADER
)));
387 Variable
.EndPtr
= (VARIABLE_HEADER
*) GetEndPointer ((VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->VolatileVariableBase
));
389 Status
= EFI_NOT_FOUND
;
393 Variable
.CurrPtr
= Variable
.StartPtr
;
394 if (Variable
.CurrPtr
->StartId
!= VARIABLE_DATA
) {
401 if (Variable
.CurrPtr
->StartId
== VARIABLE_DATA
&& Variable
.CurrPtr
->State
== VAR_ADDED
) {
402 if (!(EfiAtRuntime () && !(Variable
.CurrPtr
->Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
))) {
403 VarNameSize
= Variable
.CurrPtr
->NameSize
;
404 if (VarNameSize
<= *VariableNameSize
) {
407 GET_VARIABLE_NAME_PTR (Variable
.CurrPtr
),
412 &Variable
.CurrPtr
->VendorGuid
,
415 Status
= EFI_SUCCESS
;
417 Status
= EFI_BUFFER_TOO_SMALL
;
420 *VariableNameSize
= VarNameSize
;
427 ReleaseLockOnlyAtBootTime (&Global
->VariableServicesLock
);
435 IN CHAR16
*VariableName
,
436 IN EFI_GUID
*VendorGuid
,
437 IN UINT32 Attributes
,
440 IN VARIABLE_GLOBAL
*Global
,
441 IN UINTN
*VolatileOffset
,
442 IN UINTN
*NonVolatileOffset
,
449 This code sets variable in storage blocks (Volatile or Non-Volatile)
453 VariableName Name of Variable to be found
454 VendorGuid Variable vendor GUID
455 Attributes Attribute value of the variable found
456 DataSize Size of Data found. If size is less than the
457 data, this value contains the required size.
459 Global Pointer to VARIABLE_GLOBAL structure
460 VolatileOffset The offset of last volatile variable
461 NonVolatileOffset The offset of last non-volatile variable
462 Instance Instance of the Firmware Volume.
470 VARIABLE_POINTER_TRACK Variable
;
472 VARIABLE_HEADER
*NextVariable
;
478 if (VariableName
== NULL
|| VariableName
[0] == 0 || VendorGuid
== NULL
) {
479 return EFI_INVALID_PARAMETER
;
482 Status
= FindVariable (VariableName
, VendorGuid
, &Variable
, Global
);
484 if (Status
== EFI_INVALID_PARAMETER
) {
486 } else if (!EFI_ERROR (Status
) && Variable
.Volatile
&& EfiAtRuntime()) {
488 // If EfiAtRuntime and the variable is Volatile and Runtime Access,
489 // the volatile is ReadOnly, and SetVariable should be aborted and
490 // return EFI_WRITE_PROTECTED.
492 Status
= EFI_WRITE_PROTECTED
;
494 } else if (sizeof (VARIABLE_HEADER
) + (StrSize (VariableName
) + DataSize
) > MAX_VARIABLE_SIZE
) {
496 // The size of the VariableName, including the Unicode Null in bytes plus
497 // the DataSize is limited to maximum size of MAX_VARIABLE_SIZE (1024) bytes.
499 Status
= EFI_INVALID_PARAMETER
;
501 } else if ((Attributes
& (EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
)) == EFI_VARIABLE_RUNTIME_ACCESS
504 // Make sure if runtime bit is set, boot service bit is set also
506 Status
= EFI_INVALID_PARAMETER
;
508 } else if (EfiAtRuntime () && Attributes
&& !(Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
)) {
510 // Runtime but Attribute is not Runtime
512 Status
= EFI_INVALID_PARAMETER
;
514 } else if (EfiAtRuntime () && Attributes
&& !(Attributes
& EFI_VARIABLE_NON_VOLATILE
)) {
516 // Cannot set volatile variable in Runtime
518 Status
= EFI_INVALID_PARAMETER
;
520 } else if (DataSize
== 0 || (Attributes
& (EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
)) == 0) {
522 // Setting a data variable with no access, or zero DataSize attributes
523 // specified causes it to be deleted.
525 if (!EFI_ERROR (Status
)) {
526 Variable
.CurrPtr
->State
&= VAR_DELETED
;
527 Status
= EFI_SUCCESS
;
531 Status
= EFI_NOT_FOUND
;
534 if (!EFI_ERROR (Status
)) {
536 // If the variable is marked valid and the same data has been passed in
537 // then return to the caller immediately.
539 if (Variable
.CurrPtr
->DataSize
== DataSize
&&
540 !CompareMem (Data
, GetVariableDataPtr (Variable
.CurrPtr
), DataSize
)
542 Status
= EFI_SUCCESS
;
544 } else if (Variable
.CurrPtr
->State
== VAR_ADDED
) {
546 // Mark the old variable as in delete transition
548 Variable
.CurrPtr
->State
&= VAR_IN_DELETED_TRANSITION
;
552 // Create a new variable and copy the data.
554 VarNameOffset
= sizeof (VARIABLE_HEADER
);
555 VarNameSize
= StrSize (VariableName
);
556 VarDataOffset
= VarNameOffset
+ VarNameSize
+ GET_PAD_SIZE (VarNameSize
);
557 VarSize
= VarDataOffset
+ DataSize
+ GET_PAD_SIZE (DataSize
);
559 if (Attributes
& EFI_VARIABLE_NON_VOLATILE
) {
560 if ((UINT32
) (VarSize
+*NonVolatileOffset
) >
561 ((VARIABLE_STORE_HEADER
*) ((UINTN
) (Global
->NonVolatileVariableBase
)))->Size
563 Status
= EFI_OUT_OF_RESOURCES
;
567 NextVariable
= (VARIABLE_HEADER
*) (UINT8
*) (*NonVolatileOffset
+ (UINTN
) Global
->NonVolatileVariableBase
);
568 *NonVolatileOffset
= *NonVolatileOffset
+ VarSize
;
570 if (EfiAtRuntime ()) {
571 Status
= EFI_INVALID_PARAMETER
;
575 if ((UINT32
) (VarSize
+*VolatileOffset
) >
576 ((VARIABLE_STORE_HEADER
*) ((UINTN
) (Global
->VolatileVariableBase
)))->Size
578 Status
= EFI_OUT_OF_RESOURCES
;
582 NextVariable
= (VARIABLE_HEADER
*) (UINT8
*) (*VolatileOffset
+ (UINTN
) Global
->VolatileVariableBase
);
583 *VolatileOffset
= *VolatileOffset
+ VarSize
;
586 NextVariable
->StartId
= VARIABLE_DATA
;
587 NextVariable
->Attributes
= Attributes
;
588 NextVariable
->State
= VAR_ADDED
;
589 NextVariable
->Reserved
= 0;
592 // There will be pad bytes after Data, the NextVariable->NameSize and
593 // NextVariable->NameSize should not include pad size so that variable
594 // service can get actual size in GetVariable
596 NextVariable
->NameSize
= (UINT32
)VarNameSize
;
597 NextVariable
->DataSize
= (UINT32
)DataSize
;
599 CopyMem (&NextVariable
->VendorGuid
, VendorGuid
, sizeof (EFI_GUID
));
601 (UINT8
*) ((UINTN
) NextVariable
+ VarNameOffset
),
606 (UINT8
*) ((UINTN
) NextVariable
+ VarDataOffset
),
612 // Mark the old variable as deleted
614 if (!EFI_ERROR (Status
)) {
615 Variable
.CurrPtr
->State
&= VAR_DELETED
;
619 Status
= EFI_SUCCESS
;
621 ReleaseLockOnlyAtBootTime (&Global
->VariableServicesLock
);
625 #if (EFI_SPECIFICATION_VERSION >= 0x00020000)
629 IN UINT32 Attributes
,
630 OUT UINT64
*MaximumVariableStorageSize
,
631 OUT UINT64
*RemainingVariableStorageSize
,
632 OUT UINT64
*MaximumVariableSize
,
633 IN VARIABLE_GLOBAL
*Global
,
640 This code returns information about the EFI variables.
644 Attributes Attributes bitmask to specify the type of variables
645 on which to return information.
646 MaximumVariableStorageSize Pointer to the maximum size of the storage space available
647 for the EFI variables associated with the attributes specified.
648 RemainingVariableStorageSize Pointer to the remaining size of the storage space available
649 for the EFI variables associated with the attributes specified.
650 MaximumVariableSize Pointer to the maximum size of the individual EFI variables
651 associated with the attributes specified.
652 Global Pointer to VARIABLE_GLOBAL structure.
653 Instance Instance of the Firmware Volume.
658 EFI_INVALID_PARAMETER - An invalid combination of attribute bits was supplied.
659 EFI_SUCCESS - Query successfully.
660 EFI_UNSUPPORTED - The attribute is not supported on this platform.
664 VARIABLE_HEADER
*Variable
;
665 VARIABLE_HEADER
*NextVariable
;
667 VARIABLE_STORE_HEADER
*VariableStoreHeader
;
669 if(MaximumVariableStorageSize
== NULL
|| RemainingVariableStorageSize
== NULL
|| MaximumVariableSize
== NULL
) {
670 return EFI_INVALID_PARAMETER
;
673 if((Attributes
& (EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
)) == 0) {
675 // Make sure the Attributes combination is supported by the platform.
677 return EFI_UNSUPPORTED
;
678 } else if ((Attributes
& (EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
)) == EFI_VARIABLE_RUNTIME_ACCESS
) {
680 // Make sure if runtime bit is set, boot service bit is set also.
682 return EFI_INVALID_PARAMETER
;
683 } else if (EfiAtRuntime () && !(Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
)) {
685 // Make sure RT Attribute is set if we are in Runtime phase.
687 return EFI_INVALID_PARAMETER
;
688 } else if (EfiAtRuntime () && Attributes
&& !(Attributes
& EFI_VARIABLE_NON_VOLATILE
)) {
690 // Cannot Query volatile variable in Runtime
692 return EFI_INVALID_PARAMETER
;
695 AcquireLockOnlyAtBootTime(&Global
->VariableServicesLock
);
697 if((Attributes
& EFI_VARIABLE_NON_VOLATILE
) == 0) {
699 // Query is Volatile related.
701 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->VolatileVariableBase
);
704 // Query is Non-Volatile related.
706 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->NonVolatileVariableBase
);
710 // Now let's fill *MaximumVariableStorageSize *RemainingVariableStorageSize
711 // with the storage size (excluding the storage header size)
713 *MaximumVariableStorageSize
= VariableStoreHeader
->Size
- sizeof (VARIABLE_STORE_HEADER
);
714 *RemainingVariableStorageSize
= VariableStoreHeader
->Size
- sizeof (VARIABLE_STORE_HEADER
);
717 // Let *MaximumVariableSize be MAX_VARIABLE_SIZE
719 *MaximumVariableSize
= MAX_VARIABLE_SIZE
;
722 // Point to the starting address of the variables.
724 Variable
= (VARIABLE_HEADER
*) (VariableStoreHeader
+ 1);
727 // Now walk through the related variable store.
729 while (Variable
< GetEndPointer (VariableStoreHeader
)) {
730 if (Variable
->StartId
!= VARIABLE_DATA
) {
734 NextVariable
= (VARIABLE_HEADER
*) (GetVariableDataPtr (Variable
) + Variable
->DataSize
+ GET_PAD_SIZE (Variable
->DataSize
));
735 VariableSize
= (UINT64
) (UINTN
) NextVariable
- (UINT64
) (UINTN
) Variable
;
737 if (Variable
->State
== VAR_ADDED
) {
738 *RemainingVariableStorageSize
-= VariableSize
;
742 // Go to the next one.
744 Variable
= NextVariable
;
747 ReleaseLockOnlyAtBootTime (&Global
->VariableServicesLock
);
755 InitializeVariableStore (
756 OUT EFI_PHYSICAL_ADDRESS
*VariableBase
,
757 OUT UINTN
*LastVariableOffset
762 This function initializes variable store
770 VARIABLE_STORE_HEADER
*VariableStore
;
773 // Allocate memory for volatile variable store
775 VariableStore
= (VARIABLE_STORE_HEADER
*) AllocateRuntimePool (
778 if (NULL
== VariableStore
) {
779 return EFI_OUT_OF_RESOURCES
;
782 SetMem (VariableStore
, VARIABLE_STORE_SIZE
, 0xff);
785 // Variable Specific Data
787 *VariableBase
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) VariableStore
;
788 *LastVariableOffset
= sizeof (VARIABLE_STORE_HEADER
);
790 VariableStore
->Signature
= VARIABLE_STORE_SIGNATURE
;
791 VariableStore
->Size
= VARIABLE_STORE_SIZE
;
792 VariableStore
->Format
= VARIABLE_STORE_FORMATTED
;
793 VariableStore
->State
= VARIABLE_STORE_HEALTHY
;
794 VariableStore
->Reserved
= 0;
795 VariableStore
->Reserved1
= 0;
802 VariableCommonInitialize (
803 IN EFI_HANDLE ImageHandle
,
804 IN EFI_SYSTEM_TABLE
*SystemTable
809 This function does common initialization for variable services
820 // Allocate memory for mVariableModuleGlobal
822 mVariableModuleGlobal
= (ESAL_VARIABLE_GLOBAL
*) AllocateRuntimePool (
823 sizeof (ESAL_VARIABLE_GLOBAL
)
825 if (NULL
== mVariableModuleGlobal
) {
826 return EFI_OUT_OF_RESOURCES
;
829 EfiInitializeLock(&mVariableModuleGlobal
->VariableGlobal
[Physical
].VariableServicesLock
, EFI_TPL_NOTIFY
);
832 // Intialize volatile variable store
834 Status
= InitializeVariableStore (
835 &mVariableModuleGlobal
->VariableGlobal
[Physical
].VolatileVariableBase
,
836 &mVariableModuleGlobal
->VolatileLastVariableOffset
839 if (EFI_ERROR (Status
)) {
843 // Intialize non volatile variable store
845 Status
= InitializeVariableStore (
846 &mVariableModuleGlobal
->VariableGlobal
[Physical
].NonVolatileVariableBase
,
847 &mVariableModuleGlobal
->NonVolatileLastVariableOffset