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