diff --git a/crates/boot/src/autoconfigure/linux.rs b/crates/boot/src/autoconfigure/linux.rs index e7f3bc9..b15cb0d 100644 --- a/crates/boot/src/autoconfigure/linux.rs +++ b/crates/boot/src/autoconfigure/linux.rs @@ -1,5 +1,4 @@ use crate::utils; -use crate::utils::vercmp; use alloc::collections::BTreeMap; use alloc::string::{String, ToString}; use alloc::vec::Vec; @@ -186,17 +185,15 @@ pub fn scan( return Ok(false); } - // Sort the kernel pairs by kernel version, if it has one, newer kernels first. - pairs.sort_by(|a, b| vercmp::compare_versions(&a.kernel, &b.kernel).reverse()); - // Generate a unique name for the linux chainload action. - let chainload_action_name = format!("{}{}", LINUX_CHAINLOAD_ACTION_PREFIX, root_unique_hash,); + let chainload_action_name = format!("{}{}", LINUX_CHAINLOAD_ACTION_PREFIX, root_unique_hash); // Kernel pairs are detected, generate a list configuration for it. let generator = ListConfiguration { entry: EntryDeclaration { title: "Boot Linux $name".to_string(), actions: vec![chainload_action_name.clone()], + sort_key: Some("$kernel".to_string()), ..Default::default() }, values: pairs diff --git a/crates/boot/src/autoconfigure/windows.rs b/crates/boot/src/autoconfigure/windows.rs index bc954d4..93a015c 100644 --- a/crates/boot/src/autoconfigure/windows.rs +++ b/crates/boot/src/autoconfigure/windows.rs @@ -51,13 +51,14 @@ pub fn scan( let chainload_action_name = format!("{}{}", WINDOWS_CHAINLOAD_ACTION_PREFIX, root_unique_hash,); // Generate an entry name for Windows. - let entry_name = format!("auto-windows-{}", root_unique_hash,); + let entry_name = format!("auto-windows-{}", root_unique_hash); // Create an entry for Windows and insert it into the configuration. let entry = EntryDeclaration { title: "Boot Windows".to_string(), actions: vec![chainload_action_name.clone()], values: Default::default(), + sort_key: None, // Use the default sort key. }; config.entries.insert(entry_name, entry); diff --git a/crates/boot/src/entries.rs b/crates/boot/src/entries.rs index 352ef6d..903669e 100644 --- a/crates/boot/src/entries.rs +++ b/crates/boot/src/entries.rs @@ -12,6 +12,7 @@ pub struct BootableEntry { declaration: EntryDeclaration, default: bool, pin_name: bool, + sort_key: Option, } impl BootableEntry { @@ -29,6 +30,7 @@ impl BootableEntry { declaration, default: false, pin_name: false, + sort_key: None, } } @@ -107,6 +109,22 @@ impl BootableEntry { self.name == needle || self.title == needle } + /// Set the sort key of the entry. This is used to sort entries via version comparison. + pub fn set_sort_key(&mut self, sort_key: String) { + self.sort_key = Some(sort_key); + } + + /// Retrieve a reference to the sort key of the entry. If one is not specified, we will use the + /// name of the entry. + pub fn sort_key(&self) -> &str { + // Use the sort key specified in the bootable entry, or use the declaration sort key, + // or use the name of the entry. + self.sort_key + .as_deref() + .or(self.declaration.sort_key.as_deref()) + .unwrap_or(&self.name) + } + /// Find an entry by `needle` inside the entry iterator `haystack`. /// This will search for an entry by name, title, or index. pub fn find<'a>( diff --git a/crates/boot/src/generators/bls.rs b/crates/boot/src/generators/bls.rs index ebdf088..a5abd90 100644 --- a/crates/boot/src/generators/bls.rs +++ b/crates/boot/src/generators/bls.rs @@ -206,6 +206,16 @@ pub fn generate(context: Rc, bls: &BlsConfiguration) -> Result Result<()> { } } + // Sort the entries by their sort key, finalizing the order to show entries. This happens + // in reverse order so that entries that would come last show up first in the menu. + entries.sort_by(|a, b| compare_versions(a.sort_key(), b.sort_key()).reverse()); + // Tell the bootloader interface what entries are available. BootloaderInterface::set_entries(entries.iter().map(|entry| entry.name())) .context("unable to set entries in bootloader interface")?; diff --git a/crates/config/src/entries.rs b/crates/config/src/entries.rs index 61dbc23..a14fdb7 100644 --- a/crates/config/src/entries.rs +++ b/crates/config/src/entries.rs @@ -18,4 +18,7 @@ pub struct EntryDeclaration { /// The values to insert into the context when the entry is selected. #[serde(default)] pub values: BTreeMap, + /// The key to sort entries, via version comparison. + #[serde(default, rename = "sort-key")] + pub sort_key: Option, }