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