]> git.proxmox.com Git - mirror_edk2.git/blame - EdkModulePkg/Universal/Variable/RuntimeDxe/Variable.c
1. Removed #ifdef EDK_RELEASE_VERSION from all c files for all modules
[mirror_edk2.git] / EdkModulePkg / Universal / Variable / RuntimeDxe / Variable.c
CommitLineData
878ddf1f 1/*++\r
2\r
ce8bd86e 3Copyright (c) 2006 - 2007, Intel Corporation\r
4All rights reserved. This program and the accompanying materials\r
5are licensed and made available under the terms and conditions of the BSD License\r
6which accompanies this distribution. The full text of the license may be found at\r
7http://opensource.org/licenses/bsd-license.php\r
8\r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
878ddf1f 11\r
12Module Name:\r
13\r
14 Variable.c\r
15\r
16Abstract:\r
17\r
3681d193 18Revision History\r
878ddf1f 19\r
20--*/\r
21\r
22#include "Variable.h"\r
23#include "reclaim.h"\r
24\r
25//\r
26// Don't use module globals after the SetVirtualAddress map is signaled\r
27//\r
28ESAL_VARIABLE_GLOBAL *mVariableModuleGlobal;\r
29\r
6ed71dcc 30//\r
ce8bd86e 31// This is a temperary function which will be removed\r
6ed71dcc 32// when EfiAcquireLock in UefiLib can handle the\r
33// the call in UEFI Runtimer driver in RT phase.\r
34//\r
657579af 35STATIC\r
6ed71dcc 36VOID\r
37AcquireLockOnlyAtBootTime (\r
38 IN EFI_LOCK *Lock\r
39 )\r
40{\r
41 if (!EfiAtRuntime ()) {\r
42 EfiAcquireLock (Lock);\r
43 }\r
44}\r
45\r
46//\r
ce8bd86e 47// This is a temperary function which will be removed\r
6ed71dcc 48// when EfiAcquireLock in UefiLib can handle the\r
49// the call in UEFI Runtimer driver in RT phase.\r
50//\r
657579af 51STATIC\r
6ed71dcc 52VOID\r
53ReleaseLockOnlyAtBootTime (\r
54 IN EFI_LOCK *Lock\r
55 )\r
56{\r
57 if (!EfiAtRuntime ()) {\r
58 EfiReleaseLock (Lock);\r
59 }\r
60}\r
61\r
1cc8ee78 62STATIC\r
878ddf1f 63BOOLEAN\r
64EFIAPI\r
65IsValidVariableHeader (\r
66 IN VARIABLE_HEADER *Variable\r
67 )\r
68/*++\r
69\r
70Routine Description:\r
71\r
72 This code checks if variable header is valid or not.\r
73\r
74Arguments:\r
75 Variable Pointer to the Variable Header.\r
76\r
77Returns:\r
78 TRUE Variable header is valid.\r
79 FALSE Variable header is not valid.\r
80\r
81--*/\r
82{\r
83 if (Variable == NULL ||\r
84 Variable->StartId != VARIABLE_DATA ||\r
85 (sizeof (VARIABLE_HEADER) + Variable->NameSize + Variable->DataSize) > MAX_VARIABLE_SIZE\r
86 ) {\r
87 return FALSE;\r
88 }\r
89\r
90 return TRUE;\r
91}\r
92\r
1cc8ee78 93STATIC\r
878ddf1f 94EFI_STATUS\r
95EFIAPI\r
96UpdateVariableStore (\r
97 IN VARIABLE_GLOBAL *Global,\r
98 IN BOOLEAN Volatile,\r
99 IN BOOLEAN SetByIndex,\r
100 IN UINTN Instance,\r
101 IN UINTN DataPtrIndex,\r
102 IN UINT32 DataSize,\r
103 IN UINT8 *Buffer\r
104 )\r
105/*++\r
106\r
107Routine Description:\r
108\r
109 This function writes data to the FWH at the correct LBA even if the LBAs\r
110 are fragmented.\r
111\r
112Arguments:\r
113\r
114 Global Pointer to VARAIBLE_GLOBAL structure\r
115 Volatile If the Variable is Volatile or Non-Volatile\r
116 SetByIndex TRUE: Target pointer is given as index\r
117 FALSE: Target pointer is absolute\r
118 Instance Instance of FV Block services\r
119 DataPtrIndex Pointer to the Data from the end of VARIABLE_STORE_HEADER\r
120 structure\r
121 DataSize Size of data to be written.\r
122 Buffer Pointer to the buffer from which data is written\r
123\r
124Returns:\r
125\r
3681d193 126 EFI STATUS\r
878ddf1f 127\r
128--*/\r
129{\r
130 EFI_FV_BLOCK_MAP_ENTRY *PtrBlockMapEntry;\r
131 UINTN BlockIndex2;\r
132 UINTN LinearOffset;\r
133 UINTN CurrWriteSize;\r
134 UINTN CurrWritePtr;\r
135 UINT8 *CurrBuffer;\r
136 EFI_LBA LbaNumber;\r
137 UINTN Size;\r
138 EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;\r
139 VARIABLE_STORE_HEADER *VolatileBase;\r
140 EFI_PHYSICAL_ADDRESS FvVolHdr;\r
141 EFI_PHYSICAL_ADDRESS DataPtr;\r
142 EFI_STATUS Status;\r
143\r
144 FwVolHeader = NULL;\r
145 DataPtr = DataPtrIndex;\r
146\r
147 //\r
148 // Check if the Data is Volatile\r
149 //\r
150 if (!Volatile) {\r
151 EfiFvbGetPhysicalAddress (Instance, &FvVolHdr);\r
152 FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) FvVolHdr);\r
153 //\r
154 // Data Pointer should point to the actual Address where data is to be\r
155 // written\r
156 //\r
157 if (SetByIndex) {\r
158 DataPtr += Global->NonVolatileVariableBase;\r
159 }\r
160\r
161 if ((DataPtr + DataSize) >= ((EFI_PHYSICAL_ADDRESS) (UINTN) ((UINT8 *) FwVolHeader + FwVolHeader->FvLength))) {\r
162 return EFI_INVALID_PARAMETER;\r
163 }\r
164 } else {\r
165 //\r
166 // Data Pointer should point to the actual Address where data is to be\r
167 // written\r
168 //\r
169 VolatileBase = (VARIABLE_STORE_HEADER *) ((UINTN) Global->VolatileVariableBase);\r
170 if (SetByIndex) {\r
171 DataPtr += Global->VolatileVariableBase;\r
172 }\r
173\r
174 if ((DataPtr + DataSize) >= ((UINTN) ((UINT8 *) VolatileBase + VolatileBase->Size))) {\r
175 return EFI_INVALID_PARAMETER;\r
176 }\r
3681d193 177 }\r
178 //\r
179 // If Volatile Variable just do a simple mem copy.\r
180 //\r
181 if (Volatile) {\r
878ddf1f 182 CopyMem ((UINT8 *) ((UINTN) DataPtr), Buffer, DataSize);\r
183 return EFI_SUCCESS;\r
184 }\r
185 //\r
186 // If we are here we are dealing with Non-Volatile Variables\r
187 //\r
188 LinearOffset = (UINTN) FwVolHeader;\r
189 CurrWritePtr = (UINTN) DataPtr;\r
190 CurrWriteSize = DataSize;\r
191 CurrBuffer = Buffer;\r
192 LbaNumber = 0;\r
193\r
194 if (CurrWritePtr < LinearOffset) {\r
195 return EFI_INVALID_PARAMETER;\r
196 }\r
197\r
198 for (PtrBlockMapEntry = FwVolHeader->FvBlockMap; PtrBlockMapEntry->NumBlocks != 0; PtrBlockMapEntry++) {\r
199 for (BlockIndex2 = 0; BlockIndex2 < PtrBlockMapEntry->NumBlocks; BlockIndex2++) {\r
200 //\r
201 // Check to see if the Variable Writes are spanning through multiple\r
202 // blocks.\r
203 //\r
204 if ((CurrWritePtr >= LinearOffset) && (CurrWritePtr < LinearOffset + PtrBlockMapEntry->BlockLength)) {\r
205 if ((CurrWritePtr + CurrWriteSize) <= (LinearOffset + PtrBlockMapEntry->BlockLength)) {\r
206 Status = EfiFvbWriteBlock (\r
207 Instance,\r
208 LbaNumber,\r
209 (UINTN) (CurrWritePtr - LinearOffset),\r
210 &CurrWriteSize,\r
211 CurrBuffer\r
212 );\r
3681d193 213 if (EFI_ERROR (Status)) {\r
214 return Status;\r
215 }\r
878ddf1f 216 } else {\r
217 Size = (UINT32) (LinearOffset + PtrBlockMapEntry->BlockLength - CurrWritePtr);\r
218 Status = EfiFvbWriteBlock (\r
219 Instance,\r
220 LbaNumber,\r
221 (UINTN) (CurrWritePtr - LinearOffset),\r
222 &Size,\r
223 CurrBuffer\r
224 );\r
225 if (EFI_ERROR (Status)) {\r
226 return Status;\r
227 }\r
228\r
229 CurrWritePtr = LinearOffset + PtrBlockMapEntry->BlockLength;\r
230 CurrBuffer = CurrBuffer + Size;\r
231 CurrWriteSize = CurrWriteSize - Size;\r
232 }\r
233 }\r
234\r
235 LinearOffset += PtrBlockMapEntry->BlockLength;\r
236 LbaNumber++;\r
237 }\r
238 }\r
239\r
240 return EFI_SUCCESS;\r
241}\r
242\r
1cc8ee78 243STATIC\r
878ddf1f 244VARIABLE_STORE_STATUS\r
245EFIAPI\r
246GetVariableStoreStatus (\r
247 IN VARIABLE_STORE_HEADER *VarStoreHeader\r
248 )\r
249/*++\r
250\r
251Routine Description:\r
252\r
253 This code gets the current status of Variable Store.\r
254\r
255Arguments:\r
256\r
257 VarStoreHeader Pointer to the Variable Store Header.\r
258\r
259Returns:\r
260\r
261 EfiRaw Variable store status is raw\r
262 EfiValid Variable store status is valid\r
ce8bd86e 263 EfiInvalid Variable store status is invalid\r
878ddf1f 264\r
265--*/\r
266{\r
267 if (VarStoreHeader->Signature == VARIABLE_STORE_SIGNATURE &&\r
268 VarStoreHeader->Format == VARIABLE_STORE_FORMATTED &&\r
269 VarStoreHeader->State == VARIABLE_STORE_HEALTHY\r
270 ) {\r
271\r
272 return EfiValid;\r
273 } else if (VarStoreHeader->Signature == 0xffffffff &&\r
274 VarStoreHeader->Size == 0xffffffff &&\r
275 VarStoreHeader->Format == 0xff &&\r
276 VarStoreHeader->State == 0xff\r
277 ) {\r
278\r
279 return EfiRaw;\r
280 } else {\r
281 return EfiInvalid;\r
282 }\r
283}\r
284\r
1cc8ee78 285STATIC\r
878ddf1f 286UINT8 *\r
287EFIAPI\r
288GetVariableDataPtr (\r
289 IN VARIABLE_HEADER *Variable\r
290 )\r
291/*++\r
292\r
293Routine Description:\r
294\r
295 This code gets the pointer to the variable data.\r
296\r
297Arguments:\r
298\r
299 Variable Pointer to the Variable Header.\r
300\r
301Returns:\r
302\r
303 UINT8* Pointer to Variable Data\r
304\r
305--*/\r
306{\r
307 //\r
308 // Be careful about pad size for alignment\r
309 //\r
310 return (UINT8 *) ((UINTN) GET_VARIABLE_NAME_PTR (Variable) + Variable->NameSize + GET_PAD_SIZE (Variable->NameSize));\r
311}\r
312\r
1cc8ee78 313STATIC\r
878ddf1f 314VARIABLE_HEADER *\r
315EFIAPI\r
316GetNextVariablePtr (\r
317 IN VARIABLE_HEADER *Variable\r
318 )\r
319/*++\r
320\r
321Routine Description:\r
322\r
323 This code gets the pointer to the next variable header.\r
324\r
325Arguments:\r
326\r
327 Variable Pointer to the Variable Header.\r
328\r
329Returns:\r
330\r
331 VARIABLE_HEADER* Pointer to next variable header.\r
332\r
333--*/\r
334{\r
335 if (!IsValidVariableHeader (Variable)) {\r
336 return NULL;\r
337 }\r
338 //\r
339 // Be careful about pad size for alignment\r
340 //\r
341 return (VARIABLE_HEADER *) ((UINTN) GetVariableDataPtr (Variable) + Variable->DataSize + GET_PAD_SIZE (Variable->DataSize));\r
342}\r
343\r
1cc8ee78 344STATIC\r
878ddf1f 345VARIABLE_HEADER *\r
346EFIAPI\r
347GetEndPointer (\r
348 IN VARIABLE_STORE_HEADER *VarStoreHeader\r
349 )\r
350/*++\r
351\r
352Routine Description:\r
353\r
354 This code gets the pointer to the last variable memory pointer byte\r
355\r
356Arguments:\r
357\r
358 VarStoreHeader Pointer to the Variable Store Header.\r
359\r
360Returns:\r
361\r
362 VARIABLE_HEADER* Pointer to last unavailable Variable Header\r
363\r
364--*/\r
365{\r
366 //\r
367 // The end of variable store\r
368 //\r
369 return (VARIABLE_HEADER *) ((UINTN) VarStoreHeader + VarStoreHeader->Size);\r
370}\r
371\r
1cc8ee78 372STATIC\r
878ddf1f 373EFI_STATUS\r
374EFIAPI\r
375Reclaim (\r
376 IN EFI_PHYSICAL_ADDRESS VariableBase,\r
377 OUT UINTN *LastVariableOffset,\r
378 IN BOOLEAN IsVolatile\r
379 )\r
380/*++\r
381\r
382Routine Description:\r
383\r
384 Variable store garbage collection and reclaim operation\r
385\r
386Arguments:\r
387\r
388 VariableBase Base address of variable store\r
389 LastVariableOffset Offset of last variable\r
390 IsVolatile The variable store is volatile or not,\r
391 if it is non-volatile, need FTW\r
392\r
393Returns:\r
394\r
395 EFI STATUS\r
396\r
397--*/\r
398{\r
399 VARIABLE_HEADER *Variable;\r
400 VARIABLE_HEADER *NextVariable;\r
401 VARIABLE_STORE_HEADER *VariableStoreHeader;\r
402 UINT8 *ValidBuffer;\r
403 UINTN ValidBufferSize;\r
404 UINTN VariableSize;\r
405 UINT8 *CurrPtr;\r
406 EFI_STATUS Status;\r
407\r
408 VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINTN) VariableBase);\r
409\r
410 //\r
411 // Start Pointers for the variable.\r
412 //\r
413 Variable = (VARIABLE_HEADER *) (VariableStoreHeader + 1);\r
414\r
415 ValidBufferSize = sizeof (VARIABLE_STORE_HEADER);\r
416\r
417 while (IsValidVariableHeader (Variable)) {\r
418 NextVariable = GetNextVariablePtr (Variable);\r
419 if (Variable->State == VAR_ADDED) {\r
420 VariableSize = (UINTN) NextVariable - (UINTN) Variable;\r
421 ValidBufferSize += VariableSize;\r
422 }\r
423\r
424 Variable = NextVariable;\r
425 }\r
426\r
427 Status = gBS->AllocatePool (\r
428 EfiBootServicesData,\r
429 ValidBufferSize,\r
430 (VOID **) &ValidBuffer\r
431 );\r
432 if (EFI_ERROR (Status)) {\r
433 return Status;\r
434 }\r
435\r
436 SetMem (ValidBuffer, ValidBufferSize, 0xff);\r
437\r
438 CurrPtr = ValidBuffer;\r
439\r
440 //\r
441 // Copy variable store header\r
442 //\r
443 CopyMem (CurrPtr, VariableStoreHeader, sizeof (VARIABLE_STORE_HEADER));\r
444 CurrPtr += sizeof (VARIABLE_STORE_HEADER);\r
445\r
446 //\r
447 // Start Pointers for the variable.\r
448 //\r
449 Variable = (VARIABLE_HEADER *) (VariableStoreHeader + 1);\r
450\r
451 while (IsValidVariableHeader (Variable)) {\r
452 NextVariable = GetNextVariablePtr (Variable);\r
453 if (Variable->State == VAR_ADDED) {\r
454 VariableSize = (UINTN) NextVariable - (UINTN) Variable;\r
455 CopyMem (CurrPtr, (UINT8 *) Variable, VariableSize);\r
456 CurrPtr += VariableSize;\r
457 }\r
458\r
459 Variable = NextVariable;\r
460 }\r
461\r
462 if (IsVolatile) {\r
463 //\r
464 // If volatile variable store, just copy valid buffer\r
465 //\r
466 SetMem ((UINT8 *) (UINTN) VariableBase, VariableStoreHeader->Size, 0xff);\r
467 CopyMem ((UINT8 *) (UINTN) VariableBase, ValidBuffer, ValidBufferSize);\r
468 *LastVariableOffset = ValidBufferSize;\r
469 Status = EFI_SUCCESS;\r
470 } else {\r
471 //\r
472 // If non-volatile variable store, perform FTW here.\r
473 //\r
474 Status = FtwVariableSpace (\r
475 VariableBase,\r
476 ValidBuffer,\r
477 ValidBufferSize\r
478 );\r
479 if (!EFI_ERROR (Status)) {\r
480 *LastVariableOffset = ValidBufferSize;\r
481 }\r
482 }\r
483\r
484 gBS->FreePool (ValidBuffer);\r
485\r
486 if (EFI_ERROR (Status)) {\r
487 *LastVariableOffset = 0;\r
488 }\r
489\r
490 return Status;\r
491}\r
492\r
1cc8ee78 493STATIC\r
878ddf1f 494EFI_STATUS\r
495EFIAPI\r
496FindVariable (\r
497 IN CHAR16 *VariableName,\r
498 IN EFI_GUID *VendorGuid,\r
499 OUT VARIABLE_POINTER_TRACK *PtrTrack,\r
500 IN VARIABLE_GLOBAL *Global\r
501 )\r
502/*++\r
503\r
504Routine Description:\r
505\r
506 This code finds variable in storage blocks (Volatile or Non-Volatile)\r
507\r
508Arguments:\r
509\r
510 VariableName Name of the variable to be found\r
511 VendorGuid Vendor GUID to be found.\r
512 PtrTrack Variable Track Pointer structure that contains\r
513 Variable Information.\r
514 Contains the pointer of Variable header.\r
515 Global VARIABLE_GLOBAL pointer\r
516\r
517Returns:\r
518\r
519 EFI STATUS\r
520\r
521--*/\r
522{\r
523 VARIABLE_HEADER *Variable[2];\r
524 VARIABLE_STORE_HEADER *VariableStoreHeader[2];\r
525 UINTN Index;\r
526\r
6ed71dcc 527 //\r
528 // We aquire the lock at the entry of FindVariable as GetVariable, GetNextVariableName\r
529 // SetVariable all call FindVariable at entry point. Please move "Aquire Lock" to\r
530 // the correct places if this assumption does not hold TRUE anymore.\r
531 //\r
532 AcquireLockOnlyAtBootTime(&Global->VariableServicesLock);\r
533\r
878ddf1f 534 //\r
535 // 0: Non-Volatile, 1: Volatile\r
536 //\r
537 VariableStoreHeader[0] = (VARIABLE_STORE_HEADER *) ((UINTN) Global->NonVolatileVariableBase);\r
538 VariableStoreHeader[1] = (VARIABLE_STORE_HEADER *) ((UINTN) Global->VolatileVariableBase);\r
539\r
540 //\r
541 // Start Pointers for the variable.\r
542 // Actual Data Pointer where data can be written.\r
543 //\r
544 Variable[0] = (VARIABLE_HEADER *) (VariableStoreHeader[0] + 1);\r
545 Variable[1] = (VARIABLE_HEADER *) (VariableStoreHeader[1] + 1);\r
546\r
547 if (VariableName[0] != 0 && VendorGuid == NULL) {\r
548 return EFI_INVALID_PARAMETER;\r
549 }\r
550 //\r
551 // Find the variable by walk through non-volatile and volatile variable store\r
552 //\r
553 for (Index = 0; Index < 2; Index++) {\r
554 PtrTrack->StartPtr = (VARIABLE_HEADER *) (VariableStoreHeader[Index] + 1);\r
555 PtrTrack->EndPtr = GetEndPointer (VariableStoreHeader[Index]);\r
556\r
557 while (IsValidVariableHeader (Variable[Index]) && (Variable[Index] <= GetEndPointer (VariableStoreHeader[Index]))) {\r
558 if (Variable[Index]->State == VAR_ADDED) {\r
559 if (!(EfiAtRuntime () && !(Variable[Index]->Attributes & EFI_VARIABLE_RUNTIME_ACCESS))) {\r
560 if (VariableName[0] == 0) {\r
561 PtrTrack->CurrPtr = Variable[Index];\r
562 PtrTrack->Volatile = (BOOLEAN) Index;\r
563 return EFI_SUCCESS;\r
564 } else {\r
565 if (CompareGuid (VendorGuid, &Variable[Index]->VendorGuid)) {\r
bb60dd97 566 if (!CompareMem (VariableName, GET_VARIABLE_NAME_PTR (Variable[Index]), Variable[Index]->NameSize)) {\r
878ddf1f 567 PtrTrack->CurrPtr = Variable[Index];\r
568 PtrTrack->Volatile = (BOOLEAN) Index;\r
569 return EFI_SUCCESS;\r
570 }\r
571 }\r
572 }\r
573 }\r
574 }\r
575\r
576 Variable[Index] = GetNextVariablePtr (Variable[Index]);\r
577 }\r
578 //\r
579 // While (...)\r
580 //\r
581 }\r
582 //\r
583 // for (...)\r
584 //\r
585 PtrTrack->CurrPtr = NULL;\r
586 return EFI_NOT_FOUND;\r
587}\r
588\r
589EFI_STATUS\r
590EFIAPI\r
591GetVariable (\r
592 IN CHAR16 *VariableName,\r
593 IN EFI_GUID * VendorGuid,\r
594 OUT UINT32 *Attributes OPTIONAL,\r
595 IN OUT UINTN *DataSize,\r
596 OUT VOID *Data,\r
597 IN VARIABLE_GLOBAL * Global,\r
598 IN UINT32 Instance\r
599 )\r
600/*++\r
601\r
602Routine Description:\r
603\r
604 This code finds variable in storage blocks (Volatile or Non-Volatile)\r
605\r
606Arguments:\r
607\r
608 VariableName Name of Variable to be found\r
609 VendorGuid Variable vendor GUID\r
610 Attributes OPTIONAL Attribute value of the variable found\r
611 DataSize Size of Data found. If size is less than the\r
612 data, this value contains the required size.\r
613 Data Data pointer\r
614 Global Pointer to VARIABLE_GLOBAL structure\r
615 Instance Instance of the Firmware Volume.\r
616\r
617Returns:\r
618\r
619 EFI STATUS\r
620\r
621--*/\r
622{\r
623 VARIABLE_POINTER_TRACK Variable;\r
624 UINTN VarDataSize;\r
625 EFI_STATUS Status;\r
626\r
627 if (VariableName == NULL || VendorGuid == NULL || DataSize == NULL) {\r
628 return EFI_INVALID_PARAMETER;\r
629 }\r
630 //\r
631 // Find existing variable\r
632 //\r
633 Status = FindVariable (VariableName, VendorGuid, &Variable, Global);\r
634\r
635 if (Variable.CurrPtr == NULL || EFI_ERROR (Status)) {\r
6ed71dcc 636 goto Done;\r
878ddf1f 637 }\r
638 //\r
639 // Get data size\r
640 //\r
641 VarDataSize = Variable.CurrPtr->DataSize;\r
642 if (*DataSize >= VarDataSize) {\r
643 if (Data == NULL) {\r
6ed71dcc 644 Status = EFI_INVALID_PARAMETER;\r
645 goto Done;\r
878ddf1f 646 }\r
647\r
648 CopyMem (Data, GetVariableDataPtr (Variable.CurrPtr), VarDataSize);\r
649 if (Attributes != NULL) {\r
650 *Attributes = Variable.CurrPtr->Attributes;\r
651 }\r
652\r
653 *DataSize = VarDataSize;\r
6ed71dcc 654 Status = EFI_SUCCESS;\r
655 goto Done;\r
878ddf1f 656 } else {\r
657 *DataSize = VarDataSize;\r
6ed71dcc 658 Status = EFI_BUFFER_TOO_SMALL;\r
659 goto Done;\r
878ddf1f 660 }\r
6ed71dcc 661\r
662Done:\r
663 ReleaseLockOnlyAtBootTime (&Global->VariableServicesLock);\r
664 return Status;\r
878ddf1f 665}\r
666\r
667EFI_STATUS\r
668EFIAPI\r
669GetNextVariableName (\r
670 IN OUT UINTN *VariableNameSize,\r
671 IN OUT CHAR16 *VariableName,\r
672 IN OUT EFI_GUID *VendorGuid,\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 Finds the Next available variable\r
681\r
682Arguments:\r
683\r
684 VariableNameSize Size of the variable\r
685 VariableName Pointer to variable name\r
686 VendorGuid Variable Vendor Guid\r
687 Global VARIABLE_GLOBAL structure pointer.\r
688 Instance FV instance\r
689\r
690Returns:\r
691\r
692 EFI STATUS\r
693\r
694--*/\r
695{\r
696 VARIABLE_POINTER_TRACK Variable;\r
697 UINTN VarNameSize;\r
698 EFI_STATUS Status;\r
699\r
700 if (VariableNameSize == NULL || VariableName == NULL || VendorGuid == NULL) {\r
701 return EFI_INVALID_PARAMETER;\r
702 }\r
703\r
704 Status = FindVariable (VariableName, VendorGuid, &Variable, Global);\r
705\r
706 if (Variable.CurrPtr == NULL || EFI_ERROR (Status)) {\r
6ed71dcc 707 goto Done;\r
878ddf1f 708 }\r
709\r
710 if (VariableName[0] != 0) {\r
711 //\r
712 // If variable name is not NULL, get next variable\r
713 //\r
714 Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);\r
715 }\r
716\r
717 while (TRUE) {\r
718 //\r
719 // If both volatile and non-volatile variable store are parsed,\r
720 // return not found\r
721 //\r
722 if (Variable.CurrPtr >= Variable.EndPtr || Variable.CurrPtr == NULL) {\r
723 Variable.Volatile = (BOOLEAN) (Variable.Volatile ^ ((BOOLEAN) 0x1));\r
724 if (Variable.Volatile) {\r
725 Variable.StartPtr = (VARIABLE_HEADER *) ((UINTN) (Global->VolatileVariableBase + sizeof (VARIABLE_STORE_HEADER)));\r
726 Variable.EndPtr = (VARIABLE_HEADER *) GetEndPointer ((VARIABLE_STORE_HEADER *) ((UINTN) Global->VolatileVariableBase));\r
727 } else {\r
6ed71dcc 728 Status = EFI_NOT_FOUND;\r
729 goto Done;\r
878ddf1f 730 }\r
731\r
732 Variable.CurrPtr = Variable.StartPtr;\r
733 if (!IsValidVariableHeader (Variable.CurrPtr)) {\r
734 continue;\r
735 }\r
736 }\r
737 //\r
738 // Variable is found\r
739 //\r
740 if (IsValidVariableHeader (Variable.CurrPtr) && Variable.CurrPtr->State == VAR_ADDED) {\r
741 if (!(EfiAtRuntime () && !(Variable.CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS))) {\r
742 VarNameSize = Variable.CurrPtr->NameSize;\r
743 if (VarNameSize <= *VariableNameSize) {\r
744 CopyMem (\r
745 VariableName,\r
746 GET_VARIABLE_NAME_PTR (Variable.CurrPtr),\r
747 VarNameSize\r
748 );\r
749 CopyMem (\r
750 VendorGuid,\r
751 &Variable.CurrPtr->VendorGuid,\r
752 sizeof (EFI_GUID)\r
753 );\r
754 Status = EFI_SUCCESS;\r
755 } else {\r
756 Status = EFI_BUFFER_TOO_SMALL;\r
757 }\r
758\r
759 *VariableNameSize = VarNameSize;\r
6ed71dcc 760 goto Done;\r
878ddf1f 761 }\r
762 }\r
763\r
764 Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);\r
765 }\r
766\r
6ed71dcc 767Done:\r
768 ReleaseLockOnlyAtBootTime (&Global->VariableServicesLock);\r
769 return Status;\r
878ddf1f 770}\r
771\r
772EFI_STATUS\r
773EFIAPI\r
774SetVariable (\r
775 IN CHAR16 *VariableName,\r
776 IN EFI_GUID *VendorGuid,\r
777 IN UINT32 Attributes,\r
778 IN UINTN DataSize,\r
779 IN VOID *Data,\r
780 IN VARIABLE_GLOBAL *Global,\r
781 IN UINTN *VolatileOffset,\r
782 IN UINTN *NonVolatileOffset,\r
783 IN UINT32 Instance\r
784 )\r
785/*++\r
786\r
787Routine Description:\r
788\r
789 This code sets variable in storage blocks (Volatile or Non-Volatile)\r
790\r
791Arguments:\r
792\r
793 VariableName Name of Variable to be found\r
794 VendorGuid Variable vendor GUID\r
795 Attributes Attribute value of the variable found\r
796 DataSize Size of Data found. If size is less than the\r
797 data, this value contains the required size.\r
798 Data Data pointer\r
799 Global Pointer to VARIABLE_GLOBAL structure\r
800 VolatileOffset The offset of last volatile variable\r
801 NonVolatileOffset The offset of last non-volatile variable\r
802 Instance Instance of the Firmware Volume.\r
803\r
804Returns:\r
805\r
806 EFI STATUS\r
807 EFI_INVALID_PARAMETER - Invalid parameter\r
808 EFI_SUCCESS - Set successfully\r
809 EFI_OUT_OF_RESOURCES - Resource not enough to set variable\r
810 EFI_NOT_FOUND - Not found\r
811\r
812--*/\r
813{\r
814 VARIABLE_POINTER_TRACK Variable;\r
815 EFI_STATUS Status;\r
816 VARIABLE_HEADER *NextVariable;\r
817 UINTN VarNameSize;\r
818 UINTN VarNameOffset;\r
819 UINTN VarDataOffset;\r
820 UINTN VarSize;\r
821 UINT8 State;\r
822 BOOLEAN Reclaimed;\r
823\r
824 Reclaimed = FALSE;\r
825\r
826 if (VariableName == NULL || VariableName[0] == 0 || VendorGuid == NULL) {\r
827 return EFI_INVALID_PARAMETER;\r
828 }\r
829\r
830 Status = FindVariable (VariableName, VendorGuid, &Variable, Global);\r
831\r
832 if (Status == EFI_INVALID_PARAMETER) {\r
6ed71dcc 833 goto Done;\r
f53a0732 834 } else if (!EFI_ERROR (Status) && Variable.Volatile && EfiAtRuntime()) {\r
835 //\r
ce8bd86e 836 // If EfiAtRuntime and the variable is Volatile and Runtime Access,\r
837 // the volatile is ReadOnly, and SetVariable should be aborted and\r
f53a0732 838 // return EFI_WRITE_PROTECTED.\r
839 //\r
6ed71dcc 840 Status = EFI_WRITE_PROTECTED;\r
841 goto Done;\r
bb60dd97 842 } else if (sizeof (VARIABLE_HEADER) + StrSize (VariableName) + DataSize > MAX_VARIABLE_SIZE) {\r
f53a0732 843 //\r
844 // The size of the VariableName, including the Unicode Null in bytes plus\r
845 // the DataSize is limited to maximum size of MAX_VARIABLE_SIZE (1024) bytes.\r
846 //\r
6ed71dcc 847 Status = EFI_INVALID_PARAMETER;\r
848 goto Done;\r
f53a0732 849 } else if (Attributes == EFI_VARIABLE_NON_VOLATILE) {\r
850 //\r
ce8bd86e 851 // Make sure not only EFI_VARIABLE_NON_VOLATILE is set\r
f53a0732 852 //\r
6ed71dcc 853 Status = EFI_INVALID_PARAMETER;\r
854 goto Done;\r
ce8bd86e 855 } else if ((Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) ==\r
f53a0732 856 EFI_VARIABLE_RUNTIME_ACCESS) {\r
857 //\r
858 // Make sure if runtime bit is set, boot service bit is set also\r
859 //\r
6ed71dcc 860 Status = EFI_INVALID_PARAMETER;\r
861 goto Done;\r
f53a0732 862 } else if (EfiAtRuntime () && Attributes && !(Attributes & EFI_VARIABLE_RUNTIME_ACCESS)) {\r
863 //\r
864 // Runtime but Attribute is not Runtime\r
865 //\r
6ed71dcc 866 Status = EFI_INVALID_PARAMETER;\r
867 goto Done;\r
f53a0732 868 } else if (EfiAtRuntime () && Attributes && !(Attributes & EFI_VARIABLE_NON_VOLATILE)) {\r
869 //\r
870 // Cannot set volatile variable in Runtime\r
871 //\r
6ed71dcc 872 Status = EFI_INVALID_PARAMETER;\r
873 goto Done;\r
f53a0732 874 } else if (DataSize == 0 || (Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == 0) {\r
875 //\r
876 // Setting a data variable with no access, or zero DataSize attributes\r
877 // specified causes it to be deleted.\r
878 //\r
878ddf1f 879 if (!EFI_ERROR (Status)) {\r
880 State = Variable.CurrPtr->State;\r
881 State &= VAR_DELETED;\r
882\r
883 Status = UpdateVariableStore (\r
884 Global,\r
885 Variable.Volatile,\r
886 FALSE,\r
887 Instance,\r
888 (UINTN) &Variable.CurrPtr->State,\r
889 sizeof (UINT8),\r
890 &State\r
891 );\r
892 if (EFI_ERROR (Status)) {\r
6ed71dcc 893 goto Done;\r
878ddf1f 894 }\r
895\r
6ed71dcc 896 Status = EFI_SUCCESS;\r
897 goto Done;\r
878ddf1f 898 }\r
899\r
6ed71dcc 900 Status = EFI_NOT_FOUND;\r
901 goto Done;\r
878ddf1f 902 } else {\r
903 if (!EFI_ERROR (Status)) {\r
904 //\r
905 // If the variable is marked valid and the same data has been passed in\r
906 // then return to the caller immediately.\r
907 //\r
908 if (Variable.CurrPtr->DataSize == DataSize &&\r
909 !CompareMem (Data, GetVariableDataPtr (Variable.CurrPtr), DataSize)\r
910 ) {\r
6ed71dcc 911 Status = EFI_SUCCESS;\r
912 goto Done;\r
878ddf1f 913 } else if (Variable.CurrPtr->State == VAR_ADDED) {\r
914 //\r
915 // Mark the old variable as in delete transition\r
916 //\r
917 State = Variable.CurrPtr->State;\r
918 State &= VAR_IN_DELETED_TRANSITION;\r
919\r
920 Status = UpdateVariableStore (\r
921 Global,\r
922 Variable.Volatile,\r
923 FALSE,\r
924 Instance,\r
925 (UINTN) &Variable.CurrPtr->State,\r
926 sizeof (UINT8),\r
927 &State\r
928 );\r
929 if (EFI_ERROR (Status)) {\r
6ed71dcc 930 goto Done;\r
878ddf1f 931 }\r
932 }\r
933 }\r
934 //\r
935 // Create a new variable and copy the data.\r
936 //\r
937 // Tricky part: Use scratch data area at the end of volatile variable store\r
938 // as a temporary storage.\r
939 //\r
940 NextVariable = GetEndPointer ((VARIABLE_STORE_HEADER *) ((UINTN) Global->VolatileVariableBase));\r
941\r
942 SetMem (NextVariable, SCRATCH_SIZE, 0xff);\r
943\r
944 NextVariable->StartId = VARIABLE_DATA;\r
945 NextVariable->Attributes = Attributes;\r
946 //\r
947 // NextVariable->State = VAR_ADDED;\r
948 //\r
949 NextVariable->Reserved = 0;\r
950 VarNameOffset = sizeof (VARIABLE_HEADER);\r
bb60dd97 951 VarNameSize = StrSize (VariableName);\r
878ddf1f 952 CopyMem (\r
953 (UINT8 *) ((UINTN) NextVariable + VarNameOffset),\r
954 VariableName,\r
955 VarNameSize\r
956 );\r
957 VarDataOffset = VarNameOffset + VarNameSize + GET_PAD_SIZE (VarNameSize);\r
958 CopyMem (\r
959 (UINT8 *) ((UINTN) NextVariable + VarDataOffset),\r
960 Data,\r
961 DataSize\r
962 );\r
963 CopyMem (&NextVariable->VendorGuid, VendorGuid, sizeof (EFI_GUID));\r
964 //\r
965 // There will be pad bytes after Data, the NextVariable->NameSize and\r
966 // NextVariable->DataSize should not include pad size so that variable\r
967 // service can get actual size in GetVariable\r
968 //\r
969 NextVariable->NameSize = (UINT32)VarNameSize;\r
970 NextVariable->DataSize = (UINT32)DataSize;\r
971\r
972 //\r
973 // The actual size of the variable that stores in storage should\r
974 // include pad size.\r
975 //\r
976 VarSize = VarDataOffset + DataSize + GET_PAD_SIZE (DataSize);\r
977 if (Attributes & EFI_VARIABLE_NON_VOLATILE) {\r
978 if ((UINT32) (VarSize +*NonVolatileOffset) >\r
979 ((VARIABLE_STORE_HEADER *) ((UINTN) (Global->NonVolatileVariableBase)))->Size\r
980 ) {\r
981 if (EfiAtRuntime ()) {\r
6ed71dcc 982 Status = EFI_OUT_OF_RESOURCES;\r
983 goto Done;\r
878ddf1f 984 }\r
985 //\r
986 // Perform garbage collection & reclaim operation\r
987 //\r
988 Status = Reclaim (Global->NonVolatileVariableBase, NonVolatileOffset, FALSE);\r
989 if (EFI_ERROR (Status)) {\r
6ed71dcc 990 goto Done;\r
878ddf1f 991 }\r
992 //\r
993 // If still no enough space, return out of resources\r
994 //\r
995 if ((UINT32) (VarSize +*NonVolatileOffset) >\r
996 ((VARIABLE_STORE_HEADER *) ((UINTN) (Global->NonVolatileVariableBase)))->Size\r
997 ) {\r
6ed71dcc 998 Status = EFI_OUT_OF_RESOURCES;\r
999 goto Done;\r
878ddf1f 1000 }\r
ce8bd86e 1001\r
878ddf1f 1002 Reclaimed = TRUE;\r
1003 }\r
1004 //\r
1005 // Three steps\r
1006 // 1. Write variable header\r
1007 // 2. Write variable data\r
1008 // 3. Set variable state to valid\r
1009 //\r
1010 //\r
1011 // Step 1:\r
1012 //\r
1013 Status = UpdateVariableStore (\r
1014 Global,\r
1015 FALSE,\r
1016 TRUE,\r
1017 Instance,\r
1018 *NonVolatileOffset,\r
1019 sizeof (VARIABLE_HEADER),\r
1020 (UINT8 *) NextVariable\r
1021 );\r
1022\r
1023 if (EFI_ERROR (Status)) {\r
6ed71dcc 1024 goto Done;\r
878ddf1f 1025 }\r
1026 //\r
1027 // Step 2:\r
1028 //\r
1029 Status = UpdateVariableStore (\r
1030 Global,\r
1031 FALSE,\r
1032 TRUE,\r
1033 Instance,\r
1034 *NonVolatileOffset + sizeof (VARIABLE_HEADER),\r
1035 (UINT32) VarSize - sizeof (VARIABLE_HEADER),\r
1036 (UINT8 *) NextVariable + sizeof (VARIABLE_HEADER)\r
1037 );\r
1038\r
1039 if (EFI_ERROR (Status)) {\r
6ed71dcc 1040 goto Done;\r
878ddf1f 1041 }\r
1042 //\r
1043 // Step 3:\r
1044 //\r
1045 NextVariable->State = VAR_ADDED;\r
1046 Status = UpdateVariableStore (\r
1047 Global,\r
1048 FALSE,\r
1049 TRUE,\r
1050 Instance,\r
1051 *NonVolatileOffset,\r
1052 sizeof (VARIABLE_HEADER),\r
1053 (UINT8 *) NextVariable\r
1054 );\r
1055\r
1056 if (EFI_ERROR (Status)) {\r
6ed71dcc 1057 goto Done;\r
878ddf1f 1058 }\r
1059\r
1060 *NonVolatileOffset = *NonVolatileOffset + VarSize;\r
1061\r
1062 } else {\r
1063 if (EfiAtRuntime ()) {\r
6ed71dcc 1064 Status = EFI_INVALID_PARAMETER;\r
1065 goto Done;\r
878ddf1f 1066 }\r
1067\r
1068 if ((UINT32) (VarSize +*VolatileOffset) >\r
1069 ((VARIABLE_STORE_HEADER *) ((UINTN) (Global->VolatileVariableBase)))->Size\r
1070 ) {\r
1071 //\r
1072 // Perform garbage collection & reclaim operation\r
1073 //\r
1074 Status = Reclaim (Global->VolatileVariableBase, VolatileOffset, TRUE);\r
1075 if (EFI_ERROR (Status)) {\r
6ed71dcc 1076 goto Done;\r
878ddf1f 1077 }\r
1078 //\r
1079 // If still no enough space, return out of resources\r
1080 //\r
1081 if ((UINT32) (VarSize +*VolatileOffset) >\r
1082 ((VARIABLE_STORE_HEADER *) ((UINTN) (Global->VolatileVariableBase)))->Size\r
1083 ) {\r
6ed71dcc 1084 Status = EFI_OUT_OF_RESOURCES;\r
1085 goto Done;\r
878ddf1f 1086 }\r
ce8bd86e 1087\r
878ddf1f 1088 Reclaimed = TRUE;\r
1089 }\r
1090\r
1091 NextVariable->State = VAR_ADDED;\r
1092 Status = UpdateVariableStore (\r
1093 Global,\r
1094 TRUE,\r
1095 TRUE,\r
1096 Instance,\r
1097 *VolatileOffset,\r
1098 (UINT32) VarSize,\r
1099 (UINT8 *) NextVariable\r
1100 );\r
1101\r
1102 if (EFI_ERROR (Status)) {\r
6ed71dcc 1103 goto Done;\r
878ddf1f 1104 }\r
1105\r
1106 *VolatileOffset = *VolatileOffset + VarSize;\r
1107 }\r
1108 //\r
1109 // Mark the old variable as deleted\r
1110 //\r
1111 if (!Reclaimed && !EFI_ERROR (Status) && Variable.CurrPtr != NULL) {\r
1112 State = Variable.CurrPtr->State;\r
1113 State &= VAR_DELETED;\r
1114\r
1115 Status = UpdateVariableStore (\r
1116 Global,\r
1117 Variable.Volatile,\r
1118 FALSE,\r
1119 Instance,\r
1120 (UINTN) &Variable.CurrPtr->State,\r
1121 sizeof (UINT8),\r
1122 &State\r
1123 );\r
1124\r
1125 if (EFI_ERROR (Status)) {\r
6ed71dcc 1126 goto Done;\r
878ddf1f 1127 }\r
1128 }\r
1129 }\r
1130\r
6ed71dcc 1131 Status = EFI_SUCCESS;\r
1132Done:\r
1133 ReleaseLockOnlyAtBootTime (&Global->VariableServicesLock);\r
1134 return Status;\r
878ddf1f 1135}\r
1136\r
045f4521 1137EFI_STATUS\r
1138EFIAPI\r
1139QueryVariableInfo (\r
1140 IN UINT32 Attributes,\r
1141 OUT UINT64 *MaximumVariableStorageSize,\r
1142 OUT UINT64 *RemainingVariableStorageSize,\r
1143 OUT UINT64 *MaximumVariableSize,\r
1144 IN VARIABLE_GLOBAL *Global,\r
1145 IN UINT32 Instance\r
1146 )\r
1147/*++\r
1148\r
1149Routine Description:\r
1150\r
1151 This code returns information about the EFI variables.\r
1152\r
1153Arguments:\r
1154\r
ce8bd86e 1155 Attributes Attributes bitmask to specify the type of variables\r
045f4521 1156 on which to return information.\r
1157 MaximumVariableStorageSize Pointer to the maximum size of the storage space available\r
1158 for the EFI variables associated with the attributes specified.\r
ce8bd86e 1159 RemainingVariableStorageSize Pointer to the remaining size of the storage space available\r
045f4521 1160 for the EFI variables associated with the attributes specified.\r
1161 MaximumVariableSize Pointer to the maximum size of the individual EFI variables\r
1162 associated with the attributes specified.\r
1163 Global Pointer to VARIABLE_GLOBAL structure.\r
1164 Instance Instance of the Firmware Volume.\r
1165\r
1166Returns:\r
1167\r
1168 EFI STATUS\r
1169 EFI_INVALID_PARAMETER - An invalid combination of attribute bits was supplied.\r
1170 EFI_SUCCESS - Query successfully.\r
1171 EFI_UNSUPPORTED - The attribute is not supported on this platform.\r
1172\r
1173--*/\r
1174{\r
1175 VARIABLE_HEADER *Variable;\r
1176 VARIABLE_HEADER *NextVariable;\r
1177 UINT64 VariableSize;\r
1178 VARIABLE_STORE_HEADER *VariableStoreHeader;\r
6ed71dcc 1179\r
045f4521 1180 if(MaximumVariableStorageSize == NULL || RemainingVariableStorageSize == NULL || MaximumVariableSize == NULL) {\r
1181 return EFI_INVALID_PARAMETER;\r
1182 }\r
1183\r
1184 if((Attributes & (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS)) == 0) {\r
1185 //\r
1186 // Make sure the Attributes combination is supported by the platform.\r
1187 //\r
1188 return EFI_UNSUPPORTED;\r
1189 } else if ((Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == EFI_VARIABLE_RUNTIME_ACCESS) {\r
1190 //\r
1191 // Make sure if runtime bit is set, boot service bit is set also.\r
1192 //\r
1193 return EFI_INVALID_PARAMETER;\r
1194 } else if (EfiAtRuntime () && !(Attributes & EFI_VARIABLE_RUNTIME_ACCESS)) {\r
1195 //\r
1196 // Make sure RT Attribute is set if we are in Runtime phase.\r
1197 //\r
1198 return EFI_INVALID_PARAMETER;\r
1199 }\r
1200\r
6ed71dcc 1201 AcquireLockOnlyAtBootTime(&Global->VariableServicesLock);\r
ce8bd86e 1202\r
045f4521 1203 if((Attributes & EFI_VARIABLE_NON_VOLATILE) == 0) {\r
1204 //\r
1205 // Query is Volatile related.\r
1206 //\r
ce8bd86e 1207 VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINTN) Global->VolatileVariableBase);\r
045f4521 1208 } else {\r
1209 //\r
1210 // Query is Non-Volatile related.\r
1211 //\r
1212 VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINTN) Global->NonVolatileVariableBase);\r
1213 }\r
1214\r
1215 //\r
ce8bd86e 1216 // Now let's fill *MaximumVariableStorageSize *RemainingVariableStorageSize\r
045f4521 1217 // with the storage size (excluding the storage header size).\r
1218 //\r
1219 *MaximumVariableStorageSize = VariableStoreHeader->Size - sizeof (VARIABLE_STORE_HEADER);\r
1220 *RemainingVariableStorageSize = VariableStoreHeader->Size - sizeof (VARIABLE_STORE_HEADER);\r
1221\r
1222 //\r
1223 // Let *MaximumVariableSize be MAX_VARIABLE_SIZE.\r
1224 //\r
1225 *MaximumVariableSize = MAX_VARIABLE_SIZE;\r
1226\r
1227 //\r
1228 // Point to the starting address of the variables.\r
1229 //\r
1230 Variable = (VARIABLE_HEADER *) (VariableStoreHeader + 1);\r
1231\r
1232 //\r
1233 // Now walk through the related variable store.\r
1234 //\r
1235 while (IsValidVariableHeader (Variable) && (Variable < GetEndPointer (VariableStoreHeader))) {\r
1236 NextVariable = GetNextVariablePtr (Variable);\r
1237 VariableSize = (UINT64) (UINTN) NextVariable - (UINT64) (UINTN) Variable;\r
1238\r
1239 if (EfiAtRuntime ()) {\r
1240 //\r
ce8bd86e 1241 // we don't take the state of the variables in mind\r
045f4521 1242 // when calculating RemainingVariableStorageSize,\r
ce8bd86e 1243 // since the space occupied by variables not marked with\r
045f4521 1244 // VAR_ADDED is not allowed to be reclaimed in Runtime.\r
1245 //\r
1246 *RemainingVariableStorageSize -= VariableSize;\r
1247 } else {\r
1248 //\r
ce8bd86e 1249 // Only care about Variables with State VAR_ADDED,because\r
045f4521 1250 // the space not marked as VAR_ADDED is reclaimable now.\r
1251 //\r
1252 if (Variable->State == VAR_ADDED) {\r
1253 *RemainingVariableStorageSize -= VariableSize;\r
1254 }\r
1255 }\r
1256 \r
1257 //\r
1258 // Go to the next one\r
1259 //\r
1260 Variable = NextVariable;\r
1261 }\r
1262 \r
6ed71dcc 1263 ReleaseLockOnlyAtBootTime (&Global->VariableServicesLock);\r
045f4521 1264 return EFI_SUCCESS;\r
1265}\r
045f4521 1266\r
878ddf1f 1267EFI_STATUS\r
1268EFIAPI\r
1269VariableCommonInitialize (\r
1270 IN EFI_HANDLE ImageHandle,\r
1271 IN EFI_SYSTEM_TABLE *SystemTable\r
1272 )\r
1273/*++\r
1274\r
1275Routine Description:\r
1276 This function does common initialization for variable services\r
1277\r
1278Arguments:\r
1279\r
1280 ImageHandle - The firmware allocated handle for the EFI image.\r
1281 SystemTable - A pointer to the EFI System Table.\r
1282\r
1283Returns:\r
ce8bd86e 1284\r
878ddf1f 1285 Status code.\r
ce8bd86e 1286\r
878ddf1f 1287 EFI_NOT_FOUND - Variable store area not found.\r
1288 EFI_UNSUPPORTED - Currently only one non-volatile variable store is supported.\r
1289 EFI_SUCCESS - Variable services successfully initialized.\r
1290\r
1291--*/\r
1292{\r
1293 EFI_STATUS Status;\r
1294 EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;\r
1295 CHAR8 *CurrPtr;\r
1296 VARIABLE_STORE_HEADER *VolatileVariableStore;\r
1297 VARIABLE_STORE_HEADER *VariableStoreHeader;\r
1298 VARIABLE_HEADER *NextVariable;\r
1299 UINT32 Instance;\r
1300 EFI_PHYSICAL_ADDRESS FvVolHdr;\r
1301\r
202c5d55 1302 UINT64 TempVariableStoreHeader;\r
1303\r
878ddf1f 1304 EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor;\r
1305 EFI_FLASH_SUBAREA_ENTRY VariableStoreEntry;\r
1306 UINT64 BaseAddress;\r
1307 UINT64 Length;\r
1308 UINTN Index;\r
1309 UINT8 Data;\r
878ddf1f 1310\r
1311 Status = gBS->AllocatePool (\r
1312 EfiRuntimeServicesData,\r
1313 sizeof (ESAL_VARIABLE_GLOBAL),\r
1314 (VOID **) &mVariableModuleGlobal\r
1315 );\r
1316\r
1317 if (EFI_ERROR (Status)) {\r
1318 return Status;\r
1319 }\r
6ed71dcc 1320\r
6dcb94c7 1321 EfiInitializeLock(&mVariableModuleGlobal->VariableGlobal[Physical].VariableServicesLock, EFI_TPL_NOTIFY);\r
ce8bd86e 1322\r
878ddf1f 1323 //\r
1324 // Allocate memory for volatile variable store\r
1325 //\r
1326 Status = gBS->AllocatePool (\r
1327 EfiRuntimeServicesData,\r
1328 VARIABLE_STORE_SIZE + SCRATCH_SIZE,\r
1329 (VOID **) &VolatileVariableStore\r
1330 );\r
1331\r
1332 if (EFI_ERROR (Status)) {\r
1333 gBS->FreePool (mVariableModuleGlobal);\r
1334 return Status;\r
1335 }\r
1336\r
1337 SetMem (VolatileVariableStore, VARIABLE_STORE_SIZE + SCRATCH_SIZE, 0xff);\r
1338\r
1339 //\r
1340 // Variable Specific Data\r
1341 //\r
6ed71dcc 1342 mVariableModuleGlobal->VariableGlobal[Physical].VolatileVariableBase = (EFI_PHYSICAL_ADDRESS) (UINTN) VolatileVariableStore;\r
878ddf1f 1343 mVariableModuleGlobal->VolatileLastVariableOffset = sizeof (VARIABLE_STORE_HEADER);\r
1344\r
1345 VolatileVariableStore->Signature = VARIABLE_STORE_SIGNATURE;\r
1346 VolatileVariableStore->Size = VARIABLE_STORE_SIZE;\r
1347 VolatileVariableStore->Format = VARIABLE_STORE_FORMATTED;\r
1348 VolatileVariableStore->State = VARIABLE_STORE_HEALTHY;\r
1349 VolatileVariableStore->Reserved = 0;\r
1350 VolatileVariableStore->Reserved1 = 0;\r
1351\r
1352 //\r
1353 // Get non volatile varaible store\r
1354 //\r
1355\r
202c5d55 1356 TempVariableStoreHeader = (UINT64) PcdGet32 (PcdFlashNvStorageVariableBase);\r
1357 VariableStoreEntry.Base = TempVariableStoreHeader + \\r
1358 (((EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) (TempVariableStoreHeader)) -> HeaderLength);\r
1359 VariableStoreEntry.Length = (UINT64) PcdGet32 (PcdFlashNvStorageVariableSize) - \\r
1360 (((EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) (TempVariableStoreHeader)) -> HeaderLength);\r
878ddf1f 1361 //\r
1362 // Mark the variable storage region of the FLASH as RUNTIME\r
1363 //\r
1364 BaseAddress = VariableStoreEntry.Base & (~EFI_PAGE_MASK);\r
1365 Length = VariableStoreEntry.Length + (VariableStoreEntry.Base - BaseAddress);\r
1366 Length = (Length + EFI_PAGE_SIZE - 1) & (~EFI_PAGE_MASK);\r
1367\r
1368 Status = gDS->GetMemorySpaceDescriptor (BaseAddress, &GcdDescriptor);\r
1369 if (EFI_ERROR (Status)) {\r
1370 gBS->FreePool (mVariableModuleGlobal);\r
1371 gBS->FreePool (VolatileVariableStore);\r
1372 return EFI_UNSUPPORTED;\r
1373 }\r
1374\r
1375 Status = gDS->SetMemorySpaceAttributes (\r
1376 BaseAddress,\r
1377 Length,\r
1378 GcdDescriptor.Attributes | EFI_MEMORY_RUNTIME\r
1379 );\r
1380 if (EFI_ERROR (Status)) {\r
1381 gBS->FreePool (mVariableModuleGlobal);\r
1382 gBS->FreePool (VolatileVariableStore);\r
1383 return EFI_UNSUPPORTED;\r
1384 }\r
1385 //\r
1386 // Get address of non volatile variable store base\r
1387 //\r
6ed71dcc 1388 mVariableModuleGlobal->VariableGlobal[Physical].NonVolatileVariableBase = VariableStoreEntry.Base;\r
878ddf1f 1389\r
1390 //\r
1391 // Check Integrity\r
1392 //\r
1393 //\r
1394 // Find the Correct Instance of the FV Block Service.\r
1395 //\r
1396 Instance = 0;\r
6ed71dcc 1397 CurrPtr = (CHAR8 *) ((UINTN) mVariableModuleGlobal->VariableGlobal[Physical].NonVolatileVariableBase);\r
878ddf1f 1398 while (EfiFvbGetPhysicalAddress (Instance, &FvVolHdr) == EFI_SUCCESS) {\r
1399 FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) FvVolHdr);\r
1400 if (CurrPtr >= (CHAR8 *) FwVolHeader && CurrPtr < (((CHAR8 *) FwVolHeader) + FwVolHeader->FvLength)) {\r
1401 mVariableModuleGlobal->FvbInstance = Instance;\r
1402 break;\r
1403 }\r
1404\r
1405 Instance++;\r
1406 }\r
1407\r
1408 VariableStoreHeader = (VARIABLE_STORE_HEADER *) CurrPtr;\r
1409 if (GetVariableStoreStatus (VariableStoreHeader) == EfiValid) {\r
1410 if (~VariableStoreHeader->Size == 0) {\r
1411 Status = UpdateVariableStore (\r
6ed71dcc 1412 &mVariableModuleGlobal->VariableGlobal[Physical],\r
878ddf1f 1413 FALSE,\r
1414 FALSE,\r
1415 mVariableModuleGlobal->FvbInstance,\r
1416 (UINTN) &VariableStoreHeader->Size,\r
1417 sizeof (UINT32),\r
1418 (UINT8 *) &VariableStoreEntry.Length\r
1419 );\r
1420\r
1421 if (EFI_ERROR (Status)) {\r
1422 return Status;\r
1423 }\r
1424 }\r
1425\r
6ed71dcc 1426 mVariableModuleGlobal->VariableGlobal[Physical].NonVolatileVariableBase = (EFI_PHYSICAL_ADDRESS) ((UINTN) CurrPtr);\r
878ddf1f 1427 //\r
1428 // Parse non-volatile variable data and get last variable offset\r
1429 //\r
1430 NextVariable = (VARIABLE_HEADER *) (CurrPtr + sizeof (VARIABLE_STORE_HEADER));\r
1431 Status = EFI_SUCCESS;\r
1432\r
1433 while (IsValidVariableHeader (NextVariable)) {\r
1434 NextVariable = GetNextVariablePtr (NextVariable);\r
1435 }\r
1436\r
1437 mVariableModuleGlobal->NonVolatileLastVariableOffset = (UINTN) NextVariable - (UINTN) CurrPtr;\r
1438\r
c65c1e1e 1439 //\r
1440 // Check if the free area is blow a threshold\r
1441 //\r
1442 if ((((VARIABLE_STORE_HEADER *)((UINTN) CurrPtr))->Size - mVariableModuleGlobal->NonVolatileLastVariableOffset) < VARIABLE_RECLAIM_THRESHOLD) {\r
1443 Status = Reclaim (\r
6ed71dcc 1444 mVariableModuleGlobal->VariableGlobal[Physical].NonVolatileVariableBase,\r
c65c1e1e 1445 &mVariableModuleGlobal->NonVolatileLastVariableOffset,\r
1446 FALSE\r
1447 );\r
1448 }\r
1449\r
1450 if (EFI_ERROR (Status)) {\r
1451 gBS->FreePool (mVariableModuleGlobal);\r
1452 gBS->FreePool (VolatileVariableStore);\r
1453 return Status;\r
1454 }\r
1455\r
878ddf1f 1456 //\r
1457 // Check if the free area is really free.\r
1458 //\r
1459 for (Index = mVariableModuleGlobal->NonVolatileLastVariableOffset; Index < VariableStoreHeader->Size; Index++) {\r
6ed71dcc 1460 Data = ((UINT8 *) (UINTN) mVariableModuleGlobal->VariableGlobal[Physical].NonVolatileVariableBase)[Index];\r
878ddf1f 1461 if (Data != 0xff) {\r
1462 //\r
1463 // There must be something wrong in variable store, do reclaim operation.\r
1464 //\r
1465 Status = Reclaim (\r
6ed71dcc 1466 mVariableModuleGlobal->VariableGlobal[Physical].NonVolatileVariableBase,\r
878ddf1f 1467 &mVariableModuleGlobal->NonVolatileLastVariableOffset,\r
1468 FALSE\r
1469 );\r
1470 break;\r
1471 }\r
1472 }\r
1473 }\r
1474\r
1475 if (EFI_ERROR (Status)) {\r
1476 gBS->FreePool (mVariableModuleGlobal);\r
1477 gBS->FreePool (VolatileVariableStore);\r
1478 }\r
1479\r
1480 return Status;\r
1481}\r