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