xtask/tasks/guest_test/uefi/
gpt_efi_disk.rsuse anyhow::Context;
use anyhow::Result;
use fatfs::FileSystem;
use fatfs::FormatVolumeOptions;
use fatfs::FsOptions;
use guid::Guid;
use std::io::Cursor;
use std::io::Seek;
use std::path::Path;
use zerocopy::IntoBytes;
const SECTOR_SIZE: usize = 512;
const EFI_GUID: Guid = guid::guid!("{c12a7328-f81f-11d2-ba4b-00a0c93ec93b}");
pub fn create_gpt_efi_disk(out_img: &Path, with_files: &[(&Path, &Path)]) -> Result<()> {
if out_img.extension().unwrap_or_default() != "img" {
return Err(anyhow::anyhow!(
"only .img disk images are supported at this time"
));
}
let disk_size = 1024 * 1024 * 32; let num_sectors = disk_size / SECTOR_SIZE;
let mut disk = vec![0; num_sectors * SECTOR_SIZE];
let efi_partition_range = {
let mut cur = Cursor::new(&mut disk);
let mut mbr = mbrman::MBR::new_from(&mut cur, SECTOR_SIZE as u32, [0xff; 4])?;
let mut gpt = gptman::GPT::new_from(&mut cur, SECTOR_SIZE as u64, [0xff; 16])?;
let first_chs = mbrman::CHS::new(0, 0, 2);
let last_chs = mbrman::CHS::empty(); mbr[1] = mbrman::MBRPartitionEntry {
boot: mbrman::BOOT_INACTIVE,
first_chs,
sys: 0xEE, last_chs,
starting_lba: 1,
sectors: gpt.header.last_usable_lba.try_into().unwrap_or(0xFFFFFFFF),
};
mbr.write_into(&mut cur)?;
cur.rewind()?;
gpt[1] = gptman::GPTPartitionEntry {
partition_type_guid: EFI_GUID.as_bytes().try_into().unwrap(),
unique_partition_guid: [0xff; 16],
starting_lba: gpt.header.first_usable_lba,
ending_lba: gpt.header.last_usable_lba,
attribute_bits: 0,
partition_name: "EFI".into(),
};
gpt.write_into(&mut cur)?;
let partition_start_byte = gpt[1].starting_lba as usize * SECTOR_SIZE;
let partition_num_bytes = (gpt[1].ending_lba - gpt[1].starting_lba) as usize * SECTOR_SIZE;
partition_start_byte..partition_start_byte + partition_num_bytes
};
init_fat(&mut disk[efi_partition_range], with_files).context("initializing FAT partition")?;
fs_err::write(out_img, &disk)?;
log::info!("Wrote test image to: {}", out_img.display());
Ok(())
}
fn init_fat(partition: &mut [u8], with_files: &[(&Path, &Path)]) -> Result<()> {
let efi_fs = {
let mut cursor = Cursor::new(partition);
fatfs::format_volume(
&mut cursor,
FormatVolumeOptions::new()
.fat_type(fatfs::FatType::Fat32)
.volume_label(*b"hvlite_test"),
)?;
cursor.rewind()?;
FileSystem::new(cursor, FsOptions::new().update_accessed_date(false))?
};
let root_dir = efi_fs.root_dir();
for (dst_file, src_file) in with_files {
let ancestors = dst_file.ancestors().collect::<Vec<_>>();
let num_ancestors = ancestors.len();
for (i, chunk) in ancestors.into_iter().rev().enumerate() {
if i == 0 {
continue;
}
if i != num_ancestors - 1 {
log::info!("creating dir {}", chunk.display());
root_dir
.create_dir(chunk.to_str().unwrap())
.context("creating dir")?;
} else {
log::info!("creating file {}", chunk.display());
let mut file = root_dir
.create_file(chunk.to_str().unwrap())
.context(format!("creating file {}", chunk.display()))?;
std::io::copy(&mut fs_err::File::open(src_file)?, &mut file)?;
}
}
}
log::info!("{:?}", efi_fs.stats()?);
Ok(())
}