summaryrefslogtreecommitdiffstats
path: root/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/NvVarsFileLib
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-11 08:17:27 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-11 08:17:27 +0000
commitf215e02bf85f68d3a6106c2a1f4f7f063f819064 (patch)
tree6bb5b92c046312c4e95ac2620b10ddf482d3fa8b /src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/NvVarsFileLib
parentInitial commit. (diff)
downloadvirtualbox-f215e02bf85f68d3a6106c2a1f4f7f063f819064.tar.xz
virtualbox-f215e02bf85f68d3a6106c2a1f4f7f063f819064.zip
Adding upstream version 7.0.14-dfsg.upstream/7.0.14-dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/NvVarsFileLib')
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/NvVarsFileLib/FsAccess.c508
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/NvVarsFileLib/NvVarsFileLib.c77
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/NvVarsFileLib/NvVarsFileLib.h55
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/NvVarsFileLib/NvVarsFileLib.inf56
4 files changed, 696 insertions, 0 deletions
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/NvVarsFileLib/FsAccess.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/NvVarsFileLib/FsAccess.c
new file mode 100644
index 00000000..8fbea471
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/NvVarsFileLib/FsAccess.c
@@ -0,0 +1,508 @@
+/** @file
+ File System Access for NvVarsFileLib
+
+ Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#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
+ );
+
+ 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 = (UINTN) 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 occurred.
+
+**/
+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;
+ EFI_HANDLE SerializedVariables;
+
+ Status = GetNvVarsFile (FsHandle, TRUE, &File);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_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 ((
+ DEBUG_INFO,
+ "FsAccess.c: Read %Lu bytes from NV Variables file\n",
+ (UINT64)FileSize
+ ));
+
+ Status = SerializeVariablesNewInstanceFromBuffer (
+ &SerializedVariables,
+ FileContents,
+ FileSize
+ );
+ if (!RETURN_ERROR (Status)) {
+ Status = SerializeVariablesSetSerializedVariables (SerializedVariables);
+ }
+
+ FreePool (FileContents);
+ FileHandleClose (File);
+
+ return Status;
+}
+
+
+/**
+ Writes a variable to indicate that the NV variables
+ have been loaded from the file system.
+
+**/
+STATIC
+VOID
+SetNvVarsVariable (
+ VOID
+ )
+{
+ BOOLEAN VarData;
+ UINTN Size;
+
+ //
+ // 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
+ );
+}
+
+
+/**
+ 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 ((DEBUG_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 relevant 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 ((DEBUG_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 ((DEBUG_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.
+ //
+ SetNvVarsVariable();
+
+ DEBUG ((
+ DEBUG_INFO,
+ "FsAccess.c: Read NV Variables file (size=%Lu)\n",
+ (UINT64)Size
+ ));
+
+ return Status;
+}
+
+
+STATIC
+RETURN_STATUS
+EFIAPI
+IterateVariablesCallbackAddAllNvVariables (
+ 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;
+
+ //
+ // Only save non-volatile variables
+ //
+ if ((Attributes & EFI_VARIABLE_NON_VOLATILE) == 0) {
+ return RETURN_SUCCESS;
+ }
+
+ return SerializeVariablesAddVariable (
+ Instance,
+ VariableName,
+ VendorGuid,
+ Attributes,
+ DataSize,
+ Data
+ );
+}
+
+
+/**
+ 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 WriteSize;
+ UINTN VariableDataSize;
+ VOID *VariableData;
+ EFI_HANDLE SerializedVariables;
+
+ SerializedVariables = NULL;
+
+ Status = SerializeVariablesNewInstance (&SerializedVariables);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = SerializeVariablesIterateSystemVariables (
+ IterateVariablesCallbackAddAllNvVariables,
+ (VOID*) SerializedVariables
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ VariableData = NULL;
+ VariableDataSize = 0;
+ Status = SerializeVariablesToBuffer (
+ SerializedVariables,
+ NULL,
+ &VariableDataSize
+ );
+ if (Status == RETURN_BUFFER_TOO_SMALL) {
+ VariableData = AllocatePool (VariableDataSize);
+ if (VariableData == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ } else {
+ Status = SerializeVariablesToBuffer (
+ SerializedVariables,
+ VariableData,
+ &VariableDataSize
+ );
+ }
+ }
+
+ SerializeVariablesFreeInstance (SerializedVariables);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Open the NvVars file for writing.
+ //
+ Status = GetNvVarsFile (FsHandle, FALSE, &File);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_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;
+ }
+
+ WriteSize = VariableDataSize;
+ Status = FileHandleWrite (File, &WriteSize, VariableData);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ FileHandleClose (File);
+
+ if (!EFI_ERROR (Status)) {
+ //
+ // Write a variable to indicate we've already loaded the
+ // variable data. If it is found, we skip the loading on
+ // subsequent attempts.
+ //
+ SetNvVarsVariable();
+
+ DEBUG ((DEBUG_INFO, "Saved NV Variables to NvVars file\n"));
+ }
+
+ return Status;
+
+}
+
+
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/NvVarsFileLib/NvVarsFileLib.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/NvVarsFileLib/NvVarsFileLib.c
new file mode 100644
index 00000000..7395723a
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/NvVarsFileLib/NvVarsFileLib.c
@@ -0,0 +1,77 @@
+/** @file
+ Save Non-Volatile Variables to a file system.
+
+ Copyright (c) 2009, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "NvVarsFileLib.h"
+#include <Library/DebugLib.h>
+#include <Library/NvVarsFileLib.h>
+
+EFI_HANDLE mNvVarsFileLibFsHandle = NULL;
+
+
+/**
+ 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);
+ if (!EFI_ERROR (Status)) {
+ mNvVarsFileLibFsHandle = FsHandle;
+ }
+
+ return Status;
+}
+
+
+/**
+ Update non-volatile variables stored on the file system.
+
+ @return The EFI_STATUS while attempting to update the variable on
+ the connected file system.
+ @retval EFI_SUCCESS - The non-volatile variables were saved to the disk
+ @retval EFI_NOT_STARTED - A file system has not been connected
+
+**/
+EFI_STATUS
+EFIAPI
+UpdateNvVarsOnFileSystem (
+ )
+{
+ if (mNvVarsFileLibFsHandle == NULL) {
+ //
+ // A file system had not been connected to the library.
+ //
+ return EFI_NOT_STARTED;
+ } else {
+ return SaveNvVarsToFs (mNvVarsFileLibFsHandle);
+ }
+}
+
+
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/NvVarsFileLib/NvVarsFileLib.h b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/NvVarsFileLib/NvVarsFileLib.h
new file mode 100644
index 00000000..c736aeb6
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/NvVarsFileLib/NvVarsFileLib.h
@@ -0,0 +1,55 @@
+/** @file
+ Save Non-Volatile Variables to a file system.
+
+ Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#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/SerializeVariablesLib.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
+ );
+
+#endif
+
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/NvVarsFileLib/NvVarsFileLib.inf b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/NvVarsFileLib/NvVarsFileLib.inf
new file mode 100644
index 00000000..7df3c831
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/NvVarsFileLib/NvVarsFileLib.inf
@@ -0,0 +1,56 @@
+## @file
+# NvVarsFileLib
+#
+# This library saves and restores non-volatile variables in a
+# file within a file system.
+#
+# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#
+##
+
+[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 UEFI_DRIVER
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 EBC
+#
+
+[Sources]
+ FsAccess.c
+ NvVarsFileLib.c
+ NvVarsFileLib.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ OvmfPkg/OvmfPkg.dec
+ ShellPkg/ShellPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ FileHandleLib
+ MemoryAllocationLib
+ SerializeVariablesLib
+
+[Protocols]
+ gEfiSimpleFileSystemProtocolGuid ## CONSUMES
+
+
+[Guids]
+ gEfiFileInfoGuid
+
+[Depex]
+ gEfiVariableWriteArchProtocolGuid
+