2 File System Access for NvVarsFileLib
4 Copyright (c) 2004 - 2011, 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 Loads the non-volatile variables from the NvVars file on the
282 @param[in] FsHandle - Handle for a gEfiSimpleFileSystemProtocolGuid instance
284 @return EFI_STATUS based on the success or failure of load operation
296 DEBUG ((EFI_D_INFO
, "FsAccess.c: LoadNvVarsFromFs\n"));
299 // We write a variable to indicate we've already loaded the
300 // variable data. If it is found, we skip the loading.
302 // This is relevent if the non-volatile variable have been
303 // able to survive a reboot operation. In that case, we don't
304 // want to re-load the file as it would overwrite newer changes
305 // made to the variables.
307 Size
= sizeof (VarData
);
309 Status
= gRT
->GetVariable (
311 &gEfiSimpleFileSystemProtocolGuid
,
316 if (Status
== EFI_SUCCESS
) {
317 DEBUG ((EFI_D_INFO
, "NV Variables were already loaded\n"));
318 return EFI_ALREADY_STARTED
;
322 // Attempt to restore the variables from the NvVars file.
324 Status
= ReadNvVarsFile (FsHandle
);
325 if (EFI_ERROR (Status
)) {
326 DEBUG ((EFI_D_INFO
, "Error while restoring NV variable data\n"));
331 // Write a variable to indicate we've already loaded the
332 // variable data. If it is found, we skip the loading on
333 // subsequent attempts.
335 Size
= sizeof (VarData
);
339 &gEfiSimpleFileSystemProtocolGuid
,
340 EFI_VARIABLE_NON_VOLATILE
|
341 EFI_VARIABLE_BOOTSERVICE_ACCESS
|
342 EFI_VARIABLE_RUNTIME_ACCESS
,
349 "FsAccess.c: Read NV Variables file (size=%d)\n",
360 IterateVariablesCallbackAddAllNvVariables (
362 IN CHAR16
*VariableName
,
363 IN EFI_GUID
*VendorGuid
,
364 IN UINT32 Attributes
,
371 Instance
= (EFI_HANDLE
) Context
;
374 // Only save non-volatile variables
376 if ((Attributes
& EFI_VARIABLE_NON_VOLATILE
) == 0) {
377 return RETURN_SUCCESS
;
380 return SerializeVariablesAddVariable (
392 Saves the non-volatile variables into the NvVars file on the
395 @param[in] FsHandle - Handle for a gEfiSimpleFileSystemProtocolGuid instance
397 @return EFI_STATUS based on the success or failure of load operation
406 EFI_FILE_HANDLE File
;
408 UINTN VariableDataSize
;
410 EFI_HANDLE SerializedVariables
;
412 Status
= SerializeVariablesNewInstance (&SerializedVariables
);
413 if (EFI_ERROR (Status
)) {
417 Status
= SerializeVariablesIterateSystemVariables (
418 IterateVariablesCallbackAddAllNvVariables
,
419 (VOID
*) SerializedVariables
421 if (EFI_ERROR (Status
)) {
426 VariableDataSize
= 0;
427 Status
= SerializeVariablesToBuffer (
432 if (Status
== RETURN_BUFFER_TOO_SMALL
) {
433 VariableData
= AllocatePool (VariableDataSize
);
434 if (VariableData
== NULL
) {
435 Status
= EFI_OUT_OF_RESOURCES
;
437 Status
= SerializeVariablesToBuffer (
445 SerializeVariablesFreeInstance (SerializedVariables
);
447 if (EFI_ERROR (Status
)) {
452 // Open the NvVars file for writing.
454 Status
= GetNvVarsFile (FsHandle
, FALSE
, &File
);
455 if (EFI_ERROR (Status
)) {
456 DEBUG ((EFI_D_INFO
, "FsAccess.c: Unable to open file to saved NV Variables\n"));
461 // Empty the starting file contents.
463 Status
= FileHandleEmpty (File
);
464 if (EFI_ERROR (Status
)) {
465 FileHandleClose (File
);
469 WriteSize
= VariableDataSize
;
470 Status
= FileHandleWrite (File
, &WriteSize
, VariableData
);
471 if (EFI_ERROR (Status
)) {
475 FileHandleClose (File
);
477 if (!EFI_ERROR (Status
)) {
478 DEBUG ((EFI_D_INFO
, "Saved NV Variables to NvVars file\n"));