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