@@ -25,6 +25,13 @@ use std::fs::{self, File};
2525use std:: io:: { BufRead , BufReader , BufWriter , Write } ;
2626use std:: path:: { Path , PathBuf } ;
2727
28+ #[ derive( Debug , Clone , Copy , PartialEq , Eq ) ]
29+ pub ( crate ) enum Bootloader {
30+ Grub2 ,
31+ #[ cfg( feature = "systemd-boot" ) ]
32+ SystemdBoot ,
33+ }
34+
2835pub ( crate ) enum ConfigMode {
2936 None ,
3037 Static ,
@@ -81,6 +88,8 @@ pub(crate) fn install(
8188 anyhow:: bail!( "No components specified" ) ;
8289 }
8390
91+ let bootloader = select_bootloader ( & source_root) ;
92+
8493 let mut state = SavedState :: default ( ) ;
8594 let mut installed_efi_vendor = None ;
8695 for & component in target_components. iter ( ) {
@@ -93,20 +102,51 @@ pub(crate) fn install(
93102 continue ;
94103 }
95104
105+ #[ cfg( feature = "systemd-boot" ) ]
106+ if bootloader == Bootloader :: SystemdBoot && component. name ( ) == "BIOS" {
107+ log:: warn!( "Skip installing BIOS component when using systemd-boot" ) ;
108+ continue ;
109+ }
110+
111+ let update_firmware = match bootloader {
112+ Bootloader :: Grub2 => update_firmware,
113+ #[ cfg( feature = "systemd-boot" ) ]
114+ Bootloader :: SystemdBoot => false ,
115+ } ;
116+
96117 let meta = component
97- . install ( & source_root, dest_root, device, update_firmware)
118+ . install (
119+ & source_root,
120+ dest_root,
121+ device,
122+ update_firmware,
123+ & bootloader,
124+ )
98125 . with_context ( || format ! ( "installing component {}" , component. name( ) ) ) ?;
99126 log:: info!( "Installed {} {}" , component. name( ) , meta. meta. version) ;
100127 state. installed . insert ( component. name ( ) . into ( ) , meta) ;
101- // Yes this is a hack...the Component thing just turns out to be too generic.
102- if let Some ( vendor) = component. get_efi_vendor ( & source_root) ? {
103- assert ! ( installed_efi_vendor. is_none( ) ) ;
104- installed_efi_vendor = Some ( vendor) ;
128+
129+ match bootloader {
130+ Bootloader :: Grub2 => {
131+ // Yes this is a hack...the Component thing just turns out to be too generic.
132+ if let Some ( vendor) = component. get_efi_vendor ( & source_root) ? {
133+ assert ! ( installed_efi_vendor. is_none( ) ) ;
134+ installed_efi_vendor = Some ( vendor) ;
135+ }
136+ }
137+ #[ cfg( feature = "systemd-boot" ) ]
138+ _ => { }
105139 }
106140 }
107141 let sysroot = & openat:: Dir :: open ( dest_root) ?;
108142
109- match configs. enabled_with_uuid ( ) {
143+ // If systemd-boot is enabled, do not run grubconfigs::install
144+ let configs_with_uuid = match bootloader {
145+ Bootloader :: Grub2 => configs. enabled_with_uuid ( ) ,
146+ #[ cfg( feature = "systemd-boot" ) ]
147+ _ => None ,
148+ } ;
149+ match configs_with_uuid {
110150 Some ( uuid) => {
111151 let meta = get_static_config_meta ( ) ?;
112152 state. static_configs = Some ( meta) ;
@@ -715,6 +755,41 @@ fn strip_grub_config_file(
715755 Ok ( ( ) )
716756}
717757
758+ /// Determine whether the necessary bootloader files are present for GRUB.
759+ fn has_grub ( source_root : & openat:: Dir ) -> bool {
760+ source_root. open_file ( bios:: GRUB_BIN ) . is_ok ( )
761+ }
762+
763+ /// Determine whether the necessary bootloader files are present for systemd-boot.
764+ #[ cfg( feature = "systemd-boot" ) ]
765+ fn has_systemd_boot ( source_root : & openat:: Dir ) -> bool {
766+ source_root. open_file ( efi:: SYSTEMD_BOOT_EFI ) . is_ok ( )
767+ }
768+
769+ /// Select the bootloader based on available binaries and feature flags.
770+ fn select_bootloader ( source_root : & openat:: Dir ) -> Bootloader {
771+ #[ cfg( not( feature = "systemd-boot" ) ) ]
772+ {
773+ if has_grub ( source_root) {
774+ Bootloader :: Grub2
775+ } else {
776+ log:: warn!( "No bootloader binaries found, defaulting to Grub2" ) ;
777+ Bootloader :: Grub2
778+ }
779+ }
780+ #[ cfg( feature = "systemd-boot" ) ]
781+ {
782+ if has_grub ( source_root) {
783+ Bootloader :: Grub2
784+ } else if has_systemd_boot ( source_root) {
785+ Bootloader :: SystemdBoot
786+ } else {
787+ log:: warn!( "No bootloader binaries found, defaulting to Grub2" ) ;
788+ Bootloader :: Grub2
789+ }
790+ }
791+ }
792+
718793#[ cfg( test) ]
719794mod tests {
720795 use super :: * ;
0 commit comments