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