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