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