]> git.proxmox.com Git - mirror_edk2.git/blame - DuetPkg/FSVariable/FSVariable.c
Fix some bugs in FSVariable and BdsPlatform for duet platform.
[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
9071550e 746 //\r
747 // The size of the VariableName, including the Unicode Null in bytes plus\r
748 // the DataSize is limited to maximum size of MAX_HARDWARE_ERROR_VARIABLE_SIZE (32K)\r
749 // bytes for HwErrRec, and MAX_VARIABLE_SIZE (1024) bytes for the others.\r
750 //\r
751 if ((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD) {\r
752 if ((DataSize > MAX_HARDWARE_ERROR_VARIABLE_SIZE) || \r
753 (sizeof (VARIABLE_HEADER) + StrSize (VariableName) + DataSize > MAX_HARDWARE_ERROR_VARIABLE_SIZE)) {\r
754 return EFI_INVALID_PARAMETER;\r
755 } \r
756 } else {\r
757 if ((DataSize > MAX_VARIABLE_SIZE) ||\r
758 (sizeof (VARIABLE_HEADER) + StrSize (VariableName) + DataSize > MAX_VARIABLE_SIZE)) {\r
759 return EFI_INVALID_PARAMETER;\r
760 } \r
761 } \r
e5653d94 762\r
9071550e 763 //\r
764 // Check whether the input variable is already existed\r
765 //\r
766\r
767 Status = FindVariable (VariableName, VendorGuid, &Variable);\r
768\r
769 if (Status == EFI_SUCCESS && Variable.CurrPtr != NULL) { \r
770 //\r
771 // Update/Delete existing variable\r
772 //\r
773 \r
774 if (EfiAtRuntime ()) { \r
775 //\r
776 // If EfiAtRuntime and the variable is Volatile and Runtime Access, \r
777 // the volatile is ReadOnly, and SetVariable should be aborted and \r
778 // return EFI_WRITE_PROTECTED.\r
779 //\r
780 if (Variable.Type == Volatile) {\r
781 return EFI_WRITE_PROTECTED;\r
782 }\r
783 //\r
784 // Only variable have NV attribute can be updated/deleted in Runtime\r
785 //\r
786 if (!(Variable.CurrPtr->Attributes & EFI_VARIABLE_NON_VOLATILE)) {\r
787 return EFI_INVALID_PARAMETER; \r
788 }\r
789 }\r
790 \r
791 //\r
792 // Setting a data variable with no access, or zero DataSize attributes\r
793 // specified causes it to be deleted.\r
794 //\r
795 if (DataSize == 0 || (Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == 0) {\r
796 //\r
797 // Found this variable in storage\r
798 //\r
799 State = Variable.CurrPtr->State;\r
800 State &= VAR_DELETED;\r
801\r
802 Status = mGlobal->VariableStore[Variable.Type]->Write (\r
803 mGlobal->VariableStore[Variable.Type],\r
804 VARIABLE_MEMBER_OFFSET (State, (UINTN) Variable.CurrPtr - (UINTN) Variable.StartPtr),\r
805 sizeof (Variable.CurrPtr->State),\r
806 &State\r
807 );\r
808 //\r
809 // NOTE: Write operation at least can write data to memory cache\r
810 // Discard file writing failure here.\r
811 //\r
812 return EFI_SUCCESS;\r
813 }\r
814 \r
815 //\r
816 // Found this variable in storage\r
817 // If the variable is marked valid and the same data has been passed in\r
818 // then return to the caller immediately.\r
819 //\r
820 if ((Variable.CurrPtr->DataSize == DataSize) &&\r
821 (CompareMem (Data, GetVariableDataPtr (Variable.CurrPtr), DataSize) == 0)\r
822 ) {\r
823 return EFI_SUCCESS;\r
824 } else if ((Variable.CurrPtr->State == VAR_ADDED) ||\r
825 (Variable.CurrPtr->State == (VAR_ADDED & VAR_IN_DELETED_TRANSITION))) {\r
826 //\r
827 // Mark the old variable as in delete transition\r
828 //\r
829 State = Variable.CurrPtr->State;\r
830 State &= VAR_IN_DELETED_TRANSITION;\r
831\r
832 Status = mGlobal->VariableStore[Variable.Type]->Write (\r
833 mGlobal->VariableStore[Variable.Type],\r
834 VARIABLE_MEMBER_OFFSET (State, (UINTN) Variable.CurrPtr - (UINTN) Variable.StartPtr),\r
835 sizeof (Variable.CurrPtr->State),\r
836 &State\r
837 );\r
838 //\r
839 // NOTE: Write operation at least can write data to memory cache\r
840 // Discard file writing failure here.\r
841 //\r
842 }\r
843 } else if (Status == EFI_NOT_FOUND) {\r
844 //\r
845 // Create a new variable\r
846 // \r
847 \r
848 //\r
849 // Make sure we are trying to create a new variable.\r
850 // Setting a data variable with no access, or zero DataSize attributes means to delete it. \r
851 //\r
852 if (DataSize == 0 || (Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == 0) {\r
853 return EFI_NOT_FOUND;\r
854 } \r
855 //\r
856 // Only variable have NV|RT attribute can be created in Runtime\r
857 //\r
858 if (EfiAtRuntime () &&\r
859 (!(Attributes & EFI_VARIABLE_RUNTIME_ACCESS) || !(Attributes & EFI_VARIABLE_NON_VOLATILE))) {\r
860 return EFI_INVALID_PARAMETER;\r
861 } \r
862 \r
863 } else {\r
864 //\r
865 // Status should be EFI_INVALID_PARAMETER here according to return status of FindVariable().\r
866 //\r
867 return Status;\r
868 } \r
869\r
870 //\r
871 // Function part - create a new variable and copy the data.\r
872 // Both update a variable and create a variable will come here. \r
873 // We can firstly write all the data in memory, then write them to file\r
874 // This can reduce the times of write operation\r
875 //\r
876 \r
877 NextVariable = (VARIABLE_HEADER *) mGlobal->Scratch;\r
878\r
879 NextVariable->StartId = VARIABLE_DATA;\r
880 NextVariable->Attributes = Attributes;\r
881 NextVariable->State = VAR_ADDED;\r
882 NextVariable->Reserved = 0;\r
883 VarNameOffset = sizeof (VARIABLE_HEADER);\r
884 VarNameSize = StrSize (VariableName);\r
885 CopyMem (\r
886 (UINT8 *) ((UINTN) NextVariable + VarNameOffset),\r
887 VariableName,\r
888 VarNameSize\r
889 );\r
890 VarDataOffset = VarNameOffset + VarNameSize + GET_PAD_SIZE (VarNameSize);\r
891 CopyMem (\r
892 (UINT8 *) ((UINTN) NextVariable + VarDataOffset),\r
893 Data,\r
894 DataSize\r
895 );\r
896 CopyMem (&NextVariable->VendorGuid, VendorGuid, sizeof (EFI_GUID));\r
897 //\r
898 // There will be pad bytes after Data, the NextVariable->NameSize and\r
899 // NextVariable->DataSize should not include pad size so that variable\r
900 // service can get actual size in GetVariable\r
901 //\r
902 NextVariable->NameSize = (UINT32)VarNameSize;\r
903 NextVariable->DataSize = (UINT32)DataSize;\r
904\r
905 //\r
906 // The actual size of the variable that stores in storage should\r
907 // include pad size.\r
908 // VarDataOffset: offset from begin of current variable header\r
909 //\r
910 VarSize = VarDataOffset + DataSize + GET_PAD_SIZE (DataSize);\r
911\r
912 StorageType = (Attributes & EFI_VARIABLE_NON_VOLATILE) ? NonVolatile : Volatile;\r
913\r
914 if ((UINT32) (VarSize + mGlobal->LastVariableOffset[StorageType]) >\r
915 ((VARIABLE_STORE_HEADER *) mGlobal->VariableBase[StorageType])->Size\r
916 ) {\r
917 if ((StorageType == NonVolatile) && EfiAtRuntime ()) {\r
918 return EFI_OUT_OF_RESOURCES;\r
919 }\r
920 //\r
921 // Perform garbage collection & reclaim operation\r
922 //\r
923 Status = Reclaim (StorageType, Variable.CurrPtr);\r
924 if (EFI_ERROR (Status)) {\r
925 //\r
926 // Reclaim error\r
927 // we cannot restore to original state, fetal error, report to user\r
928 //\r
929 DEBUG ((EFI_D_ERROR, "FSVariable: Recalim error (fetal error) - %r\n", Status));\r
930 return Status;\r
931 }\r
932 //\r
933 // If still no enough space, return out of resources\r
934 //\r
935 if ((UINT32) (VarSize + mGlobal->LastVariableOffset[StorageType]) >\r
936 ((VARIABLE_STORE_HEADER *) mGlobal->VariableBase[StorageType])->Size\r
937 ) {\r
938 return EFI_OUT_OF_RESOURCES;\r
939 }\r
940\r
941 Reclaimed = TRUE;\r
942 }\r
943 Status = mGlobal->VariableStore[StorageType]->Write (\r
944 mGlobal->VariableStore[StorageType],\r
945 mGlobal->LastVariableOffset[StorageType],\r
946 VarSize,\r
947 NextVariable\r
948 );\r
949 //\r
950 // NOTE: Write operation at least can write data to memory cache\r
951 // Discard file writing failure here.\r
952 //\r
953 mGlobal->LastVariableOffset[StorageType] += VarSize;\r
954\r
955 //\r
956 // Mark the old variable as deleted\r
957 //\r
958 if (!Reclaimed && !EFI_ERROR (Status) && Variable.CurrPtr != NULL) {\r
959 State = Variable.CurrPtr->State;\r
960 State &= VAR_DELETED;\r
961\r
962 Status = mGlobal->VariableStore[StorageType]->Write (\r
963 mGlobal->VariableStore[StorageType],\r
964 VARIABLE_MEMBER_OFFSET (State, (UINTN) Variable.CurrPtr - (UINTN) Variable.StartPtr),\r
965 sizeof (Variable.CurrPtr->State),\r
966 &State\r
967 );\r
968 //\r
969 // NOTE: Write operation at least can write data to memory cache\r
970 // Discard file writing failure here.\r
971 //\r
972 }\r
973\r
974 return EFI_SUCCESS;\r
975}\r
976\r
9071550e 977EFI_STATUS\r
978EFIAPI\r
979QueryVariableInfo (\r
980 IN UINT32 Attributes,\r
981 OUT UINT64 *MaximumVariableStorageSize,\r
982 OUT UINT64 *RemainingVariableStorageSize,\r
983 OUT UINT64 *MaximumVariableSize\r
984 )\r
985/*++\r
986\r
987Routine Description:\r
988\r
989 This code returns information about the EFI variables.\r
990\r
991Arguments:\r
992\r
993 Attributes Attributes bitmask to specify the type of variables\r
994 on which to return information.\r
995 MaximumVariableStorageSize Pointer to the maximum size of the storage space available\r
996 for the EFI variables associated with the attributes specified.\r
997 RemainingVariableStorageSize Pointer to the remaining size of the storage space available\r
998 for the EFI variables associated with the attributes specified.\r
999 MaximumVariableSize Pointer to the maximum size of the individual EFI variables\r
1000 associated with the attributes specified.\r
1001\r
1002Returns:\r
1003\r
1004 EFI STATUS\r
1005 EFI_INVALID_PARAMETER - An invalid combination of attribute bits was supplied.\r
1006 EFI_SUCCESS - Query successfully.\r
1007 EFI_UNSUPPORTED - The attribute is not supported on this platform.\r
1008\r
1009--*/\r
1010{\r
1011 VARIABLE_HEADER *Variable;\r
1012 VARIABLE_HEADER *NextVariable;\r
1013 UINT64 VariableSize;\r
1014 VARIABLE_STORE_HEADER *VariableStoreHeader;\r
1015\r
1016 if(MaximumVariableStorageSize == NULL || RemainingVariableStorageSize == NULL || MaximumVariableSize == NULL || Attributes == 0) {\r
1017 return EFI_INVALID_PARAMETER;\r
1018 }\r
1019 \r
9071550e 1020 if((Attributes & (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) == 0) {\r
1021 //\r
1022 // Make sure the Attributes combination is supported by the platform.\r
1023 //\r
1024 return EFI_UNSUPPORTED; \r
1025 } \r
9071550e 1026 else if ((Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == EFI_VARIABLE_RUNTIME_ACCESS) {\r
1027 //\r
1028 // Make sure if runtime bit is set, boot service bit is set also.\r
1029 //\r
1030 return EFI_INVALID_PARAMETER;\r
1031 } else if (EfiAtRuntime () && !(Attributes & EFI_VARIABLE_RUNTIME_ACCESS)) {\r
1032 //\r
1033 // Make sure RT Attribute is set if we are in Runtime phase.\r
1034 //\r
1035 return EFI_INVALID_PARAMETER;\r
1036 } \r
1037 \r
1038 VariableStoreHeader = (VARIABLE_STORE_HEADER *) mGlobal->VariableBase[\r
1039 (Attributes & EFI_VARIABLE_NON_VOLATILE) ? NonVolatile : Volatile\r
1040 ];\r
1041 //\r
1042 // Now let's fill *MaximumVariableStorageSize *RemainingVariableStorageSize\r
1043 // with the storage size (excluding the storage header size).\r
1044 //\r
1045 *MaximumVariableStorageSize = VariableStoreHeader->Size - sizeof (VARIABLE_STORE_HEADER);\r
1046 *RemainingVariableStorageSize = VariableStoreHeader->Size - sizeof (VARIABLE_STORE_HEADER);\r
1047\r
1048 //\r
1049 // Let *MaximumVariableSize be MAX_VARIABLE_SIZE with the exception of the variable header size.\r
1050 //\r
1051 *MaximumVariableSize = MAX_VARIABLE_SIZE - sizeof (VARIABLE_HEADER);\r
1052\r
9071550e 1053 //\r
1054 // Harware error record variable needs larger size.\r
1055 //\r
1056 if ((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD) {\r
1057 *MaximumVariableSize = MAX_HARDWARE_ERROR_VARIABLE_SIZE - sizeof (VARIABLE_HEADER);\r
1058 }\r
9071550e 1059 \r
1060 //\r
1061 // Point to the starting address of the variables.\r
1062 //\r
1063 Variable = (VARIABLE_HEADER *) (VariableStoreHeader + 1);\r
1064\r
1065 //\r
1066 // Now walk through the related variable store.\r
1067 //\r
1068 while (IsValidVariableHeader (Variable) && (Variable < GetEndPointer (VariableStoreHeader))) {\r
1069 NextVariable = GetNextVariablePtr (Variable);\r
1070 VariableSize = (UINT64) (UINTN) NextVariable - (UINT64) (UINTN) Variable;\r
1071\r
1072 if (EfiAtRuntime ()) {\r
1073 //\r
1074 // we don't take the state of the variables in mind\r
1075 // when calculating RemainingVariableStorageSize,\r
1076 // since the space occupied by variables not marked with\r
1077 // VAR_ADDED is not allowed to be reclaimed in Runtime.\r
1078 //\r
1079 *RemainingVariableStorageSize -= VariableSize;\r
1080 } else {\r
1081 //\r
1082 // Only care about Variables with State VAR_ADDED,because\r
1083 // the space not marked as VAR_ADDED is reclaimable now.\r
1084 //\r
1085 if ((Variable->State == VAR_ADDED) ||\r
1086 (Variable->State == (VAR_ADDED & VAR_IN_DELETED_TRANSITION))) {\r
1087 *RemainingVariableStorageSize -= VariableSize;\r
1088 }\r
1089 }\r
1090\r
1091 //\r
1092 // Go to the next one\r
1093 //\r
1094 Variable = NextVariable;\r
1095 }\r
1096 \r
1097 if (*RemainingVariableStorageSize < sizeof (VARIABLE_HEADER)) {\r
1098 *MaximumVariableSize = 0;\r
1099 } else if ((*RemainingVariableStorageSize - sizeof (VARIABLE_HEADER)) < *MaximumVariableSize) {\r
1100 *MaximumVariableSize = *RemainingVariableStorageSize - sizeof (VARIABLE_HEADER);\r
1101 }\r
1102\r
1103 return EFI_SUCCESS;\r
1104}\r
9071550e 1105\r
1106EFI_STATUS\r
1107EFIAPI\r
1108VariableServiceInitialize (\r
1109 IN EFI_HANDLE ImageHandle,\r
1110 IN EFI_SYSTEM_TABLE *SystemTable\r
1111 )\r
1112/*++\r
1113\r
1114Routine Description:\r
1115 This function does initialization for variable services\r
1116\r
1117Arguments:\r
1118\r
1119 ImageHandle - The firmware allocated handle for the EFI image.\r
1120 SystemTable - A pointer to the EFI System Table.\r
1121\r
1122Returns:\r
1123\r
1124 Status code.\r
1125\r
1126 EFI_NOT_FOUND - Variable store area not found.\r
1127 EFI_SUCCESS - Variable services successfully initialized.\r
1128\r
1129--*/\r
1130{\r
1131 EFI_STATUS Status;\r
1132 EFI_HANDLE NewHandle;\r
1133 VS_DEV *Dev;\r
eb16e240 1134 EFI_PEI_HOB_POINTERS GuidHob;\r
9071550e 1135 VARIABLE_HEADER *NextVariable;\r
1136 VARIABLE_STORE_HEADER *VariableStoreHeader;\r
1137 EFI_FLASH_MAP_FS_ENTRY_DATA *FlashMapEntryData;\r
1138 EFI_FLASH_SUBAREA_ENTRY VariableStoreEntry;\r
9071550e 1139 UINT64 BaseAddress;\r
1140 UINT64 Length;\r
1141 EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor;\r
1142\r
1143 Status = gBS->AllocatePool (\r
1144 EfiRuntimeServicesData,\r
1145 (UINTN) sizeof (VARIABLE_GLOBAL),\r
1146 &mGlobal\r
1147 );\r
1148 if (EFI_ERROR (Status)) {\r
1149 return Status;\r
1150 }\r
1151\r
eb16e240 1152 GuidHob.Raw = GetHobList ();\r
1153 FlashMapEntryData = NULL;\r
1154 while ((GuidHob.Raw = GetNextGuidHob (&gEfiFlashMapHobGuid, GuidHob.Raw)) != NULL) {\r
1155 FlashMapEntryData = (EFI_FLASH_MAP_FS_ENTRY_DATA *) GET_GUID_HOB_DATA (GuidHob.Guid);\r
9071550e 1156 if (FlashMapEntryData->AreaType == EFI_FLASH_AREA_EFI_VARIABLES) {\r
1157 break;\r
1158 }\r
eb16e240 1159 GuidHob.Raw = GET_NEXT_HOB (GuidHob); \r
9071550e 1160 }\r
1161\r
eb16e240 1162 if (FlashMapEntryData == NULL) {\r
1163 DEBUG ((EFI_D_ERROR, "FSVariable: Could not find flash area for variable!\n"));\r
9071550e 1164 Status = EFI_NOT_FOUND;\r
1165 return Status;\r
1166 }\r
1167\r
1168 VariableStoreEntry = FlashMapEntryData->Entries[0];\r
1169\r
1170 //\r
1171 // Mark the variable storage region of the FLASH as RUNTIME\r
1172 //\r
1173 BaseAddress = VariableStoreEntry.Base & (~EFI_PAGE_MASK);\r
1174 Length = VariableStoreEntry.Length + (VariableStoreEntry.Base - BaseAddress);\r
1175 Length = (Length + EFI_PAGE_SIZE - 1) & (~EFI_PAGE_MASK);\r
1176 Status = gDS->GetMemorySpaceDescriptor (BaseAddress, &GcdDescriptor);\r
1177 if (EFI_ERROR (Status)) {\r
1178 Status = EFI_UNSUPPORTED;\r
1179 return Status;\r
1180 }\r
1181 Status = gDS->SetMemorySpaceAttributes (\r
1182 BaseAddress,\r
1183 Length,\r
1184 GcdDescriptor.Attributes | EFI_MEMORY_RUNTIME\r
1185 );\r
1186 if (EFI_ERROR (Status)) {\r
1187 Status = EFI_UNSUPPORTED;\r
1188 return Status;\r
1189 }\r
1190 \r
1191 Status = FileStorageConstructor (\r
1192 &mGlobal->VariableStore[NonVolatile], \r
1193 &mGlobal->GoVirtualChildEvent[NonVolatile],\r
1194 VariableStoreEntry.Base,\r
1195 (UINT32) VariableStoreEntry.Length,\r
1196 FlashMapEntryData->VolumeId,\r
1197 FlashMapEntryData->FilePath\r
1198 );\r
1199 ASSERT_EFI_ERROR (Status);\r
1200\r
1201 //\r
1202 // Volatile Storage\r
1203 //\r
1204 Status = MemStorageConstructor (\r
1205 &mGlobal->VariableStore[Volatile],\r
1206 &mGlobal->GoVirtualChildEvent[Volatile],\r
1207 VOLATILE_VARIABLE_STORE_SIZE\r
1208 );\r
1209 ASSERT_EFI_ERROR (Status);\r
1210\r
1211 //\r
1212 // Scratch\r
1213 //\r
1214 Status = gBS->AllocatePool (\r
1215 EfiRuntimeServicesData,\r
1216 VARIABLE_SCRATCH_SIZE,\r
1217 &mGlobal->Scratch\r
1218 );\r
1219 ASSERT_EFI_ERROR (Status);\r
1220\r
1221 //\r
1222 // 1. NV Storage\r
1223 //\r
1224 Dev = DEV_FROM_THIS (mGlobal->VariableStore[NonVolatile]);\r
1225 VariableStoreHeader = (VARIABLE_STORE_HEADER *) VAR_DATA_PTR (Dev);\r
1226 if (GetVariableStoreStatus (VariableStoreHeader) == EfiValid) {\r
1227 if (~VariableStoreHeader->Size == 0) {\r
1228 VariableStoreHeader->Size = (UINT32) VariableStoreEntry.Length;\r
1229 }\r
1230 }\r
1231 //\r
1232 // Calculate LastVariableOffset\r
1233 //\r
1234 NextVariable = (VARIABLE_HEADER *) (VariableStoreHeader + 1);\r
1235 while (IsValidVariableHeader (NextVariable)) {\r
1236 NextVariable = GetNextVariablePtr (NextVariable);\r
1237 }\r
1238 mGlobal->LastVariableOffset[NonVolatile] = (UINTN) NextVariable - (UINTN) VariableStoreHeader;\r
1239 mGlobal->VariableBase[NonVolatile] = VariableStoreHeader;\r
1240\r
1241 //\r
1242 // Reclaim if remaining space is too small\r
1243 //\r
1244 if ((VariableStoreHeader->Size - mGlobal->LastVariableOffset[NonVolatile]) < VARIABLE_RECLAIM_THRESHOLD) {\r
1245 Status = Reclaim (NonVolatile, NULL);\r
1246 if (EFI_ERROR (Status)) {\r
1247 //\r
1248 // Reclaim error\r
1249 // we cannot restore to original state\r
1250 //\r
1251 DEBUG ((EFI_D_ERROR, "FSVariable: Recalim error (fetal error) - %r\n", Status));\r
1252 ASSERT_EFI_ERROR (Status);\r
1253 }\r
1254 }\r
1255 \r
1256 //\r
1257 // 2. Volatile Storage\r
1258 //\r
1259 Dev = DEV_FROM_THIS (mGlobal->VariableStore[Volatile]);\r
1260 VariableStoreHeader = (VARIABLE_STORE_HEADER *) VAR_DATA_PTR (Dev);\r
1261 mGlobal->VariableBase[Volatile] = VAR_DATA_PTR (Dev); \r
1262 mGlobal->LastVariableOffset[Volatile] = sizeof (VARIABLE_STORE_HEADER);\r
1263 //\r
1264 // init store_header & body in memory.\r
1265 //\r
1266 mGlobal->VariableStore[Volatile]->Erase (mGlobal->VariableStore[Volatile]);\r
1267 mGlobal->VariableStore[Volatile]->Write (\r
1268 mGlobal->VariableStore[Volatile],\r
1269 0,\r
1270 sizeof (VARIABLE_STORE_HEADER),\r
1271 &mStoreHeaderTemplate\r
1272 );\r
1273\r
1274\r
1275 SystemTable->RuntimeServices->GetVariable = GetVariable;\r
1276 SystemTable->RuntimeServices->GetNextVariableName = GetNextVariableName;\r
1277 SystemTable->RuntimeServices->SetVariable = SetVariable;\r
1278\r
9071550e 1279 SystemTable->RuntimeServices->QueryVariableInfo = QueryVariableInfo;\r
9071550e 1280\r
1281 //\r
1282 // Now install the Variable Runtime Architectural Protocol on a new handle\r
1283 //\r
1284 NewHandle = NULL;\r
1285 Status = gBS->InstallMultipleProtocolInterfaces (\r
1286 &NewHandle,\r
1287 &gEfiVariableArchProtocolGuid,\r
1288 NULL,\r
1289 &gEfiVariableWriteArchProtocolGuid,\r
1290 NULL,\r
1291 NULL\r
1292 );\r
1293 ASSERT_EFI_ERROR (Status);\r
1294\r
1295 return Status;\r
1296\r
1297//Shutdown:\r
1298// EfiShutdownRuntimeDriverLib ();\r
1299// return Status;\r
1300}\r
1301\r
1302\r
1303\r
1304STATIC\r
1305VOID\r
1306EFIAPI\r
1307OnVirtualAddressChange (\r
1308 IN EFI_EVENT Event,\r
1309 IN VOID *Context\r
1310 )\r
1311{\r
1312 UINTN Index;\r
1313\r
1314 for (Index = 0; Index < MaxType; Index++) {\r
1315 mGlobal->GoVirtualChildEvent[Index] (Event, mGlobal->VariableStore[Index]);\r
1316 EfiConvertPointer (0, &mGlobal->VariableStore[Index]);\r
1317 EfiConvertPointer (0, &mGlobal->VariableBase[Index]);\r
1318 }\r
1319 EfiConvertPointer (0, &mGlobal->Scratch);\r
1320 EfiConvertPointer (0, &mGlobal);\r
1321}\r