use std::{env, fs, os::unix::ffi::OsStrExt, path::PathBuf, process::Command}; use gpt::{mbr::ProtectiveMBR, GptConfig}; const ROOT_DISK_SIZE_MB: usize = 256; fn main() { println!("cargo:rerun-if-changed=sysroot"); println!("cargo:rerun-if-changed=build.rs"); println!("cargo:rerun-if-changed=initrd_file_list"); println!("cargo:rerun-if-changed=bootloader-x86_64-uefi.efi"); println!("cargo:rerun-if-changed=boot.json"); // set by cargo, build scripts should use this directory for output files let out_dir = std::env::var_os("OUT_DIR").unwrap(); std::fs::write("out_dir_path", out_dir.as_os_str().as_bytes()).unwrap(); let mut initrd_path = out_dir.clone(); initrd_path.push("/initrd.tar"); Command::new("bash") .arg("-c") .arg(format!( "cd sysroot; tar cvf {:?} $(cat ../initrd_file_list)", initrd_path )) .output() .unwrap(); let kernel = PathBuf::from(env::var_os("CARGO_BIN_FILE_KERNEL_kernel").unwrap()); let mut disk_path = out_dir.clone(); disk_path.push("/root.img"); Command::new("dd") .arg("if=/dev/zero") .arg(format!("of={}", disk_path.to_str().unwrap())) .arg("bs=1M") .arg(format!("count={}", ROOT_DISK_SIZE_MB)) .output() .unwrap(); let mut disk = GptConfig::new().writable(true).create(&disk_path).unwrap(); ProtectiveMBR::new() .overwrite_lba0(disk.device_mut()) .unwrap(); let boot_part_id = disk .add_partition("boot", 32 * 1024 * 1024, gpt::partition_types::EFI, 0, None) .unwrap(); let root_part_id = disk .add_partition( "root", disk.find_free_sectors()[1].1 * disk.logical_block_size().as_u64(), gpt::partition_types::LINUX_FS, 0, None, ) .unwrap(); disk.write_inplace().unwrap(); let boot_part = &disk.partitions()[&boot_part_id]; let root_part = &disk.partitions()[&root_part_id]; Command::new("dd") .arg(format!("if={}", disk_path.to_str().unwrap())) .arg("of=tmp_ext2.img") .arg(format!("bs={}", disk.logical_block_size().as_u64())) .arg(format!("skip={}", root_part.first_lba)) .arg(format!("count={}", root_part.sectors_len().unwrap())) .output() .unwrap(); Command::new("mkfs.ext2") .arg("-O") .arg("^resize_inode") .arg("-d") .arg("sysroot") .arg("tmp_ext2.img") .output() .unwrap(); Command::new("dd") .arg("if=tmp_ext2.img") .arg(format!("of={}", disk_path.to_str().unwrap())) .arg(format!("bs={}", disk.logical_block_size().as_u64())) .arg(format!("seek={}", root_part.first_lba)) .arg("conv=notrunc") .output() .unwrap(); fs::remove_file("tmp_ext2.img").unwrap(); Command::new("dd") .arg(format!("if={}", disk_path.to_str().unwrap())) .arg("of=tmp_esp.img") .arg(format!("bs={}", disk.logical_block_size().as_u64())) .arg(format!("skip={}", boot_part.first_lba)) .arg(format!("count={}", boot_part.sectors_len().unwrap())) .output() .unwrap(); Command::new("mkfs.fat") .arg("-g") .arg("64/32") .arg("-i") .arg("12345678") .arg("-n") .arg("kernel-bd3a") .arg("tmp_esp.img") .output() .unwrap(); Command::new("mmd") .arg("-i") .arg("tmp_esp.img") .arg("efi") .output() .unwrap(); Command::new("mmd") .arg("-i") .arg("tmp_esp.img") .arg("efi/boot") .output() .unwrap(); Command::new("mcopy") .arg("-i") .arg("tmp_esp.img") .arg("bootloader-x86_64-uefi.efi") .arg("::efi/boot/bootx64.efi") .output() .unwrap(); Command::new("mcopy") .arg("-i") .arg("tmp_esp.img") .arg(&kernel) .arg("::kernel-x86_64") .output() .unwrap(); Command::new("mcopy") .arg("-i") .arg("tmp_esp.img") .arg(&initrd_path) .arg("::ramdisk") .output() .unwrap(); Command::new("mcopy") .arg("-i") .arg("tmp_esp.img") .arg("boot.json") .arg("::") .output() .unwrap(); Command::new("dd") .arg("if=tmp_esp.img") .arg(format!("of={}", disk_path.to_str().unwrap())) .arg(format!("bs={}", disk.logical_block_size().as_u64())) .arg(format!("seek={}", boot_part.first_lba)) .arg("conv=notrunc") .output() .unwrap(); fs::remove_file("tmp_esp.img").unwrap(); println!("cargo:rustc-env=DISK_PATH={}", disk_path.to_string_lossy()); }