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