mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-04-04 22:39:46 +00:00
refactor: derive OsPartitionInfo from fstab instead of config.yaml
Replace the serialized os_partitions field in ServerConfig with runtime fstab parsing. OsPartitionInfo::from_fstab() resolves PARTUUID/UUID/LABEL device specs via blkid and discovers the BIOS boot partition by scanning for its GPT type GUID via lsblk. Also removes the efibootmgr-based boot order management (replaced by GRUB-based USB detection in a subsequent commit) and adds a dedicated bios: Option<PathBuf> field for the unformatted BIOS boot partition.
This commit is contained in:
@@ -68,21 +68,6 @@ fi
|
|||||||
|
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# Promote the USB installer boot entry back to first in EFI boot order.
|
|
||||||
# The entry number was saved during initial OS install.
|
|
||||||
if [ -d /sys/firmware/efi ] && [ -f /media/startos/config/efi-installer-entry ]; then
|
|
||||||
USB_ENTRY=$(cat /media/startos/config/efi-installer-entry)
|
|
||||||
if [ -n "$USB_ENTRY" ]; then
|
|
||||||
CURRENT_ORDER=$(efibootmgr | grep BootOrder | sed 's/BootOrder: //')
|
|
||||||
OTHER_ENTRIES=$(echo "$CURRENT_ORDER" | tr ',' '\n' | grep -v "$USB_ENTRY" | tr '\n' ',' | sed 's/,$//')
|
|
||||||
if [ -n "$OTHER_ENTRIES" ]; then
|
|
||||||
efibootmgr -o "$USB_ENTRY,$OTHER_ENTRIES"
|
|
||||||
else
|
|
||||||
efibootmgr -o "$USB_ENTRY"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Sign unsigned kernel modules for Secure Boot
|
# Sign unsigned kernel modules for Secure Boot
|
||||||
SIGN_FILE="$(ls -1 /media/startos/next/usr/lib/linux-kbuild-*/scripts/sign-file 2>/dev/null | head -1)"
|
SIGN_FILE="$(ls -1 /media/startos/next/usr/lib/linux-kbuild-*/scripts/sign-file 2>/dev/null | head -1)"
|
||||||
/media/startos/next/usr/lib/startos/scripts/sign-unsigned-modules \
|
/media/startos/next/usr/lib/startos/scripts/sign-unsigned-modules \
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ use serde::de::DeserializeOwned;
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::MAIN_DATA;
|
use crate::MAIN_DATA;
|
||||||
use crate::disk::OsPartitionInfo;
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::util::serde::IoFormat;
|
use crate::util::serde::IoFormat;
|
||||||
use crate::version::VersionT;
|
use crate::version::VersionT;
|
||||||
@@ -120,8 +119,6 @@ impl ClientConfig {
|
|||||||
pub struct ServerConfig {
|
pub struct ServerConfig {
|
||||||
#[arg(short, long, help = "help.arg.config-file-path")]
|
#[arg(short, long, help = "help.arg.config-file-path")]
|
||||||
pub config: Option<PathBuf>,
|
pub config: Option<PathBuf>,
|
||||||
#[arg(skip)]
|
|
||||||
pub os_partitions: Option<OsPartitionInfo>,
|
|
||||||
#[arg(long, help = "help.arg.socks-listen-address")]
|
#[arg(long, help = "help.arg.socks-listen-address")]
|
||||||
pub socks_listen: Option<SocketAddr>,
|
pub socks_listen: Option<SocketAddr>,
|
||||||
#[arg(long, help = "help.arg.revision-cache-size")]
|
#[arg(long, help = "help.arg.revision-cache-size")]
|
||||||
@@ -138,7 +135,6 @@ impl ContextConfig for ServerConfig {
|
|||||||
self.config.take()
|
self.config.take()
|
||||||
}
|
}
|
||||||
fn merge_with(&mut self, other: Self) {
|
fn merge_with(&mut self, other: Self) {
|
||||||
self.os_partitions = self.os_partitions.take().or(other.os_partitions);
|
|
||||||
self.socks_listen = self.socks_listen.take().or(other.socks_listen);
|
self.socks_listen = self.socks_listen.take().or(other.socks_listen);
|
||||||
self.revision_cache_size = self
|
self.revision_cache_size = self
|
||||||
.revision_cache_size
|
.revision_cache_size
|
||||||
|
|||||||
@@ -327,12 +327,7 @@ impl RpcContext {
|
|||||||
|
|
||||||
let seed = Arc::new(RpcContextSeed {
|
let seed = Arc::new(RpcContextSeed {
|
||||||
is_closed: AtomicBool::new(false),
|
is_closed: AtomicBool::new(false),
|
||||||
os_partitions: config.os_partitions.clone().ok_or_else(|| {
|
os_partitions: OsPartitionInfo::from_fstab().await?,
|
||||||
Error::new(
|
|
||||||
eyre!("{}", t!("context.rpc.os-partition-info-missing")),
|
|
||||||
ErrorKind::Filesystem,
|
|
||||||
)
|
|
||||||
})?,
|
|
||||||
wifi_interface: wifi_interface.clone(),
|
wifi_interface: wifi_interface.clone(),
|
||||||
ethernet_interface: find_eth_iface().await?,
|
ethernet_interface: find_eth_iface().await?,
|
||||||
disk_guid,
|
disk_guid,
|
||||||
|
|||||||
@@ -1,13 +1,17 @@
|
|||||||
|
use std::collections::BTreeMap;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use lazy_format::lazy_format;
|
use lazy_format::lazy_format;
|
||||||
use rpc_toolkit::{CallRemoteHandler, Context, Empty, HandlerExt, ParentHandler, from_fn_async};
|
use rpc_toolkit::{CallRemoteHandler, Context, Empty, HandlerExt, ParentHandler, from_fn_async};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use tokio::process::Command;
|
||||||
|
|
||||||
use crate::Error;
|
use crate::{Error, ErrorKind};
|
||||||
use crate::context::{CliContext, RpcContext};
|
use crate::context::{CliContext, RpcContext};
|
||||||
use crate::disk::util::DiskInfo;
|
use crate::disk::util::DiskInfo;
|
||||||
|
use crate::prelude::*;
|
||||||
|
use crate::util::Invoke;
|
||||||
use crate::util::serde::{HandlerExtSerde, WithIoFormat, display_serializable};
|
use crate::util::serde::{HandlerExtSerde, WithIoFormat, display_serializable};
|
||||||
|
|
||||||
pub mod fsck;
|
pub mod fsck;
|
||||||
@@ -21,27 +25,143 @@ pub const REPAIR_DISK_PATH: &str = "/media/startos/config/repair-disk";
|
|||||||
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
|
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct OsPartitionInfo {
|
pub struct OsPartitionInfo {
|
||||||
pub efi: Option<PathBuf>,
|
|
||||||
pub bios: Option<PathBuf>,
|
pub bios: Option<PathBuf>,
|
||||||
pub boot: PathBuf,
|
pub boot: PathBuf,
|
||||||
pub root: PathBuf,
|
pub root: PathBuf,
|
||||||
#[serde(skip)] // internal use only
|
#[serde(default)]
|
||||||
|
pub extra_boot: BTreeMap<String, PathBuf>,
|
||||||
|
#[serde(skip)]
|
||||||
pub data: Option<PathBuf>,
|
pub data: Option<PathBuf>,
|
||||||
}
|
}
|
||||||
impl OsPartitionInfo {
|
impl OsPartitionInfo {
|
||||||
pub fn contains(&self, logicalname: impl AsRef<Path>) -> bool {
|
pub fn contains(&self, logicalname: impl AsRef<Path>) -> bool {
|
||||||
self.efi
|
let p = logicalname.as_ref();
|
||||||
.as_ref()
|
self.bios.as_deref() == Some(p)
|
||||||
.map(|p| p == logicalname.as_ref())
|
|| p == &*self.boot
|
||||||
.unwrap_or(false)
|
|| p == &*self.root
|
||||||
|| self
|
|| self.extra_boot.values().any(|v| v == p)
|
||||||
.bios
|
|
||||||
.as_ref()
|
|
||||||
.map(|p| p == logicalname.as_ref())
|
|
||||||
.unwrap_or(false)
|
|
||||||
|| &*self.boot == logicalname.as_ref()
|
|
||||||
|| &*self.root == logicalname.as_ref()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Build partition info by parsing /etc/fstab and resolving device specs,
|
||||||
|
/// then discovering the BIOS boot partition (which is never mounted).
|
||||||
|
pub async fn from_fstab() -> Result<Self, Error> {
|
||||||
|
let fstab = tokio::fs::read_to_string("/etc/fstab")
|
||||||
|
.await
|
||||||
|
.with_ctx(|_| (ErrorKind::Filesystem, "/etc/fstab"))?;
|
||||||
|
|
||||||
|
let mut boot = None;
|
||||||
|
let mut root = None;
|
||||||
|
let mut extra_boot = BTreeMap::new();
|
||||||
|
|
||||||
|
for line in fstab.lines() {
|
||||||
|
let line = line.trim();
|
||||||
|
if line.is_empty() || line.starts_with('#') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let mut fields = line.split_whitespace();
|
||||||
|
let Some(source) = fields.next() else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
let Some(target) = fields.next() else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
let dev = match resolve_fstab_source(source).await {
|
||||||
|
Ok(d) => d,
|
||||||
|
Err(e) => {
|
||||||
|
tracing::warn!("Failed to resolve fstab source {source}: {e}");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
match target {
|
||||||
|
"/" => root = Some(dev),
|
||||||
|
"/boot" => boot = Some(dev),
|
||||||
|
t if t.starts_with("/boot/") => {
|
||||||
|
if let Some(name) = t.strip_prefix("/boot/") {
|
||||||
|
extra_boot.insert(name.to_string(), dev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let boot = boot.unwrap_or_default();
|
||||||
|
let bios = if !boot.as_os_str().is_empty() {
|
||||||
|
find_bios_boot_partition(&boot).await.ok().flatten()
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
bios,
|
||||||
|
boot,
|
||||||
|
root: root.unwrap_or_default(),
|
||||||
|
extra_boot,
|
||||||
|
data: None,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const BIOS_BOOT_TYPE_GUID: &str = "21686148-6449-6e6f-744e-656564726548";
|
||||||
|
|
||||||
|
/// Find the BIOS boot partition on the same disk as `known_part`.
|
||||||
|
async fn find_bios_boot_partition(known_part: &Path) -> Result<Option<PathBuf>, Error> {
|
||||||
|
let output = Command::new("lsblk")
|
||||||
|
.args(["-n", "-l", "-o", "NAME,PKNAME,PARTTYPE"])
|
||||||
|
.arg(known_part)
|
||||||
|
.invoke(ErrorKind::DiskManagement)
|
||||||
|
.await?;
|
||||||
|
let text = String::from_utf8(output)?;
|
||||||
|
|
||||||
|
let parent_disk = text.lines().find_map(|line| {
|
||||||
|
let mut fields = line.split_whitespace();
|
||||||
|
let _name = fields.next()?;
|
||||||
|
let pkname = fields.next()?;
|
||||||
|
(!pkname.is_empty()).then(|| pkname.to_string())
|
||||||
|
});
|
||||||
|
|
||||||
|
let Some(parent_disk) = parent_disk else {
|
||||||
|
return Ok(None);
|
||||||
|
};
|
||||||
|
|
||||||
|
let output = Command::new("lsblk")
|
||||||
|
.args(["-n", "-l", "-o", "NAME,PARTTYPE"])
|
||||||
|
.arg(format!("/dev/{parent_disk}"))
|
||||||
|
.invoke(ErrorKind::DiskManagement)
|
||||||
|
.await?;
|
||||||
|
let text = String::from_utf8(output)?;
|
||||||
|
|
||||||
|
for line in text.lines() {
|
||||||
|
let mut fields = line.split_whitespace();
|
||||||
|
let Some(name) = fields.next() else { continue };
|
||||||
|
let Some(parttype) = fields.next() else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
if parttype.eq_ignore_ascii_case(BIOS_BOOT_TYPE_GUID) {
|
||||||
|
return Ok(Some(PathBuf::from(format!("/dev/{name}"))));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Resolve an fstab device spec (e.g. /dev/sda1, PARTUUID=..., UUID=...) to a
|
||||||
|
/// canonical device path.
|
||||||
|
async fn resolve_fstab_source(source: &str) -> Result<PathBuf, Error> {
|
||||||
|
if source.starts_with('/') {
|
||||||
|
return Ok(
|
||||||
|
tokio::fs::canonicalize(source)
|
||||||
|
.await
|
||||||
|
.unwrap_or_else(|_| PathBuf::from(source)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// PARTUUID=, UUID=, LABEL= — resolve via blkid
|
||||||
|
let output = Command::new("blkid")
|
||||||
|
.args(["-o", "device", "-t", source])
|
||||||
|
.invoke(ErrorKind::DiskManagement)
|
||||||
|
.await?;
|
||||||
|
Ok(PathBuf::from(String::from_utf8(output)?.trim()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn disk<C: Context>() -> ParentHandler<C> {
|
pub fn disk<C: Context>() -> ParentHandler<C> {
|
||||||
|
|||||||
@@ -197,11 +197,19 @@ pub async fn partition(
|
|||||||
.invoke(crate::ErrorKind::DiskManagement)
|
.invoke(crate::ErrorKind::DiskManagement)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
let mut extra_boot = std::collections::BTreeMap::new();
|
||||||
|
let bios;
|
||||||
|
if efi {
|
||||||
|
extra_boot.insert("efi".to_string(), partition_for(&disk_path, 1));
|
||||||
|
bios = None;
|
||||||
|
} else {
|
||||||
|
bios = Some(partition_for(&disk_path, 1));
|
||||||
|
}
|
||||||
Ok(OsPartitionInfo {
|
Ok(OsPartitionInfo {
|
||||||
efi: efi.then(|| partition_for(&disk_path, 1)),
|
bios,
|
||||||
bios: (!efi).then(|| partition_for(&disk_path, 1)),
|
|
||||||
boot: partition_for(&disk_path, 2),
|
boot: partition_for(&disk_path, 2),
|
||||||
root: partition_for(&disk_path, 3),
|
root: partition_for(&disk_path, 3),
|
||||||
|
extra_boot,
|
||||||
data: data_part,
|
data: data_part,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -164,10 +164,10 @@ pub async fn partition(
|
|||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
Ok(OsPartitionInfo {
|
Ok(OsPartitionInfo {
|
||||||
efi: None,
|
|
||||||
bios: None,
|
bios: None,
|
||||||
boot: partition_for(&disk_path, 1),
|
boot: partition_for(&disk_path, 1),
|
||||||
root: partition_for(&disk_path, 2),
|
root: partition_for(&disk_path, 2),
|
||||||
|
extra_boot: Default::default(),
|
||||||
data: data_part,
|
data: data_part,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,53 +27,6 @@ use crate::util::serde::IoFormat;
|
|||||||
mod gpt;
|
mod gpt;
|
||||||
mod mbr;
|
mod mbr;
|
||||||
|
|
||||||
/// Get the EFI BootCurrent entry number (the entry firmware used to boot).
|
|
||||||
/// Returns None on non-EFI systems or if BootCurrent is not set.
|
|
||||||
async fn get_efi_boot_current() -> Result<Option<String>, Error> {
|
|
||||||
let efi_output = String::from_utf8(Command::new("efibootmgr").invoke(ErrorKind::Grub).await?)?;
|
|
||||||
|
|
||||||
Ok(efi_output
|
|
||||||
.lines()
|
|
||||||
.find(|line| line.starts_with("BootCurrent:"))
|
|
||||||
.and_then(|line| line.strip_prefix("BootCurrent:"))
|
|
||||||
.map(|s| s.trim().to_string()))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Promote a specific boot entry to first in the EFI boot order.
|
|
||||||
async fn promote_efi_entry(entry: &str) -> Result<(), Error> {
|
|
||||||
let efi_output = String::from_utf8(Command::new("efibootmgr").invoke(ErrorKind::Grub).await?)?;
|
|
||||||
|
|
||||||
let current_order = efi_output
|
|
||||||
.lines()
|
|
||||||
.find(|line| line.starts_with("BootOrder:"))
|
|
||||||
.and_then(|line| line.strip_prefix("BootOrder:"))
|
|
||||||
.map(|s| s.trim())
|
|
||||||
.unwrap_or("");
|
|
||||||
|
|
||||||
if current_order.is_empty() || current_order.starts_with(entry) {
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
let other_entries: Vec<&str> = current_order
|
|
||||||
.split(',')
|
|
||||||
.filter(|e| e.trim() != entry)
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let new_order = if other_entries.is_empty() {
|
|
||||||
entry.to_string()
|
|
||||||
} else {
|
|
||||||
format!("{},{}", entry, other_entries.join(","))
|
|
||||||
};
|
|
||||||
|
|
||||||
Command::new("efibootmgr")
|
|
||||||
.arg("-o")
|
|
||||||
.arg(&new_order)
|
|
||||||
.invoke(ErrorKind::Grub)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Probe a squashfs image to determine its target architecture
|
/// Probe a squashfs image to determine its target architecture
|
||||||
async fn probe_squashfs_arch(squashfs_path: &Path) -> Result<InternedString, Error> {
|
async fn probe_squashfs_arch(squashfs_path: &Path) -> Result<InternedString, Error> {
|
||||||
let output = String::from_utf8(
|
let output = String::from_utf8(
|
||||||
@@ -190,7 +143,7 @@ pub async fn install_os_to(
|
|||||||
|
|
||||||
let part_info = partition(disk_path, capacity, partition_table, protect, use_efi).await?;
|
let part_info = partition(disk_path, capacity, partition_table, protect, use_efi).await?;
|
||||||
|
|
||||||
if let Some(efi) = &part_info.efi {
|
if let Some(efi) = part_info.extra_boot.get("efi") {
|
||||||
Command::new("mkfs.vfat")
|
Command::new("mkfs.vfat")
|
||||||
.arg(efi)
|
.arg(efi)
|
||||||
.invoke(crate::ErrorKind::DiskManagement)
|
.invoke(crate::ErrorKind::DiskManagement)
|
||||||
@@ -307,10 +260,7 @@ pub async fn install_os_to(
|
|||||||
|
|
||||||
tokio::fs::write(
|
tokio::fs::write(
|
||||||
rootfs.path().join("config/config.yaml"),
|
rootfs.path().join("config/config.yaml"),
|
||||||
IoFormat::Yaml.to_vec(&ServerConfig {
|
IoFormat::Yaml.to_vec(&ServerConfig::default())?,
|
||||||
os_partitions: Some(part_info.clone()),
|
|
||||||
..Default::default()
|
|
||||||
})?,
|
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
@@ -329,7 +279,7 @@ pub async fn install_os_to(
|
|||||||
ReadWrite,
|
ReadWrite,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
let efi = if let Some(efi) = &part_info.efi {
|
let efi = if let Some(efi) = part_info.extra_boot.get("efi") {
|
||||||
Some(
|
Some(
|
||||||
MountGuard::mount(
|
MountGuard::mount(
|
||||||
&BlockDev::new(efi),
|
&BlockDev::new(efi),
|
||||||
@@ -370,8 +320,8 @@ pub async fn install_os_to(
|
|||||||
include_str!("fstab.template"),
|
include_str!("fstab.template"),
|
||||||
boot = part_info.boot.display(),
|
boot = part_info.boot.display(),
|
||||||
efi = part_info
|
efi = part_info
|
||||||
.efi
|
.extra_boot
|
||||||
.as_ref()
|
.get("efi")
|
||||||
.map(|p| p.display().to_string())
|
.map(|p| p.display().to_string())
|
||||||
.unwrap_or_else(|| "# N/A".to_owned()),
|
.unwrap_or_else(|| "# N/A".to_owned()),
|
||||||
root = part_info.root.display(),
|
root = part_info.root.display(),
|
||||||
@@ -502,20 +452,6 @@ pub async fn install_os(
|
|||||||
|
|
||||||
let use_efi = tokio::fs::metadata("/sys/firmware/efi").await.is_ok();
|
let use_efi = tokio::fs::metadata("/sys/firmware/efi").await.is_ok();
|
||||||
|
|
||||||
// Save the boot entry we booted from (the USB installer) before grub-install
|
|
||||||
// overwrites the boot order.
|
|
||||||
let boot_current = if use_efi {
|
|
||||||
match get_efi_boot_current().await {
|
|
||||||
Ok(entry) => entry,
|
|
||||||
Err(e) => {
|
|
||||||
tracing::warn!("Failed to get EFI BootCurrent: {e}");
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
let InstallOsResult {
|
let InstallOsResult {
|
||||||
part_info,
|
part_info,
|
||||||
rootfs,
|
rootfs,
|
||||||
@@ -531,23 +467,6 @@ pub async fn install_os(
|
|||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
// grub-install prepends its new entry to the EFI boot order, overriding the
|
|
||||||
// USB-first priority. Promote the USB entry (identified by BootCurrent from
|
|
||||||
// when we booted the installer) back to first, and persist the entry number
|
|
||||||
// so the upgrade script can do the same.
|
|
||||||
if let Some(ref entry) = boot_current {
|
|
||||||
if let Err(e) = promote_efi_entry(entry).await {
|
|
||||||
tracing::warn!("Failed to restore EFI boot order: {e}");
|
|
||||||
}
|
|
||||||
let efi_entry_path = rootfs.path().join("config/efi-installer-entry");
|
|
||||||
if let Err(e) = tokio::fs::write(&efi_entry_path, entry).await {
|
|
||||||
tracing::warn!("Failed to save EFI installer entry number: {e}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx.config
|
|
||||||
.mutate(|c| c.os_partitions = Some(part_info.clone()));
|
|
||||||
|
|
||||||
let mut setup_info = SetupInfo::default();
|
let mut setup_info = SetupInfo::default();
|
||||||
setup_info.mok_enrolled = mok_enrolled;
|
setup_info.mok_enrolled = mok_enrolled;
|
||||||
|
|
||||||
|
|||||||
@@ -95,8 +95,8 @@ const LIVE_MEDIUM_PATH: &str = "/run/live/medium";
|
|||||||
|
|
||||||
pub async fn list_disks(ctx: SetupContext) -> Result<Vec<DiskInfo>, Error> {
|
pub async fn list_disks(ctx: SetupContext) -> Result<Vec<DiskInfo>, Error> {
|
||||||
let mut disks = crate::disk::util::list(
|
let mut disks = crate::disk::util::list(
|
||||||
&ctx.config
|
&crate::disk::OsPartitionInfo::from_fstab()
|
||||||
.peek(|c| c.os_partitions.clone())
|
.await
|
||||||
.unwrap_or_default(),
|
.unwrap_or_default(),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|||||||
Reference in New Issue
Block a user