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
;
39 Determine the length of null terminated char16 array.
43 String Null-terminated CHAR16 array pointer.
47 UINT32 Number of bytes in the string, including the double NULL at the end;
59 while (0 != String
[Count
]) {
63 return (Count
* 2) + 2;
69 GetVariableStoreStatus (
70 IN VARIABLE_STORE_HEADER
*VarStoreHeader
76 This code gets the pointer to the variable name.
80 VarStoreHeader Pointer to the Variable Store Header.
84 EfiHealthy Variable store is healthy
85 EfiRaw Variable store is raw
86 EfiInvalid Variable store is invalid
90 if (VarStoreHeader
->Signature
== VARIABLE_STORE_SIGNATURE
&&
91 VarStoreHeader
->Format
== VARIABLE_STORE_FORMATTED
&&
92 VarStoreHeader
->State
== VARIABLE_STORE_HEALTHY
96 } else if (VarStoreHeader
->Signature
== 0xffffffff &&
97 VarStoreHeader
->Size
== 0xffffffff &&
98 VarStoreHeader
->Format
== 0xff &&
99 VarStoreHeader
->State
== 0xff
112 IN VARIABLE_HEADER
*Variable
118 This code gets the pointer to the variable data.
122 Variable Pointer to the Variable Header.
126 UINT8* Pointer to Variable Data
130 if (Variable
->StartId
!= VARIABLE_DATA
) {
134 // Be careful about pad size for alignment
136 return (UINT8
*) ((UINTN
) GET_VARIABLE_NAME_PTR (Variable
) + Variable
->NameSize
+ GET_PAD_SIZE (Variable
->NameSize
));
143 IN VARIABLE_HEADER
*Variable
149 This code gets the pointer to the next variable header.
153 Variable Pointer to the Variable Header.
157 VARIABLE_HEADER* Pointer to next variable header.
161 VARIABLE_HEADER
*VarHeader
;
163 if (Variable
->StartId
!= VARIABLE_DATA
) {
167 // Be careful about pad size for alignment
169 VarHeader
= (VARIABLE_HEADER
*) (GetVariableDataPtr (Variable
) + Variable
->DataSize
+ GET_PAD_SIZE (Variable
->DataSize
));
171 if (VarHeader
->StartId
!= VARIABLE_DATA
||
172 (sizeof (VARIABLE_HEADER
) + VarHeader
->DataSize
+ VarHeader
->NameSize
) > MAX_VARIABLE_SIZE
184 IN VARIABLE_STORE_HEADER
*VolHeader
190 This code gets the pointer to the last variable memory pointer byte
194 Variable Pointer to the Variable Header.
198 VARIABLE_HEADER* Pointer to last unavailable Variable Header
203 // The end of variable store
205 return (VARIABLE_HEADER
*) ((UINTN
) VolHeader
+ VolHeader
->Size
);
212 IN CHAR16
*VariableName
,
213 IN EFI_GUID
*VendorGuid
,
214 OUT VARIABLE_POINTER_TRACK
*PtrTrack
,
215 IN VARIABLE_GLOBAL
*Global
221 This code finds variable in storage blocks (Volatile or Non-Volatile)
225 VariableName Name of the variable to be found
226 VendorGuid Vendor GUID to be found.
227 PtrTrack Variable Track Pointer structure that contains
228 Variable Information.
229 Contains the pointer of Variable header.
230 Global VARIABLE_GLOBAL pointer
238 VARIABLE_HEADER
*Variable
[2];
239 VARIABLE_STORE_HEADER
*VariableStoreHeader
[2];
243 // 0: Non-Volatile, 1: Volatile
245 VariableStoreHeader
[0] = (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->NonVolatileVariableBase
);
246 VariableStoreHeader
[1] = (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->VolatileVariableBase
);
249 // Start Pointers for the variable.
250 // Actual Data Pointer where data can be written.
252 Variable
[0] = (VARIABLE_HEADER
*) (VariableStoreHeader
[0] + 1);
253 Variable
[1] = (VARIABLE_HEADER
*) (VariableStoreHeader
[1] + 1);
255 if (VariableName
[0] != 0 && VendorGuid
== NULL
) {
256 return EFI_INVALID_PARAMETER
;
259 // Find the variable by walk through non-volatile and volatile variable store
261 for (Index
= 0; Index
< 2; Index
++) {
262 PtrTrack
->StartPtr
= (VARIABLE_HEADER
*) (VariableStoreHeader
[Index
] + 1);
263 PtrTrack
->EndPtr
= GetEndPointer (VariableStoreHeader
[Index
]);
265 while ((Variable
[Index
] != NULL
) && (Variable
[Index
] <= GetEndPointer (VariableStoreHeader
[Index
]))) {
266 if (Variable
[Index
]->StartId
== VARIABLE_DATA
&& Variable
[Index
]->State
== VAR_ADDED
) {
267 if (!(EfiAtRuntime () && !(Variable
[Index
]->Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
))) {
268 if (VariableName
[0] == 0) {
269 PtrTrack
->CurrPtr
= Variable
[Index
];
270 PtrTrack
->Volatile
= (BOOLEAN
) Index
;
273 if (CompareGuid (VendorGuid
, &Variable
[Index
]->VendorGuid
)) {
274 if (!CompareMem (VariableName
, GET_VARIABLE_NAME_PTR (Variable
[Index
]), ArrayLength (VariableName
))) {
275 PtrTrack
->CurrPtr
= Variable
[Index
];
276 PtrTrack
->Volatile
= (BOOLEAN
) Index
;
284 Variable
[Index
] = GetNextVariablePtr (Variable
[Index
]);
287 PtrTrack
->CurrPtr
= NULL
;
288 return EFI_NOT_FOUND
;
294 IN CHAR16
*VariableName
,
295 IN EFI_GUID
* VendorGuid
,
296 OUT UINT32
*Attributes OPTIONAL
,
297 IN OUT UINTN
*DataSize
,
299 IN VARIABLE_GLOBAL
* Global
,
306 This code finds variable in storage blocks (Volatile or Non-Volatile)
310 VariableName Name of Variable to be found
311 VendorGuid Variable vendor GUID
312 Attributes OPTIONAL Attribute value of the variable found
313 DataSize Size of Data found. If size is less than the
314 data, this value contains the required size.
316 Global Pointer to VARIABLE_GLOBAL structure
317 Instance Instance of the Firmware Volume.
325 VARIABLE_POINTER_TRACK Variable
;
329 if (VariableName
== NULL
|| VendorGuid
== NULL
|| DataSize
== NULL
) {
330 return EFI_INVALID_PARAMETER
;
333 // Find existing variable
335 Status
= FindVariable (VariableName
, VendorGuid
, &Variable
, Global
);
337 if (Variable
.CurrPtr
== NULL
|| EFI_ERROR (Status
)) {
343 VarDataSize
= Variable
.CurrPtr
->DataSize
;
344 if (*DataSize
>= VarDataSize
) {
346 return EFI_INVALID_PARAMETER
;
349 CopyMem (Data
, GetVariableDataPtr (Variable
.CurrPtr
), VarDataSize
);
350 if (Attributes
!= NULL
) {
351 *Attributes
= Variable
.CurrPtr
->Attributes
;
354 *DataSize
= VarDataSize
;
357 *DataSize
= VarDataSize
;
358 return EFI_BUFFER_TOO_SMALL
;
364 GetNextVariableName (
365 IN OUT UINTN
*VariableNameSize
,
366 IN OUT CHAR16
*VariableName
,
367 IN OUT EFI_GUID
*VendorGuid
,
368 IN VARIABLE_GLOBAL
*Global
,
375 This code Finds the Next available variable
379 VariableNameSize Size of the variable
380 VariableName Pointer to variable name
381 VendorGuid Variable Vendor Guid
382 Global VARIABLE_GLOBAL structure pointer.
391 VARIABLE_POINTER_TRACK Variable
;
395 if (VariableNameSize
== NULL
|| VariableName
== NULL
|| VendorGuid
== NULL
) {
396 return EFI_INVALID_PARAMETER
;
399 Status
= FindVariable (VariableName
, VendorGuid
, &Variable
, Global
);
401 if (Variable
.CurrPtr
== NULL
|| EFI_ERROR (Status
)) {
406 if (VariableName
[0] != 0) {
408 // If variable name is not NULL, get next variable
410 Variable
.CurrPtr
= GetNextVariablePtr (Variable
.CurrPtr
);
413 // If both volatile and non-volatile variable store are parsed,
416 if (Variable
.CurrPtr
>= Variable
.EndPtr
|| Variable
.CurrPtr
== NULL
) {
417 Variable
.Volatile
= (BOOLEAN
) (Variable
.Volatile
^ ((BOOLEAN
) 0x1));
418 if (Variable
.Volatile
) {
419 Variable
.StartPtr
= (VARIABLE_HEADER
*) ((UINTN
) (Global
->VolatileVariableBase
+ sizeof (VARIABLE_STORE_HEADER
)));
420 Variable
.EndPtr
= (VARIABLE_HEADER
*) GetEndPointer ((VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->VolatileVariableBase
));
425 Variable
.CurrPtr
= Variable
.StartPtr
;
426 if (Variable
.CurrPtr
->StartId
!= VARIABLE_DATA
) {
433 if (Variable
.CurrPtr
->StartId
== VARIABLE_DATA
&& Variable
.CurrPtr
->State
== VAR_ADDED
) {
434 if (!(EfiAtRuntime () && !(Variable
.CurrPtr
->Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
))) {
435 VarNameSize
= Variable
.CurrPtr
->NameSize
;
436 if (VarNameSize
<= *VariableNameSize
) {
439 GET_VARIABLE_NAME_PTR (Variable
.CurrPtr
),
444 &Variable
.CurrPtr
->VendorGuid
,
447 Status
= EFI_SUCCESS
;
449 Status
= EFI_BUFFER_TOO_SMALL
;
452 *VariableNameSize
= VarNameSize
;
459 return EFI_NOT_FOUND
;
465 IN CHAR16
*VariableName
,
466 IN EFI_GUID
*VendorGuid
,
467 IN UINT32 Attributes
,
470 IN VARIABLE_GLOBAL
*Global
,
471 IN UINTN
*VolatileOffset
,
472 IN UINTN
*NonVolatileOffset
,
479 This code sets variable in storage blocks (Volatile or Non-Volatile)
483 VariableName Name of Variable to be found
484 VendorGuid Variable vendor GUID
485 Attributes Attribute value of the variable found
486 DataSize Size of Data found. If size is less than the
487 data, this value contains the required size.
489 Global Pointer to VARIABLE_GLOBAL structure
490 VolatileOffset The offset of last volatile variable
491 NonVolatileOffset The offset of last non-volatile variable
492 Instance Instance of the Firmware Volume.
500 VARIABLE_POINTER_TRACK Variable
;
502 VARIABLE_HEADER
*NextVariable
;
508 if (VariableName
== NULL
|| VariableName
[0] == 0 || VendorGuid
== NULL
) {
509 return EFI_INVALID_PARAMETER
;
512 Status
= FindVariable (VariableName
, VendorGuid
, &Variable
, Global
);
514 if (Status
== EFI_INVALID_PARAMETER
) {
516 } else if (!EFI_ERROR (Status
) && Variable
.Volatile
&& EfiAtRuntime()) {
518 // If EfiAtRuntime and the variable is Volatile and Runtime Access,
519 // the volatile is ReadOnly, and SetVariable should be aborted and
520 // return EFI_WRITE_PROTECTED.
522 return EFI_WRITE_PROTECTED
;
523 } else if (sizeof (VARIABLE_HEADER
) + (ArrayLength (VariableName
) + DataSize
) > MAX_VARIABLE_SIZE
) {
525 // The size of the VariableName, including the Unicode Null in bytes plus
526 // the DataSize is limited to maximum size of MAX_VARIABLE_SIZE (1024) bytes.
528 return EFI_INVALID_PARAMETER
;
529 } else if ((Attributes
& (EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
)) == EFI_VARIABLE_RUNTIME_ACCESS
532 // Make sure if runtime bit is set, boot service bit is set also
534 return EFI_INVALID_PARAMETER
;
535 } else if (EfiAtRuntime () && Attributes
&& !(Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
)) {
537 // Runtime but Attribute is not Runtime
539 return EFI_INVALID_PARAMETER
;
540 } else if (EfiAtRuntime () && Attributes
&& !(Attributes
& EFI_VARIABLE_NON_VOLATILE
)) {
542 // Cannot set volatile variable in Runtime
544 return EFI_INVALID_PARAMETER
;
545 } else if (DataSize
== 0 || (Attributes
& (EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
)) == 0) {
547 // Setting a data variable with no access, or zero DataSize attributes
548 // specified causes it to be deleted.
550 if (!EFI_ERROR (Status
)) {
551 Variable
.CurrPtr
->State
&= VAR_DELETED
;
555 return EFI_NOT_FOUND
;
557 if (!EFI_ERROR (Status
)) {
559 // If the variable is marked valid and the same data has been passed in
560 // then return to the caller immediately.
562 if (Variable
.CurrPtr
->DataSize
== DataSize
&&
563 !CompareMem (Data
, GetVariableDataPtr (Variable
.CurrPtr
), DataSize
)
566 } else if (Variable
.CurrPtr
->State
== VAR_ADDED
) {
568 // Mark the old variable as in delete transition
570 Variable
.CurrPtr
->State
&= VAR_IN_DELETED_TRANSITION
;
574 // Create a new variable and copy the data.
576 VarNameOffset
= sizeof (VARIABLE_HEADER
);
577 VarNameSize
= ArrayLength (VariableName
);
578 VarDataOffset
= VarNameOffset
+ VarNameSize
+ GET_PAD_SIZE (VarNameSize
);
579 VarSize
= VarDataOffset
+ DataSize
+ GET_PAD_SIZE (DataSize
);
581 if (Attributes
& EFI_VARIABLE_NON_VOLATILE
) {
582 if ((UINT32
) (VarSize
+*NonVolatileOffset
) >
583 ((VARIABLE_STORE_HEADER
*) ((UINTN
) (Global
->NonVolatileVariableBase
)))->Size
585 return EFI_OUT_OF_RESOURCES
;
588 NextVariable
= (VARIABLE_HEADER
*) (UINT8
*) (*NonVolatileOffset
+ (UINTN
) Global
->NonVolatileVariableBase
);
589 *NonVolatileOffset
= *NonVolatileOffset
+ VarSize
;
591 if (EfiAtRuntime ()) {
592 return EFI_INVALID_PARAMETER
;
595 if ((UINT32
) (VarSize
+*VolatileOffset
) >
596 ((VARIABLE_STORE_HEADER
*) ((UINTN
) (Global
->VolatileVariableBase
)))->Size
598 return EFI_OUT_OF_RESOURCES
;
601 NextVariable
= (VARIABLE_HEADER
*) (UINT8
*) (*VolatileOffset
+ (UINTN
) Global
->VolatileVariableBase
);
602 *VolatileOffset
= *VolatileOffset
+ VarSize
;
605 NextVariable
->StartId
= VARIABLE_DATA
;
606 NextVariable
->Attributes
= Attributes
;
607 NextVariable
->State
= VAR_ADDED
;
608 NextVariable
->Reserved
= 0;
611 // There will be pad bytes after Data, the NextVariable->NameSize and
612 // NextVariable->NameSize should not include pad size so that variable
613 // service can get actual size in GetVariable
615 NextVariable
->NameSize
= (UINT32
)VarNameSize
;
616 NextVariable
->DataSize
= (UINT32
)DataSize
;
618 CopyMem (&NextVariable
->VendorGuid
, VendorGuid
, sizeof (EFI_GUID
));
620 (UINT8
*) ((UINTN
) NextVariable
+ VarNameOffset
),
625 (UINT8
*) ((UINTN
) NextVariable
+ VarDataOffset
),
631 // Mark the old variable as deleted
633 if (!EFI_ERROR (Status
)) {
634 Variable
.CurrPtr
->State
&= VAR_DELETED
;
641 #if (EFI_SPECIFICATION_VERSION >= 0x00020000)
645 IN UINT32 Attributes
,
646 OUT UINT64
*MaximumVariableStorageSize
,
647 OUT UINT64
*RemainingVariableStorageSize
,
648 OUT UINT64
*MaximumVariableSize
,
649 IN VARIABLE_GLOBAL
*Global
,
656 This code returns information about the EFI variables.
660 Attributes Attributes bitmask to specify the type of variables
661 on which to return information.
662 MaximumVariableStorageSize Pointer to the maximum size of the storage space available
663 for the EFI variables associated with the attributes specified.
664 RemainingVariableStorageSize Pointer to the remaining size of the storage space available
665 for the EFI variables associated with the attributes specified.
666 MaximumVariableSize Pointer to the maximum size of the individual EFI variables
667 associated with the attributes specified.
668 Global Pointer to VARIABLE_GLOBAL structure.
669 Instance Instance of the Firmware Volume.
674 EFI_INVALID_PARAMETER - An invalid combination of attribute bits was supplied.
675 EFI_SUCCESS - Query successfully.
676 EFI_UNSUPPORTED - The attribute is not supported on this platform.
680 VARIABLE_HEADER
*Variable
;
681 VARIABLE_HEADER
*NextVariable
;
683 VARIABLE_STORE_HEADER
*VariableStoreHeader
;
685 if(MaximumVariableStorageSize
== NULL
|| RemainingVariableStorageSize
== NULL
|| MaximumVariableSize
== NULL
) {
686 return EFI_INVALID_PARAMETER
;
689 if((Attributes
& (EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
)) == 0) {
691 // Make sure the Attributes combination is supported by the platform.
693 return EFI_UNSUPPORTED
;
694 } else if ((Attributes
& (EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
)) == EFI_VARIABLE_RUNTIME_ACCESS
) {
696 // Make sure if runtime bit is set, boot service bit is set also.
698 return EFI_INVALID_PARAMETER
;
699 } else if (EfiAtRuntime () && !(Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
)) {
701 // Make sure RT Attribute is set if we are in Runtime phase.
703 return EFI_INVALID_PARAMETER
;
704 } else if (EfiAtRuntime () && Attributes
&& !(Attributes
& EFI_VARIABLE_NON_VOLATILE
)) {
706 // Cannot Query volatile variable in Runtime
708 return EFI_INVALID_PARAMETER
;
711 if((Attributes
& EFI_VARIABLE_NON_VOLATILE
) == 0) {
713 // Query is Volatile related.
715 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->VolatileVariableBase
);
718 // Query is Non-Volatile related.
720 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->NonVolatileVariableBase
);
724 // Now let's fill *MaximumVariableStorageSize *RemainingVariableStorageSize
725 // with the storage size (excluding the storage header size)
727 *MaximumVariableStorageSize
= VariableStoreHeader
->Size
- sizeof (VARIABLE_STORE_HEADER
);
728 *RemainingVariableStorageSize
= VariableStoreHeader
->Size
- sizeof (VARIABLE_STORE_HEADER
);
731 // Let *MaximumVariableSize be MAX_VARIABLE_SIZE
733 *MaximumVariableSize
= MAX_VARIABLE_SIZE
;
736 // Point to the starting address of the variables.
738 Variable
= (VARIABLE_HEADER
*) (VariableStoreHeader
+ 1);
741 // Now walk through the related variable store.
743 while (Variable
< GetEndPointer (VariableStoreHeader
)) {
744 if (Variable
->StartId
!= VARIABLE_DATA
) {
748 NextVariable
= (VARIABLE_HEADER
*) (GetVariableDataPtr (Variable
) + Variable
->DataSize
+ GET_PAD_SIZE (Variable
->DataSize
));
749 VariableSize
= (UINT64
) (UINTN
) NextVariable
- (UINT64
) (UINTN
) Variable
;
751 if (Variable
->State
== VAR_ADDED
) {
752 *RemainingVariableStorageSize
-= VariableSize
;
756 // Go to the next one.
758 Variable
= NextVariable
;
768 InitializeVariableStore (
769 OUT EFI_PHYSICAL_ADDRESS
*VariableBase
,
770 OUT UINTN
*LastVariableOffset
775 This function initializes variable store
783 VARIABLE_STORE_HEADER
*VariableStore
;
786 // Allocate memory for volatile variable store
788 VariableStore
= (VARIABLE_STORE_HEADER
*) AllocateRuntimePool (
791 if (NULL
== VariableStore
) {
792 return EFI_OUT_OF_RESOURCES
;
795 SetMem (VariableStore
, VARIABLE_STORE_SIZE
, 0xff);
798 // Variable Specific Data
800 *VariableBase
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) VariableStore
;
801 *LastVariableOffset
= sizeof (VARIABLE_STORE_HEADER
);
803 VariableStore
->Signature
= VARIABLE_STORE_SIGNATURE
;
804 VariableStore
->Size
= VARIABLE_STORE_SIZE
;
805 VariableStore
->Format
= VARIABLE_STORE_FORMATTED
;
806 VariableStore
->State
= VARIABLE_STORE_HEALTHY
;
807 VariableStore
->Reserved
= 0;
808 VariableStore
->Reserved1
= 0;
815 VariableCommonInitialize (
816 IN EFI_HANDLE ImageHandle
,
817 IN EFI_SYSTEM_TABLE
*SystemTable
822 This function does common initialization for variable services
833 // Allocate memory for mVariableModuleGlobal
835 mVariableModuleGlobal
= (ESAL_VARIABLE_GLOBAL
*) AllocateRuntimePool (
836 sizeof (ESAL_VARIABLE_GLOBAL
)
838 if (NULL
== mVariableModuleGlobal
) {
839 return EFI_OUT_OF_RESOURCES
;
842 // Intialize volatile variable store
844 Status
= InitializeVariableStore (
845 &mVariableModuleGlobal
->VariableBase
[Physical
].VolatileVariableBase
,
846 &mVariableModuleGlobal
->VolatileLastVariableOffset
849 if (EFI_ERROR (Status
)) {
853 // Intialize non volatile variable store
855 Status
= InitializeVariableStore (
856 &mVariableModuleGlobal
->VariableBase
[Physical
].NonVolatileVariableBase
,
857 &mVariableModuleGlobal
->NonVolatileLastVariableOffset