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;
67 GetVariableStoreStatus (
68 IN VARIABLE_STORE_HEADER
*VarStoreHeader
74 This code gets the pointer to the variable name.
78 VarStoreHeader Pointer to the Variable Store Header.
82 EfiHealthy Variable store is healthy
83 EfiRaw Variable store is raw
84 EfiInvalid Variable store is invalid
88 if (VarStoreHeader
->Signature
== VARIABLE_STORE_SIGNATURE
&&
89 VarStoreHeader
->Format
== VARIABLE_STORE_FORMATTED
&&
90 VarStoreHeader
->State
== VARIABLE_STORE_HEALTHY
94 } else if (VarStoreHeader
->Signature
== 0xffffffff &&
95 VarStoreHeader
->Size
== 0xffffffff &&
96 VarStoreHeader
->Format
== 0xff &&
97 VarStoreHeader
->State
== 0xff
109 IN VARIABLE_HEADER
*Variable
115 This code gets the pointer to the variable data.
119 Variable Pointer to the Variable Header.
123 UINT8* Pointer to Variable Data
127 if (Variable
->StartId
!= VARIABLE_DATA
) {
131 // Be careful about pad size for alignment
133 return (UINT8
*) ((UINTN
) GET_VARIABLE_NAME_PTR (Variable
) + Variable
->NameSize
+ GET_PAD_SIZE (Variable
->NameSize
));
139 IN VARIABLE_HEADER
*Variable
145 This code gets the pointer to the next variable header.
149 Variable Pointer to the Variable Header.
153 VARIABLE_HEADER* Pointer to next variable header.
157 VARIABLE_HEADER
*VarHeader
;
159 if (Variable
->StartId
!= VARIABLE_DATA
) {
163 // Be careful about pad size for alignment
165 VarHeader
= (VARIABLE_HEADER
*) (GetVariableDataPtr (Variable
) + Variable
->DataSize
+ GET_PAD_SIZE (Variable
->DataSize
));
167 if (VarHeader
->StartId
!= VARIABLE_DATA
||
168 (sizeof (VARIABLE_HEADER
) + VarHeader
->DataSize
+ VarHeader
->NameSize
) > MAX_VARIABLE_SIZE
179 IN VARIABLE_STORE_HEADER
*VolHeader
185 This code gets the pointer to the last variable memory pointer byte
189 Variable Pointer to the Variable Header.
193 VARIABLE_HEADER* Pointer to last unavailable Variable Header
198 // The end of variable store
200 return (VARIABLE_HEADER
*) ((UINTN
) VolHeader
+ VolHeader
->Size
);
206 IN CHAR16
*VariableName
,
207 IN EFI_GUID
*VendorGuid
,
208 OUT VARIABLE_POINTER_TRACK
*PtrTrack
,
209 IN VARIABLE_GLOBAL
*Global
215 This code finds variable in storage blocks (Volatile or Non-Volatile)
219 VariableName Name of the variable to be found
220 VendorGuid Vendor GUID to be found.
221 PtrTrack Variable Track Pointer structure that contains
222 Variable Information.
223 Contains the pointer of Variable header.
224 Global VARIABLE_GLOBAL pointer
232 VARIABLE_HEADER
*Variable
[2];
233 VARIABLE_STORE_HEADER
*VariableStoreHeader
[2];
237 // 0: Non-Volatile, 1: Volatile
239 VariableStoreHeader
[0] = (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->NonVolatileVariableBase
);
240 VariableStoreHeader
[1] = (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->VolatileVariableBase
);
243 // Start Pointers for the variable.
244 // Actual Data Pointer where data can be written.
246 Variable
[0] = (VARIABLE_HEADER
*) (VariableStoreHeader
[0] + 1);
247 Variable
[1] = (VARIABLE_HEADER
*) (VariableStoreHeader
[1] + 1);
249 if (VariableName
[0] != 0 && VendorGuid
== NULL
) {
250 return EFI_INVALID_PARAMETER
;
253 // Find the variable by walk through non-volatile and volatile variable store
255 for (Index
= 0; Index
< 2; Index
++) {
256 PtrTrack
->StartPtr
= (VARIABLE_HEADER
*) (VariableStoreHeader
[Index
] + 1);
257 PtrTrack
->EndPtr
= GetEndPointer (VariableStoreHeader
[Index
]);
259 while ((Variable
[Index
] != NULL
) && (Variable
[Index
] <= GetEndPointer (VariableStoreHeader
[Index
]))) {
260 if (Variable
[Index
]->StartId
== VARIABLE_DATA
&& Variable
[Index
]->State
== VAR_ADDED
) {
261 if (!(EfiAtRuntime () && !(Variable
[Index
]->Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
))) {
262 if (VariableName
[0] == 0) {
263 PtrTrack
->CurrPtr
= Variable
[Index
];
264 PtrTrack
->Volatile
= (BOOLEAN
) Index
;
267 if (CompareGuid (VendorGuid
, &Variable
[Index
]->VendorGuid
)) {
268 if (!CompareMem (VariableName
, GET_VARIABLE_NAME_PTR (Variable
[Index
]), ArrayLength (VariableName
))) {
269 PtrTrack
->CurrPtr
= Variable
[Index
];
270 PtrTrack
->Volatile
= (BOOLEAN
) Index
;
278 Variable
[Index
] = GetNextVariablePtr (Variable
[Index
]);
281 PtrTrack
->CurrPtr
= NULL
;
282 return EFI_NOT_FOUND
;
288 IN CHAR16
*VariableName
,
289 IN EFI_GUID
* VendorGuid
,
290 OUT UINT32
*Attributes OPTIONAL
,
291 IN OUT UINTN
*DataSize
,
293 IN VARIABLE_GLOBAL
* Global
,
300 This code finds variable in storage blocks (Volatile or Non-Volatile)
304 VariableName Name of Variable to be found
305 VendorGuid Variable vendor GUID
306 Attributes OPTIONAL Attribute value of the variable found
307 DataSize Size of Data found. If size is less than the
308 data, this value contains the required size.
310 Global Pointer to VARIABLE_GLOBAL structure
311 Instance Instance of the Firmware Volume.
319 VARIABLE_POINTER_TRACK Variable
;
323 if (VariableName
== NULL
|| VendorGuid
== NULL
|| DataSize
== NULL
) {
324 return EFI_INVALID_PARAMETER
;
327 // Find existing variable
329 Status
= FindVariable (VariableName
, VendorGuid
, &Variable
, Global
);
331 if (Variable
.CurrPtr
== NULL
|| EFI_ERROR (Status
)) {
337 VarDataSize
= Variable
.CurrPtr
->DataSize
;
338 if (*DataSize
>= VarDataSize
) {
340 return EFI_INVALID_PARAMETER
;
343 CopyMem (Data
, GetVariableDataPtr (Variable
.CurrPtr
), VarDataSize
);
344 if (Attributes
!= NULL
) {
345 *Attributes
= Variable
.CurrPtr
->Attributes
;
348 *DataSize
= VarDataSize
;
351 *DataSize
= VarDataSize
;
352 return EFI_BUFFER_TOO_SMALL
;
358 GetNextVariableName (
359 IN OUT UINTN
*VariableNameSize
,
360 IN OUT CHAR16
*VariableName
,
361 IN OUT EFI_GUID
*VendorGuid
,
362 IN VARIABLE_GLOBAL
*Global
,
369 This code Finds the Next available variable
373 VariableNameSize Size of the variable
374 VariableName Pointer to variable name
375 VendorGuid Variable Vendor Guid
376 Global VARIABLE_GLOBAL structure pointer.
385 VARIABLE_POINTER_TRACK Variable
;
389 if (VariableNameSize
== NULL
|| VariableName
== NULL
|| VendorGuid
== NULL
) {
390 return EFI_INVALID_PARAMETER
;
393 Status
= FindVariable (VariableName
, VendorGuid
, &Variable
, Global
);
395 if (Variable
.CurrPtr
== NULL
|| EFI_ERROR (Status
)) {
400 if (VariableName
[0] != 0) {
402 // If variable name is not NULL, get next variable
404 Variable
.CurrPtr
= GetNextVariablePtr (Variable
.CurrPtr
);
407 // If both volatile and non-volatile variable store are parsed,
410 if (Variable
.CurrPtr
>= Variable
.EndPtr
|| Variable
.CurrPtr
== NULL
) {
411 Variable
.Volatile
= (BOOLEAN
) (Variable
.Volatile
^ ((BOOLEAN
) 0x1));
412 if (Variable
.Volatile
) {
413 Variable
.StartPtr
= (VARIABLE_HEADER
*) ((UINTN
) (Global
->VolatileVariableBase
+ sizeof (VARIABLE_STORE_HEADER
)));
414 Variable
.EndPtr
= (VARIABLE_HEADER
*) GetEndPointer ((VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->VolatileVariableBase
));
416 return EFI_NOT_FOUND
;
419 Variable
.CurrPtr
= Variable
.StartPtr
;
420 if (Variable
.CurrPtr
->StartId
!= VARIABLE_DATA
) {
427 if (Variable
.CurrPtr
->StartId
== VARIABLE_DATA
&& Variable
.CurrPtr
->State
== VAR_ADDED
) {
428 if (!(EfiAtRuntime () && !(Variable
.CurrPtr
->Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
))) {
429 VarNameSize
= Variable
.CurrPtr
->NameSize
;
430 if (VarNameSize
<= *VariableNameSize
) {
433 GET_VARIABLE_NAME_PTR (Variable
.CurrPtr
),
438 &Variable
.CurrPtr
->VendorGuid
,
441 Status
= EFI_SUCCESS
;
443 Status
= EFI_BUFFER_TOO_SMALL
;
446 *VariableNameSize
= VarNameSize
;
452 return EFI_NOT_FOUND
;
458 IN CHAR16
*VariableName
,
459 IN EFI_GUID
*VendorGuid
,
460 IN UINT32 Attributes
,
463 IN VARIABLE_GLOBAL
*Global
,
464 IN UINTN
*VolatileOffset
,
465 IN UINTN
*NonVolatileOffset
,
472 This code sets variable in storage blocks (Volatile or Non-Volatile)
476 VariableName Name of Variable to be found
477 VendorGuid Variable vendor GUID
478 Attributes Attribute value of the variable found
479 DataSize Size of Data found. If size is less than the
480 data, this value contains the required size.
482 Global Pointer to VARIABLE_GLOBAL structure
483 VolatileOffset The offset of last volatile variable
484 NonVolatileOffset The offset of last non-volatile variable
485 Instance Instance of the Firmware Volume.
493 VARIABLE_POINTER_TRACK Variable
;
495 VARIABLE_HEADER
*NextVariable
;
501 if (VariableName
== NULL
|| VariableName
[0] == 0 || VendorGuid
== NULL
) {
502 return EFI_INVALID_PARAMETER
;
505 Status
= FindVariable (VariableName
, VendorGuid
, &Variable
, Global
);
507 if (Status
== EFI_INVALID_PARAMETER
) {
511 // The size of the VariableName, including the Unicode Null in bytes plus
512 // the DataSize is limited to maximum size of MAX_VARIABLE_SIZE (1024) bytes.
514 else if (sizeof (VARIABLE_HEADER
) + (ArrayLength (VariableName
) + DataSize
) > MAX_VARIABLE_SIZE
) {
515 return EFI_INVALID_PARAMETER
;
518 // Make sure if runtime bit is set, boot service bit is set also
520 else if ((Attributes
& (EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
)) == EFI_VARIABLE_RUNTIME_ACCESS
522 return EFI_INVALID_PARAMETER
;
525 // Runtime but Attribute is not Runtime
527 else if (EfiAtRuntime () && Attributes
&& !(Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
)) {
528 return EFI_INVALID_PARAMETER
;
531 // Cannot set volatile variable in Runtime
533 else if (EfiAtRuntime () && Attributes
&& !(Attributes
& EFI_VARIABLE_NON_VOLATILE
)) {
534 return EFI_INVALID_PARAMETER
;
537 // Setting a data variable with no access, or zero DataSize attributes
538 // specified causes it to be deleted.
540 else if (DataSize
== 0 || Attributes
== 0) {
541 if (!EFI_ERROR (Status
)) {
542 Variable
.CurrPtr
->State
&= VAR_DELETED
;
546 return EFI_NOT_FOUND
;
548 if (!EFI_ERROR (Status
)) {
550 // If the variable is marked valid and the same data has been passed in
551 // then return to the caller immediately.
553 if (Variable
.CurrPtr
->DataSize
== DataSize
&&
554 !CompareMem (Data
, GetVariableDataPtr (Variable
.CurrPtr
), DataSize
)
557 } else if (Variable
.CurrPtr
->State
== VAR_ADDED
) {
559 // Mark the old variable as in delete transition
561 Variable
.CurrPtr
->State
&= VAR_IN_DELETED_TRANSITION
;
565 // Create a new variable and copy the data.
567 VarNameOffset
= sizeof (VARIABLE_HEADER
);
568 VarNameSize
= ArrayLength (VariableName
);
569 VarDataOffset
= VarNameOffset
+ VarNameSize
+ GET_PAD_SIZE (VarNameSize
);
570 VarSize
= VarDataOffset
+ DataSize
+ GET_PAD_SIZE (DataSize
);
572 if (Attributes
& EFI_VARIABLE_NON_VOLATILE
) {
573 if ((UINT32
) (VarSize
+*NonVolatileOffset
) >
574 ((VARIABLE_STORE_HEADER
*) ((UINTN
) (Global
->NonVolatileVariableBase
)))->Size
576 return EFI_OUT_OF_RESOURCES
;
579 NextVariable
= (VARIABLE_HEADER
*) (UINT8
*) (*NonVolatileOffset
+ (UINTN
) Global
->NonVolatileVariableBase
);
580 *NonVolatileOffset
= *NonVolatileOffset
+ VarSize
;
582 if (EfiAtRuntime ()) {
583 return EFI_INVALID_PARAMETER
;
586 if ((UINT32
) (VarSize
+*VolatileOffset
) >
587 ((VARIABLE_STORE_HEADER
*) ((UINTN
) (Global
->VolatileVariableBase
)))->Size
589 return EFI_OUT_OF_RESOURCES
;
592 NextVariable
= (VARIABLE_HEADER
*) (UINT8
*) (*VolatileOffset
+ (UINTN
) Global
->VolatileVariableBase
);
593 *VolatileOffset
= *VolatileOffset
+ VarSize
;
596 NextVariable
->StartId
= VARIABLE_DATA
;
597 NextVariable
->Attributes
= Attributes
;
598 NextVariable
->State
= VAR_ADDED
;
599 NextVariable
->Reserved
= 0;
602 // There will be pad bytes after Data, the NextVariable->NameSize and
603 // NextVariable->NameSize should not include pad size so that variable
604 // service can get actual size in GetVariable
606 NextVariable
->NameSize
= (UINT32
)VarNameSize
;
607 NextVariable
->DataSize
= (UINT32
)DataSize
;
609 CopyMem (&NextVariable
->VendorGuid
, VendorGuid
, sizeof (EFI_GUID
));
611 (UINT8
*) ((UINTN
) NextVariable
+ VarNameOffset
),
616 (UINT8
*) ((UINTN
) NextVariable
+ VarDataOffset
),
622 // Mark the old variable as deleted
624 if (!EFI_ERROR (Status
)) {
625 Variable
.CurrPtr
->State
&= VAR_DELETED
;
632 #if (EFI_SPECIFICATION_VERSION >= 0x00020000)
636 IN UINT32 Attributes
,
637 OUT UINT64
*MaximumVariableStorageSize
,
638 OUT UINT64
*RemainingVariableStorageSize
,
639 OUT UINT64
*MaximumVariableSize
,
640 IN VARIABLE_GLOBAL
*Global
,
647 This code returns information about the EFI variables.
651 Attributes Attributes bitmask to specify the type of variables
652 on which to return information.
653 MaximumVariableStorageSize Pointer to the maximum size of the storage space available
654 for the EFI variables associated with the attributes specified.
655 RemainingVariableStorageSize Pointer to the remaining size of the storage space available
656 for the EFI variables associated with the attributes specified.
657 MaximumVariableSize Pointer to the maximum size of the individual EFI variables
658 associated with the attributes specified.
659 Global Pointer to VARIABLE_GLOBAL structure.
660 Instance Instance of the Firmware Volume.
665 EFI_INVALID_PARAMETER - An invalid combination of attribute bits was supplied.
666 EFI_SUCCESS - Query successfully.
667 EFI_UNSUPPORTED - The attribute is not supported on this platform.
671 VARIABLE_HEADER
*Variable
;
672 VARIABLE_HEADER
*NextVariable
;
674 VARIABLE_STORE_HEADER
*VariableStoreHeader
;
676 if(MaximumVariableStorageSize
== NULL
|| RemainingVariableStorageSize
== NULL
|| MaximumVariableSize
== NULL
) {
677 return EFI_INVALID_PARAMETER
;
680 if((Attributes
& (EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
)) == 0) {
682 // Make sure the Attributes combination is supported by the platform.
684 return EFI_UNSUPPORTED
;
685 } else if ((Attributes
& (EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
)) == EFI_VARIABLE_RUNTIME_ACCESS
) {
687 // Make sure if runtime bit is set, boot service bit is set also.
689 return EFI_INVALID_PARAMETER
;
690 } else if (EfiAtRuntime () && !(Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
)) {
692 // Make sure RT Attribute is set if we are in Runtime phase.
694 return EFI_INVALID_PARAMETER
;
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
;
753 InitializeVariableStore (
754 OUT EFI_PHYSICAL_ADDRESS
*VariableBase
,
755 OUT UINTN
*LastVariableOffset
760 This function initializes variable store
768 VARIABLE_STORE_HEADER
*VariableStore
;
771 // Allocate memory for volatile variable store
773 VariableStore
= (VARIABLE_STORE_HEADER
*) AllocateRuntimePool (
776 if (NULL
== VariableStore
) {
777 return EFI_OUT_OF_RESOURCES
;
780 SetMem (VariableStore
, VARIABLE_STORE_SIZE
, 0xff);
783 // Variable Specific Data
785 *VariableBase
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) VariableStore
;
786 *LastVariableOffset
= sizeof (VARIABLE_STORE_HEADER
);
788 VariableStore
->Signature
= VARIABLE_STORE_SIGNATURE
;
789 VariableStore
->Size
= VARIABLE_STORE_SIZE
;
790 VariableStore
->Format
= VARIABLE_STORE_FORMATTED
;
791 VariableStore
->State
= VARIABLE_STORE_HEALTHY
;
792 VariableStore
->Reserved
= 0;
793 VariableStore
->Reserved1
= 0;
800 VariableCommonInitialize (
801 IN EFI_HANDLE ImageHandle
,
802 IN EFI_SYSTEM_TABLE
*SystemTable
807 This function does common initialization for variable services
818 // Allocate memory for mVariableModuleGlobal
820 mVariableModuleGlobal
= (ESAL_VARIABLE_GLOBAL
*) AllocateRuntimePool (
821 sizeof (ESAL_VARIABLE_GLOBAL
)
823 if (NULL
== mVariableModuleGlobal
) {
824 return EFI_OUT_OF_RESOURCES
;
827 // Intialize volatile variable store
829 Status
= InitializeVariableStore (
830 &mVariableModuleGlobal
->VariableBase
[Physical
].VolatileVariableBase
,
831 &mVariableModuleGlobal
->VolatileLastVariableOffset
834 if (EFI_ERROR (Status
)) {
838 // Intialize non volatile variable store
840 Status
= InitializeVariableStore (
841 &mVariableModuleGlobal
->VariableBase
[Physical
].NonVolatileVariableBase
,
842 &mVariableModuleGlobal
->NonVolatileLastVariableOffset