boot: case fold Type #2 entry IDs with boot counter or profile ID

config_find_entry() matches the case folded patterns from loader.conf and
the LoaderEntry* EFI variables against entry IDs with the case sensitive
efi_fnmatch(), relying on the IDs being lower case already. Type #1
entries fold their ID after the boot counter has been parsed, but Type #2
entries only did so when the file name carried no boot counter, because
boot_entry_parse_tries() rebuilds the ID from the original file name. The
ID of a secondary UKI profile was not folded either, as the profile ID
from the .profile section is appended verbatim.

Hence a UKI like EFI/Linux/Foo+3.efi, or a profile with ID=Profile1,
could never be selected via default, preferred, @saved, bootctl
set-default or systemctl reboot --boot-loader-entry=, while bootctl
(which matches case insensitively) claimed that it was the default.

Fold the ID unconditionally, like Type #1 entries do, and fold the
profile suffix as well. The file names used for renaming the boot
counter keep their case.

Follow-up for 4301ad00ef and
941b91600c.

(cherry picked from commit 1402519771a45745de3f6b7e93d08d7c96d3d65b)
This commit is contained in:
Florian Franzen
2026-10-16 17:24:51 +01:00
committed by Luca Boccassi
parent 3e95f9bf08
commit 2f53f23355
+5 -2
View File
@@ -2493,14 +2493,17 @@ static void boot_entry_add_type2(
/* If the filename had no tries suffixes then the id won't be set by the above call, do it now */
if (!entry->id)
entry->id = strtolower16(xstrdup16(filename));
entry->id = xstrdup16(filename);
/* Patterns are case folded before matching, hence IDs must be too. */
strtolower16(entry->id);
/* Ensure the secondary profiles IDs also have the tries suffix stripped, to match the primary */
if (profile > 0) {
entry->id_without_profile = TAKE_PTR(entry->id);
if (profile_id)
entry->id = xasprintf("%ls@%ls", entry->id_without_profile, profile_id);
entry->id = strtolower16(xasprintf("%ls@%ls", entry->id_without_profile, profile_id));
else
entry->id = xasprintf("%ls@%u", entry->id_without_profile, profile);