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