1pub fn create_gpt_disk(fat_image: &Path, out_gpt_path: &Path) -> anyhow::Result<()> {
3 let mut disk = fs::OpenOptions::new()
5 .create(true)
6 .truncate(true)
7 .read(true)
8 .write(true)
9 .open(out_gpt_path)
10 .with_context(|| format!("failed to create GPT file at `{}`", out_gpt_path.display()))?;
11
12 let partition_size: u64 = fs::metadata(fat_image)
14 .context("failed to read metadata of fat image")?
15 .len();
16 let disk_size = partition_size + 1024 * 64; disk.set_len(disk_size)
18 .context("failed to set GPT image file length")?;
19
20 let mbr = gpt::mbr::ProtectiveMBR::with_lb_size(
23 u32::try_from((disk_size / 512) - 1).unwrap_or(0xFF_FF_FF_FF),
24 );
25 mbr.overwrite_lba0(&mut disk)
26 .context("failed to write protective MBR")?;
27
28 let block_size = gpt::disk::LogicalBlockSize::Lb512;
30 let mut gpt = gpt::GptConfig::new()
31 .writable(true)
32 .initialized(false)
33 .logical_block_size(block_size)
34 .create_from_device(Box::new(&mut disk), None)
35 .context("failed to create GPT structure in file")?;
36 gpt.update_partitions(Default::default())
37 .context("failed to update GPT partitions")?;
38
39 let partition_id = gpt
41 .add_partition("boot", partition_size, gpt::partition_types::EFI, 0, None)
42 .context("failed to add boot EFI partition")?;
43 let partition = gpt
44 .partitions()
45 .get(&partition_id)
46 .context("failed to open boot partition after creation")?;
47 let start_offset = partition
48 .bytes_start(block_size)
49 .context("failed to get start offset of boot partition")?;
50
51 gpt.write().context("failed to write out GPT changes")?;
53
54 disk.seek(io::SeekFrom::Start(start_offset))
56 .context("failed to seek to start offset")?;
57 io::copy(
58 &mut File::open(fat_image).context("failed to open FAT image")?,
59 &mut disk,
60 )
61 .context("failed to copy FAT image to GPT disk")?;
62
63 Ok(())
64}
65
66use {
69 anyhow::Context,
70 std::{
71 fs::{self, File},
72 io::{self, Seek},
73 path::Path,
74 }
75};