@@ -25,6 +25,13 @@ use std::fs::{self, File};
25
25
use std:: io:: { BufRead , BufReader , BufWriter , Write } ;
26
26
use std:: path:: { Path , PathBuf } ;
27
27
28
+ #[ derive( Debug , Clone , Copy , PartialEq , Eq ) ]
29
+ pub ( crate ) enum Bootloader {
30
+ Grub2 ,
31
+ #[ cfg( feature = "systemd-boot" ) ]
32
+ SystemdBoot ,
33
+ }
34
+
28
35
pub ( crate ) enum ConfigMode {
29
36
None ,
30
37
Static ,
@@ -81,6 +88,8 @@ pub(crate) fn install(
81
88
anyhow:: bail!( "No components specified" ) ;
82
89
}
83
90
91
+ let bootloader = select_bootloader ( & source_root) ;
92
+
84
93
let mut state = SavedState :: default ( ) ;
85
94
let mut installed_efi_vendor = None ;
86
95
for & component in target_components. iter ( ) {
@@ -93,20 +102,51 @@ pub(crate) fn install(
93
102
continue ;
94
103
}
95
104
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
+
96
117
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
+ )
98
125
. with_context ( || format ! ( "installing component {}" , component. name( ) ) ) ?;
99
126
log:: info!( "Installed {} {}" , component. name( ) , meta. meta. version) ;
100
127
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
+ _ => { }
105
139
}
106
140
}
107
141
let sysroot = & openat:: Dir :: open ( dest_root) ?;
108
142
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 {
110
150
Some ( uuid) => {
111
151
let meta = get_static_config_meta ( ) ?;
112
152
state. static_configs = Some ( meta) ;
@@ -715,6 +755,41 @@ fn strip_grub_config_file(
715
755
Ok ( ( ) )
716
756
}
717
757
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
+
718
793
#[ cfg( test) ]
719
794
mod tests {
720
795
use super :: * ;
0 commit comments