/** Saves the non-volatile variables into the NvVars file on the given file system. @param[in] FsHandle - Handle for a gEfiSimpleFileSystemProtocolGuid instance @return EFI_STATUS based on the success or failure of load operation **/ EFI_STATUS SaveNvVarsToFs ( EFI_HANDLE FsHandle ) { EFI_STATUS Status; EFI_FILE_HANDLE File; UINTN WriteSize; UINTN VariableDataSize; VOID *VariableData; EFI_HANDLE SerializedVariables; SerializedVariables = NULL; Status = SerializeVariablesNewInstance (&SerializedVariables); if (EFI_ERROR (Status)) { return Status; } Status = SerializeVariablesIterateSystemVariables ( IterateVariablesCallbackAddAllNvVariables, (VOID*) SerializedVariables ); if (EFI_ERROR (Status)) { return Status; } VariableData = NULL; VariableDataSize = 0; Status = SerializeVariablesToBuffer ( SerializedVariables, NULL, &VariableDataSize ); if (Status == RETURN_BUFFER_TOO_SMALL) { VariableData = AllocatePool (VariableDataSize); if (VariableData == NULL) { Status = EFI_OUT_OF_RESOURCES; } else { Status = SerializeVariablesToBuffer ( SerializedVariables, VariableData, &VariableDataSize ); } } SerializeVariablesFreeInstance (SerializedVariables); if (EFI_ERROR (Status)) { return Status; } // // Open the NvVars file for writing. // Status = GetNvVarsFile (FsHandle, FALSE, &File); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_INFO, "FsAccess.c: Unable to open file to saved NV Variables\n")); return Status; } // // Empty the starting file contents. // Status = FileHandleEmpty (File); if (EFI_ERROR (Status)) { FileHandleClose (File); return Status; } WriteSize = VariableDataSize; Status = FileHandleWrite (File, &WriteSize, VariableData); if (EFI_ERROR (Status)) { return Status; } FileHandleClose (File); if (!EFI_ERROR (Status)) { // // Write a variable to indicate we've already loaded the // variable data. If it is found, we skip the loading on // subsequent attempts. // SetNvVarsVariable(); DEBUG ((EFI_D_INFO, "Saved NV Variables to NvVars file\n")); } return Status; }
/** Saves the non-volatile variables into the NvVars file on the given file system. @param[in] FsHandle - Handle for a gEfiSimpleFileSystemProtocolGuid instance @return EFI_STATUS based on the success or failure of load operation **/ EFI_STATUS SaveNvVarsToFs ( EFI_HANDLE FsHandle ) { EFI_STATUS Status; EFI_FILE_HANDLE File; UINTN VariableNameBufferSize; UINTN VariableNameSize; CHAR16 *VariableName; EFI_GUID VendorGuid; UINTN VariableDataBufferSize; UINTN VariableDataSize; VOID *VariableData; UINT32 VariableAttributes; VOID *NewBuffer; // // Open the NvVars file for writing. // Status = GetNvVarsFile (FsHandle, FALSE, &File); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_INFO, "FsAccess.c: Unable to open file to saved NV Variables\n")); return Status; } // // Empty the starting file contents. // Status = FileHandleEmpty (File); if (EFI_ERROR (Status)) { FileHandleClose (File); return Status; } // // Initialize the variable name and data buffer variables. // VariableNameBufferSize = sizeof (CHAR16); VariableName = AllocateZeroPool (VariableNameBufferSize); VariableDataBufferSize = 0; VariableData = NULL; for (;;) { // // Get the next variable name and guid // VariableNameSize = VariableNameBufferSize; Status = gRT->GetNextVariableName ( &VariableNameSize, VariableName, &VendorGuid ); if (Status == EFI_BUFFER_TOO_SMALL) { // // The currently allocated VariableName buffer is too small, // so we allocate a larger buffer, and copy the old buffer // to it. // NewBuffer = AllocatePool (VariableNameSize); if (NewBuffer == NULL) { Status = EFI_OUT_OF_RESOURCES; break; } CopyMem (NewBuffer, VariableName, VariableNameBufferSize); if (VariableName != NULL) { FreePool (VariableName); } VariableName = NewBuffer; VariableNameBufferSize = VariableNameSize; // // Try to get the next variable name again with the larger buffer. // Status = gRT->GetNextVariableName ( &VariableNameSize, VariableName, &VendorGuid ); } if (EFI_ERROR (Status)) { if (Status == EFI_NOT_FOUND) { Status = EFI_SUCCESS; } break; } // // Get the variable data and attributes // VariableDataSize = VariableDataBufferSize; Status = gRT->GetVariable ( VariableName, &VendorGuid, &VariableAttributes, &VariableDataSize, VariableData ); if (Status == EFI_BUFFER_TOO_SMALL) { // // The currently allocated VariableData buffer is too small, // so we allocate a larger buffer. // if (VariableDataBufferSize != 0) { FreePool (VariableData); VariableData = NULL; VariableDataBufferSize = 0; } VariableData = AllocatePool (VariableDataSize); if (VariableData == NULL) { Status = EFI_OUT_OF_RESOURCES; break; } VariableDataBufferSize = VariableDataSize; // // Try to read the variable again with the larger buffer. // Status = gRT->GetVariable ( VariableName, &VendorGuid, &VariableAttributes, &VariableDataSize, VariableData ); } if (EFI_ERROR (Status)) { break; } // // Skip volatile variables. We only preserve non-volatile variables. // if ((VariableAttributes & EFI_VARIABLE_NON_VOLATILE) == 0) { continue; } DEBUG (( EFI_D_INFO, "Saving variable %g:%s to file\n", &VendorGuid, VariableName )); // // Write the variable information out to the file // Status = PackVariableIntoFile ( File, VariableName, (UINT32) VariableNameSize, &VendorGuid, VariableAttributes, VariableData, (UINT32) VariableDataSize ); if (EFI_ERROR (Status)) { break; } } if (VariableName != NULL) { FreePool (VariableName); } if (VariableData != NULL) { FreePool (VariableData); } FileHandleClose (File); if (!EFI_ERROR (Status)) { DEBUG ((EFI_D_INFO, "Saved NV Variables to NvVars file\n")); } return Status; }