feat(bls): one entry for each profile of a unified kernel image

A unified kernel image can have several profiles, each started by a
.profile section and made of the sections after it on top of the base.
Every profile is an entry. The first has the id of the file, and the
others add @ and the identifier or the number of the profile, with a
title that names the profile and the profile number as the load options.
The profiles share the boot counter of the file, sort in the order they
are in the image, and a profile after the first is not picked as the
default entry when no default was asked for.

The PE reader keeps every section in order, so repeated names and the
sections that a profile removes can be told apart, and reads images with
more than 96 sections.
This commit is contained in:
alex authored and Alex Zenla committed 2026-10-03 20:23:57 -07:00
1 parent ac49899294
commit 50f62f5bb6
7 files changed
+628 -86

No files matched your search

+31 -1
View File
@@ -3,6 +3,7 @@ use crate::context::SproutContext;
use alloc::format;
use alloc::rc::Rc;
use alloc::string::{String, ToString};
use edera_sprout_bls::profile_entry_id;
use edera_sprout_config::entries::EntryDeclaration;
use edera_sprout_parsing::{fnmatch_ignore_case, glob_match};
@@ -18,6 +19,7 @@ pub struct BootableEntry {
sort_key: Option<String>,
boot_counter: Option<BootCounterTarget>,
id_suffix: Option<String>,
id_profile: Option<String>,
}
impl BootableEntry {
@@ -38,6 +40,7 @@ impl BootableEntry {
sort_key: None,
boot_counter: None,
id_suffix: None,
id_profile: None,
}
}
@@ -51,11 +54,38 @@ impl BootableEntry {
/// `fedora.conf`, in lower case. Any other entry has its name as the id.
pub fn id(&self) -> String {
match self.id_suffix {
Some(ref suffix) => format!("{}{}", self.name, suffix).to_lowercase(),
Some(ref suffix) => {
let file = format!("{}{}", self.sort_name(), suffix);
profile_entry_id(&file, self.id_profile.as_deref())
}
None => self.name.clone(),
}
}
/// Fetch the name of the entry without the profile of a unified kernel image, which is
/// the same for every profile of the same image.
pub fn sort_name(&self) -> &str {
self.id_profile
.as_deref()
.and_then(|profile| {
self.name
.strip_suffix(profile)
.and_then(|name| name.strip_suffix('@'))
})
.unwrap_or(&self.name)
}
/// Fetch whether the entry is a profile of a unified kernel image after the first, which
/// is never picked as the default entry unless it was asked for.
pub fn is_extra_profile(&self) -> bool {
self.id_profile.is_some()
}
/// Set the profile of a unified kernel image that is part of the id of this entry.
pub fn set_id_profile(&mut self, profile: &str) {
self.id_profile = Some(profile.to_string());
}
/// Set the file extension that is part of the id of this entry, such as `.conf`.
pub fn set_id_suffix(&mut self, suffix: &str) {
self.id_suffix = Some(suffix.to_string());