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