mirror of https://github.com/acidanthera/audk.git
Implement NvVarsFileLib to save and restore non-volatile variables using a file.
This library provides an interface where variables can be saved and restored using a file in a file system accessible to the firmware. It is expected that a platform BDS library will use this library. The platform BDS implementation can decide which devices to connect and then to attempt to use for saving and restoring NV variables. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@9272 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
parent
af2cfce391
commit
5094454579
|
@ -0,0 +1,35 @@
|
|||
/** @file
|
||||
Provides functions to save and restore NV variables in a file.
|
||||
|
||||
Copyright (c) 2009, Intel Corporation<BR>
|
||||
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.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __NV_VARS_FILE_LIB__
|
||||
#define __NV_VARS_FILE_LIB__
|
||||
|
||||
/**
|
||||
Attempts to connect the NvVarsFileLib to the specified file system.
|
||||
|
||||
@param[in] FsHandle - Handle for a gEfiSimpleFileSystemProtocolGuid instance
|
||||
|
||||
@return The EFI_STATUS while attempting to connect the NvVarsFileLib
|
||||
to the file system instance.
|
||||
@retval EFI_SUCCESS - The given file system was connected successfully
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
ConnectNvVarsToFileSystem (
|
||||
IN EFI_HANDLE FsHandle
|
||||
);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,540 @@
|
|||
/** @file
|
||||
File System Access for NvVarsFileLib
|
||||
|
||||
Copyright (c) 2004 - 2009, Intel Corporation. <BR>
|
||||
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 "NvVarsFileLib.h"
|
||||
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/MemoryAllocationLib.h>
|
||||
|
||||
|
||||
/**
|
||||
Open the NvVars file for reading or writing
|
||||
|
||||
@param[in] FsHandle - Handle for a gEfiSimpleFileSystemProtocolGuid instance
|
||||
@param[in] ReadingFile - TRUE: open the file for reading. FALSE: writing
|
||||
@param[out] NvVarsFile - If EFI_SUCCESS is returned, then this is updated
|
||||
with the opened NvVars file.
|
||||
|
||||
@return EFI_SUCCESS if the file was opened
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
GetNvVarsFile (
|
||||
IN EFI_HANDLE FsHandle,
|
||||
IN BOOLEAN ReadingFile,
|
||||
OUT EFI_FILE_HANDLE *NvVarsFile
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Fs;
|
||||
EFI_FILE_HANDLE Root;
|
||||
|
||||
//
|
||||
// Get the FileSystem protocol on that handle
|
||||
//
|
||||
Status = gBS->HandleProtocol (
|
||||
FsHandle,
|
||||
&gEfiSimpleFileSystemProtocolGuid,
|
||||
(VOID **)&Fs
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Get the volume (the root directory)
|
||||
//
|
||||
Status = Fs->OpenVolume (Fs, &Root);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Attempt to open the NvVars file in the root directory
|
||||
//
|
||||
Status = Root->Open (
|
||||
Root,
|
||||
NvVarsFile,
|
||||
L"NvVars",
|
||||
ReadingFile ?
|
||||
EFI_FILE_MODE_READ :
|
||||
(
|
||||
EFI_FILE_MODE_CREATE |
|
||||
EFI_FILE_MODE_READ |
|
||||
EFI_FILE_MODE_WRITE
|
||||
),
|
||||
0
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Open the NvVars file for reading or writing
|
||||
|
||||
@param[in] File - The file to inspect
|
||||
@param[out] Exists - Returns whether the file exists
|
||||
@param[out] Size - Returns the size of the file
|
||||
(0 if the file does not exist)
|
||||
|
||||
**/
|
||||
VOID
|
||||
NvVarsFileReadCheckup (
|
||||
IN EFI_FILE_HANDLE File,
|
||||
OUT BOOLEAN *Exists,
|
||||
OUT UINTN *Size
|
||||
)
|
||||
{
|
||||
EFI_FILE_INFO *FileInfo;
|
||||
|
||||
*Exists = FALSE;
|
||||
*Size = 0;
|
||||
|
||||
FileInfo = FileHandleGetInfo (File);
|
||||
if (FileInfo == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((FileInfo->Attribute & EFI_FILE_DIRECTORY) != 0) {
|
||||
FreePool (FileInfo);
|
||||
return;
|
||||
}
|
||||
|
||||
*Exists = TRUE;
|
||||
*Size = FileInfo->FileSize;
|
||||
|
||||
FreePool (FileInfo);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Open the NvVars file for reading or writing
|
||||
|
||||
@param[in] File - The file to inspect
|
||||
@param[out] Exists - Returns whether the file exists
|
||||
@param[out] Size - Returns the size of the file
|
||||
(0 if the file does not exist)
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
FileHandleEmpty (
|
||||
IN EFI_FILE_HANDLE File
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_FILE_INFO *FileInfo;
|
||||
|
||||
//
|
||||
// Retrieve the FileInfo structure
|
||||
//
|
||||
FileInfo = FileHandleGetInfo (File);
|
||||
if (FileInfo == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
//
|
||||
// If the path is a directory, then return an error
|
||||
//
|
||||
if ((FileInfo->Attribute & EFI_FILE_DIRECTORY) != 0) {
|
||||
FreePool (FileInfo);
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
//
|
||||
// If the file size is already 0, then it is empty, so
|
||||
// we can return success.
|
||||
//
|
||||
if (FileInfo->FileSize == 0) {
|
||||
FreePool (FileInfo);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// Set the file size to 0.
|
||||
//
|
||||
FileInfo->FileSize = 0;
|
||||
Status = FileHandleSetInfo (File, FileInfo);
|
||||
|
||||
FreePool (FileInfo);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Reads a file to a newly allocated buffer
|
||||
|
||||
@param[in] File - The file to read
|
||||
@param[in] ReadSize - The size of data to read from the file
|
||||
|
||||
@return Pointer to buffer allocated to hold the file
|
||||
contents. NULL if an error occured.
|
||||
|
||||
**/
|
||||
VOID*
|
||||
FileHandleReadToNewBuffer (
|
||||
IN EFI_FILE_HANDLE FileHandle,
|
||||
IN UINTN ReadSize
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINTN ActualReadSize;
|
||||
VOID *FileContents;
|
||||
|
||||
ActualReadSize = ReadSize;
|
||||
FileContents = AllocatePool (ReadSize);
|
||||
if (FileContents != NULL) {
|
||||
Status = FileHandleRead (
|
||||
FileHandle,
|
||||
&ReadSize,
|
||||
FileContents
|
||||
);
|
||||
if (EFI_ERROR (Status) || (ActualReadSize != ReadSize)) {
|
||||
FreePool (FileContents);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return FileContents;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Reads the contents of the NvVars file on the file system
|
||||
|
||||
@param[in] FsHandle - Handle for a gEfiSimpleFileSystemProtocolGuid instance
|
||||
|
||||
@return EFI_STATUS based on the success or failure of the file read
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
ReadNvVarsFile (
|
||||
IN EFI_HANDLE FsHandle
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_FILE_HANDLE File;
|
||||
UINTN FileSize;
|
||||
BOOLEAN FileExists;
|
||||
VOID *FileContents;
|
||||
|
||||
Status = GetNvVarsFile (FsHandle, TRUE, &File);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((EFI_D_INFO, "FsAccess.c: Could not open NV Variables file on this file system\n"));
|
||||
return Status;
|
||||
}
|
||||
|
||||
NvVarsFileReadCheckup (File, &FileExists, &FileSize);
|
||||
if (FileSize == 0) {
|
||||
FileHandleClose (File);
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
FileContents = FileHandleReadToNewBuffer (File, FileSize);
|
||||
if (FileContents == NULL) {
|
||||
FileHandleClose (File);
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
DEBUG ((
|
||||
EFI_D_INFO,
|
||||
"FsAccess.c: Read %d bytes from NV Variables file\n",
|
||||
FileSize
|
||||
));
|
||||
|
||||
Status = SetVariablesFromBuffer (FileContents, FileSize);
|
||||
|
||||
FreePool (FileContents);
|
||||
FileHandleClose (File);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Loads the non-volatile variables from the NvVars file on the
|
||||
given file system.
|
||||
|
||||
@param[in] FsHandle - Handle for a gEfiSimpleFileSystemProtocolGuid instance
|
||||
|
||||
@return EFI_STATUS based on the success or failure of load operation
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
LoadNvVarsFromFs (
|
||||
EFI_HANDLE FsHandle
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
BOOLEAN VarData;
|
||||
UINTN Size;
|
||||
|
||||
DEBUG ((EFI_D_INFO, "FsAccess.c: LoadNvVarsFromFs\n"));
|
||||
|
||||
//
|
||||
// We write a variable to indicate we've already loaded the
|
||||
// variable data. If it is found, we skip the loading.
|
||||
//
|
||||
// This is relevent if the non-volatile variable have been
|
||||
// able to survive a reboot operation. In that case, we don't
|
||||
// want to re-load the file as it would overwrite newer changes
|
||||
// made to the variables.
|
||||
//
|
||||
Size = sizeof (VarData);
|
||||
VarData = TRUE;
|
||||
Status = gRT->GetVariable (
|
||||
L"NvVars",
|
||||
&gEfiSimpleFileSystemProtocolGuid,
|
||||
NULL,
|
||||
&Size,
|
||||
(VOID*) &VarData
|
||||
);
|
||||
if (Status == EFI_SUCCESS) {
|
||||
DEBUG ((EFI_D_INFO, "NV Variables were already loaded\n"));
|
||||
return EFI_ALREADY_STARTED;
|
||||
}
|
||||
|
||||
//
|
||||
// Attempt to restore the variables from the NvVars file.
|
||||
//
|
||||
Status = ReadNvVarsFile (FsHandle);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((EFI_D_INFO, "Error while restoring NV variable data\n"));
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Write a variable to indicate we've already loaded the
|
||||
// variable data. If it is found, we skip the loading on
|
||||
// subsequent attempts.
|
||||
//
|
||||
Size = sizeof (VarData);
|
||||
VarData = TRUE;
|
||||
gRT->SetVariable (
|
||||
L"NvVars",
|
||||
&gEfiSimpleFileSystemProtocolGuid,
|
||||
EFI_VARIABLE_NON_VOLATILE |
|
||||
EFI_VARIABLE_BOOTSERVICE_ACCESS |
|
||||
EFI_VARIABLE_RUNTIME_ACCESS,
|
||||
Size,
|
||||
(VOID*) &VarData
|
||||
);
|
||||
|
||||
DEBUG ((
|
||||
EFI_D_INFO,
|
||||
"FsAccess.c: Read NV Variables file (size=%d)\n",
|
||||
Size
|
||||
));
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Saves the non-volatile variables into the NvVars file on the
|
||||
given file system.
|
||||
|
||||
@param[in] FsHandle - Handle for a gEfiSimpleFileSystemProtocolGuid instance
|
||||
|
||||
@return EFI_STATUS based on the success or failure of load operation
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SaveNvVarsToFs (
|
||||
EFI_HANDLE FsHandle
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_FILE_HANDLE File;
|
||||
UINTN VariableNameBufferSize;
|
||||
UINTN VariableNameSize;
|
||||
CHAR16 *VariableName;
|
||||
EFI_GUID VendorGuid;
|
||||
UINTN VariableDataBufferSize;
|
||||
UINTN VariableDataSize;
|
||||
VOID *VariableData;
|
||||
UINT32 VariableAttributes;
|
||||
VOID *NewBuffer;
|
||||
|
||||
//
|
||||
// Open the NvVars file for writing.
|
||||
//
|
||||
Status = GetNvVarsFile (FsHandle, FALSE, &File);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((EFI_D_INFO, "FsAccess.c: Unable to open file to saved NV Variables\n"));
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Empty the starting file contents.
|
||||
//
|
||||
Status = FileHandleEmpty (File);
|
||||
if (EFI_ERROR (Status)) {
|
||||
FileHandleClose (File);
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// 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;
|
||||
}
|
||||
|
||||
//
|
||||
// Skip volatile variables. We only preserve non-volatile variables.
|
||||
//
|
||||
if ((VariableAttributes & EFI_VARIABLE_NON_VOLATILE) == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
DEBUG ((
|
||||
EFI_D_INFO,
|
||||
"Saving variable %g:%s to file\n",
|
||||
&VendorGuid,
|
||||
VariableName
|
||||
));
|
||||
|
||||
//
|
||||
// Write the variable information out to the file
|
||||
//
|
||||
Status = PackVariableIntoFile (
|
||||
File,
|
||||
VariableName,
|
||||
VariableNameSize,
|
||||
&VendorGuid,
|
||||
VariableAttributes,
|
||||
VariableData,
|
||||
VariableDataSize
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (VariableName != NULL) {
|
||||
FreePool (VariableName);
|
||||
}
|
||||
|
||||
if (VariableData != NULL) {
|
||||
FreePool (VariableData);
|
||||
}
|
||||
|
||||
FileHandleClose (File);
|
||||
|
||||
if (!EFI_ERROR (Status)) {
|
||||
DEBUG ((EFI_D_INFO, "Saved NV Variables to NvVars file\n"));
|
||||
}
|
||||
|
||||
return Status;
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
/** @file
|
||||
Save Non-Volatile Variables to a file system.
|
||||
|
||||
Copyright (c) 2009, Intel Corporation. <BR>
|
||||
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 "NvVarsFileLib.h"
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/NvVarsFileLib.h>
|
||||
|
||||
|
||||
/**
|
||||
Attempts to connect the NvVarsFileLib to the specified file system.
|
||||
|
||||
@param[in] FsHandle - Handle for a gEfiSimpleFileSystemProtocolGuid instance
|
||||
|
||||
@return The EFI_STATUS while attempting to connect the NvVarsFileLib
|
||||
to the file system instance.
|
||||
@retval EFI_SUCCESS - The given file system was connected successfully
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
ConnectNvVarsToFileSystem (
|
||||
IN EFI_HANDLE FsHandle
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
//
|
||||
// We might fail to load the variable, since the file system initially
|
||||
// will not have the NvVars file.
|
||||
//
|
||||
LoadNvVarsFromFs (FsHandle);
|
||||
|
||||
//
|
||||
// We must be able to save the variables successfully to the file system
|
||||
// to have connected successfully.
|
||||
//
|
||||
Status = SaveNvVarsToFs (FsHandle);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,103 @@
|
|||
/** @file
|
||||
Save Non-Volatile Variables to a file system.
|
||||
|
||||
Copyright (c) 2009, 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.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __NV_VARS_FILE_LIB_INSTANCE__
|
||||
#define __NV_VARS_FILE_LIB_INSTANCE__
|
||||
|
||||
#include <Uefi.h>
|
||||
|
||||
#include <Guid/FileInfo.h>
|
||||
|
||||
#include <Protocol/SimpleFileSystem.h>
|
||||
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/FileHandleLib.h>
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
#include <Library/UefiRuntimeServicesTableLib.h>
|
||||
#include <Library/UefiLib.h>
|
||||
|
||||
/**
|
||||
Loads the non-volatile variables from the NvVars file on the
|
||||
given file system.
|
||||
|
||||
@param[in] FsHandle - Handle for a gEfiSimpleFileSystemProtocolGuid instance
|
||||
|
||||
@return EFI_STATUS based on the success or failure of load operation
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
LoadNvVarsFromFs (
|
||||
EFI_HANDLE FsHandle
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
Saves the non-volatile variables into the NvVars file on the
|
||||
given file system.
|
||||
|
||||
@param[in] FsHandle - Handle for a gEfiSimpleFileSystemProtocolGuid instance
|
||||
|
||||
@return EFI_STATUS based on the success or failure of load operation
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SaveNvVarsToFs (
|
||||
EFI_HANDLE FsHandle
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
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
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
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
|
||||
);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
#/** @file
|
||||
# NvVarsFileLib
|
||||
#
|
||||
# This kibrary saves and restores non-volatile variables in a
|
||||
# file within a file system.
|
||||
#
|
||||
# Copyright (c) 2006 - 2009, 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.
|
||||
#
|
||||
#
|
||||
#**/
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = NvVarsFileLib
|
||||
FILE_GUID = 9172fe8b-9a36-40f8-bba5-5e57a44390bd
|
||||
MODULE_TYPE = UEFI_DRIVER
|
||||
VERSION_STRING = 1.0
|
||||
LIBRARY_CLASS = NvVarsFileLib|DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SAL_DRIVER UEFI_DRIVER
|
||||
|
||||
#
|
||||
# The following information is for reference only and not required by the build tools.
|
||||
#
|
||||
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
|
||||
#
|
||||
|
||||
[Sources.common]
|
||||
FsAccess.c
|
||||
NvVarsFileLib.c
|
||||
VarBuffer.c
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
MdeModulePkg/MdeModulePkg.dec
|
||||
OvmfPkg/OvmfPkg.dec
|
||||
ShellPkg/ShellPkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
BaseLib
|
||||
BaseMemoryLib
|
||||
DebugLib
|
||||
FileHandleLib
|
||||
MemoryAllocationLib
|
||||
|
||||
[Protocols]
|
||||
gEfiSimpleFileSystemProtocolGuid ## CONSUMES
|
||||
|
||||
|
||||
[Guids]
|
||||
gEfiFileInfoGuid
|
||||
|
||||
[Depex]
|
||||
gEfiVariableWriteArchProtocolGuid
|
||||
|
|
@ -0,0 +1,345 @@
|
|||
/** @file
|
||||
File System Access
|
||||
|
||||
Copyright (c) 2004 - 2009, Intel Corporation. <BR>
|
||||
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 "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;
|
||||
}
|
||||
|
|
@ -19,6 +19,9 @@
|
|||
PACKAGE_GUID = 2daf5f34-50e5-4b9d-b8e3-5562334d87e5
|
||||
PACKAGE_VERSION = 0.1
|
||||
|
||||
[Includes]
|
||||
Include
|
||||
|
||||
[Guids.common]
|
||||
gUefiOvmfPkgTokenSpaceGuid = {0x93bb96af, 0xb9f2, 0x4eb8, {0x94, 0x62, 0xe0, 0xba, 0x74, 0x56, 0x42, 0x36}}
|
||||
|
||||
|
@ -31,4 +34,8 @@
|
|||
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFirmwareBlockSize|0|UINT32|0x00001013
|
||||
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageVariableBase|0x0|UINT32|0x00001014
|
||||
|
||||
[LibraryClasses]
|
||||
## @libraryclass Save and restore variables using a file
|
||||
#
|
||||
NvVarsFileLib|Include/Library/NvVarsFileLib.h
|
||||
|
||||
|
|
Loading…
Reference in New Issue