@@ -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 } ;
@@ -1183,6 +1182,10 @@ pub(crate) fn fixup_etc_fstab(root: &Dir) -> Result<()> {
11831182
11841183#[ cfg( test) ]
11851184mod tests {
1185+ use std:: collections:: HashMap ;
1186+
1187+ use crate :: parsers:: grub_menuconfig:: MenuentryBody ;
1188+
11861189 use super :: * ;
11871190
11881191 #[ test]
@@ -1277,4 +1280,119 @@ UUID=6907-17CA /boot/efi vfat umask=0077,shortname=win
12771280 assert_eq ! ( tempdir. read_to_string( "etc/fstab" ) ?, modified) ;
12781281 Ok ( ( ) )
12791282 }
1283+
1284+ #[ test]
1285+ fn test_sorted_bls_boot_entries ( ) -> Result < ( ) > {
1286+ let tempdir = cap_std_ext:: cap_tempfile:: tempdir ( cap_std:: ambient_authority ( ) ) ?;
1287+
1288+ let entry1 = r#"
1289+ title Fedora 42.20250623.3.1 (CoreOS)
1290+ version 1
1291+ linux /boot/7e11ac46e3e022053e7226a20104ac656bf72d1a84e3a398b7cce70e9df188b6/vmlinuz-5.14.10
1292+ initrd /boot/7e11ac46e3e022053e7226a20104ac656bf72d1a84e3a398b7cce70e9df188b6/initramfs-5.14.10.img
1293+ options root=UUID=abc123 rw composefs=7e11ac46e3e022053e7226a20104ac656bf72d1a84e3a398b7cce70e9df188b6
1294+ "# ;
1295+
1296+ let entry2 = r#"
1297+ title Fedora 41.20250214.2.0 (CoreOS)
1298+ version 2
1299+ linux /boot/febdf62805de2ae7b6b597f2a9775d9c8a753ba1e5f09298fc8fbe0b0d13bf01/vmlinuz-5.14.10
1300+ initrd /boot/febdf62805de2ae7b6b597f2a9775d9c8a753ba1e5f09298fc8fbe0b0d13bf01/initramfs-5.14.10.img
1301+ options root=UUID=abc123 rw composefs=febdf62805de2ae7b6b597f2a9775d9c8a753ba1e5f09298fc8fbe0b0d13bf01
1302+ "# ;
1303+
1304+ tempdir. create_dir_all ( "loader/entries" ) ?;
1305+ tempdir. atomic_write (
1306+ "loader/entries/random_file.txt" ,
1307+ "Random file that we won't parse" ,
1308+ ) ?;
1309+ tempdir. atomic_write ( "loader/entries/entry1.conf" , entry1) ?;
1310+ tempdir. atomic_write ( "loader/entries/entry2.conf" , entry2) ?;
1311+
1312+ let result = get_sorted_bls_boot_entries ( & tempdir, true ) ;
1313+
1314+ let mut expected = vec ! [
1315+ BLSConfig {
1316+ title: Some ( "Fedora 42.20250623.3.1 (CoreOS)" . into( ) ) ,
1317+ version: 1 ,
1318+ linux: "/boot/7e11ac46e3e022053e7226a20104ac656bf72d1a84e3a398b7cce70e9df188b6/vmlinuz-5.14.10" . into( ) ,
1319+ initrd: "/boot/7e11ac46e3e022053e7226a20104ac656bf72d1a84e3a398b7cce70e9df188b6/initramfs-5.14.10.img" . into( ) ,
1320+ options: "root=UUID=abc123 rw composefs=7e11ac46e3e022053e7226a20104ac656bf72d1a84e3a398b7cce70e9df188b6" . into( ) ,
1321+ extra: HashMap :: new( ) ,
1322+ } ,
1323+ BLSConfig {
1324+ title: Some ( "Fedora 41.20250214.2.0 (CoreOS)" . into( ) ) ,
1325+ version: 2 ,
1326+ linux: "/boot/febdf62805de2ae7b6b597f2a9775d9c8a753ba1e5f09298fc8fbe0b0d13bf01/vmlinuz-5.14.10" . into( ) ,
1327+ initrd: "/boot/febdf62805de2ae7b6b597f2a9775d9c8a753ba1e5f09298fc8fbe0b0d13bf01/initramfs-5.14.10.img" . into( ) ,
1328+ options: "root=UUID=abc123 rw composefs=febdf62805de2ae7b6b597f2a9775d9c8a753ba1e5f09298fc8fbe0b0d13bf01" . into( ) ,
1329+ extra: HashMap :: new( ) ,
1330+ } ,
1331+ ] ;
1332+
1333+ assert_eq ! ( result. unwrap( ) , expected) ;
1334+
1335+ let result = get_sorted_bls_boot_entries ( & tempdir, false ) ;
1336+ expected. reverse ( ) ;
1337+ assert_eq ! ( result. unwrap( ) , expected) ;
1338+
1339+ Ok ( ( ) )
1340+ }
1341+
1342+ #[ test]
1343+ fn test_sorted_uki_boot_entries ( ) -> Result < ( ) > {
1344+ let user_cfg = r#"
1345+ if [ -f ${config_directory}/efiuuid.cfg ]; then
1346+ source ${config_directory}/efiuuid.cfg
1347+ fi
1348+
1349+ menuentry "Fedora Bootc UKI: (f7415d75017a12a387a39d2281e033a288fc15775108250ef70a01dcadb93346)" {
1350+ insmod fat
1351+ insmod chain
1352+ search --no-floppy --set=root --fs-uuid "${EFI_PART_UUID}"
1353+ chainloader /EFI/Linux/f7415d75017a12a387a39d2281e033a288fc15775108250ef70a01dcadb93346.efi
1354+ }
1355+
1356+ menuentry "Fedora Bootc UKI: (7e11ac46e3e022053e7226a20104ac656bf72d1a84e3a398b7cce70e9df188b6)" {
1357+ insmod fat
1358+ insmod chain
1359+ search --no-floppy --set=root --fs-uuid "${EFI_PART_UUID}"
1360+ chainloader /EFI/Linux/7e11ac46e3e022053e7226a20104ac656bf72d1a84e3a398b7cce70e9df188b6.efi
1361+ }
1362+ "# ;
1363+
1364+ let bootdir = cap_std_ext:: cap_tempfile:: tempdir ( cap_std:: ambient_authority ( ) ) ?;
1365+ bootdir. create_dir_all ( format ! ( "grub2" ) ) ?;
1366+ bootdir. atomic_write ( format ! ( "grub2/{USER_CFG}" ) , user_cfg) ?;
1367+
1368+ let mut s = String :: new ( ) ;
1369+ let result = get_sorted_uki_boot_entries ( & bootdir, & mut s) ?;
1370+
1371+ let expected = vec ! [
1372+ MenuEntry {
1373+ title: "Fedora Bootc UKI: (f7415d75017a12a387a39d2281e033a288fc15775108250ef70a01dcadb93346)" . into( ) ,
1374+ body: MenuentryBody {
1375+ insmod: vec![ "fat" , "chain" ] ,
1376+ chainloader: "/EFI/Linux/f7415d75017a12a387a39d2281e033a288fc15775108250ef70a01dcadb93346.efi" . into( ) ,
1377+ search: "--no-floppy --set=root --fs-uuid \" ${EFI_PART_UUID}\" " ,
1378+ version: 0 ,
1379+ extra: vec![ ] ,
1380+ } ,
1381+ } ,
1382+ MenuEntry {
1383+ title: "Fedora Bootc UKI: (7e11ac46e3e022053e7226a20104ac656bf72d1a84e3a398b7cce70e9df188b6)" . into( ) ,
1384+ body: MenuentryBody {
1385+ insmod: vec![ "fat" , "chain" ] ,
1386+ chainloader: "/EFI/Linux/7e11ac46e3e022053e7226a20104ac656bf72d1a84e3a398b7cce70e9df188b6.efi" . into( ) ,
1387+ search: "--no-floppy --set=root --fs-uuid \" ${EFI_PART_UUID}\" " ,
1388+ version: 0 ,
1389+ extra: vec![ ] ,
1390+ } ,
1391+ } ,
1392+ ] ;
1393+
1394+ assert_eq ! ( result, expected) ;
1395+
1396+ Ok ( ( ) )
1397+ }
12801398}
0 commit comments