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>
16 Open the NvVars file for reading or writing
18 @param[in] FsHandle - Handle for a gEfiSimpleFileSystemProtocolGuid instance
19 @param[in] ReadingFile - TRUE: open the file for reading. FALSE: writing
20 @param[out] NvVarsFile - If EFI_SUCCESS is returned, then this is updated
21 with the opened NvVars file.
23 @return EFI_SUCCESS if the file was opened
28 IN EFI_HANDLE FsHandle
,
29 IN BOOLEAN ReadingFile
,
30 OUT EFI_FILE_HANDLE
*NvVarsFile
34 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL
*Fs
;
38 // Get the FileSystem protocol on that handle
40 Status
= gBS
->HandleProtocol (
42 &gEfiSimpleFileSystemProtocolGuid
,
45 if (EFI_ERROR (Status
)) {
50 // Get the volume (the root directory)
52 Status
= Fs
->OpenVolume (Fs
, &Root
);
53 if (EFI_ERROR (Status
)) {
58 // Attempt to open the NvVars file in the root directory
67 EFI_FILE_MODE_CREATE
|
78 Open the NvVars file for reading or writing
80 @param[in] File - The file to inspect
81 @param[out] Exists - Returns whether the file exists
82 @param[out] Size - Returns the size of the file
83 (0 if the file does not exist)
87 NvVarsFileReadCheckup (
88 IN EFI_FILE_HANDLE File
,
93 EFI_FILE_INFO
*FileInfo
;
98 FileInfo
= FileHandleGetInfo (File
);
99 if (FileInfo
== NULL
) {
103 if ((FileInfo
->Attribute
& EFI_FILE_DIRECTORY
) != 0) {
109 *Size
= (UINTN
)FileInfo
->FileSize
;
115 Open the NvVars file for reading or writing
117 @param[in] File - The file to inspect
118 @param[out] Exists - Returns whether the file exists
119 @param[out] Size - Returns the size of the file
120 (0 if the file does not exist)
125 IN EFI_FILE_HANDLE File
129 EFI_FILE_INFO
*FileInfo
;
132 // Retrieve the FileInfo structure
134 FileInfo
= FileHandleGetInfo (File
);
135 if (FileInfo
== NULL
) {
136 return EFI_INVALID_PARAMETER
;
140 // If the path is a directory, then return an error
142 if ((FileInfo
->Attribute
& EFI_FILE_DIRECTORY
) != 0) {
144 return EFI_INVALID_PARAMETER
;
148 // If the file size is already 0, then it is empty, so
149 // we can return success.
151 if (FileInfo
->FileSize
== 0) {
157 // Set the file size to 0.
159 FileInfo
->FileSize
= 0;
160 Status
= FileHandleSetInfo (File
, FileInfo
);
168 Reads a file to a newly allocated buffer
170 @param[in] File - The file to read
171 @param[in] ReadSize - The size of data to read from the file
173 @return Pointer to buffer allocated to hold the file
174 contents. NULL if an error occurred.
178 FileHandleReadToNewBuffer (
179 IN EFI_FILE_HANDLE FileHandle
,
184 UINTN ActualReadSize
;
187 ActualReadSize
= ReadSize
;
188 FileContents
= AllocatePool (ReadSize
);
189 if (FileContents
!= NULL
) {
190 Status
= FileHandleRead (
195 if (EFI_ERROR (Status
) || (ActualReadSize
!= ReadSize
)) {
196 FreePool (FileContents
);
205 Reads the contents of the NvVars file on the file system
207 @param[in] FsHandle - Handle for a gEfiSimpleFileSystemProtocolGuid instance
209 @return EFI_STATUS based on the success or failure of the file read
214 IN EFI_HANDLE FsHandle
218 EFI_FILE_HANDLE File
;
222 EFI_HANDLE SerializedVariables
;
224 Status
= GetNvVarsFile (FsHandle
, TRUE
, &File
);
225 if (EFI_ERROR (Status
)) {
226 DEBUG ((DEBUG_INFO
, "FsAccess.c: Could not open NV Variables file on this file system\n"));
230 NvVarsFileReadCheckup (File
, &FileExists
, &FileSize
);
232 FileHandleClose (File
);
233 return EFI_UNSUPPORTED
;
236 FileContents
= FileHandleReadToNewBuffer (File
, FileSize
);
237 if (FileContents
== NULL
) {
238 FileHandleClose (File
);
239 return EFI_UNSUPPORTED
;
244 "FsAccess.c: Read %Lu bytes from NV Variables file\n",
248 Status
= SerializeVariablesNewInstanceFromBuffer (
249 &SerializedVariables
,
253 if (!RETURN_ERROR (Status
)) {
254 Status
= SerializeVariablesSetSerializedVariables (SerializedVariables
);
257 FreePool (FileContents
);
258 FileHandleClose (File
);
264 Writes a variable to indicate that the NV variables
265 have been loaded from the file system.
278 // Write a variable to indicate we've already loaded the
279 // variable data. If it is found, we skip the loading on
280 // subsequent attempts.
282 Size
= sizeof (VarData
);
286 &gEfiSimpleFileSystemProtocolGuid
,
287 EFI_VARIABLE_NON_VOLATILE
|
288 EFI_VARIABLE_BOOTSERVICE_ACCESS
|
289 EFI_VARIABLE_RUNTIME_ACCESS
,
296 Loads the non-volatile variables from the NvVars file on the
299 @param[in] FsHandle - Handle for a gEfiSimpleFileSystemProtocolGuid instance
301 @return EFI_STATUS based on the success or failure of load operation
313 DEBUG ((DEBUG_INFO
, "FsAccess.c: LoadNvVarsFromFs\n"));
316 // We write a variable to indicate we've already loaded the
317 // variable data. If it is found, we skip the loading.
319 // This is relevant if the non-volatile variable have been
320 // able to survive a reboot operation. In that case, we don't
321 // want to re-load the file as it would overwrite newer changes
322 // made to the variables.
324 Size
= sizeof (VarData
);
326 Status
= gRT
->GetVariable (
328 &gEfiSimpleFileSystemProtocolGuid
,
333 if (Status
== EFI_SUCCESS
) {
334 DEBUG ((DEBUG_INFO
, "NV Variables were already loaded\n"));
335 return EFI_ALREADY_STARTED
;
339 // Attempt to restore the variables from the NvVars file.
341 Status
= ReadNvVarsFile (FsHandle
);
342 if (EFI_ERROR (Status
)) {
343 DEBUG ((DEBUG_INFO
, "Error while restoring NV variable data\n"));
348 // Write a variable to indicate we've already loaded the
349 // variable data. If it is found, we skip the loading on
350 // subsequent attempts.
352 SetNvVarsVariable ();
356 "FsAccess.c: Read NV Variables file (size=%Lu)\n",
366 IterateVariablesCallbackAddAllNvVariables (
368 IN CHAR16
*VariableName
,
369 IN EFI_GUID
*VendorGuid
,
370 IN UINT32 Attributes
,
377 Instance
= (EFI_HANDLE
)Context
;
380 // Only save non-volatile variables
382 if ((Attributes
& EFI_VARIABLE_NON_VOLATILE
) == 0) {
383 return RETURN_SUCCESS
;
386 return SerializeVariablesAddVariable (
397 Saves the non-volatile variables into the NvVars file on the
400 @param[in] FsHandle - Handle for a gEfiSimpleFileSystemProtocolGuid instance
402 @return EFI_STATUS based on the success or failure of load operation
411 EFI_FILE_HANDLE File
;
413 UINTN VariableDataSize
;
415 EFI_HANDLE SerializedVariables
;
417 SerializedVariables
= NULL
;
419 Status
= SerializeVariablesNewInstance (&SerializedVariables
);
420 if (EFI_ERROR (Status
)) {
424 Status
= SerializeVariablesIterateSystemVariables (
425 IterateVariablesCallbackAddAllNvVariables
,
426 (VOID
*)SerializedVariables
428 if (EFI_ERROR (Status
)) {
433 VariableDataSize
= 0;
434 Status
= SerializeVariablesToBuffer (
439 if (Status
== RETURN_BUFFER_TOO_SMALL
) {
440 VariableData
= AllocatePool (VariableDataSize
);
441 if (VariableData
== NULL
) {
442 Status
= EFI_OUT_OF_RESOURCES
;
444 Status
= SerializeVariablesToBuffer (
452 SerializeVariablesFreeInstance (SerializedVariables
);
454 if (EFI_ERROR (Status
)) {
459 // Open the NvVars file for writing.
461 Status
= GetNvVarsFile (FsHandle
, FALSE
, &File
);
462 if (EFI_ERROR (Status
)) {
463 DEBUG ((DEBUG_INFO
, "FsAccess.c: Unable to open file to saved NV Variables\n"));
468 // Empty the starting file contents.
470 Status
= FileHandleEmpty (File
);
471 if (EFI_ERROR (Status
)) {
472 FileHandleClose (File
);
476 WriteSize
= VariableDataSize
;
477 Status
= FileHandleWrite (File
, &WriteSize
, VariableData
);
478 if (EFI_ERROR (Status
)) {
482 FileHandleClose (File
);
484 if (!EFI_ERROR (Status
)) {
486 // Write a variable to indicate we've already loaded the
487 // variable data. If it is found, we skip the loading on
488 // subsequent attempts.
490 SetNvVarsVariable ();
492 DEBUG ((DEBUG_INFO
, "Saved NV Variables to NvVars file\n"));