Files
start-os/backend/src/os_install/gpt.rs
Aiden McClelland c7d82102ed Bugfix/gpt reflash (#2266)
* debug entry

* update magic numbers

* remove dbg

* fix hostname

* fix reinstall logic
2023-05-11 14:16:19 -06:00

137 lines
4.8 KiB
Rust

use std::path::Path;
use color_eyre::eyre::eyre;
use gpt::disk::LogicalBlockSize;
use gpt::GptConfig;
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<OsPartitionInfo, Error> {
let efi = {
let disk = disk.clone();
tokio::task::spawn_blocking(move || {
let use_efi = Path::new("/sys/firmware/efi").exists();
let mut device = Box::new(
std::fs::File::options()
.read(true)
.write(true)
.open(&disk.logicalname)?,
);
let (mut gpt, guid_part) = if overwrite {
let mbr = gpt::mbr::ProtectiveMBR::with_lb_size(
u32::try_from((disk.capacity / 512) - 1).unwrap_or(0xFF_FF_FF_FF),
);
mbr.overwrite_lba0(&mut device)?;
(
GptConfig::new()
.writable(true)
.initialized(false)
.logical_block_size(LogicalBlockSize::Lb512)
.create_from_device(device, None)?,
None,
)
} else {
let gpt = GptConfig::new()
.writable(true)
.initialized(true)
.logical_block_size(LogicalBlockSize::Lb512)
.open_from_device(device)?;
let mut guid_part = None;
for (idx, part_info) in disk
.partitions
.iter()
.enumerate()
.map(|(idx, x)| (idx + 1, x))
{
if let Some(entry) = gpt.partitions().get(&(idx as u32)) {
if part_info.guid.is_some() {
if entry.first_lba < if use_efi { 33759266 } else { 33570850 } {
return Err(Error::new(
eyre!("Not enough space before embassy data"),
crate::ErrorKind::InvalidRequest,
));
}
guid_part = Some(entry.clone());
break;
}
}
}
(gpt, guid_part)
};
gpt.update_partitions(Default::default())?;
let efi = if use_efi {
gpt.add_partition("efi", 100 * 1024 * 1024, gpt::partition_types::EFI, 0, None)?;
true
} else {
gpt.add_partition(
"bios-grub",
8 * 1024 * 1024,
gpt::partition_types::BIOS,
0,
None,
)?;
false
};
gpt.add_partition(
"boot",
1024 * 1024 * 1024,
gpt::partition_types::LINUX_FS,
0,
None,
)?;
gpt.add_partition(
"root",
15 * 1024 * 1024 * 1024,
match *crate::ARCH {
"x86_64" => gpt::partition_types::LINUX_ROOT_X64,
"aarch64" => gpt::partition_types::LINUX_ROOT_ARM_64,
_ => gpt::partition_types::LINUX_FS,
},
0,
None,
)?;
if overwrite {
gpt.add_partition(
"data",
gpt.find_free_sectors()
.iter()
.map(|(_, size)| *size * u64::from(*gpt.logical_block_size()))
.max()
.ok_or_else(|| {
Error::new(
eyre!("No free space left on device"),
crate::ErrorKind::BlockDevice,
)
})?,
gpt::partition_types::LINUX_LVM,
0,
None,
)?;
} else if let Some(guid_part) = guid_part {
let mut parts = gpt.partitions().clone();
parts.insert(gpt.find_next_partition_id(), guid_part);
gpt.update_partitions(parts)?;
}
gpt.write()?;
Ok(efi)
})
.await
.unwrap()?
};
Ok(OsPartitionInfo {
efi: efi.then(|| partition_for(&disk.logicalname, 1)),
bios: (!efi).then(|| partition_for(&disk.logicalname, 1)),
boot: partition_for(&disk.logicalname, 2),
root: partition_for(&disk.logicalname, 3),
})
}