]> git.proxmox.com Git - mirror_edk2.git/blame - 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
878ddf1f 1/*++\r
2\r
6ed71dcc 3Copyright (c) 2006 - 2007, Intel Corporation\r
09d4dd14 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
6ed71dcc 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
657579af 34STATIC\r
6ed71dcc 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
657579af 50STATIC\r
6ed71dcc 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
1cc8ee78 62STATIC\r
878ddf1f 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
1cc8ee78 99STATIC\r
878ddf1f 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
09d4dd14 127 return (UINT8 *) ((UINTN) GET_VARIABLE_NAME_PTR (Variable) + Variable->NameSize + GET_PAD_SIZE (Variable->NameSize));\r
878ddf1f 128}\r
129\r
1cc8ee78 130STATIC\r
878ddf1f 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
1cc8ee78 171STATIC\r
878ddf1f 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
1cc8ee78 199STATIC\r
878ddf1f 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
6ed71dcc 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
878ddf1f 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
6ed71dcc 336 goto Done;\r
878ddf1f 337 }\r
338 //\r
339 // Get data size\r
340 //\r
341 VarDataSize = Variable.CurrPtr->DataSize;\r
342 if (*DataSize >= VarDataSize) {\r
35d02d76 343 if (Data == NULL) {\r
6ed71dcc 344 Status = EFI_INVALID_PARAMETER;\r
345 goto Done;\r
35d02d76 346 }\r
347\r
878ddf1f 348 CopyMem (Data, GetVariableDataPtr (Variable.CurrPtr), VarDataSize);\r
35d02d76 349 if (Attributes != NULL) {\r
878ddf1f 350 *Attributes = Variable.CurrPtr->Attributes;\r
351 }\r
352\r
353 *DataSize = VarDataSize;\r
6ed71dcc 354 Status = EFI_SUCCESS;\r
355 goto Done;\r
878ddf1f 356 } else {\r
357 *DataSize = VarDataSize;\r
6ed71dcc 358 Status = EFI_BUFFER_TOO_SMALL;\r
359 goto Done;\r
878ddf1f 360 }\r
6ed71dcc 361\r
362Done:\r
363 ReleaseLockOnlyAtBootTime (&Global->VariableServicesLock);\r
364 return Status;\r
878ddf1f 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
3820a171 400 if (VariableNameSize == NULL || VariableName == NULL || VendorGuid == NULL) {\r
878ddf1f 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
6ed71dcc 407 goto Done;\r
878ddf1f 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
6ed71dcc 427 Status = EFI_NOT_FOUND;\r
428 goto Done;\r
878ddf1f 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
6ed71dcc 459 goto Done;\r
878ddf1f 460 }\r
461 }\r
462 }\r
463\r
6ed71dcc 464Done:\r
465 ReleaseLockOnlyAtBootTime (&Global->VariableServicesLock);\r
466 return Status;\r
467 \r
878ddf1f 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
6ed71dcc 523 goto Done;\r
f53a0732 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
6ed71dcc 530 Status = EFI_WRITE_PROTECTED;\r
531 goto Done;\r
f53a0732 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
6ed71dcc 537 Status = EFI_INVALID_PARAMETER;\r
538 goto Done;\r
f53a0732 539 } else if ((Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == EFI_VARIABLE_RUNTIME_ACCESS\r
878ddf1f 540 ) {\r
f53a0732 541 //\r
542 // Make sure if runtime bit is set, boot service bit is set also\r
543 //\r
6ed71dcc 544 Status = EFI_INVALID_PARAMETER;\r
545 goto Done;\r
f53a0732 546 } else if (EfiAtRuntime () && Attributes && !(Attributes & EFI_VARIABLE_RUNTIME_ACCESS)) {\r
547 //\r
548 // Runtime but Attribute is not Runtime\r
549 //\r
6ed71dcc 550 Status = EFI_INVALID_PARAMETER;\r
551 goto Done;\r
f53a0732 552 } else if (EfiAtRuntime () && Attributes && !(Attributes & EFI_VARIABLE_NON_VOLATILE)) {\r
553 //\r
554 // Cannot set volatile variable in Runtime\r
555 //\r
6ed71dcc 556 Status = EFI_INVALID_PARAMETER;\r
557 goto Done;\r
f53a0732 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
878ddf1f 563 if (!EFI_ERROR (Status)) {\r
564 Variable.CurrPtr->State &= VAR_DELETED;\r
6ed71dcc 565 Status = EFI_SUCCESS;\r
566 goto Done;\r
878ddf1f 567 }\r
568\r
6ed71dcc 569 Status = EFI_NOT_FOUND;\r
570 goto Done;\r
878ddf1f 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
6ed71dcc 580 Status = EFI_SUCCESS;\r
581 goto Done;\r
878ddf1f 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
09d4dd14 594 VarDataOffset = VarNameOffset + VarNameSize + GET_PAD_SIZE (VarNameSize);\r
595 VarSize = VarDataOffset + DataSize + GET_PAD_SIZE (DataSize);\r
878ddf1f 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
6ed71dcc 601 Status = EFI_OUT_OF_RESOURCES;\r
602 goto Done;\r
878ddf1f 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
6ed71dcc 609 Status = EFI_INVALID_PARAMETER;\r
610 goto Done;\r
878ddf1f 611 }\r
612\r
613 if ((UINT32) (VarSize +*VolatileOffset) >\r
614 ((VARIABLE_STORE_HEADER *) ((UINTN) (Global->VolatileVariableBase)))->Size\r
615 ) {\r
6ed71dcc 616 Status = EFI_OUT_OF_RESOURCES;\r
617 goto Done;\r
878ddf1f 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
6ed71dcc 657 Status = EFI_SUCCESS;\r
658Done:\r
659 ReleaseLockOnlyAtBootTime (&Global->VariableServicesLock);\r
660 return Status;\r
878ddf1f 661}\r
662\r
045f4521 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
09d4dd14 682 Attributes Attributes bitmask to specify the type of variables\r
045f4521 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
09d4dd14 686 RemainingVariableStorageSize Pointer to the remaining size of the storage space available\r
045f4521 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
09d4dd14 706\r
045f4521 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
f53a0732 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
045f4521 731 }\r
732\r
6ed71dcc 733 AcquireLockOnlyAtBootTime(&Global->VariableServicesLock);\r
734 \r
045f4521 735 if((Attributes & EFI_VARIABLE_NON_VOLATILE) == 0) {\r
736 //\r
737 // Query is Volatile related.\r
738 //\r
09d4dd14 739 VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINTN) Global->VolatileVariableBase);\r
045f4521 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
09d4dd14 748 // Now let's fill *MaximumVariableStorageSize *RemainingVariableStorageSize\r
045f4521 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
09d4dd14 755 // Let *MaximumVariableSize be MAX_VARIABLE_SIZE\r
045f4521 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
6ed71dcc 785 ReleaseLockOnlyAtBootTime (&Global->VariableServicesLock);\r
045f4521 786 return EFI_SUCCESS;\r
787}\r
788#endif\r
789\r
1cc8ee78 790STATIC\r
878ddf1f 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
09d4dd14 862 );\r
878ddf1f 863 if (NULL == mVariableModuleGlobal) {\r
864 return EFI_OUT_OF_RESOURCES;\r
865 }\r
6ed71dcc 866\r
867 EfiInitializeLock(&mVariableModuleGlobal->VariableGlobal[Physical].VariableServicesLock, EFI_TPL_CALLBACK);\r
868 \r
878ddf1f 869 //\r
870 // Intialize volatile variable store\r
871 //\r
872 Status = InitializeVariableStore (\r
6ed71dcc 873 &mVariableModuleGlobal->VariableGlobal[Physical].VolatileVariableBase,\r
878ddf1f 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
6ed71dcc 884 &mVariableModuleGlobal->VariableGlobal[Physical].NonVolatileVariableBase,\r
878ddf1f 885 &mVariableModuleGlobal->NonVolatileLastVariableOffset\r
886 );\r
887\r
888 return Status;\r
889}\r