@@ -44,7 +44,10 @@ use cap_std_ext::cmdext::CapStdExtCommandExt;
4444use cap_std_ext:: prelude:: CapStdExtDirExt ;
4545use clap:: ValueEnum ;
4646use composefs:: fs:: read_file;
47- use composefs:: tree:: FileSystem ;
47+ use composefs:: tree:: { FileSystem , RegularFile } ;
48+ use composefs_boot:: bootloader:: {
49+ PEType , Type2Entry , UsrLibModulesUki , EFI_ADDON_DIR_EXT , EFI_ADDON_FILE_EXT , EFI_EXT ,
50+ } ;
4851use fn_error_context:: context;
4952use ostree:: gio;
5053use ostree_ext:: composefs:: {
@@ -1717,7 +1720,7 @@ pub(crate) fn setup_composefs_bls_boot(
17171720 // TODO: Make this generic
17181721 repo : ComposefsRepository < Sha256HashValue > ,
17191722 id : & Sha256HashValue ,
1720- entry : ComposefsBootEntry < Sha256HashValue > ,
1723+ entry : & ComposefsBootEntry < Sha256HashValue > ,
17211724) -> Result < String > {
17221725 let id_hex = id. to_hex ( ) ;
17231726
@@ -1931,13 +1934,106 @@ fi
19311934 )
19321935}
19331936
1937+ fn write_pe_to_esp (
1938+ repo : & ComposefsRepository < Sha256HashValue > ,
1939+ file : & RegularFile < Sha256HashValue > ,
1940+ file_path : & PathBuf ,
1941+ pe_type : PEType ,
1942+ uki_id : & String ,
1943+ is_insecure_from_opts : bool ,
1944+ mounted_efi : & PathBuf ,
1945+ ) -> Result < Option < String > > {
1946+ let efi_bin = read_file ( file, & repo) . context ( "Reading .efi binary" ) ?;
1947+
1948+ let mut boot_label = None ;
1949+
1950+ // UKI Extension might not even have a cmdline
1951+ // TODO: UKI Addon might also have a composefs= cmdline???
1952+ if matches ! ( pe_type, PEType :: Uki ) {
1953+ let cmdline = uki:: get_cmdline ( & efi_bin) . context ( "Getting UKI cmdline" ) ?;
1954+
1955+ let ( composefs_cmdline, insecure) = get_cmdline_composefs :: < Sha256HashValue > ( cmdline) ?;
1956+
1957+ // If the UKI cmdline does not match what the user has passed as cmdline option
1958+ // NOTE: This will only be checked for new installs and now upgrades/switches
1959+ match is_insecure_from_opts {
1960+ true => {
1961+ if !insecure {
1962+ tracing:: warn!(
1963+ "--insecure passed as option but UKI cmdline does not support it"
1964+ ) ;
1965+ }
1966+ }
1967+
1968+ false => {
1969+ if insecure {
1970+ tracing:: warn!( "UKI cmdline has composefs set as insecure" )
1971+ }
1972+ }
1973+ }
1974+
1975+ if composefs_cmdline. to_hex ( ) != * uki_id {
1976+ anyhow:: bail!(
1977+ "The UKI has the wrong composefs= parameter (is '{composefs_cmdline:?}', should be {uki_id:?})"
1978+ ) ;
1979+ }
1980+
1981+ boot_label = Some ( uki:: get_boot_label ( & efi_bin) . context ( "Getting UKI boot label" ) ?) ;
1982+ }
1983+
1984+ // Write the UKI to ESP
1985+ let efi_linux_path = mounted_efi. join ( EFI_LINUX ) ;
1986+ create_dir_all ( & efi_linux_path) . context ( "Creating EFI/Linux" ) ?;
1987+
1988+ let final_pe_path = if let Some ( parent) = file_path. parent ( ) {
1989+ let renamed_path = if parent. as_str ( ) ?. ends_with ( EFI_ADDON_DIR_EXT ) {
1990+ let dir_name = format ! ( "{}{}" , uki_id, EFI_ADDON_DIR_EXT ) ;
1991+
1992+ parent
1993+ . parent ( )
1994+ . map ( |p| p. join ( & dir_name) )
1995+ . unwrap_or ( dir_name. into ( ) )
1996+ } else {
1997+ parent. to_path_buf ( )
1998+ } ;
1999+
2000+ let full_path = efi_linux_path. join ( renamed_path) ;
2001+ create_dir_all ( & full_path) ?;
2002+
2003+ full_path
2004+ } else {
2005+ efi_linux_path
2006+ } ;
2007+
2008+ let pe_dir = cap_std:: fs:: Dir :: open_ambient_dir ( & final_pe_path, cap_std:: ambient_authority ( ) )
2009+ . with_context ( || format ! ( "Opening {final_pe_path:?}" ) ) ?;
2010+
2011+ let pe_name = match pe_type {
2012+ PEType :: Uki => format ! ( "{}{}" , uki_id, EFI_EXT ) ,
2013+ PEType :: UkiAddon => format ! ( "{}{}" , uki_id, EFI_ADDON_FILE_EXT ) ,
2014+ } ;
2015+
2016+ pe_dir
2017+ . atomic_write ( pe_name, efi_bin)
2018+ . context ( "Writing UKI" ) ?;
2019+
2020+ rustix:: fs:: fsync (
2021+ pe_dir
2022+ . reopen_as_ownedfd ( )
2023+ . context ( "Reopening as owned fd" ) ?,
2024+ )
2025+ . context ( "fsync" ) ?;
2026+
2027+ Ok ( boot_label)
2028+ }
2029+
19342030#[ context( "Setting up UKI boot" ) ]
19352031pub ( crate ) fn setup_composefs_uki_boot (
19362032 setup_type : BootSetupType ,
19372033 // TODO: Make this generic
19382034 repo : ComposefsRepository < Sha256HashValue > ,
19392035 id : & Sha256HashValue ,
1940- entry : ComposefsBootEntry < Sha256HashValue > ,
2036+ entries : Vec < ComposefsBootEntry < Sha256HashValue > > ,
19412037) -> Result < ( ) > {
19422038 let ( root_path, esp_device, is_insecure_from_opts) = match setup_type {
19432039 BootSetupType :: Setup ( ( root_setup, state, ..) ) => {
@@ -1957,7 +2053,11 @@ pub(crate) fn setup_composefs_uki_boot(
19572053 (
19582054 root_setup. physical_root_path . clone ( ) ,
19592055 esp_part. node . clone ( ) ,
1960- state. composefs_options . as_ref ( ) . map ( |x| x. insecure ) ,
2056+ state
2057+ . composefs_options
2058+ . as_ref ( )
2059+ . map ( |x| x. insecure )
2060+ . unwrap_or ( false ) ,
19612061 )
19622062 }
19632063
@@ -1971,7 +2071,7 @@ pub(crate) fn setup_composefs_uki_boot(
19712071 anyhow:: bail!( "Could not find parent device for mountpoint /sysroot" ) ;
19722072 } ;
19732073
1974- ( sysroot, get_esp_partition ( & parent) ?. 0 , None )
2074+ ( sysroot, get_esp_partition ( & parent) ?. 0 , false )
19752075 }
19762076 } ;
19772077
@@ -1983,66 +2083,42 @@ pub(crate) fn setup_composefs_uki_boot(
19832083 . args ( [ & PathBuf :: from ( & esp_device) , & mounted_efi. clone ( ) ] )
19842084 . run ( ) ?;
19852085
1986- let boot_label = match entry {
1987- ComposefsBootEntry :: Type1 ( ..) => unimplemented ! ( ) ,
1988- ComposefsBootEntry :: UsrLibModulesUki ( ..) => unimplemented ! ( ) ,
1989- ComposefsBootEntry :: UsrLibModulesVmLinuz ( ..) => unimplemented ! ( ) ,
1990-
1991- ComposefsBootEntry :: Type2 ( type2_entry) => {
1992- let uki = read_file ( & type2_entry. file , & repo) . context ( "Reading UKI" ) ?;
1993- let cmdline = uki:: get_cmdline ( & uki) . context ( "Getting UKI cmdline" ) ?;
1994- let ( composefs_cmdline, insecure) = get_cmdline_composefs :: < Sha256HashValue > ( cmdline) ?;
1995-
1996- // If the UKI cmdline does not match what the user has passed as cmdline option
1997- // NOTE: This will only be checked for new installs and now upgrades/switches
1998- if let Some ( is_insecure_from_opts) = is_insecure_from_opts {
1999- match is_insecure_from_opts {
2000- true => {
2001- if !insecure {
2002- tracing:: warn!(
2003- "--insecure passed as option but UKI cmdline does not support it"
2004- )
2005- }
2006- }
2086+ let mut boot_label = String :: new ( ) ;
20072087
2008- false => {
2009- if insecure {
2010- tracing:: warn!( "UKI cmdline has composefs set as insecure" )
2011- }
2012- }
2013- }
2088+ for entry in entries {
2089+ match entry {
2090+ ComposefsBootEntry :: Type1 ( ..) => tracing:: debug!( "Skipping Type1 Entry" ) ,
2091+ ComposefsBootEntry :: UsrLibModulesVmLinuz ( ..) => {
2092+ tracing:: debug!( "Skipping vmlinuz in /usr/lib/modules" )
20142093 }
20152094
2016- let boot_label = uki:: get_boot_label ( & uki) . context ( "Getting UKI boot label" ) ?;
2017-
2018- if composefs_cmdline != * id {
2019- anyhow:: bail!(
2020- "The UKI has the wrong composefs= parameter (is '{composefs_cmdline:?}', should be {id:?})"
2021- ) ;
2095+ ComposefsBootEntry :: UsrLibModulesUki ( UsrLibModulesUki {
2096+ file,
2097+ file_path,
2098+ pe_type,
2099+ ..
2100+ } )
2101+ | ComposefsBootEntry :: Type2 ( Type2Entry {
2102+ file,
2103+ file_path,
2104+ pe_type,
2105+ } ) => {
2106+ let ret = write_pe_to_esp (
2107+ & repo,
2108+ & file,
2109+ & file_path,
2110+ pe_type,
2111+ & id. to_hex ( ) ,
2112+ is_insecure_from_opts,
2113+ & mounted_efi,
2114+ ) ?;
2115+
2116+ if let Some ( label) = ret {
2117+ boot_label = label;
2118+ }
20222119 }
2023-
2024- // Write the UKI to ESP
2025- let efi_linux_path = mounted_efi. join ( EFI_LINUX ) ;
2026- create_dir_all ( & efi_linux_path) . context ( "Creating EFI/Linux" ) ?;
2027-
2028- let efi_linux =
2029- cap_std:: fs:: Dir :: open_ambient_dir ( & efi_linux_path, cap_std:: ambient_authority ( ) )
2030- . with_context ( || format ! ( "Opening {efi_linux_path:?}" ) ) ?;
2031-
2032- efi_linux
2033- . atomic_write ( format ! ( "{}.efi" , id. to_hex( ) ) , uki)
2034- . context ( "Writing UKI" ) ?;
2035-
2036- rustix:: fs:: fsync (
2037- efi_linux
2038- . reopen_as_ownedfd ( )
2039- . context ( "Reopening as owned fd" ) ?,
2040- )
2041- . context ( "fsync" ) ?;
2042-
2043- boot_label
2044- }
2045- } ;
2120+ } ;
2121+ }
20462122
20472123 Command :: new ( "umount" )
20482124 . arg ( & mounted_efi)
@@ -2194,11 +2270,11 @@ fn setup_composefs_boot(root_setup: &RootSetup, state: &State, image_id: &str) -
21942270 let entries = fs. transform_for_boot ( & repo) ?;
21952271 let id = fs. commit_image ( & repo, None ) ?;
21962272
2197- let Some ( entry) = entries. into_iter ( ) . next ( ) else {
2273+ let Some ( entry) = entries. iter ( ) . next ( ) else {
21982274 anyhow:: bail!( "No boot entries!" ) ;
21992275 } ;
22002276
2201- let boot_type = BootType :: from ( & entry) ;
2277+ let boot_type = BootType :: from ( entry) ;
22022278 let mut boot_digest: Option < String > = None ;
22032279
22042280 match boot_type {
@@ -2216,7 +2292,7 @@ fn setup_composefs_boot(root_setup: &RootSetup, state: &State, image_id: &str) -
22162292 BootSetupType :: Setup ( ( & root_setup, & state, & fs) ) ,
22172293 repo,
22182294 & id,
2219- entry ,
2295+ entries ,
22202296 ) ?,
22212297 } ;
22222298
0 commit comments