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