yggdrasil/xtask/src/build/x86_64.rs

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)
}