@@ -1538,15 +1538,18 @@ pub(crate) fn setup_composefs_bls_boot(
15381538 id : & Sha256HashValue ,
15391539 entry : BootEntry < Sha256HashValue > ,
15401540) -> 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 ( ) ,
15431544 // 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+ ) ,
15461548
15471549 BootSetupType :: Upgrade => (
15481550 Utf8PathBuf :: from ( "/sysroot" ) ,
15491551 & vec ! [ format!( "root=UUID={DPS_UUID}" ) , RW_KARG . to_string( ) ] ,
1552+ format ! ( "{}.staged" , id. to_hex( ) ) ,
15501553 ) ,
15511554 } ;
15521555
@@ -1562,7 +1565,7 @@ pub(crate) fn setup_composefs_bls_boot(
15621565 false ,
15631566 root_path. as_std_path ( ) ,
15641567 Some ( "boot" ) ,
1565- Some ( & id . to_hex ( ) ) ,
1568+ Some ( & entry_id ) ,
15661569 & str_slice,
15671570 )
15681571}
@@ -1578,6 +1581,24 @@ pub fn get_esp_partition(device: &str) -> Result<(String, Option<String>)> {
15781581 Ok ( ( esp. node , esp. uuid ) )
15791582}
15801583
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+
15811602#[ context( "Setting up UKI boot" ) ]
15821603pub ( crate ) fn setup_composefs_uki_boot (
15831604 setup_type : BootSetupType ,
@@ -1648,66 +1669,63 @@ pub(crate) fn setup_composefs_uki_boot(
16481669
16491670 let is_upgrade = matches ! ( setup_type, BootSetupType :: Upgrade ) ;
16501671
1651- // Add the user grug cfg
1652- let grub_user_config = format ! (
1672+ let efi_uuid_source = format ! (
16531673 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+ "#
16621678 ) ;
16631679
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+ } ;
16651685 let user_cfg_path = boot_dir. join ( user_cfg_name) ;
16661686
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
16711688 if is_upgrade {
1672- let contents =
1673- std:: fs:: read_to_string ( & user_cfg_path) . context ( format ! ( "Reading {user_cfg_name}" ) ) ?;
1674-
16751689 let mut usr_cfg = std:: fs:: OpenOptions :: new ( )
16761690 . write ( true )
1677- . truncate ( true )
1691+ . create ( true )
16781692 . open ( user_cfg_path)
16791693 . with_context ( || format ! ( "Opening {user_cfg_name}" ) ) ?;
16801694
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?;
16841701
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 ( ) ;
16881705
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+ }
16921708
16931709 return Ok ( ( ) ) ;
16941710 }
16951711
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
16971715 // This will be sourced by grub2/user.cfg to be used for `--fs-uuid`
16981716 let mut efi_uuid_file = std:: fs:: OpenOptions :: new ( )
16991717 . write ( true )
17001718 . 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}" ) ) ?;
17031721
17041722 let esp_uuid = Task :: new ( "blkid for ESP UUID" , "blkid" )
17051723 . args ( [ "-s" , "UUID" , "-o" , "value" , & esp_device] )
17061724 . read ( ) ?;
17071725
17081726 efi_uuid_file
17091727 . 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}" ) ) ?;
17111729
17121730 // Write to grub2/user.cfg
17131731 let mut usr_cfg = std:: fs:: OpenOptions :: new ( )
@@ -1716,15 +1734,8 @@ menuentry "Fedora Bootc UKI: ({uki_id})" {{
17161734 . open ( user_cfg_path)
17171735 . with_context ( || format ! ( "Opening {user_cfg_name}" ) ) ?;
17181736
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 ( ) ) ?;
17281739
17291740 Ok ( ( ) )
17301741}
0 commit comments