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