@@ -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 } ;
@@ -1543,6 +1545,31 @@ async fn initialize_composefs_repository(
15431545 composefs_oci_pull ( & Arc :: new ( repo) , & format ! ( "{transport}{image_name}" ) , None ) . await
15441546}
15451547
1548+ fn get_booted_bls ( ) -> Result < BLSConfig > {
1549+ let cmdline = crate :: kernel:: parse_cmdline ( ) ?;
1550+ let booted = cmdline. iter ( ) . find_map ( |x| x. strip_prefix ( "composefs=" ) ) ;
1551+
1552+ let Some ( booted) = booted else {
1553+ anyhow:: bail!( "Failed to find composefs parameter in kernel cmdline" ) ;
1554+ } ;
1555+
1556+ for entry in std:: fs:: read_dir ( "/sysroot/boot/loader/entries" ) ? {
1557+ let entry = entry?;
1558+
1559+ if !entry. file_name ( ) . as_str ( ) ?. ends_with ( ".conf" ) {
1560+ continue ;
1561+ }
1562+
1563+ let bls = parse_bls_config ( & std:: fs:: read_to_string ( & entry. path ( ) ) ?) ?;
1564+
1565+ if bls. options . contains ( booted) {
1566+ return Ok ( bls) ;
1567+ }
1568+ }
1569+
1570+ Err ( anyhow:: anyhow!( "Booted BLS not found" ) )
1571+ }
1572+
15461573pub ( crate ) enum BootSetupType < ' a > {
15471574 /// For initial setup, i.e. install to-disk
15481575 Setup ( & ' a RootSetup ) ,
@@ -1556,38 +1583,97 @@ pub(crate) fn setup_composefs_bls_boot(
15561583 // TODO: Make this generic
15571584 repo : ComposefsRepository < Sha256HashValue > ,
15581585 id : & Sha256HashValue ,
1559- entry : BootEntry < Sha256HashValue > ,
1586+ entry : ComposefsBootEntry < Sha256HashValue > ,
15601587) -> Result < ( ) > {
1561- let ( root_path, cmdline_refs, entry_id) = match setup_type {
1562- BootSetupType :: Setup ( root_setup) => (
1563- root_setup. physical_root_path . clone ( ) ,
1588+ let id_hex = id. to_hex ( ) ;
1589+
1590+ let ( root_path, cmdline_refs) = match setup_type {
1591+ BootSetupType :: Setup ( root_setup) => {
15641592 // root_setup.kargs has [root=UUID=<UUID>, "rw"]
1565- & root_setup. kargs ,
1566- format ! ( "{}" , id. to_hex( ) ) ,
1567- ) ,
1593+ let mut cmdline_options = String :: from ( root_setup. kargs . join ( " " ) ) ;
1594+ cmdline_options. push_str ( & format ! ( " composefs={id_hex}" ) ) ;
1595+
1596+ ( root_setup. physical_root_path . clone ( ) , cmdline_options)
1597+ }
15681598
15691599 BootSetupType :: Upgrade => (
15701600 Utf8PathBuf :: from ( "/sysroot" ) ,
1571- & vec ! [ format!( "root=UUID={DPS_UUID}" ) , RW_KARG . to_string( ) ] ,
1572- format ! ( "{}.staged" , id. to_hex( ) ) ,
1601+ vec ! [
1602+ format!( "root=UUID={DPS_UUID}" ) ,
1603+ RW_KARG . to_string( ) ,
1604+ format!( "composefs={id_hex}" ) ,
1605+ ]
1606+ . join ( " " ) ,
15731607 ) ,
15741608 } ;
15751609
1576- let str_slice = cmdline_refs
1577- . iter ( )
1578- . map ( |x| x. as_str ( ) )
1579- . collect :: < Vec < & str > > ( ) ;
1610+ let boot_dir = root_path. join ( "boot" ) ;
15801611
1581- composefs_write_boot_simple (
1582- & repo,
1583- entry,
1584- & id,
1585- false ,
1586- root_path. as_std_path ( ) ,
1587- Some ( "boot" ) ,
1588- Some ( & entry_id) ,
1589- & str_slice,
1590- )
1612+ let bls_config = match & entry {
1613+ ComposefsBootEntry :: Type1 ( ..) => todo ! ( ) ,
1614+ ComposefsBootEntry :: Type2 ( ..) => todo ! ( ) ,
1615+ ComposefsBootEntry :: UsrLibModulesUki ( ..) => todo ! ( ) ,
1616+
1617+ ComposefsBootEntry :: UsrLibModulesVmLinuz ( usr_lib_modules_vmlinuz) => {
1618+ // Write the initrd and vmlinuz at /boot/<id>/
1619+ let path = boot_dir. join ( & id_hex) ;
1620+ create_dir_all ( & path) ?;
1621+
1622+ let vmlinuz_path = path. join ( "vmlinuz" ) ;
1623+ let initrd_path = path. join ( "initrd" ) ;
1624+
1625+ std:: fs:: write (
1626+ & vmlinuz_path,
1627+ read_file ( & usr_lib_modules_vmlinuz. vmlinuz , & repo) . context ( "Reading vmlinuz" ) ?,
1628+ )
1629+ . context ( "Writing vmlinuz to path" ) ?;
1630+
1631+ if let Some ( initramfs) = & usr_lib_modules_vmlinuz. initramfs {
1632+ std:: fs:: write (
1633+ & initrd_path,
1634+ read_file ( initramfs, & repo) . context ( "Reading initramfs" ) ?,
1635+ )
1636+ . context ( "Writing initrd to path" ) ?;
1637+ } else {
1638+ anyhow:: bail!( "initramfs not found" ) ;
1639+ } ;
1640+
1641+ BLSConfig {
1642+ title : Some ( id_hex. clone ( ) ) ,
1643+ version : 1 ,
1644+ linux : format ! ( "/boot/{id_hex}/vmlinuz" ) ,
1645+ initrd : format ! ( "/boot/{id_hex}/initrd" ) ,
1646+ options : cmdline_refs,
1647+ extra : HashMap :: new ( ) ,
1648+ }
1649+ }
1650+ } ;
1651+
1652+ let ( entries_path, booted_bls) = if matches ! ( setup_type, BootSetupType :: Upgrade ) {
1653+ let mut booted_bls = get_booted_bls ( ) ?;
1654+ booted_bls. version = 0 ; // entries are sorted by their filename in reverse order
1655+
1656+ // This will be atomically renamed to 'loader/entries' on shutdown/reboot
1657+ ( boot_dir. join ( "loader/entries.staged" ) , Some ( booted_bls) )
1658+ } else {
1659+ ( boot_dir. join ( "loader/entries" ) , None )
1660+ } ;
1661+
1662+ create_dir_all ( & entries_path) . with_context ( || format ! ( "Creating {:?}" , entries_path) ) ?;
1663+
1664+ std:: fs:: write (
1665+ entries_path. join ( format ! ( "bootc-composefs-{}.conf" , bls_config. version) ) ,
1666+ bls_config. to_string ( ) . as_bytes ( ) ,
1667+ ) ?;
1668+
1669+ if let Some ( booted_bls) = booted_bls {
1670+ std:: fs:: write (
1671+ entries_path. join ( format ! ( "bootc-composefs-{}.conf" , booted_bls. version) ) ,
1672+ booted_bls. to_string ( ) . as_bytes ( ) ,
1673+ ) ?;
1674+ }
1675+
1676+ Ok ( ( ) )
15911677}
15921678
15931679pub fn get_esp_partition ( device : & str ) -> Result < ( String , Option < String > ) > {
0 commit comments