@@ -26,8 +26,7 @@ use ostree_ext::tokio_util::spawn_blocking_cancellable_flatten;
2626use rustix:: fs:: { fsync, renameat_with, AtFlags , RenameFlags } ;
2727
2828use crate :: composefs_consts:: {
29- BOOT_LOADER_ENTRIES , ROLLBACK_BOOT_LOADER_ENTRIES , USER_CFG ,
30- USER_CFG_ROLLBACK ,
29+ BOOT_LOADER_ENTRIES , ROLLBACK_BOOT_LOADER_ENTRIES , USER_CFG , USER_CFG_ROLLBACK ,
3130} ;
3231use crate :: install:: { get_efi_uuid_source, BootType } ;
3332use crate :: parsers:: bls_config:: { parse_bls_config, BLSConfig } ;
@@ -1189,6 +1188,10 @@ pub(crate) fn fixup_etc_fstab(root: &Dir) -> Result<()> {
11891188
11901189#[ cfg( test) ]
11911190mod tests {
1191+ use std:: collections:: HashMap ;
1192+
1193+ use crate :: parsers:: grub_menuconfig:: MenuentryBody ;
1194+
11921195 use super :: * ;
11931196
11941197 #[ test]
@@ -1283,4 +1286,119 @@ UUID=6907-17CA /boot/efi vfat umask=0077,shortname=win
12831286 assert_eq ! ( tempdir. read_to_string( "etc/fstab" ) ?, modified) ;
12841287 Ok ( ( ) )
12851288 }
1289+
1290+ #[ test]
1291+ fn test_sorted_bls_boot_entries ( ) -> Result < ( ) > {
1292+ let tempdir = cap_std_ext:: cap_tempfile:: tempdir ( cap_std:: ambient_authority ( ) ) ?;
1293+
1294+ let entry1 = r#"
1295+ title Fedora 42.20250623.3.1 (CoreOS)
1296+ version 1
1297+ linux /boot/7e11ac46e3e022053e7226a20104ac656bf72d1a84e3a398b7cce70e9df188b6/vmlinuz-5.14.10
1298+ initrd /boot/7e11ac46e3e022053e7226a20104ac656bf72d1a84e3a398b7cce70e9df188b6/initramfs-5.14.10.img
1299+ options root=UUID=abc123 rw composefs=7e11ac46e3e022053e7226a20104ac656bf72d1a84e3a398b7cce70e9df188b6
1300+ "# ;
1301+
1302+ let entry2 = r#"
1303+ title Fedora 41.20250214.2.0 (CoreOS)
1304+ version 2
1305+ linux /boot/febdf62805de2ae7b6b597f2a9775d9c8a753ba1e5f09298fc8fbe0b0d13bf01/vmlinuz-5.14.10
1306+ initrd /boot/febdf62805de2ae7b6b597f2a9775d9c8a753ba1e5f09298fc8fbe0b0d13bf01/initramfs-5.14.10.img
1307+ options root=UUID=abc123 rw composefs=febdf62805de2ae7b6b597f2a9775d9c8a753ba1e5f09298fc8fbe0b0d13bf01
1308+ "# ;
1309+
1310+ tempdir. create_dir_all ( "loader/entries" ) ?;
1311+ tempdir. atomic_write (
1312+ "loader/entries/random_file.txt" ,
1313+ "Random file that we won't parse" ,
1314+ ) ?;
1315+ tempdir. atomic_write ( "loader/entries/entry1.conf" , entry1) ?;
1316+ tempdir. atomic_write ( "loader/entries/entry2.conf" , entry2) ?;
1317+
1318+ let result = get_sorted_bls_boot_entries ( & tempdir, true ) ;
1319+
1320+ let mut expected = vec ! [
1321+ BLSConfig {
1322+ title: Some ( "Fedora 42.20250623.3.1 (CoreOS)" . into( ) ) ,
1323+ version: 1 ,
1324+ linux: "/boot/7e11ac46e3e022053e7226a20104ac656bf72d1a84e3a398b7cce70e9df188b6/vmlinuz-5.14.10" . into( ) ,
1325+ initrd: "/boot/7e11ac46e3e022053e7226a20104ac656bf72d1a84e3a398b7cce70e9df188b6/initramfs-5.14.10.img" . into( ) ,
1326+ options: "root=UUID=abc123 rw composefs=7e11ac46e3e022053e7226a20104ac656bf72d1a84e3a398b7cce70e9df188b6" . into( ) ,
1327+ extra: HashMap :: new( ) ,
1328+ } ,
1329+ BLSConfig {
1330+ title: Some ( "Fedora 41.20250214.2.0 (CoreOS)" . into( ) ) ,
1331+ version: 2 ,
1332+ linux: "/boot/febdf62805de2ae7b6b597f2a9775d9c8a753ba1e5f09298fc8fbe0b0d13bf01/vmlinuz-5.14.10" . into( ) ,
1333+ initrd: "/boot/febdf62805de2ae7b6b597f2a9775d9c8a753ba1e5f09298fc8fbe0b0d13bf01/initramfs-5.14.10.img" . into( ) ,
1334+ options: "root=UUID=abc123 rw composefs=febdf62805de2ae7b6b597f2a9775d9c8a753ba1e5f09298fc8fbe0b0d13bf01" . into( ) ,
1335+ extra: HashMap :: new( ) ,
1336+ } ,
1337+ ] ;
1338+
1339+ assert_eq ! ( result. unwrap( ) , expected) ;
1340+
1341+ let result = get_sorted_bls_boot_entries ( & tempdir, false ) ;
1342+ expected. reverse ( ) ;
1343+ assert_eq ! ( result. unwrap( ) , expected) ;
1344+
1345+ Ok ( ( ) )
1346+ }
1347+
1348+ #[ test]
1349+ fn test_sorted_uki_boot_entries ( ) -> Result < ( ) > {
1350+ let user_cfg = r#"
1351+ if [ -f ${config_directory}/efiuuid.cfg ]; then
1352+ source ${config_directory}/efiuuid.cfg
1353+ fi
1354+
1355+ menuentry "Fedora Bootc UKI: (f7415d75017a12a387a39d2281e033a288fc15775108250ef70a01dcadb93346)" {
1356+ insmod fat
1357+ insmod chain
1358+ search --no-floppy --set=root --fs-uuid "${EFI_PART_UUID}"
1359+ chainloader /EFI/Linux/f7415d75017a12a387a39d2281e033a288fc15775108250ef70a01dcadb93346.efi
1360+ }
1361+
1362+ menuentry "Fedora Bootc UKI: (7e11ac46e3e022053e7226a20104ac656bf72d1a84e3a398b7cce70e9df188b6)" {
1363+ insmod fat
1364+ insmod chain
1365+ search --no-floppy --set=root --fs-uuid "${EFI_PART_UUID}"
1366+ chainloader /EFI/Linux/7e11ac46e3e022053e7226a20104ac656bf72d1a84e3a398b7cce70e9df188b6.efi
1367+ }
1368+ "# ;
1369+
1370+ let bootdir = cap_std_ext:: cap_tempfile:: tempdir ( cap_std:: ambient_authority ( ) ) ?;
1371+ bootdir. create_dir_all ( format ! ( "grub2" ) ) ?;
1372+ bootdir. atomic_write ( format ! ( "grub2/{USER_CFG}" ) , user_cfg) ?;
1373+
1374+ let mut s = String :: new ( ) ;
1375+ let result = get_sorted_uki_boot_entries ( & bootdir, & mut s) ?;
1376+
1377+ let expected = vec ! [
1378+ MenuEntry {
1379+ title: "Fedora Bootc UKI: (f7415d75017a12a387a39d2281e033a288fc15775108250ef70a01dcadb93346)" . into( ) ,
1380+ body: MenuentryBody {
1381+ insmod: vec![ "fat" , "chain" ] ,
1382+ chainloader: "/EFI/Linux/f7415d75017a12a387a39d2281e033a288fc15775108250ef70a01dcadb93346.efi" . into( ) ,
1383+ search: "--no-floppy --set=root --fs-uuid \" ${EFI_PART_UUID}\" " ,
1384+ version: 0 ,
1385+ extra: vec![ ] ,
1386+ } ,
1387+ } ,
1388+ MenuEntry {
1389+ title: "Fedora Bootc UKI: (7e11ac46e3e022053e7226a20104ac656bf72d1a84e3a398b7cce70e9df188b6)" . into( ) ,
1390+ body: MenuentryBody {
1391+ insmod: vec![ "fat" , "chain" ] ,
1392+ chainloader: "/EFI/Linux/7e11ac46e3e022053e7226a20104ac656bf72d1a84e3a398b7cce70e9df188b6.efi" . into( ) ,
1393+ search: "--no-floppy --set=root --fs-uuid \" ${EFI_PART_UUID}\" " ,
1394+ version: 0 ,
1395+ extra: vec![ ] ,
1396+ } ,
1397+ } ,
1398+ ] ;
1399+
1400+ assert_eq ! ( result, expected) ;
1401+
1402+ Ok ( ( ) )
1403+ }
12861404}
0 commit comments