fix(bls): write boot counters systemd can read and match systemd on small details

Do not pad the boot counter digits or cap the tries done counter, as
systemd-bless-boot reads a counter with a leading zero as octal and
systemd-boot never writes one. A profile only selects a profile when it
is a number above zero, an unterminated bracket in a pattern matches
nothing, and files that start with auto- are ignored in any case and for
unified kernel images too. The saved entry is compared ignoring case, and
entry settings are only expanded for sources that are looked at.
This commit is contained in:
alex authored and Alex Zenla committed 2026-10-03 19:41:39 -07:00
1 parent 8bb5f1132d
commit 14bcfc2653
4 files changed
+78 -66

No files matched your search

+5 -2
View File
@@ -9,7 +9,7 @@ use alloc::{
};
use anyhow::{Context, Result};
use core::{cmp::Ordering, str::FromStr};
use edera_sprout_bls::{BlsEntry, BootCounter, sort_bls, strip_extension};
use edera_sprout_bls::{BlsEntry, BootCounter, is_reserved_entry_name, sort_bls, strip_extension};
use edera_sprout_config::generators::bls::BlsConfiguration;
use log::{info, warn};
use uefi::{
@@ -187,7 +187,7 @@ fn generate_type1(
continue;
}
// Names that start with auto- are reserved for entries the boot loader makes itself.
if file_name.starts_with("auto-") {
if is_reserved_entry_name(&file_name) {
continue;
}
let extension = extension.to_string();
@@ -315,6 +315,9 @@ fn generate_type2(
// The id is the file name without the extension and the boot counter.
let file_name = image.file_name;
if is_reserved_entry_name(&file_name) {
continue;
}
let Some((stem, extension)) = strip_extension(&file_name, ".efi") else {
continue;
};
+11 -6
View File
@@ -477,7 +477,7 @@ fn run() -> Result<()> {
// no entry, such as when the entry was removed, is ignored so that the next source is used.
// The preferred entry sources never use an entry with no boot counter tries left.
// Each source has whether it matches by id, and whether it skips bad entries.
for (source, pattern, by_id, skip_bad) in [
for (source, value, by_id, skip_bad) in [
(
"configuration",
config.options.default_entry.clone(),
@@ -486,29 +486,31 @@ fn run() -> Result<()> {
),
(
"bootloader interface preferred",
entry_pattern(bootloader_interface_preferred_entry),
bootloader_interface_preferred_entry.clone(),
true,
true,
),
(
"loader.conf preferred",
entry_pattern(loader_conf.preferred.clone()),
loader_conf.preferred.clone(),
true,
true,
),
(
"bootloader interface default",
entry_pattern(bootloader_interface_default_entry.clone()),
bootloader_interface_default_entry.clone(),
true,
false,
),
(
"loader.conf default",
entry_pattern(loader_conf.default.clone()),
loader_conf.default.clone(),
true,
false,
),
] {
// The configuration is a pattern as it is. The other sources can be `@saved`.
let pattern = if by_id { entry_pattern(value) } else { value };
let Some(pattern) = pattern else {
continue;
};
@@ -618,7 +620,10 @@ fn run() -> Result<()> {
if forced_entry.is_none() {
let id = entry.id();
if use_saved_entry {
if last_booted_entry.as_deref() != Some(id.as_str()) {
if !last_booted_entry
.as_deref()
.is_some_and(|saved| saved.eq_ignore_ascii_case(&id))
{
advisory(
BootloaderInterface::set_last_booted_entry(&id)
.context("unable to save last booted entry in bootloader interface"),