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