1use super::*;
2use std::ffi::OsStr;
3use std::fs;
4use std::io::Write;
5use std::path::Path;
6
7pub const DEFAULT_STARTUP_NSH: &[u8] = include_bytes!("startup.nsh");
9
10pub struct EfiImage {
12 fs: fatfs::FileSystem<fs::File>,
13}
14
15impl EfiImage {
16 pub fn new<P: AsRef<Path>>(path: P, size: u64) -> Result<Self> {
18 let file = std::fs::OpenOptions::new()
20 .read(true)
21 .write(true)
22 .create_new(true)
23 .open(&path)?;
24 file.set_len(size)?;
25
26 fatfs::format_volume(&file, fatfs::FormatVolumeOptions::new())?;
28 let fs = fatfs::FileSystem::new(file, fatfs::FsOptions::new())?;
29
30 Ok(Self { fs })
31 }
32
33 fn add_file<P: AsRef<Path>>(&mut self, path: P) -> Result<fatfs::File<'_, fs::File>> {
35 let path = path.as_ref();
36 let file_name = path
37 .file_name()
38 .ok_or_else(|| Error::msg("Invalid path"))?
39 .to_str()
40 .ok_or_else(|| Error::msg("Invalid filename encoding"))?;
41 let mut dir = self.fs.root_dir();
42 if let Some(dir_path) = path.parent() {
43 for dir_path_component in dir_path.iter() {
44 if dir_path_component == OsStr::new(&std::path::MAIN_SEPARATOR.to_string()) {
45 continue;
46 }
47 let dir_path_component = dir_path_component
48 .to_str()
49 .ok_or_else(|| Error::msg("Cannot convert path to string"))?;
50 dir = dir.create_dir(dir_path_component)?;
51 }
52 }
53 let mut file = dir.create_file(file_name)?;
54 file.truncate()?;
55 Ok(file)
56 }
57
58 pub fn copy_host_file<P1: AsRef<Path>, P2: AsRef<Path>>(
60 &mut self,
61 src: P1,
62 dst: P2,
63 ) -> Result<()> {
64 let file_contents = fs::read(src)?;
65 let mut file = self.add_file(dst)?;
66 file.write_all(&file_contents)?;
67 Ok(())
68 }
69
70 pub fn set_file_contents<P: AsRef<Path>, B: AsRef<[u8]>>(
72 &mut self,
73 path: P,
74 contents: B,
75 ) -> Result<()> {
76 let mut file = self.add_file(path)?;
77 file.write_all(contents.as_ref())?;
78 Ok(())
79 }
80}