@@ -568,50 +568,44 @@ impl Component for Efi {
568568 }
569569
570570 fn generate_update_metadata ( & self , sysroot : & str ) -> Result < Option < ContentMetadata > > {
571- let sysroot_path = Path :: new ( sysroot) ;
571+ let sysroot_path = Utf8Path :: new ( sysroot) ;
572572 let sysroot_dir = Dir :: open_ambient_dir ( sysroot_path, cap_std:: ambient_authority ( ) ) ?;
573573
574- if let Some ( ostreeboot) = sysroot_dir
574+ let ostreeboot = sysroot_dir
575575 . open_dir_optional ( ostreeutil:: BOOT_PREFIX )
576- . context ( "Opening usr/lib/ostree-boot" ) ?
577- {
578- let cruft = [ "loader" , "grub2" ] ;
579- for p in cruft. iter ( ) {
580- ostreeboot. remove_all_optional ( p) ?;
581- }
582- // Transfer ostree-boot EFI files to usr/lib/efi
583- transfer_ostree_boot_to_usr ( sysroot_path) ?;
576+ . context ( "Opening usr/lib/ostree-boot" ) ?;
577+
578+ // Newer images >= F44 have boot entries in /usr/lib/efi, but older images
579+ // have them in /usr/lib/ostree-boot, which we move to /usr/lib/bootupd/updates/EFI
580+ let metadata = match ostreeboot {
581+ Some ( ostreeboot) => {
582+ let cruft = [ "loader" , "grub2" ] ;
583+ for p in cruft. iter ( ) {
584+ ostreeboot. remove_all_optional ( p) ?;
585+ }
584586
585- // Remove usr/lib/ostree-boot/efi/EFI dir (after transfer) or if it is empty
586- ostreeboot. remove_all_optional ( "efi/EFI" ) ?;
587- }
587+ let meta = if sysroot_path. join ( EFILIB ) . exists ( ) {
588+ // Transfer usr/lib/ostree-boot/EFI files to usr/lib/efi
589+ transfer_ostree_boot_to_usr ( sysroot_path) ?;
590+ generate_meta_from_usr_efi ( sysroot_path) ?
591+ } else {
592+ // Transfer usr/lib/ostree-boot/EFI files to usr/lib/bootupd/updates/EFI
593+ transfer_ostree_boot_to_bootupd_updates ( sysroot_path, self ) ?
594+ } ;
588595
589- if let Some ( efi_components) =
590- get_efi_component_from_usr ( Utf8Path :: from_path ( sysroot_path) . unwrap ( ) , EFILIB ) ?
591- {
592- let mut packages = Vec :: new ( ) ;
593- let mut modules_vec: Vec < Module > = vec ! [ ] ;
594- for efi in efi_components {
595- packages. push ( format ! ( "{}-{}" , efi. name, efi. version) ) ;
596- modules_vec. push ( Module {
597- name : efi. name ,
598- rpm_evr : efi. version ,
599- } ) ;
596+ // Remove usr/lib/ostree-boot/efi/EFI dir (after transfer) or if it is empty
597+ ostreeboot. remove_all_optional ( "efi/EFI" ) ?;
598+
599+ meta
600600 }
601- modules_vec. sort_unstable ( ) ;
602-
603- // change to now to workaround https://github.com/coreos/bootupd/issues/933
604- let timestamp = std:: time:: SystemTime :: now ( ) ;
605- let meta = ContentMetadata {
606- timestamp : chrono:: DateTime :: < Utc > :: from ( timestamp) ,
607- version : packages. join ( "," ) ,
608- versions : Some ( modules_vec) ,
609- } ;
610- write_update_metadata ( sysroot, self , & meta) ?;
611- Ok ( Some ( meta) )
612- } else {
613- anyhow:: bail!( "Failed to find EFI components" ) ;
614- }
601+
602+ // If /usr/lib/ostree-boot doesn't exist, assume /usr/lib/efi will
603+ None => generate_meta_from_usr_efi ( sysroot_path) ?,
604+ } ;
605+
606+ write_update_metadata ( sysroot_path. as_str ( ) , self , & metadata) ?;
607+
608+ Ok ( Some ( metadata) )
615609 }
616610
617611 fn query_update ( & self , sysroot : & openat:: Dir ) -> Result < Option < ContentMetadata > > {
@@ -801,6 +795,34 @@ fn find_file_recursive<P: AsRef<Path>>(dir: P, target_file: &str) -> Result<Vec<
801795 Ok ( result)
802796}
803797
798+ #[ context( "Generating metadata from usr/lib/efi" ) ]
799+ fn generate_meta_from_usr_efi ( sysroot_path : & Utf8Path ) -> Result < ContentMetadata > {
800+ let Some ( efi_components) = get_efi_component_from_usr ( sysroot_path, EFILIB ) ? else {
801+ anyhow:: bail!( "Failed to find EFI components" ) ;
802+ } ;
803+
804+ let mut packages = Vec :: new ( ) ;
805+ let mut modules_vec: Vec < Module > = vec ! [ ] ;
806+ for efi in efi_components {
807+ packages. push ( format ! ( "{}-{}" , efi. name, efi. version) ) ;
808+ modules_vec. push ( Module {
809+ name : efi. name ,
810+ rpm_evr : efi. version ,
811+ } ) ;
812+ }
813+ modules_vec. sort_unstable ( ) ;
814+
815+ // change to now to workaround https://github.com/coreos/bootupd/issues/933
816+ let timestamp = std:: time:: SystemTime :: now ( ) ;
817+ let meta = ContentMetadata {
818+ timestamp : chrono:: DateTime :: < Utc > :: from ( timestamp) ,
819+ version : packages. join ( "," ) ,
820+ versions : Some ( modules_vec) ,
821+ } ;
822+
823+ Ok ( meta)
824+ }
825+
804826#[ derive( Debug , PartialEq , Eq ) ]
805827pub struct EFIComponent {
806828 pub name : String ,
@@ -851,9 +873,48 @@ fn get_efi_component_from_usr<'a>(
851873 Ok ( Some ( components) )
852874}
853875
876+ /// Copies usr/lib/ostree-boot/EFI to usr/lib/bootupd/updates
877+ fn transfer_ostree_boot_to_bootupd_updates (
878+ sysroot : & Utf8Path ,
879+ component : & Efi ,
880+ ) -> Result < ContentMetadata > {
881+ let ostreebootdir = sysroot. join ( ostreeutil:: BOOT_PREFIX ) ;
882+
883+ // move EFI files to updates dir from /usr/lib/ostree-boot
884+ if !ostreebootdir. exists ( ) {
885+ anyhow:: bail!( "Failed to find {ostreebootdir}" ) ;
886+ }
887+
888+ let efisrc = ostreebootdir. join ( "efi/EFI" ) ;
889+ if !efisrc. exists ( ) {
890+ bail ! ( "Failed to find {:?}" , & efisrc) ;
891+ }
892+
893+ let dest_efidir = component_updatedir ( sysroot. as_str ( ) , component) ;
894+ let dest_efidir = Utf8PathBuf :: from_path_buf ( dest_efidir) . expect ( "Path is invalid UTF-8" ) ;
895+
896+ // Fork off mv() because on overlayfs one can't rename() a lower level
897+ // directory today, and this will handle the copy fallback.
898+ Command :: new ( "mv" )
899+ . args ( [ & efisrc, & dest_efidir] )
900+ . run_capture_stderr ( ) ?;
901+
902+ let efidir = openat:: Dir :: open ( dest_efidir. as_std_path ( ) )
903+ . with_context ( || format ! ( "Opening {}" , dest_efidir) ) ?;
904+
905+ let files = crate :: util:: filenames ( & efidir) ?. into_iter ( ) . map ( |mut f| {
906+ f. insert_str ( 0 , "/boot/efi/EFI" ) ;
907+ f
908+ } ) ;
909+
910+ let files = files. collect :: < Vec < _ > > ( ) ;
911+
912+ query_files ( sysroot. as_str ( ) , files)
913+ }
914+
854915/// Copy files from usr/lib/ostree-boot/efi/EFI to /usr/lib/efi/<component>/<evr>/
855- fn transfer_ostree_boot_to_usr ( sysroot : & Path ) -> Result < ( ) > {
856- let ostreeboot_efi = Path :: new ( ostreeutil:: BOOT_PREFIX ) . join ( "efi" ) ;
916+ fn transfer_ostree_boot_to_usr ( sysroot : & Utf8Path ) -> Result < ( ) > {
917+ let ostreeboot_efi = Utf8Path :: new ( ostreeutil:: BOOT_PREFIX ) . join ( "efi" ) ;
857918 let ostreeboot_efi_path = sysroot. join ( & ostreeboot_efi) ;
858919
859920 let efi = ostreeboot_efi_path. join ( "EFI" ) ;
@@ -873,7 +934,7 @@ fn transfer_ostree_boot_to_usr(sysroot: &Path) -> Result<()> {
873934
874935 // Run `rpm -qf <filepath>`
875936 let pkg = crate :: packagesystem:: query_file (
876- sysroot. to_str ( ) . unwrap ( ) ,
937+ sysroot. as_str ( ) ,
877938 boot_filepath. to_str ( ) . unwrap ( ) ,
878939 ) ?;
879940
@@ -882,15 +943,15 @@ fn transfer_ostree_boot_to_usr(sysroot: &Path) -> Result<()> {
882943 // get path usr/lib/efi/<component>/<evr>
883944 let efilib_path = Path :: new ( EFILIB ) . join ( component) . join ( evr) ;
884945
885- let sysroot_dir = openat:: Dir :: open ( sysroot) ?;
946+ let sysroot_dir = openat:: Dir :: open ( sysroot. as_str ( ) ) ?;
886947 // Ensure dest parent directory exists
887948 if let Some ( parent) = efilib_path. join ( filepath) . parent ( ) {
888949 sysroot_dir. ensure_dir_all ( parent, 0o755 ) ?;
889950 }
890951
891952 // Source dir is usr/lib/ostree-boot/efi
892953 let src = sysroot_dir
893- . sub_dir ( & ostreeboot_efi)
954+ . sub_dir ( ostreeboot_efi. as_str ( ) )
894955 . context ( "Opening ostree-boot dir" ) ?;
895956 // Dest dir is usr/lib/efi/<component>/<evr>
896957 let dest = sysroot_dir
0 commit comments