X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=OvmfPkg%2FLibrary%2FSerializeVariablesLib%2FSerializeVariablesLib.c;h=3a24edcd48f47a074b4623ee3d8dc5f7ba3ba0bc;hp=6822c5c725eeb1db909518ed96196a0cf01d4a62;hb=251ca60496719b37e02978bc5b037e2b06a39659;hpb=5679a62a0fb22adadd6483d4d4765397015695f0 diff --git a/OvmfPkg/Library/SerializeVariablesLib/SerializeVariablesLib.c b/OvmfPkg/Library/SerializeVariablesLib/SerializeVariablesLib.c index 6822c5c725..3a24edcd48 100644 --- a/OvmfPkg/Library/SerializeVariablesLib/SerializeVariablesLib.c +++ b/OvmfPkg/Library/SerializeVariablesLib/SerializeVariablesLib.c @@ -1,289 +1,289 @@ -/** @file - Serialize Variables Library implementation - - Copyright (c) 2004 - 2011, Intel Corporation. All rights reserved.
- This program and the accompanying materials - are licensed and made available under the terms and conditions of the BSD License - which accompanies this distribution. The full text of the license may be found at - http://opensource.org/licenses/bsd-license.php - - THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, - WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - -**/ - -#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 (( - EFI_D_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 - ) -{ +/** @file + Serialize Variables Library implementation + + Copyright (c) 2004 - 2011, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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 (( + EFI_D_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 | @@ -304,567 +304,567 @@ IterateVariablesCallbackSetSystemVariable ( 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; -} - +} + + +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; +} +