1
0
mirror of https://github.com/containers/bootc.git synced 2026-02-05 15:45:53 +01:00

install: mount esp in clean_boot_directories()

On FCOS, esp is not mounted after booted, need to find esp and
mount before cleaning, or `/boot/efi` will be removed.

Signed-off-by: Huijing Hei <hhei@redhat.com>
This commit is contained in:
Huijing Hei
2025-12-18 14:45:57 +08:00
committed by Colin Walters
parent b9ac902709
commit 1d7b73d24b
2 changed files with 47 additions and 5 deletions

View File

@@ -5,12 +5,13 @@ use anyhow::{anyhow, bail, Context, Result};
use bootc_utils::CommandRunExt;
use camino::Utf8Path;
use cap_std_ext::cap_std::fs::Dir;
use cap_std_ext::dirext::CapStdExtDirExt;
use fn_error_context::context;
use bootc_blockdev::{Partition, PartitionTable};
use bootc_mount as mount;
use crate::bootc_composefs::boot::{mount_esp, SecurebootKeys};
use crate::bootc_composefs::boot::{get_sysroot_parent_dev, mount_esp, SecurebootKeys};
use crate::{discoverable_partition_specification, utils};
/// The name of the mountpoint for efi (as a subdirectory of /boot, or at the toplevel)
@@ -30,6 +31,42 @@ 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<Option<String>> {
let device = get_sysroot_parent_dev(&root)?;
let base_partitions = bootc_blockdev::partitions_of(Utf8Path::new(&device))?;
let esp = base_partitions.find_partition_of_esp()?;
Ok(esp.map(|v| v.node.clone()))
}
/// Mount ESP part at /boot/efi
pub(crate) fn mount_esp_part(root: &Dir, root_path: &Utf8Path, is_ostree: bool) -> Result<()> {
let efi_path = Utf8Path::new("boot").join(crate::bootloader::EFI_DIR);
let Some(esp_fd) = root
.open_dir_optional(&efi_path)
.context("Opening /boot/efi")?
else {
return Ok(());
};
let Some(false) = esp_fd.is_mountpoint(".")? else {
return Ok(());
};
tracing::debug!("Not a mountpoint: /boot/efi");
// On ostree env with enabled composefs, should be /target/sysroot
let physical_root = if is_ostree {
&root.open_dir("sysroot").context("Opening /sysroot")?
} else {
root
};
if let Some(esp_part) = get_esp_partition_node(physical_root)? {
bootc_mount::mount(&esp_part, &root_path.join(&efi_path))?;
tracing::debug!("Mounted {esp_part} at /boot/efi");
}
Ok(())
}
/// Determine if the invoking environment contains bootupd, and if there are bootupd-based
/// updates in the target root.
#[context("Querying for bootupd")]

View File

@@ -1978,15 +1978,20 @@ fn remove_all_except_loader_dirs(bootdir: &Dir, is_ostree: bool) -> Result<()> {
}
#[context("Removing boot directory content")]
fn clean_boot_directories(rootfs: &Dir, is_ostree: bool) -> Result<()> {
fn clean_boot_directories(rootfs: &Dir, rootfs_path: &Utf8Path, is_ostree: bool) -> Result<()> {
let bootdir =
crate::utils::open_dir_remount_rw(rootfs, BOOT.into()).context("Opening /boot")?;
if ARCH_USES_EFI {
// On booted FCOS, esp is not mounted by default
// Mount ESP part at /boot/efi before clean
crate::bootloader::mount_esp_part(&rootfs, &rootfs_path, is_ostree)?;
}
// This should not remove /boot/efi note.
remove_all_except_loader_dirs(&bootdir, is_ostree).context("Emptying /boot")?;
// TODO: Discover the ESP the same way bootupd does it; we should also
// support not wiping the ESP.
// TODO: we should also support not wiping the ESP.
if ARCH_USES_EFI {
if let Some(efidir) = bootdir
.open_dir_optional(crate::bootloader::EFI_DIR)
@@ -2194,7 +2199,7 @@ pub(crate) async fn install_to_filesystem(
.await??;
}
Some(ReplaceMode::Alongside) => {
clean_boot_directories(&target_rootfs_fd, is_already_ostree)?
clean_boot_directories(&target_rootfs_fd, &target_root_path, is_already_ostree)?
}
None => require_empty_rootdir(&rootfs_fd)?,
}