@@ -48,6 +48,7 @@ use ostree_ext::composefs::{
4848 repository:: Repository as ComposefsRepository ,
4949 util:: Sha256Digest ,
5050} ;
51+ use ostree_ext:: composefs_boot:: bootloader:: read_file;
5152use ostree_ext:: composefs_boot:: {
5253 bootloader:: BootEntry as ComposefsBootEntry ,
5354 write_boot:: write_boot_simple as composefs_write_boot_simple, BootOps ,
@@ -72,6 +73,7 @@ use schemars::JsonSchema;
7273
7374#[ cfg( feature = "install-to-disk" ) ]
7475use self :: baseline:: InstallBlockDeviceOpts ;
76+ use crate :: bls_config:: { parse_bls_config, BLSConfig } ;
7577use crate :: boundimage:: { BoundImage , ResolvedBoundImage } ;
7678use crate :: containerenv:: ContainerExecutionInfo ;
7779use crate :: deploy:: { prepare_for_pull, pull_from_prepared, PreparedImportMeta , PreparedPullResult } ;
@@ -1550,6 +1552,31 @@ async fn initialize_composefs_repository(
15501552 composefs_oci_pull ( & Arc :: new ( repo) , & format ! ( "{transport}{image_name}" ) , None ) . await
15511553}
15521554
1555+ fn get_booted_bls ( ) -> Result < BLSConfig > {
1556+ let cmdline = crate :: kernel:: parse_cmdline ( ) ?;
1557+ let booted = cmdline. iter ( ) . find_map ( |x| x. strip_prefix ( "composefs=" ) ) ;
1558+
1559+ let Some ( booted) = booted else {
1560+ anyhow:: bail!( "Failed to find composefs parameter in kernel cmdline" ) ;
1561+ } ;
1562+
1563+ for entry in std:: fs:: read_dir ( "/sysroot/boot/loader/entries" ) ? {
1564+ let entry = entry?;
1565+
1566+ if !entry. file_name ( ) . as_str ( ) ?. ends_with ( ".conf" ) {
1567+ continue ;
1568+ }
1569+
1570+ let bls = parse_bls_config ( & std:: fs:: read_to_string ( & entry. path ( ) ) ?) ?;
1571+
1572+ if bls. options . contains ( booted) {
1573+ return Ok ( bls) ;
1574+ }
1575+ }
1576+
1577+ Err ( anyhow:: anyhow!( "Booted BLS not found" ) )
1578+ }
1579+
15531580pub ( crate ) enum BootSetupType < ' a > {
15541581 /// For initial setup, i.e. install to-disk
15551582 Setup ( & ' a RootSetup ) ,
@@ -1563,38 +1590,97 @@ pub(crate) fn setup_composefs_bls_boot(
15631590 // TODO: Make this generic
15641591 repo : ComposefsRepository < Sha256HashValue > ,
15651592 id : & Sha256HashValue ,
1566- entry : BootEntry < Sha256HashValue > ,
1593+ entry : ComposefsBootEntry < Sha256HashValue > ,
15671594) -> Result < ( ) > {
1568- let ( root_path, cmdline_refs, entry_id) = match setup_type {
1569- BootSetupType :: Setup ( root_setup) => (
1570- root_setup. physical_root_path . clone ( ) ,
1595+ let id_hex = id. to_hex ( ) ;
1596+
1597+ let ( root_path, cmdline_refs) = match setup_type {
1598+ BootSetupType :: Setup ( root_setup) => {
15711599 // root_setup.kargs has [root=UUID=<UUID>, "rw"]
1572- & root_setup. kargs ,
1573- format ! ( "{}" , id. to_hex( ) ) ,
1574- ) ,
1600+ let mut cmdline_options = String :: from ( root_setup. kargs . join ( " " ) ) ;
1601+ cmdline_options. push_str ( & format ! ( " composefs={id_hex}" ) ) ;
1602+
1603+ ( root_setup. physical_root_path . clone ( ) , cmdline_options)
1604+ }
15751605
15761606 BootSetupType :: Upgrade => (
15771607 Utf8PathBuf :: from ( "/sysroot" ) ,
1578- & vec ! [ format!( "root=UUID={DPS_UUID}" ) , RW_KARG . to_string( ) ] ,
1579- format ! ( "{}.staged" , id. to_hex( ) ) ,
1608+ vec ! [
1609+ format!( "root=UUID={DPS_UUID}" ) ,
1610+ RW_KARG . to_string( ) ,
1611+ format!( "composefs={id_hex}" ) ,
1612+ ]
1613+ . join ( " " ) ,
15801614 ) ,
15811615 } ;
15821616
1583- let str_slice = cmdline_refs
1584- . iter ( )
1585- . map ( |x| x. as_str ( ) )
1586- . collect :: < Vec < & str > > ( ) ;
1617+ let boot_dir = root_path. join ( "boot" ) ;
15871618
1588- composefs_write_boot_simple (
1589- & repo,
1590- entry,
1591- & id,
1592- false ,
1593- root_path. as_std_path ( ) ,
1594- Some ( "boot" ) ,
1595- Some ( & entry_id) ,
1596- & str_slice,
1597- )
1619+ let bls_config = match & entry {
1620+ ComposefsBootEntry :: Type1 ( ..) => todo ! ( ) ,
1621+ ComposefsBootEntry :: Type2 ( ..) => todo ! ( ) ,
1622+ ComposefsBootEntry :: UsrLibModulesUki ( ..) => todo ! ( ) ,
1623+
1624+ ComposefsBootEntry :: UsrLibModulesVmLinuz ( usr_lib_modules_vmlinuz) => {
1625+ // Write the initrd and vmlinuz at /boot/<id>/
1626+ let path = boot_dir. join ( & id_hex) ;
1627+ create_dir_all ( & path) ?;
1628+
1629+ let vmlinuz_path = path. join ( "vmlinuz" ) ;
1630+ let initrd_path = path. join ( "initrd" ) ;
1631+
1632+ std:: fs:: write (
1633+ & vmlinuz_path,
1634+ read_file ( & usr_lib_modules_vmlinuz. vmlinuz , & repo) . context ( "Reading vmlinuz" ) ?,
1635+ )
1636+ . context ( "Writing vmlinuz to path" ) ?;
1637+
1638+ if let Some ( initramfs) = & usr_lib_modules_vmlinuz. initramfs {
1639+ std:: fs:: write (
1640+ & initrd_path,
1641+ read_file ( initramfs, & repo) . context ( "Reading initramfs" ) ?,
1642+ )
1643+ . context ( "Writing initrd to path" ) ?;
1644+ } else {
1645+ anyhow:: bail!( "initramfs not found" ) ;
1646+ } ;
1647+
1648+ BLSConfig {
1649+ title : Some ( id_hex. clone ( ) ) ,
1650+ version : 1 ,
1651+ linux : format ! ( "/boot/{id_hex}/vmlinuz" ) ,
1652+ initrd : format ! ( "/boot/{id_hex}/initrd" ) ,
1653+ options : cmdline_refs,
1654+ extra : HashMap :: new ( ) ,
1655+ }
1656+ }
1657+ } ;
1658+
1659+ let ( entries_path, booted_bls) = if matches ! ( setup_type, BootSetupType :: Upgrade ) {
1660+ let mut booted_bls = get_booted_bls ( ) ?;
1661+ booted_bls. version = 0 ; // entries are sorted by their filename in reverse order
1662+
1663+ // This will be atomically renamed to 'loader/entries' on shutdown/reboot
1664+ ( boot_dir. join ( "loader/entries.staged" ) , Some ( booted_bls) )
1665+ } else {
1666+ ( boot_dir. join ( "loader/entries" ) , None )
1667+ } ;
1668+
1669+ create_dir_all ( & entries_path) . with_context ( || format ! ( "Creating {:?}" , entries_path) ) ?;
1670+
1671+ std:: fs:: write (
1672+ entries_path. join ( format ! ( "bootc-composefs-{}.conf" , bls_config. version) ) ,
1673+ bls_config. to_string ( ) . as_bytes ( ) ,
1674+ ) ?;
1675+
1676+ if let Some ( booted_bls) = booted_bls {
1677+ std:: fs:: write (
1678+ entries_path. join ( format ! ( "bootc-composefs-{}.conf" , booted_bls. version) ) ,
1679+ booted_bls. to_string ( ) . as_bytes ( ) ,
1680+ ) ?;
1681+ }
1682+
1683+ Ok ( ( ) )
15981684}
15991685
16001686pub fn get_esp_partition ( device : & str ) -> Result < ( String , Option < String > ) > {
0 commit comments