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