Skip to content

Commit 6a57c72

Browse files
authored
feat(boot): introduce sort keys, which are sorted in reverse order, to make boot order more configurable (#55)
1 parent d50f22a commit 6a57c72

File tree

6 files changed

+40
-6
lines changed

6 files changed

+40
-6
lines changed

crates/boot/src/autoconfigure/linux.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
use crate::utils;
2-
use crate::utils::vercmp;
32
use alloc::collections::BTreeMap;
43
use alloc::string::{String, ToString};
54
use alloc::vec::Vec;
@@ -186,17 +185,15 @@ pub fn scan(
186185
return Ok(false);
187186
}
188187

189-
// Sort the kernel pairs by kernel version, if it has one, newer kernels first.
190-
pairs.sort_by(|a, b| vercmp::compare_versions(&a.kernel, &b.kernel).reverse());
191-
192188
// Generate a unique name for the linux chainload action.
193-
let chainload_action_name = format!("{}{}", LINUX_CHAINLOAD_ACTION_PREFIX, root_unique_hash,);
189+
let chainload_action_name = format!("{}{}", LINUX_CHAINLOAD_ACTION_PREFIX, root_unique_hash);
194190

195191
// Kernel pairs are detected, generate a list configuration for it.
196192
let generator = ListConfiguration {
197193
entry: EntryDeclaration {
198194
title: "Boot Linux $name".to_string(),
199195
actions: vec![chainload_action_name.clone()],
196+
sort_key: Some("$kernel".to_string()),
200197
..Default::default()
201198
},
202199
values: pairs

crates/boot/src/autoconfigure/windows.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,14 @@ pub fn scan(
5151
let chainload_action_name = format!("{}{}", WINDOWS_CHAINLOAD_ACTION_PREFIX, root_unique_hash,);
5252

5353
// Generate an entry name for Windows.
54-
let entry_name = format!("auto-windows-{}", root_unique_hash,);
54+
let entry_name = format!("auto-windows-{}", root_unique_hash);
5555

5656
// Create an entry for Windows and insert it into the configuration.
5757
let entry = EntryDeclaration {
5858
title: "Boot Windows".to_string(),
5959
actions: vec![chainload_action_name.clone()],
6060
values: Default::default(),
61+
sort_key: None, // Use the default sort key.
6162
};
6263
config.entries.insert(entry_name, entry);
6364

crates/boot/src/entries.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ pub struct BootableEntry {
1212
declaration: EntryDeclaration,
1313
default: bool,
1414
pin_name: bool,
15+
sort_key: Option<String>,
1516
}
1617

1718
impl BootableEntry {
@@ -29,6 +30,7 @@ impl BootableEntry {
2930
declaration,
3031
default: false,
3132
pin_name: false,
33+
sort_key: None,
3234
}
3335
}
3436

@@ -107,6 +109,22 @@ impl BootableEntry {
107109
self.name == needle || self.title == needle
108110
}
109111

112+
/// Set the sort key of the entry. This is used to sort entries via version comparison.
113+
pub fn set_sort_key(&mut self, sort_key: String) {
114+
self.sort_key = Some(sort_key);
115+
}
116+
117+
/// Retrieve a reference to the sort key of the entry. If one is not specified, we will use the
118+
/// name of the entry.
119+
pub fn sort_key(&self) -> &str {
120+
// Use the sort key specified in the bootable entry, or use the declaration sort key,
121+
// or use the name of the entry.
122+
self.sort_key
123+
.as_deref()
124+
.or(self.declaration.sort_key.as_deref())
125+
.unwrap_or(&self.name)
126+
}
127+
110128
/// Find an entry by `needle` inside the entry iterator `haystack`.
111129
/// This will search for an entry by name, title, or index.
112130
pub fn find<'a>(

crates/boot/src/generators/bls.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,16 @@ pub fn generate(context: Rc<SproutContext>, bls: &BlsConfiguration) -> Result<Ve
206206
// Sort all the entries according to the BLS sort system.
207207
entries.sort_by(sort_entries);
208208

209+
// Grab the number of entries that we have, so we can calculate a reverse index.
210+
let entry_count = entries.len();
211+
212+
// Set the sort keys of all the bootable entries to a semi-unique prefix + the BLS sort order.
213+
// The final comparison happens using version comparison, so this will sort
214+
// things properly.
215+
for (idx, (_bls, boot)) in entries.iter_mut().enumerate() {
216+
boot.set_sort_key(format!("bls-{}-{}", path, entry_count - idx - 1));
217+
}
218+
209219
// Collect all the bootable entries and return them.
210220
Ok(entries.into_iter().map(|(_, boot)| boot).collect())
211221
}

crates/boot/src/main.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use crate::context::{RootContext, SproutContext};
77
use crate::entries::BootableEntry;
88
use crate::options::SproutOptions;
99
use crate::phases::phase;
10+
use crate::utils::vercmp::compare_versions;
1011
use alloc::collections::BTreeMap;
1112
use alloc::format;
1213
use alloc::string::ToString;
@@ -257,6 +258,10 @@ fn run() -> Result<()> {
257258
}
258259
}
259260

261+
// Sort the entries by their sort key, finalizing the order to show entries. This happens
262+
// in reverse order so that entries that would come last show up first in the menu.
263+
entries.sort_by(|a, b| compare_versions(a.sort_key(), b.sort_key()).reverse());
264+
260265
// Tell the bootloader interface what entries are available.
261266
BootloaderInterface::set_entries(entries.iter().map(|entry| entry.name()))
262267
.context("unable to set entries in bootloader interface")?;

crates/config/src/entries.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,7 @@ pub struct EntryDeclaration {
1818
/// The values to insert into the context when the entry is selected.
1919
#[serde(default)]
2020
pub values: BTreeMap<String, String>,
21+
/// The key to sort entries, via version comparison.
22+
#[serde(default, rename = "sort-key")]
23+
pub sort_key: Option<String>,
2124
}

0 commit comments

Comments
 (0)