mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-26 02:11:53 +00:00
137 lines
4.8 KiB
Rust
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),
|
|
})
|
|
}
|