Skip to content

Commit 5d11404

Browse files
martinezjavierckyrouac
authored andcommitted
install: Add a Bootloader::None option
Currently, the bootc install workflow assumes that the bootloader must be managed by bootupd. This works well for server and edge environments, but it is too inflexible for embedded or custom platforms where the bootloader is managed externally (e.g., aboot for automotive use cases). In these scenarios, users want to install the filesystem content (OSTree commit, kernel, initramfs, etc), without bootc assuming that a boot or ESP partition exists that have to be setup or udpated by bootupd. By adding a --bootloader=none option users can have explicit control over how the boot loading is handled, without bootc or bootupd intervention. Note that so far only support for the ostree backend has been added and the bootloader=none option is not supported by the composefs backend. Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
1 parent 8a90c4b commit 5d11404

12 files changed

Lines changed: 46 additions & 0 deletions

File tree

crates/lib/src/bootc_composefs/boot.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -622,6 +622,8 @@ pub(crate) fn setup_composefs_bls_boot(
622622
Some(efi_mount),
623623
)
624624
}
625+
626+
Bootloader::None => unreachable!("Checked at install time"),
625627
};
626628

627629
let (bls_config, boot_digest, os_id) = match &entry {
@@ -851,6 +853,7 @@ fn write_pe_to_esp(
851853
let efi_linux_path = mounted_efi.as_ref().join(match bootloader {
852854
Bootloader::Grub => EFI_LINUX,
853855
Bootloader::Systemd => SYSTEMD_UKI_DIR,
856+
Bootloader::None => unreachable!("Checked at install time"),
854857
});
855858

856859
create_dir_all(&efi_linux_path).context("Creating EFI/Linux")?;
@@ -1163,6 +1166,8 @@ pub(crate) fn setup_composefs_uki_boot(
11631166
}
11641167

11651168
Bootloader::Systemd => write_systemd_uki_config(&esp_mount.fd, &setup_type, uki_info, id)?,
1169+
1170+
Bootloader::None => unreachable!("Checked at install time"),
11661171
};
11671172

11681173
Ok(boot_digest)

crates/lib/src/bootc_composefs/delete.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,8 @@ fn delete_depl_boot_entries(
241241
// For Systemd UKI as well, we use .conf files
242242
delete_type1_entry(deployment, boot_dir, deleting_staged)
243243
}
244+
245+
Bootloader::None => unreachable!("Checked at install time"),
244246
}
245247
}
246248

crates/lib/src/bootc_composefs/finalize.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,8 @@ pub(crate) async fn composefs_backend_finalize(
120120
let entries_dir = boot_dir.open_dir("loader")?;
121121
rename_exchange_bls_entries(&entries_dir)?;
122122
}
123+
124+
Bootloader::None => unreachable!("Checked at install time"),
123125
};
124126

125127
Ok(())

crates/lib/src/bootc_composefs/gc.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ fn list_bootloader_entries(storage: &Storage) -> Result<Vec<String>> {
8080
.map(|entry| entry.get_verity())
8181
.collect::<Result<Vec<_>, _>>()?
8282
}
83+
84+
Bootloader::None => unreachable!("Checked at install time"),
8385
};
8486

8587
Ok(entries)

crates/lib/src/bootc_composefs/rollback.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,8 @@ pub(crate) async fn composefs_rollback(
233233
// We use BLS entries for systemd UKI as well
234234
rollback_composefs_entries(boot_dir, rollback_entry.bootloader.clone())?;
235235
}
236+
237+
Bootloader::None => unreachable!("Checked at install time"),
236238
}
237239

238240
if reverting {

crates/lib/src/bootc_composefs/status.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -751,6 +751,8 @@ pub(crate) async fn composefs_deployment_status_from(
751751

752752
(is_rollback_queued, Some(bls_configs), None)
753753
}
754+
755+
Bootloader::None => unreachable!("Checked at install time"),
754756
};
755757

756758
// Determine rollback deployment by matching extra deployment boot entries against entires read from /boot

crates/lib/src/bootc_composefs/update.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,8 @@ pub(crate) fn validate_update(
189189
},
190190

191191
Bootloader::Systemd => rm_staged_type1_ent(boot_dir)?,
192+
193+
Bootloader::None => unreachable!("Checked at install time"),
192194
}
193195

194196
// Remove state directory

crates/lib/src/install.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1590,6 +1590,12 @@ async fn prepare_install(
15901590
composefs_options.composefs_backend = true;
15911591
}
15921592

1593+
if composefs_options.composefs_backend
1594+
&& matches!(config_opts.bootloader, Some(Bootloader::None))
1595+
{
1596+
anyhow::bail!("Bootloader set to none is not supported with the composefs backend");
1597+
}
1598+
15931599
// We need to access devices that are set up by the host udev
15941600
bootc_mount::ensure_mirrored_host_mount("/dev")?;
15951601
// We need to read our own container image (and any logically bound images)
@@ -1646,6 +1652,12 @@ async fn prepare_install(
16461652
tracing::debug!("No install configuration found");
16471653
}
16481654

1655+
if let Some(crate::spec::Bootloader::None) = config_opts.bootloader {
1656+
if cfg!(target_arch = "s390x") {
1657+
anyhow::bail!("Bootloader set to none is not supported for the s390x architecture");
1658+
}
1659+
}
1660+
16491661
// Convert the keyfile to a hashmap because GKeyFile isnt Send for probably bad reasons.
16501662
let prepareroot_config = {
16511663
let kf = ostree_prepareroot::require_config_from_root(&rootfs)?;
@@ -1761,6 +1773,9 @@ async fn install_with_sysroot(
17611773
Bootloader::Systemd => {
17621774
anyhow::bail!("bootupd is required for ostree-based installs");
17631775
}
1776+
Bootloader::None => {
1777+
tracing::debug!("Skip bootloader installation due set to None");
1778+
}
17641779
}
17651780
}
17661781
tracing::debug!("Installed bootloader");

crates/lib/src/spec.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,13 +191,16 @@ pub enum Bootloader {
191191
Grub,
192192
/// Use SystemdBoot as the bootloader
193193
Systemd,
194+
/// Don't use a bootloader managed by bootc
195+
None,
194196
}
195197

196198
impl Display for Bootloader {
197199
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
198200
let string = match self {
199201
Bootloader::Grub => "grub",
200202
Bootloader::Systemd => "systemd",
203+
Bootloader::None => "none",
201204
};
202205

203206
write!(f, "{}", string)
@@ -211,6 +214,7 @@ impl FromStr for Bootloader {
211214
match value {
212215
"grub" => Ok(Self::Grub),
213216
"systemd" => Ok(Self::Systemd),
217+
"none" => Ok(Self::None),
214218
unrecognized => Err(anyhow::anyhow!("Unrecognized bootloader: '{unrecognized}'")),
215219
}
216220
}

crates/lib/src/store/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ impl BootedStorage {
205205
Bootloader::Grub => physical_root.open_dir("boot").context("Opening boot")?,
206206
// NOTE: Handle XBOOTLDR partitions here if and when we use it
207207
Bootloader::Systemd => esp_mount.fd.try_clone().context("Cloning fd")?,
208+
Bootloader::None => unreachable!("Checked at install time"),
208209
};
209210

210211
let storage = Storage {

0 commit comments

Comments
 (0)