/// Creates a GPT disk from the provided FAT image. pub fn create_gpt_disk(fat_image: &Path, out_gpt_path: &Path) -> anyhow::Result<()> { // create new file let mut disk = fs::OpenOptions::new() .create(true) .truncate(true) .read(true) .write(true) .open(out_gpt_path) .with_context(|| format!("failed to create GPT file at `{}`", out_gpt_path.display()))?; // set file size let partition_size: u64 = fs::metadata(fat_image) .context("failed to read metadata of fat image")? .len(); let disk_size = partition_size + 1024 * 64; // for GPT headers disk.set_len(disk_size) .context("failed to set GPT image file length")?; // create a protective MBR at LBA0 so that disk is not considered // unformatted on BIOS systems let mbr = gpt::mbr::ProtectiveMBR::with_lb_size( u32::try_from((disk_size / 512) - 1).unwrap_or(0xFF_FF_FF_FF), ); mbr.overwrite_lba0(&mut disk) .context("failed to write protective MBR")?; // create new GPT structure let block_size = gpt::disk::LogicalBlockSize::Lb512; let mut gpt = gpt::GptConfig::new() .writable(true) .initialized(false) .logical_block_size(block_size) .create_from_device(Box::new(&mut disk), None) .context("failed to create GPT structure in file")?; gpt.update_partitions(Default::default()) .context("failed to update GPT partitions")?; // add new EFI system partition and get its byte offset in the file let partition_id = gpt .add_partition("boot", partition_size, gpt::partition_types::EFI, 0, None) .context("failed to add boot EFI partition")?; let partition = gpt .partitions() .get(&partition_id) .context("failed to open boot partition after creation")?; let start_offset = partition .bytes_start(block_size) .context("failed to get start offset of boot partition")?; // close the GPT structure and write out changes gpt.write().context("failed to write out GPT changes")?; // place the FAT filesystem in the newly created partition disk.seek(io::SeekFrom::Start(start_offset)) .context("failed to seek to start offset")?; io::copy( &mut File::open(fat_image).context("failed to open FAT image")?, &mut disk, ) .context("failed to copy FAT image to GPT disk")?; Ok(()) } // IMPORTS // use { anyhow::Context, std::{ fs::{self, File}, io::{self, Seek}, path::Path, } };