REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3737 Apply uncrustify changes to .c/.h files in the OvmfPkg package Cc: Andrew Fish <afish@apple.com> Cc: Leif Lindholm <leif@nuviainc.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com> Reviewed-by: Andrew Fish <afish@apple.com>
		
			
				
	
	
		
			872 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			872 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   Serialize Variables Library implementation
 | |
| 
 | |
|   Copyright (c) 2004 - 2011, Intel Corporation. All rights reserved.<BR>
 | |
|   SPDX-License-Identifier: BSD-2-Clause-Patent
 | |
| 
 | |
| **/
 | |
| 
 | |
| #include "SerializeVariablesLib.h"
 | |
| 
 | |
| /**
 | |
|   Serialization format:
 | |
| 
 | |
|   The SerializeVariablesLib interface does not specify a format
 | |
|   for the serialization of the variable data.  This library uses
 | |
|   a packed array of a non-uniformly sized data structure elements.
 | |
| 
 | |
|   Each variable is stored (packed) as:
 | |
|     UINT32   VendorNameSize;  // Name size in bytes
 | |
|     CHAR16   VendorName[?];   // The variable unicode name including the
 | |
|                               // null terminating character.
 | |
|     EFI_GUID VendorGuid;      // The variable GUID
 | |
|     UINT32   DataSize;        // The size of variable data in bytes
 | |
|     UINT8    Data[?];         // The variable data
 | |
| 
 | |
| **/
 | |
| 
 | |
| /**
 | |
|   Unpacks the next variable from the buffer
 | |
| 
 | |
|   @param[in]  Buffer - Buffer pointing to the next variable instance
 | |
|                 On subsequent calls, the pointer should be incremented
 | |
|                 by the returned SizeUsed value.
 | |
|   @param[in]  MaxSize - Max allowable size for the variable data
 | |
|                 On subsequent calls, this should be decremented
 | |
|                 by the returned SizeUsed value.
 | |
|   @param[out] Name - Variable name string (address in Buffer)
 | |
|   @param[out] NameSize - Size of Name in bytes
 | |
|   @param[out] Guid - GUID of variable (address in Buffer)
 | |
|   @param[out] Attributes - Attributes of variable
 | |
|   @param[out] Data - Buffer containing Data for variable (address in Buffer)
 | |
|   @param[out] DataSize - Size of Data in bytes
 | |
|   @param[out] SizeUsed - Total size used for this variable instance in Buffer
 | |
| 
 | |
|   @return     EFI_STATUS based on the success or failure of the operation
 | |
| 
 | |
| **/
 | |
| STATIC
 | |
| 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
 | |
|   )
 | |
