Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
7 changes: 2 additions & 5 deletions crates/boot/src/autoconfigure/linux.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use crate::utils;
use crate::utils::vercmp;
use alloc::collections::BTreeMap;
use alloc::string::{String, ToString};
use alloc::vec::Vec;
Expand Down Expand Up @@ -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
Expand Down
3 changes: 2 additions & 1 deletion crates/boot/src/autoconfigure/windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
18 changes: 18 additions & 0 deletions crates/boot/src/entries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ pub struct BootableEntry {
declaration: EntryDeclaration,
default: bool,
pin_name: bool,
sort_key: Option<String>,
}

impl BootableEntry {
Expand All @@ -29,6 +30,7 @@ impl BootableEntry {
declaration,
default: false,
pin_name: false,
sort_key: None,
}
}

Expand Down Expand Up @@ -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>(
Expand Down
10 changes: 10 additions & 0 deletions crates/boot/src/generators/bls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,16 @@ pub fn generate(context: Rc<SproutContext>, bls: &BlsConfiguration) -> Result<Ve
// Sort all the entries according to the BLS sort system.
entries.sort_by(sort_entries);

// Grab the number of entries that we have, so we can calculate a reverse index.
let entry_count = entries.len();

// Set the sort keys of all the bootable entries to a semi-unique prefix + the BLS sort order.
// The final comparison happens using version comparison, so this will sort
// things properly.
for (idx, (_bls, boot)) in entries.iter_mut().enumerate() {
boot.set_sort_key(format!("bls-{}-{}", path, entry_count - idx - 1));
}

// Collect all the bootable entries and return them.
Ok(entries.into_iter().map(|(_, boot)| boot).collect())
}
5 changes: 5 additions & 0 deletions crates/boot/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use crate::context::{RootContext, SproutContext};
use crate::entries::BootableEntry;
use crate::options::SproutOptions;
use crate::phases::phase;
use crate::utils::vercmp::compare_versions;
use alloc::collections::BTreeMap;
use alloc::format;
use alloc::string::ToString;
Expand Down Expand Up @@ -257,6 +258,10 @@ fn run() -> 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")?;
Expand Down
3 changes: 3 additions & 0 deletions crates/config/src/entries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,7 @@ pub struct EntryDeclaration {
/// The values to insert into the context when the entry is selected.
#[serde(default)]
pub values: BTreeMap<String, String>,
/// The key to sort entries, via version comparison.
#[serde(default, rename = "sort-key")]
pub sort_key: Option<String>,
}
Loading