­ ­ ­ ­ ­ ­ ­ ­ ­ ­ ­ ­ ­ ­ ­ ­ ­ ­ # 100_create_efiboot.sh # USB device needs to be formatted with command `rear format -- --efi /dev/' is_true $USING_UEFI_BOOTLOADER || return 0 Log "Configuring device for EFI boot" # $BUILD_DIR is not present at this stage, temp dir will be used instead. # Slackware version of mktemp requires 6 Xs in template and # plain 'mktemp' uses XXXXXXXXXX by default (at least on SLES11 and openSUSE Leap 15.0) # so that we comply with the 'mktemp' default to avoid 'mktemp' errors "too few X's in template": EFI_MPT=$( mktemp -d /tmp/rear-efi.XXXXXXXXXX ) || Error "mktemp failed to create mount point '/tmp/rear-efi.XXXXXXXXXX' for EFI partition" uefi_bootloader_basename=$( basename "$UEFI_BOOTLOADER" ) EFI_LABEL="REAR-EFI" EFI_PART="/dev/disk/by-label/${EFI_LABEL}" EFI_DIR="/EFI/BOOT" EFI_DST="${EFI_MPT}/${EFI_DIR}" # Fail if EFI partition is not present if [[ ! -b ${EFI_PART} ]]; then Error "${EFI_PART} is not block device. Use \`rear format -- --efi ' for correct format" fi # Mount EFI partition mount $EFI_PART $EFI_MPT || Error "Failed to mount EFI partition '$EFI_PART' at '$EFI_MPT'" # Create EFI friendly dir structure mkdir -p $EFI_DST || Error "Failed to create directory '$EFI_DST'" # Copy boot loader # The SECURE_BOOT_BOOTLOADER related code below is based on the code in output/ISO/Linux-i386/250_populate_efibootimg.sh # because I noticed that Secure Boot works with ISO at least for me, cf. # https://github.com/rear/rear/pull/3025#issuecomment-1635876186 # but not with USB, cf. # https://github.com/rear/rear/pull/3025#issuecomment-1643774477 # so I tried to re-use the ISO Secure Boot code for USB # which made Secure Boot "just work" for me with USB # but I had to do some (minor) adaptions to make it work # within the existing USB code, cf. # https://github.com/rear/rear/pull/3031#issuecomment-1653443454 # Copy UEFI bootloader: if test -f "$SECURE_BOOT_BOOTLOADER" ; then # For a technical description of Shim see https://mjg59.dreamwidth.org/19448.html # Shim is a signed EFI binary that is a first stage bootloader # that loads and executes another (signed) EFI binary # which normally is a second stage bootloader # which normally is a GRUB EFI binary # which normally is available as a file named grub*.efi # so when SECURE_BOOT_BOOTLOADER is used as UEFI_BOOTLOADER # (cf. rescue/default/850_save_sysfs_uefi_vars.sh) # then Shim (usually shim.efi) must be copied as EFI/BOOT/BOOTX64.efi # and Shim's second stage bootloader must be also copied where Shim already is. DebugPrint "Using '$SECURE_BOOT_BOOTLOADER' as first stage Secure Boot bootloader BOOTX64.efi" cp -L $v "$SECURE_BOOT_BOOTLOADER" "$EFI_DST/BOOTX64.efi" || Error "Failed to copy SECURE_BOOT_BOOTLOADER '$SECURE_BOOT_BOOTLOADER' to $EFI_DST/BOOTX64.efi" # When Shim is used, its second stage bootloader can be actually anything # named grub*.efi (second stage bootloader is Shim compile time option), see # http://www.rodsbooks.com/efi-bootloaders/secureboot.html#initial_shim local uefi_bootloader_dirname="$( dirname $SECURE_BOOT_BOOTLOADER )" local second_stage_UEFI_bootloader_files="$( echo $uefi_bootloader_dirname/grub*.efi )" # Avoid 'nullglob' pitfall when nothing matches .../grub*.efi which would result # an invalid "cp -v /var/tmp/.../EFI/BOOT/" command that fails # cf. https://github.com/rear/rear/issues/1921 test "$second_stage_UEFI_bootloader_files" || Error "Could not find second stage Secure Boot bootloader $uefi_bootloader_dirname/grub*.efi" DebugPrint "Using second stage Secure Boot bootloader files: $second_stage_UEFI_bootloader_files" cp -L $v $second_stage_UEFI_bootloader_files $EFI_DST/ || Error "Failed to copy second stage Secure Boot bootloader files" else cp -L $v "$UEFI_BOOTLOADER" "$EFI_DST/BOOTX64.efi" || Error "Failed to copy UEFI_BOOTLOADER '$UEFI_BOOTLOADER' to $EFI_DST/BOOTX64.efi" fi cp $v $UEFI_BOOTLOADER "$EFI_DST/BOOTX64.efi" || Error "Failed to copy UEFI_BOOTLOADER '$UEFI_BOOTLOADER' to $EFI_DST/BOOTX64.efi" # Copy kernel cp -pL $v "$KERNEL_FILE" "$EFI_DST/kernel" || Error "Failed to copy KERNEL_FILE '$KERNEL_FILE' to $EFI_DST/kernel" # Copy initrd cp -p $v "$TMP_DIR/$REAR_INITRD_FILENAME" "$EFI_DST/$REAR_INITRD_FILENAME" || Error "Failed to copy initrd to $EFI_DST/$REAR_INITRD_FILENAME" Log "Copied kernel $KERNEL_FILE and initrd $REAR_INITRD_FILENAME to $EFI_DST" # Configure elilo for EFI boot if test "$uefi_bootloader_basename" = "elilo.efi" ; then Log "Configuring elilo for EFI boot" # Create config for elilo Log "Creating ${EFI_DST}/elilo.conf" create_ebiso_elilo_conf > ${EFI_DST}/elilo.conf # Configure grub for EFI boot or die else # Hope this assumption is not wrong ... if has_binary grub-install grub2-install; then # Choose right grub binary # Issue #849 if has_binary grub2-install; then NUM=2 fi GRUB_INSTALL=grub${NUM}-install # What version of grub are we using # substr() for awk did not work as expected for this reason cut was used # First charecter should be enough to identify grub version grub_version=$($GRUB_INSTALL --version | awk '{print $NF}' | cut -c1-1) case ${grub_version} in 0) Log "Configuring grub 0.97 for EFI boot" # Create config for grub 0.97 cat > ${EFI_DST}/BOOTX64.conf << EOF default=0 timeout=5 title Relax-and-Recover (no Secure Boot) kernel ${EFI_DIR}/kernel $KERNEL_CMDLINE initrd ${EFI_DIR}/$REAR_INITRD_FILENAME EOF ;; 2) Log "Configuring grub 2.0 for EFI boot" # We need to explicitly set $root variable to $EFI_LABEL # (currently "REAR-EFI") in Grub because default $root would # point to memdisk, where kernel and initrd are NOT present. # Variable grub2_set_usb_root will be used in later call of # create_grub2_cfg(). grub2_set_usb_root="search --no-floppy --set=root --label ${EFI_LABEL}" # Create config for grub 2.0 create_grub2_cfg ${EFI_DIR}/kernel ${EFI_DIR}/$REAR_INITRD_FILENAME > ${EFI_DST}/grub.cfg # Create bootloader, this overwrite BOOTX64.efi copied in previous step ... # Create BOOTX86.efi but only if we are NOT secure booting. # We are not able to create signed boot loader # so we need to reuse existing one. # See issue #1374 # build_bootx86_efi () can be safely used for other scenarios. if ! test -f "$SECURE_BOOT_BOOTLOADER" ; then build_bootx86_efi ${EFI_DST}/BOOTX64.efi ${EFI_DST}/grub.cfg "/boot" "$UEFI_BOOTLOADER" fi ;; *) BugError "Neither grub 0.97 nor 2.0" ;; esac else BugIfError "Unknown EFI bootloader" fi fi # Do cleanup of EFI temporary mount point Log "Doing cleanup of ${EFI_MPT}" umount ${EFI_MPT} if [[ $? -eq 0 ]]; then rmdir ${EFI_MPT} LogIfError "Could not remove temporary directory ${EFI_MPT}, please check manually" else Log "Could not umount ${EFI_MPT}, please check manually" fi Log "Created EFI configuration for USB"