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
;
26 Acquires lock only at boot time. Simply returns at runtime.
28 This is a temperary function which will be removed when
29 EfiAcquireLock() in UefiLib can handle the call in UEFI
30 Runtimer driver in RT phase.
31 It calls EfiAcquireLock() at boot time, and simply returns
34 @param Lock A pointer to the lock to acquire
38 AcquireLockOnlyAtBootTime (
42 if (!EfiAtRuntime ()) {
43 EfiAcquireLock (Lock
);
48 Releases lock only at boot time. Simply returns at runtime.
50 This is a temperary function which will be removed when
51 EfiReleaseLock() in UefiLib can handle the call in UEFI
52 Runtimer driver in RT phase.
53 It calls EfiReleaseLock() at boot time, and simply returns
56 @param Lock A pointer to the lock to release
60 ReleaseLockOnlyAtBootTime (
64 if (!EfiAtRuntime ()) {
65 EfiReleaseLock (Lock
);
70 Gets pointer to the variable data.
72 This function gets the pointer to the variable data according
73 to the input pointer to the variable header.
75 @param Variable Pointer to the variable header.
77 @return Pointer to variable data
82 IN VARIABLE_HEADER
*Variable
85 if (Variable
->StartId
!= VARIABLE_DATA
) {
89 // Be careful about pad size for alignment
91 return (UINT8
*) ((UINTN
) GET_VARIABLE_NAME_PTR (Variable
) + Variable
->NameSize
+ GET_PAD_SIZE (Variable
->NameSize
));
95 Gets pointer to header of the next variable.
97 This function gets the pointer to the next variable header according
98 to the input point to the variable header.
100 @param Variable Pointer to header of the next variable
102 @return Pointer to next variable header.
107 IN VARIABLE_HEADER
*Variable
110 VARIABLE_HEADER
*VarHeader
;
112 if (Variable
->StartId
!= VARIABLE_DATA
) {
116 // Be careful about pad size for alignment
118 VarHeader
= (VARIABLE_HEADER
*) (GetVariableDataPtr (Variable
) + Variable
->DataSize
+ GET_PAD_SIZE (Variable
->DataSize
));
120 if (VarHeader
->StartId
!= VARIABLE_DATA
||
121 (sizeof (VARIABLE_HEADER
) + VarHeader
->DataSize
+ VarHeader
->NameSize
) > FixedPcdGet32(PcdMaxVariableSize
)
130 Gets pointer to the end of the variable storage area.
132 This function gets pointer to the end of the variable storage
133 area, according to the input variable store header.
135 @param VolHeader Pointer to the variale store header
137 @return Pointer to the end of the variable storage area.
142 IN VARIABLE_STORE_HEADER
*VolHeader
146 // The end of variable store
148 return (VARIABLE_HEADER
*) ((UINTN
) VolHeader
+ VolHeader
->Size
);
152 Finds variable in storage blocks of volatile and non-volatile storage areas.
154 This code finds variable in storage blocks of volatile and non-volatile storage areas.
155 If VariableName is an empty string, then we just return the first
156 qualified variable without comparing VariableName and VendorGuid.
157 Otherwise, VariableName and VendorGuid are compared.
159 @param VariableName Name of the variable to be found.
160 @param VendorGuid Vendor GUID to be found.
161 @param PtrTrack VARIABLE_POINTER_TRACK structure for output,
162 including the range searched and the target position.
163 @param Global Pointer to VARIABLE_GLOBAL structure, including
164 base of volatile variable storage area, base of
165 NV variable storage area, and a lock.
167 @retval EFI_INVALID_PARAMETER If VariableName is not an empty string, while
169 @retval EFI_SUCCESS Variable successfully found.
170 @retval EFI_NOT_FOUND Variable not found.
175 IN CHAR16
*VariableName
,
176 IN EFI_GUID
*VendorGuid
,
177 OUT VARIABLE_POINTER_TRACK
*PtrTrack
,
178 IN VARIABLE_GLOBAL
*Global
181 VARIABLE_HEADER
*Variable
[2];
182 VARIABLE_STORE_HEADER
*VariableStoreHeader
[2];
186 // We aquire the lock at the entry of FindVariable as GetVariable, GetNextVariableName
187 // SetVariable all call FindVariable at entry point. Please move "Aquire Lock" to
188 // the correct places if this assumption does not hold TRUE anymore.
190 AcquireLockOnlyAtBootTime(&Global
->VariableServicesLock
);
193 // 0: Non-Volatile, 1: Volatile
195 VariableStoreHeader
[0] = (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->NonVolatileVariableBase
);
196 VariableStoreHeader
[1] = (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->VolatileVariableBase
);
199 // Start Pointers for the variable.
200 // Actual Data Pointer where data can be written.
202 Variable
[0] = (VARIABLE_HEADER
*) (VariableStoreHeader
[0] + 1);
203 Variable
[1] = (VARIABLE_HEADER
*) (VariableStoreHeader
[1] + 1);
205 if (VariableName
[0] != 0 && VendorGuid
== NULL
) {
206 return EFI_INVALID_PARAMETER
;
209 // Find the variable by walk through non-volatile and volatile variable store
211 for (Index
= 0; Index
< 2; Index
++) {
212 PtrTrack
->StartPtr
= (VARIABLE_HEADER
*) (VariableStoreHeader
[Index
] + 1);
213 PtrTrack
->EndPtr
= GetEndPointer (VariableStoreHeader
[Index
]);
215 while ((Variable
[Index
] != NULL
) && (Variable
[Index
] <= GetEndPointer (VariableStoreHeader
[Index
]))) {
216 if (Variable
[Index
]->StartId
== VARIABLE_DATA
&& Variable
[Index
]->State
== VAR_ADDED
) {
217 if (!(EfiAtRuntime () && ((Variable
[Index
]->Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
) == 0))) {
218 if (VariableName
[0] == 0) {
219 PtrTrack
->CurrPtr
= Variable
[Index
];
220 PtrTrack
->Volatile
= (BOOLEAN
) Index
;
223 if (CompareGuid (VendorGuid
, &Variable
[Index
]->VendorGuid
)) {
224 if (CompareMem (VariableName
, GET_VARIABLE_NAME_PTR (Variable
[Index
]), Variable
[Index
]->NameSize
) == 0) {
225 PtrTrack
->CurrPtr
= Variable
[Index
];
226 PtrTrack
->Volatile
= (BOOLEAN
) Index
;
234 Variable
[Index
] = GetNextVariablePtr (Variable
[Index
]);
237 PtrTrack
->CurrPtr
= NULL
;
238 return EFI_NOT_FOUND
;
242 This code finds variable in storage blocks (Volatile or Non-Volatile).
244 @param VariableName A Null-terminated Unicode string that is the name of
245 the vendor's variable.
246 @param VendorGuid A unique identifier for the vendor.
247 @param Attributes If not NULL, a pointer to the memory location to return the
248 attributes bitmask for the variable.
249 @param DataSize Size of Data found. If size is less than the
250 data, this value contains the required size.
251 @param Data On input, the size in bytes of the return Data buffer.
252 On output, the size of data returned in Data.
253 @param Global Pointer to VARIABLE_GLOBAL structure
254 @param Instance Instance of the Firmware Volume.
256 @retval EFI_SUCCESS The function completed successfully.
257 @retval EFI_NOT_FOUND The variable was not found.
258 @retval EFI_BUFFER_TOO_SMALL DataSize is too small for the result. DataSize has
259 been updated with the size needed to complete the request.
260 @retval EFI_INVALID_PARAMETER VariableName or VendorGuid or DataSize is NULL.
266 IN CHAR16
*VariableName
,
267 IN EFI_GUID
* VendorGuid
,
268 OUT UINT32
*Attributes OPTIONAL
,
269 IN OUT UINTN
*DataSize
,
271 IN VARIABLE_GLOBAL
* Global
,
275 VARIABLE_POINTER_TRACK Variable
;
279 if (VariableName
== NULL
|| VendorGuid
== NULL
|| DataSize
== NULL
) {
280 return EFI_INVALID_PARAMETER
;
283 // Find existing variable
285 Status
= FindVariable (VariableName
, VendorGuid
, &Variable
, Global
);
287 if (Variable
.CurrPtr
== NULL
|| EFI_ERROR (Status
)) {
293 VarDataSize
= Variable
.CurrPtr
->DataSize
;
294 if (*DataSize
>= VarDataSize
) {
296 Status
= EFI_INVALID_PARAMETER
;
300 CopyMem (Data
, GetVariableDataPtr (Variable
.CurrPtr
), VarDataSize
);
301 if (Attributes
!= NULL
) {
302 *Attributes
= Variable
.CurrPtr
->Attributes
;
305 *DataSize
= VarDataSize
;
306 Status
= EFI_SUCCESS
;
309 *DataSize
= VarDataSize
;
310 Status
= EFI_BUFFER_TOO_SMALL
;
315 ReleaseLockOnlyAtBootTime (&Global
->VariableServicesLock
);
321 This code Finds the Next available variable.
323 @param VariableNameSize Size of the variable.
324 @param VariableName On input, supplies the last VariableName that was returned by GetNextVariableName().
325 On output, returns the Null-terminated Unicode string of the current variable.
326 @param VendorGuid On input, supplies the last VendorGuid that was returned by GetNextVariableName().
327 On output, returns the VendorGuid of the current variable.
328 @param Global Pointer to VARIABLE_GLOBAL structure.
329 @param Instance Instance of the Firmware Volume.
331 @retval EFI_SUCCESS The function completed successfully.
332 @retval EFI_NOT_FOUND The next variable was not found.
333 @retval EFI_BUFFER_TOO_SMALL VariableNameSize is too small for the result.
334 VariableNameSize has been updated with the size needed to complete the request.
335 @retval EFI_INVALID_PARAMETER VariableNameSize or VariableName or VendorGuid is NULL.
340 GetNextVariableName (
341 IN OUT UINTN
*VariableNameSize
,
342 IN OUT CHAR16
*VariableName
,
343 IN OUT EFI_GUID
*VendorGuid
,
344 IN VARIABLE_GLOBAL
*Global
,
348 VARIABLE_POINTER_TRACK Variable
;
352 if (VariableNameSize
== NULL
|| VariableName
== NULL
|| VendorGuid
== NULL
) {
353 return EFI_INVALID_PARAMETER
;
356 Status
= FindVariable (VariableName
, VendorGuid
, &Variable
, Global
);
358 if (Variable
.CurrPtr
== NULL
|| EFI_ERROR (Status
)) {
363 if (VariableName
[0] != 0) {
365 // If variable name is not NULL, get next variable
367 Variable
.CurrPtr
= GetNextVariablePtr (Variable
.CurrPtr
);
370 // If both volatile and non-volatile variable store are parsed,
373 if (Variable
.CurrPtr
>= Variable
.EndPtr
|| Variable
.CurrPtr
== NULL
) {
374 Variable
.Volatile
= (BOOLEAN
) (Variable
.Volatile
^ ((BOOLEAN
) 0x1));
375 if (Variable
.Volatile
) {
376 Variable
.StartPtr
= (VARIABLE_HEADER
*) ((UINTN
) (Global
->VolatileVariableBase
+ sizeof (VARIABLE_STORE_HEADER
)));
377 Variable
.EndPtr
= (VARIABLE_HEADER
*) GetEndPointer ((VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->VolatileVariableBase
));
379 Status
= EFI_NOT_FOUND
;
383 Variable
.CurrPtr
= Variable
.StartPtr
;
384 if (Variable
.CurrPtr
->StartId
!= VARIABLE_DATA
) {
391 if (Variable
.CurrPtr
->StartId
== VARIABLE_DATA
&& Variable
.CurrPtr
->State
== VAR_ADDED
) {
392 if (!(EfiAtRuntime () && ((Variable
.CurrPtr
->Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
) == 0))) {
393 VarNameSize
= Variable
.CurrPtr
->NameSize
;
394 if (VarNameSize
<= *VariableNameSize
) {
397 GET_VARIABLE_NAME_PTR (Variable
.CurrPtr
),
402 &Variable
.CurrPtr
->VendorGuid
,
405 Status
= EFI_SUCCESS
;
407 Status
= EFI_BUFFER_TOO_SMALL
;
410 *VariableNameSize
= VarNameSize
;
417 ReleaseLockOnlyAtBootTime (&Global
->VariableServicesLock
);
424 This code sets variable in storage blocks (Volatile or Non-Volatile).
426 @param VariableName A Null-terminated Unicode string that is the name of the vendor's
427 variable. Each VariableName is unique for each
428 VendorGuid. VariableName must contain 1 or more
429 Unicode characters. If VariableName is an empty Unicode
430 string, then EFI_INVALID_PARAMETER is returned.
431 @param VendorGuid A unique identifier for the vendor
432 @param Attributes Attributes bitmask to set for the variable
433 @param DataSize The size in bytes of the Data buffer. A size of zero causes the
434 variable to be deleted.
435 @param Data The contents for the variable
436 @param Global Pointer to VARIABLE_GLOBAL structure
437 @param VolatileOffset The offset of last volatile variable
438 @param NonVolatileOffset The offset of last non-volatile variable
439 @param Instance Instance of the Firmware Volume.
441 @retval EFI_SUCCESS The firmware has successfully stored the variable and its data as
442 defined by the Attributes.
443 @retval EFI_INVALID_PARAMETER An invalid combination of attribute bits was supplied, or the
444 DataSize exceeds the maximum allowed, or VariableName is an empty
445 Unicode string, or VendorGuid is NULL.
446 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data.
447 @retval EFI_DEVICE_ERROR The variable could not be saved due to a hardware failure.
448 @retval EFI_WRITE_PROTECTED The variable in question is read-only or cannot be deleted.
449 @retval EFI_NOT_FOUND The variable trying to be updated or deleted was not found.
455 IN CHAR16
*VariableName
,
456 IN EFI_GUID
*VendorGuid
,
457 IN UINT32 Attributes
,
460 IN VARIABLE_GLOBAL
*Global
,
461 IN UINTN
*VolatileOffset
,
462 IN UINTN
*NonVolatileOffset
,
466 VARIABLE_POINTER_TRACK Variable
;
468 VARIABLE_HEADER
*NextVariable
;
475 // Check input parameters
477 if (VariableName
== NULL
|| VariableName
[0] == 0 || VendorGuid
== NULL
) {
478 return EFI_INVALID_PARAMETER
;
481 // Make sure if runtime bit is set, boot service bit is set also
483 if ((Attributes
& (EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
)) == EFI_VARIABLE_RUNTIME_ACCESS
) {
484 return EFI_INVALID_PARAMETER
;
487 // The size of the VariableName, including the Unicode Null in bytes plus
488 // the DataSize is limited to maximum size of FixedPcdGet32(PcdMaxHardwareErrorVariableSize)
489 // bytes for HwErrRec, and FixedPcdGet32(PcdMaxVariableSize) bytes for the others.
491 if ((Attributes
& EFI_VARIABLE_HARDWARE_ERROR_RECORD
) == EFI_VARIABLE_HARDWARE_ERROR_RECORD
) {
492 if ((DataSize
> FixedPcdGet32(PcdMaxHardwareErrorVariableSize
)) ||
493 (sizeof (VARIABLE_HEADER
) + StrSize (VariableName
) + DataSize
> FixedPcdGet32(PcdMaxHardwareErrorVariableSize
))) {
494 return EFI_INVALID_PARAMETER
;
498 // The size of the VariableName, including the Unicode Null in bytes plus
499 // the DataSize is limited to maximum size of FixedPcdGet32(PcdMaxVariableSize) bytes.
501 if ((DataSize
> FixedPcdGet32(PcdMaxVariableSize
)) ||
502 (sizeof (VARIABLE_HEADER
) + StrSize (VariableName
) + DataSize
> FixedPcdGet32(PcdMaxVariableSize
))) {
503 return EFI_INVALID_PARAMETER
;
507 // Check whether the input variable is already existed
510 Status
= FindVariable (VariableName
, VendorGuid
, &Variable
, Global
);
512 if (Status
== EFI_SUCCESS
&& Variable
.CurrPtr
!= NULL
) {
514 // Update/Delete existing variable
517 if (EfiAtRuntime ()) {
519 // If EfiAtRuntime and the variable is Volatile and Runtime Access,
520 // the volatile is ReadOnly, and SetVariable should be aborted and
521 // return EFI_WRITE_PROTECTED.
523 if (Variable
.Volatile
) {
524 Status
= EFI_WRITE_PROTECTED
;
528 // Only variable have NV attribute can be updated/deleted in Runtime
530 if ((Variable
.CurrPtr
->Attributes
& EFI_VARIABLE_NON_VOLATILE
) == 0) {
531 Status
= EFI_INVALID_PARAMETER
;
537 // Setting a data variable with no access, or zero DataSize attributes
538 // specified causes it to be deleted.
540 if (DataSize
== 0 || (Attributes
& (EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
)) == 0) {
541 Variable
.CurrPtr
->State
&= VAR_DELETED
;
542 Status
= EFI_SUCCESS
;
547 // If the variable is marked valid and the same data has been passed in
548 // then return to the caller immediately.
550 if (Variable
.CurrPtr
->DataSize
== DataSize
&&
551 CompareMem (Data
, GetVariableDataPtr (Variable
.CurrPtr
), DataSize
) == 0
553 Status
= EFI_SUCCESS
;
555 } else if (Variable
.CurrPtr
->State
== VAR_ADDED
) {
557 // Mark the old variable as in delete transition
559 Variable
.CurrPtr
->State
&= VAR_IN_DELETED_TRANSITION
;
562 } else if (Status
== EFI_NOT_FOUND
) {
564 // Create a new variable
568 // Make sure we are trying to create a new variable.
569 // Setting a data variable with no access, or zero DataSize attributes means to delete it.
571 if (DataSize
== 0 || (Attributes
& (EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
)) == 0) {
572 Status
= EFI_NOT_FOUND
;
577 // Only variable have NV|RT attribute can be created in Runtime
579 if (EfiAtRuntime () &&
580 (((Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
) == 0) || ((Attributes
& EFI_VARIABLE_NON_VOLATILE
) == 0))) {
581 Status
= EFI_INVALID_PARAMETER
;
586 // Status should be EFI_INVALID_PARAMETER here according to return status of FindVariable().
588 ASSERT (Status
== EFI_INVALID_PARAMETER
);
593 // Function part - create a new variable and copy the data.
594 // Both update a variable and create a variable will come here.
597 VarNameOffset
= sizeof (VARIABLE_HEADER
);
598 VarNameSize
= StrSize (VariableName
);
599 VarDataOffset
= VarNameOffset
+ VarNameSize
+ GET_PAD_SIZE (VarNameSize
);
600 VarSize
= VarDataOffset
+ DataSize
+ GET_PAD_SIZE (DataSize
);
602 if ((Attributes
& EFI_VARIABLE_NON_VOLATILE
) != 0) {
603 if ((UINT32
) (VarSize
+*NonVolatileOffset
) >
604 ((VARIABLE_STORE_HEADER
*) ((UINTN
) (Global
->NonVolatileVariableBase
)))->Size
606 Status
= EFI_OUT_OF_RESOURCES
;
610 NextVariable
= (VARIABLE_HEADER
*) (UINT8
*) (*NonVolatileOffset
+ (UINTN
) Global
->NonVolatileVariableBase
);
611 *NonVolatileOffset
= *NonVolatileOffset
+ VarSize
;
613 if ((UINT32
) (VarSize
+*VolatileOffset
) >
614 ((VARIABLE_STORE_HEADER
*) ((UINTN
) (Global
->VolatileVariableBase
)))->Size
616 Status
= EFI_OUT_OF_RESOURCES
;
620 NextVariable
= (VARIABLE_HEADER
*) (UINT8
*) (*VolatileOffset
+ (UINTN
) Global
->VolatileVariableBase
);
621 *VolatileOffset
= *VolatileOffset
+ VarSize
;
624 NextVariable
->StartId
= VARIABLE_DATA
;
625 NextVariable
->Attributes
= Attributes
;
626 NextVariable
->State
= VAR_ADDED
;
627 NextVariable
->Reserved
= 0;
630 // There will be pad bytes after Data, the NextVariable->NameSize and
631 // NextVariable->NameSize should not include pad size so that variable
632 // service can get actual size in GetVariable
634 NextVariable
->NameSize
= (UINT32
)VarNameSize
;
635 NextVariable
->DataSize
= (UINT32
)DataSize
;
637 CopyMem (&NextVariable
->VendorGuid
, VendorGuid
, sizeof (EFI_GUID
));
639 (UINT8
*) ((UINTN
) NextVariable
+ VarNameOffset
),
644 (UINT8
*) ((UINTN
) NextVariable
+ VarDataOffset
),
650 // Mark the old variable as deleted
652 if (!EFI_ERROR (Status
)) {
653 Variable
.CurrPtr
->State
&= VAR_DELETED
;
656 Status
= EFI_SUCCESS
;
658 ReleaseLockOnlyAtBootTime (&Global
->VariableServicesLock
);
664 This code returns information about the EFI variables.
666 @param Attributes Attributes bitmask to specify the type of variables
667 on which to return information.
668 @param MaximumVariableStorageSize On output the maximum size of the storage space available for
669 the EFI variables associated with the attributes specified.
670 @param RemainingVariableStorageSize Returns the remaining size of the storage space available for EFI
671 variables associated with the attributes specified.
672 @param MaximumVariableSize Returns the maximum size of an individual EFI variable
673 associated with the attributes specified.
674 @param Global Pointer to VARIABLE_GLOBAL structure.
675 @param Instance Instance of the Firmware Volume.
677 @retval EFI_SUCCESS Valid answer returned.
678 @retval EFI_INVALID_PARAMETER An invalid combination of attribute bits was supplied
679 @retval EFI_UNSUPPORTED The attribute is not supported on this platform, and the
680 MaximumVariableStorageSize, RemainingVariableStorageSize,
681 MaximumVariableSize are undefined.
687 IN UINT32 Attributes
,
688 OUT UINT64
*MaximumVariableStorageSize
,
689 OUT UINT64
*RemainingVariableStorageSize
,
690 OUT UINT64
*MaximumVariableSize
,
691 IN VARIABLE_GLOBAL
*Global
,
695 VARIABLE_HEADER
*Variable
;
696 VARIABLE_HEADER
*NextVariable
;
698 VARIABLE_STORE_HEADER
*VariableStoreHeader
;
700 if(MaximumVariableStorageSize
== NULL
|| RemainingVariableStorageSize
== NULL
|| MaximumVariableSize
== NULL
|| Attributes
== 0) {
701 return EFI_INVALID_PARAMETER
;
704 if((Attributes
& (EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_HARDWARE_ERROR_RECORD
)) == 0) {
706 // Make sure the Attributes combination is supported by the platform.
708 return EFI_UNSUPPORTED
;
709 } else if ((Attributes
& (EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
)) == EFI_VARIABLE_RUNTIME_ACCESS
) {
711 // Make sure if runtime bit is set, boot service bit is set also.
713 return EFI_INVALID_PARAMETER
;
714 } else if (EfiAtRuntime () && ((Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
) == 0)) {
716 // Make sure RT Attribute is set if we are in Runtime phase.
718 return EFI_INVALID_PARAMETER
;
721 AcquireLockOnlyAtBootTime(&Global
->VariableServicesLock
);
723 if((Attributes
& EFI_VARIABLE_NON_VOLATILE
) == 0) {
725 // Query is Volatile related.
727 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->VolatileVariableBase
);
730 // Query is Non-Volatile related.
732 VariableStoreHeader
= (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->NonVolatileVariableBase
);
736 // Now let's fill *MaximumVariableStorageSize *RemainingVariableStorageSize
737 // with the storage size (excluding the storage header size)
739 *MaximumVariableStorageSize
= VariableStoreHeader
->Size
- sizeof (VARIABLE_STORE_HEADER
);
740 *RemainingVariableStorageSize
= VariableStoreHeader
->Size
- sizeof (VARIABLE_STORE_HEADER
);
743 // Let *MaximumVariableSize be FixedPcdGet32(PcdMaxVariableSize) with the exception of the variable header size.
745 *MaximumVariableSize
= FixedPcdGet32(PcdMaxVariableSize
) - sizeof (VARIABLE_HEADER
);
748 // Harware error record variable needs larger size.
750 if ((Attributes
& EFI_VARIABLE_HARDWARE_ERROR_RECORD
) == EFI_VARIABLE_HARDWARE_ERROR_RECORD
) {
751 *MaximumVariableSize
= FixedPcdGet32(PcdMaxHardwareErrorVariableSize
) - sizeof (VARIABLE_HEADER
);
755 // Point to the starting address of the variables.
757 Variable
= (VARIABLE_HEADER
*) (VariableStoreHeader
+ 1);
760 // Now walk through the related variable store.
762 while (Variable
< GetEndPointer (VariableStoreHeader
)) {
763 if (Variable
->StartId
!= VARIABLE_DATA
) {
767 NextVariable
= (VARIABLE_HEADER
*) (GetVariableDataPtr (Variable
) + Variable
->DataSize
+ GET_PAD_SIZE (Variable
->DataSize
));
768 VariableSize
= (UINT64
) (UINTN
) NextVariable
- (UINT64
) (UINTN
) Variable
;
770 if (Variable
->State
== VAR_ADDED
) {
771 *RemainingVariableStorageSize
-= VariableSize
;
775 // Go to the next one.
777 Variable
= NextVariable
;
780 if (*RemainingVariableStorageSize
< sizeof (VARIABLE_HEADER
)) {
781 *MaximumVariableSize
= 0;
782 } else if ((*RemainingVariableStorageSize
- sizeof (VARIABLE_HEADER
)) < *MaximumVariableSize
) {
783 *MaximumVariableSize
= *RemainingVariableStorageSize
- sizeof (VARIABLE_HEADER
);
786 ReleaseLockOnlyAtBootTime (&Global
->VariableServicesLock
);
791 Initializes variable store area.
793 This function allocates memory space for variable store area and initializes its attributes.
795 @param VariableBase Base of the variable store area created
796 @param LastVariableOffset Size of VARIABLE_STORE_HEADER
800 InitializeVariableStore (
801 OUT EFI_PHYSICAL_ADDRESS
*VariableBase
,
802 OUT UINTN
*LastVariableOffset
805 VARIABLE_STORE_HEADER
*VariableStore
;
808 // Allocate memory for volatile variable store
810 VariableStore
= (VARIABLE_STORE_HEADER
*) AllocateRuntimePool (
811 FixedPcdGet32(PcdVariableStoreSize
)
813 if (NULL
== VariableStore
) {
814 return EFI_OUT_OF_RESOURCES
;
817 SetMem (VariableStore
, FixedPcdGet32(PcdVariableStoreSize
), 0xff);
820 // Variable Specific Data
822 *VariableBase
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) VariableStore
;
823 *LastVariableOffset
= sizeof (VARIABLE_STORE_HEADER
);
825 VariableStore
->Signature
= VARIABLE_STORE_SIGNATURE
;
826 VariableStore
->Size
= FixedPcdGet32(PcdVariableStoreSize
);
827 VariableStore
->Format
= VARIABLE_STORE_FORMATTED
;
828 VariableStore
->State
= VARIABLE_STORE_HEALTHY
;
829 VariableStore
->Reserved
= 0;
830 VariableStore
->Reserved1
= 0;
836 Initializes variable store area for non-volatile and volatile variable.
838 This function allocates and initializes memory space for global context of ESAL
839 variable service and variable store area for non-volatile and volatile variable.
841 @param ImageHandle The Image handle of this driver.
842 @param SystemTable The pointer of EFI_SYSTEM_TABLE.
844 @retval EFI_SUCCESS Function successfully executed.
845 @retval EFI_OUT_OF_RESOURCES Fail to allocate enough memory resource.
850 VariableCommonInitialize (
851 IN EFI_HANDLE ImageHandle
,
852 IN EFI_SYSTEM_TABLE
*SystemTable
858 // Allocate memory for mVariableModuleGlobal
860 mVariableModuleGlobal
= (ESAL_VARIABLE_GLOBAL
*) AllocateRuntimePool (
861 sizeof (ESAL_VARIABLE_GLOBAL
)
863 if (NULL
== mVariableModuleGlobal
) {
864 return EFI_OUT_OF_RESOURCES
;
867 EfiInitializeLock(&mVariableModuleGlobal
->VariableGlobal
[Physical
].VariableServicesLock
, TPL_NOTIFY
);
870 // Intialize volatile variable store
872 Status
= InitializeVariableStore (
873 &mVariableModuleGlobal
->VariableGlobal
[Physical
].VolatileVariableBase
,
874 &mVariableModuleGlobal
->VolatileLastVariableOffset
877 if (EFI_ERROR (Status
)) {
881 // Intialize non volatile variable store
883 Status
= InitializeVariableStore (
884 &mVariableModuleGlobal
->VariableGlobal
[Physical
].NonVolatileVariableBase
,
885 &mVariableModuleGlobal
->NonVolatileLastVariableOffset