Skip to content

Commit edefd33

Browse files
cfs: Use bootupd for all installs if available
Check if we have a new enough version of bootupd (by checking if the binary provides a `--bootloader` flag). If we have a new enough bootupd, use it to install grub-cc and systemd-boot We do not have this version of bootupd as an rpm package, so this will not break any existing systems. This is mostly for reverse dep testing in bootupd as testing this for bootc requires packaging bootupd, updating grub-cc and systemd-boot rpms to install their respective EFI binaries in the correct place which they don't right now Signed-off-by: Pragyan Poudyal <pragyanpoudyal41999@gmail.com>
1 parent 1773424 commit edefd33

3 files changed

Lines changed: 66 additions & 18 deletions

File tree

crates/lib/src/bootc_composefs/boot.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ use serde::{Deserialize, Serialize};
9696
use crate::bootc_composefs::state::{get_booted_bls, write_composefs_state};
9797
use crate::bootc_composefs::status::ComposefsCmdline;
9898
use crate::bootc_kargs::compute_new_kargs;
99+
use crate::bootloader::bootupd_supports_bootloader_flag;
99100
use crate::composefs_consts::{TYPE1_BOOT_DIR_PREFIX, TYPE1_ENT_PATH, TYPE1_ENT_PATH_STAGED};
100101
use crate::parsers::bls_config::{BLSConfig, BLSConfigType, EFIKey};
101102
use crate::spec::BootloaderKind;
@@ -1388,6 +1389,16 @@ pub(crate) async fn setup_composefs_boot(
13881389
&root_setup.device_info.require_single_root()?,
13891390
boot_uuid,
13901391
)?;
1392+
} else if bootupd_supports_bootloader_flag(&root_setup.physical_root_path, None)
1393+
.is_ok_and(|v| v)
1394+
{
1395+
crate::bootloader::install_via_bootupd(
1396+
&root_setup.device_info,
1397+
&root_setup.physical_root_path,
1398+
&state.config_opts,
1399+
None,
1400+
Some(postfetch.detected_bootloader),
1401+
)?;
13911402
} else if matches!(
13921403
postfetch.detected_bootloader,
13931404
Bootloader::Grub | Bootloader::GrubCC
@@ -1397,6 +1408,7 @@ pub(crate) async fn setup_composefs_boot(
13971408
&root_setup.physical_root_path,
13981409
&state.config_opts,
13991410
None,
1411+
None,
14001412
)?;
14011413

14021414
// FIXME: Remove this hack once we have support in bootupd

crates/lib/src/bootloader.rs

Lines changed: 53 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use fn_error_context::context;
1212
use bootc_mount as mount;
1313

1414
use crate::bootc_composefs::boot::{MountedImageRoot, SecurebootKeys};
15+
use crate::spec::Bootloader;
1516
use crate::utils;
1617

1718
/// The name of the mountpoint for efi (as a subdirectory of /boot, or at the toplevel)
@@ -95,13 +96,11 @@ pub(crate) fn supports_bootupd(root: &Dir) -> Result<bool> {
9596
Ok(r)
9697
}
9798

98-
/// Check whether the target bootupd supports `--filesystem`.
99-
///
100-
/// Runs `bootupctl backend install --help` and looks for `--filesystem` in the
101-
/// output. When `deployment_path` is set the command runs inside a chroot
102-
/// (via [`ChrootCmd`]) so we probe the binary from the target image.
103-
fn bootupd_supports_filesystem(rootfs: &Utf8Path, deployment_path: Option<&str>) -> Result<bool> {
99+
fn bootupd_install_help(rootfs: &Utf8Path, deployment_path: Option<&str>) -> Result<String> {
100+
static STATUS: std::sync::OnceLock<String> = std::sync::OnceLock::new();
101+
104102
let help_args = ["bootupctl", "backend", "install", "--help"];
103+
105104
let output = if let Some(deploy) = deployment_path {
106105
let target_root = rootfs.join(deploy);
107106
ChrootCmd::new(&target_root)
@@ -114,6 +113,17 @@ fn bootupd_supports_filesystem(rootfs: &Utf8Path, deployment_path: Option<&str>)
114113
.run_get_string()?
115114
};
116115

116+
Ok(STATUS.get_or_init(|| output).to_string())
117+
}
118+
119+
/// Check whether the target bootupd supports `--filesystem`.
120+
///
121+
/// Runs `bootupctl backend install --help` and looks for `--filesystem` in the
122+
/// output. When `deployment_path` is set the command runs inside a chroot
123+
/// (via [`ChrootCmd`]) so we probe the binary from the target image.
124+
fn bootupd_supports_filesystem(rootfs: &Utf8Path, deployment_path: Option<&str>) -> Result<bool> {
125+
let output = bootupd_install_help(rootfs, deployment_path)?;
126+
117127
let use_filesystem = output.contains("--filesystem");
118128

119129
if use_filesystem {
@@ -125,6 +135,24 @@ fn bootupd_supports_filesystem(rootfs: &Utf8Path, deployment_path: Option<&str>)
125135
Ok(use_filesystem)
126136
}
127137

138+
/// Check whether the target bootupd supports `--bootloader` for installs
139+
pub(crate) fn bootupd_supports_bootloader_flag(
140+
rootfs: &Utf8Path,
141+
deployment_path: Option<&str>,
142+
) -> Result<bool> {
143+
let output = bootupd_install_help(rootfs, deployment_path)?;
144+
145+
let supports_bootloader = output.contains("--bootloader");
146+
147+
if supports_bootloader {
148+
tracing::debug!("bootupd supports --bootloader");
149+
} else {
150+
tracing::debug!("bootupd does not support --bootloader");
151+
}
152+
153+
Ok(supports_bootloader)
154+
}
155+
128156
/// Install the bootloader via bootupd.
129157
///
130158
/// When the target bootupd supports `--filesystem` we pass it pointing at a
@@ -140,10 +168,12 @@ pub(crate) fn install_via_bootupd(
140168
rootfs: &Utf8Path,
141169
configopts: &crate::install::InstallConfigOpts,
142170
deployment_path: Option<&str>,
171+
bootloader: Option<Bootloader>,
143172
) -> Result<()> {
144173
let verbose = std::env::var_os("BOOTC_BOOTLOADER_DEBUG").map(|_| "-vvvv");
145174
// bootc defaults to only targeting the platform boot method.
146-
let bootupd_opts = (!configopts.generic_image).then_some(["--update-firmware", "--auto"]);
175+
let bootupd_opts = (!configopts.generic_image)
176+
.then_some(["--update-firmware", "--auto"].map(|x| x.to_string()));
147177

148178
// When not running inside the target container (through `--src-imgref`) we
149179
// run bootupctl from the deployment via a chroot ([`ChrootCmd`]).
@@ -159,20 +189,25 @@ pub(crate) fn install_via_bootupd(
159189
println!("Installing bootloader via bootupd");
160190

161191
// Build the bootupctl arguments
162-
let mut bootupd_args: Vec<&str> = vec!["backend", "install"];
192+
let mut bootupd_args: Vec<String> = vec!["backend".into(), "install".into()];
163193
if configopts.bootupd_skip_boot_uuid {
164-
bootupd_args.push("--with-static-configs")
194+
bootupd_args.push("--with-static-configs".into())
165195
} else {
166-
bootupd_args.push("--write-uuid");
196+
bootupd_args.push("--write-uuid".into());
167197
}
168198
if let Some(v) = verbose {
169-
bootupd_args.push(v);
199+
bootupd_args.push(v.into());
170200
}
171201

172-
if let Some(ref opts) = bootupd_opts {
173-
bootupd_args.extend(opts.iter().copied());
202+
if let Some(opts) = bootupd_opts {
203+
bootupd_args.extend(opts);
174204
}
175205

206+
if let Some(b) = bootloader {
207+
bootupd_args.push("--bootloader".into());
208+
bootupd_args.push(b.to_string());
209+
};
210+
176211
// When the target bootupd lacks --filesystem support, fall back to the
177212
// legacy --device flag. For --device we need the whole-disk device path
178213
// (e.g. /dev/vda), not a partition (e.g. /dev/vda3), so resolve the
@@ -188,12 +223,12 @@ pub(crate) fn install_via_bootupd(
188223
};
189224
if let Some(ref dev) = root_device_path {
190225
tracing::debug!("bootupd does not support --filesystem, falling back to --device {dev}");
191-
bootupd_args.extend(["--device", dev]);
192-
bootupd_args.push(rootfs_mount);
226+
bootupd_args.extend(["--device".into(), dev.into()]);
227+
bootupd_args.push(rootfs_mount.into());
193228
} else {
194229
tracing::debug!("bootupd supports --filesystem");
195-
bootupd_args.extend(["--filesystem", rootfs_mount]);
196-
bootupd_args.push(rootfs_mount);
230+
bootupd_args.extend(["--filesystem".into(), rootfs_mount.into()]);
231+
bootupd_args.push(rootfs_mount.into());
197232
}
198233

199234
// Run inside a chroot ([`ChrootCmd`]). It sets up a fresh mount
@@ -209,7 +244,7 @@ pub(crate) fn install_via_bootupd(
209244

210245
// Prepend "bootupctl" to the args (ChrootCmd's calling
211246
// convention puts the program in args[0]).
212-
let mut chroot_args = vec!["bootupctl"];
247+
let mut chroot_args = vec!["bootupctl".to_string()];
213248
chroot_args.extend(bootupd_args);
214249

215250
let mut cmd = ChrootCmd::new(&target_root)

crates/lib/src/install.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1876,6 +1876,7 @@ async fn install_with_sysroot(
18761876
.unwrap_or(rootfs.physical_root_path.clone()),
18771877
&state.config_opts,
18781878
Some(&deployment_path.as_str()),
1879+
None,
18791880
)?;
18801881
}
18811882
Bootloader::Systemd | Bootloader::GrubCC => {

0 commit comments

Comments
 (0)