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