@@ -10,6 +10,7 @@ use std::path::{Path, PathBuf};
1010use std:: process:: Command ;
1111
1212use anyhow:: { bail, Context , Result } ;
13+ use bootc_utils:: CommandRunExt ;
1314use cap_std:: fs:: Dir ;
1415use cap_std_ext:: cap_std;
1516use fn_error_context:: context;
@@ -22,7 +23,7 @@ use widestring::U16CString;
2223use crate :: bootupd:: RootContext ;
2324use crate :: model:: * ;
2425use crate :: ostreeutil;
25- use crate :: util:: { self , CommandRunExt } ;
26+ use crate :: util;
2627use crate :: { blockdev, filetree} ;
2728use crate :: { component:: * , packagesystem} ;
2829
@@ -381,10 +382,42 @@ impl Component for Efi {
381382 }
382383
383384 fn generate_update_metadata ( & self , sysroot_path : & str ) -> Result < ContentMetadata > {
384- let ostreebootdir = Path :: new ( sysroot_path) . join ( ostreeutil:: BOOT_PREFIX ) ;
385385 let dest_efidir = component_updatedir ( sysroot_path, self ) ;
386386
387- if ostreebootdir. exists ( ) {
387+ // New EFI dir /usr/lib/efi
388+ let efi_lib = Path :: new ( sysroot_path) . join ( "usr/lib/efi" ) ;
389+ // Legacy ostree-boot dir
390+ let ostreebootdir = Path :: new ( sysroot_path) . join ( ostreeutil:: BOOT_PREFIX ) ;
391+
392+ let meta = if efi_lib. exists ( ) {
393+ // Get EFI paths like /usr/lib/efi/(shim|grub2)/<version>/EFI
394+ let efi_paths = find_all_efi_dirs ( & efi_lib)
395+ . with_context ( || format ! ( "Failed to find EFI path under {}" , efi_lib. display( ) ) ) ?;
396+
397+ // Get all files under EFI paths
398+ let all_files: Result < Vec < String > > =
399+ efi_paths. iter ( ) . try_fold ( Vec :: new ( ) , |mut acc, efi| {
400+ let efidir = openat:: Dir :: open ( efi)
401+ . with_context ( || format ! ( "Opening {}" , efi. display( ) ) ) ?;
402+
403+ // Get all files path
404+ let mut files = crate :: util:: filenames ( & efidir) ?
405+ . into_iter ( )
406+ . map ( |mut f| {
407+ f. insert_str ( 0 , efi. to_str ( ) . unwrap ( ) ) ;
408+ f
409+ } )
410+ . collect :: < Vec < String > > ( ) ;
411+
412+ Command :: new ( "mv" )
413+ . arg ( & efi)
414+ . arg ( & dest_efidir)
415+ . run_with_cmd_context ( ) ?;
416+ acc. append ( & mut files) ;
417+ Ok ( acc)
418+ } ) ;
419+ packagesystem:: query_files ( sysroot_path, all_files?. into_iter ( ) ) ?
420+ } else if ostreebootdir. exists ( ) {
388421 let cruft = [ "loader" , "grub2" ] ;
389422 for p in cruft. iter ( ) {
390423 let p = ostreebootdir. join ( p) ;
@@ -400,17 +433,25 @@ impl Component for Efi {
400433
401434 // Fork off mv() because on overlayfs one can't rename() a lower level
402435 // directory today, and this will handle the copy fallback.
403- Command :: new ( "mv" ) . args ( [ & efisrc, & dest_efidir] ) . run ( ) ?;
404- }
405-
406- let efidir = openat:: Dir :: open ( & dest_efidir)
407- . with_context ( || format ! ( "Opening {}" , dest_efidir. display( ) ) ) ?;
408- let files = crate :: util:: filenames ( & efidir) ?. into_iter ( ) . map ( |mut f| {
409- f. insert_str ( 0 , "/boot/efi/EFI/" ) ;
410- f
411- } ) ;
436+ Command :: new ( "mv" )
437+ . args ( [ & efisrc, & dest_efidir] )
438+ . run_with_cmd_context ( ) ?;
439+
440+ let efidir = openat:: Dir :: open ( & dest_efidir)
441+ . with_context ( || format ! ( "Opening {}" , dest_efidir. display( ) ) ) ?;
442+ let files = crate :: util:: filenames ( & efidir) ?. into_iter ( ) . map ( |mut f| {
443+ f. insert_str ( 0 , "/boot/efi/EFI/" ) ;
444+ f
445+ } ) ;
446+ packagesystem:: query_files ( sysroot_path, files) ?
447+ } else {
448+ bail ! (
449+ "No directories found {} or {}" ,
450+ efi_lib. display( ) ,
451+ ostreebootdir. display( )
452+ ) ;
453+ } ;
412454
413- let meta = packagesystem:: query_files ( sysroot_path, files) ?;
414455 write_update_metadata ( sysroot_path, self , & meta) ?;
415456 Ok ( meta)
416457 }
@@ -615,6 +656,29 @@ fn find_file_recursive<P: AsRef<Path>>(dir: P, target_file: &str) -> Result<Vec<
615656 Ok ( result)
616657}
617658
659+ // Find EFI dirs under usr/lib/efi
660+ // for exmaple: usr/lib/efi/shim/15.8-4/EFI, usr/lib/efi/grub2/2.12-34.fc42/EFI
661+ fn find_all_efi_dirs ( sysroot_lib : & Path ) -> Result < Vec < PathBuf > > {
662+ const LIBDIRS : & [ & str ] = & [ "grub2" , "shim" ] ;
663+
664+ LIBDIRS . iter ( ) . try_fold ( Vec :: new ( ) , |mut acc, pkg| {
665+ let lib_path = sysroot_lib. join ( pkg) ;
666+ if !lib_path. exists ( ) {
667+ return Ok ( acc) ;
668+ }
669+
670+ for entry in std:: fs:: read_dir ( & lib_path) ? {
671+ let entry = entry?;
672+ let version_dir = entry. path ( ) ;
673+ let efi_path = version_dir. join ( "EFI" ) ;
674+ if efi_path. is_dir ( ) {
675+ acc. push ( efi_path) ;
676+ }
677+ }
678+ Ok ( acc)
679+ } )
680+ }
681+
618682#[ cfg( test) ]
619683mod tests {
620684 use cap_std_ext:: dirext:: CapStdExtDirExt ;
@@ -735,4 +799,34 @@ Boot0003* test";
735799 }
736800 Ok ( ( ) )
737801 }
802+ #[ test]
803+ fn test_find_all_efi_dirs ( ) -> Result < ( ) > {
804+ let td = tempfile:: tempdir ( ) ?;
805+ let tdp = td. path ( ) ;
806+ let tdp_efi = tdp. join ( "usr/lib/efi" ) ;
807+ std:: fs:: create_dir_all ( tdp_efi. join ( "grub2/2.12-34.fc42/EFI/fedora" ) ) ?;
808+ std:: fs:: create_dir_all ( tdp_efi. join ( "shim/15.8-4/EFI/BOOT" ) ) ?;
809+ std:: fs:: create_dir_all ( tdp_efi. join ( "grub/testdir/test" ) ) ?;
810+ {
811+ let dirs = find_all_efi_dirs ( & tdp_efi) ?;
812+ assert_eq ! ( 2 , dirs. len( ) ) ;
813+ }
814+ {
815+ let td = openat:: Dir :: open ( & tdp_efi) ?;
816+ td. remove_all ( "grub2" ) ?;
817+ let dirs = find_all_efi_dirs ( & tdp_efi) ?;
818+ assert_eq ! ( 1 , dirs. len( ) ) ;
819+
820+ td. remove_all ( "shim" ) ?;
821+ let dirs = find_all_efi_dirs ( & tdp_efi) ?;
822+ assert_eq ! ( 0 , dirs. len( ) ) ;
823+ }
824+ {
825+ std:: fs:: create_dir_all ( tdp_efi. join ( "grub2/2.12-34.fc42" ) ) ?;
826+ std:: fs:: create_dir_all ( tdp_efi. join ( "shim/15.8-4/EFI/BOOT" ) ) ?;
827+ let dirs = find_all_efi_dirs ( & tdp_efi) ?;
828+ assert_eq ! ( 1 , dirs. len( ) ) ;
829+ }
830+ Ok ( ( ) )
831+ }
738832}
0 commit comments