Skip to content

Commit

Permalink
feat(efiboot): add efiboot dump and efiboot import (#64)
Browse files Browse the repository at this point in the history
  • Loading branch information
iTrooz committed Aug 11, 2023
1 parent 74566c1 commit 7773ce4
Show file tree
Hide file tree
Showing 6 changed files with 136 additions and 0 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions efiboot/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ description = "EFI boot manager variable editor written in Rust"
edition = "2018"

[dependencies]
byteorder = "1.4.3"
efivar = { version = "1.3.0", path = "../efivar", features = ["store"] }
itertools = "0.11.0"
paw = "1.0.0"
Expand Down
4 changes: 4 additions & 0 deletions efiboot/src/cli.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
mod boot;
mod delete;
mod dump;
mod import;
mod list;
mod read;

pub use self::boot::get_entries as get_boot_entries;
pub use self::boot::get_order as get_boot_order;
pub use self::delete::run as delete;
pub use self::dump::run as dump;
pub use self::import::run as import;
pub use self::list::run as list;
pub use self::read::run as read;
39 changes: 39 additions & 0 deletions efiboot/src/cli/dump.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
use std::{fs::File, io::Write, path::Path};

use uuid::Uuid;

use efivar::{
efi::{VariableFlags, VariableName, VariableVendor},
VarManager,
};

fn dump(output_path: &Path, flags: VariableFlags, data: &[u8]) -> Result<(), std::io::Error> {
let mut file = File::create(output_path)?;
file.write_all(&flags.bits().to_le_bytes())?;
file.write_all(data)?;

Ok(())
}

pub fn run(reader: Box<dyn VarManager>, name: &str, namespace: Option<Uuid>, output_path: &Path) {
let var = VariableName::new_with_vendor(
name,
namespace.map_or(VariableVendor::Efi, VariableVendor::Custom),
);

let mut buf = vec![0u8; 512];
match reader.read(&var, &mut buf) {
Ok((size, flags)) => {
buf.resize(size, 0);
match dump(output_path, flags, &buf) {
Ok(_) => println!(
"Dumped variable {} to file {}",
var,
output_path.canonicalize().unwrap().display()
),
Err(err) => eprintln!("Failed to write to file: {}", err),
}
}
Err(err) => eprintln!("Failed to read variable: {}", err),
}
}
49 changes: 49 additions & 0 deletions efiboot/src/cli/import.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
use std::{fs::File, io::Read, path::Path};

use uuid::Uuid;

use byteorder::{LittleEndian, ReadBytesExt};

use efivar::{
efi::{VariableFlags, VariableName, VariableVendor},
VarManager,
};

fn read_var_from_file(input_path: &Path) -> Result<(VariableFlags, Vec<u8>), std::io::Error> {
let mut file = File::open(input_path)?;

let flags = VariableFlags::from_bits(file.read_u32::<LittleEndian>()?).unwrap();
let mut data = Vec::new();
file.read_to_end(&mut data)?;

Ok((flags, data))
}

pub fn run(
mut manager: Box<dyn VarManager>,
input_path: &Path,
name: &str,
namespace: Option<Uuid>,
) {
let var = VariableName::new_with_vendor(
name,
namespace.map_or(VariableVendor::Efi, VariableVendor::Custom),
);

let (flags, data) = match read_var_from_file(input_path) {
Ok(inner) => inner,
Err(err) => {
eprintln!(
"Failed to read variable from file {}: {}",
input_path.display(),
err
);
return;
}
};

match manager.write(&var, flags, &data) {
Ok(()) => println!("Imported variable {} with success", var),
Err(err) => eprintln!("Failed to write variable {}: {}", var, err),
}
}
42 changes: 42 additions & 0 deletions efiboot/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,34 @@ enum Command {

/// Manage boot-related variables
Boot(BootCommand),
/// Dump a variable to file
Dump {
/// Name of the variable to dump
#[structopt(value_name = "VARIABLE")]
name: String,

/// GUID of the namespace. Default: EFI standard namespace
#[structopt(short, long, value_name = "NAMESPACE")]
namespace: Option<uuid::Uuid>,

/// Output file
#[structopt(value_name = "OUTPUT_FILE")]
output_file: PathBuf,
},
/// Import a variable from a file
Import {
/// Input file
#[structopt(value_name = "OUTPUT_FILE")]
input_file: PathBuf,

/// Name of the variable to create
#[structopt(value_name = "VARIABLE")]
name: String,

/// GUID of the namespace. Default: EFI standard namespace
#[structopt(short, long, value_name = "NAMESPACE")]
namespace: Option<uuid::Uuid>,
},
}

#[derive(StructOpt)]
Expand Down Expand Up @@ -101,5 +129,19 @@ fn main(opts: Opt) {
cli::get_boot_entries(manager, verbose);
}
},
Command::Dump {
name,
namespace,
output_file,
} => {
cli::dump(manager, &name, namespace, &output_file);
}
Command::Import {
input_file,
name,
namespace,
} => {
cli::import(manager, &input_file, &name, namespace);
}
}
}

0 comments on commit 7773ce4

Please sign in to comment.