| {
 | |
|   UINT8  *BytePtr;
 | |
|   UINTN  Offset;
 | |
| 
 | |
|   BytePtr = (UINT8 *)Buffer;
 | |
|   Offset  = 0;
 | |
| 
 | |
|   *NameSize = *(UINT32 *)(BytePtr + Offset);
 | |
|   Offset    = Offset + sizeof (UINT32);
 | |
| 
 | |
|   if (Offset > MaxSize) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   *Name  = (CHAR16 *)(BytePtr + Offset);
 | |
|   Offset = Offset + *(UINT32 *)BytePtr;
 | |
|   if (Offset > MaxSize) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   *Guid  = (EFI_GUID *)(BytePtr + Offset);
 | |
|   Offset = Offset + sizeof (EFI_GUID);
 | |
|   if (Offset > MaxSize) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   *Attributes = *(UINT32 *)(BytePtr + Offset);
 | |
|   Offset      = Offset + sizeof (UINT32);
 | |
|   if (Offset > MaxSize) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   *DataSize = *(UINT32 *)(BytePtr + Offset);
 | |
|   Offset    = Offset + sizeof (UINT32);
 | |
|   if (Offset > MaxSize) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   *Data  = (VOID *)(BytePtr + Offset);
 | |
|   Offset = Offset + *DataSize;
 | |
|   if (Offset > MaxSize) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   *SizeUsed = Offset;
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Iterates through the variables in the buffer, and calls a callback
 | |
|   function for each variable found.
 | |
| 
 | |
|   @param[in]  CallbackFunction - Function called for each variable instance
 | |
|   @param[in]  Context - Passed to each call of CallbackFunction
 | |
|   @param[in]  Buffer - Buffer containing serialized variables
 | |
|   @param[in]  MaxSize - Size of Buffer in bytes
 | |
| 
 | |
|   @return     EFI_STATUS based on the success or failure of the operation
 | |
| 
 | |
| **/
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| IterateVariablesInBuffer (
 | |
|   IN VARIABLE_SERIALIZATION_ITERATION_CALLBACK  CallbackFunction,
 | |
|   IN VOID                                       *CallbackContext,
 | |
|   IN VOID                                       *Buffer,
 | |
|   IN UINTN                                      MaxSize
 | |
|   )
 | |
| {
 | |
|   RETURN_STATUS  Status;
 | |
|   UINTN          TotalSizeUsed;
 | |
|   UINTN          SizeUsed;
 | |
| 
 | |
|   CHAR16    *Name;
 | |
|   UINT32    NameSize;
 | |
|   CHAR16    *AlignedName;
 | |
|   UINT32    AlignedNameMaxSize;
 | |
|   EFI_GUID  *Guid;
 | |
|   UINT32    Attributes;
 | |
|   UINT32    DataSize;
 | |
|   VOID      *Data;
 | |
| 
 | |
|   SizeUsed           = 0;
 | |
|   AlignedName        = NULL;
 | |
|   AlignedNameMaxSize = 0;
 | |
|   Name               = NULL;
 | |
|   Guid               = NULL;
 | |
|   Attributes         = 0;
 | |
|   DataSize           = 0;
 | |
|   Data               = NULL;
 | |
| 
 | |
|   for (
 | |
|        Status = EFI_SUCCESS, TotalSizeUsed = 0;
 | |
|        !EFI_ERROR (Status) && (TotalSizeUsed < MaxSize);
 | |
|        )
 | |
|   {
 | |
|     Status = UnpackVariableFromBuffer (
 | |
|                (VOID *)((UINT8 *)Buffer + TotalSizeUsed),
 | |
|                (MaxSize - TotalSizeUsed),
 | |
|                &Name,
 | |
|                &NameSize,
 | |
|                &Guid,
 | |
|                &Attributes,
 | |
|                &DataSize,
 | |
|                &Data,
 | |
|                &SizeUsed
 | |
|                );
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       return Status;
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // We copy the name to a separately allocated buffer,
 | |
|     // to be sure it is 16-bit aligned.
 | |
|     //
 | |
|     if (NameSize > AlignedNameMaxSize) {
 | |
|       if (AlignedName != NULL) {
 | |
|         FreePool (AlignedName);
 | |
|       }
 | |
| 
 | |
|       AlignedName = AllocatePool (NameSize);
 | |
|     }
 | |
| 
 | |
|     if (AlignedName == NULL) {
 | |
|       return EFI_OUT_OF_RESOURCES;
 | |
|     }
 | |
| 
 | |
|     CopyMem (AlignedName, Name, NameSize);
 | |
| 
 | |
|     TotalSizeUsed = TotalSizeUsed + SizeUsed;
 | |
| 
 | |
|     //
 | |
|     // Run the callback function
 | |
|     //
 | |
|     Status = (*CallbackFunction)(
 | |
|   CallbackContext,
 | |
|   AlignedName,
 | |
|   Guid,
 | |
|   Attributes,
 | |
|   DataSize,
 | |
|   Data
 | |
|   );
 | |
|   }
 | |
| 
 | |
|   if (AlignedName != NULL) {
 | |
|     FreePool (AlignedName);
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Make sure the entire buffer was used, or else return an error
 | |
|   //
 | |
|   if (TotalSizeUsed != MaxSize) {
 | |
|     DEBUG ((
 | |
|       DEBUG_ERROR,
 | |
|       "Deserialize variables error: TotalSizeUsed(%Lu) != MaxSize(%Lu)\n",
 | |
|       (UINT64)TotalSizeUsed,
 | |
|       (UINT64)MaxSize
 | |
|       ));
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| STATIC
 | |
| RETURN_STATUS
 | |
| EFIAPI
 | |
| IterateVariablesCallbackNop (
 | |
|   IN  VOID      *Context,
 | |
|   IN  CHAR16    *VariableName,
 | |
|   IN  EFI_GUID  *VendorGuid,
 | |
|   IN  UINT32    Attributes,
 | |
|   IN  UINTN     DataSize,
 | |
|   IN  VOID      *Data
 | |
|   )
 | |
| {
 | |
|   return RETURN_SUCCESS;
 | |
| }
 | |
| 
 | |
| STATIC
 | |
| RETURN_STATUS
 | |
| EFIAPI
 | |
| IterateVariablesCallbackSetInInstance (
 | |
|   IN  VOID      *Context,
 | |
|   IN  CHAR16    *VariableName,
 | |
|   IN  EFI_GUID  *VendorGuid,
 | |
|   IN  UINT32    Attributes,
 | |
|   IN  UINTN     DataSize,
 | |
|   IN  VOID      *Data
 | |
|   )
 | |
| {
 | |
|   EFI_HANDLE  Instance;
 | |
| 
 | |
|   Instance = (EFI_HANDLE)Context;
 | |
| 
 | |
|   return SerializeVariablesAddVariable (
 | |
|            Instance,
 | |
|            VariableName,
 | |
|            VendorGuid,
 | |
|            Attributes,
 | |
|            DataSize,
 | |
|            Data
 | |
|            );
 | |
| }
 | |
| 
 | |
| STATIC
 | |
| RETURN_STATUS
 | |
| EFIAPI
 | |
| IterateVariablesCallbackSetSystemVariable (
 | |
|   IN  VOID      *Context,
 | |
|   IN  CHAR16    *VariableName,
 | |
|   IN  EFI_GUID  *VendorGuid,
 | |
|   IN  UINT32    Attributes,
 | |
|   IN  UINTN     DataSize,
 | |
|   IN  VOID      *Data
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS           Status;
 | |
|   STATIC CONST UINT32  AuthMask =
 | |
|     EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS |
 | |
|     EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
 | |
| 
 | |
|   Status = gRT->SetVariable (
 | |
|                   VariableName,
 | |
|                   VendorGuid,
 | |
|                   Attributes,
 | |
|                   DataSize,
 | |
|                   Data
 | |
|                   );
 | |
| 
 | |
|   if ((Status == EFI_SECURITY_VIOLATION) && ((Attributes & AuthMask) != 0)) {
 | |
|     DEBUG ((
 | |
|       DEBUG_WARN,
 | |
|       "%a: setting authenticated variable \"%s\" "
 | |
|       "failed with EFI_SECURITY_VIOLATION, ignoring\n",
 | |
|       __FUNCTION__,
 | |
|       VariableName
 | |
|       ));
 | |
|     Status = EFI_SUCCESS;
 | |
|   } else if (Status == EFI_WRITE_PROTECTED) {
 | |
|     DEBUG ((
 | |
|       DEBUG_WARN,
 | |
|       "%a: setting ReadOnly variable \"%s\" "
 | |
|       "failed with EFI_WRITE_PROTECTED, ignoring\n",
 | |
|       __FUNCTION__,
 | |
|       VariableName
 | |
|       ));
 | |
|     Status = EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| STATIC
 | |
| RETURN_STATUS
 | |
| EnsureExtraBufferSpace (
 | |
|   IN  SV_INSTANCE  *Instance,
 | |
|   IN  UINTN        Size
 | |
|   )
 | |
| {
 | |
|   VOID   *NewBuffer;
 | |
|   UINTN  NewSize;
 | |
| 
 | |
|   NewSize = Instance->DataSize + Size;
 | |
|   if (NewSize <= Instance->BufferSize) {
 | |
|     return RETURN_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Double the required size to lessen the need to re-allocate in the future
 | |
|   //
 | |
|   NewSize = 2 * NewSize;
 | |
| 
 | |
|   NewBuffer = AllocatePool (NewSize);
 | |
|   if (NewBuffer == NULL) {
 | |
|     return RETURN_OUT_OF_RESOURCES;
 | |
|   }
 | |
| 
 | |
|   if (Instance->BufferPtr != NULL) {
 | |
|     CopyMem (NewBuffer, Instance->BufferPtr, Instance->DataSize);
 | |
|     FreePool (Instance->BufferPtr);
 | |
|   }
 | |
| 
 | |
|   Instance->BufferPtr  = NewBuffer;
 | |
|   Instance->BufferSize = NewSize;
 | |
| 
 | |
|   return RETURN_SUCCESS;
 | |
| }
 | |
| 
 | |
| STATIC
 | |
| VOID
 | |
| AppendToBuffer (
 | |
|   IN  SV_INSTANCE  *Instance,
 | |
|   IN  VOID         *Data,
 | |
|   IN  UINTN        Size
 | |
|   )
 | |
| {
 | |
|   UINTN  NewSize;
 | |
| 
 | |
|   ASSERT (Instance != NULL);
 | |
|   ASSERT (Data != NULL);
 | |
| 
 | |
|   NewSize = Instance->DataSize + Size;
 | |
|   ASSERT ((Instance->DataSize + Size) <= Instance->BufferSize);
 | |
| 
 | |
|   CopyMem (
 | |
|     (VOID *)(((UINT8 *)(Instance->BufferPtr)) + Instance->DataSize),
 | |
|     Data,
 | |
|     Size
 | |
|     );
 | |
| 
 | |
|   Instance->DataSize = NewSize;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Creates a new variable serialization instance
 | |
| 
 | |
|   @param[out]  Handle - Handle for a variable serialization instance
 | |
| 
 | |
|   @retval      RETURN_SUCCESS - The variable serialization instance was
 | |
|                  successfully created.
 | |
|   @retval      RETURN_OUT_OF_RESOURCES - There we not enough resources to
 | |
|                  create the variable serialization instance.
 | |
| 
 | |
| **/
 | |
| RETURN_STATUS
 | |
| EFIAPI
 | |
| SerializeVariablesNewInstance (
 | |
|   OUT EFI_HANDLE  *Handle
 | |
|   )
 | |
| {
 | |
|   SV_INSTANCE  *New;
 | |
| 
 | |
|   New = AllocateZeroPool (sizeof (*New));
 | |
|   if (New == NULL) {
 | |
|     return RETURN_OUT_OF_RESOURCES;
 | |
|   }
 | |
| 
 | |
|   New->Signature = SV_SIGNATURE;
 | |
| 
 | |
|   *Handle = (EFI_HANDLE)New;
 | |
|   return RETURN_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Free memory associated with a variable serialization instance
 | |
| 
 | |
|   @param[in]  Handle - Handle for a variable serialization instance
 | |
| 
 | |
|   @retval      RETURN_SUCCESS - The variable serialization instance was
 | |
|                  successfully freed.
 | |
|   @retval      RETURN_INVALID_PARAMETER - Handle was not a valid
 | |
|                  variable serialization instance.
 | |
| 
 | |
| **/
 | |
| RETURN_STATUS
 | |
| EFIAPI
 | |
| SerializeVariablesFreeInstance (
 | |
|   IN EFI_HANDLE  Handle
 | |
|   )
 | |
| {
 | |
|   SV_INSTANCE  *Instance;
 | |
| 
 | |
|   Instance = SV_FROM_HANDLE (Handle);
 | |
| 
 | |
|   if (Instance->Signature != SV_SIGNATURE) {
 | |
|     return RETURN_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   Instance->Signature = 0;
 | |
| 
 | |
|   if (Instance->BufferPtr != NULL) {
 | |
|     FreePool (Instance->BufferPtr);
 | |
|   }
 | |
| 
 | |
|   FreePool (Instance);
 | |
| 
 | |
|   return RETURN_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Creates a new variable serialization instance using the given
 | |
|   binary representation of the variables to fill the new instance
 | |
| 
 | |
|   @param[out] Handle - Handle for a variable serialization instance
 | |
|   @param[in]  Buffer - A buffer with the serialized representation
 | |
|                 of the variables.  Must be the same format as produced
 | |
|                 by SerializeVariablesToBuffer.
 | |
|   @param[in]  Size - This is the size of the binary representation
 | |
|                 of the variables.
 | |
| 
 | |
|   @retval      RETURN_SUCCESS - The binary representation was successfully
 | |
|                  imported into a new variable serialization instance
 | |
|   @retval      RETURN_OUT_OF_RESOURCES - There we not enough resources to
 | |
|                  create the new variable serialization instance
 | |
| 
 | |
| **/
 | |
| RETURN_STATUS
 | |
| EFIAPI
 | |
| SerializeVariablesNewInstanceFromBuffer (
 | |
|   OUT EFI_HANDLE  *Handle,
 | |
|   IN  VOID        *Buffer,
 | |
|   IN  UINTN       Size
 | |
|   )
 | |
| {
 | |
|   RETURN_STATUS  Status;
 | |
| 
 | |
|   Status = SerializeVariablesNewInstance (Handle);
 | |
|   if (RETURN_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   Status = IterateVariablesInBuffer (
 | |
|              IterateVariablesCallbackNop,
 | |
|              NULL,
 | |
|              Buffer,
 | |
|              Size
 | |
|              );
 | |
|   if (RETURN_ERROR (Status)) {
 | |
|     SerializeVariablesFreeInstance (*Handle);
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   Status = IterateVariablesInBuffer (
 | |
|              IterateVariablesCallbackSetInInstance,
 | |
|              (VOID *)*Handle,
 | |
|              Buffer,
 | |
|              Size
 | |
|              );
 | |
|   if (RETURN_ERROR (Status)) {
 | |
|     SerializeVariablesFreeInstance (*Handle);
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Iterates all variables found with RuntimeServices GetNextVariableName
 | |
| 
 | |
|   @param[in]   CallbackFunction - Function called for each variable instance
 | |
|   @param[in]   Context - Passed to each call of CallbackFunction
 | |
| 
 | |
|   @retval      RETURN_SUCCESS - All variables were iterated without the
 | |
|                  CallbackFunction returning an error
 | |
|   @retval      RETURN_OUT_OF_RESOURCES - There we not enough resources to
 | |
|                  iterate through the variables
 | |
|   @return      Any of RETURN_ERROR indicates an error reading the variable
 | |
|                  or an error was returned from CallbackFunction
 | |
| 
 | |
| **/
 | |
| RETURN_STATUS
 | |
| EFIAPI
 | |
| SerializeVariablesIterateSystemVariables (
 | |
|   IN VARIABLE_SERIALIZATION_ITERATION_CALLBACK  CallbackFunction,
 | |
|   IN VOID                                       *Context
 | |
|   )
 | |
| {
 | |
|   RETURN_STATUS  Status;
 | |
|   UINTN          VariableNameBufferSize;
 | |
|   UINTN          VariableNameSize;
 | |
|   CHAR16         *VariableName;
 | |
|   EFI_GUID       VendorGuid;
 | |
|   UINTN          VariableDataBufferSize;
 | |
|   UINTN          VariableDataSize;
 | |
|   VOID           *VariableData;
 | |
|   UINT32         VariableAttributes;
 | |
|   VOID           *NewBuffer;
 | |
| 
 | |
|   //
 | |
|   // Initialize the variable name and data buffer variables.
 | |
|   //
 | |
|   VariableNameBufferSize = sizeof (CHAR16);
 | |
|   VariableName           = AllocateZeroPool (VariableNameBufferSize);
 | |
| 
 | |
|   VariableDataBufferSize = 0;
 | |
|   VariableData           = NULL;
 | |
| 
 | |
|   for ( ; ;) {
 | |
|     //
 | |
|     // Get the next variable name and guid
 | |
|     //
 | |
|     VariableNameSize = VariableNameBufferSize;
 | |
|     Status           = gRT->GetNextVariableName (
 | |
|                               &VariableNameSize,
 | |
|                               VariableName,
 | |
|                               &VendorGuid
 | |
|                               );
 | |
|     if (Status == EFI_BUFFER_TOO_SMALL) {
 | |
|       //
 | |
|       // The currently allocated VariableName buffer is too small,
 | |
|       // so we allocate a larger buffer, and copy the old buffer
 | |
|       // to it.
 | |
|       //
 | |
|       NewBuffer = AllocatePool (VariableNameSize);
 | |
|       if (NewBuffer == NULL) {
 | |
|         Status = EFI_OUT_OF_RESOURCES;
 | |
|         break;
 | |
|       }
 | |
| 
 | |
|       CopyMem (NewBuffer, VariableName, VariableNameBufferSize);
 | |
|       if (VariableName != NULL) {
 | |
|         FreePool (VariableName);
 | |
|       }
 | |
| 
 | |
|       VariableName           = NewBuffer;
 | |
|       VariableNameBufferSize = VariableNameSize;
 | |
| 
 | |
|       //
 | |
|       // Try to get the next variable name again with the larger buffer.
 | |
|       //
 | |
|       Status = gRT->GetNextVariableName (
 | |
|                       &VariableNameSize,
 | |
|                       VariableName,
 | |
|                       &VendorGuid
 | |
|                       );
 | |
|     }
 | |
| 
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       if (Status == EFI_NOT_FOUND) {
 | |
|         Status = EFI_SUCCESS;
 | |
|       }
 | |
| 
 | |
|       break;
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Get the variable data and attributes
 | |
|     //
 | |
|     VariableDataSize = VariableDataBufferSize;
 | |
|     Status           = gRT->GetVariable (
 | |
|                               VariableName,
 | |
|                               &VendorGuid,
 | |
|                               &VariableAttributes,
 | |
|                               &VariableDataSize,
 | |
|                               VariableData
 | |
|                               );
 | |
|     if (Status == EFI_BUFFER_TOO_SMALL) {
 | |
|       //
 | |
|       // The currently allocated VariableData buffer is too small,
 | |
|       // so we allocate a larger buffer.
 | |
|       //
 | |
|       if (VariableDataBufferSize != 0) {
 | |
|         FreePool (VariableData);
 | |
|         VariableData           = NULL;
 | |
|         VariableDataBufferSize = 0;
 | |
|       }
 | |
| 
 | |
|       VariableData = AllocatePool (VariableDataSize);
 | |
|       if (VariableData == NULL) {
 | |
|         Status = EFI_OUT_OF_RESOURCES;
 | |
|         break;
 | |
|       }
 | |
| 
 | |
|       VariableDataBufferSize = VariableDataSize;
 | |
| 
 | |
|       //
 | |
|       // Try to read the variable again with the larger buffer.
 | |
|       //
 | |
|       Status = gRT->GetVariable (
 | |
|                       VariableName,
 | |
|                       &VendorGuid,
 | |
|                       &VariableAttributes,
 | |
|                       &VariableDataSize,
 | |
|                       VariableData
 | |
|                       );
 | |
|     }
 | |
| 
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       break;
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Run the callback function
 | |
|     //
 | |
|     Status = (*CallbackFunction)(
 | |
|   Context,
 | |
|   VariableName,
 | |
|   &VendorGuid,
 | |
|   VariableAttributes,
 | |
|   VariableDataSize,
 | |
|   VariableData
 | |
|   );
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       break;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (VariableName != NULL) {
 | |
|     FreePool (VariableName);
 | |
|   }
 | |
| 
 | |
|   if (VariableData != NULL) {
 | |
|     FreePool (VariableData);
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Iterates all variables found in the variable serialization instance
 | |
| 
 | |
|   @param[in]   Handle - Handle for a variable serialization instance
 | |
|   @param[in]   CallbackFunction - Function called for each variable instance
 | |
|   @param[in]   Context - Passed to each call of CallbackFunction
 | |
| 
 | |
|   @retval      RETURN_SUCCESS - All variables were iterated without the
 | |
|                  CallbackFunction returning an error
 | |
|   @retval      RETURN_OUT_OF_RESOURCES - There we not enough resources to
 | |
|                  iterate through the variables
 | |
|   @return      Any of RETURN_ERROR indicates an error reading the variable
 | |
|                  or an error was returned from CallbackFunction
 | |
| 
 | |
| **/
 | |
| RETURN_STATUS
 | |
| EFIAPI
 | |
| SerializeVariablesIterateInstanceVariables (
 | |
|   IN EFI_HANDLE                                 Handle,
 | |
|   IN VARIABLE_SERIALIZATION_ITERATION_CALLBACK  CallbackFunction,
 | |
|   IN VOID                                       *Context
 | |
|   )
 | |
| {
 | |
|   SV_INSTANCE  *Instance;
 | |
| 
 | |
|   Instance = SV_FROM_HANDLE (Handle);
 | |
| 
 | |
|   if ((Instance->BufferPtr != NULL) && (Instance->DataSize != 0)) {
 | |
|     return IterateVariablesInBuffer (
 | |
|              CallbackFunction,
 | |
|              Context,
 | |
|              Instance->BufferPtr,
 | |
|              Instance->DataSize
 | |
|              );
 | |
|   } else {
 | |
|     return RETURN_SUCCESS;
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Sets all variables found in the variable serialization instance
 | |
| 
 | |
|   @param[in]   Handle - Handle for a variable serialization instance
 | |
| 
 | |
|   @retval      RETURN_SUCCESS - All variables were set successfully
 | |
|   @retval      RETURN_OUT_OF_RESOURCES - There we not enough resources to
 | |
|                  set all the variables
 | |
|   @return      Any of RETURN_ERROR indicates an error reading the variables
 | |
|                  or in attempting to set a variable
 | |
| 
 | |
| **/
 | |
| RETURN_STATUS
 | |
| EFIAPI
 | |
| SerializeVariablesSetSerializedVariables (
 | |
|   IN EFI_HANDLE  Handle
 | |
|   )
 | |
| {
 | |
|   return SerializeVariablesIterateInstanceVariables (
 | |
|            Handle,
 | |
|            IterateVariablesCallbackSetSystemVariable,
 | |
|            NULL
 | |
|            );
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Adds a variable to the variable serialization instance
 | |
| 
 | |
|   @param[in] Handle - Handle for a variable serialization instance
 | |
|   @param[in] VariableName - Refer to RuntimeServices GetVariable
 | |
|   @param[in] VendorGuid - Refer to RuntimeServices GetVariable
 | |
|   @param[in] Attributes - Refer to RuntimeServices GetVariable
 | |
|   @param[in] DataSize - Refer to RuntimeServices GetVariable
 | |
|   @param[in] Data - Refer to RuntimeServices GetVariable
 | |
| 
 | |
|   @retval      RETURN_SUCCESS - All variables were set successfully
 | |
|   @retval      RETURN_OUT_OF_RESOURCES - There we not enough resources to
 | |
|                  add the variable
 | |
|   @retval      RETURN_INVALID_PARAMETER - Handle was not a valid
 | |
|                  variable serialization instance or
 | |
|                  VariableName, VariableGuid or Data are NULL.
 | |
| 
 | |
| **/
 | |
| RETURN_STATUS
 | |
| EFIAPI
 | |
| SerializeVariablesAddVariable (
 | |
|   IN EFI_HANDLE  Handle,
 | |
|   IN CHAR16      *VariableName,
 | |
|   IN EFI_GUID    *VendorGuid,
 | |
|   IN UINT32      Attributes,
 | |
|   IN UINTN       DataSize,
 | |
|   IN VOID        *Data
 | |
|   )
 | |
| {
 | |
|   RETURN_STATUS  Status;
 | |
|   SV_INSTANCE    *Instance;
 | |
|   UINT32         SerializedNameSize;
 | |
|   UINT32         SerializedDataSize;
 | |
|   UINTN          SerializedSize;
 | |
| 
 | |
|   Instance = SV_FROM_HANDLE (Handle);
 | |
| 
 | |
|   if ((Instance->Signature != SV_SIGNATURE) ||
 | |
|       (VariableName == NULL) || (VendorGuid == NULL) || (Data == NULL))
 | |
|   {
 | |
|   }
 | |
| 
 | |
|   SerializedNameSize = (UINT32)StrSize (VariableName);
 | |
| 
 | |
|   SerializedSize =
 | |
|     sizeof (SerializedNameSize) +
 | |
|     SerializedNameSize +
 | |
|     sizeof (*VendorGuid) +
 | |
|     sizeof (Attributes) +
 | |
|     sizeof (SerializedDataSize) +
 | |
|     DataSize;
 | |
| 
 | |
|   Status = EnsureExtraBufferSpace (
 | |
|              Instance,
 | |
|              SerializedSize
 | |
|              );
 | |
|   if (RETURN_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Add name size (UINT32)
 | |
|   //
 | |
|   AppendToBuffer (Instance, (VOID *)&SerializedNameSize, sizeof (SerializedNameSize));
 | |
| 
 | |
|   //
 | |
|   // Add variable unicode name string
 | |
|   //
 | |
|   AppendToBuffer (Instance, (VOID *)VariableName, SerializedNameSize);
 | |
| 
 | |
|   //
 | |
|   // Add variable GUID
 | |
|   //
 | |
|   AppendToBuffer (Instance, (VOID *)VendorGuid, sizeof (*VendorGuid));
 | |
| 
 | |
|   //
 | |
|   // Add variable attributes
 | |
|   //
 | |
|   AppendToBuffer (Instance, (VOID *)&Attributes, sizeof (Attributes));
 | |
| 
 | |
|   //
 | |
|   // Add variable data size (UINT32)
 | |
|   //
 | |
|   SerializedDataSize = (UINT32)DataSize;
 | |
|   AppendToBuffer (Instance, (VOID *)&SerializedDataSize, sizeof (SerializedDataSize));
 | |
| 
 | |
|   //
 | |
|   // Add variable data
 | |
|   //
 | |
|   AppendToBuffer (Instance, Data, DataSize);
 | |
| 
 | |
|   return RETURN_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Serializes the variables known to this instance into the
 | |
|   provided buffer.
 | |
| 
 | |
|   @param[in]     Handle - Handle for a variable serialization instance
 | |
|   @param[out]    Buffer - A buffer to store the binary representation
 | |
|                    of the variables.
 | |
|   @param[in,out] Size - On input this is the size of the buffer.
 | |
|                    On output this is the size of the binary representation
 | |
|                    of the variables.
 | |
| 
 | |
|   @retval      RETURN_SUCCESS - The binary representation was successfully
 | |
|                  completed and returned in the buffer.
 | |
|   @retval      RETURN_OUT_OF_RESOURCES - There we not enough resources to
 | |
|                  save the variables to the buffer.
 | |
|   @retval      RETURN_INVALID_PARAMETER - Handle was not a valid
 | |
|                  variable serialization instance or
 | |
|                  Size or Buffer were NULL.
 | |
|   @retval      RETURN_BUFFER_TOO_SMALL - The Buffer size as indicated by
 | |
|                  the Size parameter was too small for the serialized
 | |
|                  variable data.  Size is returned with the required size.
 | |
| 
 | |
| **/
 | |
| RETURN_STATUS
 | |
| EFIAPI
 | |
| SerializeVariablesToBuffer (
 | |
|   IN     EFI_HANDLE  Handle,
 | |
|   OUT    VOID        *Buffer,
 | |
|   IN OUT UINTN       *Size
 | |
|   )
 | |
| {
 | |
|   SV_INSTANCE  *Instance;
 | |
| 
 | |
|   Instance = SV_FROM_HANDLE (Handle);
 | |
| 
 | |
|   if (Size == NULL) {
 | |
|     return RETURN_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   if (*Size < Instance->DataSize) {
 | |
|     *Size = Instance->DataSize;
 | |
|     return RETURN_BUFFER_TOO_SMALL;
 | |
|   }
 | |
| 
 | |
|   if (Buffer == NULL) {
 | |
|     return RETURN_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   *Size = Instance->DataSize;
 | |
|   CopyMem (Buffer, Instance->BufferPtr, Instance->DataSize);
 | |
| 
 | |
|   return RETURN_SUCCESS;
 | |
| }
 |