fix ecc warning
[edk2.git] / MdeModulePkg / Universal / Variable / EmuRuntimeDxe / EmuVariable.c
blobcb56f6607841244dfea5568cc30cfa51ce3cf556
1 /** @file
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.
15 **/
17 #include "Variable.h"
19 ///
20 /// Don't use module globals after the SetVirtualAddress map is signaled
21 ///
22 ESAL_VARIABLE_GLOBAL *mVariableModuleGlobal;
25 /**
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
32 at runtime
34 @param Lock A pointer to the lock to acquire
36 **/
37 VOID
38 AcquireLockOnlyAtBootTime (
39 IN EFI_LOCK *Lock
42 if (!EfiAtRuntime ()) {
43 EfiAcquireLock (Lock);
47 /**
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
54 at runtime
56 @param Lock A pointer to the lock to release
58 **/
59 VOID
60 ReleaseLockOnlyAtBootTime (
61 IN EFI_LOCK *Lock
64 if (!EfiAtRuntime ()) {
65 EfiReleaseLock (Lock);
69 /**
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
79 **/
80 UINT8 *
81 GetVariableDataPtr (
82 IN VARIABLE_HEADER *Variable
85 if (Variable->StartId != VARIABLE_DATA) {
86 return NULL;
89 // Be careful about pad size for alignment
91 return (UINT8 *) ((UINTN) GET_VARIABLE_NAME_PTR (Variable) + Variable->NameSize + GET_PAD_SIZE (Variable->NameSize));
94 /**
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.
105 VARIABLE_HEADER *
106 GetNextVariablePtr (
107 IN VARIABLE_HEADER *Variable
110 VARIABLE_HEADER *VarHeader;
112 if (Variable->StartId != VARIABLE_DATA) {
113 return NULL;
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)
123 return NULL;
126 return VarHeader;
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.
140 VARIABLE_HEADER *
141 GetEndPointer (
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
168 VendorGuid is NULL.
169 @retval EFI_SUCCESS Variable successfully found.
170 @retval EFI_NOT_FOUND Variable not found.
173 EFI_STATUS
174 FindVariable (
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];
183 UINTN Index;
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;
221 return EFI_SUCCESS;
222 } else {
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;
227 return EFI_SUCCESS;
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.
263 EFI_STATUS
264 EFIAPI
265 GetVariable (
266 IN CHAR16 *VariableName,
267 IN EFI_GUID * VendorGuid,
268 OUT UINT32 *Attributes OPTIONAL,
269 IN OUT UINTN *DataSize,
270 OUT VOID *Data,
271 IN VARIABLE_GLOBAL * Global,
272 IN UINT32 Instance
275 VARIABLE_POINTER_TRACK Variable;
276 UINTN VarDataSize;
277 EFI_STATUS Status;
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)) {
288 goto Done;
291 // Get data size
293 VarDataSize = Variable.CurrPtr->DataSize;
294 if (*DataSize >= VarDataSize) {
295 if (Data == NULL) {
296 Status = EFI_INVALID_PARAMETER;
297 goto Done;
300 CopyMem (Data, GetVariableDataPtr (Variable.CurrPtr), VarDataSize);
301 if (Attributes != NULL) {
302 *Attributes = Variable.CurrPtr->Attributes;
305 *DataSize = VarDataSize;
306 Status = EFI_SUCCESS;
307 goto Done;
308 } else {
309 *DataSize = VarDataSize;
310 Status = EFI_BUFFER_TOO_SMALL;
311 goto Done;
314 Done:
315 ReleaseLockOnlyAtBootTime (&Global->VariableServicesLock);
316 return Status;
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.
338 EFI_STATUS
339 EFIAPI
340 GetNextVariableName (
341 IN OUT UINTN *VariableNameSize,
342 IN OUT CHAR16 *VariableName,
343 IN OUT EFI_GUID *VendorGuid,
344 IN VARIABLE_GLOBAL *Global,
345 IN UINT32 Instance
348 VARIABLE_POINTER_TRACK Variable;
349 UINTN VarNameSize;
350 EFI_STATUS Status;
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)) {
359 goto Done;
362 while (TRUE) {
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,
371 // return not found
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));
378 } else {
379 Status = EFI_NOT_FOUND;
380 goto Done;
383 Variable.CurrPtr = Variable.StartPtr;
384 if (Variable.CurrPtr->StartId != VARIABLE_DATA) {
385 continue;
389 // Variable is found
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) {
395 CopyMem (
396 VariableName,
397 GET_VARIABLE_NAME_PTR (Variable.CurrPtr),
398 VarNameSize
400 CopyMem (
401 VendorGuid,
402 &Variable.CurrPtr->VendorGuid,
403 sizeof (EFI_GUID)
405 Status = EFI_SUCCESS;
406 } else {
407 Status = EFI_BUFFER_TOO_SMALL;
410 *VariableNameSize = VarNameSize;
411 goto Done;
416 Done:
417 ReleaseLockOnlyAtBootTime (&Global->VariableServicesLock);
418 return Status;
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.
452 EFI_STATUS
453 EFIAPI
454 SetVariable (
455 IN CHAR16 *VariableName,
456 IN EFI_GUID *VendorGuid,
457 IN UINT32 Attributes,
458 IN UINTN DataSize,
459 IN VOID *Data,
460 IN VARIABLE_GLOBAL *Global,
461 IN UINTN *VolatileOffset,
462 IN UINTN *NonVolatileOffset,
463 IN UINT32 Instance
466 VARIABLE_POINTER_TRACK Variable;
467 EFI_STATUS Status;
468 VARIABLE_HEADER *NextVariable;
469 UINTN VarNameSize;
470 UINTN VarNameOffset;
471 UINTN VarDataOffset;
472 UINTN VarSize;
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;
496 } else {
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;
525 goto Done;
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;
532 goto Done;
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;
543 goto Done;
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;
554 goto Done;
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;
573 goto Done;
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;
582 goto Done;
584 } else {
586 // Status should be EFI_INVALID_PARAMETER here according to return status of FindVariable().
588 ASSERT (Status == EFI_INVALID_PARAMETER);
589 goto Done;
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;
607 goto Done;
610 NextVariable = (VARIABLE_HEADER *) (UINT8 *) (*NonVolatileOffset + (UINTN) Global->NonVolatileVariableBase);
611 *NonVolatileOffset = *NonVolatileOffset + VarSize;
612 } else {
613 if ((UINT32) (VarSize +*VolatileOffset) >
614 ((VARIABLE_STORE_HEADER *) ((UINTN) (Global->VolatileVariableBase)))->Size
616 Status = EFI_OUT_OF_RESOURCES;
617 goto Done;
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));
638 CopyMem (
639 (UINT8 *) ((UINTN) NextVariable + VarNameOffset),
640 VariableName,
641 VarNameSize
643 CopyMem (
644 (UINT8 *) ((UINTN) NextVariable + VarDataOffset),
645 Data,
646 DataSize
650 // Mark the old variable as deleted
652 if (!EFI_ERROR (Status)) {
653 Variable.CurrPtr->State &= VAR_DELETED;
656 Status = EFI_SUCCESS;
657 Done:
658 ReleaseLockOnlyAtBootTime (&Global->VariableServicesLock);
659 return Status;
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.
684 EFI_STATUS
685 EFIAPI
686 QueryVariableInfo (
687 IN UINT32 Attributes,
688 OUT UINT64 *MaximumVariableStorageSize,
689 OUT UINT64 *RemainingVariableStorageSize,
690 OUT UINT64 *MaximumVariableSize,
691 IN VARIABLE_GLOBAL *Global,
692 IN UINT32 Instance
695 VARIABLE_HEADER *Variable;
696 VARIABLE_HEADER *NextVariable;
697 UINT64 VariableSize;
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);
728 } else {
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) {
764 break;
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);
787 return EFI_SUCCESS;
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
799 EFI_STATUS
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;
832 return EFI_SUCCESS;
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.
848 EFI_STATUS
849 EFIAPI
850 VariableCommonInitialize (
851 IN EFI_HANDLE ImageHandle,
852 IN EFI_SYSTEM_TABLE *SystemTable
855 EFI_STATUS Status;
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)) {
878 return Status;
881 // Intialize non volatile variable store
883 Status = InitializeVariableStore (
884 &mVariableModuleGlobal->VariableGlobal[Physical].NonVolatileVariableBase,
885 &mVariableModuleGlobal->NonVolatileLastVariableOffset
888 return Status;