3 Copyright (c) 2006, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
25 // Don't use module globals after the SetVirtualAddress map is signaled
27 ESAL_VARIABLE_GLOBAL
*mVariableModuleGlobal
;
38 Determine the length of null terminated char16 array.
42 String Null-terminated CHAR16 array pointer.
46 UINT32 Number of bytes in the string, including the double NULL at the end;
58 while (0 != String
[Count
]) {
62 return (Count
* 2) + 2;
74 This function return the pad size for alignment
78 Value The value need to align
87 // If alignment is 0 or 1, means no alignment required
89 if (ALIGNMENT
== 0 || ALIGNMENT
== 1) {
93 return ALIGNMENT
- (Value
% ALIGNMENT
);
98 GetVariableStoreStatus (
99 IN VARIABLE_STORE_HEADER
*VarStoreHeader
105 This code gets the pointer to the variable name.
109 VarStoreHeader Pointer to the Variable Store Header.
113 EfiHealthy Variable store is healthy
114 EfiRaw Variable store is raw
115 EfiInvalid Variable store is invalid
119 if (VarStoreHeader
->Signature
== VARIABLE_STORE_SIGNATURE
&&
120 VarStoreHeader
->Format
== VARIABLE_STORE_FORMATTED
&&
121 VarStoreHeader
->State
== VARIABLE_STORE_HEALTHY
125 } else if (VarStoreHeader
->Signature
== 0xffffffff &&
126 VarStoreHeader
->Size
== 0xffffffff &&
127 VarStoreHeader
->Format
== 0xff &&
128 VarStoreHeader
->State
== 0xff
140 IN VARIABLE_HEADER
*Variable
146 This code gets the pointer to the variable data.
150 Variable Pointer to the Variable Header.
154 UINT8* Pointer to Variable Data
158 if (Variable
->StartId
!= VARIABLE_DATA
) {
162 // Be careful about pad size for alignment
164 return (UINT8
*) ((UINTN
) GET_VARIABLE_NAME_PTR (Variable
) + Variable
->NameSize
+ GetPadSize (Variable
->NameSize
));
170 IN VARIABLE_HEADER
*Variable
176 This code gets the pointer to the next variable header.
180 Variable Pointer to the Variable Header.
184 VARIABLE_HEADER* Pointer to next variable header.
188 VARIABLE_HEADER
*VarHeader
;
190 if (Variable
->StartId
!= VARIABLE_DATA
) {
194 // Be careful about pad size for alignment
196 VarHeader
= (VARIABLE_HEADER
*) (GetVariableDataPtr (Variable
) + Variable
->DataSize
+ GET_PAD_SIZE (Variable
->DataSize
));
198 if (VarHeader
->StartId
!= VARIABLE_DATA
||
199 (sizeof (VARIABLE_HEADER
) + VarHeader
->DataSize
+ VarHeader
->NameSize
) > MAX_VARIABLE_SIZE
210 IN VARIABLE_STORE_HEADER
*VolHeader
216 This code gets the pointer to the last variable memory pointer byte
220 Variable Pointer to the Variable Header.
224 VARIABLE_HEADER* Pointer to last unavailable Variable Header
229 // The end of variable store
231 return (VARIABLE_HEADER
*) ((UINTN
) VolHeader
+ VolHeader
->Size
);
237 IN CHAR16
*VariableName
,
238 IN EFI_GUID
*VendorGuid
,
239 OUT VARIABLE_POINTER_TRACK
*PtrTrack
,
240 IN VARIABLE_GLOBAL
*Global
246 This code finds variable in storage blocks (Volatile or Non-Volatile)
250 VariableName Name of the variable to be found
251 VendorGuid Vendor GUID to be found.
252 PtrTrack Variable Track Pointer structure that contains
253 Variable Information.
254 Contains the pointer of Variable header.
255 Global VARIABLE_GLOBAL pointer
263 VARIABLE_HEADER
*Variable
[2];
264 VARIABLE_STORE_HEADER
*VariableStoreHeader
[2];
268 // 0: Non-Volatile, 1: Volatile
270 VariableStoreHeader
[0] = (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->NonVolatileVariableBase
);
271 VariableStoreHeader
[1] = (VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->VolatileVariableBase
);
274 // Start Pointers for the variable.
275 // Actual Data Pointer where data can be written.
277 Variable
[0] = (VARIABLE_HEADER
*) (VariableStoreHeader
[0] + 1);
278 Variable
[1] = (VARIABLE_HEADER
*) (VariableStoreHeader
[1] + 1);
280 if (VariableName
[0] != 0 && VendorGuid
== NULL
) {
281 return EFI_INVALID_PARAMETER
;
284 // Find the variable by walk through non-volatile and volatile variable store
286 for (Index
= 0; Index
< 2; Index
++) {
287 PtrTrack
->StartPtr
= (VARIABLE_HEADER
*) (VariableStoreHeader
[Index
] + 1);
288 PtrTrack
->EndPtr
= GetEndPointer (VariableStoreHeader
[Index
]);
290 while ((Variable
[Index
] != NULL
) && (Variable
[Index
] <= GetEndPointer (VariableStoreHeader
[Index
]))) {
291 if (Variable
[Index
]->StartId
== VARIABLE_DATA
&& Variable
[Index
]->State
== VAR_ADDED
) {
292 if (!(EfiAtRuntime () && !(Variable
[Index
]->Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
))) {
293 if (VariableName
[0] == 0) {
294 PtrTrack
->CurrPtr
= Variable
[Index
];
295 PtrTrack
->Volatile
= (BOOLEAN
) Index
;
298 if (CompareGuid (VendorGuid
, &Variable
[Index
]->VendorGuid
)) {
299 if (!CompareMem (VariableName
, GET_VARIABLE_NAME_PTR (Variable
[Index
]), ArrayLength (VariableName
))) {
300 PtrTrack
->CurrPtr
= Variable
[Index
];
301 PtrTrack
->Volatile
= (BOOLEAN
) Index
;
309 Variable
[Index
] = GetNextVariablePtr (Variable
[Index
]);
312 PtrTrack
->CurrPtr
= NULL
;
313 return EFI_NOT_FOUND
;
319 IN CHAR16
*VariableName
,
320 IN EFI_GUID
* VendorGuid
,
321 OUT UINT32
*Attributes OPTIONAL
,
322 IN OUT UINTN
*DataSize
,
324 IN VARIABLE_GLOBAL
* Global
,
331 This code finds variable in storage blocks (Volatile or Non-Volatile)
335 VariableName Name of Variable to be found
336 VendorGuid Variable vendor GUID
337 Attributes OPTIONAL Attribute value of the variable found
338 DataSize Size of Data found. If size is less than the
339 data, this value contains the required size.
341 Global Pointer to VARIABLE_GLOBAL structure
342 Instance Instance of the Firmware Volume.
350 VARIABLE_POINTER_TRACK Variable
;
354 if (VariableName
== NULL
|| VendorGuid
== NULL
|| DataSize
== NULL
) {
355 return EFI_INVALID_PARAMETER
;
358 // Find existing variable
360 Status
= FindVariable (VariableName
, VendorGuid
, &Variable
, Global
);
362 if (Variable
.CurrPtr
== NULL
|| EFI_ERROR (Status
)) {
368 VarDataSize
= Variable
.CurrPtr
->DataSize
;
369 if (*DataSize
>= VarDataSize
) {
370 CopyMem (Data
, GetVariableDataPtr (Variable
.CurrPtr
), VarDataSize
);
372 *Attributes
= Variable
.CurrPtr
->Attributes
;
375 *DataSize
= VarDataSize
;
378 *DataSize
= VarDataSize
;
379 return EFI_BUFFER_TOO_SMALL
;
385 GetNextVariableName (
386 IN OUT UINTN
*VariableNameSize
,
387 IN OUT CHAR16
*VariableName
,
388 IN OUT EFI_GUID
*VendorGuid
,
389 IN VARIABLE_GLOBAL
*Global
,
396 This code Finds the Next available variable
400 VariableNameSize Size of the variable
401 VariableName Pointer to variable name
402 VendorGuid Variable Vendor Guid
403 Global VARIABLE_GLOBAL structure pointer.
412 VARIABLE_POINTER_TRACK Variable
;
416 if (VariableNameSize
== NULL
|| VendorGuid
== NULL
) {
417 return EFI_INVALID_PARAMETER
;
420 Status
= FindVariable (VariableName
, VendorGuid
, &Variable
, Global
);
422 if (Variable
.CurrPtr
== NULL
|| EFI_ERROR (Status
)) {
427 if (VariableName
[0] != 0) {
429 // If variable name is not NULL, get next variable
431 Variable
.CurrPtr
= GetNextVariablePtr (Variable
.CurrPtr
);
434 // If both volatile and non-volatile variable store are parsed,
437 if (Variable
.CurrPtr
>= Variable
.EndPtr
|| Variable
.CurrPtr
== NULL
) {
438 Variable
.Volatile
= (BOOLEAN
) (Variable
.Volatile
^ ((BOOLEAN
) 0x1));
439 if (Variable
.Volatile
) {
440 Variable
.StartPtr
= (VARIABLE_HEADER
*) ((UINTN
) (Global
->VolatileVariableBase
+ sizeof (VARIABLE_STORE_HEADER
)));
441 Variable
.EndPtr
= (VARIABLE_HEADER
*) GetEndPointer ((VARIABLE_STORE_HEADER
*) ((UINTN
) Global
->VolatileVariableBase
));
443 return EFI_NOT_FOUND
;
446 Variable
.CurrPtr
= Variable
.StartPtr
;
447 if (Variable
.CurrPtr
->StartId
!= VARIABLE_DATA
) {
454 if (Variable
.CurrPtr
->StartId
== VARIABLE_DATA
&& Variable
.CurrPtr
->State
== VAR_ADDED
) {
455 if (!(EfiAtRuntime () && !(Variable
.CurrPtr
->Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
))) {
456 VarNameSize
= Variable
.CurrPtr
->NameSize
;
457 if (VarNameSize
<= *VariableNameSize
) {
460 GET_VARIABLE_NAME_PTR (Variable
.CurrPtr
),
465 &Variable
.CurrPtr
->VendorGuid
,
468 Status
= EFI_SUCCESS
;
470 Status
= EFI_BUFFER_TOO_SMALL
;
473 *VariableNameSize
= VarNameSize
;
479 return EFI_NOT_FOUND
;
485 IN CHAR16
*VariableName
,
486 IN EFI_GUID
*VendorGuid
,
487 IN UINT32 Attributes
,
490 IN VARIABLE_GLOBAL
*Global
,
491 IN UINTN
*VolatileOffset
,
492 IN UINTN
*NonVolatileOffset
,
499 This code sets variable in storage blocks (Volatile or Non-Volatile)
503 VariableName Name of Variable to be found
504 VendorGuid Variable vendor GUID
505 Attributes Attribute value of the variable found
506 DataSize Size of Data found. If size is less than the
507 data, this value contains the required size.
509 Global Pointer to VARIABLE_GLOBAL structure
510 VolatileOffset The offset of last volatile variable
511 NonVolatileOffset The offset of last non-volatile variable
512 Instance Instance of the Firmware Volume.
520 VARIABLE_POINTER_TRACK Variable
;
522 VARIABLE_HEADER
*NextVariable
;
528 if (VariableName
== NULL
|| VariableName
[0] == 0 || VendorGuid
== NULL
) {
529 return EFI_INVALID_PARAMETER
;
532 Status
= FindVariable (VariableName
, VendorGuid
, &Variable
, Global
);
534 if (Status
== EFI_INVALID_PARAMETER
) {
538 // The size of the VariableName, including the Unicode Null in bytes plus
539 // the DataSize is limited to maximum size of MAX_VARIABLE_SIZE (1024) bytes.
541 else if (sizeof (VARIABLE_HEADER
) + (ArrayLength (VariableName
) + DataSize
) > MAX_VARIABLE_SIZE
) {
542 return EFI_INVALID_PARAMETER
;
545 // Make sure if runtime bit is set, boot service bit is set also
547 else if ((Attributes
& (EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
)) == EFI_VARIABLE_RUNTIME_ACCESS
549 return EFI_INVALID_PARAMETER
;
552 // Runtime but Attribute is not Runtime
554 else if (EfiAtRuntime () && Attributes
&& !(Attributes
& EFI_VARIABLE_RUNTIME_ACCESS
)) {
555 return EFI_INVALID_PARAMETER
;
558 // Cannot set volatile variable in Runtime
560 else if (EfiAtRuntime () && Attributes
&& !(Attributes
& EFI_VARIABLE_NON_VOLATILE
)) {
561 return EFI_INVALID_PARAMETER
;
564 // Setting a data variable with no access, or zero DataSize attributes
565 // specified causes it to be deleted.
567 else if (DataSize
== 0 || Attributes
== 0) {
568 if (!EFI_ERROR (Status
)) {
569 Variable
.CurrPtr
->State
&= VAR_DELETED
;
573 return EFI_NOT_FOUND
;
575 if (!EFI_ERROR (Status
)) {
577 // If the variable is marked valid and the same data has been passed in
578 // then return to the caller immediately.
580 if (Variable
.CurrPtr
->DataSize
== DataSize
&&
581 !CompareMem (Data
, GetVariableDataPtr (Variable
.CurrPtr
), DataSize
)
584 } else if (Variable
.CurrPtr
->State
== VAR_ADDED
) {
586 // Mark the old variable as in delete transition
588 Variable
.CurrPtr
->State
&= VAR_IN_DELETED_TRANSITION
;
592 // Create a new variable and copy the data.
594 VarNameOffset
= sizeof (VARIABLE_HEADER
);
595 VarNameSize
= ArrayLength (VariableName
);
596 VarDataOffset
= VarNameOffset
+ VarNameSize
+ GetPadSize (VarNameSize
);
597 VarSize
= VarDataOffset
+ DataSize
+ GetPadSize (DataSize
);
599 if (Attributes
& EFI_VARIABLE_NON_VOLATILE
) {
600 if ((UINT32
) (VarSize
+*NonVolatileOffset
) >
601 ((VARIABLE_STORE_HEADER
*) ((UINTN
) (Global
->NonVolatileVariableBase
)))->Size
603 return EFI_OUT_OF_RESOURCES
;
606 NextVariable
= (VARIABLE_HEADER
*) (UINT8
*) (*NonVolatileOffset
+ (UINTN
) Global
->NonVolatileVariableBase
);
607 *NonVolatileOffset
= *NonVolatileOffset
+ VarSize
;
609 if (EfiAtRuntime ()) {
610 return EFI_INVALID_PARAMETER
;
613 if ((UINT32
) (VarSize
+*VolatileOffset
) >
614 ((VARIABLE_STORE_HEADER
*) ((UINTN
) (Global
->VolatileVariableBase
)))->Size
616 return EFI_OUT_OF_RESOURCES
;
619 NextVariable
= (VARIABLE_HEADER
*) (UINT8
*) (*VolatileOffset
+ (UINTN
) Global
->VolatileVariableBase
);
620 *VolatileOffset
= *VolatileOffset
+ VarSize
;
623 NextVariable
->StartId
= VARIABLE_DATA
;
624 NextVariable
->Attributes
= Attributes
;
625 NextVariable
->State
= VAR_ADDED
;
626 NextVariable
->Reserved
= 0;
629 // There will be pad bytes after Data, the NextVariable->NameSize and
630 // NextVariable->NameSize should not include pad size so that variable
631 // service can get actual size in GetVariable
633 NextVariable
->NameSize
= (UINT32
)VarNameSize
;
634 NextVariable
->DataSize
= (UINT32
)DataSize
;
636 CopyMem (&NextVariable
->VendorGuid
, VendorGuid
, sizeof (EFI_GUID
));
638 (UINT8
*) ((UINTN
) NextVariable
+ VarNameOffset
),
643 (UINT8
*) ((UINTN
) NextVariable
+ VarDataOffset
),
649 // Mark the old variable as deleted
651 if (!EFI_ERROR (Status
)) {
652 Variable
.CurrPtr
->State
&= VAR_DELETED
;
661 InitializeVariableStore (
662 OUT EFI_PHYSICAL_ADDRESS
*VariableBase
,
663 OUT UINTN
*LastVariableOffset
668 This function initializes variable store
676 VARIABLE_STORE_HEADER
*VariableStore
;
679 // Allocate memory for volatile variable store
681 VariableStore
= (VARIABLE_STORE_HEADER
*) AllocateRuntimePool (
684 if (NULL
== VariableStore
) {
685 return EFI_OUT_OF_RESOURCES
;
688 SetMem (VariableStore
, VARIABLE_STORE_SIZE
, 0xff);
691 // Variable Specific Data
693 *VariableBase
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) VariableStore
;
694 *LastVariableOffset
= sizeof (VARIABLE_STORE_HEADER
);
696 VariableStore
->Signature
= VARIABLE_STORE_SIGNATURE
;
697 VariableStore
->Size
= VARIABLE_STORE_SIZE
;
698 VariableStore
->Format
= VARIABLE_STORE_FORMATTED
;
699 VariableStore
->State
= VARIABLE_STORE_HEALTHY
;
700 VariableStore
->Reserved
= 0;
701 VariableStore
->Reserved1
= 0;
708 VariableCommonInitialize (
709 IN EFI_HANDLE ImageHandle
,
710 IN EFI_SYSTEM_TABLE
*SystemTable
715 This function does common initialization for variable services
726 // Allocate memory for mVariableModuleGlobal
728 mVariableModuleGlobal
= (ESAL_VARIABLE_GLOBAL
*) AllocateRuntimePool (
729 sizeof (ESAL_VARIABLE_GLOBAL
)
731 if (NULL
== mVariableModuleGlobal
) {
732 return EFI_OUT_OF_RESOURCES
;
735 // Intialize volatile variable store
737 Status
= InitializeVariableStore (
738 &mVariableModuleGlobal
->VariableBase
[Physical
].VolatileVariableBase
,
739 &mVariableModuleGlobal
->VolatileLastVariableOffset
742 if (EFI_ERROR (Status
)) {
746 // Intialize non volatile variable store
748 Status
= InitializeVariableStore (
749 &mVariableModuleGlobal
->VariableBase
[Physical
].NonVolatileVariableBase
,
750 &mVariableModuleGlobal
->NonVolatileLastVariableOffset