@@ -18,7 +18,7 @@ use std::fs::create_dir_all;
18
18
use std:: io:: Write ;
19
19
use std:: os:: fd:: { AsFd , AsRawFd } ;
20
20
use std:: os:: unix:: process:: CommandExt ;
21
- use std:: path:: Path ;
21
+ use std:: path:: { Path , PathBuf } ;
22
22
use std:: process:: Command ;
23
23
use std:: str:: FromStr ;
24
24
use std:: sync:: Arc ;
@@ -107,6 +107,10 @@ const DEFAULT_REPO_CONFIG: &[(&str, &str)] = &[
107
107
/// Kernel argument used to specify we want the rootfs mounted read-write by default
108
108
const RW_KARG : & str = "rw" ;
109
109
110
+ /// The ESP partition label on Fedora CoreOS derivatives
111
+ const COREOS_ESP_PART_LABEL : & str = "EFI-SYSTEM" ;
112
+ const ANACONDA_ESP_PART_LABEL : & str = "EFI\\ x20System\\ x20Partition" ;
113
+
110
114
#[ derive( clap:: Args , Debug , Clone , Serialize , Deserialize , PartialEq , Eq ) ]
111
115
pub ( crate ) struct InstallTargetOpts {
112
116
// TODO: A size specifier which allocates free space for the root in *addition* to the base container image size
@@ -1542,6 +1546,44 @@ fn setup_composefs_bls_boot(
1542
1546
Ok ( ( ) )
1543
1547
}
1544
1548
1549
+ fn get_esp_device ( ) -> Option < PathBuf > {
1550
+ let esp_devices = [ COREOS_ESP_PART_LABEL , ANACONDA_ESP_PART_LABEL ]
1551
+ . into_iter ( )
1552
+ . map ( |p| Path :: new ( "/dev/disk/by-partlabel/" ) . join ( p) ) ;
1553
+ let mut esp_device = None ;
1554
+ for path in esp_devices {
1555
+ if path. exists ( ) {
1556
+ esp_device = Some ( path) ;
1557
+ break ;
1558
+ }
1559
+ }
1560
+ return esp_device;
1561
+ }
1562
+
1563
+ /// esp_device - /dev/disk/by-partlabel/<ESP_DEVICE>
1564
+ fn get_esp_uuid ( esp_device : & PathBuf ) -> Result < String > {
1565
+ // not using blkid here as the output might change from under us
1566
+ let resolved = std:: fs:: canonicalize ( esp_device)
1567
+ . with_context ( || format ! ( "Failed to resolve link {esp_device:?}" ) ) ?;
1568
+
1569
+ let mut uuid = String :: new ( ) ;
1570
+
1571
+ for dir_entry in std:: fs:: read_dir ( "/dev/disk/by-uuid" ) ? {
1572
+ let file = dir_entry?;
1573
+
1574
+ let uuid_resolve = std:: fs:: canonicalize ( file. path ( ) )
1575
+ . with_context ( || format ! ( "Failed to resolve link {file:?}" ) ) ?;
1576
+
1577
+ if resolved == uuid_resolve {
1578
+ // SAFETY: UUID has to be [A-Fa-f0-9\-]
1579
+ uuid = file. file_name ( ) . to_string_lossy ( ) . into_owned ( ) ;
1580
+ break ;
1581
+ }
1582
+ }
1583
+
1584
+ Ok ( uuid)
1585
+ }
1586
+
1545
1587
#[ context( "Setting up UKI boot" ) ]
1546
1588
fn setup_composefs_uki_boot (
1547
1589
root_setup : & RootSetup ,
@@ -1550,35 +1592,47 @@ fn setup_composefs_uki_boot(
1550
1592
id : & Sha256HashValue ,
1551
1593
entry : BootEntry < Sha256HashValue > ,
1552
1594
) -> Result < ( ) > {
1553
- let rootfs_uuid = match & root_setup . rootfs_uuid {
1554
- Some ( u ) => u ,
1555
- None => anyhow:: bail!( "Expected rootfs to have a UUID by now" ) ,
1595
+ // Write the UKI to <ESP>/EFI/Linux
1596
+ let Some ( esp_device ) = get_esp_device ( ) else {
1597
+ anyhow:: bail!( "ESP device not found" ) ;
1556
1598
} ;
1557
1599
1558
- let boot_dir = root_setup. physical_root_path . join ( "boot" ) ;
1559
- create_dir_all ( & boot_dir) . context ( "Failed to create boot dir" ) ?;
1600
+ let mounted_esp: PathBuf = root_setup. physical_root_path . join ( "../esp" ) . into ( ) ;
1601
+ create_dir_all ( & mounted_esp) . context ( "Failed to create dir {mounted_esp:?}" ) ?;
1602
+
1603
+ Task :: new ( "Mounting ESP" , "mount" )
1604
+ . args ( [ & esp_device, & mounted_esp. clone ( ) ] )
1605
+ . run ( ) ?;
1560
1606
1561
1607
composefs_write_boot_simple (
1562
1608
& repo,
1563
1609
entry,
1564
1610
& id,
1565
- boot_dir . as_std_path ( ) ,
1611
+ & mounted_esp ,
1566
1612
None ,
1567
1613
Some ( & format ! ( "{}" , id. to_hex( ) ) ) ,
1568
1614
& [ ] ,
1569
1615
) ?;
1570
1616
1617
+ Task :: new ( "Unmounting ESP" , "umount" )
1618
+ . arg ( mounted_esp)
1619
+ . run ( ) ?;
1620
+
1621
+ let boot_dir = root_setup. physical_root_path . join ( "boot" ) ;
1622
+ create_dir_all ( & boot_dir) . context ( "Failed to create boot dir" ) ?;
1623
+
1571
1624
// Add the user grug cfg
1572
1625
let grub_user_config = format ! (
1573
1626
r#"
1574
1627
menuentry "Fedora Bootc UKI" {{
1575
1628
insmod fat
1576
1629
insmod chain
1577
- search --no-floppy --set=root --fs-uuid {rootfs_uuid }
1578
- chainloader /boot/ EFI/Linux/{uki_id}.efi
1630
+ search --no-floppy --set=root --fs-uuid {esp_uuid }
1631
+ chainloader /EFI/Linux/{uki_id}.efi
1579
1632
}}
1580
1633
"# ,
1581
- uki_id = id. to_hex( )
1634
+ uki_id = id. to_hex( ) ,
1635
+ esp_uuid = get_esp_uuid( & esp_device) ?
1582
1636
) ;
1583
1637
1584
1638
std:: fs:: write ( boot_dir. join ( "grub2/user.cfg" ) , grub_user_config)
0 commit comments