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