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