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