diff --git a/crates/lib/src/bootc_composefs/boot.rs b/crates/lib/src/bootc_composefs/boot.rs
index 801a019bd..18c1b2c98 100644
--- a/crates/lib/src/bootc_composefs/boot.rs
+++ b/crates/lib/src/bootc_composefs/boot.rs
@@ -106,10 +106,8 @@ use crate::{
};
use crate::{
bootc_composefs::state::{get_booted_bls, write_composefs_state},
- bootloader::esp_in,
-};
-use crate::{
- bootc_composefs::status::get_container_manifest_and_config, bootc_kargs::compute_new_kargs,
+ bootc_composefs::status::get_container_manifest_and_config,
+ bootc_kargs::compute_new_kargs,
};
use crate::{bootc_composefs::status::get_sorted_grub_uki_boot_entries, install::PostFetchState};
use crate::{
@@ -214,6 +212,17 @@ fi
)
}
+fn open_target_root(root_setup: &RootSetup) -> Result
{
+ if let Some(target_root) = root_setup.target_root_path.as_ref() {
+ Dir::open_ambient_dir(target_root, ambient_authority()).context("Opening target root path")
+ } else {
+ root_setup
+ .physical_root
+ .try_clone()
+ .context("Cloning target root handle")
+ }
+}
+
pub fn get_esp_partition(device: &str) -> Result<(String, Option)> {
let device_info = bootc_blockdev::partitions_of(Utf8Path::new(device))?;
let esp = crate::bootloader::esp_in(&device_info)?;
@@ -521,11 +530,25 @@ pub(crate) fn setup_composefs_bls_boot(
cmdline_options.extend(&Cmdline::from(&composefs_cmdline));
// Locate ESP partition device
- let esp_part = esp_in(&root_setup.device_info)?;
+ let esp_root = open_target_root(root_setup)?;
+ let esp_part = if root_setup.require_esp_mount {
+ crate::bootloader::require_boot_efi_mount(&esp_root)?
+ } else {
+ match crate::bootloader::require_boot_efi_mount(&esp_root) {
+ Ok(p) => p,
+ Err(e) => {
+ tracing::debug!(
+ "ESP mount check failed in permissive mode: {e}; falling back to partition table scan"
+ );
+ let esp = crate::bootloader::esp_in(&root_setup.device_info)?;
+ esp.node.clone()
+ }
+ }
+ };
(
root_setup.physical_root_path.clone(),
- esp_part.node.clone(),
+ esp_part,
cmdline_options,
fs,
postfetch.detected_bootloader.clone(),
@@ -1063,11 +1086,26 @@ pub(crate) fn setup_composefs_uki_boot(
BootSetupType::Setup((root_setup, state, postfetch, ..)) => {
state.require_no_kargs_for_uki()?;
- let esp_part = esp_in(&root_setup.device_info)?;
+ let esp_root = open_target_root(root_setup)?;
+
+ let esp_part = if root_setup.require_esp_mount {
+ crate::bootloader::require_boot_efi_mount(&esp_root)?
+ } else {
+ match crate::bootloader::require_boot_efi_mount(&esp_root) {
+ Ok(p) => p,
+ Err(e) => {
+ tracing::debug!(
+ "ESP mount check failed in permissive mode: {e}; falling back to partition table scan"
+ );
+ let esp = crate::bootloader::esp_in(&root_setup.device_info)?;
+ esp.node.clone()
+ }
+ }
+ };
(
root_setup.physical_root_path.clone(),
- esp_part.node.clone(),
+ esp_part,
postfetch.detected_bootloader.clone(),
state.composefs_options.insecure,
state.composefs_options.uki_addon.as_ref(),
@@ -1231,18 +1269,23 @@ pub(crate) async fn setup_composefs_boot(
.or(root_setup.rootfs_uuid.as_deref())
.ok_or_else(|| anyhow!("No uuid for boot/root"))?;
+ let target_root = open_target_root(root_setup)?;
+
if cfg!(target_arch = "s390x") {
// TODO: Integrate s390x support into install_via_bootupd
crate::bootloader::install_via_zipl(&root_setup.device_info, boot_uuid)?;
} else if postfetch.detected_bootloader == Bootloader::Grub {
crate::bootloader::install_via_bootupd(
&root_setup.device_info,
+ &target_root,
&root_setup.physical_root_path,
&state.config_opts,
None,
+ root_setup.require_esp_mount,
)?;
} else {
crate::bootloader::install_systemd_boot(
+ &target_root,
&root_setup.device_info,
&root_setup.physical_root_path,
&state.config_opts,
@@ -1406,4 +1449,11 @@ mod tests {
"RHEL should sort before Fedora in descending order"
);
}
+
+ #[test]
+ fn test_efi_uuid_source_formatting() {
+ let source = get_efi_uuid_source();
+ assert!(source.contains("${config_directory}/"));
+ assert!(source.contains(EFI_UUID_FILE));
+ }
}
diff --git a/crates/lib/src/bootloader.rs b/crates/lib/src/bootloader.rs
index 7fce2888a..882c95390 100644
--- a/crates/lib/src/bootloader.rs
+++ b/crates/lib/src/bootloader.rs
@@ -11,7 +11,7 @@ use fn_error_context::context;
use bootc_blockdev::{Partition, PartitionTable};
use bootc_mount as mount;
-use crate::bootc_composefs::boot::{SecurebootKeys, get_sysroot_parent_dev, mount_esp};
+use crate::bootc_composefs::boot::{SecurebootKeys, mount_esp};
use crate::{discoverable_partition_specification, utils};
/// The name of the mountpoint for efi (as a subdirectory of /boot, or at the toplevel)
@@ -31,40 +31,45 @@ pub(crate) fn esp_in(device: &PartitionTable) -> Result<&Partition> {
.ok_or(anyhow::anyhow!("ESP not found in partition table"))
}
-/// Get esp partition node based on the root dir
-pub(crate) fn get_esp_partition_node(root: &Dir) -> Result