@@ -1538,15 +1538,18 @@ pub(crate) fn setup_composefs_bls_boot(
1538
1538
id : & Sha256HashValue ,
1539
1539
entry : BootEntry < Sha256HashValue > ,
1540
1540
) -> Result < ( ) > {
1541
- let ( root_path, cmdline_refs) = match setup_type {
1542
- BootSetupType :: Setup ( root_setup) => {
1541
+ let ( root_path, cmdline_refs, entry_id) = match setup_type {
1542
+ BootSetupType :: Setup ( root_setup) => (
1543
+ root_setup. physical_root_path . clone ( ) ,
1543
1544
// root_setup.kargs has [root=UUID=<UUID>, "rw"]
1544
- ( root_setup. physical_root_path . clone ( ) , & root_setup. kargs )
1545
- }
1545
+ & root_setup. kargs ,
1546
+ format ! ( "{}" , id. to_hex( ) ) ,
1547
+ ) ,
1546
1548
1547
1549
BootSetupType :: Upgrade => (
1548
1550
Utf8PathBuf :: from ( "/sysroot" ) ,
1549
1551
& vec ! [ format!( "root=UUID={DPS_UUID}" ) , RW_KARG . to_string( ) ] ,
1552
+ format ! ( "{}.staged" , id. to_hex( ) ) ,
1550
1553
) ,
1551
1554
} ;
1552
1555
@@ -1562,7 +1565,7 @@ pub(crate) fn setup_composefs_bls_boot(
1562
1565
false ,
1563
1566
root_path. as_std_path ( ) ,
1564
1567
Some ( "boot" ) ,
1565
- Some ( & id . to_hex ( ) ) ,
1568
+ Some ( & entry_id ) ,
1566
1569
& str_slice,
1567
1570
)
1568
1571
}
@@ -1578,6 +1581,24 @@ pub fn get_esp_partition(device: &str) -> Result<(String, Option<String>)> {
1578
1581
Ok ( ( esp. node , esp. uuid ) )
1579
1582
}
1580
1583
1584
+ fn get_user_config ( uki_id : & str ) -> String {
1585
+ let s = format ! (
1586
+ r#"
1587
+ menuentry "Fedora Bootc UKI: ({uki_id})" {{
1588
+ insmod fat
1589
+ insmod chain
1590
+ search --no-floppy --set=root --fs-uuid "${{EFI_PART_UUID}}"
1591
+ chainloader /EFI/Linux/{uki_id}.efi
1592
+ }}
1593
+ "#
1594
+ ) ;
1595
+
1596
+ return s;
1597
+ }
1598
+
1599
+ /// Contains the EFP's filesystem UUID. Used by grub
1600
+ const EFI_UUID_FILE : & str = "efiuuid.cfg" ;
1601
+
1581
1602
#[ context( "Setting up UKI boot" ) ]
1582
1603
pub ( crate ) fn setup_composefs_uki_boot (
1583
1604
setup_type : BootSetupType ,
@@ -1648,66 +1669,63 @@ pub(crate) fn setup_composefs_uki_boot(
1648
1669
1649
1670
let is_upgrade = matches ! ( setup_type, BootSetupType :: Upgrade ) ;
1650
1671
1651
- // Add the user grug cfg
1652
- let grub_user_config = format ! (
1672
+ let efi_uuid_source = format ! (
1653
1673
r#"
1654
- menuentry "Fedora Bootc UKI: ({uki_id})" {{
1655
- insmod fat
1656
- insmod chain
1657
- search --no-floppy --set=root --fs-uuid "${{EFI_PART_UUID}}"
1658
- chainloader /EFI/Linux/{uki_id}.efi
1659
- }}
1660
- "# ,
1661
- uki_id = id. to_hex( ) ,
1674
+ if [ -f ${{config_directory}}/{EFI_UUID_FILE} ]; then
1675
+ source ${{config_directory}}/{EFI_UUID_FILE}
1676
+ fi
1677
+ "#
1662
1678
) ;
1663
1679
1664
- let user_cfg_name = "grub2/user.cfg" ;
1680
+ let user_cfg_name = if is_upgrade {
1681
+ "grub2/user.cfg.staged"
1682
+ } else {
1683
+ "grub2/user.cfg"
1684
+ } ;
1665
1685
let user_cfg_path = boot_dir. join ( user_cfg_name) ;
1666
1686
1667
- // TODO: Figure out a better way to sort these menuentries. This is a bit scuffed
1668
- //
1669
- // Read the current user.cfg, split at the first menuentry, then stick the new menuentry in
1670
- // between the efiuuid.cfg sourcing code and the previous menuentry
1687
+ // Iterate over all available deployments, and generate a menuentry for each
1671
1688
if is_upgrade {
1672
- let contents =
1673
- std:: fs:: read_to_string ( & user_cfg_path) . context ( format ! ( "Reading {user_cfg_name}" ) ) ?;
1674
-
1675
1689
let mut usr_cfg = std:: fs:: OpenOptions :: new ( )
1676
1690
. write ( true )
1677
- . truncate ( true )
1691
+ . create ( true )
1678
1692
. open ( user_cfg_path)
1679
1693
. with_context ( || format ! ( "Opening {user_cfg_name}" ) ) ?;
1680
1694
1681
- let Some ( ( before, after) ) = contents. split_once ( "menuentry" ) else {
1682
- anyhow:: bail!( "Did not find menuentry in {user_cfg_name}" )
1683
- } ;
1695
+ usr_cfg. write_all ( efi_uuid_source. as_bytes ( ) ) ?;
1696
+ usr_cfg. write_all ( get_user_config ( & id. to_hex ( ) ) . as_bytes ( ) ) ?;
1697
+
1698
+ // root_path here will be /sysroot
1699
+ for entry in std:: fs:: read_dir ( root_path. join ( STATE_DIR_RELATIVE ) ) ? {
1700
+ let entry = entry?;
1684
1701
1685
- usr_cfg
1686
- . seek ( SeekFrom :: Start ( 0 ) )
1687
- . with_context ( || format ! ( "Seek {user_cfg_name}" ) ) ? ;
1702
+ let depl_file_name = entry . file_name ( ) ;
1703
+ // SAFETY: Deployment file name shouldn't containg non UTF-8 chars
1704
+ let depl_file_name = depl_file_name . to_string_lossy ( ) ;
1688
1705
1689
- usr_cfg
1690
- . write_all ( format ! ( "{before} {grub_user_config}\n menuentry {after}" ) . as_bytes ( ) )
1691
- . with_context ( || format ! ( "Writing to {user_cfg_name}" ) ) ?;
1706
+ usr_cfg. write_all ( get_user_config ( & depl_file_name) . as_bytes ( ) ) ?;
1707
+ }
1692
1708
1693
1709
return Ok ( ( ) ) ;
1694
1710
}
1695
1711
1696
- // Open grub2/efiuuid.cfg and write the EFI partition UUID in there
1712
+ let efi_uuid_file_path = format ! ( "grub2/{EFI_UUID_FILE}" ) ;
1713
+
1714
+ // Open grub2/efiuuid.cfg and write the EFI partition fs-UUID in there
1697
1715
// This will be sourced by grub2/user.cfg to be used for `--fs-uuid`
1698
1716
let mut efi_uuid_file = std:: fs:: OpenOptions :: new ( )
1699
1717
. write ( true )
1700
1718
. create ( true )
1701
- . open ( boot_dir. join ( "grub2/efiuuid.cfg" ) )
1702
- . context ( "Opening grub2/efiuuid.cfg" ) ?;
1719
+ . open ( boot_dir. join ( & efi_uuid_file_path ) )
1720
+ . with_context ( || format ! ( "Opening {efi_uuid_file_path}" ) ) ?;
1703
1721
1704
1722
let esp_uuid = Task :: new ( "blkid for ESP UUID" , "blkid" )
1705
1723
. args ( [ "-s" , "UUID" , "-o" , "value" , & esp_device] )
1706
1724
. read ( ) ?;
1707
1725
1708
1726
efi_uuid_file
1709
1727
. write_all ( format ! ( "set EFI_PART_UUID=\" {}\" " , esp_uuid. trim( ) ) . as_bytes ( ) )
1710
- . context ( "Writing to grub2/efiuuid.cfg" ) ?;
1728
+ . with_context ( || format ! ( "Writing to {efi_uuid_file_path}" ) ) ?;
1711
1729
1712
1730
// Write to grub2/user.cfg
1713
1731
let mut usr_cfg = std:: fs:: OpenOptions :: new ( )
@@ -1716,15 +1734,8 @@ menuentry "Fedora Bootc UKI: ({uki_id})" {{
1716
1734
. open ( user_cfg_path)
1717
1735
. with_context ( || format ! ( "Opening {user_cfg_name}" ) ) ?;
1718
1736
1719
- let efi_uuid_source = r#"
1720
- if [ -f ${config_directory}/efiuuid.cfg ]; then
1721
- source ${config_directory}/efiuuid.cfg
1722
- fi
1723
- "# ;
1724
-
1725
- usr_cfg
1726
- . write_all ( format ! ( "{efi_uuid_source}\n {grub_user_config}" ) . as_bytes ( ) )
1727
- . with_context ( || format ! ( "Writing to {user_cfg_name}" ) ) ?;
1737
+ usr_cfg. write_all ( efi_uuid_source. as_bytes ( ) ) ?;
1738
+ usr_cfg. write_all ( get_user_config ( & id. to_hex ( ) ) . as_bytes ( ) ) ?;
1728
1739
1729
1740
Ok ( ( ) )
1730
1741
}
0 commit comments