3 Copyright (c) 2006, 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
;
38 Determine the length of null terminated char16 array.
42 String Null-terminated CHAR16 array pointer.
46 UINT32 Number of bytes in the string, including the double NULL at the end;
58 while (0 != String
[Count
]) {
62 return (Count
* 2) + 2;
74 This function return the pad size for alignment
78 Value The value need to align
87 // If alignment is 0 or 1, means no alignment required
89 if (ALIGNMENT
== 0 || ALIGNMENT
== 1) {
93 return ALIGNMENT
- (Value
% ALIGNMENT
);
98 GetVariableStoreStatus (
99 IN VARIABLE_STORE_HEADER
*VarStoreHeader
105 This code gets the pointer to the variable name.
109 VarStoreHeader Pointer to the Variable Store Header.
113 EfiHealthy Variable store is healthy
114 EfiRaw Variable store is raw
115 EfiInvalid Variable store is invalid
119 if (VarStoreHeader
->Signature
== VARIABLE_STORE_SIGNATURE
&&
120 VarStoreHeader
->Format
== VARIABLE_STORE_FORMATTED
&&
121 VarStoreHeader
->State
== VARIABLE_STORE_HEALTHY
125 } else if (VarStoreHeader
->Signature
== 0xffffffff &&
126 VarStoreHeader
->Size
== 0xffffffff &&
127 VarStoreHeader
->Format
== 0xff &&
128 VarStoreHeader
->State
== 0xff
140 IN VARIABLE_HEADER
*Variable
146 This code gets the pointer to the variable data.
150 Variable Pointer to the Variable Header.
154 UINT8* Pointer to Variable Data
158 if (Variable
->StartId
!= VARIABLE_DATA
) {
162 // Be careful about pad size for alignment
164 return (UINT8
*) ((UINTN
) GET_VARIABLE_NAME_PTR (Variable
) + Variable
->NameSize
+ GetPadSize (Variable
->NameSize
));
170 IN VARIABLE_HEADER
*Variable
176 This code gets the pointer to the next variable header.
180 Variable Pointer to the Variable Header.
184 VARIABLE_HEADER* Pointer to next variable header.
188 VARIABLE_HEADER
*VarHeader
;
190 if (Variable
->StartId
!= VARIABLE_DATA
) {
194 // Be careful about pad size for alignment
196 VarHeader
= (VARIABLE_HEADER
*) (GetVariableDataPtr (Variable
) + Variable
->DataSize
+ GET_PAD_SIZE (Variable
->DataSize
));
198 if (VarHeader
->StartId
!= VARIABLE_DATA
||
199 (sizeof (VARIABLE_HEADER
) + VarHeader
->DataSize
+ VarHeader
->NameSize
) > MAX_VARIABLE_SIZE
210 IN VARIABLE_STORE_HEADER
*VolHeader
216 This code gets the pointer to the last variable memory pointer byte
220 Variable Pointer to the Variable Header.
224 VARIABLE_HEADER* Pointer to last unavailable Variable Header
229 // The end of variable store
231 return (VARIABLE_HEADER
*) ((UINTN
) VolHeader
+ VolHeader
->Size
);
237 IN CHAR16
*VariableName
,
238 IN EFI_GUID
*VendorGuid
,
239 OUT VARIABLE_POINTER_TRACK
*PtrTrack
,
240 IN VARIABLE_GLOBAL
*Global
246 This code finds variable in storage blocks (Volatile or Non-Volatile)
250 VariableName Name of the variable to be found
251 VendorGuid Vendor GUID to be found.
252 PtrTrack Variable Track Pointer structure that contains
253 Variable Information.
254 Contains the pointer of Variable header.
255 Global VARIABLE_GLOBAL pointer
263 VARIABLE_HEADER
*Variable
[2];
264 VARIABLE_STORE_HEADER
*VariableStoreHeader
[2];
268 // 0: Non-Volatile, 1: Volatile
270 VariableStoreHeader
[0] = (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->NonVolatileVariableBase
);
271 VariableStoreHeader
[1] = (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->VolatileVariableBase
);
274 // Start Pointers for the variable.
275 // Actual Data Pointer where data can be written.
277 Variable
[0] = (VARIABLE_HEADER
*) (VariableStoreHeader
[0] + 1);
278 Variable
[1] = (VARIABLE_HEADER
*) (VariableStoreHeader
[1] + 1);
280 if (VariableName
[0] != 0 && VendorGuid
== NULL
) {
281 return EFI_INVALID_PARAMETER
;
284 // Find the variable by walk through non-volatile and volatile variable store
286 for (Index
= 0; Index
< 2; Index
++) {
287 PtrTrack
->StartPtr
= (VARIABLE_HEADER
*) (VariableStoreHeader
[Index
] + 1);
288 PtrTrack
->EndPtr
= GetEndPointer (VariableStoreHeader
[Index
]);
290 while ((Variable
[Index
] != NULL
) && (Variable
[Index
] <= GetEndPointer (VariableStoreHeader
[Index
]))) {
291 if (Variable
[Index
]->StartId
== VARIABLE_DATA
&& Variable
[Index
]->State
== VAR_ADDED
) {
292 if (!(EfiAtRuntime () && !(Variable
[Index
]->Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
))) {
293 if (VariableName
[0] == 0) {
294 PtrTrack
->CurrPtr
= Variable
[Index
];
295 PtrTrack
->Volatile
= (BOOLEAN
) Index
;
298 if (CompareGuid (VendorGuid
, &Variable
[Index
]->VendorGuid
)) {
299 if (!CompareMem (VariableName
, GET_VARIABLE_NAME_PTR (Variable
[Index
]), ArrayLength (VariableName
))) {
300 PtrTrack
->CurrPtr
= Variable
[Index
];
301 PtrTrack
->Volatile
= (BOOLEAN
) Index
;
309 Variable
[Index
] = GetNextVariablePtr (Variable
[Index
]);
312 PtrTrack
->CurrPtr
= NULL
;
313 return EFI_NOT_FOUND
;
319 IN CHAR16
*VariableName
,
320 IN EFI_GUID
* VendorGuid
,
321 OUT UINT32
*Attributes OPTIONAL
,
322 IN OUT UINTN
*DataSize
,
324 IN VARIABLE_GLOBAL
* Global
,
331 This code finds variable in storage blocks (Volatile or Non-Volatile)
335 VariableName Name of Variable to be found
336 VendorGuid Variable vendor GUID
337 Attributes OPTIONAL Attribute value of the variable found
338 DataSize Size of Data found. If size is less than the
339 data, this value contains the required size.
341 Global Pointer to VARIABLE_GLOBAL structure
342 Instance Instance of the Firmware Volume.
350 VARIABLE_POINTER_TRACK Variable
;
354 if (VariableName
== NULL
|| VendorGuid
== NULL
|| DataSize
== NULL
) {
355 return EFI_INVALID_PARAMETER
;
358 // Find existing variable
360 Status
= FindVariable (VariableName
, VendorGuid
, &Variable
, Global
);
362 if (Variable
.CurrPtr
== NULL
|| EFI_ERROR (Status
)) {
368 VarDataSize
= Variable
.CurrPtr
->DataSize
;
369 if (*DataSize
>= VarDataSize
) {
370 CopyMem (Data
, GetVariableDataPtr (Variable
.CurrPtr
), VarDataSize
);
372 *Attributes
= Variable
.CurrPtr
->Attributes
;
375 *DataSize
= VarDataSize
;
378 *DataSize
= VarDataSize
;
379 return EFI_BUFFER_TOO_SMALL
;
385 GetNextVariableName (
386 IN OUT UINTN
*VariableNameSize
,
387 IN OUT CHAR16
*VariableName
,
388 IN OUT EFI_GUID
*VendorGuid
,
389 IN VARIABLE_GLOBAL
*Global
,
396 This code Finds the Next available variable
400 VariableNameSize Size of the variable
401 VariableName Pointer to variable name
402 VendorGuid Variable Vendor Guid
403 Global VARIABLE_GLOBAL structure pointer.
412 VARIABLE_POINTER_TRACK Variable
;
416 if (VariableNameSize
== NULL
|| VendorGuid
== NULL
) {
417 return EFI_INVALID_PARAMETER
;
420 Status
= FindVariable (VariableName
, VendorGuid
, &Variable
, Global
);
422 if (Variable
.CurrPtr
== NULL
|| EFI_ERROR (Status
)) {
427 if (VariableName
[0] != 0) {
429 // If variable name is not NULL, get next variable
431 Variable
.CurrPtr
= GetNextVariablePtr (Variable
.CurrPtr
);
434 // If both volatile and non-volatile variable store are parsed,
437 if (Variable
.CurrPtr
>= Variable
.EndPtr
|| Variable
.CurrPtr
== NULL
) {
438 Variable
.Volatile
= (BOOLEAN
) (Variable
.Volatile
^ ((BOOLEAN
) 0x1));
439 if (Variable
.Volatile
) {
440 Variable
.StartPtr
= (VARIABLE_HEADER
*) ((UINTN
) (Global
->VolatileVariableBase
+ sizeof (VARIABLE_STORE_HEADER
)));
441 Variable
.EndPtr
= (VARIABLE_HEADER
*) GetEndPointer ((VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->VolatileVariableBase
));
443 return EFI_NOT_FOUND
;
446 Variable
.CurrPtr
= Variable
.StartPtr
;
447 if (Variable
.CurrPtr
->StartId
!= VARIABLE_DATA
) {
454 if (Variable
.CurrPtr
->StartId
== VARIABLE_DATA
&& Variable
.CurrPtr
->State
== VAR_ADDED
) {
455 if (!(EfiAtRuntime () && !(Variable
.CurrPtr
->Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
))) {
456 VarNameSize
= Variable
.CurrPtr
->NameSize
;
457 if (VarNameSize
<= *VariableNameSize
) {
460 GET_VARIABLE_NAME_PTR (Variable
.CurrPtr
),
465 &Variable
.CurrPtr
->VendorGuid
,
468 Status
= EFI_SUCCESS
;
470 Status
= EFI_BUFFER_TOO_SMALL
;
473 *VariableNameSize
= VarNameSize
;
479 return EFI_NOT_FOUND
;
485 IN CHAR16
*VariableName
,
486 IN EFI_GUID
*VendorGuid
,
487 IN UINT32 Attributes
,
490 IN VARIABLE_GLOBAL
*Global
,
491 IN UINTN
*VolatileOffset
,
492 IN UINTN
*NonVolatileOffset
,
499 This code sets variable in storage blocks (Volatile or Non-Volatile)
503 VariableName Name of Variable to be found
504 VendorGuid Variable vendor GUID
505 Attributes Attribute value of the variable found
506 DataSize Size of Data found. If size is less than the
507 data, this value contains the required size.
509 Global Pointer to VARIABLE_GLOBAL structure
510 VolatileOffset The offset of last volatile variable
511 NonVolatileOffset The offset of last non-volatile variable
512 Instance Instance of the Firmware Volume.
520 VARIABLE_POINTER_TRACK Variable
;
522 VARIABLE_HEADER
*NextVariable
;
528 if (VariableName
== NULL
|| VariableName
[0] == 0 || VendorGuid
== NULL
) {
529 return EFI_INVALID_PARAMETER
;
532 Status
= FindVariable (VariableName
, VendorGuid
, &Variable
, Global
);
534 if (Status
== EFI_INVALID_PARAMETER
) {
538 // The size of the VariableName, including the Unicode Null in bytes plus
539 // the DataSize is limited to maximum size of MAX_VARIABLE_SIZE (1024) bytes.
541 else if (sizeof (VARIABLE_HEADER
) + (ArrayLength (VariableName
) + DataSize
) > MAX_VARIABLE_SIZE
) {
542 return EFI_INVALID_PARAMETER
;
545 // Make sure if runtime bit is set, boot service bit is set also
547 else if ((Attributes
& (EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
)) == EFI_VARIABLE_RUNTIME_ACCESS
549 return EFI_INVALID_PARAMETER
;
552 // Runtime but Attribute is not Runtime
554 else if (EfiAtRuntime () && Attributes
&& !(Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
)) {
555 return EFI_INVALID_PARAMETER
;
558 // Cannot set volatile variable in Runtime
560 else if (EfiAtRuntime () && Attributes
&& !(Attributes
& EFI_VARIABLE_NON_VOLATILE
)) {
561 return EFI_INVALID_PARAMETER
;
564 // Setting a data variable with no access, or zero DataSize attributes
565 // specified causes it to be deleted.
567 else if (DataSize
== 0 || Attributes
== 0) {
568 if (!EFI_ERROR (Status
)) {
569 Variable
.CurrPtr
->State
&= VAR_DELETED
;
573 return EFI_NOT_FOUND
;
575 if (!EFI_ERROR (Status
)) {
577 // If the variable is marked valid and the same data has been passed in
578 // then return to the caller immediately.
580 if (Variable
.CurrPtr
->DataSize
== DataSize
&&
581 !CompareMem (Data
, GetVariableDataPtr (Variable
.CurrPtr
), DataSize
)
584 } else if (Variable
.CurrPtr
->State
== VAR_ADDED
) {
586 // Mark the old variable as in delete transition
588 Variable
.CurrPtr
->State
&= VAR_IN_DELETED_TRANSITION
;
592 // Create a new variable and copy the data.
594 VarNameOffset
= sizeof (VARIABLE_HEADER
);
595 VarNameSize
= ArrayLength (VariableName
);
596 VarDataOffset
= VarNameOffset
+ VarNameSize
+ GetPadSize (VarNameSize
);
597 VarSize
= VarDataOffset
+ DataSize
+ GetPadSize (DataSize
);
599 if (Attributes
& EFI_VARIABLE_NON_VOLATILE
) {
600 if ((UINT32
) (VarSize
+*NonVolatileOffset
) >
601 ((VARIABLE_STORE_HEADER
*) ((UINTN
) (Global
->NonVolatileVariableBase
)))->Size
603 return EFI_OUT_OF_RESOURCES
;
606 NextVariable
= (VARIABLE_HEADER
*) (UINT8
*) (*NonVolatileOffset
+ (UINTN
) Global
->NonVolatileVariableBase
);
607 *NonVolatileOffset
= *NonVolatileOffset
+ VarSize
;
609 if (EfiAtRuntime ()) {
610 return EFI_INVALID_PARAMETER
;
613 if ((UINT32
) (VarSize
+*VolatileOffset
) >
614 ((VARIABLE_STORE_HEADER
*) ((UINTN
) (Global
->VolatileVariableBase
)))->Size
616 return EFI_OUT_OF_RESOURCES
;
619 NextVariable
= (VARIABLE_HEADER
*) (UINT8
*) (*VolatileOffset
+ (UINTN
) Global
->VolatileVariableBase
);
620 *VolatileOffset
= *VolatileOffset
+ VarSize
;
623 NextVariable
->StartId
= VARIABLE_DATA
;
624 NextVariable
->Attributes
= Attributes
;
625 NextVariable
->State
= VAR_ADDED
;
626 NextVariable
->Reserved
= 0;
629 // There will be pad bytes after Data, the NextVariable->NameSize and
630 // NextVariable->NameSize should not include pad size so that variable
631 // service can get actual size in GetVariable
633 NextVariable
->NameSize
= (UINT32
)VarNameSize
;
634 NextVariable
->DataSize
= (UINT32
)DataSize
;
636 CopyMem (&NextVariable
->VendorGuid
, VendorGuid
, sizeof (EFI_GUID
));
638 (UINT8
*) ((UINTN
) NextVariable
+ VarNameOffset
),
643 (UINT8
*) ((UINTN
) NextVariable
+ VarDataOffset
),
649 // Mark the old variable as deleted
651 if (!EFI_ERROR (Status
)) {
652 Variable
.CurrPtr
->State
&= VAR_DELETED
;
659 #if (EFI_SPECIFICATION_VERSION >= 0x00020000)
663 IN UINT32 Attributes
,
664 OUT UINT64
*MaximumVariableStorageSize
,
665 OUT UINT64
*RemainingVariableStorageSize
,
666 OUT UINT64
*MaximumVariableSize
,
667 IN VARIABLE_GLOBAL
*Global
,
674 This code returns information about the EFI variables.
678 Attributes Attributes bitmask to specify the type of variables
679 on which to return information.
680 MaximumVariableStorageSize Pointer to the maximum size of the storage space available
681 for the EFI variables associated with the attributes specified.
682 RemainingVariableStorageSize Pointer to the remaining size of the storage space available
683 for the EFI variables associated with the attributes specified.
684 MaximumVariableSize Pointer to the maximum size of the individual EFI variables
685 associated with the attributes specified.
686 Global Pointer to VARIABLE_GLOBAL structure.
687 Instance Instance of the Firmware Volume.
692 EFI_INVALID_PARAMETER - An invalid combination of attribute bits was supplied.
693 EFI_SUCCESS - Query successfully.
694 EFI_UNSUPPORTED - The attribute is not supported on this platform.
698 VARIABLE_HEADER
*Variable
;
699 VARIABLE_HEADER
*NextVariable
;
701 VARIABLE_STORE_HEADER
*VariableStoreHeader
;
703 if(MaximumVariableStorageSize
== NULL
|| RemainingVariableStorageSize
== NULL
|| MaximumVariableSize
== NULL
) {
704 return EFI_INVALID_PARAMETER
;
707 if((Attributes
& (EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
)) == 0) {
709 // Make sure the Attributes combination is supported by the platform.
711 return EFI_UNSUPPORTED
;
712 } else if ((Attributes
& (EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
)) == EFI_VARIABLE_RUNTIME_ACCESS
) {
714 // Make sure if runtime bit is set, boot service bit is set also.
716 return EFI_INVALID_PARAMETER
;
717 } else if (EfiAtRuntime () && !(Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
)) {
719 // Make sure RT Attribute is set if we are in Runtime phase.
721 return EFI_INVALID_PARAMETER
;
724 if((Attributes
& EFI_VARIABLE_NON_VOLATILE
) == 0) {
726 // Query is Volatile related.
728 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->VolatileVariableBase
);
731 // Query is Non-Volatile related.
733 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->NonVolatileVariableBase
);
737 // Now let's fill *MaximumVariableStorageSize *RemainingVariableStorageSize
738 // with the storage size (excluding the storage header size)
740 *MaximumVariableStorageSize
= VariableStoreHeader
->Size
- sizeof (VARIABLE_STORE_HEADER
);
741 *RemainingVariableStorageSize
= VariableStoreHeader
->Size
- sizeof (VARIABLE_STORE_HEADER
);
744 // Let *MaximumVariableSize be MAX_VARIABLE_SIZE
746 *MaximumVariableSize
= MAX_VARIABLE_SIZE
;
749 // Point to the starting address of the variables.
751 Variable
= (VARIABLE_HEADER
*) (VariableStoreHeader
+ 1);
754 // Now walk through the related variable store.
756 while (Variable
< GetEndPointer (VariableStoreHeader
)) {
757 if (Variable
->StartId
!= VARIABLE_DATA
) {
761 NextVariable
= (VARIABLE_HEADER
*) (GetVariableDataPtr (Variable
) + Variable
->DataSize
+ GET_PAD_SIZE (Variable
->DataSize
));
762 VariableSize
= (UINT64
) (UINTN
) NextVariable
- (UINT64
) (UINTN
) Variable
;
764 if (Variable
->State
== VAR_ADDED
) {
765 *RemainingVariableStorageSize
-= VariableSize
;
769 // Go to the next one.
771 Variable
= NextVariable
;
780 InitializeVariableStore (
781 OUT EFI_PHYSICAL_ADDRESS
*VariableBase
,
782 OUT UINTN
*LastVariableOffset
787 This function initializes variable store
795 VARIABLE_STORE_HEADER
*VariableStore
;
798 // Allocate memory for volatile variable store
800 VariableStore
= (VARIABLE_STORE_HEADER
*) AllocateRuntimePool (
803 if (NULL
== VariableStore
) {
804 return EFI_OUT_OF_RESOURCES
;
807 SetMem (VariableStore
, VARIABLE_STORE_SIZE
, 0xff);
810 // Variable Specific Data
812 *VariableBase
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) VariableStore
;
813 *LastVariableOffset
= sizeof (VARIABLE_STORE_HEADER
);
815 VariableStore
->Signature
= VARIABLE_STORE_SIGNATURE
;
816 VariableStore
->Size
= VARIABLE_STORE_SIZE
;
817 VariableStore
->Format
= VARIABLE_STORE_FORMATTED
;
818 VariableStore
->State
= VARIABLE_STORE_HEALTHY
;
819 VariableStore
->Reserved
= 0;
820 VariableStore
->Reserved1
= 0;
827 VariableCommonInitialize (
828 IN EFI_HANDLE ImageHandle
,
829 IN EFI_SYSTEM_TABLE
*SystemTable
834 This function does common initialization for variable services
845 // Allocate memory for mVariableModuleGlobal
847 mVariableModuleGlobal
= (ESAL_VARIABLE_GLOBAL
*) AllocateRuntimePool (
848 sizeof (ESAL_VARIABLE_GLOBAL
)
850 if (NULL
== mVariableModuleGlobal
) {
851 return EFI_OUT_OF_RESOURCES
;
854 // Intialize volatile variable store
856 Status
= InitializeVariableStore (
857 &mVariableModuleGlobal
->VariableBase
[Physical
].VolatileVariableBase
,
858 &mVariableModuleGlobal
->VolatileLastVariableOffset
861 if (EFI_ERROR (Status
)) {
865 // Intialize non volatile variable store
867 Status
= InitializeVariableStore (
868 &mVariableModuleGlobal
->VariableBase
[Physical
].NonVolatileVariableBase
,
869 &mVariableModuleGlobal
->NonVolatileLastVariableOffset