Merge R8 tracker #8374 to make EmuVariable.GetNextVariableName() comply with UEFI...
[mirror_edk2.git] / EdkModulePkg / Universal / EmuVariable / RuntimeDxe / EmuVariable.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 EmuVariable.c\r
15\r
16Abstract:\r
17\r
18Revision History\r
19\r
20--*/\r
21\r
22#include "Variable.h"\r
23\r
24//\r
25// Don't use module globals after the SetVirtualAddress map is signaled\r
26//\r
27ESAL_VARIABLE_GLOBAL *mVariableModuleGlobal;\r
28\r
29UINT32\r
30EFIAPI\r
31ArrayLength (\r
32 IN CHAR16 *String\r
33 )\r
34/*++\r
35\r
36Routine Description:\r
37\r
38 Determine the length of null terminated char16 array.\r
39\r
40Arguments:\r
41\r
42 String Null-terminated CHAR16 array pointer.\r
43\r
44Returns:\r
45\r
46 UINT32 Number of bytes in the string, including the double NULL at the end;\r
47\r
48--*/\r
49{\r
50 UINT32 Count;\r
51\r
52 if (NULL == String) {\r
53 return 0;\r
54 }\r
55\r
56 Count = 0;\r
57\r
58 while (0 != String[Count]) {\r
59 Count++;\r
60 }\r
61\r
62 return (Count * 2) + 2;\r
63}\r
64\r
65UINTN\r
66EFIAPI\r
67GetPadSize (\r
68 IN UINTN Value\r
69 )\r
70/*++\r
71\r
72Routine Description:\r
73\r
74 This function return the pad size for alignment\r
75\r
76Arguments:\r
77\r
78 Value The value need to align\r
79\r
80Returns:\r
81\r
82 Pad size for value\r
83\r
84--*/\r
85{\r
86 //\r
87 // If alignment is 0 or 1, means no alignment required\r
88 //\r
89 if (ALIGNMENT == 0 || ALIGNMENT == 1) {\r
90 return 0;\r
91 }\r
92\r
93 return ALIGNMENT - (Value % ALIGNMENT);\r
94}\r
95\r
96VARIABLE_STORE_STATUS\r
97EFIAPI\r
98GetVariableStoreStatus (\r
99 IN VARIABLE_STORE_HEADER *VarStoreHeader\r
100 )\r
101/*++\r
102\r
103Routine Description:\r
104\r
105 This code gets the pointer to the variable name.\r
106\r
107Arguments:\r
108\r
109 VarStoreHeader Pointer to the Variable Store Header.\r
110\r
111Returns:\r
112\r
113 EfiHealthy Variable store is healthy\r
114 EfiRaw Variable store is raw\r
115 EfiInvalid Variable store is invalid\r
116\r
117--*/\r
118{\r
119 if (VarStoreHeader->Signature == VARIABLE_STORE_SIGNATURE &&\r
120 VarStoreHeader->Format == VARIABLE_STORE_FORMATTED &&\r
121 VarStoreHeader->State == VARIABLE_STORE_HEALTHY\r
122 ) {\r
123\r
124 return EfiValid;\r
125 } else if (VarStoreHeader->Signature == 0xffffffff &&\r
126 VarStoreHeader->Size == 0xffffffff &&\r
127 VarStoreHeader->Format == 0xff &&\r
128 VarStoreHeader->State == 0xff\r
129 ) {\r
130\r
131 return EfiRaw;\r
132 } else {\r
133 return EfiInvalid;\r
134 }\r
135}\r
136\r
137UINT8 *\r
138EFIAPI\r
139GetVariableDataPtr (\r
140 IN VARIABLE_HEADER *Variable\r
141 )\r
142/*++\r
143\r
144Routine Description:\r
145\r
146 This code gets the pointer to the variable data.\r
147\r
148Arguments:\r
149\r
150 Variable Pointer to the Variable Header.\r
151\r
152Returns:\r
153\r
154 UINT8* Pointer to Variable Data\r
155\r
156--*/\r
157{\r
158 if (Variable->StartId != VARIABLE_DATA) {\r
159 return NULL;\r
160 }\r
161 //\r
162 // Be careful about pad size for alignment\r
163 //\r
164 return (UINT8 *) ((UINTN) GET_VARIABLE_NAME_PTR (Variable) + Variable->NameSize + GetPadSize (Variable->NameSize));\r
165}\r
166\r
167VARIABLE_HEADER *\r
168EFIAPI\r
169GetNextVariablePtr (\r
170 IN VARIABLE_HEADER *Variable\r
171 )\r
172/*++\r
173\r
174Routine Description:\r
175\r
176 This code gets the pointer to the next variable header.\r
177\r
178Arguments:\r
179\r
180 Variable Pointer to the Variable Header.\r
181\r
182Returns:\r
183\r
184 VARIABLE_HEADER* Pointer to next variable header.\r
185\r
186--*/\r
187{\r
188 VARIABLE_HEADER *VarHeader;\r
189\r
190 if (Variable->StartId != VARIABLE_DATA) {\r
191 return NULL;\r
192 }\r
193 //\r
194 // Be careful about pad size for alignment\r
195 //\r
196 VarHeader = (VARIABLE_HEADER *) (GetVariableDataPtr (Variable) + Variable->DataSize + GET_PAD_SIZE (Variable->DataSize));\r
197\r
198 if (VarHeader->StartId != VARIABLE_DATA ||\r
199 (sizeof (VARIABLE_HEADER) + VarHeader->DataSize + VarHeader->NameSize) > MAX_VARIABLE_SIZE\r
200 ) {\r
201 return NULL;\r
202 }\r
203\r
204 return VarHeader;\r
205}\r
206\r
207VARIABLE_HEADER *\r
208EFIAPI\r
209GetEndPointer (\r
210 IN VARIABLE_STORE_HEADER *VolHeader\r
211 )\r
212/*++\r
213\r
214Routine Description:\r
215\r
216 This code gets the pointer to the last variable memory pointer byte\r
217\r
218Arguments:\r
219\r
220 Variable Pointer to the Variable Header.\r
221\r
222Returns:\r
223\r
224 VARIABLE_HEADER* Pointer to last unavailable Variable Header\r
225\r
226--*/\r
227{\r
228 //\r
229 // The end of variable store\r
230 //\r
231 return (VARIABLE_HEADER *) ((UINTN) VolHeader + VolHeader->Size);\r
232}\r
233\r
234EFI_STATUS\r
235EFIAPI\r
236FindVariable (\r
237 IN CHAR16 *VariableName,\r
238 IN EFI_GUID *VendorGuid,\r
239 OUT VARIABLE_POINTER_TRACK *PtrTrack,\r
240 IN VARIABLE_GLOBAL *Global\r
241 )\r
242/*++\r
243\r
244Routine Description:\r
245\r
246 This code finds variable in storage blocks (Volatile or Non-Volatile)\r
247\r
248Arguments:\r
249\r
250 VariableName Name of the variable to be found\r
251 VendorGuid Vendor GUID to be found.\r
252 PtrTrack Variable Track Pointer structure that contains\r
253 Variable Information.\r
254 Contains the pointer of Variable header.\r
255 Global VARIABLE_GLOBAL pointer\r
256\r
257Returns:\r
258\r
259 EFI STATUS\r
260\r
261--*/\r
262{\r
263 VARIABLE_HEADER *Variable[2];\r
264 VARIABLE_STORE_HEADER *VariableStoreHeader[2];\r
265 UINTN Index;\r
266\r
267 //\r
268 // 0: Non-Volatile, 1: Volatile\r
269 //\r
270 VariableStoreHeader[0] = (VARIABLE_STORE_HEADER *) ((UINTN) Global->NonVolatileVariableBase);\r
271 VariableStoreHeader[1] = (VARIABLE_STORE_HEADER *) ((UINTN) Global->VolatileVariableBase);\r
272\r
273 //\r
274 // Start Pointers for the variable.\r
275 // Actual Data Pointer where data can be written.\r
276 //\r
277 Variable[0] = (VARIABLE_HEADER *) (VariableStoreHeader[0] + 1);\r
278 Variable[1] = (VARIABLE_HEADER *) (VariableStoreHeader[1] + 1);\r
279\r
280 if (VariableName[0] != 0 && VendorGuid == NULL) {\r
281 return EFI_INVALID_PARAMETER;\r
282 }\r
283 //\r
284 // Find the variable by walk through non-volatile and volatile variable store\r
285 //\r
286 for (Index = 0; Index < 2; Index++) {\r
287 PtrTrack->StartPtr = (VARIABLE_HEADER *) (VariableStoreHeader[Index] + 1);\r
288 PtrTrack->EndPtr = GetEndPointer (VariableStoreHeader[Index]);\r
289\r
290 while ((Variable[Index] != NULL) && (Variable[Index] <= GetEndPointer (VariableStoreHeader[Index]))) {\r
291 if (Variable[Index]->StartId == VARIABLE_DATA && Variable[Index]->State == VAR_ADDED) {\r
292 if (!(EfiAtRuntime () && !(Variable[Index]->Attributes & EFI_VARIABLE_RUNTIME_ACCESS))) {\r
293 if (VariableName[0] == 0) {\r
294 PtrTrack->CurrPtr = Variable[Index];\r
295 PtrTrack->Volatile = (BOOLEAN) Index;\r
296 return EFI_SUCCESS;\r
297 } else {\r
298 if (CompareGuid (VendorGuid, &Variable[Index]->VendorGuid)) {\r
299 if (!CompareMem (VariableName, GET_VARIABLE_NAME_PTR (Variable[Index]), ArrayLength (VariableName))) {\r
300 PtrTrack->CurrPtr = Variable[Index];\r
301 PtrTrack->Volatile = (BOOLEAN) Index;\r
302 return EFI_SUCCESS;\r
303 }\r
304 }\r
305 }\r
306 }\r
307 }\r
308\r
309 Variable[Index] = GetNextVariablePtr (Variable[Index]);\r
310 }\r
311 }\r
312 PtrTrack->CurrPtr = NULL;\r
313 return EFI_NOT_FOUND;\r
314}\r
315\r
316EFI_STATUS\r
317EFIAPI\r
318GetVariable (\r
319 IN CHAR16 *VariableName,\r
320 IN EFI_GUID * VendorGuid,\r
321 OUT UINT32 *Attributes OPTIONAL,\r
322 IN OUT UINTN *DataSize,\r
323 OUT VOID *Data,\r
324 IN VARIABLE_GLOBAL * Global,\r
325 IN UINT32 Instance\r
326 )\r
327/*++\r
328\r
329Routine Description:\r
330\r
331 This code finds variable in storage blocks (Volatile or Non-Volatile)\r
332\r
333Arguments:\r
334\r
335 VariableName Name of Variable to be found\r
336 VendorGuid Variable vendor GUID\r
337 Attributes OPTIONAL Attribute value of the variable found\r
338 DataSize Size of Data found. If size is less than the\r
339 data, this value contains the required size.\r
340 Data Data pointer\r
341 Global Pointer to VARIABLE_GLOBAL structure\r
342 Instance Instance of the Firmware Volume.\r
343\r
344Returns:\r
345\r
346 EFI STATUS\r
347\r
348--*/\r
349{\r
350 VARIABLE_POINTER_TRACK Variable;\r
351 UINTN VarDataSize;\r
352 EFI_STATUS Status;\r
353\r
354 if (VariableName == NULL || VendorGuid == NULL || DataSize == NULL) {\r
355 return EFI_INVALID_PARAMETER;\r
356 }\r
357 //\r
358 // Find existing variable\r
359 //\r
360 Status = FindVariable (VariableName, VendorGuid, &Variable, Global);\r
361\r
362 if (Variable.CurrPtr == NULL || EFI_ERROR (Status)) {\r
363 return Status;\r
364 }\r
365 //\r
366 // Get data size\r
367 //\r
368 VarDataSize = Variable.CurrPtr->DataSize;\r
369 if (*DataSize >= VarDataSize) {\r
370 CopyMem (Data, GetVariableDataPtr (Variable.CurrPtr), VarDataSize);\r
371 if (Attributes) {\r
372 *Attributes = Variable.CurrPtr->Attributes;\r
373 }\r
374\r
375 *DataSize = VarDataSize;\r
376 return EFI_SUCCESS;\r
377 } else {\r
378 *DataSize = VarDataSize;\r
379 return EFI_BUFFER_TOO_SMALL;\r
380 }\r
381}\r
382\r
383EFI_STATUS\r
384EFIAPI\r
385GetNextVariableName (\r
386 IN OUT UINTN *VariableNameSize,\r
387 IN OUT CHAR16 *VariableName,\r
388 IN OUT EFI_GUID *VendorGuid,\r
389 IN VARIABLE_GLOBAL *Global,\r
390 IN UINT32 Instance\r
391 )\r
392/*++\r
393\r
394Routine Description:\r
395\r
396 This code Finds the Next available variable\r
397\r
398Arguments:\r
399\r
400 VariableNameSize Size of the variable\r
401 VariableName Pointer to variable name\r
402 VendorGuid Variable Vendor Guid\r
403 Global VARIABLE_GLOBAL structure pointer.\r
404 Instance FV instance\r
405\r
406Returns:\r
407\r
408 EFI STATUS\r
409\r
410--*/\r
411{\r
412 VARIABLE_POINTER_TRACK Variable;\r
413 UINTN VarNameSize;\r
414 EFI_STATUS Status;\r
415\r
027c2ecb 416 if (VariableNameSize == NULL || VariableName == NULL || VendorGuid == NULL) {\r
878ddf1f 417 return EFI_INVALID_PARAMETER;\r
418 }\r
419\r
420 Status = FindVariable (VariableName, VendorGuid, &Variable, Global);\r
421\r
422 if (Variable.CurrPtr == NULL || EFI_ERROR (Status)) {\r
423 return Status;\r
424 }\r
425\r
426 while (TRUE) {\r
427 if (VariableName[0] != 0) {\r
428 //\r
429 // If variable name is not NULL, get next variable\r
430 //\r
431 Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);\r
432 }\r
433 //\r
434 // If both volatile and non-volatile variable store are parsed,\r
435 // return not found\r
436 //\r
437 if (Variable.CurrPtr >= Variable.EndPtr || Variable.CurrPtr == NULL) {\r
438 Variable.Volatile = (BOOLEAN) (Variable.Volatile ^ ((BOOLEAN) 0x1));\r
439 if (Variable.Volatile) {\r
440 Variable.StartPtr = (VARIABLE_HEADER *) ((UINTN) (Global->VolatileVariableBase + sizeof (VARIABLE_STORE_HEADER)));\r
441 Variable.EndPtr = (VARIABLE_HEADER *) GetEndPointer ((VARIABLE_STORE_HEADER *) ((UINTN) Global->VolatileVariableBase));\r
442 } else {\r
443 return EFI_NOT_FOUND;\r
444 }\r
445\r
446 Variable.CurrPtr = Variable.StartPtr;\r
447 if (Variable.CurrPtr->StartId != VARIABLE_DATA) {\r
448 continue;\r
449 }\r
450 }\r
451 //\r
452 // Variable is found\r
453 //\r
454 if (Variable.CurrPtr->StartId == VARIABLE_DATA && Variable.CurrPtr->State == VAR_ADDED) {\r
455 if (!(EfiAtRuntime () && !(Variable.CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS))) {\r
456 VarNameSize = Variable.CurrPtr->NameSize;\r
457 if (VarNameSize <= *VariableNameSize) {\r
458 CopyMem (\r
459 VariableName,\r
460 GET_VARIABLE_NAME_PTR (Variable.CurrPtr),\r
461 VarNameSize\r
462 );\r
463 CopyMem (\r
464 VendorGuid,\r
465 &Variable.CurrPtr->VendorGuid,\r
466 sizeof (EFI_GUID)\r
467 );\r
468 Status = EFI_SUCCESS;\r
469 } else {\r
470 Status = EFI_BUFFER_TOO_SMALL;\r
471 }\r
472\r
473 *VariableNameSize = VarNameSize;\r
474 return Status;\r
475 }\r
476 }\r
477 }\r
478\r
479 return EFI_NOT_FOUND;\r
480}\r
481\r
482EFI_STATUS\r
483EFIAPI\r
484SetVariable (\r
485 IN CHAR16 *VariableName,\r
486 IN EFI_GUID *VendorGuid,\r
487 IN UINT32 Attributes,\r
488 IN UINTN DataSize,\r
489 IN VOID *Data,\r
490 IN VARIABLE_GLOBAL *Global,\r
491 IN UINTN *VolatileOffset,\r
492 IN UINTN *NonVolatileOffset,\r
493 IN UINT32 Instance\r
494 )\r
495/*++\r
496\r
497Routine Description:\r
498\r
499 This code sets variable in storage blocks (Volatile or Non-Volatile)\r
500\r
501Arguments:\r
502\r
503 VariableName Name of Variable to be found\r
504 VendorGuid Variable vendor GUID\r
505 Attributes Attribute value of the variable found\r
506 DataSize Size of Data found. If size is less than the\r
507 data, this value contains the required size.\r
508 Data Data pointer\r
509 Global Pointer to VARIABLE_GLOBAL structure\r
510 VolatileOffset The offset of last volatile variable\r
511 NonVolatileOffset The offset of last non-volatile variable\r
512 Instance Instance of the Firmware Volume.\r
513\r
514Returns:\r
515\r
516 EFI STATUS\r
517\r
518--*/\r
519{\r
520 VARIABLE_POINTER_TRACK Variable;\r
521 EFI_STATUS Status;\r
522 VARIABLE_HEADER *NextVariable;\r
523 UINTN VarNameSize;\r
524 UINTN VarNameOffset;\r
525 UINTN VarDataOffset;\r
526 UINTN VarSize;\r
527\r
528 if (VariableName == NULL || VariableName[0] == 0 || VendorGuid == NULL) {\r
529 return EFI_INVALID_PARAMETER;\r
530 }\r
531\r
532 Status = FindVariable (VariableName, VendorGuid, &Variable, Global);\r
533\r
534 if (Status == EFI_INVALID_PARAMETER) {\r
535 return Status;\r
536 }\r
537 //\r
538 // The size of the VariableName, including the Unicode Null in bytes plus\r
539 // the DataSize is limited to maximum size of MAX_VARIABLE_SIZE (1024) bytes.\r
540 //\r
541 else if (sizeof (VARIABLE_HEADER) + (ArrayLength (VariableName) + DataSize) > MAX_VARIABLE_SIZE) {\r
542 return EFI_INVALID_PARAMETER;\r
543 }\r
544 //\r
545 // Make sure if runtime bit is set, boot service bit is set also\r
546 //\r
547 else if ((Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == EFI_VARIABLE_RUNTIME_ACCESS\r
548 ) {\r
549 return EFI_INVALID_PARAMETER;\r
550 }\r
551 //\r
552 // Runtime but Attribute is not Runtime\r
553 //\r
554 else if (EfiAtRuntime () && Attributes && !(Attributes & EFI_VARIABLE_RUNTIME_ACCESS)) {\r
555 return EFI_INVALID_PARAMETER;\r
556 }\r
557 //\r
558 // Cannot set volatile variable in Runtime\r
559 //\r
560 else if (EfiAtRuntime () && Attributes && !(Attributes & EFI_VARIABLE_NON_VOLATILE)) {\r
561 return EFI_INVALID_PARAMETER;\r
562 }\r
563 //\r
564 // Setting a data variable with no access, or zero DataSize attributes\r
565 // specified causes it to be deleted.\r
566 //\r
567 else if (DataSize == 0 || Attributes == 0) {\r
568 if (!EFI_ERROR (Status)) {\r
569 Variable.CurrPtr->State &= VAR_DELETED;\r
570 return EFI_SUCCESS;\r
571 }\r
572\r
573 return EFI_NOT_FOUND;\r
574 } else {\r
575 if (!EFI_ERROR (Status)) {\r
576 //\r
577 // If the variable is marked valid and the same data has been passed in\r
578 // then return to the caller immediately.\r
579 //\r
580 if (Variable.CurrPtr->DataSize == DataSize &&\r
581 !CompareMem (Data, GetVariableDataPtr (Variable.CurrPtr), DataSize)\r
582 ) {\r
583 return EFI_SUCCESS;\r
584 } else if (Variable.CurrPtr->State == VAR_ADDED) {\r
585 //\r
586 // Mark the old variable as in delete transition\r
587 //\r
588 Variable.CurrPtr->State &= VAR_IN_DELETED_TRANSITION;\r
589 }\r
590 }\r
591 //\r
592 // Create a new variable and copy the data.\r
593 //\r
594 VarNameOffset = sizeof (VARIABLE_HEADER);\r
595 VarNameSize = ArrayLength (VariableName);\r
596 VarDataOffset = VarNameOffset + VarNameSize + GetPadSize (VarNameSize);\r
597 VarSize = VarDataOffset + DataSize + GetPadSize (DataSize);\r
598\r
599 if (Attributes & EFI_VARIABLE_NON_VOLATILE) {\r
600 if ((UINT32) (VarSize +*NonVolatileOffset) >\r
601 ((VARIABLE_STORE_HEADER *) ((UINTN) (Global->NonVolatileVariableBase)))->Size\r
602 ) {\r
603 return EFI_OUT_OF_RESOURCES;\r
604 }\r
605\r
606 NextVariable = (VARIABLE_HEADER *) (UINT8 *) (*NonVolatileOffset + (UINTN) Global->NonVolatileVariableBase);\r
607 *NonVolatileOffset = *NonVolatileOffset + VarSize;\r
608 } else {\r
609 if (EfiAtRuntime ()) {\r
610 return EFI_INVALID_PARAMETER;\r
611 }\r
612\r
613 if ((UINT32) (VarSize +*VolatileOffset) >\r
614 ((VARIABLE_STORE_HEADER *) ((UINTN) (Global->VolatileVariableBase)))->Size\r
615 ) {\r
616 return EFI_OUT_OF_RESOURCES;\r
617 }\r
618\r
619 NextVariable = (VARIABLE_HEADER *) (UINT8 *) (*VolatileOffset + (UINTN) Global->VolatileVariableBase);\r
620 *VolatileOffset = *VolatileOffset + VarSize;\r
621 }\r
622\r
623 NextVariable->StartId = VARIABLE_DATA;\r
624 NextVariable->Attributes = Attributes;\r
625 NextVariable->State = VAR_ADDED;\r
626 NextVariable->Reserved = 0;\r
627\r
628 //\r
629 // There will be pad bytes after Data, the NextVariable->NameSize and\r
630 // NextVariable->NameSize should not include pad size so that variable\r
631 // service can get actual size in GetVariable\r
632 //\r
633 NextVariable->NameSize = (UINT32)VarNameSize;\r
634 NextVariable->DataSize = (UINT32)DataSize;\r
635\r
636 CopyMem (&NextVariable->VendorGuid, VendorGuid, sizeof (EFI_GUID));\r
637 CopyMem (\r
638 (UINT8 *) ((UINTN) NextVariable + VarNameOffset),\r
639 VariableName,\r
640 VarNameSize\r
641 );\r
642 CopyMem (\r
643 (UINT8 *) ((UINTN) NextVariable + VarDataOffset),\r
644 Data,\r
645 DataSize\r
646 );\r
647\r
648 //\r
649 // Mark the old variable as deleted\r
650 //\r
651 if (!EFI_ERROR (Status)) {\r
652 Variable.CurrPtr->State &= VAR_DELETED;\r
653 }\r
654 }\r
655\r
656 return EFI_SUCCESS;\r
657}\r
658\r
045f4521 659#if (EFI_SPECIFICATION_VERSION >= 0x00020000)\r
660EFI_STATUS\r
661EFIAPI\r
662QueryVariableInfo (\r
663 IN UINT32 Attributes,\r
664 OUT UINT64 *MaximumVariableStorageSize,\r
665 OUT UINT64 *RemainingVariableStorageSize,\r
666 OUT UINT64 *MaximumVariableSize,\r
667 IN VARIABLE_GLOBAL *Global,\r
668 IN UINT32 Instance\r
669 )\r
670/*++\r
671\r
672Routine Description:\r
673\r
674 This code returns information about the EFI variables.\r
675\r
676Arguments:\r
677\r
678 Attributes Attributes bitmask to specify the type of variables \r
679 on which to return information.\r
680 MaximumVariableStorageSize Pointer to the maximum size of the storage space available\r
681 for the EFI variables associated with the attributes specified.\r
682 RemainingVariableStorageSize Pointer to the remaining size of the storage space available \r
683 for the EFI variables associated with the attributes specified.\r
684 MaximumVariableSize Pointer to the maximum size of the individual EFI variables\r
685 associated with the attributes specified.\r
686 Global Pointer to VARIABLE_GLOBAL structure.\r
687 Instance Instance of the Firmware Volume.\r
688\r
689Returns:\r
690\r
691 EFI STATUS\r
692 EFI_INVALID_PARAMETER - An invalid combination of attribute bits was supplied.\r
693 EFI_SUCCESS - Query successfully.\r
694 EFI_UNSUPPORTED - The attribute is not supported on this platform.\r
695\r
696--*/\r
697{\r
698 VARIABLE_HEADER *Variable;\r
699 VARIABLE_HEADER *NextVariable;\r
700 UINT64 VariableSize;\r
701 VARIABLE_STORE_HEADER *VariableStoreHeader;\r
702 \r
703 if(MaximumVariableStorageSize == NULL || RemainingVariableStorageSize == NULL || MaximumVariableSize == NULL) {\r
704 return EFI_INVALID_PARAMETER;\r
705 }\r
706\r
707 if((Attributes & (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS)) == 0) {\r
708 //\r
709 // Make sure the Attributes combination is supported by the platform.\r
710 //\r
711 return EFI_UNSUPPORTED;\r
712 } else if ((Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == EFI_VARIABLE_RUNTIME_ACCESS) {\r
713 //\r
714 // Make sure if runtime bit is set, boot service bit is set also.\r
715 //\r
716 return EFI_INVALID_PARAMETER;\r
717 } else if (EfiAtRuntime () && !(Attributes & EFI_VARIABLE_RUNTIME_ACCESS)) {\r
718 //\r
719 // Make sure RT Attribute is set if we are in Runtime phase.\r
720 //\r
721 return EFI_INVALID_PARAMETER;\r
722 }\r
723\r
724 if((Attributes & EFI_VARIABLE_NON_VOLATILE) == 0) {\r
725 //\r
726 // Query is Volatile related.\r
727 //\r
728 VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINTN) Global->VolatileVariableBase); \r
729 } else {\r
730 //\r
731 // Query is Non-Volatile related.\r
732 //\r
733 VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINTN) Global->NonVolatileVariableBase);\r
734 }\r
735\r
736 //\r
737 // Now let's fill *MaximumVariableStorageSize *RemainingVariableStorageSize \r
738 // with the storage size (excluding the storage header size)\r
739 //\r
740 *MaximumVariableStorageSize = VariableStoreHeader->Size - sizeof (VARIABLE_STORE_HEADER);\r
741 *RemainingVariableStorageSize = VariableStoreHeader->Size - sizeof (VARIABLE_STORE_HEADER);\r
742\r
743 //\r
744 // Let *MaximumVariableSize be MAX_VARIABLE_SIZE \r
745 //\r
746 *MaximumVariableSize = MAX_VARIABLE_SIZE;\r
747\r
748 //\r
749 // Point to the starting address of the variables.\r
750 //\r
751 Variable = (VARIABLE_HEADER *) (VariableStoreHeader + 1);\r
752\r
753 //\r
754 // Now walk through the related variable store.\r
755 //\r
756 while (Variable < GetEndPointer (VariableStoreHeader)) {\r
757 if (Variable->StartId != VARIABLE_DATA) {\r
758 break;\r
759 }\r
760\r
761 NextVariable = (VARIABLE_HEADER *) (GetVariableDataPtr (Variable) + Variable->DataSize + GET_PAD_SIZE (Variable->DataSize));\r
762 VariableSize = (UINT64) (UINTN) NextVariable - (UINT64) (UINTN) Variable;\r
763\r
764 if (Variable->State == VAR_ADDED) {\r
765 *RemainingVariableStorageSize -= VariableSize;\r
766 }\r
767\r
768 //\r
769 // Go to the next one.\r
770 //\r
771 Variable = NextVariable;\r
772 }\r
773\r
774 return EFI_SUCCESS;\r
775}\r
776#endif\r
777\r
878ddf1f 778EFI_STATUS\r
779EFIAPI\r
780InitializeVariableStore (\r
781 OUT EFI_PHYSICAL_ADDRESS *VariableBase,\r
782 OUT UINTN *LastVariableOffset\r
783 )\r
784/*++\r
785\r
786Routine Description:\r
787 This function initializes variable store\r
788\r
789Arguments:\r
790\r
791Returns:\r
792\r
793--*/\r
794{\r
795 VARIABLE_STORE_HEADER *VariableStore;\r
796\r
797 //\r
798 // Allocate memory for volatile variable store\r
799 //\r
800 VariableStore = (VARIABLE_STORE_HEADER *) AllocateRuntimePool (\r
801 VARIABLE_STORE_SIZE\r
802 );\r
803 if (NULL == VariableStore) {\r
804 return EFI_OUT_OF_RESOURCES;\r
805 }\r
806\r
807 SetMem (VariableStore, VARIABLE_STORE_SIZE, 0xff);\r
808\r
809 //\r
810 // Variable Specific Data\r
811 //\r
812 *VariableBase = (EFI_PHYSICAL_ADDRESS) (UINTN) VariableStore;\r
813 *LastVariableOffset = sizeof (VARIABLE_STORE_HEADER);\r
814\r
815 VariableStore->Signature = VARIABLE_STORE_SIGNATURE;\r
816 VariableStore->Size = VARIABLE_STORE_SIZE;\r
817 VariableStore->Format = VARIABLE_STORE_FORMATTED;\r
818 VariableStore->State = VARIABLE_STORE_HEALTHY;\r
819 VariableStore->Reserved = 0;\r
820 VariableStore->Reserved1 = 0;\r
821\r
822 return EFI_SUCCESS;\r
823}\r
824\r
825EFI_STATUS\r
826EFIAPI\r
827VariableCommonInitialize (\r
828 IN EFI_HANDLE ImageHandle,\r
829 IN EFI_SYSTEM_TABLE *SystemTable\r
830 )\r
831/*++\r
832\r
833Routine Description:\r
834 This function does common initialization for variable services\r
835\r
836Arguments:\r
837\r
838Returns:\r
839\r
840--*/\r
841{\r
842 EFI_STATUS Status;\r
843\r
844 //\r
845 // Allocate memory for mVariableModuleGlobal\r
846 //\r
847 mVariableModuleGlobal = (ESAL_VARIABLE_GLOBAL *) AllocateRuntimePool (\r
848 sizeof (ESAL_VARIABLE_GLOBAL)\r
849 );\r
850 if (NULL == mVariableModuleGlobal) {\r
851 return EFI_OUT_OF_RESOURCES;\r
852 }\r
853 //\r
854 // Intialize volatile variable store\r
855 //\r
856 Status = InitializeVariableStore (\r
857 &mVariableModuleGlobal->VariableBase[Physical].VolatileVariableBase,\r
858 &mVariableModuleGlobal->VolatileLastVariableOffset\r
859 );\r
860\r
861 if (EFI_ERROR (Status)) {\r
862 return Status;\r
863 }\r
864 //\r
865 // Intialize non volatile variable store\r
866 //\r
867 Status = InitializeVariableStore (\r
868 &mVariableModuleGlobal->VariableBase[Physical].NonVolatileVariableBase,\r
869 &mVariableModuleGlobal->NonVolatileLastVariableOffset\r
870 );\r
871\r
872 return Status;\r
873}\r