2 File System Access for NvVarsFileLib
4 Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
9 #include "NvVarsFileLib.h"
11 #include <Library/BaseMemoryLib.h>
12 #include <Library/DebugLib.h>
13 #include <Library/MemoryAllocationLib.h>
17 Open the NvVars file for reading or writing
19 @param[in] FsHandle - Handle for a gEfiSimpleFileSystemProtocolGuid instance
20 @param[in] ReadingFile - TRUE: open the file for reading. FALSE: writing
21 @param[out] NvVarsFile - If EFI_SUCCESS is returned, then this is updated
22 with the opened NvVars file.
24 @return EFI_SUCCESS if the file was opened
29 IN EFI_HANDLE FsHandle
,
30 IN BOOLEAN ReadingFile
,
31 OUT EFI_FILE_HANDLE
*NvVarsFile
35 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL
*Fs
;
39 // Get the FileSystem protocol on that handle
41 Status
= gBS
->HandleProtocol (
43 &gEfiSimpleFileSystemProtocolGuid
,
46 if (EFI_ERROR (Status
)) {
51 // Get the volume (the root directory)
53 Status
= Fs
->OpenVolume (Fs
, &Root
);
54 if (EFI_ERROR (Status
)) {
59 // Attempt to open the NvVars file in the root directory
68 EFI_FILE_MODE_CREATE
|
80 Open the NvVars file for reading or writing
82 @param[in] File - The file to inspect
83 @param[out] Exists - Returns whether the file exists
84 @param[out] Size - Returns the size of the file
85 (0 if the file does not exist)
89 NvVarsFileReadCheckup (
90 IN EFI_FILE_HANDLE File
,
95 EFI_FILE_INFO
*FileInfo
;
100 FileInfo
= FileHandleGetInfo (File
);
101 if (FileInfo
== NULL
) {
105 if ((FileInfo
->Attribute
& EFI_FILE_DIRECTORY
) != 0) {
111 *Size
= (UINTN
) FileInfo
->FileSize
;
118 Open the NvVars file for reading or writing
120 @param[in] File - The file to inspect
121 @param[out] Exists - Returns whether the file exists
122 @param[out] Size - Returns the size of the file
123 (0 if the file does not exist)
128 IN EFI_FILE_HANDLE File
132 EFI_FILE_INFO
*FileInfo
;
135 // Retrieve the FileInfo structure
137 FileInfo
= FileHandleGetInfo (File
);
138 if (FileInfo
== NULL
) {
139 return EFI_INVALID_PARAMETER
;
143 // If the path is a directory, then return an error
145 if ((FileInfo
->Attribute
& EFI_FILE_DIRECTORY
) != 0) {
147 return EFI_INVALID_PARAMETER
;
151 // If the file size is already 0, then it is empty, so
152 // we can return success.
154 if (FileInfo
->FileSize
== 0) {
160 // Set the file size to 0.
162 FileInfo
->FileSize
= 0;
163 Status
= FileHandleSetInfo (File
, FileInfo
);
172 Reads a file to a newly allocated buffer
174 @param[in] File - The file to read
175 @param[in] ReadSize - The size of data to read from the file
177 @return Pointer to buffer allocated to hold the file
178 contents. NULL if an error occurred.
182 FileHandleReadToNewBuffer (
183 IN EFI_FILE_HANDLE FileHandle
,
188 UINTN ActualReadSize
;
191 ActualReadSize
= ReadSize
;
192 FileContents
= AllocatePool (ReadSize
);
193 if (FileContents
!= NULL
) {
194 Status
= FileHandleRead (
199 if (EFI_ERROR (Status
) || (ActualReadSize
!= ReadSize
)) {
200 FreePool (FileContents
);
210 Reads the contents of the NvVars file on the file system
212 @param[in] FsHandle - Handle for a gEfiSimpleFileSystemProtocolGuid instance
214 @return EFI_STATUS based on the success or failure of the file read
219 IN EFI_HANDLE FsHandle
223 EFI_FILE_HANDLE File
;
227 EFI_HANDLE SerializedVariables
;
229 Status
= GetNvVarsFile (FsHandle
, TRUE
, &File
);
230 if (EFI_ERROR (Status
)) {
231 DEBUG ((DEBUG_INFO
, "FsAccess.c: Could not open NV Variables file on this file system\n"));
235 NvVarsFileReadCheckup (File
, &FileExists
, &FileSize
);
237 FileHandleClose (File
);
238 return EFI_UNSUPPORTED
;
241 FileContents
= FileHandleReadToNewBuffer (File
, FileSize
);
242 if (FileContents
== NULL
) {
243 FileHandleClose (File
);
244 return EFI_UNSUPPORTED
;
249 "FsAccess.c: Read %Lu bytes from NV Variables file\n",
253 Status
= SerializeVariablesNewInstanceFromBuffer (
254 &SerializedVariables
,
258 if (!RETURN_ERROR (Status
)) {
259 Status
= SerializeVariablesSetSerializedVariables (SerializedVariables
);
262 FreePool (FileContents
);
263 FileHandleClose (File
);
270 Writes a variable to indicate that the NV variables
271 have been loaded from the file system.
284 // Write a variable to indicate we've already loaded the
285 // variable data. If it is found, we skip the loading on
286 // subsequent attempts.
288 Size
= sizeof (VarData
);
292 &gEfiSimpleFileSystemProtocolGuid
,
293 EFI_VARIABLE_NON_VOLATILE
|
294 EFI_VARIABLE_BOOTSERVICE_ACCESS
|
295 EFI_VARIABLE_RUNTIME_ACCESS
,
303 Loads the non-volatile variables from the NvVars file on the
306 @param[in] FsHandle - Handle for a gEfiSimpleFileSystemProtocolGuid instance
308 @return EFI_STATUS based on the success or failure of load operation
320 DEBUG ((DEBUG_INFO
, "FsAccess.c: LoadNvVarsFromFs\n"));
323 // We write a variable to indicate we've already loaded the
324 // variable data. If it is found, we skip the loading.
326 // This is relevant if the non-volatile variable have been
327 // able to survive a reboot operation. In that case, we don't
328 // want to re-load the file as it would overwrite newer changes
329 // made to the variables.
331 Size
= sizeof (VarData
);
333 Status
= gRT
->GetVariable (
335 &gEfiSimpleFileSystemProtocolGuid
,
340 if (Status
== EFI_SUCCESS
) {
341 DEBUG ((DEBUG_INFO
, "NV Variables were already loaded\n"));
342 return EFI_ALREADY_STARTED
;
346 // Attempt to restore the variables from the NvVars file.
348 Status
= ReadNvVarsFile (FsHandle
);
349 if (EFI_ERROR (Status
)) {
350 DEBUG ((DEBUG_INFO
, "Error while restoring NV variable data\n"));
355 // Write a variable to indicate we've already loaded the
356 // variable data. If it is found, we skip the loading on
357 // subsequent attempts.
363 "FsAccess.c: Read NV Variables file (size=%Lu)\n",
374 IterateVariablesCallbackAddAllNvVariables (
376 IN CHAR16
*VariableName
,
377 IN EFI_GUID
*VendorGuid
,
378 IN UINT32 Attributes
,
385 Instance
= (EFI_HANDLE
) Context
;
388 // Only save non-volatile variables
390 if ((Attributes
& EFI_VARIABLE_NON_VOLATILE
) == 0) {
391 return RETURN_SUCCESS
;
394 return SerializeVariablesAddVariable (
406 Saves the non-volatile variables into the NvVars file on the
409 @param[in] FsHandle - Handle for a gEfiSimpleFileSystemProtocolGuid instance
411 @return EFI_STATUS based on the success or failure of load operation
420 EFI_FILE_HANDLE File
;
422 UINTN VariableDataSize
;
424 EFI_HANDLE SerializedVariables
;
426 SerializedVariables
= NULL
;
428 Status
= SerializeVariablesNewInstance (&SerializedVariables
);
429 if (EFI_ERROR (Status
)) {
433 Status
= SerializeVariablesIterateSystemVariables (
434 IterateVariablesCallbackAddAllNvVariables
,
435 (VOID
*) SerializedVariables
437 if (EFI_ERROR (Status
)) {
442 VariableDataSize
= 0;
443 Status
= SerializeVariablesToBuffer (
448 if (Status
== RETURN_BUFFER_TOO_SMALL
) {
449 VariableData
= AllocatePool (VariableDataSize
);
450 if (VariableData
== NULL
) {
451 Status
= EFI_OUT_OF_RESOURCES
;
453 Status
= SerializeVariablesToBuffer (
461 SerializeVariablesFreeInstance (SerializedVariables
);
463 if (EFI_ERROR (Status
)) {
468 // Open the NvVars file for writing.
470 Status
= GetNvVarsFile (FsHandle
, FALSE
, &File
);
471 if (EFI_ERROR (Status
)) {
472 DEBUG ((DEBUG_INFO
, "FsAccess.c: Unable to open file to saved NV Variables\n"));
477 // Empty the starting file contents.
479 Status
= FileHandleEmpty (File
);
480 if (EFI_ERROR (Status
)) {
481 FileHandleClose (File
);
485 WriteSize
= VariableDataSize
;
486 Status
= FileHandleWrite (File
, &WriteSize
, VariableData
);
487 if (EFI_ERROR (Status
)) {
491 FileHandleClose (File
);
493 if (!EFI_ERROR (Status
)) {
495 // Write a variable to indicate we've already loaded the
496 // variable data. If it is found, we skip the loading on
497 // subsequent attempts.
501 DEBUG ((DEBUG_INFO
, "Saved NV Variables to NvVars file\n"));