@@ -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
@@ -1533,6 +1537,44 @@ fn setup_composefs_bls_boot(
1533
1537
Ok ( ( ) )
1534
1538
}
1535
1539
1540
+ fn get_esp_device ( ) -> Option < PathBuf > {
1541
+ let esp_devices = [ COREOS_ESP_PART_LABEL , ANACONDA_ESP_PART_LABEL ]
1542
+ . into_iter ( )
1543
+ . map ( |p| Path :: new ( "/dev/disk/by-partlabel/" ) . join ( p) ) ;
1544
+ let mut esp_device = None ;
1545
+ for path in esp_devices {
1546
+ if path. exists ( ) {
1547
+ esp_device = Some ( path) ;
1548
+ break ;
1549
+ }
1550
+ }
1551
+ return esp_device;
1552
+ }
1553
+
1554
+ /// esp_device - /dev/disk/by-partlabel/<ESP_DEVICE>
1555
+ fn get_esp_uuid ( esp_device : & PathBuf ) -> Result < String > {
1556
+ // not using blkid here as the output might change from under us
1557
+ let resolved = std:: fs:: canonicalize ( esp_device)
1558
+ . with_context ( || format ! ( "Failed to resolve link {esp_device:?}" ) ) ?;
1559
+
1560
+ let mut uuid = String :: new ( ) ;
1561
+
1562
+ for dir_entry in std:: fs:: read_dir ( "/dev/disk/by-uuid" ) ? {
1563
+ let file = dir_entry?;
1564
+
1565
+ let uuid_resolve = std:: fs:: canonicalize ( file. path ( ) )
1566
+ . with_context ( || format ! ( "Failed to resolve link {file:?}" ) ) ?;
1567
+
1568
+ if resolved == uuid_resolve {
1569
+ // SAFETY: UUID has to be [A-Fa-f0-9\-]
1570
+ uuid = file. file_name ( ) . to_string_lossy ( ) . into_owned ( ) ;
1571
+ break ;
1572
+ }
1573
+ }
1574
+
1575
+ Ok ( uuid)
1576
+ }
1577
+
1536
1578
#[ context( "Setting up UKI boot" ) ]
1537
1579
fn setup_composefs_uki_boot (
1538
1580
root_setup : & RootSetup ,
@@ -1541,35 +1583,47 @@ fn setup_composefs_uki_boot(
1541
1583
id : & Sha256HashValue ,
1542
1584
entry : BootEntry < Sha256HashValue > ,
1543
1585
) -> Result < ( ) > {
1544
- let rootfs_uuid = match & root_setup . rootfs_uuid {
1545
- Some ( u ) => u ,
1546
- None => anyhow:: bail!( "Expected rootfs to have a UUID by now" ) ,
1586
+ // Write the UKI to <ESP>/EFI/Linux
1587
+ let Some ( esp_device ) = get_esp_device ( ) else {
1588
+ anyhow:: bail!( "ESP device not found" ) ;
1547
1589
} ;
1548
1590
1549
- let boot_dir = root_setup. physical_root_path . join ( "boot" ) ;
1550
- create_dir_all ( & boot_dir) . context ( "Failed to create boot dir" ) ?;
1591
+ let mounted_esp: PathBuf = root_setup. physical_root_path . join ( "../esp" ) . into ( ) ;
1592
+ create_dir_all ( & mounted_esp) . context ( "Failed to create dir {mounted_esp:?}" ) ?;
1593
+
1594
+ Task :: new ( "Mounting ESP" , "mount" )
1595
+ . args ( [ & esp_device, & mounted_esp. clone ( ) ] )
1596
+ . run ( ) ?;
1551
1597
1552
1598
composefs_write_boot_simple (
1553
1599
& repo,
1554
1600
entry,
1555
1601
& id,
1556
- boot_dir . as_std_path ( ) ,
1602
+ & mounted_esp ,
1557
1603
None ,
1558
1604
Some ( & format ! ( "{}" , id. to_hex( ) ) ) ,
1559
1605
& [ ] ,
1560
1606
) ?;
1561
1607
1608
+ Task :: new ( "Unmounting ESP" , "umount" )
1609
+ . arg ( mounted_esp)
1610
+ . run ( ) ?;
1611
+
1612
+ let boot_dir = root_setup. physical_root_path . join ( "boot" ) ;
1613
+ create_dir_all ( & boot_dir) . context ( "Failed to create boot dir" ) ?;
1614
+
1562
1615
// Add the user grug cfg
1563
1616
let grub_user_config = format ! (
1564
1617
r#"
1565
1618
menuentry "Fedora Bootc UKI" {{
1566
1619
insmod fat
1567
1620
insmod chain
1568
- search --no-floppy --set=root --fs-uuid {rootfs_uuid }
1569
- chainloader /boot/ EFI/Linux/{uki_id}.efi
1621
+ search --no-floppy --set=root --fs-uuid {esp_uuid }
1622
+ chainloader /EFI/Linux/{uki_id}.efi
1570
1623
}}
1571
1624
"# ,
1572
- uki_id = id. to_hex( )
1625
+ uki_id = id. to_hex( ) ,
1626
+ esp_uuid = get_esp_uuid( & esp_device) ?
1573
1627
) ;
1574
1628
1575
1629
std:: fs:: write ( boot_dir. join ( "grub2/user.cfg" ) , grub_user_config)
0 commit comments