@@ -15,7 +15,7 @@ use cap_std_ext::{
1515use clap:: ValueEnum ;
1616use composefs:: fs:: read_file;
1717use 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 } ;
1919use composefs_boot:: BootOps ;
2020use fn_error_context:: context;
2121use ostree_ext:: composefs:: {
@@ -35,6 +35,7 @@ use serde::{Deserialize, Serialize};
3535use crate :: bootc_composefs:: repo:: open_composefs_repo;
3636use crate :: bootc_composefs:: state:: { get_booted_bls, write_composefs_state} ;
3737use crate :: bootc_composefs:: status:: get_sorted_uki_boot_entries;
38+ use crate :: composefs_consts:: { TYPE1_ENT_PATH , TYPE1_ENT_PATH_STAGED } ;
3839use crate :: parsers:: bls_config:: { BLSConfig , BLSConfigType } ;
3940use crate :: parsers:: grub_menuconfig:: MenuEntry ;
4041use crate :: spec:: ImageReference ;
@@ -55,6 +56,16 @@ pub(crate) const EFI_UUID_FILE: &str = "efiuuid.cfg";
5556/// The EFI Linux directory
5657const EFI_LINUX : & str = "EFI/Linux" ;
5758
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+
5869pub ( crate ) enum BootSetupType < ' a > {
5970 /// For initial setup, i.e. install to-disk
6071 Setup ( ( & ' a RootSetup , & ' a State , & ' a FileSystem < Sha256HashValue > ) ) ,
@@ -541,6 +552,7 @@ fn write_pe_to_esp(
541552 uki_id : & String ,
542553 is_insecure_from_opts : bool ,
543554 mounted_efi : impl AsRef < Path > ,
555+ bootloader : & Bootloader ,
544556) -> Result < Option < String > > {
545557 let efi_bin = read_file ( file, & repo) . context ( "Reading .efi binary" ) ?;
546558
@@ -577,7 +589,11 @@ fn write_pe_to_esp(
577589 }
578590
579591 // 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+
581597 create_dir_all ( & efi_linux_path) . context ( "Creating EFI/Linux" ) ?;
582598
583599 let final_pe_path = match file_path. parent ( ) {
@@ -609,7 +625,12 @@ fn write_pe_to_esp(
609625
610626 let pe_name = match pe_type {
611627 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 ( ) ,
613634 } ;
614635
615636 pe_dir
@@ -630,7 +651,7 @@ fn write_pe_to_esp(
630651fn write_grub_uki_menuentry (
631652 root_path : Utf8PathBuf ,
632653 setup_type : & BootSetupType ,
633- boot_label : & String ,
654+ boot_label : String ,
634655 id : & Sha256HashValue ,
635656 esp_device : & String ,
636657) -> Result < ( ) > {
@@ -714,6 +735,64 @@ fn write_grub_uki_menuentry(
714735 Ok ( ( ) )
715736}
716737
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+
717796#[ context( "Setting up UKI boot" ) ]
718797pub ( crate ) fn setup_composefs_uki_boot (
719798 setup_type : BootSetupType ,
@@ -791,6 +870,7 @@ pub(crate) fn setup_composefs_uki_boot(
791870 & id. to_hex ( ) ,
792871 is_insecure_from_opts,
793872 esp_mount. dir . path ( ) ,
873+ & bootloader,
794874 ) ?;
795875
796876 if let Some ( label) = ret {
@@ -802,12 +882,11 @@ pub(crate) fn setup_composefs_uki_boot(
802882
803883 match bootloader {
804884 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) ?
806886 }
807887
808888 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) ?
811890 }
812891 } ;
813892
0 commit comments