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