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**/
55STATIC
56EFI_STATUS
57UnpackVariableFromBuffer (
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**/
130STATIC
131EFI_STATUS
132IterateVariablesInBuffer (
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
232STATIC
233RETURN_STATUS
234EFIAPI
235IterateVariablesCallbackNop (
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
248STATIC
249RETURN_STATUS
250EFIAPI
251IterateVariablesCallbackSetInInstance (
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
275STATIC
276RETURN_STATUS
277EFIAPI
278IterateVariablesCallbackSetSystemVariable (
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
315STATIC
316RETURN_STATUS
317EnsureExtraBufferSpace (
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
352STATIC
353VOID
354AppendToBuffer (
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**/
389RETURN_STATUS
390EFIAPI
391SerializeVariablesNewInstance (
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**/
420RETURN_STATUS
421EFIAPI
422SerializeVariablesFreeInstance (
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**/
463RETURN_STATUS
464EFIAPI
465SerializeVariablesNewInstanceFromBuffer (
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**/
518RETURN_STATUS
519EFIAPI
520SerializeVariablesIterateSystemVariables (
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**/
677RETURN_STATUS
678EFIAPI
679SerializeVariablesIterateInstanceVariables (
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**/
714RETURN_STATUS
715EFIAPI
716SerializeVariablesSetSerializedVariables (
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**/
746RETURN_STATUS
747EFIAPI
748SerializeVariablesAddVariable (
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**/
845RETURN_STATUS
846EFIAPI
847SerializeVariablesToBuffer (
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