3 Emulation Variable services operate on the runtime volatile memory.
4 The nonvolatile variable space doesn't exist.
6 Copyright (c) 2006 - 2008, Intel Corporation
7 All rights reserved. This program and the accompanying materials
8 are licensed and made available under the terms and conditions of the BSD License
9 which accompanies this distribution. The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
20 /// Don't use module globals after the SetVirtualAddress map is signaled
22 ESAL_VARIABLE_GLOBAL
*mVariableModuleGlobal
;
24 VARIABLE_INFO_ENTRY
*gVariableInfo
= NULL
;
27 Acquires lock only at boot time. Simply returns at runtime.
29 This is a temperary function which will be removed when
30 EfiAcquireLock() in UefiLib can handle the call in UEFI
31 Runtimer driver in RT phase.
32 It calls EfiAcquireLock() at boot time, and simply returns
35 @param Lock A pointer to the lock to acquire
39 AcquireLockOnlyAtBootTime (
43 if (!EfiAtRuntime ()) {
44 EfiAcquireLock (Lock
);
49 Releases lock only at boot time. Simply returns at runtime.
51 This is a temperary function which will be removed when
52 EfiReleaseLock() in UefiLib can handle the call in UEFI
53 Runtimer driver in RT phase.
54 It calls EfiReleaseLock() at boot time, and simply returns
57 @param Lock A pointer to the lock to release
61 ReleaseLockOnlyAtBootTime (
65 if (!EfiAtRuntime ()) {
66 EfiReleaseLock (Lock
);
71 Gets pointer to the variable data.
73 This function gets the pointer to the variable data according
74 to the input pointer to the variable header.
76 @param Variable Pointer to the variable header.
78 @return Pointer to variable data
83 IN VARIABLE_HEADER
*Variable
86 if (Variable
->StartId
!= VARIABLE_DATA
) {
90 // Be careful about pad size for alignment
92 return (UINT8
*) ((UINTN
) GET_VARIABLE_NAME_PTR (Variable
) + Variable
->NameSize
+ GET_PAD_SIZE (Variable
->NameSize
));
96 Gets pointer to header of the next variable.
98 This function gets the pointer to the next variable header according
99 to the input point to the variable header.
101 @param Variable Pointer to header of the next variable
103 @return Pointer to next variable header.
108 IN VARIABLE_HEADER
*Variable
111 VARIABLE_HEADER
*VarHeader
;
113 if (Variable
->StartId
!= VARIABLE_DATA
) {
117 // Be careful about pad size for alignment
119 VarHeader
= (VARIABLE_HEADER
*) (GetVariableDataPtr (Variable
) + Variable
->DataSize
+ GET_PAD_SIZE (Variable
->DataSize
));
121 if (VarHeader
->StartId
!= VARIABLE_DATA
||
122 (sizeof (VARIABLE_HEADER
) + VarHeader
->DataSize
+ VarHeader
->NameSize
) > FixedPcdGet32(PcdMaxVariableSize
)
131 Gets pointer to the end of the variable storage area.
133 This function gets pointer to the end of the variable storage
134 area, according to the input variable store header.
136 @param VolHeader Pointer to the variale store header
138 @return Pointer to the end of the variable storage area.
143 IN VARIABLE_STORE_HEADER
*VolHeader
147 // The end of variable store
149 return (VARIABLE_HEADER
*) ((UINTN
) VolHeader
+ VolHeader
->Size
);
153 Routine used to track statistical information about variable usage.
154 The data is stored in the EFI system table so it can be accessed later.
155 VariableInfo.efi can dump out the table. Only Boot Services variable
156 accesses are tracked by this code. The PcdVariableCollectStatistics
157 build flag controls if this feature is enabled.
159 A read that hits in the cache will have Read and Cache true for
160 the transaction. Data is allocated by this routine, but never
163 @param[in] VariableName Name of the Variable to track
164 @param[in] VendorGuid Guid of the Variable to track
165 @param[in] Volatile TRUE if volatile FALSE if non-volatile
166 @param[in] Read TRUE if GetVariable() was called
167 @param[in] Write TRUE if SetVariable() was called
168 @param[in] Delete TRUE if deleted via SetVariable()
169 @param[in] Cache TRUE for a cache hit.
174 IN CHAR16
*VariableName
,
175 IN EFI_GUID
*VendorGuid
,
183 VARIABLE_INFO_ENTRY
*Entry
;
185 if (FeaturePcdGet (PcdVariableCollectStatistics
)) {
187 if (EfiAtRuntime ()) {
188 // Don't collect statistics at runtime
192 if (gVariableInfo
== NULL
) {
194 // on the first call allocate a entry and place a pointer to it in
195 // the EFI System Table
197 gVariableInfo
= AllocateZeroPool (sizeof (VARIABLE_INFO_ENTRY
));
198 ASSERT (gVariableInfo
!= NULL
);
200 CopyGuid (&gVariableInfo
->VendorGuid
, VendorGuid
);
201 gVariableInfo
->Name
= AllocatePool (StrLen (VariableName
));
202 ASSERT (gVariableInfo
->Name
!= NULL
);
203 StrCpy (gVariableInfo
->Name
, VariableName
);
204 gVariableInfo
->Volatile
= Volatile
;
206 gBS
->InstallConfigurationTable (&gEfiVariableGuid
, gVariableInfo
);
210 for (Entry
= gVariableInfo
; Entry
!= NULL
; Entry
= Entry
->Next
) {
211 if (CompareGuid (VendorGuid
, &Entry
->VendorGuid
)) {
212 if (StrCmp (VariableName
, Entry
->Name
) == 0) {
220 Entry
->DeleteCount
++;
230 if (Entry
->Next
== NULL
) {
232 // If the entry is not in the table add it.
233 // Next iteration of the loop will fill in the data
235 Entry
->Next
= AllocateZeroPool (sizeof (VARIABLE_INFO_ENTRY
));
236 ASSERT (Entry
->Next
!= NULL
);
238 CopyGuid (&Entry
->Next
->VendorGuid
, VendorGuid
);
239 Entry
->Next
->Name
= AllocatePool (StrLen (VariableName
));
240 ASSERT (Entry
->Next
->Name
!= NULL
);
241 StrCpy (Entry
->Next
->Name
, VariableName
);
242 Entry
->Next
->Volatile
= Volatile
;
250 Finds variable in storage blocks of volatile and non-volatile storage areas.
252 This code finds variable in storage blocks of volatile and non-volatile storage areas.
253 If VariableName is an empty string, then we just return the first
254 qualified variable without comparing VariableName and VendorGuid.
255 Otherwise, VariableName and VendorGuid are compared.
257 @param VariableName Name of the variable to be found.
258 @param VendorGuid Vendor GUID to be found.
259 @param PtrTrack VARIABLE_POINTER_TRACK structure for output,
260 including the range searched and the target position.
261 @param Global Pointer to VARIABLE_GLOBAL structure, including
262 base of volatile variable storage area, base of
263 NV variable storage area, and a lock.
265 @retval EFI_INVALID_PARAMETER If VariableName is not an empty string, while
267 @retval EFI_SUCCESS Variable successfully found.
268 @retval EFI_NOT_FOUND Variable not found.
273 IN CHAR16
*VariableName
,
274 IN EFI_GUID
*VendorGuid
,
275 OUT VARIABLE_POINTER_TRACK
*PtrTrack
,
276 IN VARIABLE_GLOBAL
*Global
279 VARIABLE_HEADER
*Variable
[2];
280 VARIABLE_STORE_HEADER
*VariableStoreHeader
[2];
284 // We aquire the lock at the entry of FindVariable as GetVariable, GetNextVariableName
285 // SetVariable all call FindVariable at entry point. Please move "Aquire Lock" to
286 // the correct places if this assumption does not hold TRUE anymore.
288 AcquireLockOnlyAtBootTime(&Global
->VariableServicesLock
);
291 // 0: Non-Volatile, 1: Volatile
293 VariableStoreHeader
[0] = (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->NonVolatileVariableBase
);
294 VariableStoreHeader
[1] = (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->VolatileVariableBase
);
297 // Start Pointers for the variable.
298 // Actual Data Pointer where data can be written.
300 Variable
[0] = (VARIABLE_HEADER
*) (VariableStoreHeader
[0] + 1);
301 Variable
[1] = (VARIABLE_HEADER
*) (VariableStoreHeader
[1] + 1);
303 if (VariableName
[0] != 0 && VendorGuid
== NULL
) {
304 return EFI_INVALID_PARAMETER
;
307 // Find the variable by walk through non-volatile and volatile variable store
309 for (Index
= 0; Index
< 2; Index
++) {
310 PtrTrack
->StartPtr
= (VARIABLE_HEADER
*) (VariableStoreHeader
[Index
] + 1);
311 PtrTrack
->EndPtr
= GetEndPointer (VariableStoreHeader
[Index
]);
313 while ((Variable
[Index
] != NULL
) && (Variable
[Index
] <= GetEndPointer (VariableStoreHeader
[Index
]))) {
314 if (Variable
[Index
]->StartId
== VARIABLE_DATA
&& Variable
[Index
]->State
== VAR_ADDED
) {
315 if (!(EfiAtRuntime () && ((Variable
[Index
]->Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
) == 0))) {
316 if (VariableName
[0] == 0) {
317 PtrTrack
->CurrPtr
= Variable
[Index
];
318 PtrTrack
->Volatile
= (BOOLEAN
) Index
;
321 if (CompareGuid (VendorGuid
, &Variable
[Index
]->VendorGuid
)) {
322 if (CompareMem (VariableName
, GET_VARIABLE_NAME_PTR (Variable
[Index
]), Variable
[Index
]->NameSize
) == 0) {
323 PtrTrack
->CurrPtr
= Variable
[Index
];
324 PtrTrack
->Volatile
= (BOOLEAN
) Index
;
332 Variable
[Index
] = GetNextVariablePtr (Variable
[Index
]);
335 PtrTrack
->CurrPtr
= NULL
;
336 return EFI_NOT_FOUND
;
340 This code finds variable in storage blocks (Volatile or Non-Volatile).
342 @param VariableName A Null-terminated Unicode string that is the name of
343 the vendor's variable.
344 @param VendorGuid A unique identifier for the vendor.
345 @param Attributes If not NULL, a pointer to the memory location to return the
346 attributes bitmask for the variable.
347 @param DataSize Size of Data found. If size is less than the
348 data, this value contains the required size.
349 @param Data On input, the size in bytes of the return Data buffer.
350 On output, the size of data returned in Data.
351 @param Global Pointer to VARIABLE_GLOBAL structure
352 @param Instance Instance of the Firmware Volume.
354 @retval EFI_SUCCESS The function completed successfully.
355 @retval EFI_NOT_FOUND The variable was not found.
356 @retval EFI_BUFFER_TOO_SMALL DataSize is too small for the result. DataSize has
357 been updated with the size needed to complete the request.
358 @retval EFI_INVALID_PARAMETER VariableName or VendorGuid or DataSize is NULL.
364 IN CHAR16
*VariableName
,
365 IN EFI_GUID
* VendorGuid
,
366 OUT UINT32
*Attributes OPTIONAL
,
367 IN OUT UINTN
*DataSize
,
369 IN VARIABLE_GLOBAL
* Global
,
373 VARIABLE_POINTER_TRACK Variable
;
377 if (VariableName
== NULL
|| VendorGuid
== NULL
|| DataSize
== NULL
) {
378 return EFI_INVALID_PARAMETER
;
381 // Find existing variable
383 Status
= FindVariable (VariableName
, VendorGuid
, &Variable
, Global
);
385 if (Variable
.CurrPtr
== NULL
|| EFI_ERROR (Status
)) {
391 VarDataSize
= Variable
.CurrPtr
->DataSize
;
392 if (*DataSize
>= VarDataSize
) {
394 Status
= EFI_INVALID_PARAMETER
;
398 CopyMem (Data
, GetVariableDataPtr (Variable
.CurrPtr
), VarDataSize
);
399 if (Attributes
!= NULL
) {
400 *Attributes
= Variable
.CurrPtr
->Attributes
;
403 *DataSize
= VarDataSize
;
404 UpdateVariableInfo (VariableName
, VendorGuid
, Variable
.Volatile
, TRUE
, FALSE
, FALSE
, FALSE
);
405 Status
= EFI_SUCCESS
;
408 *DataSize
= VarDataSize
;
409 Status
= EFI_BUFFER_TOO_SMALL
;
414 ReleaseLockOnlyAtBootTime (&Global
->VariableServicesLock
);
420 This code Finds the Next available variable.
422 @param VariableNameSize Size of the variable.
423 @param VariableName On input, supplies the last VariableName that was returned by GetNextVariableName().
424 On output, returns the Null-terminated Unicode string of the current variable.
425 @param VendorGuid On input, supplies the last VendorGuid that was returned by GetNextVariableName().
426 On output, returns the VendorGuid of the current variable.
427 @param Global Pointer to VARIABLE_GLOBAL structure.
428 @param Instance Instance of the Firmware Volume.
430 @retval EFI_SUCCESS The function completed successfully.
431 @retval EFI_NOT_FOUND The next variable was not found.
432 @retval EFI_BUFFER_TOO_SMALL VariableNameSize is too small for the result.
433 VariableNameSize has been updated with the size needed to complete the request.
434 @retval EFI_INVALID_PARAMETER VariableNameSize or VariableName or VendorGuid is NULL.
439 GetNextVariableName (
440 IN OUT UINTN
*VariableNameSize
,
441 IN OUT CHAR16
*VariableName
,
442 IN OUT EFI_GUID
*VendorGuid
,
443 IN VARIABLE_GLOBAL
*Global
,
447 VARIABLE_POINTER_TRACK Variable
;
451 if (VariableNameSize
== NULL
|| VariableName
== NULL
|| VendorGuid
== NULL
) {
452 return EFI_INVALID_PARAMETER
;
455 Status
= FindVariable (VariableName
, VendorGuid
, &Variable
, Global
);
457 if (Variable
.CurrPtr
== NULL
|| EFI_ERROR (Status
)) {
462 if (VariableName
[0] != 0) {
464 // If variable name is not NULL, get next variable
466 Variable
.CurrPtr
= GetNextVariablePtr (Variable
.CurrPtr
);
469 // If both volatile and non-volatile variable store are parsed,
472 if (Variable
.CurrPtr
>= Variable
.EndPtr
|| Variable
.CurrPtr
== NULL
) {
473 Variable
.Volatile
= (BOOLEAN
) (Variable
.Volatile
^ ((BOOLEAN
) 0x1));
474 if (Variable
.Volatile
) {
475 Variable
.StartPtr
= (VARIABLE_HEADER
*) ((UINTN
) (Global
->VolatileVariableBase
+ sizeof (VARIABLE_STORE_HEADER
)));
476 Variable
.EndPtr
= (VARIABLE_HEADER
*) GetEndPointer ((VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->VolatileVariableBase
));
478 Status
= EFI_NOT_FOUND
;
482 Variable
.CurrPtr
= Variable
.StartPtr
;
483 if (Variable
.CurrPtr
->StartId
!= VARIABLE_DATA
) {
490 if (Variable
.CurrPtr
->StartId
== VARIABLE_DATA
&& Variable
.CurrPtr
->State
== VAR_ADDED
) {
491 if (!(EfiAtRuntime () && ((Variable
.CurrPtr
->Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
) == 0))) {
492 VarNameSize
= Variable
.CurrPtr
->NameSize
;
493 if (VarNameSize
<= *VariableNameSize
) {
496 GET_VARIABLE_NAME_PTR (Variable
.CurrPtr
),
501 &Variable
.CurrPtr
->VendorGuid
,
504 Status
= EFI_SUCCESS
;
506 Status
= EFI_BUFFER_TOO_SMALL
;
509 *VariableNameSize
= VarNameSize
;
516 ReleaseLockOnlyAtBootTime (&Global
->VariableServicesLock
);
523 This code sets variable in storage blocks (Volatile or Non-Volatile).
525 @param VariableName A Null-terminated Unicode string that is the name of the vendor's
526 variable. Each VariableName is unique for each
527 VendorGuid. VariableName must contain 1 or more
528 Unicode characters. If VariableName is an empty Unicode
529 string, then EFI_INVALID_PARAMETER is returned.
530 @param VendorGuid A unique identifier for the vendor
531 @param Attributes Attributes bitmask to set for the variable
532 @param DataSize The size in bytes of the Data buffer. A size of zero causes the
533 variable to be deleted.
534 @param Data The contents for the variable
535 @param Global Pointer to VARIABLE_GLOBAL structure
536 @param VolatileOffset The offset of last volatile variable
537 @param NonVolatileOffset The offset of last non-volatile variable
538 @param Instance Instance of the Firmware Volume.
540 @retval EFI_SUCCESS The firmware has successfully stored the variable and its data as
541 defined by the Attributes.
542 @retval EFI_INVALID_PARAMETER An invalid combination of attribute bits was supplied, or the
543 DataSize exceeds the maximum allowed, or VariableName is an empty
544 Unicode string, or VendorGuid is NULL.
545 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data.
546 @retval EFI_DEVICE_ERROR The variable could not be saved due to a hardware failure.
547 @retval EFI_WRITE_PROTECTED The variable in question is read-only or cannot be deleted.
548 @retval EFI_NOT_FOUND The variable trying to be updated or deleted was not found.
554 IN CHAR16
*VariableName
,
555 IN EFI_GUID
*VendorGuid
,
556 IN UINT32 Attributes
,
559 IN VARIABLE_GLOBAL
*Global
,
560 IN UINTN
*VolatileOffset
,
561 IN UINTN
*NonVolatileOffset
,
565 VARIABLE_POINTER_TRACK Variable
;
567 VARIABLE_HEADER
*NextVariable
;
574 // Check input parameters
576 if (VariableName
== NULL
|| VariableName
[0] == 0 || VendorGuid
== NULL
) {
577 return EFI_INVALID_PARAMETER
;
580 // Make sure if runtime bit is set, boot service bit is set also
582 if ((Attributes
& (EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
)) == EFI_VARIABLE_RUNTIME_ACCESS
) {
583 return EFI_INVALID_PARAMETER
;
586 // The size of the VariableName, including the Unicode Null in bytes plus
587 // the DataSize is limited to maximum size of FixedPcdGet32(PcdMaxHardwareErrorVariableSize)
588 // bytes for HwErrRec, and FixedPcdGet32(PcdMaxVariableSize) bytes for the others.
590 if ((Attributes
& EFI_VARIABLE_HARDWARE_ERROR_RECORD
) == EFI_VARIABLE_HARDWARE_ERROR_RECORD
) {
591 if ((DataSize
> FixedPcdGet32(PcdMaxHardwareErrorVariableSize
)) ||
592 (sizeof (VARIABLE_HEADER
) + StrSize (VariableName
) + DataSize
> FixedPcdGet32(PcdMaxHardwareErrorVariableSize
))) {
593 return EFI_INVALID_PARAMETER
;
597 // The size of the VariableName, including the Unicode Null in bytes plus
598 // the DataSize is limited to maximum size of FixedPcdGet32(PcdMaxVariableSize) bytes.
600 if ((DataSize
> FixedPcdGet32(PcdMaxVariableSize
)) ||
601 (sizeof (VARIABLE_HEADER
) + StrSize (VariableName
) + DataSize
> FixedPcdGet32(PcdMaxVariableSize
))) {
602 return EFI_INVALID_PARAMETER
;
606 // Check whether the input variable is already existed
609 Status
= FindVariable (VariableName
, VendorGuid
, &Variable
, Global
);
611 if (Status
== EFI_SUCCESS
&& Variable
.CurrPtr
!= NULL
) {
613 // Update/Delete existing variable
616 if (EfiAtRuntime ()) {
618 // If EfiAtRuntime and the variable is Volatile and Runtime Access,
619 // the volatile is ReadOnly, and SetVariable should be aborted and
620 // return EFI_WRITE_PROTECTED.
622 if (Variable
.Volatile
) {
623 Status
= EFI_WRITE_PROTECTED
;
627 // Only variable have NV attribute can be updated/deleted in Runtime
629 if ((Variable
.CurrPtr
->Attributes
& EFI_VARIABLE_NON_VOLATILE
) == 0) {
630 Status
= EFI_INVALID_PARAMETER
;
636 // Setting a data variable with no access, or zero DataSize attributes
637 // specified causes it to be deleted.
639 if (DataSize
== 0 || (Attributes
& (EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
)) == 0) {
640 Variable
.CurrPtr
->State
&= VAR_DELETED
;
641 UpdateVariableInfo (VariableName
, VendorGuid
, Variable
.Volatile
, FALSE
, FALSE
, TRUE
, FALSE
);
642 Status
= EFI_SUCCESS
;
647 // If the variable is marked valid and the same data has been passed in
648 // then return to the caller immediately.
650 if (Variable
.CurrPtr
->DataSize
== DataSize
&&
651 CompareMem (Data
, GetVariableDataPtr (Variable
.CurrPtr
), DataSize
) == 0
653 Status
= EFI_SUCCESS
;
655 } else if (Variable
.CurrPtr
->State
== VAR_ADDED
) {
657 // Mark the old variable as in delete transition
659 Variable
.CurrPtr
->State
&= VAR_IN_DELETED_TRANSITION
;
662 } else if (Status
== EFI_NOT_FOUND
) {
664 // Create a new variable
668 // Make sure we are trying to create a new variable.
669 // Setting a data variable with no access, or zero DataSize attributes means to delete it.
671 if (DataSize
== 0 || (Attributes
& (EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
)) == 0) {
672 Status
= EFI_NOT_FOUND
;
677 // Only variable have NV|RT attribute can be created in Runtime
679 if (EfiAtRuntime () &&
680 (((Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
) == 0) || ((Attributes
& EFI_VARIABLE_NON_VOLATILE
) == 0))) {
681 Status
= EFI_INVALID_PARAMETER
;
686 // Status should be EFI_INVALID_PARAMETER here according to return status of FindVariable().
688 ASSERT (Status
== EFI_INVALID_PARAMETER
);
693 // Function part - create a new variable and copy the data.
694 // Both update a variable and create a variable will come here.
697 VarNameOffset
= sizeof (VARIABLE_HEADER
);
698 VarNameSize
= StrSize (VariableName
);
699 VarDataOffset
= VarNameOffset
+ VarNameSize
+ GET_PAD_SIZE (VarNameSize
);
700 VarSize
= VarDataOffset
+ DataSize
+ GET_PAD_SIZE (DataSize
);
702 if ((Attributes
& EFI_VARIABLE_NON_VOLATILE
) != 0) {
703 if ((UINT32
) (VarSize
+*NonVolatileOffset
) >
704 ((VARIABLE_STORE_HEADER
*) ((UINTN
) (Global
->NonVolatileVariableBase
)))->Size
706 Status
= EFI_OUT_OF_RESOURCES
;
710 NextVariable
= (VARIABLE_HEADER
*) (UINT8
*) (*NonVolatileOffset
+ (UINTN
) Global
->NonVolatileVariableBase
);
711 *NonVolatileOffset
= *NonVolatileOffset
+ VarSize
;
713 if ((UINT32
) (VarSize
+*VolatileOffset
) >
714 ((VARIABLE_STORE_HEADER
*) ((UINTN
) (Global
->VolatileVariableBase
)))->Size
716 Status
= EFI_OUT_OF_RESOURCES
;
720 NextVariable
= (VARIABLE_HEADER
*) (UINT8
*) (*VolatileOffset
+ (UINTN
) Global
->VolatileVariableBase
);
721 *VolatileOffset
= *VolatileOffset
+ VarSize
;
724 NextVariable
->StartId
= VARIABLE_DATA
;
725 NextVariable
->Attributes
= Attributes
;
726 NextVariable
->State
= VAR_ADDED
;
727 NextVariable
->Reserved
= 0;
730 // There will be pad bytes after Data, the NextVariable->NameSize and
731 // NextVariable->NameSize should not include pad size so that variable
732 // service can get actual size in GetVariable
734 NextVariable
->NameSize
= (UINT32
)VarNameSize
;
735 NextVariable
->DataSize
= (UINT32
)DataSize
;
737 CopyMem (&NextVariable
->VendorGuid
, VendorGuid
, sizeof (EFI_GUID
));
739 (UINT8
*) ((UINTN
) NextVariable
+ VarNameOffset
),
744 (UINT8
*) ((UINTN
) NextVariable
+ VarDataOffset
),
750 // Mark the old variable as deleted
752 if (!EFI_ERROR (Status
)) {
753 Variable
.CurrPtr
->State
&= VAR_DELETED
;
756 UpdateVariableInfo (VariableName
, VendorGuid
, Variable
.Volatile
, FALSE
, TRUE
, FALSE
, FALSE
);
758 Status
= EFI_SUCCESS
;
760 ReleaseLockOnlyAtBootTime (&Global
->VariableServicesLock
);
766 This code returns information about the EFI variables.
768 @param Attributes Attributes bitmask to specify the type of variables
769 on which to return information.
770 @param MaximumVariableStorageSize On output the maximum size of the storage space available for
771 the EFI variables associated with the attributes specified.
772 @param RemainingVariableStorageSize Returns the remaining size of the storage space available for EFI
773 variables associated with the attributes specified.
774 @param MaximumVariableSize Returns the maximum size of an individual EFI variable
775 associated with the attributes specified.
776 @param Global Pointer to VARIABLE_GLOBAL structure.
777 @param Instance Instance of the Firmware Volume.
779 @retval EFI_SUCCESS Valid answer returned.
780 @retval EFI_INVALID_PARAMETER An invalid combination of attribute bits was supplied
781 @retval EFI_UNSUPPORTED The attribute is not supported on this platform, and the
782 MaximumVariableStorageSize, RemainingVariableStorageSize,
783 MaximumVariableSize are undefined.
789 IN UINT32 Attributes
,
790 OUT UINT64
*MaximumVariableStorageSize
,
791 OUT UINT64
*RemainingVariableStorageSize
,
792 OUT UINT64
*MaximumVariableSize
,
793 IN VARIABLE_GLOBAL
*Global
,
797 VARIABLE_HEADER
*Variable
;
798 VARIABLE_HEADER
*NextVariable
;
800 VARIABLE_STORE_HEADER
*VariableStoreHeader
;
802 if(MaximumVariableStorageSize
== NULL
|| RemainingVariableStorageSize
== NULL
|| MaximumVariableSize
== NULL
|| Attributes
== 0) {
803 return EFI_INVALID_PARAMETER
;
806 if((Attributes
& (EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_HARDWARE_ERROR_RECORD
)) == 0) {
808 // Make sure the Attributes combination is supported by the platform.
810 return EFI_UNSUPPORTED
;
811 } else if ((Attributes
& (EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
)) == EFI_VARIABLE_RUNTIME_ACCESS
) {
813 // Make sure if runtime bit is set, boot service bit is set also.
815 return EFI_INVALID_PARAMETER
;
816 } else if (EfiAtRuntime () && ((Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
) == 0)) {
818 // Make sure RT Attribute is set if we are in Runtime phase.
820 return EFI_INVALID_PARAMETER
;
823 AcquireLockOnlyAtBootTime(&Global
->VariableServicesLock
);
825 if((Attributes
& EFI_VARIABLE_NON_VOLATILE
) == 0) {
827 // Query is Volatile related.
829 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->VolatileVariableBase
);
832 // Query is Non-Volatile related.
834 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->NonVolatileVariableBase
);
838 // Now let's fill *MaximumVariableStorageSize *RemainingVariableStorageSize
839 // with the storage size (excluding the storage header size)
841 *MaximumVariableStorageSize
= VariableStoreHeader
->Size
- sizeof (VARIABLE_STORE_HEADER
);
842 *RemainingVariableStorageSize
= VariableStoreHeader
->Size
- sizeof (VARIABLE_STORE_HEADER
);
845 // Let *MaximumVariableSize be FixedPcdGet32(PcdMaxVariableSize) with the exception of the variable header size.
847 *MaximumVariableSize
= FixedPcdGet32(PcdMaxVariableSize
) - sizeof (VARIABLE_HEADER
);
850 // Harware error record variable needs larger size.
852 if ((Attributes
& EFI_VARIABLE_HARDWARE_ERROR_RECORD
) == EFI_VARIABLE_HARDWARE_ERROR_RECORD
) {
853 *MaximumVariableSize
= FixedPcdGet32(PcdMaxHardwareErrorVariableSize
) - sizeof (VARIABLE_HEADER
);
857 // Point to the starting address of the variables.
859 Variable
= (VARIABLE_HEADER
*) (VariableStoreHeader
+ 1);
862 // Now walk through the related variable store.
864 while (Variable
< GetEndPointer (VariableStoreHeader
)) {
865 if (Variable
->StartId
!= VARIABLE_DATA
) {
869 NextVariable
= (VARIABLE_HEADER
*) (GetVariableDataPtr (Variable
) + Variable
->DataSize
+ GET_PAD_SIZE (Variable
->DataSize
));
870 VariableSize
= (UINT64
) (UINTN
) NextVariable
- (UINT64
) (UINTN
) Variable
;
872 if (Variable
->State
== VAR_ADDED
) {
873 *RemainingVariableStorageSize
-= VariableSize
;
877 // Go to the next one.
879 Variable
= NextVariable
;
882 if (*RemainingVariableStorageSize
< sizeof (VARIABLE_HEADER
)) {
883 *MaximumVariableSize
= 0;
884 } else if ((*RemainingVariableStorageSize
- sizeof (VARIABLE_HEADER
)) < *MaximumVariableSize
) {
885 *MaximumVariableSize
= *RemainingVariableStorageSize
- sizeof (VARIABLE_HEADER
);
888 ReleaseLockOnlyAtBootTime (&Global
->VariableServicesLock
);
893 Initializes variable store area.
895 This function allocates memory space for variable store area and initializes its attributes.
897 @param VariableBase Base of the variable store area created
898 @param LastVariableOffset Size of VARIABLE_STORE_HEADER
902 InitializeVariableStore (
903 OUT EFI_PHYSICAL_ADDRESS
*VariableBase
,
904 OUT UINTN
*LastVariableOffset
907 VARIABLE_STORE_HEADER
*VariableStore
;
910 // Allocate memory for volatile variable store
912 VariableStore
= (VARIABLE_STORE_HEADER
*) AllocateRuntimePool (
913 FixedPcdGet32(PcdVariableStoreSize
)
915 if (NULL
== VariableStore
) {
916 return EFI_OUT_OF_RESOURCES
;
919 SetMem (VariableStore
, FixedPcdGet32(PcdVariableStoreSize
), 0xff);
922 // Variable Specific Data
924 *VariableBase
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) VariableStore
;
925 *LastVariableOffset
= sizeof (VARIABLE_STORE_HEADER
);
927 CopyGuid (&VariableStore
->Signature
, &gEfiVariableGuid
);
928 VariableStore
->Size
= FixedPcdGet32(PcdVariableStoreSize
);
929 VariableStore
->Format
= VARIABLE_STORE_FORMATTED
;
930 VariableStore
->State
= VARIABLE_STORE_HEALTHY
;
931 VariableStore
->Reserved
= 0;
932 VariableStore
->Reserved1
= 0;
938 Initializes variable store area for non-volatile and volatile variable.
940 This function allocates and initializes memory space for global context of ESAL
941 variable service and variable store area for non-volatile and volatile variable.
943 @param ImageHandle The Image handle of this driver.
944 @param SystemTable The pointer of EFI_SYSTEM_TABLE.
946 @retval EFI_SUCCESS Function successfully executed.
947 @retval EFI_OUT_OF_RESOURCES Fail to allocate enough memory resource.
952 VariableCommonInitialize (
953 IN EFI_HANDLE ImageHandle
,
954 IN EFI_SYSTEM_TABLE
*SystemTable
960 // Allocate memory for mVariableModuleGlobal
962 mVariableModuleGlobal
= (ESAL_VARIABLE_GLOBAL
*) AllocateRuntimePool (
963 sizeof (ESAL_VARIABLE_GLOBAL
)
965 if (NULL
== mVariableModuleGlobal
) {
966 return EFI_OUT_OF_RESOURCES
;
969 EfiInitializeLock(&mVariableModuleGlobal
->VariableGlobal
[Physical
].VariableServicesLock
, TPL_NOTIFY
);
972 // Intialize volatile variable store
974 Status
= InitializeVariableStore (
975 &mVariableModuleGlobal
->VariableGlobal
[Physical
].VolatileVariableBase
,
976 &mVariableModuleGlobal
->VolatileLastVariableOffset
979 if (EFI_ERROR (Status
)) {
983 // Intialize non volatile variable store
985 Status
= InitializeVariableStore (
986 &mVariableModuleGlobal
->VariableGlobal
[Physical
].NonVolatileVariableBase
,
987 &mVariableModuleGlobal
->NonVolatileLastVariableOffset