diff --git a/usr/share/rear/lib/uefi-functions.sh b/usr/share/rear/lib/uefi-functions.sh
index 95e6292d..c583e044 100644
--- a/usr/share/rear/lib/uefi-functions.sh
+++ b/usr/share/rear/lib/uefi-functions.sh
@@ -37,20 +37,76 @@ function trim {
}
function build_bootx86_efi {
- local gmkimage
- if has_binary grub-mkimage; then
- gmkimage=grub-mkimage
- elif has_binary grub2-mkimage; then
- gmkimage=grub2-mkimage
+ local outfile="$1"
+ local embedded_config=""
+ local gmkstandalone=""
+ local gprobe=""
+ local dirs=()
+ # modules is the list of modules to load
+ local modules=()
+
+ # Configuration file is optional for image creation.
+ shift
+ if [[ -n "$1" ]] ; then
+ # graft point syntax. $1 will appear as /boot/grub/grub.cfg in the image
+ embedded_config="/boot/grub/grub.cfg=$1"
+ shift
+ # directories that should be accessible by GRUB2 (e.g. because they contain the kernel)
+ dirs=( ${@:+"$@"} )
+ fi
+
+ if has_binary grub-mkstandalone ; then
+ gmkstandalone=grub-mkstandalone
+ elif has_binary grub2-mkstandalone ; then
+ # At least SUSE systems use 'grub2' prefixed names for GRUB2 programs:
+ gmkstandalone=grub2-mkstandalone
else
- Log "Did not find grub-mkimage (cannot build bootx86.efi)"
- return
+ # This build_bootx86_efi function is only called in output/ISO/Linux-i386/250_populate_efibootimg.sh
+ # which runs only if UEFI is used so that we simply error out here if we cannot make a bootable EFI image of GRUB2
+ # (normally a function should not exit out but return to its caller with a non-zero return code):
+ Error "Cannot make bootable EFI image of GRUB2 (neither grub-mkstandalone nor grub2-mkstandalone found)"
+ fi
+
+ # Determine what modules need to be loaded in order to access given directories
+ # (if the list of modules is not overriden by GRUB2_MODULES_LOAD)
+ if (( ${#dirs[@]} )) && ! (( ${#modules[@]} )) ; then
+ if has_binary grub-probe ; then
+ gprobe=grub-probe
+ elif has_binary grub2-probe ; then
+ # At least SUSE systems use 'grub2' prefixed names for GRUB2 programs:
+ gprobe=grub2-probe
+ else
+ LogWarn "Neither grub-probe nor grub2-probe found"
+ if test /usr/lib/grub*/x86_64-efi/partmap.lst ; then
+ LogWarn "including all partition modules"
+ modules=( $(cat /usr/lib/grub*/x86_64-efi/partmap.lst) )
+ else
+ Error "Can not determine partition modules, ${dirs[*]} would be likely inaccessible in GRUB2"
+ fi
+ fi
+
+ if [ -n "$gprobe" ]; then
+ # this is unfortunately only a crude approximation of the Grub internal probe_mods() function
+ modules=( $( for p in "${dirs[@]}" ; do
+ $gprobe --target=fs "$p"
+ $gprobe --target=partmap "$p" | sed -e 's/^/part_/'
+ $gprobe --target=abstraction "$p"
+ done | sort -u ) )
+ fi
+ fi
+
+ # grub-mkimage needs /usr/lib/grub/x86_64-efi/moddep.lst (cf. https://github.com/rear/rear/issues/1193)
+ # and at least on SUSE systems grub2-mkimage needs /usr/lib/grub2/x86_64-efi/moddep.lst (in 'grub2' directory)
+ # so that we error out if grub-mkimage or grub2-mkimage would fail when its moddep.lst is missing.
+ # Careful: usr/sbin/rear sets nullglob so that /usr/lib/grub*/x86_64-efi/moddep.lst gets empty if nothing matches
+ # and 'test -f' succeeds with empty argument so that we cannot use 'test -f /usr/lib/grub*/x86_64-efi/moddep.lst'
+ # also 'test -n' succeeds with empty argument but (fortunately/intentionally?) plain 'test' fails with empty argument:
+ test /usr/lib/grub*/x86_64-efi/moddep.lst || Error "$gmkstandalone would not make bootable EFI image of GRUB2 (no /usr/lib/grub*/x86_64-efi/moddep.lst file)"
+
+ (( ${#modules[@]} )) && LogPrint "GRUB2 modules to load: ${modules[*]}"
+
+ if ! $gmkstandalone $v ${modules:+"--modules=${modules[*]}"} -O x86_64-efi -o $outfile $embedded_config ; then
+ Error "Failed to make bootable EFI image of GRUB2 (error during $gmkstandalone of $outfile)"
fi
- # as not all Linux distro's have the same grub modules present we verify what we have (see also https://github.com/rear/rear/pull/2001)
- grub_modules=""
- for grub_module in part_gpt part_msdos fat ext2 normal chain boot configfile linux linuxefi multiboot jfs iso9660 usb usbms usb_keyboard video udf ntfs all_video gzio efi_gop reboot search test echo btrfs ; do
- test "$( find /boot -type f -name "$grub_module.mod" 2>/dev/null )" && grub_modules="$grub_modules $grub_module"
- done
- $gmkimage $v -O x86_64-efi -c $TMP_DIR/mnt/EFI/BOOT/embedded_grub.cfg -o $TMP_DIR/mnt/EFI/BOOT/BOOTX64.efi -p "/EFI/BOOT" $grub_modules
- StopIfError "Error occurred during $gmkimage of BOOTX64.efi"
}
+
diff --git a/usr/share/rear/output/ISO/Linux-i386/250_populate_efibootimg.sh b/usr/share/rear/output/ISO/Linux-i386/250_populate_efibootimg.sh
index fdf66039..e9325012 100644
--- a/usr/share/rear/output/ISO/Linux-i386/250_populate_efibootimg.sh
+++ b/usr/share/rear/output/ISO/Linux-i386/250_populate_efibootimg.sh
@@ -2,6 +2,9 @@
is_true $USING_UEFI_BOOTLOADER || return 0 # empty or 0 means NO UEFI
+local boot_dir="/boot"
+local efi_boot_tmp_dir="$TMP_DIR/mnt/EFI/BOOT"
+
mkdir $v -p $TMP_DIR/mnt/EFI/BOOT >&2
StopIfError "Could not create $TMP_DIR/mnt/EFI/BOOT"
@@ -56,14 +59,8 @@ title Relax-and-Recover (no Secure Boot)
EOF
else
-# create small embedded grub.cfg file for grub-mkimage
-cat > $TMP_DIR/mnt/EFI/BOOT/embedded_grub.cfg <<EOF
-set prefix=(cd0)/EFI/BOOT
-configfile /EFI/BOOT/grub.cfg
-EOF
-
-# create a grub.cfg
- create_grub2_cfg > $TMP_DIR/mnt/EFI/BOOT/grub.cfg
+ # create a grub.cfg
+ create_grub2_cfg > $efi_boot_tmp_dir/grub.cfg
fi
# Create BOOTX86.efi but only if we are NOT secure booting.
@@ -72,15 +69,15 @@ fi
# See issue #1374
# build_bootx86_efi () can be safely used for other scenarios.
if ! test -f "$SECURE_BOOT_BOOTLOADER" ; then
- build_bootx86_efi
+ build_bootx86_efi $TMP_DIR/mnt/EFI/BOOT/BOOTX64.efi $efi_boot_tmp_dir/grub.cfg "$boot_dir" "$UEFI_BOOTLOADER"
fi
# We will be using grub-efi or grub2 (with efi capabilities) to boot from ISO.
# Because usr/sbin/rear sets 'shopt -s nullglob' the 'echo -n' command
# outputs nothing if nothing matches the bash globbing pattern '/boot/grub*'
-local grubdir="$( echo -n /boot/grub* )"
+local grubdir="$( echo -n ${boot_dir}/grub* )"
# Use '/boot/grub' as fallback if nothing matches '/boot/grub*'
-test -d "$grubdir" || grubdir='/boot/grub'
+test -d "$grubdir" || grubdir="${boot_dir}/grub"
if [ -d $(dirname ${UEFI_BOOTLOADER})/fonts ]; then
cp $v $(dirname ${UEFI_BOOTLOADER})/fonts/* $TMP_DIR/mnt/EFI/BOOT/fonts/ >&2
diff --git a/usr/share/rear/output/default/940_grub2_rescue.sh b/usr/share/rear/output/default/940_grub2_rescue.sh
index a94957de..fbbd7074 100644
--- a/usr/share/rear/output/default/940_grub2_rescue.sh
+++ b/usr/share/rear/output/default/940_grub2_rescue.sh
@@ -144,13 +144,18 @@ if is_true $USING_UEFI_BOOTLOADER ; then
# probably a bug, as I was able to boot with value set to root=anything
root_uuid=$(mount | grep -w 'on /' | awk '{print $1}' | xargs blkid -s UUID -o value)
- # Grub2 modules that will be used for booting "Relax-and-Recover"
- # It might be useful to make this variable global in the future
- grub2_modules="linux echo all_video part_gpt ext2 btrfs search configfile"
-
# Create configuration file for "Relax-and-Recover" UEFI boot entry.
# This file will not interact with existing Grub2 configuration in any way.
- ( echo "menuentry '$grub_rear_menu_entry_name' --class os {"
+ ( echo "set btrfs_relative_path=y"
+ echo "insmod efi_gop"
+ echo "insmod efi_uga"
+ echo "insmod video_bochs"
+ echo "insmod video_cirrus"
+ echo "insmod all_video"
+ echo ""
+ echo "set gfxpayload=keep"
+ echo ""
+ echo "menuentry '$grub_rear_menu_entry_name' --class os {"
echo " search --no-floppy --fs-uuid --set=root $grub_boot_uuid"
echo " echo 'Loading kernel $boot_kernel_file ...'"
echo " linux $grub_boot_dir/$boot_kernel_name root=UUID=$root_uuid $KERNEL_CMDLINE"
@@ -159,19 +164,8 @@ if is_true $USING_UEFI_BOOTLOADER ; then
echo "}"
) > $grub_config_dir/rear.cfg
- # Tell rear.efi which configuration file to load
- ( echo "search --no-floppy --fs-uuid --set=root $grub_boot_uuid"
- echo ""
- echo "set btrfs_relative_path=y"
- echo "set prefix=(\$root)${grub_boot_dir}/grub${grub_num}"
- echo ""
- echo "configfile (\$root)${grub_boot_dir}/grub${grub_num}/rear.cfg"
- ) > $grub_config_dir/rear_embed.cfg
-
# Create rear.efi at UEFI default boot directory location.
- if ! grub${grub_num}-mkimage -o $boot_dir/efi/EFI/BOOT/rear.efi -O x86_64-efi -c $grub_config_dir/rear_embed.cfg -p /EFI/BOOT $grub2_modules ; then
- Error "Could not create UEFI boot image"
- fi
+ build_bootx86_efi $boot_dir/efi/EFI/BOOT/rear.efi $grub_config_dir/rear.cfg "$boot_dir" "$UEFI_BOOTLOADER"
# If UEFI boot entry for "Relax-and-Recover" does not exist, create it.
# This will also add "Relax-and-Recover" to boot order because if UEFI entry is not listed in BootOrder,