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