Fixed one bug in EmuVariable module: The macro (GET_PAD_SIZE) is different with GetPa...
[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
339 CopyMem (Data, GetVariableDataPtr (Variable.CurrPtr), VarDataSize);\r
340 if (Attributes) {\r
341 *Attributes = Variable.CurrPtr->Attributes;\r
342 }\r
343\r
344 *DataSize = VarDataSize;\r
345 return EFI_SUCCESS;\r
346 } else {\r
347 *DataSize = VarDataSize;\r
348 return EFI_BUFFER_TOO_SMALL;\r
349 }\r
350}\r
351\r
352EFI_STATUS\r
353EFIAPI\r
354GetNextVariableName (\r
355 IN OUT UINTN *VariableNameSize,\r
356 IN OUT CHAR16 *VariableName,\r
357 IN OUT EFI_GUID *VendorGuid,\r
358 IN VARIABLE_GLOBAL *Global,\r
359 IN UINT32 Instance\r
360 )\r
361/*++\r
362\r
363Routine Description:\r
364\r
365 This code Finds the Next available variable\r
366\r
367Arguments:\r
368\r
369 VariableNameSize Size of the variable\r
370 VariableName Pointer to variable name\r
371 VendorGuid Variable Vendor Guid\r
372 Global VARIABLE_GLOBAL structure pointer.\r
373 Instance FV instance\r
374\r
375Returns:\r
376\r
377 EFI STATUS\r
378\r
379--*/\r
380{\r
381 VARIABLE_POINTER_TRACK Variable;\r
382 UINTN VarNameSize;\r
383 EFI_STATUS Status;\r
384\r
09d4dd14 385 if (VariableNameSize == NULL || VendorGuid == NULL) {\r
878ddf1f 386 return EFI_INVALID_PARAMETER;\r
387 }\r
388\r
389 Status = FindVariable (VariableName, VendorGuid, &Variable, Global);\r
390\r
391 if (Variable.CurrPtr == NULL || EFI_ERROR (Status)) {\r
392 return Status;\r
393 }\r
394\r
395 while (TRUE) {\r
396 if (VariableName[0] != 0) {\r
397 //\r
398 // If variable name is not NULL, get next variable\r
399 //\r
400 Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);\r
401 }\r
402 //\r
403 // If both volatile and non-volatile variable store are parsed,\r
404 // return not found\r
405 //\r
406 if (Variable.CurrPtr >= Variable.EndPtr || Variable.CurrPtr == NULL) {\r
407 Variable.Volatile = (BOOLEAN) (Variable.Volatile ^ ((BOOLEAN) 0x1));\r
408 if (Variable.Volatile) {\r
409 Variable.StartPtr = (VARIABLE_HEADER *) ((UINTN) (Global->VolatileVariableBase + sizeof (VARIABLE_STORE_HEADER)));\r
410 Variable.EndPtr = (VARIABLE_HEADER *) GetEndPointer ((VARIABLE_STORE_HEADER *) ((UINTN) Global->VolatileVariableBase));\r
411 } else {\r
412 return EFI_NOT_FOUND;\r
413 }\r
414\r
415 Variable.CurrPtr = Variable.StartPtr;\r
416 if (Variable.CurrPtr->StartId != VARIABLE_DATA) {\r
417 continue;\r
418 }\r
419 }\r
420 //\r
421 // Variable is found\r
422 //\r
423 if (Variable.CurrPtr->StartId == VARIABLE_DATA && Variable.CurrPtr->State == VAR_ADDED) {\r
424 if (!(EfiAtRuntime () && !(Variable.CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS))) {\r
425 VarNameSize = Variable.CurrPtr->NameSize;\r
426 if (VarNameSize <= *VariableNameSize) {\r
427 CopyMem (\r
428 VariableName,\r
429 GET_VARIABLE_NAME_PTR (Variable.CurrPtr),\r
430 VarNameSize\r
431 );\r
432 CopyMem (\r
433 VendorGuid,\r
434 &Variable.CurrPtr->VendorGuid,\r
435 sizeof (EFI_GUID)\r
436 );\r
437 Status = EFI_SUCCESS;\r
438 } else {\r
439 Status = EFI_BUFFER_TOO_SMALL;\r
440 }\r
441\r
442 *VariableNameSize = VarNameSize;\r
443 return Status;\r
444 }\r
445 }\r
446 }\r
447\r
448 return EFI_NOT_FOUND;\r
449}\r
450\r
451EFI_STATUS\r
452EFIAPI\r
453SetVariable (\r
454 IN CHAR16 *VariableName,\r
455 IN EFI_GUID *VendorGuid,\r
456 IN UINT32 Attributes,\r
457 IN UINTN DataSize,\r
458 IN VOID *Data,\r
459 IN VARIABLE_GLOBAL *Global,\r
460 IN UINTN *VolatileOffset,\r
461 IN UINTN *NonVolatileOffset,\r
462 IN UINT32 Instance\r
463 )\r
464/*++\r
465\r
466Routine Description:\r
467\r
468 This code sets variable in storage blocks (Volatile or Non-Volatile)\r
469\r
470Arguments:\r
471\r
472 VariableName Name of Variable to be found\r
473 VendorGuid Variable vendor GUID\r
474 Attributes Attribute value of the variable found\r
475 DataSize Size of Data found. If size is less than the\r
476 data, this value contains the required size.\r
477 Data Data pointer\r
478 Global Pointer to VARIABLE_GLOBAL structure\r
479 VolatileOffset The offset of last volatile variable\r
480 NonVolatileOffset The offset of last non-volatile variable\r
481 Instance Instance of the Firmware Volume.\r
482\r
483Returns:\r
484\r
485 EFI STATUS\r
486\r
487--*/\r
488{\r
489 VARIABLE_POINTER_TRACK Variable;\r
490 EFI_STATUS Status;\r
491 VARIABLE_HEADER *NextVariable;\r
492 UINTN VarNameSize;\r
493 UINTN VarNameOffset;\r
494 UINTN VarDataOffset;\r
495 UINTN VarSize;\r
496\r
497 if (VariableName == NULL || VariableName[0] == 0 || VendorGuid == NULL) {\r
498 return EFI_INVALID_PARAMETER;\r
499 }\r
500\r
501 Status = FindVariable (VariableName, VendorGuid, &Variable, Global);\r
502\r
503 if (Status == EFI_INVALID_PARAMETER) {\r
504 return Status;\r
505 }\r
506 //\r
507 // The size of the VariableName, including the Unicode Null in bytes plus\r
508 // the DataSize is limited to maximum size of MAX_VARIABLE_SIZE (1024) bytes.\r
509 //\r
510 else if (sizeof (VARIABLE_HEADER) + (ArrayLength (VariableName) + DataSize) > MAX_VARIABLE_SIZE) {\r
511 return EFI_INVALID_PARAMETER;\r
512 }\r
513 //\r
514 // Make sure if runtime bit is set, boot service bit is set also\r
515 //\r
516 else if ((Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == EFI_VARIABLE_RUNTIME_ACCESS\r
517 ) {\r
518 return EFI_INVALID_PARAMETER;\r
519 }\r
520 //\r
521 // Runtime but Attribute is not Runtime\r
522 //\r
523 else if (EfiAtRuntime () && Attributes && !(Attributes & EFI_VARIABLE_RUNTIME_ACCESS)) {\r
524 return EFI_INVALID_PARAMETER;\r
525 }\r
526 //\r
527 // Cannot set volatile variable in Runtime\r
528 //\r
529 else if (EfiAtRuntime () && Attributes && !(Attributes & EFI_VARIABLE_NON_VOLATILE)) {\r
530 return EFI_INVALID_PARAMETER;\r
531 }\r
532 //\r
533 // Setting a data variable with no access, or zero DataSize attributes\r
534 // specified causes it to be deleted.\r
535 //\r
536 else if (DataSize == 0 || Attributes == 0) {\r
537 if (!EFI_ERROR (Status)) {\r
538 Variable.CurrPtr->State &= VAR_DELETED;\r
539 return EFI_SUCCESS;\r
540 }\r
541\r
542 return EFI_NOT_FOUND;\r
543 } else {\r
544 if (!EFI_ERROR (Status)) {\r
545 //\r
546 // If the variable is marked valid and the same data has been passed in\r
547 // then return to the caller immediately.\r
548 //\r
549 if (Variable.CurrPtr->DataSize == DataSize &&\r
550 !CompareMem (Data, GetVariableDataPtr (Variable.CurrPtr), DataSize)\r
551 ) {\r
552 return EFI_SUCCESS;\r
553 } else if (Variable.CurrPtr->State == VAR_ADDED) {\r
554 //\r
555 // Mark the old variable as in delete transition\r
556 //\r
557 Variable.CurrPtr->State &= VAR_IN_DELETED_TRANSITION;\r
558 }\r
559 }\r
560 //\r
561 // Create a new variable and copy the data.\r
562 //\r
563 VarNameOffset = sizeof (VARIABLE_HEADER);\r
564 VarNameSize = ArrayLength (VariableName);\r
09d4dd14 565 VarDataOffset = VarNameOffset + VarNameSize + GET_PAD_SIZE (VarNameSize);\r
566 VarSize = VarDataOffset + DataSize + GET_PAD_SIZE (DataSize);\r
878ddf1f 567\r
568 if (Attributes & EFI_VARIABLE_NON_VOLATILE) {\r
569 if ((UINT32) (VarSize +*NonVolatileOffset) >\r
570 ((VARIABLE_STORE_HEADER *) ((UINTN) (Global->NonVolatileVariableBase)))->Size\r
571 ) {\r
572 return EFI_OUT_OF_RESOURCES;\r
573 }\r
574\r
575 NextVariable = (VARIABLE_HEADER *) (UINT8 *) (*NonVolatileOffset + (UINTN) Global->NonVolatileVariableBase);\r
576 *NonVolatileOffset = *NonVolatileOffset + VarSize;\r
577 } else {\r
578 if (EfiAtRuntime ()) {\r
579 return EFI_INVALID_PARAMETER;\r
580 }\r
581\r
582 if ((UINT32) (VarSize +*VolatileOffset) >\r
583 ((VARIABLE_STORE_HEADER *) ((UINTN) (Global->VolatileVariableBase)))->Size\r
584 ) {\r
585 return EFI_OUT_OF_RESOURCES;\r
586 }\r
587\r
588 NextVariable = (VARIABLE_HEADER *) (UINT8 *) (*VolatileOffset + (UINTN) Global->VolatileVariableBase);\r
589 *VolatileOffset = *VolatileOffset + VarSize;\r
590 }\r
591\r
592 NextVariable->StartId = VARIABLE_DATA;\r
593 NextVariable->Attributes = Attributes;\r
594 NextVariable->State = VAR_ADDED;\r
595 NextVariable->Reserved = 0;\r
596\r
597 //\r
598 // There will be pad bytes after Data, the NextVariable->NameSize and\r
599 // NextVariable->NameSize should not include pad size so that variable\r
600 // service can get actual size in GetVariable\r
601 //\r
602 NextVariable->NameSize = (UINT32)VarNameSize;\r
603 NextVariable->DataSize = (UINT32)DataSize;\r
604\r
605 CopyMem (&NextVariable->VendorGuid, VendorGuid, sizeof (EFI_GUID));\r
606 CopyMem (\r
607 (UINT8 *) ((UINTN) NextVariable + VarNameOffset),\r
608 VariableName,\r
609 VarNameSize\r
610 );\r
611 CopyMem (\r
612 (UINT8 *) ((UINTN) NextVariable + VarDataOffset),\r
613 Data,\r
614 DataSize\r
615 );\r
616\r
617 //\r
618 // Mark the old variable as deleted\r
619 //\r
620 if (!EFI_ERROR (Status)) {\r
621 Variable.CurrPtr->State &= VAR_DELETED;\r
622 }\r
623 }\r
624\r
625 return EFI_SUCCESS;\r
626}\r
627\r
045f4521 628#if (EFI_SPECIFICATION_VERSION >= 0x00020000)\r
629EFI_STATUS\r
630EFIAPI\r
631QueryVariableInfo (\r
632 IN UINT32 Attributes,\r
633 OUT UINT64 *MaximumVariableStorageSize,\r
634 OUT UINT64 *RemainingVariableStorageSize,\r
635 OUT UINT64 *MaximumVariableSize,\r
636 IN VARIABLE_GLOBAL *Global,\r
637 IN UINT32 Instance\r
638 )\r
639/*++\r
640\r
641Routine Description:\r
642\r
643 This code returns information about the EFI variables.\r
644\r
645Arguments:\r
646\r
09d4dd14 647 Attributes Attributes bitmask to specify the type of variables\r
045f4521 648 on which to return information.\r
649 MaximumVariableStorageSize Pointer to the maximum size of the storage space available\r
650 for the EFI variables associated with the attributes specified.\r
09d4dd14 651 RemainingVariableStorageSize Pointer to the remaining size of the storage space available\r
045f4521 652 for the EFI variables associated with the attributes specified.\r
653 MaximumVariableSize Pointer to the maximum size of the individual EFI variables\r
654 associated with the attributes specified.\r
655 Global Pointer to VARIABLE_GLOBAL structure.\r
656 Instance Instance of the Firmware Volume.\r
657\r
658Returns:\r
659\r
660 EFI STATUS\r
661 EFI_INVALID_PARAMETER - An invalid combination of attribute bits was supplied.\r
662 EFI_SUCCESS - Query successfully.\r
663 EFI_UNSUPPORTED - The attribute is not supported on this platform.\r
664\r
665--*/\r
666{\r
667 VARIABLE_HEADER *Variable;\r
668 VARIABLE_HEADER *NextVariable;\r
669 UINT64 VariableSize;\r
670 VARIABLE_STORE_HEADER *VariableStoreHeader;\r
09d4dd14 671\r
045f4521 672 if(MaximumVariableStorageSize == NULL || RemainingVariableStorageSize == NULL || MaximumVariableSize == NULL) {\r
673 return EFI_INVALID_PARAMETER;\r
674 }\r
675\r
676 if((Attributes & (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS)) == 0) {\r
677 //\r
678 // Make sure the Attributes combination is supported by the platform.\r
679 //\r
680 return EFI_UNSUPPORTED;\r
681 } else if ((Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == EFI_VARIABLE_RUNTIME_ACCESS) {\r
682 //\r
683 // Make sure if runtime bit is set, boot service bit is set also.\r
684 //\r
685 return EFI_INVALID_PARAMETER;\r
686 } else if (EfiAtRuntime () && !(Attributes & EFI_VARIABLE_RUNTIME_ACCESS)) {\r
687 //\r
688 // Make sure RT Attribute is set if we are in Runtime phase.\r
689 //\r
690 return EFI_INVALID_PARAMETER;\r
691 }\r
692\r
693 if((Attributes & EFI_VARIABLE_NON_VOLATILE) == 0) {\r
694 //\r
695 // Query is Volatile related.\r
696 //\r
09d4dd14 697 VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINTN) Global->VolatileVariableBase);\r
045f4521 698 } else {\r
699 //\r
700 // Query is Non-Volatile related.\r
701 //\r
702 VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINTN) Global->NonVolatileVariableBase);\r
703 }\r
704\r
705 //\r
09d4dd14 706 // Now let's fill *MaximumVariableStorageSize *RemainingVariableStorageSize\r
045f4521 707 // with the storage size (excluding the storage header size)\r
708 //\r
709 *MaximumVariableStorageSize = VariableStoreHeader->Size - sizeof (VARIABLE_STORE_HEADER);\r
710 *RemainingVariableStorageSize = VariableStoreHeader->Size - sizeof (VARIABLE_STORE_HEADER);\r
711\r
712 //\r
09d4dd14 713 // Let *MaximumVariableSize be MAX_VARIABLE_SIZE\r
045f4521 714 //\r
715 *MaximumVariableSize = MAX_VARIABLE_SIZE;\r
716\r
717 //\r
718 // Point to the starting address of the variables.\r
719 //\r
720 Variable = (VARIABLE_HEADER *) (VariableStoreHeader + 1);\r
721\r
722 //\r
723 // Now walk through the related variable store.\r
724 //\r
725 while (Variable < GetEndPointer (VariableStoreHeader)) {\r
726 if (Variable->StartId != VARIABLE_DATA) {\r
727 break;\r
728 }\r
729\r
730 NextVariable = (VARIABLE_HEADER *) (GetVariableDataPtr (Variable) + Variable->DataSize + GET_PAD_SIZE (Variable->DataSize));\r
731 VariableSize = (UINT64) (UINTN) NextVariable - (UINT64) (UINTN) Variable;\r
732\r
733 if (Variable->State == VAR_ADDED) {\r
734 *RemainingVariableStorageSize -= VariableSize;\r
735 }\r
736\r
737 //\r
738 // Go to the next one.\r
739 //\r
740 Variable = NextVariable;\r
741 }\r
742\r
743 return EFI_SUCCESS;\r
744}\r
745#endif\r
746\r
878ddf1f 747EFI_STATUS\r
748EFIAPI\r
749InitializeVariableStore (\r
750 OUT EFI_PHYSICAL_ADDRESS *VariableBase,\r
751 OUT UINTN *LastVariableOffset\r
752 )\r
753/*++\r
754\r
755Routine Description:\r
756 This function initializes variable store\r
757\r
758Arguments:\r
759\r
760Returns:\r
761\r
762--*/\r
763{\r
764 VARIABLE_STORE_HEADER *VariableStore;\r
765\r
766 //\r
767 // Allocate memory for volatile variable store\r
768 //\r
769 VariableStore = (VARIABLE_STORE_HEADER *) AllocateRuntimePool (\r
770 VARIABLE_STORE_SIZE\r
771 );\r
772 if (NULL == VariableStore) {\r
773 return EFI_OUT_OF_RESOURCES;\r
774 }\r
775\r
776 SetMem (VariableStore, VARIABLE_STORE_SIZE, 0xff);\r
777\r
778 //\r
779 // Variable Specific Data\r
780 //\r
781 *VariableBase = (EFI_PHYSICAL_ADDRESS) (UINTN) VariableStore;\r
782 *LastVariableOffset = sizeof (VARIABLE_STORE_HEADER);\r
783\r
784 VariableStore->Signature = VARIABLE_STORE_SIGNATURE;\r
785 VariableStore->Size = VARIABLE_STORE_SIZE;\r
786 VariableStore->Format = VARIABLE_STORE_FORMATTED;\r
787 VariableStore->State = VARIABLE_STORE_HEALTHY;\r
788 VariableStore->Reserved = 0;\r
789 VariableStore->Reserved1 = 0;\r
790\r
791 return EFI_SUCCESS;\r
792}\r
793\r
794EFI_STATUS\r
795EFIAPI\r
796VariableCommonInitialize (\r
797 IN EFI_HANDLE ImageHandle,\r
798 IN EFI_SYSTEM_TABLE *SystemTable\r
799 )\r
800/*++\r
801\r
802Routine Description:\r
803 This function does common initialization for variable services\r
804\r
805Arguments:\r
806\r
807Returns:\r
808\r
809--*/\r
810{\r
811 EFI_STATUS Status;\r
812\r
813 //\r
814 // Allocate memory for mVariableModuleGlobal\r
815 //\r
816 mVariableModuleGlobal = (ESAL_VARIABLE_GLOBAL *) AllocateRuntimePool (\r
817 sizeof (ESAL_VARIABLE_GLOBAL)\r
09d4dd14 818 );\r
878ddf1f 819 if (NULL == mVariableModuleGlobal) {\r
820 return EFI_OUT_OF_RESOURCES;\r
821 }\r
822 //\r
823 // Intialize volatile variable store\r
824 //\r
825 Status = InitializeVariableStore (\r
826 &mVariableModuleGlobal->VariableBase[Physical].VolatileVariableBase,\r
827 &mVariableModuleGlobal->VolatileLastVariableOffset\r
828 );\r
829\r
830 if (EFI_ERROR (Status)) {\r
831 return Status;\r
832 }\r
833 //\r
834 // Intialize non volatile variable store\r
835 //\r
836 Status = InitializeVariableStore (\r
837 &mVariableModuleGlobal->VariableBase[Physical].NonVolatileVariableBase,\r
838 &mVariableModuleGlobal->NonVolatileLastVariableOffset\r
839 );\r
840\r
841 return Status;\r
842}\r