-
Notifications
You must be signed in to change notification settings - Fork 67
/
Copy pathdisk_image.rs
74 lines (69 loc) · 2.25 KB
/
disk_image.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
use super::error::DiskImageError;
use std::{path::Path, process::Command};
pub fn create_disk_image(
bootloader_elf_path: &Path,
output_bin_path: &Path,
) -> Result<(), DiskImageError> {
let llvm_tools = llvm_tools::LlvmTools::new()?;
let objcopy = llvm_tools
.tool(&llvm_tools::exe("llvm-objcopy"))
.ok_or(DiskImageError::LlvmObjcopyNotFound)?;
let format = match std::env::var("TARGET") {
Ok(target) => {
match target.split("-").next() {
Some("x86_64") => "elf64-x86-64",
Some("aarch64") => "elf64-aarch64",
_ => return Err(DiskImageError::TargetNotSupported { target })
}
},
Err(_) => "elf64-x86-64"
};
// convert bootloader to binary
let mut cmd = Command::new(objcopy);
cmd.arg("-I").arg(format);
cmd.arg("-O").arg("binary");
// --binary-architecture is deprecated
//cmd.arg("--binary-architecture=i386:x86-64");
cmd.arg(bootloader_elf_path);
cmd.arg(output_bin_path);
let output = cmd.output().map_err(|err| DiskImageError::Io {
message: "failed to execute llvm-objcopy command",
error: err,
})?;
if !output.status.success() {
return Err(DiskImageError::ObjcopyFailed {
stderr: output.stderr,
});
}
pad_to_nearest_block_size(output_bin_path)?;
Ok(())
}
fn pad_to_nearest_block_size(output_bin_path: &Path) -> Result<(), DiskImageError> {
const BLOCK_SIZE: u64 = 512;
use std::fs::OpenOptions;
let file = OpenOptions::new()
.write(true)
.open(&output_bin_path)
.map_err(|err| DiskImageError::Io {
message: "failed to open boot image",
error: err,
})?;
let file_size = file
.metadata()
.map_err(|err| DiskImageError::Io {
message: "failed to get size of boot image",
error: err,
})?
.len();
let remainder = file_size % BLOCK_SIZE;
let padding = if remainder > 0 {
BLOCK_SIZE - remainder
} else {
0
};
file.set_len(file_size + padding)
.map_err(|err| DiskImageError::Io {
message: "failed to pad boot image to a multiple of the block size",
error: err,
})
}