mirror of
https://github.com/CloverHackyColor/CloverBootloader.git
synced 2024-12-11 14:28:08 +01:00
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",
|
||
|
__func__,
|
||
|
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",
|
||
|
__func__,
|
||
|
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;
|
||
|
}
|