• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2   Serialize Variables Library implementation
3 
4   Copyright (c) 2004 - 2011, Intel Corporation. All rights reserved.<BR>
5   This program and the accompanying materials
6   are licensed and made available under the terms and conditions of the BSD License
7   which accompanies this distribution.  The full text of the license may be found at
8   http://opensource.org/licenses/bsd-license.php
9 
10   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12 
13 **/
14 
15 #include "SerializeVariablesLib.h"
16 
17 /**
18   Serialization format:
19 
20   The SerializeVariablesLib interface does not specify a format
21   for the serialization of the variable data.  This library uses
22   a packed array of a non-uniformly sized data structure elements.
23 
24   Each variable is stored (packed) as:
25     UINT32   VendorNameSize;  // Name size in bytes
26     CHAR16   VendorName[?];   // The variable unicode name including the
27                               // null terminating character.
28     EFI_GUID VendorGuid;      // The variable GUID
29     UINT32   DataSize;        // The size of variable data in bytes
30     UINT8    Data[?];         // The variable data
31 
32 **/
33 
34 
35 /**
36   Unpacks the next variable from the buffer
37 
38   @param[in]  Buffer - Buffer pointing to the next variable instance
39                 On subsequent calls, the pointer should be incremented
40                 by the returned SizeUsed value.
41   @param[in]  MaxSize - Max allowable size for the variable data
42                 On subsequent calls, this should be decremented
43                 by the returned SizeUsed value.
44   @param[out] Name - Variable name string (address in Buffer)
45   @param[out] NameSize - Size of Name in bytes
46   @param[out] Guid - GUID of variable (address in Buffer)
47   @param[out] Attributes - Attributes of variable
48   @param[out] Data - Buffer containing Data for variable (address in Buffer)
49   @param[out] DataSize - Size of Data in bytes
50   @param[out] SizeUsed - Total size used for this variable instance in Buffer
51 
52   @return     EFI_STATUS based on the success or failure of the operation
53 
54 **/
55 STATIC
56 EFI_STATUS
UnpackVariableFromBuffer(IN VOID * Buffer,IN UINTN MaxSize,OUT CHAR16 ** Name,OUT UINT32 * NameSize,OUT EFI_GUID ** Guid,OUT UINT32 * Attributes,OUT UINT32 * DataSize,OUT VOID ** Data,OUT UINTN * SizeUsed)57 UnpackVariableFromBuffer (
58   IN  VOID     *Buffer,
59   IN  UINTN    MaxSize,
60   OUT CHAR16   **Name,
61   OUT UINT32   *NameSize,
62   OUT EFI_GUID **Guid,
63   OUT UINT32   *Attributes,
64   OUT UINT32   *DataSize,
65   OUT VOID     **Data,
66   OUT UINTN    *SizeUsed
67   )
68 {
69   UINT8  *BytePtr;
70   UINTN  Offset;
71 
72   BytePtr = (UINT8*)Buffer;
73   Offset = 0;
74 
75   *NameSize = *(UINT32*) (BytePtr + Offset);
76   Offset = Offset + sizeof (UINT32);
77 
78   if (Offset > MaxSize) {
79     return EFI_INVALID_PARAMETER;
80   }
81 
82   *Name = (CHAR16*) (BytePtr + Offset);
83   Offset = Offset + *(UINT32*)BytePtr;
84   if (Offset > MaxSize) {
85     return EFI_INVALID_PARAMETER;
86   }
87 
88   *Guid = (EFI_GUID*) (BytePtr + Offset);
89   Offset = Offset + sizeof (EFI_GUID);
90   if (Offset > MaxSize) {
91     return EFI_INVALID_PARAMETER;
92   }
93 
94   *Attributes = *(UINT32*) (BytePtr + Offset);
95   Offset = Offset + sizeof (UINT32);
96   if (Offset > MaxSize) {
97     return EFI_INVALID_PARAMETER;
98   }
99 
100   *DataSize = *(UINT32*) (BytePtr + Offset);
101   Offset = Offset + sizeof (UINT32);
102   if (Offset > MaxSize) {
103     return EFI_INVALID_PARAMETER;
104   }
105 
106   *Data = (VOID*) (BytePtr + Offset);
107   Offset = Offset + *DataSize;
108   if (Offset > MaxSize) {
109     return EFI_INVALID_PARAMETER;
110   }
111 
112   *SizeUsed = Offset;
113 
114   return EFI_SUCCESS;
115 }
116 
117 
118 /**
119   Iterates through the variables in the buffer, and calls a callback
120   function for each variable found.
121 
122   @param[in]  CallbackFunction - Function called for each variable instance
123   @param[in]  Context - Passed to each call of CallbackFunction
124   @param[in]  Buffer - Buffer containing serialized variables
125   @param[in]  MaxSize - Size of Buffer in bytes
126 
127   @return     EFI_STATUS based on the success or failure of the operation
128 
129 **/
130 STATIC
131 EFI_STATUS
IterateVariablesInBuffer(IN VARIABLE_SERIALIZATION_ITERATION_CALLBACK CallbackFunction,IN VOID * CallbackContext,IN VOID * Buffer,IN UINTN MaxSize)132 IterateVariablesInBuffer (
133   IN VARIABLE_SERIALIZATION_ITERATION_CALLBACK  CallbackFunction,
134   IN VOID                                       *CallbackContext,
135   IN VOID                                       *Buffer,
136   IN UINTN                                      MaxSize
137   )
138 {
139   RETURN_STATUS Status;
140   UINTN         TotalSizeUsed;
141   UINTN         SizeUsed;
142 
143   CHAR16        *Name;
144   UINT32        NameSize;
145   CHAR16        *AlignedName;
146   UINT32        AlignedNameMaxSize;
147   EFI_GUID      *Guid;
148   UINT32        Attributes;
149   UINT32        DataSize;
150   VOID          *Data;
151 
152   SizeUsed = 0;
153   AlignedName = NULL;
154   AlignedNameMaxSize = 0;
155   Name = NULL;
156   Guid = NULL;
157   Attributes = 0;
158   DataSize = 0;
159   Data = NULL;
160 
161   for (
162     Status = EFI_SUCCESS, TotalSizeUsed = 0;
163     !EFI_ERROR (Status) && (TotalSizeUsed < MaxSize);
164     ) {
165     Status = UnpackVariableFromBuffer (
166                (VOID*) ((UINT8*) Buffer + TotalSizeUsed),
167                (MaxSize - TotalSizeUsed),
168                &Name,
169                &NameSize,
170                &Guid,
171                &Attributes,
172                &DataSize,
173                &Data,
174                &SizeUsed
175                );
176     if (EFI_ERROR (Status)) {
177       return Status;
178     }
179 
180     //
181     // We copy the name to a separately allocated buffer,
182     // to be sure it is 16-bit aligned.
183     //
184     if (NameSize > AlignedNameMaxSize) {
185       if (AlignedName != NULL) {
186         FreePool (AlignedName);
187       }
188       AlignedName = AllocatePool (NameSize);
189     }
190     if (AlignedName == NULL) {
191       return EFI_OUT_OF_RESOURCES;
192     }
193     CopyMem (AlignedName, Name, NameSize);
194 
195     TotalSizeUsed = TotalSizeUsed + SizeUsed;
196 
197     //
198     // Run the callback function
199     //
200     Status = (*CallbackFunction) (
201                CallbackContext,
202                AlignedName,
203                Guid,
204                Attributes,
205                DataSize,
206                Data
207                );
208 
209   }
210 
211   if (AlignedName != NULL) {
212     FreePool (AlignedName);
213   }
214 
215   //
216   // Make sure the entire buffer was used, or else return an error
217   //
218   if (TotalSizeUsed != MaxSize) {
219     DEBUG ((
220       EFI_D_ERROR,
221       "Deserialize variables error: TotalSizeUsed(%Lu) != MaxSize(%Lu)\n",
222       (UINT64)TotalSizeUsed,
223       (UINT64)MaxSize
224       ));
225     return EFI_INVALID_PARAMETER;
226   }
227 
228   return EFI_SUCCESS;
229 }
230 
231 
232 STATIC
233 RETURN_STATUS
234 EFIAPI
IterateVariablesCallbackNop(IN VOID * Context,IN CHAR16 * VariableName,IN EFI_GUID * VendorGuid,IN UINT32 Attributes,IN UINTN DataSize,IN VOID * Data)235 IterateVariablesCallbackNop (
236   IN  VOID                         *Context,
237   IN  CHAR16                       *VariableName,
238   IN  EFI_GUID                     *VendorGuid,
239   IN  UINT32                       Attributes,
240   IN  UINTN                        DataSize,
241   IN  VOID                         *Data
242   )
243 {
244   return RETURN_SUCCESS;
245 }
246 
247 
248 STATIC
249 RETURN_STATUS
250 EFIAPI
IterateVariablesCallbackSetInInstance(IN VOID * Context,IN CHAR16 * VariableName,IN EFI_GUID * VendorGuid,IN UINT32 Attributes,IN UINTN DataSize,IN VOID * Data)251 IterateVariablesCallbackSetInInstance (
252   IN  VOID                         *Context,
253   IN  CHAR16                       *VariableName,
254   IN  EFI_GUID                     *VendorGuid,
255   IN  UINT32                       Attributes,
256   IN  UINTN                        DataSize,
257   IN  VOID                         *Data
258   )
259 {
260   EFI_HANDLE  Instance;
261 
262   Instance = (EFI_HANDLE) Context;
263 
264   return SerializeVariablesAddVariable (
265            Instance,
266            VariableName,
267            VendorGuid,
268            Attributes,
269            DataSize,
270            Data
271            );
272 }
273 
274 
275 STATIC
276 RETURN_STATUS
277 EFIAPI
IterateVariablesCallbackSetSystemVariable(IN VOID * Context,IN CHAR16 * VariableName,IN EFI_GUID * VendorGuid,IN UINT32 Attributes,IN UINTN DataSize,IN VOID * Data)278 IterateVariablesCallbackSetSystemVariable (
279   IN  VOID                         *Context,
280   IN  CHAR16                       *VariableName,
281   IN  EFI_GUID                     *VendorGuid,
282   IN  UINT32                       Attributes,
283   IN  UINTN                        DataSize,
284   IN  VOID                         *Data
285   )
286 {
287   EFI_STATUS          Status;
288   STATIC CONST UINT32 AuthMask =
289                         EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS |
290                         EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
291 
292   Status = gRT->SetVariable (
293              VariableName,
294              VendorGuid,
295              Attributes,
296              DataSize,
297              Data
298              );
299 
300   if (Status == EFI_SECURITY_VIOLATION && (Attributes & AuthMask) != 0) {
301     DEBUG ((DEBUG_WARN, "%a: setting authenticated variable \"%s\" "
302             "failed with EFI_SECURITY_VIOLATION, ignoring\n", __FUNCTION__,
303             VariableName));
304     Status = EFI_SUCCESS;
305   } else if (Status == EFI_WRITE_PROTECTED) {
306     DEBUG ((DEBUG_WARN, "%a: setting ReadOnly variable \"%s\" "
307             "failed with EFI_WRITE_PROTECTED, ignoring\n", __FUNCTION__,
308             VariableName));
309     Status = EFI_SUCCESS;
310   }
311   return Status;
312 }
313 
314 
315 STATIC
316 RETURN_STATUS
EnsureExtraBufferSpace(IN SV_INSTANCE * Instance,IN UINTN Size)317 EnsureExtraBufferSpace (
318   IN  SV_INSTANCE  *Instance,
319   IN  UINTN        Size
320   )
321 {
322   VOID *NewBuffer;
323   UINTN NewSize;
324 
325   NewSize = Instance->DataSize + Size;
326   if (NewSize <= Instance->BufferSize) {
327     return RETURN_SUCCESS;
328   }
329 
330   //
331   // Double the required size to lessen the need to re-allocate in the future
332   //
333   NewSize = 2 * NewSize;
334 
335   NewBuffer = AllocatePool (NewSize);
336   if (NewBuffer == NULL) {
337     return RETURN_OUT_OF_RESOURCES;
338   }
339 
340   if (Instance->BufferPtr != NULL) {
341     CopyMem (NewBuffer, Instance->BufferPtr, Instance->DataSize);
342     FreePool (Instance->BufferPtr);
343   }
344 
345   Instance->BufferPtr = NewBuffer;
346   Instance->BufferSize = NewSize;
347 
348   return RETURN_SUCCESS;
349 }
350 
351 
352 STATIC
353 VOID
AppendToBuffer(IN SV_INSTANCE * Instance,IN VOID * Data,IN UINTN Size)354 AppendToBuffer (
355   IN  SV_INSTANCE  *Instance,
356   IN  VOID         *Data,
357   IN  UINTN        Size
358   )
359 {
360   UINTN NewSize;
361 
362   ASSERT (Instance != NULL);
363   ASSERT (Data != NULL);
364 
365   NewSize = Instance->DataSize + Size;
366   ASSERT ((Instance->DataSize + Size) <= Instance->BufferSize);
367 
368   CopyMem (
369     (VOID*) (((UINT8*) (Instance->BufferPtr)) + Instance->DataSize),
370     Data,
371     Size
372     );
373 
374   Instance->DataSize = NewSize;
375 }
376 
377 
378 /**
379   Creates a new variable serialization instance
380 
381   @param[out]  Handle - Handle for a variable serialization instance
382 
383   @retval      RETURN_SUCCESS - The variable serialization instance was
384                  successfully created.
385   @retval      RETURN_OUT_OF_RESOURCES - There we not enough resources to
386                  create the variable serialization instance.
387 
388 **/
389 RETURN_STATUS
390 EFIAPI
SerializeVariablesNewInstance(OUT EFI_HANDLE * Handle)391 SerializeVariablesNewInstance (
392   OUT EFI_HANDLE                      *Handle
393   )
394 {
395   SV_INSTANCE  *New;
396 
397   New = AllocateZeroPool (sizeof (*New));
398   if (New == NULL) {
399     return RETURN_OUT_OF_RESOURCES;
400   }
401 
402   New->Signature = SV_SIGNATURE;
403 
404   *Handle = (EFI_HANDLE) New;
405   return RETURN_SUCCESS;
406 }
407 
408 
409 /**
410   Free memory associated with a variable serialization instance
411 
412   @param[in]  Handle - Handle for a variable serialization instance
413 
414   @retval      RETURN_SUCCESS - The variable serialization instance was
415                  successfully freed.
416   @retval      RETURN_INVALID_PARAMETER - Handle was not a valid
417                  variable serialization instance.
418 
419 **/
420 RETURN_STATUS
421 EFIAPI
SerializeVariablesFreeInstance(IN EFI_HANDLE Handle)422 SerializeVariablesFreeInstance (
423   IN EFI_HANDLE Handle
424   )
425 {
426   SV_INSTANCE    *Instance;
427 
428   Instance = SV_FROM_HANDLE (Handle);
429 
430   if (Instance->Signature != SV_SIGNATURE) {
431     return RETURN_INVALID_PARAMETER;
432   }
433 
434   Instance->Signature = 0;
435 
436   if (Instance->BufferPtr != NULL) {
437     FreePool (Instance->BufferPtr);
438   }
439 
440   FreePool (Instance);
441 
442   return RETURN_SUCCESS;
443 }
444 
445 
446 /**
447   Creates a new variable serialization instance using the given
448   binary representation of the variables to fill the new instance
449 
450   @param[out] Handle - Handle for a variable serialization instance
451   @param[in]  Buffer - A buffer with the serialized representation
452                 of the variables.  Must be the same format as produced
453                 by SerializeVariablesToBuffer.
454   @param[in]  Size - This is the size of the binary representation
455                 of the variables.
456 
457   @retval      RETURN_SUCCESS - The binary representation was successfully
458                  imported into a new variable serialization instance
459   @retval      RETURN_OUT_OF_RESOURCES - There we not enough resources to
460                  create the new variable serialization instance
461 
462 **/
463 RETURN_STATUS
464 EFIAPI
SerializeVariablesNewInstanceFromBuffer(OUT EFI_HANDLE * Handle,IN VOID * Buffer,IN UINTN Size)465 SerializeVariablesNewInstanceFromBuffer (
466   OUT EFI_HANDLE                          *Handle,
467   IN  VOID                                *Buffer,
468   IN  UINTN                               Size
469   )
470 {
471   RETURN_STATUS Status;
472 
473   Status = SerializeVariablesNewInstance (Handle);
474   if (RETURN_ERROR (Status)) {
475     return Status;
476   }
477 
478   Status = IterateVariablesInBuffer (
479              IterateVariablesCallbackNop,
480              NULL,
481              Buffer,
482              Size
483              );
484   if (RETURN_ERROR (Status)) {
485     SerializeVariablesFreeInstance (*Handle);
486     return Status;
487   }
488 
489   Status = IterateVariablesInBuffer (
490              IterateVariablesCallbackSetInInstance,
491              (VOID*) *Handle,
492              Buffer,
493              Size
494              );
495   if (RETURN_ERROR (Status)) {
496     SerializeVariablesFreeInstance (*Handle);
497     return Status;
498   }
499 
500   return Status;
501 }
502 
503 
504 /**
505   Iterates all variables found with RuntimeServices GetNextVariableName
506 
507   @param[in]   CallbackFunction - Function called for each variable instance
508   @param[in]   Context - Passed to each call of CallbackFunction
509 
510   @retval      RETURN_SUCCESS - All variables were iterated without the
511                  CallbackFunction returning an error
512   @retval      RETURN_OUT_OF_RESOURCES - There we not enough resources to
513                  iterate through the variables
514   @return      Any of RETURN_ERROR indicates an error reading the variable
515                  or an error was returned from CallbackFunction
516 
517 **/
518 RETURN_STATUS
519 EFIAPI
SerializeVariablesIterateSystemVariables(IN VARIABLE_SERIALIZATION_ITERATION_CALLBACK CallbackFunction,IN VOID * Context)520 SerializeVariablesIterateSystemVariables (
521   IN VARIABLE_SERIALIZATION_ITERATION_CALLBACK CallbackFunction,
522   IN VOID                                      *Context
523   )
524 {
525   RETURN_STATUS               Status;
526   UINTN                       VariableNameBufferSize;
527   UINTN                       VariableNameSize;
528   CHAR16                      *VariableName;
529   EFI_GUID                    VendorGuid;
530   UINTN                       VariableDataBufferSize;
531   UINTN                       VariableDataSize;
532   VOID                        *VariableData;
533   UINT32                      VariableAttributes;
534   VOID                        *NewBuffer;
535 
536   //
537   // Initialize the variable name and data buffer variables.
538   //
539   VariableNameBufferSize = sizeof (CHAR16);
540   VariableName = AllocateZeroPool (VariableNameBufferSize);
541 
542   VariableDataBufferSize = 0;
543   VariableData = NULL;
544 
545   for (;;) {
546     //
547     // Get the next variable name and guid
548     //
549     VariableNameSize = VariableNameBufferSize;
550     Status = gRT->GetNextVariableName (
551                     &VariableNameSize,
552                     VariableName,
553                     &VendorGuid
554                     );
555     if (Status == EFI_BUFFER_TOO_SMALL) {
556       //
557       // The currently allocated VariableName buffer is too small,
558       // so we allocate a larger buffer, and copy the old buffer
559       // to it.
560       //
561       NewBuffer = AllocatePool (VariableNameSize);
562       if (NewBuffer == NULL) {
563         Status = EFI_OUT_OF_RESOURCES;
564         break;
565       }
566       CopyMem (NewBuffer, VariableName, VariableNameBufferSize);
567       if (VariableName != NULL) {
568         FreePool (VariableName);
569       }
570       VariableName = NewBuffer;
571       VariableNameBufferSize = VariableNameSize;
572 
573       //
574       // Try to get the next variable name again with the larger buffer.
575       //
576       Status = gRT->GetNextVariableName (
577                       &VariableNameSize,
578                       VariableName,
579                       &VendorGuid
580                       );
581     }
582 
583     if (EFI_ERROR (Status)) {
584       if (Status == EFI_NOT_FOUND) {
585         Status = EFI_SUCCESS;
586       }
587       break;
588     }
589 
590     //
591     // Get the variable data and attributes
592     //
593     VariableDataSize = VariableDataBufferSize;
594     Status = gRT->GetVariable (
595                     VariableName,
596                     &VendorGuid,
597                     &VariableAttributes,
598                     &VariableDataSize,
599                     VariableData
600                     );
601     if (Status == EFI_BUFFER_TOO_SMALL) {
602       //
603       // The currently allocated VariableData buffer is too small,
604       // so we allocate a larger buffer.
605       //
606       if (VariableDataBufferSize != 0) {
607         FreePool (VariableData);
608         VariableData = NULL;
609         VariableDataBufferSize = 0;
610       }
611       VariableData = AllocatePool (VariableDataSize);
612       if (VariableData == NULL) {
613         Status = EFI_OUT_OF_RESOURCES;
614         break;
615       }
616       VariableDataBufferSize = VariableDataSize;
617 
618       //
619       // Try to read the variable again with the larger buffer.
620       //
621       Status = gRT->GetVariable (
622                       VariableName,
623                       &VendorGuid,
624                       &VariableAttributes,
625                       &VariableDataSize,
626                       VariableData
627                       );
628     }
629     if (EFI_ERROR (Status)) {
630       break;
631     }
632 
633     //
634     // Run the callback function
635     //
636     Status = (*CallbackFunction) (
637                Context,
638                VariableName,
639                &VendorGuid,
640                VariableAttributes,
641                VariableDataSize,
642                VariableData
643                );
644     if (EFI_ERROR (Status)) {
645       break;
646     }
647 
648   }
649 
650   if (VariableName != NULL) {
651     FreePool (VariableName);
652   }
653 
654   if (VariableData != NULL) {
655     FreePool (VariableData);
656   }
657 
658   return Status;
659 }
660 
661 
662 /**
663   Iterates all variables found in the variable serialization instance
664 
665   @param[in]   Handle - Handle for a variable serialization instance
666   @param[in]   CallbackFunction - Function called for each variable instance
667   @param[in]   Context - Passed to each call of CallbackFunction
668 
669   @retval      RETURN_SUCCESS - All variables were iterated without the
670                  CallbackFunction returning an error
671   @retval      RETURN_OUT_OF_RESOURCES - There we not enough resources to
672                  iterate through the variables
673   @return      Any of RETURN_ERROR indicates an error reading the variable
674                  or an error was returned from CallbackFunction
675 
676 **/
677 RETURN_STATUS
678 EFIAPI
SerializeVariablesIterateInstanceVariables(IN EFI_HANDLE Handle,IN VARIABLE_SERIALIZATION_ITERATION_CALLBACK CallbackFunction,IN VOID * Context)679 SerializeVariablesIterateInstanceVariables (
680   IN EFI_HANDLE                                Handle,
681   IN VARIABLE_SERIALIZATION_ITERATION_CALLBACK CallbackFunction,
682   IN VOID                                      *Context
683   )
684 {
685   SV_INSTANCE    *Instance;
686 
687   Instance = SV_FROM_HANDLE (Handle);
688 
689   if ((Instance->BufferPtr != NULL) && (Instance->DataSize != 0)) {
690     return IterateVariablesInBuffer (
691              CallbackFunction,
692              Context,
693              Instance->BufferPtr,
694              Instance->DataSize
695              );
696   } else {
697     return RETURN_SUCCESS;
698   }
699 }
700 
701 
702 /**
703   Sets all variables found in the variable serialization instance
704 
705   @param[in]   Handle - Handle for a variable serialization instance
706 
707   @retval      RETURN_SUCCESS - All variables were set successfully
708   @retval      RETURN_OUT_OF_RESOURCES - There we not enough resources to
709                  set all the variables
710   @return      Any of RETURN_ERROR indicates an error reading the variables
711                  or in attempting to set a variable
712 
713 **/
714 RETURN_STATUS
715 EFIAPI
SerializeVariablesSetSerializedVariables(IN EFI_HANDLE Handle)716 SerializeVariablesSetSerializedVariables (
717   IN EFI_HANDLE                       Handle
718   )
719 {
720   return SerializeVariablesIterateInstanceVariables (
721            Handle,
722            IterateVariablesCallbackSetSystemVariable,
723            NULL
724            );
725 }
726 
727 
728 /**
729   Adds a variable to the variable serialization instance
730 
731   @param[in] Handle - Handle for a variable serialization instance
732   @param[in] VariableName - Refer to RuntimeServices GetVariable
733   @param[in] VendorGuid - Refer to RuntimeServices GetVariable
734   @param[in] Attributes - Refer to RuntimeServices GetVariable
735   @param[in] DataSize - Refer to RuntimeServices GetVariable
736   @param[in] Data - Refer to RuntimeServices GetVariable
737 
738   @retval      RETURN_SUCCESS - All variables were set successfully
739   @retval      RETURN_OUT_OF_RESOURCES - There we not enough resources to
740                  add the variable
741   @retval      RETURN_INVALID_PARAMETER - Handle was not a valid
742                  variable serialization instance or
743                  VariableName, VariableGuid or Data are NULL.
744 
745 **/
746 RETURN_STATUS
747 EFIAPI
SerializeVariablesAddVariable(IN EFI_HANDLE Handle,IN CHAR16 * VariableName,IN EFI_GUID * VendorGuid,IN UINT32 Attributes,IN UINTN DataSize,IN VOID * Data)748 SerializeVariablesAddVariable (
749   IN EFI_HANDLE                   Handle,
750   IN CHAR16                       *VariableName,
751   IN EFI_GUID                     *VendorGuid,
752   IN UINT32                       Attributes,
753   IN UINTN                        DataSize,
754   IN VOID                         *Data
755   )
756 {
757   RETURN_STATUS  Status;
758   SV_INSTANCE    *Instance;
759   UINT32         SerializedNameSize;
760   UINT32         SerializedDataSize;
761   UINTN          SerializedSize;
762 
763   Instance = SV_FROM_HANDLE (Handle);
764 
765   if ((Instance->Signature != SV_SIGNATURE) ||
766       (VariableName == NULL) || (VendorGuid == NULL) || (Data == NULL)) {
767   }
768 
769   SerializedNameSize = (UINT32) StrSize (VariableName);
770 
771   SerializedSize =
772     sizeof (SerializedNameSize) +
773     SerializedNameSize +
774     sizeof (*VendorGuid) +
775     sizeof (Attributes) +
776     sizeof (SerializedDataSize) +
777     DataSize;
778 
779   Status = EnsureExtraBufferSpace (
780              Instance,
781              SerializedSize
782              );
783   if (RETURN_ERROR (Status)) {
784     return Status;
785   }
786 
787   //
788   // Add name size (UINT32)
789   //
790   AppendToBuffer (Instance, (VOID*) &SerializedNameSize, sizeof (SerializedNameSize));
791 
792   //
793   // Add variable unicode name string
794   //
795   AppendToBuffer (Instance, (VOID*) VariableName, SerializedNameSize);
796 
797   //
798   // Add variable GUID
799   //
800   AppendToBuffer (Instance, (VOID*) VendorGuid, sizeof (*VendorGuid));
801 
802   //
803   // Add variable attributes
804   //
805   AppendToBuffer (Instance, (VOID*) &Attributes, sizeof (Attributes));
806 
807   //
808   // Add variable data size (UINT32)
809   //
810   SerializedDataSize = (UINT32) DataSize;
811   AppendToBuffer (Instance, (VOID*) &SerializedDataSize, sizeof (SerializedDataSize));
812 
813   //
814   // Add variable data
815   //
816   AppendToBuffer (Instance, Data, DataSize);
817 
818   return RETURN_SUCCESS;
819 }
820 
821 
822 /**
823   Serializes the variables known to this instance into the
824   provided buffer.
825 
826   @param[in]     Handle - Handle for a variable serialization instance
827   @param[out]    Buffer - A buffer to store the binary representation
828                    of the variables.
829   @param[in,out] Size - On input this is the size of the buffer.
830                    On output this is the size of the binary representation
831                    of the variables.
832 
833   @retval      RETURN_SUCCESS - The binary representation was successfully
834                  completed and returned in the buffer.
835   @retval      RETURN_OUT_OF_RESOURCES - There we not enough resources to
836                  save the variables to the buffer.
837   @retval      RETURN_INVALID_PARAMETER - Handle was not a valid
838                  variable serialization instance or
839                  Size or Buffer were NULL.
840   @retval      RETURN_BUFFER_TOO_SMALL - The Buffer size as indicated by
841                  the Size parameter was too small for the serialized
842                  variable data.  Size is returned with the required size.
843 
844 **/
845 RETURN_STATUS
846 EFIAPI
SerializeVariablesToBuffer(IN EFI_HANDLE Handle,OUT VOID * Buffer,IN OUT UINTN * Size)847 SerializeVariablesToBuffer (
848   IN     EFI_HANDLE                       Handle,
849   OUT    VOID                             *Buffer,
850   IN OUT UINTN                            *Size
851   )
852 {
853   SV_INSTANCE    *Instance;
854 
855   Instance = SV_FROM_HANDLE (Handle);
856 
857   if (Size == NULL) {
858     return RETURN_INVALID_PARAMETER;
859   }
860 
861   if (*Size < Instance->DataSize) {
862     *Size = Instance->DataSize;
863     return RETURN_BUFFER_TOO_SMALL;
864   }
865 
866   if (Buffer == NULL) {
867     return RETURN_INVALID_PARAMETER;
868   }
869 
870   *Size = Instance->DataSize;
871   CopyMem (Buffer, Instance->BufferPtr, Instance->DataSize);
872 
873   return RETURN_SUCCESS;
874 }
875 
876