mirror of https://github.com/acidanthera/audk.git
346 lines
8.1 KiB
C
346 lines
8.1 KiB
C
/** @file
|
|
File System Access
|
|
|
|
Copyright (c) 2004 - 2009, Intel Corporation. All rights reserved.<BR>
|
|
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 "NvVarsFileLib.h"
|
|
|
|
#include <Library/BaseMemoryLib.h>
|
|
#include <Library/DebugLib.h>
|
|
#include <Library/MemoryAllocationLib.h>
|
|
#include <Library/UefiRuntimeServicesTableLib.h>
|
|
|
|
|
|
/**
|
|
Writes the variable into the file so it can be restored from
|
|
the file on future boots of the system.
|
|
|
|
@param[in] File - The file to write to
|
|
@param[in] Name - Variable name string
|
|
@param[in] NameSize - Size of Name in bytes
|
|
@param[in] Guid - GUID of variable
|
|
@param[in] Attributes - Attributes of variable
|
|
@param[in] Data - Buffer containing Data for variable
|
|
@param[in] DataSize - Size of Data in bytes
|
|
|
|
@return EFI_STATUS based on the success or failure of the operation
|
|
|
|
**/
|
|
EFI_STATUS
|
|
PackVariableIntoFile (
|
|
IN EFI_FILE_HANDLE File,
|
|
IN CHAR16 *Name,
|
|
IN UINT32 NameSize,
|
|
IN EFI_GUID *Guid,
|
|
IN UINT32 Attributes,
|
|
IN VOID *Data,
|
|
IN UINT32 DataSize
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINTN WriteSize;
|
|
|
|
WriteSize = sizeof (NameSize);
|
|
Status = FileHandleWrite (File, &WriteSize, &NameSize);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
WriteSize = NameSize;
|
|
Status = FileHandleWrite (File, &WriteSize, (VOID*) Name);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
WriteSize = sizeof (*Guid);
|
|
Status = FileHandleWrite (File, &WriteSize, (VOID*) Guid);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
WriteSize = sizeof (Attributes);
|
|
Status = FileHandleWrite (File, &WriteSize, &Attributes);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
WriteSize = sizeof (DataSize);
|
|
Status = FileHandleWrite (File, &WriteSize, &DataSize);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
WriteSize = DataSize;
|
|
Status = FileHandleWrite (File, &WriteSize, Data);
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
/**
|
|
Unpacks the next variable from the NvVars file data
|
|
|
|
@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
|
|
|
|
**/
|
|
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;
|
|
}
|
|
|
|
|
|
/**
|
|
Examines the NvVars file contents, and updates variables based on it.
|
|
|
|
@param[in] Buffer - Buffer with NvVars data
|
|
@param[in] MaxSize - Size of Buffer in bytes
|
|
@param[in] DryRun - If TRUE, then no variable modifications should be made
|
|
(If TRUE, the Buffer is still parsed for validity.)
|
|
|
|
@return EFI_STATUS based on the success or failure of the operation
|
|
|
|
**/
|
|
EFI_STATUS
|
|
UnpackVariablesFromBuffer (
|
|
IN VOID *Buffer,
|
|
IN UINTN MaxSize,
|
|
IN BOOLEAN DryRun
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINTN Count;
|
|
UINTN TotalSizeUsed;
|
|
UINTN SizeUsed;
|
|
|
|
CHAR16 *Name;
|
|
UINT32 NameSize;
|
|
CHAR16 *AlignedName;
|
|
UINT32 AlignedNameMaxSize;
|
|
EFI_GUID *Guid;
|
|
UINT32 Attributes;
|
|
UINT32 DataSize;
|
|
VOID *Data;
|
|
|
|
AlignedName = NULL;
|
|
AlignedNameMaxSize = 0;
|
|
|
|
for (
|
|
Status = EFI_SUCCESS, Count = 0, 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);
|
|
|
|
DEBUG ((
|
|
EFI_D_INFO,
|
|
"Unpacked variable %g:%s\n",
|
|
Guid,
|
|
AlignedName
|
|
));
|
|
|
|
TotalSizeUsed = TotalSizeUsed + SizeUsed;
|
|
|
|
DEBUG ((
|
|
EFI_D_INFO,
|
|
"TotalSizeUsed(%d); MaxSize(%d)\n",
|
|
TotalSizeUsed,
|
|
MaxSize
|
|
));
|
|
|
|
if (!DryRun) {
|
|
//
|
|
// Set the variable contents
|
|
//
|
|
gRT->SetVariable (
|
|
AlignedName,
|
|
Guid,
|
|
Attributes,
|
|
DataSize,
|
|
Data
|
|
);
|
|
|
|
Count++;
|
|
|
|
DEBUG ((
|
|
EFI_D_INFO,
|
|
"Restored variable %g:%s\n",
|
|
Guid,
|
|
AlignedName
|
|
));
|
|
}
|
|
|
|
}
|
|
|
|
if (AlignedName != NULL) {
|
|
FreePool (AlignedName);
|
|
}
|
|
|
|
//
|
|
// Make sure the entire buffer was used, or else return an error
|
|
//
|
|
if (TotalSizeUsed != MaxSize) {
|
|
DEBUG ((
|
|
EFI_D_INFO,
|
|
"TotalSizeUsed(%d) != MaxSize(%d)\n",
|
|
TotalSizeUsed,
|
|
MaxSize
|
|
));
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (Count > 0) {
|
|
DEBUG ((
|
|
EFI_D_INFO,
|
|
"Restored %d Variables\n",
|
|
Count
|
|
));
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
|
|
/**
|
|
Examines the NvVars file contents, and updates variables based on it.
|
|
|
|
@param[in] VarsBuffer - Buffer with NvVars data
|
|
@param[in] VarsBufferSize - Size of VarsBuffer in bytes
|
|
|
|
@return EFI_STATUS based on the success or failure of the operation
|
|
|
|
**/
|
|
EFI_STATUS
|
|
SetVariablesFromBuffer (
|
|
IN VOID *VarsBuffer,
|
|
IN UINTN VarsBufferSize
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
//
|
|
// First test to make sure the entire buffer is in a good state
|
|
//
|
|
Status = UnpackVariablesFromBuffer (VarsBuffer, VarsBufferSize, TRUE);
|
|
if (EFI_ERROR (Status)) {
|
|
DEBUG ((EFI_D_INFO, "NvVars buffer format was invalid\n"));
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Now, actually restore the variables.
|
|
//
|
|
Status = UnpackVariablesFromBuffer (VarsBuffer, VarsBufferSize, FALSE);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|