]> git.proxmox.com Git - mirror_edk2.git/blob - EdkModulePkg/Universal/EmuVariable/RuntimeDxe/EmuVariable.c
STATIC should be prefixed for internal functions to pass the stringent compiler such...
[mirror_edk2.git] / EdkModulePkg / Universal / EmuVariable / RuntimeDxe / EmuVariable.c
1 /*++
2
3 Copyright (c) 2006 - 2007, 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
8
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.
11
12 Module Name:
13
14 EmuVariable.c
15
16 Abstract:
17
18 Revision History
19
20 --*/
21
22 #include "Variable.h"
23
24 //
25 // Don't use module globals after the SetVirtualAddress map is signaled
26 //
27 ESAL_VARIABLE_GLOBAL *mVariableModuleGlobal;
28
29 //
30 // This is a temperary function which will be removed
31 // when EfiAcquireLock in UefiLib can handle the
32 // the call in UEFI Runtimer driver in RT phase.
33 //
34 STATIC
35 VOID
36 AcquireLockOnlyAtBootTime (
37 IN EFI_LOCK *Lock
38 )
39 {
40 if (!EfiAtRuntime ()) {
41 EfiAcquireLock (Lock);
42 }
43 }
44
45 //
46 // This is a temperary function which will be removed
47 // when EfiAcquireLock in UefiLib can handle the
48 // the call in UEFI Runtimer driver in RT phase.
49 //
50 STATIC
51 VOID
52 ReleaseLockOnlyAtBootTime (
53 IN EFI_LOCK *Lock
54 )
55 {
56 if (!EfiAtRuntime ()) {
57 EfiReleaseLock (Lock);
58 }
59 }
60
61
62 STATIC
63 UINT32
64 EFIAPI
65 ArrayLength (
66 IN CHAR16 *String
67 )
68 /*++
69
70 Routine Description:
71
72 Determine the length of null terminated char16 array.
73
74 Arguments:
75
76 String Null-terminated CHAR16 array pointer.
77
78 Returns:
79
80 UINT32 Number of bytes in the string, including the double NULL at the end;
81
82 --*/
83 {
84 UINT32 Count;
85
86 if (NULL == String) {
87 return 0;
88 }
89
90 Count = 0;
91
92 while (0 != String[Count]) {
93 Count++;
94 }
95
96 return (Count * 2) + 2;
97 }
98
99 STATIC
100 UINT8 *
101 EFIAPI
102 GetVariableDataPtr (
103 IN VARIABLE_HEADER *Variable
104 )
105 /*++
106
107 Routine Description:
108
109 This code gets the pointer to the variable data.
110
111 Arguments:
112
113 Variable Pointer to the Variable Header.
114
115 Returns:
116
117 UINT8* Pointer to Variable Data
118
119 --*/
120 {
121 if (Variable->StartId != VARIABLE_DATA) {
122 return NULL;
123 }
124 //
125 // Be careful about pad size for alignment
126 //
127 return (UINT8 *) ((UINTN) GET_VARIABLE_NAME_PTR (Variable) + Variable->NameSize + GET_PAD_SIZE (Variable->NameSize));
128 }
129
130 STATIC
131 VARIABLE_HEADER *
132 EFIAPI
133 GetNextVariablePtr (
134 IN VARIABLE_HEADER *Variable
135 )
136 /*++
137
138 Routine Description:
139
140 This code gets the pointer to the next variable header.
141
142 Arguments:
143
144 Variable Pointer to the Variable Header.
145
146 Returns:
147
148 VARIABLE_HEADER* Pointer to next variable header.
149
150 --*/
151 {
152 VARIABLE_HEADER *VarHeader;
153
154 if (Variable->StartId != VARIABLE_DATA) {
155 return NULL;
156 }
157 //
158 // Be careful about pad size for alignment
159 //
160 VarHeader = (VARIABLE_HEADER *) (GetVariableDataPtr (Variable) + Variable->DataSize + GET_PAD_SIZE (Variable->DataSize));
161
162 if (VarHeader->StartId != VARIABLE_DATA ||
163 (sizeof (VARIABLE_HEADER) + VarHeader->DataSize + VarHeader->NameSize) > MAX_VARIABLE_SIZE
164 ) {
165 return NULL;
166 }
167
168 return VarHeader;
169 }
170
171 STATIC
172 VARIABLE_HEADER *
173 EFIAPI
174 GetEndPointer (
175 IN VARIABLE_STORE_HEADER *VolHeader
176 )
177 /*++
178
179 Routine Description:
180
181 This code gets the pointer to the last variable memory pointer byte
182
183 Arguments:
184
185 Variable Pointer to the Variable Header.
186
187 Returns:
188
189 VARIABLE_HEADER* Pointer to last unavailable Variable Header
190
191 --*/
192 {
193 //
194 // The end of variable store
195 //
196 return (VARIABLE_HEADER *) ((UINTN) VolHeader + VolHeader->Size);
197 }
198
199 STATIC
200 EFI_STATUS
201 EFIAPI
202 FindVariable (
203 IN CHAR16 *VariableName,
204 IN EFI_GUID *VendorGuid,
205 OUT VARIABLE_POINTER_TRACK *PtrTrack,
206 IN VARIABLE_GLOBAL *Global
207 )
208 /*++
209
210 Routine Description:
211
212 This code finds variable in storage blocks (Volatile or Non-Volatile)
213
214 Arguments:
215
216 VariableName Name of the variable to be found
217 VendorGuid Vendor GUID to be found.
218 PtrTrack Variable Track Pointer structure that contains
219 Variable Information.
220 Contains the pointer of Variable header.
221 Global VARIABLE_GLOBAL pointer
222
223 Returns:
224
225 EFI STATUS
226
227 --*/
228 {
229 VARIABLE_HEADER *Variable[2];
230 VARIABLE_STORE_HEADER *VariableStoreHeader[2];
231 UINTN Index;
232
233 //
234 // We aquire the lock at the entry of FindVariable as GetVariable, GetNextVariableName
235 // SetVariable all call FindVariable at entry point. Please move "Aquire Lock" to
236 // the correct places if this assumption does not hold TRUE anymore.
237 //
238 AcquireLockOnlyAtBootTime(&Global->VariableServicesLock);
239
240 //
241 // 0: Non-Volatile, 1: Volatile
242 //
243 VariableStoreHeader[0] = (VARIABLE_STORE_HEADER *) ((UINTN) Global->NonVolatileVariableBase);
244 VariableStoreHeader[1] = (VARIABLE_STORE_HEADER *) ((UINTN) Global->VolatileVariableBase);
245
246 //
247 // Start Pointers for the variable.
248 // Actual Data Pointer where data can be written.
249 //
250 Variable[0] = (VARIABLE_HEADER *) (VariableStoreHeader[0] + 1);
251 Variable[1] = (VARIABLE_HEADER *) (VariableStoreHeader[1] + 1);
252
253 if (VariableName[0] != 0 && VendorGuid == NULL) {
254 return EFI_INVALID_PARAMETER;
255 }
256 //
257 // Find the variable by walk through non-volatile and volatile variable store
258 //
259 for (Index = 0; Index < 2; Index++) {
260 PtrTrack->StartPtr = (VARIABLE_HEADER *) (VariableStoreHeader[Index] + 1);
261 PtrTrack->EndPtr = GetEndPointer (VariableStoreHeader[Index]);
262
263 while ((Variable[Index] != NULL) && (Variable[Index] <= GetEndPointer (VariableStoreHeader[Index]))) {
264 if (Variable[Index]->StartId == VARIABLE_DATA && Variable[Index]->State == VAR_ADDED) {
265 if (!(EfiAtRuntime () && !(Variable[Index]->Attributes & EFI_VARIABLE_RUNTIME_ACCESS))) {
266 if (VariableName[0] == 0) {
267 PtrTrack->CurrPtr = Variable[Index];
268 PtrTrack->Volatile = (BOOLEAN) Index;
269 return EFI_SUCCESS;
270 } else {
271 if (CompareGuid (VendorGuid, &Variable[Index]->VendorGuid)) {
272 if (!CompareMem (VariableName, GET_VARIABLE_NAME_PTR (Variable[Index]), ArrayLength (VariableName))) {
273 PtrTrack->CurrPtr = Variable[Index];
274 PtrTrack->Volatile = (BOOLEAN) Index;
275 return EFI_SUCCESS;
276 }
277 }
278 }
279 }
280 }
281
282 Variable[Index] = GetNextVariablePtr (Variable[Index]);
283 }
284 }
285 PtrTrack->CurrPtr = NULL;
286 return EFI_NOT_FOUND;
287 }
288
289 EFI_STATUS
290 EFIAPI
291 GetVariable (
292 IN CHAR16 *VariableName,
293 IN EFI_GUID * VendorGuid,
294 OUT UINT32 *Attributes OPTIONAL,
295 IN OUT UINTN *DataSize,
296 OUT VOID *Data,
297 IN VARIABLE_GLOBAL * Global,
298 IN UINT32 Instance
299 )
300 /*++
301
302 Routine Description:
303
304 This code finds variable in storage blocks (Volatile or Non-Volatile)
305
306 Arguments:
307
308 VariableName Name of Variable to be found
309 VendorGuid Variable vendor GUID
310 Attributes OPTIONAL Attribute value of the variable found
311 DataSize Size of Data found. If size is less than the
312 data, this value contains the required size.
313 Data Data pointer
314 Global Pointer to VARIABLE_GLOBAL structure
315 Instance Instance of the Firmware Volume.
316
317 Returns:
318
319 EFI STATUS
320
321 --*/
322 {
323 VARIABLE_POINTER_TRACK Variable;
324 UINTN VarDataSize;
325 EFI_STATUS Status;
326
327 if (VariableName == NULL || VendorGuid == NULL || DataSize == NULL) {
328 return EFI_INVALID_PARAMETER;
329 }
330 //
331 // Find existing variable
332 //
333 Status = FindVariable (VariableName, VendorGuid, &Variable, Global);
334
335 if (Variable.CurrPtr == NULL || EFI_ERROR (Status)) {
336 goto Done;
337 }
338 //
339 // Get data size
340 //
341 VarDataSize = Variable.CurrPtr->DataSize;
342 if (*DataSize >= VarDataSize) {
343 if (Data == NULL) {
344 Status = EFI_INVALID_PARAMETER;
345 goto Done;
346 }
347
348 CopyMem (Data, GetVariableDataPtr (Variable.CurrPtr), VarDataSize);
349 if (Attributes != NULL) {
350 *Attributes = Variable.CurrPtr->Attributes;
351 }
352
353 *DataSize = VarDataSize;
354 Status = EFI_SUCCESS;
355 goto Done;
356 } else {
357 *DataSize = VarDataSize;
358 Status = EFI_BUFFER_TOO_SMALL;
359 goto Done;
360 }
361
362 Done:
363 ReleaseLockOnlyAtBootTime (&Global->VariableServicesLock);
364 return Status;
365 }
366
367 EFI_STATUS
368 EFIAPI
369 GetNextVariableName (
370 IN OUT UINTN *VariableNameSize,
371 IN OUT CHAR16 *VariableName,
372 IN OUT EFI_GUID *VendorGuid,
373 IN VARIABLE_GLOBAL *Global,
374 IN UINT32 Instance
375 )
376 /*++
377
378 Routine Description:
379
380 This code Finds the Next available variable
381
382 Arguments:
383
384 VariableNameSize Size of the variable
385 VariableName Pointer to variable name
386 VendorGuid Variable Vendor Guid
387 Global VARIABLE_GLOBAL structure pointer.
388 Instance FV instance
389
390 Returns:
391
392 EFI STATUS
393
394 --*/
395 {
396 VARIABLE_POINTER_TRACK Variable;
397 UINTN VarNameSize;
398 EFI_STATUS Status;
399
400 if (VariableNameSize == NULL || VariableName == NULL || VendorGuid == NULL) {
401 return EFI_INVALID_PARAMETER;
402 }
403
404 Status = FindVariable (VariableName, VendorGuid, &Variable, Global);
405
406 if (Variable.CurrPtr == NULL || EFI_ERROR (Status)) {
407 goto Done;
408 }
409
410 while (TRUE) {
411 if (VariableName[0] != 0) {
412 //
413 // If variable name is not NULL, get next variable
414 //
415 Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);
416 }
417 //
418 // If both volatile and non-volatile variable store are parsed,
419 // return not found
420 //
421 if (Variable.CurrPtr >= Variable.EndPtr || Variable.CurrPtr == NULL) {
422 Variable.Volatile = (BOOLEAN) (Variable.Volatile ^ ((BOOLEAN) 0x1));
423 if (Variable.Volatile) {
424 Variable.StartPtr = (VARIABLE_HEADER *) ((UINTN) (Global->VolatileVariableBase + sizeof (VARIABLE_STORE_HEADER)));
425 Variable.EndPtr = (VARIABLE_HEADER *) GetEndPointer ((VARIABLE_STORE_HEADER *) ((UINTN) Global->VolatileVariableBase));
426 } else {
427 Status = EFI_NOT_FOUND;
428 goto Done;
429 }
430
431 Variable.CurrPtr = Variable.StartPtr;
432 if (Variable.CurrPtr->StartId != VARIABLE_DATA) {
433 continue;
434 }
435 }
436 //
437 // Variable is found
438 //
439 if (Variable.CurrPtr->StartId == VARIABLE_DATA && Variable.CurrPtr->State == VAR_ADDED) {
440 if (!(EfiAtRuntime () && !(Variable.CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS))) {
441 VarNameSize = Variable.CurrPtr->NameSize;
442 if (VarNameSize <= *VariableNameSize) {
443 CopyMem (
444 VariableName,
445 GET_VARIABLE_NAME_PTR (Variable.CurrPtr),
446 VarNameSize
447 );
448 CopyMem (
449 VendorGuid,
450 &Variable.CurrPtr->VendorGuid,
451 sizeof (EFI_GUID)
452 );
453 Status = EFI_SUCCESS;
454 } else {
455 Status = EFI_BUFFER_TOO_SMALL;
456 }
457
458 *VariableNameSize = VarNameSize;
459 goto Done;
460 }
461 }
462 }
463
464 Done:
465 ReleaseLockOnlyAtBootTime (&Global->VariableServicesLock);
466 return Status;
467
468 }
469
470 EFI_STATUS
471 EFIAPI
472 SetVariable (
473 IN CHAR16 *VariableName,
474 IN EFI_GUID *VendorGuid,
475 IN UINT32 Attributes,
476 IN UINTN DataSize,
477 IN VOID *Data,
478 IN VARIABLE_GLOBAL *Global,
479 IN UINTN *VolatileOffset,
480 IN UINTN *NonVolatileOffset,
481 IN UINT32 Instance
482 )
483 /*++
484
485 Routine Description:
486
487 This code sets variable in storage blocks (Volatile or Non-Volatile)
488
489 Arguments:
490
491 VariableName Name of Variable to be found
492 VendorGuid Variable vendor GUID
493 Attributes Attribute value of the variable found
494 DataSize Size of Data found. If size is less than the
495 data, this value contains the required size.
496 Data Data pointer
497 Global Pointer to VARIABLE_GLOBAL structure
498 VolatileOffset The offset of last volatile variable
499 NonVolatileOffset The offset of last non-volatile variable
500 Instance Instance of the Firmware Volume.
501
502 Returns:
503
504 EFI STATUS
505
506 --*/
507 {
508 VARIABLE_POINTER_TRACK Variable;
509 EFI_STATUS Status;
510 VARIABLE_HEADER *NextVariable;
511 UINTN VarNameSize;
512 UINTN VarNameOffset;
513 UINTN VarDataOffset;
514 UINTN VarSize;
515
516 if (VariableName == NULL || VariableName[0] == 0 || VendorGuid == NULL) {
517 return EFI_INVALID_PARAMETER;
518 }
519
520 Status = FindVariable (VariableName, VendorGuid, &Variable, Global);
521
522 if (Status == EFI_INVALID_PARAMETER) {
523 goto Done;
524 } else if (!EFI_ERROR (Status) && Variable.Volatile && EfiAtRuntime()) {
525 //
526 // If EfiAtRuntime and the variable is Volatile and Runtime Access,
527 // the volatile is ReadOnly, and SetVariable should be aborted and
528 // return EFI_WRITE_PROTECTED.
529 //
530 Status = EFI_WRITE_PROTECTED;
531 goto Done;
532 } else if (sizeof (VARIABLE_HEADER) + (ArrayLength (VariableName) + DataSize) > MAX_VARIABLE_SIZE) {
533 //
534 // The size of the VariableName, including the Unicode Null in bytes plus
535 // the DataSize is limited to maximum size of MAX_VARIABLE_SIZE (1024) bytes.
536 //
537 Status = EFI_INVALID_PARAMETER;
538 goto Done;
539 } else if ((Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == EFI_VARIABLE_RUNTIME_ACCESS
540 ) {
541 //
542 // Make sure if runtime bit is set, boot service bit is set also
543 //
544 Status = EFI_INVALID_PARAMETER;
545 goto Done;
546 } else if (EfiAtRuntime () && Attributes && !(Attributes & EFI_VARIABLE_RUNTIME_ACCESS)) {
547 //
548 // Runtime but Attribute is not Runtime
549 //
550 Status = EFI_INVALID_PARAMETER;
551 goto Done;
552 } else if (EfiAtRuntime () && Attributes && !(Attributes & EFI_VARIABLE_NON_VOLATILE)) {
553 //
554 // Cannot set volatile variable in Runtime
555 //
556 Status = EFI_INVALID_PARAMETER;
557 goto Done;
558 } else if (DataSize == 0 || (Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == 0) {
559 //
560 // Setting a data variable with no access, or zero DataSize attributes
561 // specified causes it to be deleted.
562 //
563 if (!EFI_ERROR (Status)) {
564 Variable.CurrPtr->State &= VAR_DELETED;
565 Status = EFI_SUCCESS;
566 goto Done;
567 }
568
569 Status = EFI_NOT_FOUND;
570 goto Done;
571 } else {
572 if (!EFI_ERROR (Status)) {
573 //
574 // If the variable is marked valid and the same data has been passed in
575 // then return to the caller immediately.
576 //
577 if (Variable.CurrPtr->DataSize == DataSize &&
578 !CompareMem (Data, GetVariableDataPtr (Variable.CurrPtr), DataSize)
579 ) {
580 Status = EFI_SUCCESS;
581 goto Done;
582 } else if (Variable.CurrPtr->State == VAR_ADDED) {
583 //
584 // Mark the old variable as in delete transition
585 //
586 Variable.CurrPtr->State &= VAR_IN_DELETED_TRANSITION;
587 }
588 }
589 //
590 // Create a new variable and copy the data.
591 //
592 VarNameOffset = sizeof (VARIABLE_HEADER);
593 VarNameSize = ArrayLength (VariableName);
594 VarDataOffset = VarNameOffset + VarNameSize + GET_PAD_SIZE (VarNameSize);
595 VarSize = VarDataOffset + DataSize + GET_PAD_SIZE (DataSize);
596
597 if (Attributes & EFI_VARIABLE_NON_VOLATILE) {
598 if ((UINT32) (VarSize +*NonVolatileOffset) >
599 ((VARIABLE_STORE_HEADER *) ((UINTN) (Global->NonVolatileVariableBase)))->Size
600 ) {
601 Status = EFI_OUT_OF_RESOURCES;
602 goto Done;
603 }
604
605 NextVariable = (VARIABLE_HEADER *) (UINT8 *) (*NonVolatileOffset + (UINTN) Global->NonVolatileVariableBase);
606 *NonVolatileOffset = *NonVolatileOffset + VarSize;
607 } else {
608 if (EfiAtRuntime ()) {
609 Status = EFI_INVALID_PARAMETER;
610 goto Done;
611 }
612
613 if ((UINT32) (VarSize +*VolatileOffset) >
614 ((VARIABLE_STORE_HEADER *) ((UINTN) (Global->VolatileVariableBase)))->Size
615 ) {
616 Status = EFI_OUT_OF_RESOURCES;
617 goto Done;
618 }
619
620 NextVariable = (VARIABLE_HEADER *) (UINT8 *) (*VolatileOffset + (UINTN) Global->VolatileVariableBase);
621 *VolatileOffset = *VolatileOffset + VarSize;
622 }
623
624 NextVariable->StartId = VARIABLE_DATA;
625 NextVariable->Attributes = Attributes;
626 NextVariable->State = VAR_ADDED;
627 NextVariable->Reserved = 0;
628
629 //
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
633 //
634 NextVariable->NameSize = (UINT32)VarNameSize;
635 NextVariable->DataSize = (UINT32)DataSize;
636
637 CopyMem (&NextVariable->VendorGuid, VendorGuid, sizeof (EFI_GUID));
638 CopyMem (
639 (UINT8 *) ((UINTN) NextVariable + VarNameOffset),
640 VariableName,
641 VarNameSize
642 );
643 CopyMem (
644 (UINT8 *) ((UINTN) NextVariable + VarDataOffset),
645 Data,
646 DataSize
647 );
648
649 //
650 // Mark the old variable as deleted
651 //
652 if (!EFI_ERROR (Status)) {
653 Variable.CurrPtr->State &= VAR_DELETED;
654 }
655 }
656
657 Status = EFI_SUCCESS;
658 Done:
659 ReleaseLockOnlyAtBootTime (&Global->VariableServicesLock);
660 return Status;
661 }
662
663 #if (EFI_SPECIFICATION_VERSION >= 0x00020000)
664 EFI_STATUS
665 EFIAPI
666 QueryVariableInfo (
667 IN UINT32 Attributes,
668 OUT UINT64 *MaximumVariableStorageSize,
669 OUT UINT64 *RemainingVariableStorageSize,
670 OUT UINT64 *MaximumVariableSize,
671 IN VARIABLE_GLOBAL *Global,
672 IN UINT32 Instance
673 )
674 /*++
675
676 Routine Description:
677
678 This code returns information about the EFI variables.
679
680 Arguments:
681
682 Attributes Attributes bitmask to specify the type of variables
683 on which to return information.
684 MaximumVariableStorageSize Pointer to the maximum size of the storage space available
685 for the EFI variables associated with the attributes specified.
686 RemainingVariableStorageSize Pointer to the remaining size of the storage space available
687 for the EFI variables associated with the attributes specified.
688 MaximumVariableSize Pointer to the maximum size of the individual EFI variables
689 associated with the attributes specified.
690 Global Pointer to VARIABLE_GLOBAL structure.
691 Instance Instance of the Firmware Volume.
692
693 Returns:
694
695 EFI STATUS
696 EFI_INVALID_PARAMETER - An invalid combination of attribute bits was supplied.
697 EFI_SUCCESS - Query successfully.
698 EFI_UNSUPPORTED - The attribute is not supported on this platform.
699
700 --*/
701 {
702 VARIABLE_HEADER *Variable;
703 VARIABLE_HEADER *NextVariable;
704 UINT64 VariableSize;
705 VARIABLE_STORE_HEADER *VariableStoreHeader;
706
707 if(MaximumVariableStorageSize == NULL || RemainingVariableStorageSize == NULL || MaximumVariableSize == NULL) {
708 return EFI_INVALID_PARAMETER;
709 }
710
711 if((Attributes & (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS)) == 0) {
712 //
713 // Make sure the Attributes combination is supported by the platform.
714 //
715 return EFI_UNSUPPORTED;
716 } else if ((Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == EFI_VARIABLE_RUNTIME_ACCESS) {
717 //
718 // Make sure if runtime bit is set, boot service bit is set also.
719 //
720 return EFI_INVALID_PARAMETER;
721 } else if (EfiAtRuntime () && !(Attributes & EFI_VARIABLE_RUNTIME_ACCESS)) {
722 //
723 // Make sure RT Attribute is set if we are in Runtime phase.
724 //
725 return EFI_INVALID_PARAMETER;
726 } else if (EfiAtRuntime () && Attributes && !(Attributes & EFI_VARIABLE_NON_VOLATILE)) {
727 //
728 // Cannot Query volatile variable in Runtime
729 //
730 return EFI_INVALID_PARAMETER;
731 }
732
733 AcquireLockOnlyAtBootTime(&Global->VariableServicesLock);
734
735 if((Attributes & EFI_VARIABLE_NON_VOLATILE) == 0) {
736 //
737 // Query is Volatile related.
738 //
739 VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINTN) Global->VolatileVariableBase);
740 } else {
741 //
742 // Query is Non-Volatile related.
743 //
744 VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINTN) Global->NonVolatileVariableBase);
745 }
746
747 //
748 // Now let's fill *MaximumVariableStorageSize *RemainingVariableStorageSize
749 // with the storage size (excluding the storage header size)
750 //
751 *MaximumVariableStorageSize = VariableStoreHeader->Size - sizeof (VARIABLE_STORE_HEADER);
752 *RemainingVariableStorageSize = VariableStoreHeader->Size - sizeof (VARIABLE_STORE_HEADER);
753
754 //
755 // Let *MaximumVariableSize be MAX_VARIABLE_SIZE
756 //
757 *MaximumVariableSize = MAX_VARIABLE_SIZE;
758
759 //
760 // Point to the starting address of the variables.
761 //
762 Variable = (VARIABLE_HEADER *) (VariableStoreHeader + 1);
763
764 //
765 // Now walk through the related variable store.
766 //
767 while (Variable < GetEndPointer (VariableStoreHeader)) {
768 if (Variable->StartId != VARIABLE_DATA) {
769 break;
770 }
771
772 NextVariable = (VARIABLE_HEADER *) (GetVariableDataPtr (Variable) + Variable->DataSize + GET_PAD_SIZE (Variable->DataSize));
773 VariableSize = (UINT64) (UINTN) NextVariable - (UINT64) (UINTN) Variable;
774
775 if (Variable->State == VAR_ADDED) {
776 *RemainingVariableStorageSize -= VariableSize;
777 }
778
779 //
780 // Go to the next one.
781 //
782 Variable = NextVariable;
783 }
784
785 ReleaseLockOnlyAtBootTime (&Global->VariableServicesLock);
786 return EFI_SUCCESS;
787 }
788 #endif
789
790 STATIC
791 EFI_STATUS
792 EFIAPI
793 InitializeVariableStore (
794 OUT EFI_PHYSICAL_ADDRESS *VariableBase,
795 OUT UINTN *LastVariableOffset
796 )
797 /*++
798
799 Routine Description:
800 This function initializes variable store
801
802 Arguments:
803
804 Returns:
805
806 --*/
807 {
808 VARIABLE_STORE_HEADER *VariableStore;
809
810 //
811 // Allocate memory for volatile variable store
812 //
813 VariableStore = (VARIABLE_STORE_HEADER *) AllocateRuntimePool (
814 VARIABLE_STORE_SIZE
815 );
816 if (NULL == VariableStore) {
817 return EFI_OUT_OF_RESOURCES;
818 }
819
820 SetMem (VariableStore, VARIABLE_STORE_SIZE, 0xff);
821
822 //
823 // Variable Specific Data
824 //
825 *VariableBase = (EFI_PHYSICAL_ADDRESS) (UINTN) VariableStore;
826 *LastVariableOffset = sizeof (VARIABLE_STORE_HEADER);
827
828 VariableStore->Signature = VARIABLE_STORE_SIGNATURE;
829 VariableStore->Size = VARIABLE_STORE_SIZE;
830 VariableStore->Format = VARIABLE_STORE_FORMATTED;
831 VariableStore->State = VARIABLE_STORE_HEALTHY;
832 VariableStore->Reserved = 0;
833 VariableStore->Reserved1 = 0;
834
835 return EFI_SUCCESS;
836 }
837
838 EFI_STATUS
839 EFIAPI
840 VariableCommonInitialize (
841 IN EFI_HANDLE ImageHandle,
842 IN EFI_SYSTEM_TABLE *SystemTable
843 )
844 /*++
845
846 Routine Description:
847 This function does common initialization for variable services
848
849 Arguments:
850
851 Returns:
852
853 --*/
854 {
855 EFI_STATUS Status;
856
857 //
858 // Allocate memory for mVariableModuleGlobal
859 //
860 mVariableModuleGlobal = (ESAL_VARIABLE_GLOBAL *) AllocateRuntimePool (
861 sizeof (ESAL_VARIABLE_GLOBAL)
862 );
863 if (NULL == mVariableModuleGlobal) {
864 return EFI_OUT_OF_RESOURCES;
865 }
866
867 EfiInitializeLock(&mVariableModuleGlobal->VariableGlobal[Physical].VariableServicesLock, EFI_TPL_CALLBACK);
868
869 //
870 // Intialize volatile variable store
871 //
872 Status = InitializeVariableStore (
873 &mVariableModuleGlobal->VariableGlobal[Physical].VolatileVariableBase,
874 &mVariableModuleGlobal->VolatileLastVariableOffset
875 );
876
877 if (EFI_ERROR (Status)) {
878 return Status;
879 }
880 //
881 // Intialize non volatile variable store
882 //
883 Status = InitializeVariableStore (
884 &mVariableModuleGlobal->VariableGlobal[Physical].NonVolatileVariableBase,
885 &mVariableModuleGlobal->NonVolatileLastVariableOffset
886 );
887
888 return Status;
889 }