Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
b81b60b
uki-addon: Update addons on update/switch
Johan-Liebert1 Sep 9, 2026
3b9481f
uki/addon: Support global addons
Johan-Liebert1 Sep 9, 2026
f2de70a
cfs/upgrade/switch: Handle UKI Addons
Johan-Liebert1 Sep 9, 2026
ef1b57a
tmt: Add tests for UKI Addons
Johan-Liebert1 Sep 10, 2026
8f6895e
uki-addon: Add docs for UKI Addons
Johan-Liebert1 Sep 10, 2026
b7511f3
global-uki-addons: Add prefix to name
Johan-Liebert1 Sep 10, 2026
5c744a8
uki-addon: Add CLI for managing UKI Addons
Johan-Liebert1 Sep 10, 2026
7891efb
tmt: Update UKI Addon tests
Johan-Liebert1 Sep 10, 2026
9e2aebb
manpage: Update manpages for uki-addons
Johan-Liebert1 Sep 10, 2026
19f3692
cli: Remove composefs_backend requirement from UkiAddonOpts
Johan-Liebert1 Sep 10, 2026
fb5bc1d
uki-addon: Remove addon dir if empty
Johan-Liebert1 Sep 11, 2026
3eb91ad
uki: Parse composefs cmdline from UKI addons as well
Johan-Liebert1 Sep 11, 2026
ef7e2bf
uki-addon: Refuse to remove addons containing `composefs=` cmdline
Johan-Liebert1 Sep 11, 2026
4f3f044
tmt: Add composefs= cmdline validation tests for UKI addons
Johan-Liebert1 Sep 11, 2026
0cb2f4b
uki-addons: Add `ListReferenced` cmd option
Johan-Liebert1 Sep 15, 2026
fb681de
uki-addons: GC Global UKI Addons
Johan-Liebert1 Sep 15, 2026
6c45ad0
uki-addon: Validate and atomically write on `add`
Johan-Liebert1 Sep 30, 2026
d442f71
install/uki-addons: Bail if ostree / not found
Johan-Liebert1 Sep 30, 2026
05724ae
gc: Update global UKI Addons check
Johan-Liebert1 Oct 13, 2026
db1b204
uki-addon: Handle staged deployment
Johan-Liebert1 Oct 15, 2026
bd87ba0
global-uki-addon: Have a staged directory
Johan-Liebert1 Oct 15, 2026
c74cd95
uki-addon: Warn before a global addon is GC'd on upgrade/switch
Johan-Liebert1 Oct 19, 2026
1493b2f
global-uki-addons: Staging fixes
Johan-Liebert1 Oct 21, 2026
b46272e
gc: Take live addons into account
Johan-Liebert1 Oct 27, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions contrib/packaging/finalize-uki
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,17 @@ if [[ -f "${uki_src}/${kver}.dump" ]]; then
cp "${uki_src}/${kver}.dump" /boot
fi

# If we have a UKI Addon dir, add it
if [[ -d "${uki_src}/${kver}.efi.extra.d" ]]; then
cp -r "${uki_src}/${kver}.efi.extra.d" /boot/EFI/Linux
fi

# If we have a global UKI Addon dir, add it
if [[ -d "${uki_src}/loader/addons" ]]; then
mkdir -p /boot/loader
cp -r "${uki_src}/loader/addons" /boot/loader
fi

# NOTE: We used to create a symlink from /usr/lib/modules/${kver}/${kver}.efi to the UKI
# for tooling compatibility. However, composefs-boot's find_uki_components() doesn't
# handle symlinks correctly and fails with "is not a regular file". The UKI is already
Expand Down
527 changes: 411 additions & 116 deletions crates/lib/src/bootc_composefs/boot.rs

Large diffs are not rendered by default.

10 changes: 9 additions & 1 deletion crates/lib/src/bootc_composefs/delete.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use cap_std_ext::{cap_std::fs::Dir, dirext::CapStdExtDirExt};
use crate::{
bootc_composefs::{
aboot,
boot::{BootType, get_efi_uuid_source},
boot::{BootType, STAGED_GLOBAL_UKI_ADDONS_DIR, get_efi_uuid_source},
gc::{GCOpts, composefs_gc},
rollback::{composefs_rollback, rename_exchange_user_cfg},
state::remove_staged_deployment,
Expand Down Expand Up @@ -270,6 +270,14 @@ pub(crate) async fn delete_composefs_deployment(
}
} else {
delete_depl_boot_entries(&depl_to_del, &storage, deleting_staged)?;

if deleting_staged {
let esp = storage.require_esp()?;

esp.fd
.remove_all_optional(STAGED_GLOBAL_UKI_ADDONS_DIR)
.context("Removing staged Global UKI Addons")?;
}
}

composefs_gc(
Expand Down
39 changes: 38 additions & 1 deletion crates/lib/src/bootc_composefs/finalize.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::{path::Path, process::Command};

use crate::bootc_composefs::boot::{GLOBAL_UKI_ADDONS_DIR, STAGED_GLOBAL_UKI_ADDONS_DIR};
use crate::bootc_composefs::gc::{GCOpts, composefs_gc};
use crate::bootc_composefs::rollback::{rename_exchange_bls_entries, rename_exchange_user_cfg};
use crate::bootc_composefs::status::get_composefs_status;
Expand All @@ -16,7 +17,7 @@ use cap_std_ext::dirext::CapStdExtDirExt;
use composefs::generic_tree::{FileSystem, Stat};
use composefs_ctl::composefs;
use etc_merge::{Diff, compute_diff, merge, traverse_etc};
use rustix::fs::{Mode, OFlags, fsync};
use rustix::fs::{Mode, OFlags, RenameFlags, fsync, renameat, renameat_with};

use fn_error_context::context;

Expand Down Expand Up @@ -154,6 +155,42 @@ pub(crate) async fn composefs_backend_finalize(
);
}

let esp = storage.require_esp()?;

// Un-stage Global UKI Addons (if present) as the penultimate step
if esp.fd.exists(STAGED_GLOBAL_UKI_ADDONS_DIR) {
if esp.fd.exists(GLOBAL_UKI_ADDONS_DIR) {
tracing::debug!(
"Atomically exchanging {STAGED_GLOBAL_UKI_ADDONS_DIR} and {GLOBAL_UKI_ADDONS_DIR}"
);

renameat_with(
&esp.fd,
STAGED_GLOBAL_UKI_ADDONS_DIR,
&esp.fd,
GLOBAL_UKI_ADDONS_DIR,
RenameFlags::EXCHANGE,
)
.context("Atomically exchanging staged Global UKI Addons")?;

esp.fd
.remove_dir_all(STAGED_GLOBAL_UKI_ADDONS_DIR)
.context("Removing staged Global UKI Addons dir")?;
} else {
tracing::debug!(
"No global addons in the current deployment. Finalizing global UKI Addons"
);

renameat(
&esp.fd,
STAGED_GLOBAL_UKI_ADDONS_DIR,
&esp.fd,
GLOBAL_UKI_ADDONS_DIR,
)
.context("Finalizing global UKI Addons")?;
}
}

let boot_dir = storage.require_boot_dir()?;

match booted_composefs.bootloader.kind()? {
Expand Down
Loading
Loading