@@ -15,7 +15,7 @@ use cap_std_ext::{
15
15
use clap:: ValueEnum ;
16
16
use composefs:: fs:: read_file;
17
17
use composefs:: tree:: { FileSystem , RegularFile } ;
18
- use composefs_boot:: bootloader:: { PEType , EFI_ADDON_DIR_EXT , EFI_ADDON_FILE_EXT , EFI_EXT } ;
18
+ use composefs_boot:: bootloader:: { PEType , EFI_ADDON_DIR_EXT , EFI_EXT } ;
19
19
use composefs_boot:: BootOps ;
20
20
use fn_error_context:: context;
21
21
use ostree_ext:: composefs:: {
@@ -35,6 +35,7 @@ use serde::{Deserialize, Serialize};
35
35
use crate :: bootc_composefs:: repo:: open_composefs_repo;
36
36
use crate :: bootc_composefs:: state:: { get_booted_bls, write_composefs_state} ;
37
37
use crate :: bootc_composefs:: status:: get_sorted_uki_boot_entries;
38
+ use crate :: composefs_consts:: { TYPE1_ENT_PATH , TYPE1_ENT_PATH_STAGED } ;
38
39
use crate :: parsers:: bls_config:: { BLSConfig , BLSConfigType } ;
39
40
use crate :: parsers:: grub_menuconfig:: MenuEntry ;
40
41
use crate :: spec:: ImageReference ;
@@ -55,6 +56,16 @@ pub(crate) const EFI_UUID_FILE: &str = "efiuuid.cfg";
55
56
/// The EFI Linux directory
56
57
const EFI_LINUX : & str = "EFI/Linux" ;
57
58
59
+ /// Timeout for systemd-boot bootloader menu
60
+ const SYSTEMD_TIMEOUT : & str = "timeout 5" ;
61
+ const SYSTEMD_LOADER_CONF_PATH : & str = "loader/loader.conf" ;
62
+
63
+ /// We want to be able to control the ordering of UKIs so we put them in a directory that's not the
64
+ /// directory specified by the BLS spec. We do this because we want systemd-boot to only look at
65
+ /// our config files and not show the actual UKIs in the bootloader menu
66
+ /// This is relative to the ESP
67
+ const SYSTEMD_UKI_DIR : & str = "EFI/Linux/uki" ;
68
+
58
69
pub ( crate ) enum BootSetupType < ' a > {
59
70
/// For initial setup, i.e. install to-disk
60
71
Setup ( ( & ' a RootSetup , & ' a State , & ' a FileSystem < Sha256HashValue > ) ) ,
@@ -143,7 +154,7 @@ pub fn get_sysroot_parent_dev() -> Result<String> {
143
154
}
144
155
145
156
pub fn type1_entry_conf_file_name ( sort_key : impl AsRef < str > + std:: fmt:: Display ) -> String {
146
- format ! ( "bootc-composefs-{sort_key}.conf" )
157
+ format ! ( "bootc-composefs-{sort_key}.conf" , )
147
158
}
148
159
149
160
/// Compute SHA256Sum of VMlinuz + Initrd
@@ -541,6 +552,7 @@ fn write_pe_to_esp(
541
552
uki_id : & String ,
542
553
is_insecure_from_opts : bool ,
543
554
mounted_efi : impl AsRef < Path > ,
555
+ bootloader : & Bootloader ,
544
556
) -> Result < Option < String > > {
545
557
let efi_bin = read_file ( file, & repo) . context ( "Reading .efi binary" ) ?;
546
558
@@ -577,7 +589,11 @@ fn write_pe_to_esp(
577
589
}
578
590
579
591
// Write the UKI to ESP
580
- let efi_linux_path = mounted_efi. as_ref ( ) . join ( EFI_LINUX ) ;
592
+ let efi_linux_path = mounted_efi. as_ref ( ) . join ( match bootloader {
593
+ Bootloader :: Grub => EFI_LINUX ,
594
+ Bootloader :: Systemd => SYSTEMD_UKI_DIR ,
595
+ } ) ;
596
+
581
597
create_dir_all ( & efi_linux_path) . context ( "Creating EFI/Linux" ) ?;
582
598
583
599
let final_pe_path = match file_path. parent ( ) {
@@ -609,7 +625,12 @@ fn write_pe_to_esp(
609
625
610
626
let pe_name = match pe_type {
611
627
PEType :: Uki => format ! ( "{}{}" , uki_id, EFI_EXT ) ,
612
- PEType :: UkiAddon => format ! ( "{}{}" , uki_id, EFI_ADDON_FILE_EXT ) ,
628
+ PEType :: UkiAddon => file_path
629
+ . components ( )
630
+ . last ( )
631
+ . unwrap ( )
632
+ . to_string_lossy ( )
633
+ . to_string ( ) ,
613
634
} ;
614
635
615
636
pe_dir
@@ -630,7 +651,7 @@ fn write_pe_to_esp(
630
651
fn write_grub_uki_menuentry (
631
652
root_path : Utf8PathBuf ,
632
653
setup_type : & BootSetupType ,
633
- boot_label : & String ,
654
+ boot_label : String ,
634
655
id : & Sha256HashValue ,
635
656
esp_device : & String ,
636
657
) -> Result < ( ) > {
@@ -714,6 +735,64 @@ fn write_grub_uki_menuentry(
714
735
Ok ( ( ) )
715
736
}
716
737
738
+ #[ context( "Writing systemd UKI config" ) ]
739
+ fn write_systemd_uki_config (
740
+ esp_dir : & Dir ,
741
+ setup_type : & BootSetupType ,
742
+ boot_label : String ,
743
+ id : & Sha256HashValue ,
744
+ ) -> Result < ( ) > {
745
+ let default_sort_key = "0" ;
746
+
747
+ let mut bls_conf = BLSConfig :: default ( ) ;
748
+ bls_conf
749
+ . with_title ( boot_label)
750
+ . with_cfg ( BLSConfigType :: EFI {
751
+ efi : format ! ( "/{SYSTEMD_UKI_DIR}/{}{}" , id. to_hex( ) , EFI_EXT ) ,
752
+ } )
753
+ . with_sort_key ( default_sort_key. into ( ) )
754
+ . with_version ( default_sort_key. into ( ) ) ;
755
+
756
+ let entries_dir = match setup_type {
757
+ BootSetupType :: Setup ( ..) => {
758
+ esp_dir
759
+ . create_dir_all ( TYPE1_ENT_PATH )
760
+ . with_context ( || format ! ( "Creating {TYPE1_ENT_PATH}" ) ) ?;
761
+
762
+ esp_dir. open_dir ( TYPE1_ENT_PATH ) ?
763
+ }
764
+
765
+ BootSetupType :: Upgrade ( _) => {
766
+ esp_dir
767
+ . create_dir_all ( TYPE1_ENT_PATH_STAGED )
768
+ . with_context ( || format ! ( "Creating {TYPE1_ENT_PATH_STAGED}" ) ) ?;
769
+
770
+ esp_dir. open_dir ( TYPE1_ENT_PATH_STAGED ) ?
771
+ }
772
+ } ;
773
+
774
+ entries_dir
775
+ . atomic_write (
776
+ type1_entry_conf_file_name ( default_sort_key) ,
777
+ bls_conf. to_string ( ) . as_bytes ( ) ,
778
+ )
779
+ . context ( "Writing conf file" ) ?;
780
+
781
+ // Write the timeout for bootloader menu if not exists
782
+ if !esp_dir. exists ( SYSTEMD_LOADER_CONF_PATH ) {
783
+ esp_dir
784
+ . atomic_write ( SYSTEMD_LOADER_CONF_PATH , SYSTEMD_TIMEOUT )
785
+ . with_context ( || format ! ( "Writing to {SYSTEMD_LOADER_CONF_PATH}" ) ) ?;
786
+ }
787
+
788
+ let esp_dir = esp_dir
789
+ . reopen_as_ownedfd ( )
790
+ . context ( "Reopening as owned fd" ) ?;
791
+ rustix:: fs:: fsync ( esp_dir) . context ( "fsync" ) ?;
792
+
793
+ Ok ( ( ) )
794
+ }
795
+
717
796
#[ context( "Setting up UKI boot" ) ]
718
797
pub ( crate ) fn setup_composefs_uki_boot (
719
798
setup_type : BootSetupType ,
@@ -791,6 +870,7 @@ pub(crate) fn setup_composefs_uki_boot(
791
870
& id. to_hex ( ) ,
792
871
is_insecure_from_opts,
793
872
esp_mount. dir . path ( ) ,
873
+ & bootloader,
794
874
) ?;
795
875
796
876
if let Some ( label) = ret {
@@ -802,12 +882,11 @@ pub(crate) fn setup_composefs_uki_boot(
802
882
803
883
match bootloader {
804
884
Bootloader :: Grub => {
805
- write_grub_uki_menuentry ( root_path, & setup_type, & boot_label, id, & esp_device) ?
885
+ write_grub_uki_menuentry ( root_path, & setup_type, boot_label, id, & esp_device) ?
806
886
}
807
887
808
888
Bootloader :: Systemd => {
809
- // No-op for now, but later we want to have .conf files so we can control the order of
810
- // entries.
889
+ write_systemd_uki_config ( & esp_mount. fd , & setup_type, boot_label, id) ?
811
890
}
812
891
} ;
813
892
0 commit comments