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
|
86 Open the NvVars file for reading or writing
88 @param[in] File - The file to inspect
89 @param[out] Exists - Returns whether the file exists
90 @param[out] Size - Returns the size of the file
91 (0 if the file does not exist)
95 NvVarsFileReadCheckup (
96 IN EFI_FILE_HANDLE File
,
101 EFI_FILE_INFO
*FileInfo
;
106 FileInfo
= FileHandleGetInfo (File
);
107 if (FileInfo
== NULL
) {
111 if ((FileInfo
->Attribute
& EFI_FILE_DIRECTORY
) != 0) {
117 *Size
= (UINTN
) FileInfo
->FileSize
;
124 Open the NvVars file for reading or writing
126 @param[in] File - The file to inspect
127 @param[out] Exists - Returns whether the file exists
128 @param[out] Size - Returns the size of the file
129 (0 if the file does not exist)
134 IN EFI_FILE_HANDLE File
138 EFI_FILE_INFO
*FileInfo
;
141 // Retrieve the FileInfo structure
143 FileInfo
= FileHandleGetInfo (File
);
144 if (FileInfo
== NULL
) {
145 return EFI_INVALID_PARAMETER
;
149 // If the path is a directory, then return an error
151 if ((FileInfo
->Attribute
& EFI_FILE_DIRECTORY
) != 0) {
153 return EFI_INVALID_PARAMETER
;
157 // If the file size is already 0, then it is empty, so
158 // we can return success.
160 if (FileInfo
->FileSize
== 0) {
166 // Set the file size to 0.
168 FileInfo
->FileSize
= 0;
169 Status
= FileHandleSetInfo (File
, FileInfo
);
178 Reads a file to a newly allocated buffer
180 @param[in] File - The file to read
181 @param[in] ReadSize - The size of data to read from the file
183 @return Pointer to buffer allocated to hold the file
184 contents. NULL if an error occurred.
188 FileHandleReadToNewBuffer (
189 IN EFI_FILE_HANDLE FileHandle
,
194 UINTN ActualReadSize
;
197 ActualReadSize
= ReadSize
;
198 FileContents
= AllocatePool (ReadSize
);
199 if (FileContents
!= NULL
) {
200 Status
= FileHandleRead (
205 if (EFI_ERROR (Status
) || (ActualReadSize
!= ReadSize
)) {
206 FreePool (FileContents
);
216 Reads the contents of the NvVars file on the file system
218 @param[in] FsHandle - Handle for a gEfiSimpleFileSystemProtocolGuid instance
220 @return EFI_STATUS based on the success or failure of the file read
225 IN EFI_HANDLE FsHandle
229 EFI_FILE_HANDLE File
;
233 EFI_HANDLE SerializedVariables
;
235 Status
= GetNvVarsFile (FsHandle
, TRUE
, &File
);
236 if (EFI_ERROR (Status
)) {
237 DEBUG ((EFI_D_INFO
, "FsAccess.c: Could not open NV Variables file on this file system\n"));
241 NvVarsFileReadCheckup (File
, &FileExists
, &FileSize
);
243 FileHandleClose (File
);
244 return EFI_UNSUPPORTED
;
247 FileContents
= FileHandleReadToNewBuffer (File
, FileSize
);
248 if (FileContents
== NULL
) {
249 FileHandleClose (File
);
250 return EFI_UNSUPPORTED
;
255 "FsAccess.c: Read %Lu bytes from NV Variables file\n",
259 Status
= SerializeVariablesNewInstanceFromBuffer (
260 &SerializedVariables
,
264 if (!RETURN_ERROR (Status
)) {
265 Status
= SerializeVariablesSetSerializedVariables (SerializedVariables
);
268 FreePool (FileContents
);
269 FileHandleClose (File
);
276 Writes a variable to indicate that the NV variables
277 have been loaded from the file system.
290 // Write a variable to indicate we've already loaded the
291 // variable data. If it is found, we skip the loading on
292 // subsequent attempts.
294 Size
= sizeof (VarData
);
298 &gEfiSimpleFileSystemProtocolGuid
,
299 EFI_VARIABLE_NON_VOLATILE
|
300 EFI_VARIABLE_BOOTSERVICE_ACCESS
|
301 EFI_VARIABLE_RUNTIME_ACCESS
,
309 Loads the non-volatile variables from the NvVars file on the
312 @param[in] FsHandle - Handle for a gEfiSimpleFileSystemProtocolGuid instance
314 @return EFI_STATUS based on the success or failure of load operation
326 DEBUG ((EFI_D_INFO
, "FsAccess.c: LoadNvVarsFromFs\n"));
329 // We write a variable to indicate we've already loaded the
330 // variable data. If it is found, we skip the loading.
332 // This is relevant if the non-volatile variable have been
333 // able to survive a reboot operation. In that case, we don't
334 // want to re-load the file as it would overwrite newer changes
335 // made to the variables.
337 Size
= sizeof (VarData
);
339 Status
= gRT
->GetVariable (
341 &gEfiSimpleFileSystemProtocolGuid
,
346 if (Status
== EFI_SUCCESS
) {
347 DEBUG ((EFI_D_INFO
, "NV Variables were already loaded\n"));
348 return EFI_ALREADY_STARTED
;
352 // Attempt to restore the variables from the NvVars file.
354 Status
= ReadNvVarsFile (FsHandle
);
355 if (EFI_ERROR (Status
)) {
356 DEBUG ((EFI_D_INFO
, "Error while restoring NV variable data\n"));
361 // Write a variable to indicate we've already loaded the
362 // variable data. If it is found, we skip the loading on
363 // subsequent attempts.
369 "FsAccess.c: Read NV Variables file (size=%Lu)\n",
380 IterateVariablesCallbackAddAllNvVariables (
382 IN CHAR16
*VariableName
,
383 IN EFI_GUID
*VendorGuid
,
384 IN UINT32 Attributes
,
391 Instance
= (EFI_HANDLE
) Context
;
394 // Only save non-volatile variables
396 if ((Attributes
& EFI_VARIABLE_NON_VOLATILE
) == 0) {
397 return RETURN_SUCCESS
;
400 return SerializeVariablesAddVariable (
412 Saves the non-volatile variables into the NvVars file on the
415 @param[in] FsHandle - Handle for a gEfiSimpleFileSystemProtocolGuid instance
417 @return EFI_STATUS based on the success or failure of load operation
426 EFI_FILE_HANDLE File
;
428 UINTN VariableDataSize
;
430 EFI_HANDLE SerializedVariables
;
432 SerializedVariables
= NULL
;
434 Status
= SerializeVariablesNewInstance (&SerializedVariables
);
435 if (EFI_ERROR (Status
)) {
439 Status
= SerializeVariablesIterateSystemVariables (
440 IterateVariablesCallbackAddAllNvVariables
,
441 (VOID
*) SerializedVariables
443 if (EFI_ERROR (Status
)) {
448 VariableDataSize
= 0;
449 Status
= SerializeVariablesToBuffer (
454 if (Status
== RETURN_BUFFER_TOO_SMALL
) {
455 VariableData
= AllocatePool (VariableDataSize
);
456 if (VariableData
== NULL
) {
457 Status
= EFI_OUT_OF_RESOURCES
;
459 Status
= SerializeVariablesToBuffer (
467 SerializeVariablesFreeInstance (SerializedVariables
);
469 if (EFI_ERROR (Status
)) {
474 // Open the NvVars file for writing.
476 Status
= GetNvVarsFile (FsHandle
, FALSE
, &File
);
477 if (EFI_ERROR (Status
)) {
478 DEBUG ((EFI_D_INFO
, "FsAccess.c: Unable to open file to saved NV Variables\n"));
483 // Empty the starting file contents.
485 Status
= FileHandleEmpty (File
);
486 if (EFI_ERROR (Status
)) {
487 FileHandleClose (File
);
491 WriteSize
= VariableDataSize
;
492 Status
= FileHandleWrite (File
, &WriteSize
, VariableData
);
493 if (EFI_ERROR (Status
)) {
497 FileHandleClose (File
);
499 if (!EFI_ERROR (Status
)) {
501 // Write a variable to indicate we've already loaded the
502 // variable data. If it is found, we skip the loading on
503 // subsequent attempts.
507 DEBUG ((EFI_D_INFO
, "Saved NV Variables to NvVars file\n"));