use color_eyre::eyre::eyre; use mbrman::{MBRPartitionEntry, CHS, MBR}; use crate::disk::util::DiskInfo; use crate::disk::OsPartitionInfo; use crate::os_install::partition_for; use crate::Error; pub async fn partition(disk: &DiskInfo, overwrite: bool) -> Result { { let sectors = (disk.capacity / 512) as u32; let disk = disk.clone(); tokio::task::spawn_blocking(move || { let mut file = std::fs::File::options() .read(true) .write(true) .open(&disk.logicalname)?; let (mut mbr, guid_part) = if overwrite { (MBR::new_from(&mut file, 512, rand::random())?, None) } else { let mut mbr = MBR::read_from(&mut file, 512)?; let mut guid_part = None; for (idx, part_info) in disk .partitions .iter() .enumerate() .map(|(idx, x)| (idx + 1, x)) { if let Some(entry) = mbr.get_mut(idx) { if part_info.guid.is_some() { if entry.starting_lba < 33556480 { return Err(Error::new( eyre!("Not enough space before embassy data"), crate::ErrorKind::InvalidRequest, )); } guid_part = Some(std::mem::replace(entry, MBRPartitionEntry::empty())); } *entry = MBRPartitionEntry::empty(); } } (mbr, guid_part) }; mbr[1] = MBRPartitionEntry { boot: 0x80, first_chs: CHS::empty(), sys: 0x0b, last_chs: CHS::empty(), starting_lba: 2048, sectors: 2099200 - 2048, }; mbr[2] = MBRPartitionEntry { boot: 0, first_chs: CHS::empty(), sys: 0x83, last_chs: CHS::empty(), starting_lba: 2099200, sectors: 33556480 - 2099200, }; if overwrite { mbr[3] = MBRPartitionEntry { boot: 0, first_chs: CHS::empty(), sys: 0x8e, last_chs: CHS::empty(), starting_lba: 33556480, sectors: sectors - 33556480, } } else if let Some(guid_part) = guid_part { mbr[3] = guid_part; } mbr.write_into(&mut file)?; Ok(()) }) .await .unwrap()?; } Ok(OsPartitionInfo { efi: None, bios: None, boot: partition_for(&disk.logicalname, 1), root: partition_for(&disk.logicalname, 2), }) }