From 800568a2236e0c8fb5145ced292bd1227a75c8a8 Mon Sep 17 00:00:00 2001 From: Pragyan Poudyal Date: Wed, 12 Nov 2025 16:19:04 +0530 Subject: [PATCH 1/2] bls-config: Rename 'efi' key to 'uki' Key 'uki' is more appropriate for us as the PE Binary that the key points to is a UKI Signed-off-by: Pragyan Poudyal --- crates/lib/src/bootc_composefs/boot.rs | 8 ++--- crates/lib/src/bootc_composefs/delete.rs | 14 ++++---- crates/lib/src/bootc_composefs/state.rs | 6 ++-- crates/lib/src/bootc_composefs/status.rs | 14 ++++---- crates/lib/src/parsers/bls_config.rs | 44 ++++++++++++------------ 5 files changed, 43 insertions(+), 43 deletions(-) diff --git a/crates/lib/src/bootc_composefs/boot.rs b/crates/lib/src/bootc_composefs/boot.rs index 1196c1311..16fdc980b 100644 --- a/crates/lib/src/bootc_composefs/boot.rs +++ b/crates/lib/src/bootc_composefs/boot.rs @@ -526,7 +526,7 @@ pub(crate) fn setup_composefs_bls_boot( .with_title(title) .with_sort_key(default_sort_key.into()) .with_version(version) - .with_cfg(BLSConfigType::NonEFI { + .with_cfg(BLSConfigType::NonUKI { linux: entry_paths.abs_entries_path.join(&id_hex).join(VMLINUZ), initrd: vec![entry_paths.abs_entries_path.join(&id_hex).join(INITRD)], options: Some(cmdline_refs), @@ -564,7 +564,7 @@ pub(crate) fn setup_composefs_bls_boot( })?; match bls_config.cfg_type { - BLSConfigType::NonEFI { + BLSConfigType::NonUKI { ref mut linux, ref mut initrd, .. @@ -857,8 +857,8 @@ fn write_systemd_uki_config( let mut bls_conf = BLSConfig::default(); bls_conf .with_title(boot_label.boot_label) - .with_cfg(BLSConfigType::EFI { - efi: format!("/{SYSTEMD_UKI_DIR}/{}{}", id.to_hex(), EFI_EXT).into(), + .with_cfg(BLSConfigType::UKI { + uki: format!("/{SYSTEMD_UKI_DIR}/{}{}", id.to_hex(), EFI_EXT).into(), }) .with_sort_key(default_sort_key.into()) .with_version(boot_label.version.unwrap_or(default_sort_key.into())); diff --git a/crates/lib/src/bootc_composefs/delete.rs b/crates/lib/src/bootc_composefs/delete.rs index f1a31101c..a0dd9f96b 100644 --- a/crates/lib/src/bootc_composefs/delete.rs +++ b/crates/lib/src/bootc_composefs/delete.rs @@ -62,20 +62,20 @@ fn delete_type1_entry(depl: &DeploymentEntry, boot_dir: &Dir, deleting_staged: b let bls_config = parse_bls_config(&cfg)?; match &bls_config.cfg_type { - BLSConfigType::EFI { efi } => { - if !efi.as_str().contains(&depl.deployment.verity) { + BLSConfigType::UKI { uki } => { + if !uki.as_str().contains(&depl.deployment.verity) { continue; } // Boot dir in case of EFI will be the ESP - tracing::debug!("Deleting EFI .conf file: {}", file_name); + tracing::debug!("Deleting UKI .conf file: {}", file_name); entry.remove_file().context("Removing .conf file")?; delete_uki(&depl.deployment.verity, boot_dir)?; break; } - BLSConfigType::NonEFI { options, .. } => { + BLSConfigType::NonUKI { options, .. } => { let options = options .as_ref() .ok_or(anyhow::anyhow!("options not found in BLS config file"))?; @@ -84,7 +84,7 @@ fn delete_type1_entry(depl: &DeploymentEntry, boot_dir: &Dir, deleting_staged: b continue; } - tracing::debug!("Deleting non-EFI .conf file: {}", file_name); + tracing::debug!("Deleting non-UKI .conf file: {}", file_name); entry.remove_file().context("Removing .conf file")?; if should_del_kernel { @@ -113,8 +113,8 @@ fn delete_type1_entry(depl: &DeploymentEntry, boot_dir: &Dir, deleting_staged: b #[fn_error_context::context("Deleting kernel and initrd")] fn delete_kernel_initrd(bls_config: &BLSConfigType, boot_dir: &Dir) -> Result<()> { - let BLSConfigType::NonEFI { linux, initrd, .. } = bls_config else { - anyhow::bail!("Found EFI config") + let BLSConfigType::NonUKI { linux, initrd, .. } = bls_config else { + anyhow::bail!("Found UKI config") }; // "linux" and "initrd" are relative to the boot_dir in our config files diff --git a/crates/lib/src/bootc_composefs/state.rs b/crates/lib/src/bootc_composefs/state.rs index 723d6ed19..8491a627c 100644 --- a/crates/lib/src/bootc_composefs/state.rs +++ b/crates/lib/src/bootc_composefs/state.rs @@ -44,17 +44,17 @@ pub(crate) fn get_booted_bls(boot_dir: &Dir) -> Result { for entry in sorted_entries { match &entry.cfg_type { - BLSConfigType::EFI { efi } => { + BLSConfigType::UKI { uki } => { let composefs_param_value = booted.value().ok_or_else(|| { anyhow::anyhow!("Failed to get composefs kernel cmdline value") })?; - if efi.as_str().contains(composefs_param_value) { + if uki.as_str().contains(composefs_param_value) { return Ok(entry); } } - BLSConfigType::NonEFI { options, .. } => { + BLSConfigType::NonUKI { options, .. } => { let Some(opts) = options else { anyhow::bail!("options not found in bls config") }; diff --git a/crates/lib/src/bootc_composefs/status.rs b/crates/lib/src/bootc_composefs/status.rs index 40ec1b757..ed54e0a88 100644 --- a/crates/lib/src/bootc_composefs/status.rs +++ b/crates/lib/src/bootc_composefs/status.rs @@ -361,13 +361,13 @@ pub(crate) async fn composefs_deployment_status_from( .ok_or(anyhow::anyhow!("First boot entry not found"))?; match &bls_config.cfg_type { - BLSConfigType::NonEFI { options, .. } => !options + BLSConfigType::NonUKI { options, .. } => !options .as_ref() .ok_or(anyhow::anyhow!("options key not found in bls config"))? .contains(composefs_digest.as_ref()), - BLSConfigType::EFI { .. } => { - anyhow::bail!("Found 'efi' field in Type1 boot entry") + BLSConfigType::UKI { .. } => { + anyhow::bail!("Found 'uki' field in Type1 boot entry") } BLSConfigType::Unknown => anyhow::bail!("Unknown BLS Config Type"), } @@ -394,10 +394,10 @@ pub(crate) async fn composefs_deployment_status_from( match &bls_config.cfg_type { // For UKI boot - BLSConfigType::EFI { efi } => efi.as_str().contains(composefs_digest.as_ref()), + BLSConfigType::UKI { uki } => uki.as_str().contains(composefs_digest.as_ref()), // For boot entry Type1 - BLSConfigType::NonEFI { options, .. } => !options + BLSConfigType::NonUKI { options, .. } => !options .as_ref() .ok_or(anyhow::anyhow!("options key not found in bls config"))? .contains(composefs_digest.as_ref()), @@ -470,7 +470,7 @@ mod tests { let mut config1 = BLSConfig::default(); config1.title = Some("Fedora 42.20250623.3.1 (CoreOS)".into()); config1.sort_key = Some("1".into()); - config1.cfg_type = BLSConfigType::NonEFI { + config1.cfg_type = BLSConfigType::NonUKI { linux: "/boot/7e11ac46e3e022053e7226a20104ac656bf72d1a84e3a398b7cce70e9df188b6/vmlinuz-5.14.10".into(), initrd: vec!["/boot/7e11ac46e3e022053e7226a20104ac656bf72d1a84e3a398b7cce70e9df188b6/initramfs-5.14.10.img".into()], options: Some("root=UUID=abc123 rw composefs=7e11ac46e3e022053e7226a20104ac656bf72d1a84e3a398b7cce70e9df188b6".into()), @@ -479,7 +479,7 @@ mod tests { let mut config2 = BLSConfig::default(); config2.title = Some("Fedora 41.20250214.2.0 (CoreOS)".into()); config2.sort_key = Some("2".into()); - config2.cfg_type = BLSConfigType::NonEFI { + config2.cfg_type = BLSConfigType::NonUKI { linux: "/boot/febdf62805de2ae7b6b597f2a9775d9c8a753ba1e5f09298fc8fbe0b0d13bf01/vmlinuz-5.14.10".into(), initrd: vec!["/boot/febdf62805de2ae7b6b597f2a9775d9c8a753ba1e5f09298fc8fbe0b0d13bf01/initramfs-5.14.10.img".into()], options: Some("root=UUID=abc123 rw composefs=febdf62805de2ae7b6b597f2a9775d9c8a753ba1e5f09298fc8fbe0b0d13bf01".into()) diff --git a/crates/lib/src/parsers/bls_config.rs b/crates/lib/src/parsers/bls_config.rs index 606b990c7..275baf24e 100644 --- a/crates/lib/src/parsers/bls_config.rs +++ b/crates/lib/src/parsers/bls_config.rs @@ -17,11 +17,11 @@ use crate::composefs_consts::COMPOSEFS_CMDLINE; #[derive(Debug, PartialEq, Eq, Default)] pub enum BLSConfigType { - EFI { - /// The path to the EFI binary, usually a UKI - efi: Utf8PathBuf, + UKI { + /// The path to the UKI + uki: Utf8PathBuf, }, - NonEFI { + NonUKI { /// The path to the linux kernel to boot. linux: Utf8PathBuf, /// The paths to the initrd images. @@ -102,11 +102,11 @@ impl Display for BLSConfig { writeln!(f, "version {}", self.version)?; match &self.cfg_type { - BLSConfigType::EFI { efi } => { - writeln!(f, "efi {}", efi)?; + BLSConfigType::UKI { uki } => { + writeln!(f, "uki {}", uki)?; } - BLSConfigType::NonEFI { + BLSConfigType::NonUKI { linux, initrd, options, @@ -173,16 +173,16 @@ impl BLSConfig { pub(crate) fn get_verity(&self) -> Result { match &self.cfg_type { - BLSConfigType::EFI { efi } => Ok(efi + BLSConfigType::UKI { uki } => Ok(uki .components() .last() - .ok_or(anyhow::anyhow!("Empty efi field"))? + .ok_or(anyhow::anyhow!("Empty uki field"))? .to_string() .strip_suffix(EFI_EXT) - .ok_or(anyhow::anyhow!("efi doesn't end with .efi"))? + .ok_or_else(|| anyhow::anyhow!("uki doesn't end with .efi"))? .to_string()), - BLSConfigType::NonEFI { options, .. } => { + BLSConfigType::NonUKI { options, .. } => { let options = options.as_ref().ok_or(anyhow::anyhow!("No options"))?; let cmdline = Cmdline::from(&options); @@ -209,7 +209,7 @@ pub(crate) fn parse_bls_config(input: &str) -> Result { let mut title = None; let mut version = None; let mut linux = None; - let mut efi = None; + let mut uki = None; let mut initrd = Vec::new(); let mut options = None; let mut machine_id = None; @@ -232,7 +232,7 @@ pub(crate) fn parse_bls_config(input: &str) -> Result { "options" => options = Some(CmdlineOwned::from(value)), "machine-id" => machine_id = Some(value), "sort-key" => sort_key = Some(value), - "efi" => efi = Some(Utf8PathBuf::from(value)), + "uki" => uki = Some(Utf8PathBuf::from(value)), _ => { extra.insert(key.to_string(), value); } @@ -242,10 +242,10 @@ pub(crate) fn parse_bls_config(input: &str) -> Result { let version = version.ok_or_else(|| anyhow!("Missing 'version' value"))?; - let cfg_type = match (linux, efi) { - (None, Some(efi)) => BLSConfigType::EFI { efi }, + let cfg_type = match (linux, uki) { + (None, Some(uki)) => BLSConfigType::UKI { uki }, - (Some(linux), None) => BLSConfigType::NonEFI { + (Some(linux), None) => BLSConfigType::NonUKI { linux, initrd, options, @@ -253,8 +253,8 @@ pub(crate) fn parse_bls_config(input: &str) -> Result { // The spec makes no mention of whether both can be present or not // Fow now, for us, we won't have both at the same time - (Some(_), Some(_)) => anyhow::bail!("'linux' and 'efi' values present"), - (None, None) => anyhow::bail!("Missing 'linux' or 'efi' value"), + (Some(_), Some(_)) => anyhow::bail!("'linux' and 'uki' values present"), + (None, None) => anyhow::bail!("Missing 'linux' or 'uki' value"), }; Ok(BLSConfig { @@ -285,13 +285,13 @@ mod tests { let config = parse_bls_config(input)?; - let BLSConfigType::NonEFI { + let BLSConfigType::NonUKI { linux, initrd, options, } = config.cfg_type else { - panic!("Expected non EFI variant"); + panic!("Expected non UKI variant"); }; assert_eq!( @@ -321,8 +321,8 @@ mod tests { let config = parse_bls_config(input)?; - let BLSConfigType::NonEFI { initrd, .. } = config.cfg_type else { - panic!("Expected non EFI variant"); + let BLSConfigType::NonUKI { initrd, .. } = config.cfg_type else { + panic!("Expected non UKI variant"); }; assert_eq!( From f855d30c544ca79d461d8f85299990673adb2dfc Mon Sep 17 00:00:00 2001 From: Pragyan Poudyal Date: Tue, 18 Nov 2025 17:03:52 +0530 Subject: [PATCH 2/2] composefs/uki: Install all UKIs in EFI/Linux/bootc We were making a distinction based on the bootloader and installing UKIs in EFI/Linux for Grub and EFI/Linux/bootc for sd-boot. IMO it's better if we use the same directory for both bootloaders Signed-off-by: Pragyan Poudyal --- crates/lib/src/bootc_composefs/boot.rs | 17 +++++------------ crates/lib/src/bootc_composefs/delete.rs | 4 ++-- crates/lib/src/parsers/grub_menuconfig.rs | 4 +++- 3 files changed, 10 insertions(+), 15 deletions(-) diff --git a/crates/lib/src/bootc_composefs/boot.rs b/crates/lib/src/bootc_composefs/boot.rs index 16fdc980b..548af6b7a 100644 --- a/crates/lib/src/bootc_composefs/boot.rs +++ b/crates/lib/src/bootc_composefs/boot.rs @@ -73,7 +73,7 @@ const VMLINUZ: &str = "vmlinuz"; /// directory specified by the BLS spec. We do this because we want systemd-boot to only look at /// our config files and not show the actual UKIs in the bootloader menu /// This is relative to the ESP -pub(crate) const SYSTEMD_UKI_DIR: &str = "EFI/Linux/bootc"; +pub(crate) const BOOTC_UKI_DIR: &str = "EFI/Linux/bootc"; pub(crate) enum BootSetupType<'a> { /// For initial setup, i.e. install to-disk @@ -420,7 +420,7 @@ pub(crate) fn setup_composefs_bls_boot( let current_cfg = get_booted_bls(&boot_dir)?; let mut cmdline = match current_cfg.cfg_type { - BLSConfigType::NonEFI { options, .. } => { + BLSConfigType::NonUKI { options, .. } => { let options = options .ok_or_else(|| anyhow::anyhow!("No 'options' found in BLS Config"))?; @@ -658,7 +658,6 @@ fn write_pe_to_esp( uki_id: &Sha512HashValue, is_insecure_from_opts: bool, mounted_efi: impl AsRef, - bootloader: &Bootloader, ) -> Result> { let efi_bin = read_file(file, &repo).context("Reading .efi binary")?; @@ -703,13 +702,8 @@ fn write_pe_to_esp( }); } - // Write the UKI to ESP - let efi_linux_path = mounted_efi.as_ref().join(match bootloader { - Bootloader::Grub => EFI_LINUX, - Bootloader::Systemd => SYSTEMD_UKI_DIR, - }); - - create_dir_all(&efi_linux_path).context("Creating EFI/Linux")?; + let efi_linux_path = mounted_efi.as_ref().join(BOOTC_UKI_DIR); + create_dir_all(&efi_linux_path).context("Creating bootc UKI directory")?; let final_pe_path = match file_path.parent() { Some(parent) => { @@ -858,7 +852,7 @@ fn write_systemd_uki_config( bls_conf .with_title(boot_label.boot_label) .with_cfg(BLSConfigType::UKI { - uki: format!("/{SYSTEMD_UKI_DIR}/{}{}", id.to_hex(), EFI_EXT).into(), + uki: format!("/{BOOTC_UKI_DIR}/{}{}", id.to_hex(), EFI_EXT).into(), }) .with_sort_key(default_sort_key.into()) .with_version(boot_label.version.unwrap_or(default_sort_key.into())); @@ -998,7 +992,6 @@ pub(crate) fn setup_composefs_uki_boot( &id, is_insecure_from_opts, esp_mount.dir.path(), - &bootloader, )?; if let Some(label) = ret { diff --git a/crates/lib/src/bootc_composefs/delete.rs b/crates/lib/src/bootc_composefs/delete.rs index a0dd9f96b..266ddeeea 100644 --- a/crates/lib/src/bootc_composefs/delete.rs +++ b/crates/lib/src/bootc_composefs/delete.rs @@ -7,7 +7,7 @@ use composefs_boot::bootloader::{EFI_ADDON_DIR_EXT, EFI_EXT}; use crate::{ bootc_composefs::{ - boot::{find_vmlinuz_initrd_duplicates, get_efi_uuid_source, BootType, SYSTEMD_UKI_DIR}, + boot::{find_vmlinuz_initrd_duplicates, get_efi_uuid_source, BootType, BOOTC_UKI_DIR}, gc::composefs_gc, repo::open_composefs_repo, rollback::{composefs_rollback, rename_exchange_user_cfg}, @@ -153,7 +153,7 @@ fn delete_kernel_initrd(bls_config: &BLSConfigType, boot_dir: &Dir) -> Result<() #[fn_error_context::context("Deleting UKI and UKI addons {uki_id}")] fn delete_uki(uki_id: &str, esp_mnt: &Dir) -> Result<()> { // TODO: We don't delete global addons here - let ukis = esp_mnt.open_dir(SYSTEMD_UKI_DIR)?; + let ukis = esp_mnt.open_dir(BOOTC_UKI_DIR)?; for entry in ukis.entries_utf8()? { let entry = entry?; diff --git a/crates/lib/src/parsers/grub_menuconfig.rs b/crates/lib/src/parsers/grub_menuconfig.rs index 41e25554c..d7f8ec5d0 100644 --- a/crates/lib/src/parsers/grub_menuconfig.rs +++ b/crates/lib/src/parsers/grub_menuconfig.rs @@ -15,6 +15,8 @@ use nom::{ Err, IResult, Parser, }; +use crate::bootc_composefs::boot::BOOTC_UKI_DIR; + /// Body content of a GRUB menuentry containing parsed commands. #[derive(Debug, PartialEq, Eq)] pub(crate) struct MenuentryBody<'a> { @@ -95,7 +97,7 @@ impl<'a> MenuEntry<'a> { title: format!("{boot_label}: ({uki_id})"), body: MenuentryBody { insmod: vec!["fat", "chain"], - chainloader: format!("/EFI/Linux/{uki_id}.efi"), + chainloader: format!("/{BOOTC_UKI_DIR}/{uki_id}.efi"), search: "--no-floppy --set=root --fs-uuid \"${EFI_PART_UUID}\"", version: 0, extra: vec![],