Skip to content

feature: Support UKI-specific Addons#516

Open
frhuelsz wants to merge 3 commits intomainfrom
user/frhuelsz/uki-addons
Open

feature: Support UKI-specific Addons#516
frhuelsz wants to merge 3 commits intomainfrom
user/frhuelsz/uki-addons

Conversation

@frhuelsz
Copy link
Contributor

@frhuelsz frhuelsz commented Feb 14, 2026

🔍 Description

Scan for matching addon directories and copy artifacts as needed.

TODO: cleanup old addon dirs when the corresponding UKI is removed.

Copilot AI review requested due to automatic review settings February 14, 2026 01:42
@frhuelsz frhuelsz requested a review from a team as a code owner February 14, 2026 01:42
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds support for UKI addons by detecting a per-UKI addon directory in the source image and staging addon artifacts onto the ESP alongside the staged UKI, with follow-up renaming during boot order update.

Changes:

  • Detect <UKI filename>.extra.d/ in the source image and copy addon artifacts to the ESP during UKI staging.
  • Introduce naming constants for addon directories/files and extend staging logic to ignore non-matching entries.
  • Attempt to rename a staged addon directory when renaming the staged UKI to its final name.

Comment on lines 206 to 207
}
}
Copy link

Copilot AI Feb 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Issue: When updating/replacing an existing UKI for the same uki_suffix, the function removes only the UKI file but does not remove the associated addon directory (<UKI filename>.extra.d). This can leave stale addon artifacts on the ESP across updates.

Evidence: In the for (index, suffix, path) in existing_ukis { if suffix == uki_suffix { ... fs::remove_file(&path) ... } } block earlier in this function, there is no corresponding cleanup of path + .extra.d.

Suggestion: When deleting an old UKI file for the same suffix, also delete its addon directory if present (e.g., remove_dir_all on <old_uki_path>.extra.d).

Copilot uses AI. Check for mistakes.
Comment on lines 114 to 120
if !path.ends_with(UKI_ADDON_FILE_SUFFIX) {
trace!(
"Ignoring file '{}' in addon directory that does not match expected naming scheme",
path.display()
);
continue;
}
Copy link

Copilot AI Feb 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Issue: Path::ends_with(UKI_ADDON_FILE_SUFFIX) checks whether the path ends with a path component, not whether the file name ends with a string suffix. For an addon file like foo.addon.efi, this condition will be false and the file will be incorrectly skipped (only a file literally named .addon.efi would match).

Evidence: The addon filter uses if !path.ends_with(UKI_ADDON_FILE_SUFFIX) { ... continue; }.

Suggestion: Perform the suffix check on the file name string (e.g., path.file_name() -> string -> .ends_with(UKI_ADDON_FILE_SUFFIX)) rather than using Path::ends_with.

Copilot uses AI. Check for mistakes.
@frhuelsz frhuelsz changed the title feature: Support UKI Addons feature: Support UKI-specific Addons Feb 14, 2026

/// Enumerates preexisting UKIs unmanaged by Trident (defined by naming convention: vmlinuz-6.6.117.1-1.azl3.efi)
/// in the given directory, returning their versions and paths.
fn enumerate_non_trident_managed_ukis(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i imagine we'd need to watch for the add-on folder here too?

@bfjelds
Copy link
Member

bfjelds commented Feb 14, 2026

maybe copy_boot_files_for_uefi_fallback needs to copy the add-on folder in addition to just files?

Copilot AI review requested due to automatic review settings February 14, 2026 20:06
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 2 comments.

Comment on lines +254 to +261
let addon_dir = uki_addon_dir(&path);
if addon_dir.exists() && addon_dir.is_dir() {
fs::remove_dir_all(&addon_dir)
.with_context(|| {
format!("Failed to remove addon directory '{}'", addon_dir.display())
})
.structured(ServicingError::UpdateUki)?;
}
Copy link

Copilot AI Feb 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR description mentions "TODO: cleanup old addon dirs when the corresponding UKI is removed." However, this functionality is already implemented in the code at lines 254-261, where addon directories are removed when their corresponding UKI files are removed. Consider updating the PR description to reflect that this TODO has been completed, or clarify if there's additional cleanup work still needed.

Copilot uses AI. Check for mistakes.
Comment on lines +114 to +150
fs::create_dir_all(&dest_addon_dir).context("Failed to create destination addon directory")?;

// Copy all files from the source addon directory to the destination addon
// directory. We expect these to be files with names ending in `.addon.efi`.
for entry in fs::read_dir(&addon_dir).context("Failed to read addon directory")? {
let entry = entry.context("Failed to read entry in addon directory")?;
let path = entry.path();
if !path.is_file() {
trace!(
"Ignoring non-file entry '{}' in addon directory",
path.display()
);
continue;
}

if !path
.as_os_str()
.as_encoded_bytes()
.ends_with(UKI_ADDON_FILE_SUFFIX.as_bytes())
{
trace!(
"Ignoring file '{}' in addon directory that does not end with expected suffix '{UKI_ADDON_FILE_SUFFIX}'",
path.display(),
);
continue;
}

let dest_addon_file =
dest_addon_dir.join(path.file_name().context("Failed to get addon file name")?);

debug!(
"Staging UKI addon file from '{}' to '{}'",
path.display(),
dest_addon_file.display()
);
fs::copy(&path, &dest_addon_file).context("Failed to copy addon file")?;
}
Copy link

Copilot AI Feb 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When an addon directory exists but contains no valid .addon.efi files, an empty destination addon directory is created and left on the ESP. Consider whether this is the desired behavior. If not, you could track whether any files were actually copied and remove the empty directory if none were found.

This is a minor edge case that may not matter in practice, but it could lead to empty directories accumulating on the ESP over time if images are built with empty addon directories.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants