From f215e02bf85f68d3a6106c2a1f4f7f063f819064 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Thu, 11 Apr 2024 10:17:27 +0200 Subject: Adding upstream version 7.0.14-dfsg. Signed-off-by: Daniel Baumann --- .../OvmfPkg/Library/NvVarsFileLib/FsAccess.c | 508 +++++++++++++++++++++ .../OvmfPkg/Library/NvVarsFileLib/NvVarsFileLib.c | 77 ++++ .../OvmfPkg/Library/NvVarsFileLib/NvVarsFileLib.h | 55 +++ .../Library/NvVarsFileLib/NvVarsFileLib.inf | 56 +++ 4 files changed, 696 insertions(+) create mode 100644 src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/NvVarsFileLib/FsAccess.c create mode 100644 src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/NvVarsFileLib/NvVarsFileLib.c create mode 100644 src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/NvVarsFileLib/NvVarsFileLib.h create mode 100644 src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/NvVarsFileLib/NvVarsFileLib.inf (limited to 'src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/NvVarsFileLib') 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.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "NvVarsFileLib.h" + +#include +#include +#include + + +/** + 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.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "NvVarsFileLib.h" +#include +#include + +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.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __NV_VARS_FILE_LIB_INSTANCE__ +#define __NV_VARS_FILE_LIB_INSTANCE__ + +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include + +/** + 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.
+# +# 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 + -- cgit v1.2.3