97 lines
2.5 KiB
Rust
97 lines
2.5 KiB
Rust
use std::{
|
|
fs::{File, OpenOptions},
|
|
io::{self, BufReader, BufWriter},
|
|
path::{Path, PathBuf},
|
|
};
|
|
|
|
use fscommon::BufStream;
|
|
|
|
use crate::{build::cargo::CargoBuilder, env::BuildEnv, error::Error, util};
|
|
|
|
use super::{ImageBuilt, InitrdGenerated, KernelProcessed};
|
|
|
|
pub struct YbootBuilt(PathBuf);
|
|
|
|
fn build_yboot(env: &BuildEnv) -> Result<YbootBuilt, Error> {
|
|
log::info!("Building yboot");
|
|
CargoBuilder::Host(env.verbose).build("boot/yboot")?;
|
|
let binary = env.workspace_root.join(format!(
|
|
"boot/yboot/target/x86_64-unknown-uefi/debug/yboot.efi"
|
|
));
|
|
Ok(YbootBuilt(binary))
|
|
}
|
|
|
|
fn copy_into_fat(
|
|
dir: &fatfs::Dir<'_, BufStream<File>>,
|
|
src: impl AsRef<Path>,
|
|
dst: impl AsRef<str>,
|
|
) -> Result<(), Error> {
|
|
let src = src.as_ref();
|
|
let dst = dst.as_ref();
|
|
|
|
log::debug!("{} -> {}", src.display(), dst);
|
|
let mut dst = dir.create_file(dst)?;
|
|
let mut src = BufReader::new(File::open(src)?);
|
|
|
|
dst.truncate()?;
|
|
let mut dst = BufWriter::new(dst);
|
|
|
|
io::copy(&mut src, &mut dst)?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn build_uefi_image(
|
|
env: &BuildEnv,
|
|
yboot: YbootBuilt,
|
|
kernel: KernelProcessed,
|
|
initrd: InitrdGenerated,
|
|
) -> Result<ImageBuilt, Error> {
|
|
log::info!("Building x86-64 UEFI image");
|
|
let image_path = env.kernel_output_dir.join("image.fat32");
|
|
|
|
if !image_path.exists() {
|
|
util::run_external_command(
|
|
"dd",
|
|
[
|
|
"if=/dev/zero",
|
|
&format!("of={}", image_path.display()),
|
|
"bs=1M",
|
|
"count=256",
|
|
],
|
|
false,
|
|
)?;
|
|
util::run_external_command(
|
|
"mkfs.vfat",
|
|
["-F32".as_ref(), image_path.as_os_str()],
|
|
false,
|
|
)?;
|
|
}
|
|
|
|
let image_file = OpenOptions::new()
|
|
.read(true)
|
|
.write(true)
|
|
.open(&image_path)?;
|
|
let buf_stream = fscommon::BufStream::new(image_file);
|
|
let fs = fatfs::FileSystem::new(buf_stream, fatfs::FsOptions::new())?;
|
|
|
|
let root_dir = fs.root_dir();
|
|
|
|
let boot_dir = root_dir.create_dir("EFI")?.create_dir("Boot")?;
|
|
copy_into_fat(&boot_dir, &yboot.0, "BootX64.efi")?;
|
|
copy_into_fat(&root_dir, &kernel.0 .0, "kernel.elf")?;
|
|
copy_into_fat(&root_dir, &initrd.0, "initrd.img")?;
|
|
|
|
Ok(ImageBuilt(image_path))
|
|
}
|
|
|
|
pub fn build_image(
|
|
env: &BuildEnv,
|
|
kernel: KernelProcessed,
|
|
initrd: InitrdGenerated,
|
|
) -> Result<ImageBuilt, Error> {
|
|
let yboot = build_yboot(env)?;
|
|
let image = build_uefi_image(env, yboot, kernel, initrd)?;
|
|
Ok(image)
|
|
}
|