@@ -48,6 +48,7 @@ use ostree_ext::composefs::{
48
48
repository:: Repository as ComposefsRepository ,
49
49
util:: Sha256Digest ,
50
50
} ;
51
+ use ostree_ext:: composefs_boot:: bootloader:: read_file;
51
52
use ostree_ext:: composefs_boot:: {
52
53
bootloader:: BootEntry as ComposefsBootEntry ,
53
54
write_boot:: write_boot_simple as composefs_write_boot_simple, BootOps ,
@@ -72,6 +73,7 @@ use schemars::JsonSchema;
72
73
73
74
#[ cfg( feature = "install-to-disk" ) ]
74
75
use self :: baseline:: InstallBlockDeviceOpts ;
76
+ use crate :: bls_config:: { parse_bls_config, BLSConfig } ;
75
77
use crate :: boundimage:: { BoundImage , ResolvedBoundImage } ;
76
78
use crate :: containerenv:: ContainerExecutionInfo ;
77
79
use crate :: deploy:: { prepare_for_pull, pull_from_prepared, PreparedImportMeta , PreparedPullResult } ;
@@ -1543,6 +1545,31 @@ async fn initialize_composefs_repository(
1543
1545
composefs_oci_pull ( & Arc :: new ( repo) , & format ! ( "{transport}{image_name}" ) , None ) . await
1544
1546
}
1545
1547
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
+
1546
1573
pub ( crate ) enum BootSetupType < ' a > {
1547
1574
/// For initial setup, i.e. install to-disk
1548
1575
Setup ( & ' a RootSetup ) ,
@@ -1556,38 +1583,97 @@ pub(crate) fn setup_composefs_bls_boot(
1556
1583
// TODO: Make this generic
1557
1584
repo : ComposefsRepository < Sha256HashValue > ,
1558
1585
id : & Sha256HashValue ,
1559
- entry : BootEntry < Sha256HashValue > ,
1586
+ entry : ComposefsBootEntry < Sha256HashValue > ,
1560
1587
) -> 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) => {
1564
1592
// 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
+ }
1568
1598
1569
1599
BootSetupType :: Upgrade => (
1570
1600
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 ( " " ) ,
1573
1607
) ,
1574
1608
} ;
1575
1609
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" ) ;
1580
1611
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 ( ( ) )
1591
1677
}
1592
1678
1593
1679
pub fn get_esp_partition ( device : & str ) -> Result < ( String , Option < String > ) > {
0 commit comments