From 13b0feb4773e50703611407797ecbeea679067c5 Mon Sep 17 00:00:00 2001 From: Huijing Hei Date: Thu, 4 Sep 2025 17:09:25 +0800 Subject: [PATCH 1/7] efi: update `get_efi_component_from_usr()` to return `Option` --- src/efi.rs | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/src/efi.rs b/src/efi.rs index bc0fcc9c..887113f6 100644 --- a/src/efi.rs +++ b/src/efi.rs @@ -463,16 +463,18 @@ impl Component for Efi { fn generate_update_metadata(&self, sysroot: &str) -> Result> { let sysroot_path = Utf8Path::new(sysroot); - // copy EFI files to updates dir from usr/lib/efi let efilib_path = sysroot_path.join(EFILIB); - let meta = if efilib_path.exists() { + let efi_comps = if efilib_path.exists() { + get_efi_component_from_usr(&sysroot_path, EFILIB)? + } else { + None + }; + + // copy EFI files to updates dir from usr/lib/efi + let meta = if let Some(efi_components) = efi_comps { let mut packages = Vec::new(); let mut modules_vec: Vec = vec![]; let sysroot_dir = Dir::open_ambient_dir(sysroot_path, cap_std::ambient_authority())?; - let efi_components = get_efi_component_from_usr(&sysroot_path, EFILIB)?; - if efi_components.len() == 0 { - bail!("Failed to find EFI components from {efilib_path}"); - } for efi in efi_components { Command::new("cp") .args(["-rp", "--reflink=auto"]) @@ -730,7 +732,7 @@ pub struct EFIComponent { fn get_efi_component_from_usr<'a>( sysroot: &'a Utf8Path, usr_path: &'a str, -) -> Result> { +) -> Result>> { let efilib_path = sysroot.join(usr_path); let skip_count = Utf8Path::new(usr_path).components().count(); @@ -761,9 +763,12 @@ fn get_efi_component_from_usr<'a>( }) .collect(); + if components.len() == 0 { + return Ok(None); + } components.sort_by(|a, b| a.name.cmp(&b.name)); - Ok(components) + Ok(Some(components)) } #[cfg(test)] @@ -900,7 +905,7 @@ Boot0003* test"; let efi_comps = get_efi_component_from_usr(utf8_tpath, EFILIB)?; assert_eq!( efi_comps, - vec![ + Some(vec![ EFIComponent { name: "BAR".to_string(), version: "1.1".to_string(), @@ -911,12 +916,12 @@ Boot0003* test"; version: "1.1".to_string(), path: Utf8PathBuf::from("usr/lib/efi/FOO/1.1/EFI"), }, - ] + ]) ); std::fs::remove_dir_all(efi_path.join("BAR/1.1/EFI"))?; std::fs::remove_dir_all(efi_path.join("FOO/1.1/EFI"))?; let efi_comps = get_efi_component_from_usr(utf8_tpath, EFILIB)?; - assert_eq!(efi_comps, []); + assert_eq!(efi_comps, None); Ok(()) } } From f3397a5255f4a583183e1933a2b9296b825ec6d9 Mon Sep 17 00:00:00 2001 From: Huijing Hei Date: Thu, 11 Sep 2025 17:34:03 +0800 Subject: [PATCH 2/7] Add 2 functions `query_file()` and `transfer_ostree_boot_to_usr()` - `query_file()` to query the rpm database and get package version - `transfer_ostree_boot_to_usr()` that will copy EFI files from `usr/lib/ostree-boot` to `usr/lib/efi` --- src/efi.rs | 49 ++++++++++++++++++++++++++++++++++++++++++++ src/packagesystem.rs | 15 ++++++++++++++ 2 files changed, 64 insertions(+) diff --git a/src/efi.rs b/src/efi.rs index 887113f6..87d9562a 100644 --- a/src/efi.rs +++ b/src/efi.rs @@ -771,6 +771,55 @@ fn get_efi_component_from_usr<'a>( Ok(Some(components)) } +/// Copy files from usr/lib/ostree-boot/efi/EFI to /usr/lib/efi/// +fn transfer_ostree_boot_to_usr(sysroot: &Path) -> Result<()> { + let ostreeboot_efi = Path::new(ostreeutil::BOOT_PREFIX).join("efi"); + let ostreeboot_efi_path = sysroot.join(&ostreeboot_efi); + + for entry in WalkDir::new(ostreeboot_efi_path.join("EFI")) { + let entry = entry?; + + if entry.file_type().is_file() { + let entry_path = entry.path(); + + // get path EFI/{BOOT,}/ + let filepath = entry_path.strip_prefix(&ostreeboot_efi_path)?; + // get path /boot/efi/EFI/{BOOT,}/ + let boot_filepath = Path::new("/boot/efi").join(filepath); + + // Run `rpm -qf ` + let pkg = crate::packagesystem::query_file( + sysroot.to_str().unwrap(), + boot_filepath.to_str().unwrap(), + )?; + + let (name, evr) = pkg.split_once(' ').unwrap(); + let component = name.split('-').next().unwrap_or(""); + // get path usr/lib/efi// + let efilib_path = Path::new(EFILIB).join(component).join(evr); + + let sysroot_dir = openat::Dir::open(sysroot)?; + // Ensure dest parent directory exists + if let Some(parent) = efilib_path.join(filepath).parent() { + sysroot_dir.ensure_dir_all(parent, 0o755)?; + } + + // Source dir is usr/lib/ostree-boot/efi + let src = sysroot_dir + .sub_dir(&ostreeboot_efi) + .context("Opening ostree-boot dir")?; + // Dest dir is usr/lib/efi// + let dest = sysroot_dir + .sub_dir(&efilib_path) + .context("Opening usr/lib/efi dir")?; + // Copy file from ostree-boot to usr/lib/efi + src.copy_file_at(filepath, &dest, filepath) + .context("Copying file to usr/lib/efi")?; + } + } + Ok(()) +} + #[cfg(test)] mod tests { use cap_std_ext::dirext::CapStdExtDirExt; diff --git a/src/packagesystem.rs b/src/packagesystem.rs index f20e5e81..c123b4fc 100644 --- a/src/packagesystem.rs +++ b/src/packagesystem.rs @@ -115,6 +115,21 @@ fn split_name_version(input: &str) -> Option<(String, String)> { Some((name.to_string(), format!("{version}-{release}"))) } +/// Query the rpm database and get package " " +pub(crate) fn query_file(sysroot_path: &str, path: &str) -> Result { + let mut c = ostreeutil::rpm_cmd(sysroot_path)?; + c.args(["-q", "--queryformat", "%{NAME} %{EVR}", "-f", path]); + + let rpmout = c.output()?; + if !rpmout.status.success() { + std::io::stderr().write_all(&rpmout.stderr)?; + bail!("Failed to invoke rpm -qf"); + } + + let output = String::from_utf8(rpmout.stdout)?; + Ok(output.trim().to_string()) +} + fn parse_evr(pkg: &str) -> Module { // assume it is "grub2-1:2.12-28.fc42" (from usr/lib/efi) if !pkg.ends_with(std::env::consts::ARCH) { From 123a0cd364e89e02b52fb51a53e991c15ada02b7 Mon Sep 17 00:00:00 2001 From: Huijing Hei Date: Wed, 24 Sep 2025 12:13:09 +0800 Subject: [PATCH 3/7] efi: transfer `usr/lib/ostree-boot` to `usr/lib/efi` in `generate_update_metadata()` --- src/efi.rs | 77 +++++++++++++++++++----------------------------------- 1 file changed, 27 insertions(+), 50 deletions(-) diff --git a/src/efi.rs b/src/efi.rs index 87d9562a..d4ba444f 100644 --- a/src/efi.rs +++ b/src/efi.rs @@ -14,6 +14,7 @@ use bootc_internal_utils::CommandRunExt; use camino::{Utf8Path, Utf8PathBuf}; use cap_std::fs::Dir; use cap_std_ext::cap_std; +use cap_std_ext::dirext::CapStdExtDirExt; use chrono::prelude::*; use fn_error_context::context; use openat_ext::OpenatDirExt; @@ -461,20 +462,30 @@ impl Component for Efi { } fn generate_update_metadata(&self, sysroot: &str) -> Result> { - let sysroot_path = Utf8Path::new(sysroot); + let sysroot_path = Path::new(sysroot); + let sysroot_dir = Dir::open_ambient_dir(sysroot_path, cap_std::ambient_authority())?; - let efilib_path = sysroot_path.join(EFILIB); - let efi_comps = if efilib_path.exists() { - get_efi_component_from_usr(&sysroot_path, EFILIB)? - } else { - None - }; + if let Some(ostreeboot) = sysroot_dir + .open_dir_optional(ostreeutil::BOOT_PREFIX) + .context("Opening usr/lib/ostree-boot")? + { + let cruft = ["loader", "grub2"]; + for p in cruft.iter() { + ostreeboot.remove_all_optional(p)?; + } + // Transfer ostree-boot EFI files to usr/lib/efi + transfer_ostree_boot_to_usr(sysroot_path)?; - // copy EFI files to updates dir from usr/lib/efi - let meta = if let Some(efi_components) = efi_comps { + // Remove usr/lib/ostree-boot/efi/EFI dir (after transfer) or if it is empty + ostreeboot.remove_all_optional("efi/EFI")?; + } + + // copy EFI files from usr/lib/efi to updates dir + if let Some(efi_components) = + get_efi_component_from_usr(Utf8Path::from_path(sysroot_path).unwrap(), EFILIB)? + { let mut packages = Vec::new(); let mut modules_vec: Vec = vec![]; - let sysroot_dir = Dir::open_ambient_dir(sysroot_path, cap_std::ambient_authority())?; for efi in efi_components { Command::new("cp") .args(["-rp", "--reflink=auto"]) @@ -492,50 +503,16 @@ impl Component for Efi { // change to now to workaround https://github.com/coreos/bootupd/issues/933 let timestamp = std::time::SystemTime::now(); - ContentMetadata { + let meta = ContentMetadata { timestamp: chrono::DateTime::::from(timestamp), version: packages.join(","), versions: Some(modules_vec), - } + }; + write_update_metadata(sysroot, self, &meta)?; + Ok(Some(meta)) } else { - let ostreebootdir = sysroot_path.join(ostreeutil::BOOT_PREFIX); - - // move EFI files to updates dir from /usr/lib/ostree-boot - if ostreebootdir.exists() { - let cruft = ["loader", "grub2"]; - for p in cruft.iter() { - let p = ostreebootdir.join(p); - if p.exists() { - std::fs::remove_dir_all(&p)?; - } - } - - let efisrc = ostreebootdir.join("efi/EFI"); - if !efisrc.exists() { - bail!("Failed to find {:?}", &efisrc); - } - - let dest_efidir = component_updatedir(sysroot, self); - let dest_efidir = - Utf8PathBuf::from_path_buf(dest_efidir).expect("Path is invalid UTF-8"); - // Fork off mv() because on overlayfs one can't rename() a lower level - // directory today, and this will handle the copy fallback. - Command::new("mv").args([&efisrc, &dest_efidir]).run()?; - - let efidir = openat::Dir::open(dest_efidir.as_std_path()) - .with_context(|| format!("Opening {}", dest_efidir))?; - let files = crate::util::filenames(&efidir)?.into_iter().map(|mut f| { - f.insert_str(0, "/boot/efi/EFI/"); - f - }); - query_files(sysroot, files)? - } else { - anyhow::bail!("Failed to find {ostreebootdir}"); - } - }; - - write_update_metadata(sysroot, self, &meta)?; - Ok(Some(meta)) + anyhow::bail!("Failed to find EFI components"); + } } fn query_update(&self, sysroot: &openat::Dir) -> Result> { From e44ba4acda4c0e791d042db33f33dd64f52f17b9 Mon Sep 17 00:00:00 2001 From: Huijing Hei Date: Wed, 24 Sep 2025 12:15:05 +0800 Subject: [PATCH 4/7] efi: require minimum of 2 components for update metadata generation Enhance `generate_update_metadata()` with validation to ensure at least two packages are provided, preventing the creation of incomplete or invalid update payloads. See https://github.com/coreos/bootupd/issues/994 --- src/efi.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/efi.rs b/src/efi.rs index d4ba444f..8efb3bd8 100644 --- a/src/efi.rs +++ b/src/efi.rs @@ -484,6 +484,10 @@ impl Component for Efi { if let Some(efi_components) = get_efi_component_from_usr(Utf8Path::from_path(sysroot_path).unwrap(), EFILIB)? { + // Confirm EFI has at least two components grub2 & shim + // See https://github.com/coreos/bootupd/issues/994 + assert!(efi_components.len() > 1); + let mut packages = Vec::new(); let mut modules_vec: Vec = vec![]; for efi in efi_components { From e743c387178c8c64afba15a31ce57ad62925a474 Mon Sep 17 00:00:00 2001 From: Huijing Hei Date: Wed, 24 Sep 2025 12:18:16 +0800 Subject: [PATCH 5/7] Fix building warning --- src/component.rs | 1 + src/util.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/src/component.rs b/src/component.rs index 5e611590..fe280485 100644 --- a/src/component.rs +++ b/src/component.rs @@ -112,6 +112,7 @@ pub(crate) fn component_updatedirname(component: &dyn Component) -> PathBuf { /// Returns the path to the payload directory for an available update for /// a component. +#[allow(dead_code)] #[cfg(any( target_arch = "x86_64", target_arch = "aarch64", diff --git a/src/util.rs b/src/util.rs index 3d32bc5c..2fda1778 100644 --- a/src/util.rs +++ b/src/util.rs @@ -19,6 +19,7 @@ pub(crate) fn getenv_utf8(n: &str) -> Result> { } } +#[allow(dead_code)] pub(crate) fn filenames(dir: &openat::Dir) -> Result> { let mut ret = HashSet::new(); for entry in dir.list_dir(".")? { From 46d19676356a847040ad4d5f4dcc2a4954112b5d Mon Sep 17 00:00:00 2001 From: Huijing Hei Date: Wed, 24 Sep 2025 12:18:31 +0800 Subject: [PATCH 6/7] tests: update tests with the tranfering logic --- .github/workflows/ci.yml | 2 +- tests/e2e-update/e2e-update-in-vm.sh | 22 +++++++------- tests/e2e-update/e2e-update.sh | 10 +++---- tests/kola/test-bootupd | 39 +++++++++++++++++-------- tests/tests/generate-update-metadata.sh | 20 +++++++++++++ tests/tests/move-content-to-usr.sh | 28 ------------------ 6 files changed, 64 insertions(+), 57 deletions(-) create mode 100755 tests/tests/generate-update-metadata.sh delete mode 100755 tests/tests/move-content-to-usr.sh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e1cec9ea..ea638931 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -99,4 +99,4 @@ jobs: - name: bootupctl generate-update-metadata run: | set -xeuo pipefail - sudo podman run --rm -v $PWD:/run/src -w /run/src --privileged localhost/bootupd:latest tests/tests/move-content-to-usr.sh + sudo podman run --rm -v $PWD:/run/src -w /run/src --privileged localhost/bootupd:latest tests/tests/generate-update-metadata.sh diff --git a/tests/e2e-update/e2e-update-in-vm.sh b/tests/e2e-update/e2e-update-in-vm.sh index b6bf6e53..389f50cd 100755 --- a/tests/e2e-update/e2e-update-in-vm.sh +++ b/tests/e2e-update/e2e-update-in-vm.sh @@ -18,9 +18,9 @@ if ! test -f ${stampfile}; then fatal "already at ${TARGET_COMMIT}" fi - current_grub=$(rpm -q --queryformat='%{nevra}\n' ${TARGET_GRUB_NAME}) - if test "${current_grub}" == "${TARGET_GRUB_PKG}"; then - fatal "Current grub ${current_grub} is same as target ${TARGET_GRUB_PKG}" + current_grub=$(rpm -q --queryformat='%{evr}\n' ${TARGET_GRUB_NAME}) + if test "${current_grub}" == "${TARGET_GRUB_EVR}"; then + fatal "Current grub ${current_grub} is same as target ${TARGET_GRUB_EVR}" fi # FIXME @@ -44,8 +44,8 @@ if test "$semode" != Enforcing; then fatal "SELinux mode is ${semode}" fi -if ! test -n "${TARGET_GRUB_PKG}"; then - fatal "Missing TARGET_GRUB_PKG" +if ! test -n "${TARGET_GRUB_EVR}"; then + fatal "Missing TARGET_GRUB_EVR" fi bootupctl validate @@ -53,11 +53,11 @@ ok validate bootupctl status | tee out.txt assert_file_has_content_literal out.txt 'Component EFI' -assert_file_has_content_literal out.txt ' Installed: grub2-efi-x64-' -assert_not_file_has_content out.txt ' Installed:.*test-bootupd-payload' -assert_not_file_has_content out.txt ' Installed:.*'"${TARGET_GRUB_PKG}" -assert_file_has_content out.txt 'Update: Available:.*'"${TARGET_GRUB_PKG}" -assert_file_has_content out.txt 'Update: Available:.*test-bootupd-payload-1.0' +assert_file_has_content_literal out.txt ' Installed: grub2-1:' +assert_not_file_has_content out.txt ' Installed:.*test_bootupd_payload' +assert_not_file_has_content out.txt ' Installed:.*'"${TARGET_GRUB_EVR}" +assert_file_has_content out.txt 'Update: Available:.*'"${TARGET_GRUB_EVR}" +assert_file_has_content out.txt 'Update: Available:.*test_bootupd_payload-1.0' bootupctl status --print-if-available > out.txt assert_file_has_content_literal 'out.txt' 'Updates available: BIOS EFI' ok update avail @@ -74,7 +74,7 @@ assert_file_has_content err.txt "error: .*synthetic failpoint" bootupctl update -vvv | tee out.txt assert_file_has_content out.txt "Previous EFI: .*" -assert_file_has_content out.txt "Updated EFI: ${TARGET_GRUB_PKG}.*,test-bootupd-payload-1.0" +assert_file_has_content out.txt "Updated EFI: .*${TARGET_GRUB_EVR}.*,test_bootupd_payload-1.0" assert_file_has_content ${tmpefimount}/EFI/fedora/test-bootupd.efi test-payload diff --git a/tests/e2e-update/e2e-update.sh b/tests/e2e-update/e2e-update.sh index 62cd0d05..e896babe 100755 --- a/tests/e2e-update/e2e-update.sh +++ b/tests/e2e-update/e2e-update.sh @@ -25,7 +25,7 @@ export test_tmpdir=${testtmp} # This is new content for our update test_bootupd_payload_file=/boot/efi/EFI/fedora/test-bootupd.efi test_bootupd_payload_file1=/boot/efi/EFI/BOOT/test-bootupd1.efi -build_rpm test-bootupd-payload \ +build_rpm test_bootupd_payload \ files "${test_bootupd_payload_file} ${test_bootupd_payload_file1}" \ install "mkdir -p %{buildroot}/$(dirname ${test_bootupd_payload_file}) @@ -56,9 +56,9 @@ if test -z "${e2e_skip_build:-}"; then runv cosa build runv cosa osbuild qemu prev_image=$(runv cosa meta --image-path qemu) - # Modify manifest to include `test-bootupd-payload` RPM + # Modify manifest to include `test_bootupd_ayload` RPM runv git -C src/config checkout manifest.yaml # first make sure it's clean - echo "packages: [test-bootupd-payload]" >> src/config/manifest.yaml + echo "packages: [test_bootupd_payload]" >> src/config/manifest.yaml rm -f ${overrides}/rpm/*.rpm echo "Building update ostree" # Latest (current) version in F42 @@ -77,7 +77,7 @@ case $(arch) in *) fatal "Unhandled arch $(arch)";; esac target_grub_name=grub2-efi-${grubarch} -target_grub_pkg=$(rpm -qp --queryformat='%{nevra}\n' ${overrides}/rpm/${target_grub_name}-2*.rpm) +target_grub_evr=$(rpm -qp --queryformat='%{evr}\n' ${overrides}/rpm/${target_grub_name}-2*.rpm) target_commit=$(cosa meta --get-value ostree-commit) echo "Target commit: ${target_commit}" # For some reason 9p can't write to tmpfs @@ -97,7 +97,7 @@ systemd: RemainAfterExit=yes Environment=TARGET_COMMIT=${target_commit} Environment=TARGET_GRUB_NAME=${target_grub_name} - Environment=TARGET_GRUB_PKG=${target_grub_pkg} + Environment=TARGET_GRUB_EVR=${target_grub_evr} Environment=SRCDIR=/run/bootupd-source # Run via shell because selinux denies systemd writing to 9p apparently ExecStart=/bin/sh -c '/run/bootupd-source/${testprefix}/e2e-update-in-vm.sh &>>/run/testtmp/out.txt; test -f /run/rebooting || poweroff -ff' diff --git a/tests/kola/test-bootupd b/tests/kola/test-bootupd index df904dd2..7a799ee9 100755 --- a/tests/kola/test-bootupd +++ b/tests/kola/test-bootupd @@ -30,19 +30,24 @@ efisubdir=fedora efidir=${efiupdir}/${efisubdir} ostefi=${ostbaseefi}/${efisubdir} shim=shimx64.efi +efilib=/usr/lib/efi test -f "${efidir}/${shim}" prepare_efi_update() { test -w /usr - mkdir -p ${ostbaseefi} - cp -a ${efiupdir}.orig/* ${ostbaseefi}/ + # Do not need to create ostree-boot dir after transfered + if [ ! -d ${efilib} ]; then + mkdir -p ${ostbaseefi} + cp -a ${efiupdir}.orig/* ${ostbaseefi}/ + fi rm -rf ${efiupdir} ${bootupdir}/EFI.json } bootupctl status > out.txt +evr=$(rpm -q grub2-common --qf '%{EVR}') assert_file_has_content_literal out.txt 'Component EFI' -assert_file_has_content_literal out.txt ' Installed: grub2-efi-x64-' +assert_file_has_content_literal out.txt ' Installed: grub2-'"${evr}" assert_file_has_content_literal out.txt 'Update: At latest version' assert_file_has_content out.txt '^CoreOS aleph version:' ok status @@ -61,10 +66,20 @@ test -w /usr || rpm-ostree usroverlay cp -a ${efiupdir} ${efiupdir}.orig prepare_efi_update -# FIXME need to synthesize an RPM for this -# echo somenewfile > ${ostefi}/somenew.efi -rm -v ${ostefi}/shim.efi -echo bootupd-test-changes >> ${ostefi}/grubx64.efi +shim= +grubx64= +# Change the files under usr/lib/efi after transferred +if [ -d ${efilib} ]; then + shim=$(find ${efilib} -name shim.efi) + grubx64=$(find ${efilib} -name grubx64.efi) +else + # FIXME need to synthesize an RPM for this + # echo somenewfile > ${ostefi}/somenew.efi + shim=${ostefi}/shim.efi + grubx64=${ostefi}/grubx64.efi +fi +rm -v ${shim} +echo bootupd-test-changes >> ${grubx64} /usr/libexec/bootupd generate-update-metadata / ver=$(jq -r .version < ${bootupdir}/EFI.json) vers=$(jq -r .versions < ${bootupdir}/EFI.json) @@ -78,21 +93,21 @@ mv new.json ${bootupdir}/EFI.json bootupctl status | tee out.txt assert_file_has_content_literal out.txt 'Component EFI' -assert_file_has_content_literal out.txt ' Installed: grub2-efi-x64-' -assert_not_file_has_content out.txt ' Installed: grub2-efi-x64.*,test' +assert_file_has_content_literal out.txt ' Installed: grub2-'"${evr}" +assert_not_file_has_content out.txt ' Installed: grub2-.*,test' assert_file_has_content_literal out.txt 'Update: Available:' ok update avail bootupctl status --json > status.json jq -r '.components.EFI.installed.version' < status.json > installed.txt -assert_file_has_content installed.txt '^grub2-efi-x64' +assert_file_has_content installed.txt '^grub2-'"${evr}" bootupctl update | tee out.txt -assert_file_has_content out.txt 'Updated EFI: grub2-efi-x64.*,test' +assert_file_has_content out.txt 'Updated EFI: grub2-.*,test' bootupctl status > out.txt assert_file_has_content_literal out.txt 'Component EFI' -assert_file_has_content out.txt ' Installed: grub2-efi-x64.*,test' +assert_file_has_content out.txt ' Installed: grub2-.*,test' assert_file_has_content_literal out.txt 'Update: At latest version' ok status after update diff --git a/tests/tests/generate-update-metadata.sh b/tests/tests/generate-update-metadata.sh new file mode 100755 index 00000000..f6b0e249 --- /dev/null +++ b/tests/tests/generate-update-metadata.sh @@ -0,0 +1,20 @@ +#!/bin/bash +set -xeuo pipefail + +updates=/usr/lib/bootupd/updates +rm -fv ${updates}/{BIOS,EFI}.json +if [ -d "/usr/lib/efi" ]; then + rm -rfv ${updates}/EFI +else + mv ${updates}/EFI /usr/lib/ostree-boot/efi +fi +# Run generate-update-metadata +bootupctl backend generate-update-metadata -vvv +cat ${updates}/EFI.json | jq + +# Verify the bootupd EFI has more than one component installed +version=$(cat ${updates}/EFI.json | jq -r .version | tr ',' ' ') +array=($version) +[ ${#array[*]} -gt 1 ] + +[ $(cat ${updates}/EFI.json | jq '.versions | length') -gt 1 ] diff --git a/tests/tests/move-content-to-usr.sh b/tests/tests/move-content-to-usr.sh deleted file mode 100755 index 08f94480..00000000 --- a/tests/tests/move-content-to-usr.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/bash -set -xeuo pipefail - -updates=/usr/lib/bootupd/updates -rm -fv ${updates}/{BIOS,EFI}.json -cp -r ${updates}/EFI /usr/lib/ostree-boot/efi -# prepare /usr/lib/efi// -if [ ! -d "/usr/lib/efi" ]; then - arch="$(uname --machine)" - if [[ "${arch}" == "x86_64" ]]; then - suffix="x64" - else - # Assume aarch64 for now - suffix="aa64" - fi - - grub_evr=$(rpm -qa grub2-efi-${suffix} --queryformat '%{EPOCH}:%{VERSION}-%{RELEASE}') - mkdir -p /usr/lib/efi/grub2/${grub_evr}/EFI/centos - mv ${updates}/EFI/centos/grub${suffix}.efi /usr/lib/efi/grub2/${grub_evr}/EFI/centos/ - - shim_vr=$(rpm -qa shim-${suffix} --queryformat '%{VERSION}-%{RELEASE}') - mkdir -p /usr/lib/efi/shim/${shim_vr}/EFI/ - mv ${updates}/EFI /usr/lib/efi/shim/${shim_vr}/ -else - rm -rf ${updates}/EFI -fi -bootupctl backend generate-update-metadata -vvv -cat ${updates}/EFI.json | jq From a3a349332c9ad698f52e3529d194d5dacf585c4d Mon Sep 17 00:00:00 2001 From: Huijing Hei Date: Wed, 24 Sep 2025 14:00:52 +0800 Subject: [PATCH 7/7] efi: update `transfer_ostree_boot_to_usr()` to return earlier if not existing `usr/lib/ostree-boot/efi/EFI` --- src/efi.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/efi.rs b/src/efi.rs index 8efb3bd8..2aec115e 100644 --- a/src/efi.rs +++ b/src/efi.rs @@ -757,7 +757,11 @@ fn transfer_ostree_boot_to_usr(sysroot: &Path) -> Result<()> { let ostreeboot_efi = Path::new(ostreeutil::BOOT_PREFIX).join("efi"); let ostreeboot_efi_path = sysroot.join(&ostreeboot_efi); - for entry in WalkDir::new(ostreeboot_efi_path.join("EFI")) { + let efi = ostreeboot_efi_path.join("EFI"); + if !efi.exists() { + return Ok(()); + } + for entry in WalkDir::new(&efi) { let entry = entry?; if entry.file_type().is_file() {