Home | History | Annotate | Download | only in SerializeVariablesLib
      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
     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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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