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