@@ -29,20 +29,23 @@ use rustix::path::Arg;
2929use schemars:: JsonSchema ;
3030use serde:: { Deserialize , Serialize } ;
3131
32- use crate :: bootc_composefs:: state:: { get_booted_bls, write_composefs_state} ;
3332use crate :: bootc_composefs:: status:: get_sorted_uki_boot_entries;
3433use crate :: composefs_consts:: { TYPE1_ENT_PATH , TYPE1_ENT_PATH_STAGED } ;
3534use crate :: parsers:: bls_config:: { BLSConfig , BLSConfigType } ;
3635use crate :: parsers:: grub_menuconfig:: MenuEntry ;
3736use crate :: spec:: ImageReference ;
3837use crate :: task:: Task ;
3938use crate :: { bootc_composefs:: repo:: open_composefs_repo, store:: ComposefsFilesystem } ;
39+ use crate :: {
40+ bootc_composefs:: state:: { get_booted_bls, write_composefs_state} ,
41+ bootloader:: esp_in,
42+ } ;
4043use crate :: {
4144 composefs_consts:: {
4245 BOOT_LOADER_ENTRIES , COMPOSEFS_CMDLINE , ORIGIN_KEY_BOOT , ORIGIN_KEY_BOOT_DIGEST ,
4346 STAGED_BOOT_LOADER_ENTRIES , STATE_DIR_ABS , USER_CFG , USER_CFG_STAGED ,
4447 } ,
45- install:: { dps_uuid:: DPS_UUID , ESP_GUID , RW_KARG } ,
48+ install:: { dps_uuid:: DPS_UUID , RW_KARG } ,
4649 spec:: { Bootloader , Host } ,
4750} ;
4851
@@ -51,7 +54,7 @@ use crate::install::{RootSetup, State};
5154/// Contains the EFP's filesystem UUID. Used by grub
5255pub ( crate ) const EFI_UUID_FILE : & str = "efiuuid.cfg" ;
5356/// The EFI Linux directory
54- const EFI_LINUX : & str = "EFI/Linux" ;
57+ pub ( crate ) const EFI_LINUX : & str = "EFI/Linux" ;
5558
5659/// Timeout for systemd-boot bootloader menu
5760const SYSTEMD_TIMEOUT : & str = "timeout 5" ;
126129 )
127130}
128131
132+ /// Returns `true` if detect the target rootfs carries a UKI.
133+ pub ( crate ) fn container_root_has_uki ( root : & Dir ) -> Result < bool > {
134+ let Some ( boot) = root. open_dir_optional ( crate :: install:: BOOT ) ? else {
135+ return Ok ( false ) ;
136+ } ;
137+ let Some ( efi_linux) = boot. open_dir_optional ( EFI_LINUX ) ? else {
138+ return Ok ( false ) ;
139+ } ;
140+ for entry in efi_linux. entries ( ) ? {
141+ let entry = entry?;
142+ let name = entry. file_name ( ) ;
143+ let name = Path :: new ( & name) ;
144+ let extension = name. extension ( ) . and_then ( |v| v. to_str ( ) ) ;
145+ if extension == Some ( "efi" ) {
146+ return Ok ( true ) ;
147+ }
148+ }
149+ Ok ( false )
150+ }
151+
129152pub fn get_esp_partition ( device : & str ) -> Result < ( String , Option < String > ) > {
130153 let device_info = bootc_blockdev:: partitions_of ( Utf8Path :: new ( device) ) ?;
131- let esp = device_info
132- . partitions
133- . into_iter ( )
134- . find ( |p| p. parttype . as_str ( ) == ESP_GUID )
135- . ok_or ( anyhow:: anyhow!( "ESP not found for device: {device}" ) ) ?;
154+ let esp = crate :: bootloader:: esp_in ( & device_info) ?;
136155
137- Ok ( ( esp. node , esp. uuid ) )
156+ Ok ( ( esp. node . clone ( ) , esp. uuid . clone ( ) ) )
138157}
139158
140159pub fn get_sysroot_parent_dev ( ) -> Result < String > {
@@ -360,23 +379,14 @@ pub(crate) fn setup_composefs_bls_boot(
360379 } ;
361380
362381 // Locate ESP partition device
363- let esp_part = root_setup
364- . device_info
365- . partitions
366- . iter ( )
367- . find ( |p| p. parttype . as_str ( ) == ESP_GUID )
368- . ok_or_else ( || anyhow:: anyhow!( "ESP partition not found" ) ) ?;
382+ let esp_part = esp_in ( & root_setup. device_info ) ?;
369383
370384 (
371385 root_setup. physical_root_path . clone ( ) ,
372386 esp_part. node . clone ( ) ,
373387 cmdline_options,
374388 fs,
375- state
376- . composefs_options
377- . as_ref ( )
378- . map ( |opts| opts. bootloader . clone ( ) )
379- . unwrap_or ( Bootloader :: default ( ) ) ,
389+ state. detected_bootloader . clone ( ) ,
380390 )
381391 }
382392
@@ -829,17 +839,12 @@ pub(crate) fn setup_composefs_uki_boot(
829839 anyhow:: bail!( "ComposeFS options not found" ) ;
830840 } ;
831841
832- let esp_part = root_setup
833- . device_info
834- . partitions
835- . iter ( )
836- . find ( |p| p. parttype . as_str ( ) == ESP_GUID )
837- . ok_or_else ( || anyhow ! ( "ESP partition not found" ) ) ?;
842+ let esp_part = esp_in ( & root_setup. device_info ) ?;
838843
839844 (
840845 root_setup. physical_root_path . clone ( ) ,
841846 esp_part. node . clone ( ) ,
842- cfs_opts . bootloader . clone ( ) ,
847+ state . detected_bootloader . clone ( ) ,
843848 cfs_opts. insecure ,
844849 cfs_opts. uki_addon . as_ref ( ) ,
845850 )
@@ -944,13 +949,20 @@ pub(crate) fn setup_composefs_boot(
944949 if cfg ! ( target_arch = "s390x" ) {
945950 // TODO: Integrate s390x support into install_via_bootupd
946951 crate :: bootloader:: install_via_zipl ( & root_setup. device_info , boot_uuid) ?;
947- } else {
952+ } else if state . detected_bootloader == Bootloader :: Grub {
948953 crate :: bootloader:: install_via_bootupd (
949954 & root_setup. device_info ,
950955 & root_setup. physical_root_path ,
951956 & state. config_opts ,
952957 None ,
953958 ) ?;
959+ } else {
960+ crate :: bootloader:: install_systemd_boot (
961+ & root_setup. device_info ,
962+ & root_setup. physical_root_path ,
963+ & state. config_opts ,
964+ None ,
965+ ) ?;
954966 }
955967
956968 let repo = open_composefs_repo ( & root_setup. physical_root ) ?;
@@ -1001,3 +1013,34 @@ pub(crate) fn setup_composefs_boot(
10011013
10021014 Ok ( ( ) )
10031015}
1016+
1017+ #[ cfg( test) ]
1018+ mod tests {
1019+ use super :: * ;
1020+ use cap_std_ext:: cap_std;
1021+
1022+ #[ test]
1023+ fn test_root_has_uki ( ) -> Result < ( ) > {
1024+ // Test case 1: No boot directory
1025+ let tempdir = cap_std_ext:: cap_tempfile:: tempdir ( cap_std:: ambient_authority ( ) ) ?;
1026+ assert_eq ! ( container_root_has_uki( & tempdir) ?, false ) ;
1027+
1028+ // Test case 2: boot directory exists but no EFI/Linux
1029+ tempdir. create_dir ( crate :: install:: BOOT ) ?;
1030+ assert_eq ! ( container_root_has_uki( & tempdir) ?, false ) ;
1031+
1032+ // Test case 3: boot/EFI/Linux exists but no .efi files
1033+ tempdir. create_dir_all ( "boot/EFI/Linux" ) ?;
1034+ assert_eq ! ( container_root_has_uki( & tempdir) ?, false ) ;
1035+
1036+ // Test case 4: boot/EFI/Linux exists with non-.efi file
1037+ tempdir. atomic_write ( "boot/EFI/Linux/readme.txt" , b"some file" ) ?;
1038+ assert_eq ! ( container_root_has_uki( & tempdir) ?, false ) ;
1039+
1040+ // Test case 5: boot/EFI/Linux exists with .efi file
1041+ tempdir. atomic_write ( "boot/EFI/Linux/bootx64.efi" , b"fake efi binary" ) ?;
1042+ assert_eq ! ( container_root_has_uki( & tempdir) ?, true ) ;
1043+
1044+ Ok ( ( ) )
1045+ }
1046+ }
0 commit comments