@@ -47,6 +47,7 @@ use ostree_ext::composefs::{
47
47
repository:: Repository as ComposefsRepository ,
48
48
util:: Sha256Digest ,
49
49
} ;
50
+ use ostree_ext:: composefs_boot:: bootloader:: read_file;
50
51
use ostree_ext:: composefs_boot:: {
51
52
bootloader:: BootEntry as ComposefsBootEntry ,
52
53
write_boot:: write_boot_simple as composefs_write_boot_simple, BootOps ,
@@ -71,6 +72,7 @@ use schemars::JsonSchema;
71
72
72
73
#[ cfg( feature = "install-to-disk" ) ]
73
74
use self :: baseline:: InstallBlockDeviceOpts ;
75
+ use crate :: bls_config:: { parse_bls_config, BLSConfig } ;
74
76
use crate :: boundimage:: { BoundImage , ResolvedBoundImage } ;
75
77
use crate :: containerenv:: ContainerExecutionInfo ;
76
78
use crate :: deploy:: { prepare_for_pull, pull_from_prepared, PreparedImportMeta , PreparedPullResult } ;
@@ -1552,6 +1554,31 @@ async fn initialize_composefs_repository(
1552
1554
composefs_oci_pull ( & Arc :: new ( repo) , & format ! ( "{transport}{image_name}" ) , None ) . await
1553
1555
}
1554
1556
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
+
1555
1582
pub ( crate ) enum BootSetupType < ' a > {
1556
1583
/// For initial setup, i.e. install to-disk
1557
1584
Setup ( & ' a RootSetup ) ,
@@ -1565,38 +1592,97 @@ pub(crate) fn setup_composefs_bls_boot(
1565
1592
// TODO: Make this generic
1566
1593
repo : ComposefsRepository < Sha256HashValue > ,
1567
1594
id : & Sha256HashValue ,
1568
- entry : BootEntry < Sha256HashValue > ,
1595
+ entry : ComposefsBootEntry < Sha256HashValue > ,
1569
1596
) -> 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) => {
1573
1601
// 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
+ }
1577
1607
1578
1608
BootSetupType :: Upgrade => (
1579
1609
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 ( " " ) ,
1582
1616
) ,
1583
1617
} ;
1584
1618
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" ) ;
1589
1620
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 ( ( ) )
1600
1686
}
1601
1687
1602
1688
pub fn get_esp_partition ( device : & str ) -> Result < ( String , Option < String > ) > {
0 commit comments