]> git.proxmox.com Git - mirror_edk2.git/blob - EdkModulePkg/Universal/Variable/RuntimeDxe/Variable.c
This check-in fixed the following bugs:
[mirror_edk2.git] / EdkModulePkg / Universal / Variable / RuntimeDxe / Variable.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 Variable.c
15
16 Abstract:
17
18 Revision History
19
20 --*/
21
22 #include "Variable.h"
23 #include "reclaim.h"
24
25 //
26 // Don't use module globals after the SetVirtualAddress map is signaled
27 //
28 ESAL_VARIABLE_GLOBAL *mVariableModuleGlobal;
29
30 UINT32
31 EFIAPI
32 ArrayLength (
33 IN CHAR16 *String
34 )
35 /*++
36
37 Routine Description:
38
39 Determine the length of null terminated char16 array.
40
41 Arguments:
42
43 String Null-terminated CHAR16 array pointer.
44
45 Returns:
46
47 UINT32 Number of bytes in the string, including the double NULL at the end;
48
49 --*/
50 {
51 UINT32 Count;
52
53 if (NULL == String) {
54 return 0;
55 }
56
57 Count = 0;
58
59 while (0 != String[Count]) {
60 Count++;
61 }
62
63 return (Count * 2) + 2;
64 }
65
66 BOOLEAN
67 EFIAPI
68 IsValidVariableHeader (
69 IN VARIABLE_HEADER *Variable
70 )
71 /*++
72
73 Routine Description:
74
75 This code checks if variable header is valid or not.
76
77 Arguments:
78 Variable Pointer to the Variable Header.
79
80 Returns:
81 TRUE Variable header is valid.
82 FALSE Variable header is not valid.
83
84 --*/
85 {
86 if (Variable == NULL ||
87 Variable->StartId != VARIABLE_DATA ||
88 (sizeof (VARIABLE_HEADER) + Variable->NameSize + Variable->DataSize) > MAX_VARIABLE_SIZE
89 ) {
90 return FALSE;
91 }
92
93 return TRUE;
94 }
95
96 EFI_STATUS
97 EFIAPI
98 UpdateVariableStore (
99 IN VARIABLE_GLOBAL *Global,
100 IN BOOLEAN Volatile,
101 IN BOOLEAN SetByIndex,
102 IN UINTN Instance,
103 IN UINTN DataPtrIndex,
104 IN UINT32 DataSize,
105 IN UINT8 *Buffer
106 )
107 /*++
108
109 Routine Description:
110
111 This function writes data to the FWH at the correct LBA even if the LBAs
112 are fragmented.
113
114 Arguments:
115
116 Global Pointer to VARAIBLE_GLOBAL structure
117 Volatile If the Variable is Volatile or Non-Volatile
118 SetByIndex TRUE: Target pointer is given as index
119 FALSE: Target pointer is absolute
120 Instance Instance of FV Block services
121 DataPtrIndex Pointer to the Data from the end of VARIABLE_STORE_HEADER
122 structure
123 DataSize Size of data to be written.
124 Buffer Pointer to the buffer from which data is written
125
126 Returns:
127
128 EFI STATUS
129
130 --*/
131 {
132 EFI_FV_BLOCK_MAP_ENTRY *PtrBlockMapEntry;
133 UINTN BlockIndex2;
134 UINTN LinearOffset;
135 UINTN CurrWriteSize;
136 UINTN CurrWritePtr;
137 UINT8 *CurrBuffer;
138 EFI_LBA LbaNumber;
139 UINTN Size;
140 EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
141 VARIABLE_STORE_HEADER *VolatileBase;
142 EFI_PHYSICAL_ADDRESS FvVolHdr;
143 EFI_PHYSICAL_ADDRESS DataPtr;
144 EFI_STATUS Status;
145
146 FwVolHeader = NULL;
147 DataPtr = DataPtrIndex;
148
149 //
150 // Check if the Data is Volatile
151 //
152 if (!Volatile) {
153 EfiFvbGetPhysicalAddress (Instance, &FvVolHdr);
154 FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) FvVolHdr);
155 //
156 // Data Pointer should point to the actual Address where data is to be
157 // written
158 //
159 if (SetByIndex) {
160 DataPtr += Global->NonVolatileVariableBase;
161 }
162
163 if ((DataPtr + DataSize) >= ((EFI_PHYSICAL_ADDRESS) (UINTN) ((UINT8 *) FwVolHeader + FwVolHeader->FvLength))) {
164 return EFI_INVALID_PARAMETER;
165 }
166 } else {
167 //
168 // Data Pointer should point to the actual Address where data is to be
169 // written
170 //
171 VolatileBase = (VARIABLE_STORE_HEADER *) ((UINTN) Global->VolatileVariableBase);
172 if (SetByIndex) {
173 DataPtr += Global->VolatileVariableBase;
174 }
175
176 if ((DataPtr + DataSize) >= ((UINTN) ((UINT8 *) VolatileBase + VolatileBase->Size))) {
177 return EFI_INVALID_PARAMETER;
178 }
179 }
180 //
181 // If Volatile Variable just do a simple mem copy.
182 //
183 if (Volatile) {
184 CopyMem ((UINT8 *) ((UINTN) DataPtr), Buffer, DataSize);
185 return EFI_SUCCESS;
186 }
187 //
188 // If we are here we are dealing with Non-Volatile Variables
189 //
190 LinearOffset = (UINTN) FwVolHeader;
191 CurrWritePtr = (UINTN) DataPtr;
192 CurrWriteSize = DataSize;
193 CurrBuffer = Buffer;
194 LbaNumber = 0;
195
196 if (CurrWritePtr < LinearOffset) {
197 return EFI_INVALID_PARAMETER;
198 }
199
200 for (PtrBlockMapEntry = FwVolHeader->FvBlockMap; PtrBlockMapEntry->NumBlocks != 0; PtrBlockMapEntry++) {
201 for (BlockIndex2 = 0; BlockIndex2 < PtrBlockMapEntry->NumBlocks; BlockIndex2++) {
202 //
203 // Check to see if the Variable Writes are spanning through multiple
204 // blocks.
205 //
206 if ((CurrWritePtr >= LinearOffset) && (CurrWritePtr < LinearOffset + PtrBlockMapEntry->BlockLength)) {
207 if ((CurrWritePtr + CurrWriteSize) <= (LinearOffset + PtrBlockMapEntry->BlockLength)) {
208 Status = EfiFvbWriteBlock (
209 Instance,
210 LbaNumber,
211 (UINTN) (CurrWritePtr - LinearOffset),
212 &CurrWriteSize,
213 CurrBuffer
214 );
215 if (EFI_ERROR (Status)) {
216 return Status;
217 }
218 } else {
219 Size = (UINT32) (LinearOffset + PtrBlockMapEntry->BlockLength - CurrWritePtr);
220 Status = EfiFvbWriteBlock (
221 Instance,
222 LbaNumber,
223 (UINTN) (CurrWritePtr - LinearOffset),
224 &Size,
225 CurrBuffer
226 );
227 if (EFI_ERROR (Status)) {
228 return Status;
229 }
230
231 CurrWritePtr = LinearOffset + PtrBlockMapEntry->BlockLength;
232 CurrBuffer = CurrBuffer + Size;
233 CurrWriteSize = CurrWriteSize - Size;
234 }
235 }
236
237 LinearOffset += PtrBlockMapEntry->BlockLength;
238 LbaNumber++;
239 }
240 }
241
242 return EFI_SUCCESS;
243 }
244
245 VARIABLE_STORE_STATUS
246 EFIAPI
247 GetVariableStoreStatus (
248 IN VARIABLE_STORE_HEADER *VarStoreHeader
249 )
250 /*++
251
252 Routine Description:
253
254 This code gets the current status of Variable Store.
255
256 Arguments:
257
258 VarStoreHeader Pointer to the Variable Store Header.
259
260 Returns:
261
262 EfiRaw Variable store status is raw
263 EfiValid Variable store status is valid
264 EfiInvalid Variable store status is invalid
265
266 --*/
267 {
268 if (VarStoreHeader->Signature == VARIABLE_STORE_SIGNATURE &&
269 VarStoreHeader->Format == VARIABLE_STORE_FORMATTED &&
270 VarStoreHeader->State == VARIABLE_STORE_HEALTHY
271 ) {
272
273 return EfiValid;
274 } else if (VarStoreHeader->Signature == 0xffffffff &&
275 VarStoreHeader->Size == 0xffffffff &&
276 VarStoreHeader->Format == 0xff &&
277 VarStoreHeader->State == 0xff
278 ) {
279
280 return EfiRaw;
281 } else {
282 return EfiInvalid;
283 }
284 }
285
286 UINT8 *
287 EFIAPI
288 GetVariableDataPtr (
289 IN VARIABLE_HEADER *Variable
290 )
291 /*++
292
293 Routine Description:
294
295 This code gets the pointer to the variable data.
296
297 Arguments:
298
299 Variable Pointer to the Variable Header.
300
301 Returns:
302
303 UINT8* Pointer to Variable Data
304
305 --*/
306 {
307 //
308 // Be careful about pad size for alignment
309 //
310 return (UINT8 *) ((UINTN) GET_VARIABLE_NAME_PTR (Variable) + Variable->NameSize + GET_PAD_SIZE (Variable->NameSize));
311 }
312
313 VARIABLE_HEADER *
314 EFIAPI
315 GetNextVariablePtr (
316 IN VARIABLE_HEADER *Variable
317 )
318 /*++
319
320 Routine Description:
321
322 This code gets the pointer to the next variable header.
323
324 Arguments:
325
326 Variable Pointer to the Variable Header.
327
328 Returns:
329
330 VARIABLE_HEADER* Pointer to next variable header.
331
332 --*/
333 {
334 if (!IsValidVariableHeader (Variable)) {
335 return NULL;
336 }
337 //
338 // Be careful about pad size for alignment
339 //
340 return (VARIABLE_HEADER *) ((UINTN) GetVariableDataPtr (Variable) + Variable->DataSize + GET_PAD_SIZE (Variable->DataSize));
341 }
342
343 VARIABLE_HEADER *
344 EFIAPI
345 GetEndPointer (
346 IN VARIABLE_STORE_HEADER *VarStoreHeader
347 )
348 /*++
349
350 Routine Description:
351
352 This code gets the pointer to the last variable memory pointer byte
353
354 Arguments:
355
356 VarStoreHeader Pointer to the Variable Store Header.
357
358 Returns:
359
360 VARIABLE_HEADER* Pointer to last unavailable Variable Header
361
362 --*/
363 {
364 //
365 // The end of variable store
366 //
367 return (VARIABLE_HEADER *) ((UINTN) VarStoreHeader + VarStoreHeader->Size);
368 }
369
370 EFI_STATUS
371 EFIAPI
372 Reclaim (
373 IN EFI_PHYSICAL_ADDRESS VariableBase,
374 OUT UINTN *LastVariableOffset,
375 IN BOOLEAN IsVolatile
376 )
377 /*++
378
379 Routine Description:
380
381 Variable store garbage collection and reclaim operation
382
383 Arguments:
384
385 VariableBase Base address of variable store
386 LastVariableOffset Offset of last variable
387 IsVolatile The variable store is volatile or not,
388 if it is non-volatile, need FTW
389
390 Returns:
391
392 EFI STATUS
393
394 --*/
395 {
396 VARIABLE_HEADER *Variable;
397 VARIABLE_HEADER *NextVariable;
398 VARIABLE_STORE_HEADER *VariableStoreHeader;
399 UINT8 *ValidBuffer;
400 UINTN ValidBufferSize;
401 UINTN VariableSize;
402 UINT8 *CurrPtr;
403 EFI_STATUS Status;
404
405 VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINTN) VariableBase);
406
407 //
408 // Start Pointers for the variable.
409 //
410 Variable = (VARIABLE_HEADER *) (VariableStoreHeader + 1);
411
412 ValidBufferSize = sizeof (VARIABLE_STORE_HEADER);
413
414 while (IsValidVariableHeader (Variable)) {
415 NextVariable = GetNextVariablePtr (Variable);
416 if (Variable->State == VAR_ADDED) {
417 VariableSize = (UINTN) NextVariable - (UINTN) Variable;
418 ValidBufferSize += VariableSize;
419 }
420
421 Variable = NextVariable;
422 }
423
424 Status = gBS->AllocatePool (
425 EfiBootServicesData,
426 ValidBufferSize,
427 (VOID **) &ValidBuffer
428 );
429 if (EFI_ERROR (Status)) {
430 return Status;
431 }
432
433 SetMem (ValidBuffer, ValidBufferSize, 0xff);
434
435 CurrPtr = ValidBuffer;
436
437 //
438 // Copy variable store header
439 //
440 CopyMem (CurrPtr, VariableStoreHeader, sizeof (VARIABLE_STORE_HEADER));
441 CurrPtr += sizeof (VARIABLE_STORE_HEADER);
442
443 //
444 // Start Pointers for the variable.
445 //
446 Variable = (VARIABLE_HEADER *) (VariableStoreHeader + 1);
447
448 while (IsValidVariableHeader (Variable)) {
449 NextVariable = GetNextVariablePtr (Variable);
450 if (Variable->State == VAR_ADDED) {
451 VariableSize = (UINTN) NextVariable - (UINTN) Variable;
452 CopyMem (CurrPtr, (UINT8 *) Variable, VariableSize);
453 CurrPtr += VariableSize;
454 }
455
456 Variable = NextVariable;
457 }
458
459 if (IsVolatile) {
460 //
461 // If volatile variable store, just copy valid buffer
462 //
463 SetMem ((UINT8 *) (UINTN) VariableBase, VariableStoreHeader->Size, 0xff);
464 CopyMem ((UINT8 *) (UINTN) VariableBase, ValidBuffer, ValidBufferSize);
465 *LastVariableOffset = ValidBufferSize;
466 Status = EFI_SUCCESS;
467 } else {
468 //
469 // If non-volatile variable store, perform FTW here.
470 //
471 Status = FtwVariableSpace (
472 VariableBase,
473 ValidBuffer,
474 ValidBufferSize
475 );
476 if (!EFI_ERROR (Status)) {
477 *LastVariableOffset = ValidBufferSize;
478 }
479 }
480
481 gBS->FreePool (ValidBuffer);
482
483 if (EFI_ERROR (Status)) {
484 *LastVariableOffset = 0;
485 }
486
487 return Status;
488 }
489
490 EFI_STATUS
491 EFIAPI
492 FindVariable (
493 IN CHAR16 *VariableName,
494 IN EFI_GUID *VendorGuid,
495 OUT VARIABLE_POINTER_TRACK *PtrTrack,
496 IN VARIABLE_GLOBAL *Global
497 )
498 /*++
499
500 Routine Description:
501
502 This code finds variable in storage blocks (Volatile or Non-Volatile)
503
504 Arguments:
505
506 VariableName Name of the variable to be found
507 VendorGuid Vendor GUID to be found.
508 PtrTrack Variable Track Pointer structure that contains
509 Variable Information.
510 Contains the pointer of Variable header.
511 Global VARIABLE_GLOBAL pointer
512
513 Returns:
514
515 EFI STATUS
516
517 --*/
518 {
519 VARIABLE_HEADER *Variable[2];
520 VARIABLE_STORE_HEADER *VariableStoreHeader[2];
521 UINTN Index;
522
523 //
524 // 0: Non-Volatile, 1: Volatile
525 //
526 VariableStoreHeader[0] = (VARIABLE_STORE_HEADER *) ((UINTN) Global->NonVolatileVariableBase);
527 VariableStoreHeader[1] = (VARIABLE_STORE_HEADER *) ((UINTN) Global->VolatileVariableBase);
528
529 //
530 // Start Pointers for the variable.
531 // Actual Data Pointer where data can be written.
532 //
533 Variable[0] = (VARIABLE_HEADER *) (VariableStoreHeader[0] + 1);
534 Variable[1] = (VARIABLE_HEADER *) (VariableStoreHeader[1] + 1);
535
536 if (VariableName[0] != 0 && VendorGuid == NULL) {
537 return EFI_INVALID_PARAMETER;
538 }
539 //
540 // Find the variable by walk through non-volatile and volatile variable store
541 //
542 for (Index = 0; Index < 2; Index++) {
543 PtrTrack->StartPtr = (VARIABLE_HEADER *) (VariableStoreHeader[Index] + 1);
544 PtrTrack->EndPtr = GetEndPointer (VariableStoreHeader[Index]);
545
546 while (IsValidVariableHeader (Variable[Index]) && (Variable[Index] <= GetEndPointer (VariableStoreHeader[Index]))) {
547 if (Variable[Index]->State == VAR_ADDED) {
548 if (!(EfiAtRuntime () && !(Variable[Index]->Attributes & EFI_VARIABLE_RUNTIME_ACCESS))) {
549 if (VariableName[0] == 0) {
550 PtrTrack->CurrPtr = Variable[Index];
551 PtrTrack->Volatile = (BOOLEAN) Index;
552 return EFI_SUCCESS;
553 } else {
554 if (CompareGuid (VendorGuid, &Variable[Index]->VendorGuid)) {
555 if (!CompareMem (VariableName, GET_VARIABLE_NAME_PTR (Variable[Index]), ArrayLength (VariableName))) {
556 PtrTrack->CurrPtr = Variable[Index];
557 PtrTrack->Volatile = (BOOLEAN) Index;
558 return EFI_SUCCESS;
559 }
560 }
561 }
562 }
563 }
564
565 Variable[Index] = GetNextVariablePtr (Variable[Index]);
566 }
567 //
568 // While (...)
569 //
570 }
571 //
572 // for (...)
573 //
574 PtrTrack->CurrPtr = NULL;
575 return EFI_NOT_FOUND;
576 }
577
578 EFI_STATUS
579 EFIAPI
580 GetVariable (
581 IN CHAR16 *VariableName,
582 IN EFI_GUID * VendorGuid,
583 OUT UINT32 *Attributes OPTIONAL,
584 IN OUT UINTN *DataSize,
585 OUT VOID *Data,
586 IN VARIABLE_GLOBAL * Global,
587 IN UINT32 Instance
588 )
589 /*++
590
591 Routine Description:
592
593 This code finds variable in storage blocks (Volatile or Non-Volatile)
594
595 Arguments:
596
597 VariableName Name of Variable to be found
598 VendorGuid Variable vendor GUID
599 Attributes OPTIONAL Attribute value of the variable found
600 DataSize Size of Data found. If size is less than the
601 data, this value contains the required size.
602 Data Data pointer
603 Global Pointer to VARIABLE_GLOBAL structure
604 Instance Instance of the Firmware Volume.
605
606 Returns:
607
608 EFI STATUS
609
610 --*/
611 {
612 VARIABLE_POINTER_TRACK Variable;
613 UINTN VarDataSize;
614 EFI_STATUS Status;
615
616 if (VariableName == NULL || VendorGuid == NULL || DataSize == NULL) {
617 return EFI_INVALID_PARAMETER;
618 }
619 //
620 // Find existing variable
621 //
622 Status = FindVariable (VariableName, VendorGuid, &Variable, Global);
623
624 if (Variable.CurrPtr == NULL || EFI_ERROR (Status)) {
625 return Status;
626 }
627 //
628 // Get data size
629 //
630 VarDataSize = Variable.CurrPtr->DataSize;
631 if (*DataSize >= VarDataSize) {
632 if (Data == NULL) {
633 return EFI_INVALID_PARAMETER;
634 }
635
636 CopyMem (Data, GetVariableDataPtr (Variable.CurrPtr), VarDataSize);
637 if (Attributes != NULL) {
638 *Attributes = Variable.CurrPtr->Attributes;
639 }
640
641 *DataSize = VarDataSize;
642 return EFI_SUCCESS;
643 } else {
644 *DataSize = VarDataSize;
645 return EFI_BUFFER_TOO_SMALL;
646 }
647 }
648
649 EFI_STATUS
650 EFIAPI
651 GetNextVariableName (
652 IN OUT UINTN *VariableNameSize,
653 IN OUT CHAR16 *VariableName,
654 IN OUT EFI_GUID *VendorGuid,
655 IN VARIABLE_GLOBAL *Global,
656 IN UINT32 Instance
657 )
658 /*++
659
660 Routine Description:
661
662 This code Finds the Next available variable
663
664 Arguments:
665
666 VariableNameSize Size of the variable
667 VariableName Pointer to variable name
668 VendorGuid Variable Vendor Guid
669 Global VARIABLE_GLOBAL structure pointer.
670 Instance FV instance
671
672 Returns:
673
674 EFI STATUS
675
676 --*/
677 {
678 VARIABLE_POINTER_TRACK Variable;
679 UINTN VarNameSize;
680 EFI_STATUS Status;
681
682 if (VariableNameSize == NULL || VariableName == NULL || VendorGuid == NULL) {
683 return EFI_INVALID_PARAMETER;
684 }
685
686 Status = FindVariable (VariableName, VendorGuid, &Variable, Global);
687
688 if (Variable.CurrPtr == NULL || EFI_ERROR (Status)) {
689 return Status;
690 }
691
692 if (VariableName[0] != 0) {
693 //
694 // If variable name is not NULL, get next variable
695 //
696 Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);
697 }
698
699 while (TRUE) {
700 //
701 // If both volatile and non-volatile variable store are parsed,
702 // return not found
703 //
704 if (Variable.CurrPtr >= Variable.EndPtr || Variable.CurrPtr == NULL) {
705 Variable.Volatile = (BOOLEAN) (Variable.Volatile ^ ((BOOLEAN) 0x1));
706 if (Variable.Volatile) {
707 Variable.StartPtr = (VARIABLE_HEADER *) ((UINTN) (Global->VolatileVariableBase + sizeof (VARIABLE_STORE_HEADER)));
708 Variable.EndPtr = (VARIABLE_HEADER *) GetEndPointer ((VARIABLE_STORE_HEADER *) ((UINTN) Global->VolatileVariableBase));
709 } else {
710 return EFI_NOT_FOUND;
711 }
712
713 Variable.CurrPtr = Variable.StartPtr;
714 if (!IsValidVariableHeader (Variable.CurrPtr)) {
715 continue;
716 }
717 }
718 //
719 // Variable is found
720 //
721 if (IsValidVariableHeader (Variable.CurrPtr) && Variable.CurrPtr->State == VAR_ADDED) {
722 if (!(EfiAtRuntime () && !(Variable.CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS))) {
723 VarNameSize = Variable.CurrPtr->NameSize;
724 if (VarNameSize <= *VariableNameSize) {
725 CopyMem (
726 VariableName,
727 GET_VARIABLE_NAME_PTR (Variable.CurrPtr),
728 VarNameSize
729 );
730 CopyMem (
731 VendorGuid,
732 &Variable.CurrPtr->VendorGuid,
733 sizeof (EFI_GUID)
734 );
735 Status = EFI_SUCCESS;
736 } else {
737 Status = EFI_BUFFER_TOO_SMALL;
738 }
739
740 *VariableNameSize = VarNameSize;
741 return Status;
742 }
743 }
744
745 Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);
746 }
747
748 return EFI_NOT_FOUND;
749 }
750
751 EFI_STATUS
752 EFIAPI
753 SetVariable (
754 IN CHAR16 *VariableName,
755 IN EFI_GUID *VendorGuid,
756 IN UINT32 Attributes,
757 IN UINTN DataSize,
758 IN VOID *Data,
759 IN VARIABLE_GLOBAL *Global,
760 IN UINTN *VolatileOffset,
761 IN UINTN *NonVolatileOffset,
762 IN UINT32 Instance
763 )
764 /*++
765
766 Routine Description:
767
768 This code sets variable in storage blocks (Volatile or Non-Volatile)
769
770 Arguments:
771
772 VariableName Name of Variable to be found
773 VendorGuid Variable vendor GUID
774 Attributes Attribute value of the variable found
775 DataSize Size of Data found. If size is less than the
776 data, this value contains the required size.
777 Data Data pointer
778 Global Pointer to VARIABLE_GLOBAL structure
779 VolatileOffset The offset of last volatile variable
780 NonVolatileOffset The offset of last non-volatile variable
781 Instance Instance of the Firmware Volume.
782
783 Returns:
784
785 EFI STATUS
786 EFI_INVALID_PARAMETER - Invalid parameter
787 EFI_SUCCESS - Set successfully
788 EFI_OUT_OF_RESOURCES - Resource not enough to set variable
789 EFI_NOT_FOUND - Not found
790
791 --*/
792 {
793 VARIABLE_POINTER_TRACK Variable;
794 EFI_STATUS Status;
795 VARIABLE_HEADER *NextVariable;
796 UINTN VarNameSize;
797 UINTN VarNameOffset;
798 UINTN VarDataOffset;
799 UINTN VarSize;
800 UINT8 State;
801 BOOLEAN Reclaimed;
802
803 Reclaimed = FALSE;
804
805 if (VariableName == NULL || VariableName[0] == 0 || VendorGuid == NULL) {
806 return EFI_INVALID_PARAMETER;
807 }
808
809 Status = FindVariable (VariableName, VendorGuid, &Variable, Global);
810
811 if (Status == EFI_INVALID_PARAMETER) {
812 return Status;
813 }
814 //
815 // The size of the VariableName, including the Unicode Null in bytes plus
816 // the DataSize is limited to maximum size of MAX_VARIABLE_SIZE (1024) bytes.
817 //
818 else if ((DataSize > MAX_VARIABLE_SIZE) ||
819 (sizeof (VARIABLE_HEADER) + ArrayLength (VariableName) + DataSize > MAX_VARIABLE_SIZE)) {
820 return EFI_INVALID_PARAMETER;
821 }
822 //
823 // Make sure if runtime bit is set, boot service bit is set also
824 //
825 else if ((Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == EFI_VARIABLE_RUNTIME_ACCESS
826 ) {
827 return EFI_INVALID_PARAMETER;
828 }
829 //
830 // Runtime but Attribute is not Runtime
831 //
832 else if (EfiAtRuntime () && Attributes && !(Attributes & EFI_VARIABLE_RUNTIME_ACCESS)) {
833 return EFI_INVALID_PARAMETER;
834 }
835 //
836 // Cannot set volatile variable in Runtime
837 //
838 else if (EfiAtRuntime () && Attributes && !(Attributes & EFI_VARIABLE_NON_VOLATILE)) {
839 return EFI_INVALID_PARAMETER;
840 }
841 //
842 // Setting a data variable with no access, or zero DataSize attributes
843 // specified causes it to be deleted.
844 //
845 else if (DataSize == 0 || Attributes == 0) {
846 if (!EFI_ERROR (Status)) {
847 State = Variable.CurrPtr->State;
848 State &= VAR_DELETED;
849
850 Status = UpdateVariableStore (
851 Global,
852 Variable.Volatile,
853 FALSE,
854 Instance,
855 (UINTN) &Variable.CurrPtr->State,
856 sizeof (UINT8),
857 &State
858 );
859 if (EFI_ERROR (Status)) {
860 return Status;
861 }
862
863 return EFI_SUCCESS;
864 }
865
866 return EFI_NOT_FOUND;
867 } else {
868 if (!EFI_ERROR (Status)) {
869 //
870 // If the variable is marked valid and the same data has been passed in
871 // then return to the caller immediately.
872 //
873 if (Variable.CurrPtr->DataSize == DataSize &&
874 !CompareMem (Data, GetVariableDataPtr (Variable.CurrPtr), DataSize)
875 ) {
876 return EFI_SUCCESS;
877 } else if (Variable.CurrPtr->State == VAR_ADDED) {
878 //
879 // Mark the old variable as in delete transition
880 //
881 State = Variable.CurrPtr->State;
882 State &= VAR_IN_DELETED_TRANSITION;
883
884 Status = UpdateVariableStore (
885 Global,
886 Variable.Volatile,
887 FALSE,
888 Instance,
889 (UINTN) &Variable.CurrPtr->State,
890 sizeof (UINT8),
891 &State
892 );
893 if (EFI_ERROR (Status)) {
894 return Status;
895 }
896 }
897 }
898 //
899 // Create a new variable and copy the data.
900 //
901 // Tricky part: Use scratch data area at the end of volatile variable store
902 // as a temporary storage.
903 //
904 NextVariable = GetEndPointer ((VARIABLE_STORE_HEADER *) ((UINTN) Global->VolatileVariableBase));
905
906 SetMem (NextVariable, SCRATCH_SIZE, 0xff);
907
908 NextVariable->StartId = VARIABLE_DATA;
909 NextVariable->Attributes = Attributes;
910 //
911 // NextVariable->State = VAR_ADDED;
912 //
913 NextVariable->Reserved = 0;
914 VarNameOffset = sizeof (VARIABLE_HEADER);
915 VarNameSize = ArrayLength (VariableName);
916 CopyMem (
917 (UINT8 *) ((UINTN) NextVariable + VarNameOffset),
918 VariableName,
919 VarNameSize
920 );
921 VarDataOffset = VarNameOffset + VarNameSize + GET_PAD_SIZE (VarNameSize);
922 CopyMem (
923 (UINT8 *) ((UINTN) NextVariable + VarDataOffset),
924 Data,
925 DataSize
926 );
927 CopyMem (&NextVariable->VendorGuid, VendorGuid, sizeof (EFI_GUID));
928 //
929 // There will be pad bytes after Data, the NextVariable->NameSize and
930 // NextVariable->DataSize should not include pad size so that variable
931 // service can get actual size in GetVariable
932 //
933 NextVariable->NameSize = (UINT32)VarNameSize;
934 NextVariable->DataSize = (UINT32)DataSize;
935
936 //
937 // The actual size of the variable that stores in storage should
938 // include pad size.
939 //
940 VarSize = VarDataOffset + DataSize + GET_PAD_SIZE (DataSize);
941 if (Attributes & EFI_VARIABLE_NON_VOLATILE) {
942 if ((UINT32) (VarSize +*NonVolatileOffset) >
943 ((VARIABLE_STORE_HEADER *) ((UINTN) (Global->NonVolatileVariableBase)))->Size
944 ) {
945 if (EfiAtRuntime ()) {
946 return EFI_OUT_OF_RESOURCES;
947 }
948 //
949 // Perform garbage collection & reclaim operation
950 //
951 Status = Reclaim (Global->NonVolatileVariableBase, NonVolatileOffset, FALSE);
952 if (EFI_ERROR (Status)) {
953 return Status;
954 }
955 //
956 // If still no enough space, return out of resources
957 //
958 if ((UINT32) (VarSize +*NonVolatileOffset) >
959 ((VARIABLE_STORE_HEADER *) ((UINTN) (Global->NonVolatileVariableBase)))->Size
960 ) {
961 return EFI_OUT_OF_RESOURCES;
962 }
963
964 Reclaimed = TRUE;
965 }
966 //
967 // Three steps
968 // 1. Write variable header
969 // 2. Write variable data
970 // 3. Set variable state to valid
971 //
972 //
973 // Step 1:
974 //
975 Status = UpdateVariableStore (
976 Global,
977 FALSE,
978 TRUE,
979 Instance,
980 *NonVolatileOffset,
981 sizeof (VARIABLE_HEADER),
982 (UINT8 *) NextVariable
983 );
984
985 if (EFI_ERROR (Status)) {
986 return Status;
987 }
988 //
989 // Step 2:
990 //
991 Status = UpdateVariableStore (
992 Global,
993 FALSE,
994 TRUE,
995 Instance,
996 *NonVolatileOffset + sizeof (VARIABLE_HEADER),
997 (UINT32) VarSize - sizeof (VARIABLE_HEADER),
998 (UINT8 *) NextVariable + sizeof (VARIABLE_HEADER)
999 );
1000
1001 if (EFI_ERROR (Status)) {
1002 return Status;
1003 }
1004 //
1005 // Step 3:
1006 //
1007 NextVariable->State = VAR_ADDED;
1008 Status = UpdateVariableStore (
1009 Global,
1010 FALSE,
1011 TRUE,
1012 Instance,
1013 *NonVolatileOffset,
1014 sizeof (VARIABLE_HEADER),
1015 (UINT8 *) NextVariable
1016 );
1017
1018 if (EFI_ERROR (Status)) {
1019 return Status;
1020 }
1021
1022 *NonVolatileOffset = *NonVolatileOffset + VarSize;
1023
1024 } else {
1025 if (EfiAtRuntime ()) {
1026 return EFI_INVALID_PARAMETER;
1027 }
1028
1029 if ((UINT32) (VarSize +*VolatileOffset) >
1030 ((VARIABLE_STORE_HEADER *) ((UINTN) (Global->VolatileVariableBase)))->Size
1031 ) {
1032 //
1033 // Perform garbage collection & reclaim operation
1034 //
1035 Status = Reclaim (Global->VolatileVariableBase, VolatileOffset, TRUE);
1036 if (EFI_ERROR (Status)) {
1037 return Status;
1038 }
1039 //
1040 // If still no enough space, return out of resources
1041 //
1042 if ((UINT32) (VarSize +*VolatileOffset) >
1043 ((VARIABLE_STORE_HEADER *) ((UINTN) (Global->VolatileVariableBase)))->Size
1044 ) {
1045 return EFI_OUT_OF_RESOURCES;
1046 }
1047
1048 Reclaimed = TRUE;
1049 }
1050
1051 NextVariable->State = VAR_ADDED;
1052 Status = UpdateVariableStore (
1053 Global,
1054 TRUE,
1055 TRUE,
1056 Instance,
1057 *VolatileOffset,
1058 (UINT32) VarSize,
1059 (UINT8 *) NextVariable
1060 );
1061
1062 if (EFI_ERROR (Status)) {
1063 return Status;
1064 }
1065
1066 *VolatileOffset = *VolatileOffset + VarSize;
1067 }
1068 //
1069 // Mark the old variable as deleted
1070 //
1071 if (!Reclaimed && !EFI_ERROR (Status) && Variable.CurrPtr != NULL) {
1072 State = Variable.CurrPtr->State;
1073 State &= VAR_DELETED;
1074
1075 Status = UpdateVariableStore (
1076 Global,
1077 Variable.Volatile,
1078 FALSE,
1079 Instance,
1080 (UINTN) &Variable.CurrPtr->State,
1081 sizeof (UINT8),
1082 &State
1083 );
1084
1085 if (EFI_ERROR (Status)) {
1086 return Status;
1087 }
1088 }
1089 }
1090
1091 return EFI_SUCCESS;
1092 }
1093
1094 #if (EFI_SPECIFICATION_VERSION >= 0x00020000)
1095 EFI_STATUS
1096 EFIAPI
1097 QueryVariableInfo (
1098 IN UINT32 Attributes,
1099 OUT UINT64 *MaximumVariableStorageSize,
1100 OUT UINT64 *RemainingVariableStorageSize,
1101 OUT UINT64 *MaximumVariableSize,
1102 IN VARIABLE_GLOBAL *Global,
1103 IN UINT32 Instance
1104 )
1105 /*++
1106
1107 Routine Description:
1108
1109 This code returns information about the EFI variables.
1110
1111 Arguments:
1112
1113 Attributes Attributes bitmask to specify the type of variables
1114 on which to return information.
1115 MaximumVariableStorageSize Pointer to the maximum size of the storage space available
1116 for the EFI variables associated with the attributes specified.
1117 RemainingVariableStorageSize Pointer to the remaining size of the storage space available
1118 for the EFI variables associated with the attributes specified.
1119 MaximumVariableSize Pointer to the maximum size of the individual EFI variables
1120 associated with the attributes specified.
1121 Global Pointer to VARIABLE_GLOBAL structure.
1122 Instance Instance of the Firmware Volume.
1123
1124 Returns:
1125
1126 EFI STATUS
1127 EFI_INVALID_PARAMETER - An invalid combination of attribute bits was supplied.
1128 EFI_SUCCESS - Query successfully.
1129 EFI_UNSUPPORTED - The attribute is not supported on this platform.
1130
1131 --*/
1132 {
1133 VARIABLE_HEADER *Variable;
1134 VARIABLE_HEADER *NextVariable;
1135 UINT64 VariableSize;
1136 VARIABLE_STORE_HEADER *VariableStoreHeader;
1137
1138 if(MaximumVariableStorageSize == NULL || RemainingVariableStorageSize == NULL || MaximumVariableSize == NULL) {
1139 return EFI_INVALID_PARAMETER;
1140 }
1141
1142 if((Attributes & (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS)) == 0) {
1143 //
1144 // Make sure the Attributes combination is supported by the platform.
1145 //
1146 return EFI_UNSUPPORTED;
1147 } else if ((Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == EFI_VARIABLE_RUNTIME_ACCESS) {
1148 //
1149 // Make sure if runtime bit is set, boot service bit is set also.
1150 //
1151 return EFI_INVALID_PARAMETER;
1152 } else if (EfiAtRuntime () && !(Attributes & EFI_VARIABLE_RUNTIME_ACCESS)) {
1153 //
1154 // Make sure RT Attribute is set if we are in Runtime phase.
1155 //
1156 return EFI_INVALID_PARAMETER;
1157 }
1158
1159 if((Attributes & EFI_VARIABLE_NON_VOLATILE) == 0) {
1160 //
1161 // Query is Volatile related.
1162 //
1163 VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINTN) Global->VolatileVariableBase);
1164 } else {
1165 //
1166 // Query is Non-Volatile related.
1167 //
1168 VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINTN) Global->NonVolatileVariableBase);
1169 }
1170
1171 //
1172 // Now let's fill *MaximumVariableStorageSize *RemainingVariableStorageSize
1173 // with the storage size (excluding the storage header size).
1174 //
1175 *MaximumVariableStorageSize = VariableStoreHeader->Size - sizeof (VARIABLE_STORE_HEADER);
1176 *RemainingVariableStorageSize = VariableStoreHeader->Size - sizeof (VARIABLE_STORE_HEADER);
1177
1178 //
1179 // Let *MaximumVariableSize be MAX_VARIABLE_SIZE.
1180 //
1181 *MaximumVariableSize = MAX_VARIABLE_SIZE;
1182
1183 //
1184 // Point to the starting address of the variables.
1185 //
1186 Variable = (VARIABLE_HEADER *) (VariableStoreHeader + 1);
1187
1188 //
1189 // Now walk through the related variable store.
1190 //
1191 while (IsValidVariableHeader (Variable) && (Variable < GetEndPointer (VariableStoreHeader))) {
1192 NextVariable = GetNextVariablePtr (Variable);
1193 VariableSize = (UINT64) (UINTN) NextVariable - (UINT64) (UINTN) Variable;
1194
1195 if (EfiAtRuntime ()) {
1196 //
1197 // we don't take the state of the variables in mind
1198 // when calculating RemainingVariableStorageSize,
1199 // since the space occupied by variables not marked with
1200 // VAR_ADDED is not allowed to be reclaimed in Runtime.
1201 //
1202 *RemainingVariableStorageSize -= VariableSize;
1203 } else {
1204 //
1205 // Only care about Variables with State VAR_ADDED,because
1206 // the space not marked as VAR_ADDED is reclaimable now.
1207 //
1208 if (Variable->State == VAR_ADDED) {
1209 *RemainingVariableStorageSize -= VariableSize;
1210 }
1211 }
1212
1213 //
1214 // Go to the next one
1215 //
1216 Variable = NextVariable;
1217 }
1218
1219 return EFI_SUCCESS;
1220 }
1221 #endif
1222
1223 EFI_STATUS
1224 EFIAPI
1225 VariableCommonInitialize (
1226 IN EFI_HANDLE ImageHandle,
1227 IN EFI_SYSTEM_TABLE *SystemTable
1228 )
1229 /*++
1230
1231 Routine Description:
1232 This function does common initialization for variable services
1233
1234 Arguments:
1235
1236 ImageHandle - The firmware allocated handle for the EFI image.
1237 SystemTable - A pointer to the EFI System Table.
1238
1239 Returns:
1240
1241 Status code.
1242
1243 EFI_NOT_FOUND - Variable store area not found.
1244 EFI_UNSUPPORTED - Currently only one non-volatile variable store is supported.
1245 EFI_SUCCESS - Variable services successfully initialized.
1246
1247 --*/
1248 {
1249 EFI_STATUS Status;
1250 EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
1251 CHAR8 *CurrPtr;
1252 VARIABLE_STORE_HEADER *VolatileVariableStore;
1253 VARIABLE_STORE_HEADER *VariableStoreHeader;
1254 VARIABLE_HEADER *NextVariable;
1255 UINT32 Instance;
1256 EFI_PHYSICAL_ADDRESS FvVolHdr;
1257
1258 UINT64 TempVariableStoreHeader;
1259
1260 EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor;
1261 EFI_FLASH_SUBAREA_ENTRY VariableStoreEntry;
1262 UINT64 BaseAddress;
1263 UINT64 Length;
1264 UINTN Index;
1265 UINT8 Data;
1266
1267 Status = gBS->AllocatePool (
1268 EfiRuntimeServicesData,
1269 sizeof (ESAL_VARIABLE_GLOBAL),
1270 (VOID **) &mVariableModuleGlobal
1271 );
1272
1273 if (EFI_ERROR (Status)) {
1274 return Status;
1275 }
1276 //
1277 // Allocate memory for volatile variable store
1278 //
1279 Status = gBS->AllocatePool (
1280 EfiRuntimeServicesData,
1281 VARIABLE_STORE_SIZE + SCRATCH_SIZE,
1282 (VOID **) &VolatileVariableStore
1283 );
1284
1285 if (EFI_ERROR (Status)) {
1286 gBS->FreePool (mVariableModuleGlobal);
1287 return Status;
1288 }
1289
1290 SetMem (VolatileVariableStore, VARIABLE_STORE_SIZE + SCRATCH_SIZE, 0xff);
1291
1292 //
1293 // Variable Specific Data
1294 //
1295 mVariableModuleGlobal->VariableBase[Physical].VolatileVariableBase = (EFI_PHYSICAL_ADDRESS) (UINTN) VolatileVariableStore;
1296 mVariableModuleGlobal->VolatileLastVariableOffset = sizeof (VARIABLE_STORE_HEADER);
1297
1298 VolatileVariableStore->Signature = VARIABLE_STORE_SIGNATURE;
1299 VolatileVariableStore->Size = VARIABLE_STORE_SIZE;
1300 VolatileVariableStore->Format = VARIABLE_STORE_FORMATTED;
1301 VolatileVariableStore->State = VARIABLE_STORE_HEALTHY;
1302 VolatileVariableStore->Reserved = 0;
1303 VolatileVariableStore->Reserved1 = 0;
1304
1305 //
1306 // Get non volatile varaible store
1307 //
1308
1309 TempVariableStoreHeader = (UINT64) PcdGet32 (PcdFlashNvStorageVariableBase);
1310 VariableStoreEntry.Base = TempVariableStoreHeader + \
1311 (((EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) (TempVariableStoreHeader)) -> HeaderLength);
1312 VariableStoreEntry.Length = (UINT64) PcdGet32 (PcdFlashNvStorageVariableSize) - \
1313 (((EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) (TempVariableStoreHeader)) -> HeaderLength);
1314 //
1315 // Mark the variable storage region of the FLASH as RUNTIME
1316 //
1317 BaseAddress = VariableStoreEntry.Base & (~EFI_PAGE_MASK);
1318 Length = VariableStoreEntry.Length + (VariableStoreEntry.Base - BaseAddress);
1319 Length = (Length + EFI_PAGE_SIZE - 1) & (~EFI_PAGE_MASK);
1320
1321 Status = gDS->GetMemorySpaceDescriptor (BaseAddress, &GcdDescriptor);
1322 if (EFI_ERROR (Status)) {
1323 gBS->FreePool (mVariableModuleGlobal);
1324 gBS->FreePool (VolatileVariableStore);
1325 return EFI_UNSUPPORTED;
1326 }
1327
1328 Status = gDS->SetMemorySpaceAttributes (
1329 BaseAddress,
1330 Length,
1331 GcdDescriptor.Attributes | EFI_MEMORY_RUNTIME
1332 );
1333 if (EFI_ERROR (Status)) {
1334 gBS->FreePool (mVariableModuleGlobal);
1335 gBS->FreePool (VolatileVariableStore);
1336 return EFI_UNSUPPORTED;
1337 }
1338 //
1339 // Get address of non volatile variable store base
1340 //
1341 mVariableModuleGlobal->VariableBase[Physical].NonVolatileVariableBase = VariableStoreEntry.Base;
1342
1343 //
1344 // Check Integrity
1345 //
1346 //
1347 // Find the Correct Instance of the FV Block Service.
1348 //
1349 Instance = 0;
1350 CurrPtr = (CHAR8 *) ((UINTN) mVariableModuleGlobal->VariableBase[Physical].NonVolatileVariableBase);
1351 while (EfiFvbGetPhysicalAddress (Instance, &FvVolHdr) == EFI_SUCCESS) {
1352 FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) FvVolHdr);
1353 if (CurrPtr >= (CHAR8 *) FwVolHeader && CurrPtr < (((CHAR8 *) FwVolHeader) + FwVolHeader->FvLength)) {
1354 mVariableModuleGlobal->FvbInstance = Instance;
1355 break;
1356 }
1357
1358 Instance++;
1359 }
1360
1361 VariableStoreHeader = (VARIABLE_STORE_HEADER *) CurrPtr;
1362 if (GetVariableStoreStatus (VariableStoreHeader) == EfiValid) {
1363 if (~VariableStoreHeader->Size == 0) {
1364 Status = UpdateVariableStore (
1365 &mVariableModuleGlobal->VariableBase[Physical],
1366 FALSE,
1367 FALSE,
1368 mVariableModuleGlobal->FvbInstance,
1369 (UINTN) &VariableStoreHeader->Size,
1370 sizeof (UINT32),
1371 (UINT8 *) &VariableStoreEntry.Length
1372 );
1373
1374 if (EFI_ERROR (Status)) {
1375 return Status;
1376 }
1377 }
1378
1379 mVariableModuleGlobal->VariableBase[Physical].NonVolatileVariableBase = (EFI_PHYSICAL_ADDRESS) ((UINTN) CurrPtr);
1380 //
1381 // Parse non-volatile variable data and get last variable offset
1382 //
1383 NextVariable = (VARIABLE_HEADER *) (CurrPtr + sizeof (VARIABLE_STORE_HEADER));
1384 Status = EFI_SUCCESS;
1385
1386 while (IsValidVariableHeader (NextVariable)) {
1387 NextVariable = GetNextVariablePtr (NextVariable);
1388 }
1389
1390 mVariableModuleGlobal->NonVolatileLastVariableOffset = (UINTN) NextVariable - (UINTN) CurrPtr;
1391
1392 //
1393 // Check if the free area is blow a threshold
1394 //
1395 if ((((VARIABLE_STORE_HEADER *)((UINTN) CurrPtr))->Size - mVariableModuleGlobal->NonVolatileLastVariableOffset) < VARIABLE_RECLAIM_THRESHOLD) {
1396 Status = Reclaim (
1397 mVariableModuleGlobal->VariableBase[Physical].NonVolatileVariableBase,
1398 &mVariableModuleGlobal->NonVolatileLastVariableOffset,
1399 FALSE
1400 );
1401 }
1402
1403 if (EFI_ERROR (Status)) {
1404 gBS->FreePool (mVariableModuleGlobal);
1405 gBS->FreePool (VolatileVariableStore);
1406 return Status;
1407 }
1408
1409 //
1410 // Check if the free area is really free.
1411 //
1412 for (Index = mVariableModuleGlobal->NonVolatileLastVariableOffset; Index < VariableStoreHeader->Size; Index++) {
1413 Data = ((UINT8 *) (UINTN) mVariableModuleGlobal->VariableBase[Physical].NonVolatileVariableBase)[Index];
1414 if (Data != 0xff) {
1415 //
1416 // There must be something wrong in variable store, do reclaim operation.
1417 //
1418 Status = Reclaim (
1419 mVariableModuleGlobal->VariableBase[Physical].NonVolatileVariableBase,
1420 &mVariableModuleGlobal->NonVolatileLastVariableOffset,
1421 FALSE
1422 );
1423 break;
1424 }
1425 }
1426 }
1427
1428 if (EFI_ERROR (Status)) {
1429 gBS->FreePool (mVariableModuleGlobal);
1430 gBS->FreePool (VolatileVariableStore);
1431 }
1432
1433 return Status;
1434 }