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   }
306   return Status;
307 }
308 
309 
310 STATIC
311 RETURN_STATUS
EnsureExtraBufferSpace(IN SV_INSTANCE * Instance,IN UINTN Size)312 EnsureExtraBufferSpace (
313   IN  SV_INSTANCE  *Instance,
314   IN  UINTN        Size
315   )
316 {
317   VOID *NewBuffer;
318   UINTN NewSize;
319 
320   NewSize = Instance->DataSize + Size;
321   if (NewSize <= Instance->BufferSize) {
322     return RETURN_SUCCESS;
323   }
324 
325   //
326   // Double the required size to lessen the need to re-allocate in the future
327   //
328   NewSize = 2 * NewSize;
329 
330   NewBuffer = AllocatePool (NewSize);
331   if (NewBuffer == NULL) {
332     return RETURN_OUT_OF_RESOURCES;
333   }
334 
335   if (Instance->BufferPtr != NULL) {
336     CopyMem (NewBuffer, Instance->BufferPtr, Instance->DataSize);
337     FreePool (Instance->BufferPtr);
338   }
339 
340   Instance->BufferPtr = NewBuffer;
341   Instance->BufferSize = NewSize;
342 
343   return RETURN_SUCCESS;
344 }
345 
346 
347 STATIC
348 VOID
AppendToBuffer(IN SV_INSTANCE * Instance,IN VOID * Data,IN UINTN Size)349 AppendToBuffer (
350   IN  SV_INSTANCE  *Instance,
351   IN  VOID         *Data,
352   IN  UINTN        Size
353   )
354 {
355   UINTN NewSize;
356 
357   ASSERT (Instance != NULL);
358   ASSERT (Data != NULL);
359 
360   NewSize = Instance->DataSize + Size;
361   ASSERT ((Instance->DataSize + Size) <= Instance->BufferSize);
362 
363   CopyMem (
364     (VOID*) (((UINT8*) (Instance->BufferPtr)) + Instance->DataSize),
365     Data,
366     Size
367     );
368 
369   Instance->DataSize = NewSize;
370 }
371 
372 
373 /**
374   Creates a new variable serialization instance
375 
376   @param[out]  Handle - Handle for a variable serialization instance
377 
378   @retval      RETURN_SUCCESS - The variable serialization instance was
379                  successfully created.
380   @retval      RETURN_OUT_OF_RESOURCES - There we not enough resources to
381                  create the variable serialization instance.
382 
383 **/
384 RETURN_STATUS
385 EFIAPI
SerializeVariablesNewInstance(OUT EFI_HANDLE * Handle)386 SerializeVariablesNewInstance (
387   OUT EFI_HANDLE                      *Handle
388   )
389 {
390   SV_INSTANCE  *New;
391 
392   New = AllocateZeroPool (sizeof (*New));
393   if (New == NULL) {
394     return RETURN_OUT_OF_RESOURCES;
395   }
396 
397   New->Signature = SV_SIGNATURE;
398 
399   *Handle = (EFI_HANDLE) New;
400   return RETURN_SUCCESS;
401 }
402 
403 
404 /**
405   Free memory associated with a variable serialization instance
406 
407   @param[in]  Handle - Handle for a variable serialization instance
408 
409   @retval      RETURN_SUCCESS - The variable serialization instance was
410                  successfully freed.
411   @retval      RETURN_INVALID_PARAMETER - Handle was not a valid
412                  variable serialization instance.
413 
414 **/
415 RETURN_STATUS
416 EFIAPI
SerializeVariablesFreeInstance(IN EFI_HANDLE Handle)417 SerializeVariablesFreeInstance (
418   IN EFI_HANDLE Handle
419   )
420 {
421   SV_INSTANCE    *Instance;
422 
423   Instance = SV_FROM_HANDLE (Handle);
424 
425   if (Instance->Signature != SV_SIGNATURE) {
426     return RETURN_INVALID_PARAMETER;
427   }
428 
429   Instance->Signature = 0;
430 
431   if (Instance->BufferPtr != NULL) {
432     FreePool (Instance->BufferPtr);
433   }
434 
435   FreePool (Instance);
436 
437   return RETURN_SUCCESS;
438 }
439 
440 
441 /**
442   Creates a new variable serialization instance using the given
443   binary representation of the variables to fill the new instance
444 
445   @param[out] Handle - Handle for a variable serialization instance
446   @param[in]  Buffer - A buffer with the serialized representation
447                 of the variables.  Must be the same format as produced
448                 by SerializeVariablesToBuffer.
449   @param[in]  Size - This is the size of the binary representation
450                 of the variables.
451 
452   @retval      RETURN_SUCCESS - The binary representation was successfully
453                  imported into a new variable serialization instance
454   @retval      RETURN_OUT_OF_RESOURCES - There we not enough resources to
455                  create the new variable serialization instance
456 
457 **/
458 RETURN_STATUS
459 EFIAPI
SerializeVariablesNewInstanceFromBuffer(OUT EFI_HANDLE * Handle,IN VOID * Buffer,IN UINTN Size)460 SerializeVariablesNewInstanceFromBuffer (
461   OUT EFI_HANDLE                          *Handle,
462   IN  VOID                                *Buffer,
463   IN  UINTN                               Size
464   )
465 {
466   RETURN_STATUS Status;
467 
468   Status = SerializeVariablesNewInstance (Handle);
469   if (RETURN_ERROR (Status)) {
470     return Status;
471   }
472 
473   Status = IterateVariablesInBuffer (
474              IterateVariablesCallbackNop,
475              NULL,
476              Buffer,
477              Size
478              );
479   if (RETURN_ERROR (Status)) {
480     SerializeVariablesFreeInstance (*Handle);
481     return Status;
482   }
483 
484   Status = IterateVariablesInBuffer (
485              IterateVariablesCallbackSetInInstance,
486              (VOID*) *Handle,
487              Buffer,
488              Size
489              );
490   if (RETURN_ERROR (Status)) {
491     SerializeVariablesFreeInstance (*Handle);
492     return Status;
493   }
494 
495   return Status;
496 }
497 
498 
499 /**
500   Iterates all variables found with RuntimeServices GetNextVariableName
501 
502   @param[in]   CallbackFunction - Function called for each variable instance
503   @param[in]   Context - Passed to each call of CallbackFunction
504 
505   @retval      RETURN_SUCCESS - All variables were iterated without the
506                  CallbackFunction returning an error
507   @retval      RETURN_OUT_OF_RESOURCES - There we not enough resources to
508                  iterate through the variables
509   @return      Any of RETURN_ERROR indicates an error reading the variable
510                  or an error was returned from CallbackFunction
511 
512 **/
513 RETURN_STATUS
514 EFIAPI
SerializeVariablesIterateSystemVariables(IN VARIABLE_SERIALIZATION_ITERATION_CALLBACK CallbackFunction,IN VOID * Context)515 SerializeVariablesIterateSystemVariables (
516   IN VARIABLE_SERIALIZATION_ITERATION_CALLBACK CallbackFunction,
517   IN VOID                                      *Context
518   )
519 {
520   RETURN_STATUS               Status;
521   UINTN                       VariableNameBufferSize;
522   UINTN                       VariableNameSize;
523   CHAR16                      *VariableName;
524   EFI_GUID                    VendorGuid;
525   UINTN                       VariableDataBufferSize;
526   UINTN                       VariableDataSize;
527   VOID                        *VariableData;
528   UINT32                      VariableAttributes;
529   VOID                        *NewBuffer;
530 
531   //
532   // Initialize the variable name and data buffer variables.
533   //
534   VariableNameBufferSize = sizeof (CHAR16);
535   VariableName = AllocateZeroPool (VariableNameBufferSize);
536 
537   VariableDataBufferSize = 0;
538   VariableData = NULL;
539 
540   for (;;) {
541     //
542     // Get the next variable name and guid
543     //
544     VariableNameSize = VariableNameBufferSize;
545     Status = gRT->GetNextVariableName (
546                     &VariableNameSize,
547                     VariableName,
548                     &VendorGuid
549                     );
550     if (Status == EFI_BUFFER_TOO_SMALL) {
551       //
552       // The currently allocated VariableName buffer is too small,
553       // so we allocate a larger buffer, and copy the old buffer
554       // to it.
555       //
556       NewBuffer = AllocatePool (VariableNameSize);
557       if (NewBuffer == NULL) {
558         Status = EFI_OUT_OF_RESOURCES;
559         break;
560       }
561       CopyMem (NewBuffer, VariableName, VariableNameBufferSize);
562       if (VariableName != NULL) {
563         FreePool (VariableName);
564       }
565       VariableName = NewBuffer;
566       VariableNameBufferSize = VariableNameSize;
567 
568       //
569       // Try to get the next variable name again with the larger buffer.
570       //
571       Status = gRT->GetNextVariableName (
572                       &VariableNameSize,
573                       VariableName,
574                       &VendorGuid
575                       );
576     }
577 
578     if (EFI_ERROR (Status)) {
579       if (Status == EFI_NOT_FOUND) {
580         Status = EFI_SUCCESS;
581       }
582       break;
583     }
584 
585     //
586     // Get the variable data and attributes
587     //
588     VariableDataSize = VariableDataBufferSize;
589     Status = gRT->GetVariable (
590                     VariableName,
591                     &VendorGuid,
592                     &VariableAttributes,
593                     &VariableDataSize,
594                     VariableData
595                     );
596     if (Status == EFI_BUFFER_TOO_SMALL) {
597       //
598       // The currently allocated VariableData buffer is too small,
599       // so we allocate a larger buffer.
600       //
601       if (VariableDataBufferSize != 0) {
602         FreePool (VariableData);
603         VariableData = NULL;
604         VariableDataBufferSize = 0;
605       }
606       VariableData = AllocatePool (VariableDataSize);
607       if (VariableData == NULL) {
608         Status = EFI_OUT_OF_RESOURCES;
609         break;
610       }
611       VariableDataBufferSize = VariableDataSize;
612 
613       //
614       // Try to read the variable again with the larger buffer.
615       //
616       Status = gRT->GetVariable (
617                       VariableName,
618                       &VendorGuid,
619                       &VariableAttributes,
620                       &VariableDataSize,
621                       VariableData
622                       );
623     }
624     if (EFI_ERROR (Status)) {
625       break;
626     }
627 
628     //
629     // Run the callback function
630     //
631     Status = (*CallbackFunction) (
632                Context,
633                VariableName,
634                &VendorGuid,
635                VariableAttributes,
636                VariableDataSize,
637                VariableData
638                );
639     if (EFI_ERROR (Status)) {
640       break;
641     }
642 
643   }
644 
645   if (VariableName != NULL) {
646     FreePool (VariableName);
647   }
648 
649   if (VariableData != NULL) {
650     FreePool (VariableData);
651   }
652 
653   return Status;
654 }
655 
656 
657 /**
658   Iterates all variables found in the variable serialization instance
659 
660   @param[in]   Handle - Handle for a variable serialization instance
661   @param[in]   CallbackFunction - Function called for each variable instance
662   @param[in]   Context - Passed to each call of CallbackFunction
663 
664   @retval      RETURN_SUCCESS - All variables were iterated without the
665                  CallbackFunction returning an error
666   @retval      RETURN_OUT_OF_RESOURCES - There we not enough resources to
667                  iterate through the variables
668   @return      Any of RETURN_ERROR indicates an error reading the variable
669                  or an error was returned from CallbackFunction
670 
671 **/
672 RETURN_STATUS
673 EFIAPI
SerializeVariablesIterateInstanceVariables(IN EFI_HANDLE Handle,IN VARIABLE_SERIALIZATION_ITERATION_CALLBACK CallbackFunction,IN VOID * Context)674 SerializeVariablesIterateInstanceVariables (
675   IN EFI_HANDLE                                Handle,
676   IN VARIABLE_SERIALIZATION_ITERATION_CALLBACK CallbackFunction,
677   IN VOID                                      *Context
678   )
679 {
680   SV_INSTANCE    *Instance;
681 
682   Instance = SV_FROM_HANDLE (Handle);
683 
684   if ((Instance->BufferPtr != NULL) && (Instance->DataSize != 0)) {
685     return IterateVariablesInBuffer (
686              CallbackFunction,
687              Context,
688              Instance->BufferPtr,
689              Instance->DataSize
690              );
691   } else {
692     return RETURN_SUCCESS;
693   }
694 }
695 
696 
697 /**
698   Sets all variables found in the variable serialization instance
699 
700   @param[in]   Handle - Handle for a variable serialization instance
701 
702   @retval      RETURN_SUCCESS - All variables were set successfully
703   @retval      RETURN_OUT_OF_RESOURCES - There we not enough resources to
704                  set all the variables
705   @return      Any of RETURN_ERROR indicates an error reading the variables
706                  or in attempting to set a variable
707 
708 **/
709 RETURN_STATUS
710 EFIAPI
SerializeVariablesSetSerializedVariables(IN EFI_HANDLE Handle)711 SerializeVariablesSetSerializedVariables (
712   IN EFI_HANDLE                       Handle
713   )
714 {
715   return SerializeVariablesIterateInstanceVariables (
716            Handle,
717            IterateVariablesCallbackSetSystemVariable,
718            NULL
719            );
720 }
721 
722 
723 /**
724   Adds a variable to the variable serialization instance
725 
726   @param[in] Handle - Handle for a variable serialization instance
727   @param[in] VariableName - Refer to RuntimeServices GetVariable
728   @param[in] VendorGuid - Refer to RuntimeServices GetVariable
729   @param[in] Attributes - Refer to RuntimeServices GetVariable
730   @param[in] DataSize - Refer to RuntimeServices GetVariable
731   @param[in] Data - Refer to RuntimeServices GetVariable
732 
733   @retval      RETURN_SUCCESS - All variables were set successfully
734   @retval      RETURN_OUT_OF_RESOURCES - There we not enough resources to
735                  add the variable
736   @retval      RETURN_INVALID_PARAMETER - Handle was not a valid
737                  variable serialization instance or
738                  VariableName, VariableGuid or Data are NULL.
739 
740 **/
741 RETURN_STATUS
742 EFIAPI
SerializeVariablesAddVariable(IN EFI_HANDLE Handle,IN CHAR16 * VariableName,IN EFI_GUID * VendorGuid,IN UINT32 Attributes,IN UINTN DataSize,IN VOID * Data)743 SerializeVariablesAddVariable (
744   IN EFI_HANDLE                   Handle,
745   IN CHAR16                       *VariableName,
746   IN EFI_GUID                     *VendorGuid,
747   IN UINT32                       Attributes,
748   IN UINTN                        DataSize,
749   IN VOID                         *Data
750   )
751 {
752   RETURN_STATUS  Status;
753   SV_INSTANCE    *Instance;
754   UINT32         SerializedNameSize;
755   UINT32         SerializedDataSize;
756   UINTN          SerializedSize;
757 
758   Instance = SV_FROM_HANDLE (Handle);
759 
760   if ((Instance->Signature != SV_SIGNATURE) ||
761       (VariableName == NULL) || (VendorGuid == NULL) || (Data == NULL)) {
762   }
763 
764   SerializedNameSize = (UINT32) StrSize (VariableName);
765 
766   SerializedSize =
767     sizeof (SerializedNameSize) +
768     SerializedNameSize +
769     sizeof (*VendorGuid) +
770     sizeof (Attributes) +
771     sizeof (SerializedDataSize) +
772     DataSize;
773 
774   Status = EnsureExtraBufferSpace (
775              Instance,
776              SerializedSize
777              );
778   if (RETURN_ERROR (Status)) {
779     return Status;
780   }
781 
782   //
783   // Add name size (UINT32)
784   //
785   AppendToBuffer (Instance, (VOID*) &SerializedNameSize, sizeof (SerializedNameSize));
786 
787   //
788   // Add variable unicode name string
789   //
790   AppendToBuffer (Instance, (VOID*) VariableName, SerializedNameSize);
791 
792   //
793   // Add variable GUID
794   //
795   AppendToBuffer (Instance, (VOID*) VendorGuid, sizeof (*VendorGuid));
796 
797   //
798   // Add variable attributes
799   //
800   AppendToBuffer (Instance, (VOID*) &Attributes, sizeof (Attributes));
801 
802   //
803   // Add variable data size (UINT32)
804   //
805   SerializedDataSize = (UINT32) DataSize;
806   AppendToBuffer (Instance, (VOID*) &SerializedDataSize, sizeof (SerializedDataSize));
807 
808   //
809   // Add variable data
810   //
811   AppendToBuffer (Instance, Data, DataSize);
812 
813   return RETURN_SUCCESS;
814 }
815 
816 
817 /**
818   Serializes the variables known to this instance into the
819   provided buffer.
820 
821   @param[in]     Handle - Handle for a variable serialization instance
822   @param[out]    Buffer - A buffer to store the binary representation
823                    of the variables.
824   @param[in,out] Size - On input this is the size of the buffer.
825                    On output this is the size of the binary representation
826                    of the variables.
827 
828   @retval      RETURN_SUCCESS - The binary representation was successfully
829                  completed and returned in the buffer.
830   @retval      RETURN_OUT_OF_RESOURCES - There we not enough resources to
831                  save the variables to the buffer.
832   @retval      RETURN_INVALID_PARAMETER - Handle was not a valid
833                  variable serialization instance or
834                  Size or Buffer were NULL.
835   @retval      RETURN_BUFFER_TOO_SMALL - The Buffer size as indicated by
836                  the Size parameter was too small for the serialized
837                  variable data.  Size is returned with the required size.
838 
839 **/
840 RETURN_STATUS
841 EFIAPI
SerializeVariablesToBuffer(IN EFI_HANDLE Handle,OUT VOID * Buffer,IN OUT UINTN * Size)842 SerializeVariablesToBuffer (
843   IN     EFI_HANDLE                       Handle,
844   OUT    VOID                             *Buffer,
845   IN OUT UINTN                            *Size
846   )
847 {
848   SV_INSTANCE    *Instance;
849 
850   Instance = SV_FROM_HANDLE (Handle);
851 
852   if (Size == NULL) {
853     return RETURN_INVALID_PARAMETER;
854   }
855 
856   if (*Size < Instance->DataSize) {
857     *Size = Instance->DataSize;
858     return RETURN_BUFFER_TOO_SMALL;
859   }
860 
861   if (Buffer == NULL) {
862     return RETURN_INVALID_PARAMETER;
863   }
864 
865   *Size = Instance->DataSize;
866   CopyMem (Buffer, Instance->BufferPtr, Instance->DataSize);
867 
868   return RETURN_SUCCESS;
869 }
870 
871