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