2 File System Access for NvVarsFileLib
4 Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include "NvVarsFileLib.h"
17 #include <Library/BaseMemoryLib.h>
18 #include <Library/DebugLib.h>
19 #include <Library/MemoryAllocationLib.h>
23 Open the NvVars file for reading or writing
25 @param[in] FsHandle - Handle for a gEfiSimpleFileSystemProtocolGuid instance
26 @param[in] ReadingFile - TRUE: open the file for reading. FALSE: writing
27 @param[out] NvVarsFile - If EFI_SUCCESS is returned, then this is updated
28 with the opened NvVars file.
30 @return EFI_SUCCESS if the file was opened
35 IN EFI_HANDLE FsHandle
,
36 IN BOOLEAN ReadingFile
,
37 OUT EFI_FILE_HANDLE
*NvVarsFile
41 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL
*Fs
;
45 // Get the FileSystem protocol on that handle
47 Status
= gBS
->HandleProtocol (
49 &gEfiSimpleFileSystemProtocolGuid
,
52 if (EFI_ERROR (Status
)) {
57 // Get the volume (the root directory)
59 Status
= Fs
->OpenVolume (Fs
, &Root
);
60 if (EFI_ERROR (Status
)) {
65 // Attempt to open the NvVars file in the root directory
74 EFI_FILE_MODE_CREATE
|
80 if (EFI_ERROR (Status
)) {
89 Open the NvVars file for reading or writing
91 @param[in] File - The file to inspect
92 @param[out] Exists - Returns whether the file exists
93 @param[out] Size - Returns the size of the file
94 (0 if the file does not exist)
98 NvVarsFileReadCheckup (
99 IN EFI_FILE_HANDLE File
,
104 EFI_FILE_INFO
*FileInfo
;
109 FileInfo
= FileHandleGetInfo (File
);
110 if (FileInfo
== NULL
) {
114 if ((FileInfo
->Attribute
& EFI_FILE_DIRECTORY
) != 0) {
120 *Size
= (UINTN
) FileInfo
->FileSize
;
127 Open the NvVars file for reading or writing
129 @param[in] File - The file to inspect
130 @param[out] Exists - Returns whether the file exists
131 @param[out] Size - Returns the size of the file
132 (0 if the file does not exist)
137 IN EFI_FILE_HANDLE File
141 EFI_FILE_INFO
*FileInfo
;
144 // Retrieve the FileInfo structure
146 FileInfo
= FileHandleGetInfo (File
);
147 if (FileInfo
== NULL
) {
148 return EFI_INVALID_PARAMETER
;
152 // If the path is a directory, then return an error
154 if ((FileInfo
->Attribute
& EFI_FILE_DIRECTORY
) != 0) {
156 return EFI_INVALID_PARAMETER
;
160 // If the file size is already 0, then it is empty, so
161 // we can return success.
163 if (FileInfo
->FileSize
== 0) {
169 // Set the file size to 0.
171 FileInfo
->FileSize
= 0;
172 Status
= FileHandleSetInfo (File
, FileInfo
);
181 Reads a file to a newly allocated buffer
183 @param[in] File - The file to read
184 @param[in] ReadSize - The size of data to read from the file
186 @return Pointer to buffer allocated to hold the file
187 contents. NULL if an error occured.
191 FileHandleReadToNewBuffer (
192 IN EFI_FILE_HANDLE FileHandle
,
197 UINTN ActualReadSize
;
200 ActualReadSize
= ReadSize
;
201 FileContents
= AllocatePool (ReadSize
);
202 if (FileContents
!= NULL
) {
203 Status
= FileHandleRead (
208 if (EFI_ERROR (Status
) || (ActualReadSize
!= ReadSize
)) {
209 FreePool (FileContents
);
219 Reads the contents of the NvVars file on the file system
221 @param[in] FsHandle - Handle for a gEfiSimpleFileSystemProtocolGuid instance
223 @return EFI_STATUS based on the success or failure of the file read
228 IN EFI_HANDLE FsHandle
232 EFI_FILE_HANDLE File
;
236 EFI_HANDLE SerializedVariables
;
238 Status
= GetNvVarsFile (FsHandle
, TRUE
, &File
);
239 if (EFI_ERROR (Status
)) {
240 DEBUG ((EFI_D_INFO
, "FsAccess.c: Could not open NV Variables file on this file system\n"));
244 NvVarsFileReadCheckup (File
, &FileExists
, &FileSize
);
246 FileHandleClose (File
);
247 return EFI_UNSUPPORTED
;
250 FileContents
= FileHandleReadToNewBuffer (File
, FileSize
);
251 if (FileContents
== NULL
) {
252 FileHandleClose (File
);
253 return EFI_UNSUPPORTED
;
258 "FsAccess.c: Read %d bytes from NV Variables file\n",
262 Status
= SerializeVariablesNewInstanceFromBuffer (
263 &SerializedVariables
,
267 if (!RETURN_ERROR (Status
)) {
268 Status
= SerializeVariablesSetSerializedVariables (SerializedVariables
);
271 FreePool (FileContents
);
272 FileHandleClose (File
);
279 Writes a variable to indicate that the NV variables
280 have been loaded from the file system.
293 // Write a variable to indicate we've already loaded the
294 // variable data. If it is found, we skip the loading on
295 // subsequent attempts.
297 Size
= sizeof (VarData
);
301 &gEfiSimpleFileSystemProtocolGuid
,
302 EFI_VARIABLE_NON_VOLATILE
|
303 EFI_VARIABLE_BOOTSERVICE_ACCESS
|
304 EFI_VARIABLE_RUNTIME_ACCESS
,
312 Loads the non-volatile variables from the NvVars file on the
315 @param[in] FsHandle - Handle for a gEfiSimpleFileSystemProtocolGuid instance
317 @return EFI_STATUS based on the success or failure of load operation
329 DEBUG ((EFI_D_INFO
, "FsAccess.c: LoadNvVarsFromFs\n"));
332 // We write a variable to indicate we've already loaded the
333 // variable data. If it is found, we skip the loading.
335 // This is relevent if the non-volatile variable have been
336 // able to survive a reboot operation. In that case, we don't
337 // want to re-load the file as it would overwrite newer changes
338 // made to the variables.
340 Size
= sizeof (VarData
);
342 Status
= gRT
->GetVariable (
344 &gEfiSimpleFileSystemProtocolGuid
,
349 if (Status
== EFI_SUCCESS
) {
350 DEBUG ((EFI_D_INFO
, "NV Variables were already loaded\n"));
351 return EFI_ALREADY_STARTED
;
355 // Attempt to restore the variables from the NvVars file.
357 Status
= ReadNvVarsFile (FsHandle
);
358 if (EFI_ERROR (Status
)) {
359 DEBUG ((EFI_D_INFO
, "Error while restoring NV variable data\n"));
364 // Write a variable to indicate we've already loaded the
365 // variable data. If it is found, we skip the loading on
366 // subsequent attempts.
372 "FsAccess.c: Read NV Variables file (size=%d)\n",
383 IterateVariablesCallbackAddAllNvVariables (
385 IN CHAR16
*VariableName
,
386 IN EFI_GUID
*VendorGuid
,
387 IN UINT32 Attributes
,
394 Instance
= (EFI_HANDLE
) Context
;
397 // Only save non-volatile variables
399 if ((Attributes
& EFI_VARIABLE_NON_VOLATILE
) == 0) {
400 return RETURN_SUCCESS
;
403 return SerializeVariablesAddVariable (
415 Saves the non-volatile variables into the NvVars file on the
418 @param[in] FsHandle - Handle for a gEfiSimpleFileSystemProtocolGuid instance
420 @return EFI_STATUS based on the success or failure of load operation
429 EFI_FILE_HANDLE File
;
431 UINTN VariableDataSize
;
433 EFI_HANDLE SerializedVariables
;
435 SerializedVariables
= NULL
;
437 Status
= SerializeVariablesNewInstance (&SerializedVariables
);
438 if (EFI_ERROR (Status
)) {
442 Status
= SerializeVariablesIterateSystemVariables (
443 IterateVariablesCallbackAddAllNvVariables
,
444 (VOID
*) SerializedVariables
446 if (EFI_ERROR (Status
)) {
451 VariableDataSize
= 0;
452 Status
= SerializeVariablesToBuffer (
457 if (Status
== RETURN_BUFFER_TOO_SMALL
) {
458 VariableData
= AllocatePool (VariableDataSize
);
459 if (VariableData
== NULL
) {
460 Status
= EFI_OUT_OF_RESOURCES
;
462 Status
= SerializeVariablesToBuffer (
470 SerializeVariablesFreeInstance (SerializedVariables
);
472 if (EFI_ERROR (Status
)) {
477 // Open the NvVars file for writing.
479 Status
= GetNvVarsFile (FsHandle
, FALSE
, &File
);
480 if (EFI_ERROR (Status
)) {
481 DEBUG ((EFI_D_INFO
, "FsAccess.c: Unable to open file to saved NV Variables\n"));
486 // Empty the starting file contents.
488 Status
= FileHandleEmpty (File
);
489 if (EFI_ERROR (Status
)) {
490 FileHandleClose (File
);
494 WriteSize
= VariableDataSize
;
495 Status
= FileHandleWrite (File
, &WriteSize
, VariableData
);
496 if (EFI_ERROR (Status
)) {
500 FileHandleClose (File
);
502 if (!EFI_ERROR (Status
)) {
504 // Write a variable to indicate we've already loaded the
505 // variable data. If it is found, we skip the loading on
506 // subsequent attempts.
510 DEBUG ((EFI_D_INFO
, "Saved NV Variables to NvVars file\n"));