mirror of
https://github.com/edera-dev/sprout.git
synced 2026-11-04 19:52:22 +00:00
feat(bls): boot counting (#107)
* feat(bls): parse and render boot counters * feat(bls): sort entries with no boot tries left last * feat(boot): strip boot counters from bls entry ids * feat(boot): consume bls boot counter tries before booting * fix(boot): never default to a bad boot counter entry while a good one exists
This commit is contained in:
5 files changed
+398
-7
No files matched your search
+32
-5
@@ -36,6 +36,9 @@ pub mod actions;
|
||||
/// autoconfigure: Autoconfigure Sprout based on the detected environment.
|
||||
pub mod autoconfigure;
|
||||
|
||||
/// boot_counter: Consume the boot counter tries of BLS entries.
|
||||
pub mod boot_counter;
|
||||
|
||||
/// config: Sprout configuration mechanism.
|
||||
pub mod config;
|
||||
|
||||
@@ -407,11 +410,20 @@ fn run() -> Result<()> {
|
||||
force_boot_entry = Some(bootloader_interface_oneshot_entry.clone());
|
||||
}
|
||||
|
||||
// If no entries were the default, pick the first entry as the default entry.
|
||||
if entries.iter().all(|entry| !entry.is_default())
|
||||
&& let Some(entry) = entries.first_mut()
|
||||
{
|
||||
entry.mark_default();
|
||||
// Entries that have no boot counter tries left are never picked automatically.
|
||||
// If no entries are the default, pick the first usable entry as the default entry.
|
||||
let default_flags = edera_sprout_bls::resolve_default_flags(
|
||||
&entries
|
||||
.iter()
|
||||
.map(|entry| (entry.is_default(), entry.is_bad()))
|
||||
.collect::<Vec<_>>(),
|
||||
);
|
||||
for (entry, default) in entries.iter_mut().zip(default_flags) {
|
||||
if default {
|
||||
entry.mark_default();
|
||||
} else {
|
||||
entry.unmark_default();
|
||||
}
|
||||
}
|
||||
|
||||
// Convert the menu timeout to a duration.
|
||||
@@ -465,6 +477,21 @@ fn run() -> Result<()> {
|
||||
// Execute the late phase, now that the entry is chosen but before its actions are executed.
|
||||
phase(context.clone(), &config.phases.late).context("unable to execute late phase")?;
|
||||
|
||||
// Consume a try from the boot counter of the selected entry.
|
||||
// Failing to do so must not prevent the entry from booting.
|
||||
if let Some(target) = entry.boot_counter()
|
||||
&& !target.counter.is_bad()
|
||||
{
|
||||
match target.consume() {
|
||||
Ok(path) => info!("updated boot counter of entry {}: {}", entry.name(), path),
|
||||
Err(error) => warn!(
|
||||
"unable to update boot counter of entry {}: {:#}",
|
||||
entry.name(),
|
||||
error
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
// Execute all the actions for the selected entry.
|
||||
for action in &entry.declaration().actions {
|
||||
let action = entry.context().stamp(action);
|
||||
|
||||
Reference in new issue
Block a user