Blame SOURCES/rear-bz1945869.patch

b9f7b3
diff --git a/usr/share/rear/finalize/Linux-i386/670_run_efibootmgr.sh b/usr/share/rear/finalize/Linux-i386/670_run_efibootmgr.sh
b9f7b3
old mode 100644
b9f7b3
new mode 100755
b9f7b3
index cc646359..33d87767
b9f7b3
--- a/usr/share/rear/finalize/Linux-i386/670_run_efibootmgr.sh
b9f7b3
+++ b/usr/share/rear/finalize/Linux-i386/670_run_efibootmgr.sh
b9f7b3
@@ -8,6 +8,10 @@ is_true $USING_UEFI_BOOTLOADER || return 0
b9f7b3
 # (cf. finalize/Linux-i386/610_EFISTUB_run_efibootmgr.sh): 
b9f7b3
 is_true $EFI_STUB && return
b9f7b3
 
b9f7b3
+LogPrint "Creating EFI Boot Manager entries..."
b9f7b3
+
b9f7b3
+local esp_mountpoint esp_mountpoint_inside boot_efi_parts boot_efi_dev
b9f7b3
+
b9f7b3
 # When UEFI_BOOTLOADER is not a regular file in the restored target system
b9f7b3
 # (cf. how esp_mountpoint is set below) it means BIOS is used
b9f7b3
 # (cf. rescue/default/850_save_sysfs_uefi_vars.sh)
b9f7b3
@@ -15,64 +19,80 @@ is_true $EFI_STUB && return
b9f7b3
 # because when UEFI_BOOTLOADER is empty the test below evaluates to
b9f7b3
 #   test -f /mnt/local/
b9f7b3
 # which also returns false because /mnt/local/ is a directory
b9f7b3
-# (cf. https://github.com/rear/rear/pull/2051/files#r258826856):
b9f7b3
-test -f "$TARGET_FS_ROOT/$UEFI_BOOTLOADER" || return 0
b9f7b3
+# (cf. https://github.com/rear/rear/pull/2051/files#r258826856)
b9f7b3
+# but using BIOS conflicts with USING_UEFI_BOOTLOADER is true
b9f7b3
+# i.e. we should create EFI Boot Manager entries but we cannot:
b9f7b3
+if ! test -f "$TARGET_FS_ROOT/$UEFI_BOOTLOADER" ; then
b9f7b3
+    LogPrintError "Failed to create EFI Boot Manager entries (UEFI bootloader '$UEFI_BOOTLOADER' not found under target $TARGET_FS_ROOT)"
b9f7b3
+    return 1
b9f7b3
+fi
b9f7b3
 
b9f7b3
 # Determine where the EFI System Partition (ESP) is mounted in the currently running recovery system:
b9f7b3
-esp_mountpoint=$( df -P "$TARGET_FS_ROOT/$UEFI_BOOTLOADER" | tail -1 | awk '{print $6}' )
b9f7b3
-# Use TARGET_FS_ROOT/boot/efi as fallback ESP mountpoint:
b9f7b3
-test "$esp_mountpoint" || esp_mountpoint="$TARGET_FS_ROOT/boot/efi"
b9f7b3
+esp_mountpoint=$( filesystem_name "$TARGET_FS_ROOT/$UEFI_BOOTLOADER" )
b9f7b3
+# Use TARGET_FS_ROOT/boot/efi as fallback ESP mountpoint (filesystem_name returns "/"
b9f7b3
+# if mountpoint not found otherwise):
b9f7b3
+if [ "$esp_mountpoint" = "/" ] ; then
b9f7b3
+    esp_mountpoint="$TARGET_FS_ROOT/boot/efi"
b9f7b3
+    LogPrint "Mountpoint of $TARGET_FS_ROOT/$UEFI_BOOTLOADER not found, trying $esp_mountpoint"
b9f7b3
+fi
b9f7b3
 
b9f7b3
 # Skip if there is no esp_mountpoint directory (e.g. the fallback ESP mountpoint may not exist).
b9f7b3
 # Double quotes are mandatory here because 'test -d' without any (possibly empty) argument results true:
b9f7b3
-test -d "$esp_mountpoint" || return 0
b9f7b3
-
b9f7b3
-BootEfiDev="$( mount | grep "$esp_mountpoint" | awk '{print $1}' )"
b9f7b3
-# /dev/sda1 or /dev/mapper/vol34_part2 or /dev/mapper/mpath99p4
b9f7b3
-Dev=$( get_device_name $BootEfiDev )
b9f7b3
-# 1 (must anyway be a low nr <9)
b9f7b3
-ParNr=$( get_partition_number $Dev )
b9f7b3
-# /dev/sda or /dev/mapper/vol34_part or /dev/mapper/mpath99p or /dev/mmcblk0p
b9f7b3
-Disk=$( echo ${Dev%$ParNr} )
b9f7b3
-
b9f7b3
-# Strip trailing partition remainders like '_part' or '-part' or 'p'
b9f7b3
-# if we have 'mapper' in disk device name:
b9f7b3
-if [[ ${Dev/mapper//} != $Dev ]] ; then
b9f7b3
-    # we only expect mpath_partX or mpathpX or mpath-partX
b9f7b3
-    case $Disk in
b9f7b3
-        (*p)     Disk=${Disk%p} ;;
b9f7b3
-        (*-part) Disk=${Disk%-part} ;;
b9f7b3
-        (*_part) Disk=${Disk%_part} ;;
b9f7b3
-        (*)      Log "Unsupported kpartx partition delimiter for $Dev"
b9f7b3
-    esac
b9f7b3
+if ! test -d "$esp_mountpoint" ; then
b9f7b3
+    LogPrintError "Failed to create EFI Boot Manager entries (no ESP mountpoint directory $esp_mountpoint)"
b9f7b3
+    return 1
b9f7b3
 fi
b9f7b3
 
b9f7b3
-# For eMMC devices the trailing 'p' in the Disk value
b9f7b3
-# (as in /dev/mmcblk0p that is derived from /dev/mmcblk0p1)
b9f7b3
-# needs to be stripped (to get /dev/mmcblk0), otherwise the
b9f7b3
-# efibootmgr call fails because of a wrong disk device name.
b9f7b3
-# See also https://github.com/rear/rear/issues/2103
b9f7b3
-if [[ $Disk = *'/mmcblk'+([0-9])p ]] ; then
b9f7b3
-    Disk=${Disk%p}
b9f7b3
-fi
b9f7b3
+# Mount point inside the target system,
b9f7b3
+# accounting for possible trailing slashes in TARGET_FS_ROOT
b9f7b3
+esp_mountpoint_inside="${esp_mountpoint#${TARGET_FS_ROOT%%*(/)}}"
b9f7b3
 
b9f7b3
-# For NVMe devices the trailing 'p' in the Disk value
b9f7b3
-# (as in /dev/nvme0n1p that is derived from /dev/nvme0n1p1)
b9f7b3
-# needs to be stripped (to get /dev/nvme0n1), otherwise the
b9f7b3
-# efibootmgr call fails because of a wrong disk device name.
b9f7b3
-# See also https://github.com/rear/rear/issues/1564
b9f7b3
-if [[ $Disk = *'/nvme'+([0-9])n+([0-9])p ]] ; then
b9f7b3
-    Disk=${Disk%p}
b9f7b3
+boot_efi_parts=$( find_partition "fs:$esp_mountpoint_inside" fs )
b9f7b3
+if ! test "$boot_efi_parts" ; then
b9f7b3
+    LogPrint "Unable to find ESP $esp_mountpoint_inside in layout"
b9f7b3
+    LogPrint "Trying to determine device currently mounted at $esp_mountpoint as fallback"
b9f7b3
+    boot_efi_dev="$( mount | grep "$esp_mountpoint" | awk '{print $1}' )"
b9f7b3
+    if ! test "$boot_efi_dev" ; then
b9f7b3
+        LogPrintError "Cannot create EFI Boot Manager entry (unable to find ESP $esp_mountpoint among mounted devices)"
b9f7b3
+        return 1
b9f7b3
+    fi
b9f7b3
+    if test $(get_component_type "$boot_efi_dev") = part ; then
b9f7b3
+        boot_efi_parts="$boot_efi_dev"
b9f7b3
+    else
b9f7b3
+        boot_efi_parts=$( find_partition "$boot_efi_dev" )
b9f7b3
+    fi
b9f7b3
+    if ! test "$boot_efi_parts" ; then
b9f7b3
+        LogPrintError "Cannot create EFI Boot Manager entry (unable to find partition for $boot_efi_dev)"
b9f7b3
+        return 1
b9f7b3
+    fi
b9f7b3
+    LogPrint "Using fallback EFI boot partition(s) $boot_efi_parts (unable to find ESP $esp_mountpoint_inside in layout)"
b9f7b3
 fi
b9f7b3
 
b9f7b3
+local bootloader partition_block_device partition_number disk efipart
b9f7b3
+
b9f7b3
 # EFI\fedora\shim.efi
b9f7b3
-BootLoader=$( echo $UEFI_BOOTLOADER | cut -d"/" -f4- | sed -e 's;/;\\;g' )
b9f7b3
-LogPrint "Creating  EFI Boot Manager entry '$OS_VENDOR $OS_VERSION' for '$BootLoader' (UEFI_BOOTLOADER='$UEFI_BOOTLOADER')"
b9f7b3
-Log efibootmgr --create --gpt --disk ${Disk} --part ${ParNr} --write-signature --label \"${OS_VENDOR} ${OS_VERSION}\" --loader \"\\${BootLoader}\"
b9f7b3
-if efibootmgr --create --gpt --disk ${Disk} --part ${ParNr} --write-signature --label "${OS_VENDOR} ${OS_VERSION}" --loader "\\${BootLoader}" ; then
b9f7b3
-    # ok, boot loader has been set-up - tell rear we are done using following var.
b9f7b3
-    NOBOOTLOADER=''
b9f7b3
-    return
b9f7b3
-fi
b9f7b3
+bootloader=$( echo $UEFI_BOOTLOADER | cut -d"/" -f4- | sed -e 's;/;\\;g' )
b9f7b3
+
b9f7b3
+for efipart in $boot_efi_parts ; do
b9f7b3
+    # /dev/sda1 or /dev/mapper/vol34_part2 or /dev/mapper/mpath99p4
b9f7b3
+    partition_block_device=$( get_device_name $efipart )
b9f7b3
+    # 1 or 2 or 4 for the examples above
b9f7b3
+    partition_number=$( get_partition_number $partition_block_device )
b9f7b3
+    if ! disk=$( get_device_from_partition $partition_block_device $partition_number ) ; then
b9f7b3
+        LogPrintError "Cannot create EFI Boot Manager entry for ESP $partition_block_device (unable to find the underlying disk)"
b9f7b3
+        # do not error out - we may be able to locate other disks if there are more of them
b9f7b3
+        continue
b9f7b3
+    fi
b9f7b3
+    LogPrint "Creating  EFI Boot Manager entry '$OS_VENDOR $OS_VERSION' for '$bootloader' (UEFI_BOOTLOADER='$UEFI_BOOTLOADER') "
b9f7b3
+    Log efibootmgr --create --gpt --disk $disk --part $partition_number --write-signature --label \"${OS_VENDOR} ${OS_VERSION}\" --loader \"\\${bootloader}\"
b9f7b3
+    if efibootmgr --create --gpt --disk $disk --part $partition_number --write-signature --label "${OS_VENDOR} ${OS_VERSION}" --loader "\\${bootloader}" ; then
b9f7b3
+        # ok, boot loader has been set-up - continue with other disks (ESP can be on RAID)
b9f7b3
+        NOBOOTLOADER=''
b9f7b3
+    else
b9f7b3
+        LogPrintError "efibootmgr failed to create EFI Boot Manager entry on $disk partition $partition_number (ESP $partition_block_device )"
b9f7b3
+    fi
b9f7b3
+done
b9f7b3
 
b9f7b3
-LogPrintError "efibootmgr failed to create EFI Boot Manager entry for '$BootLoader' (UEFI_BOOTLOADER='$UEFI_BOOTLOADER')"
b9f7b3
+is_true $NOBOOTLOADER || return 0
b9f7b3
+LogPrintError "efibootmgr failed to create EFI Boot Manager entry for '$bootloader' (UEFI_BOOTLOADER='$UEFI_BOOTLOADER')"
b9f7b3
+return 1
b9f7b3
diff --git a/usr/share/rear/lib/layout-functions.sh b/usr/share/rear/lib/layout-functions.sh
b9f7b3
index 54ddb50f..cdd81a14 100644
b9f7b3
--- a/usr/share/rear/lib/layout-functions.sh
b9f7b3
+++ b/usr/share/rear/lib/layout-functions.sh
b9f7b3
@@ -302,12 +302,20 @@ get_child_components() {
b9f7b3
     done
b9f7b3
 }
b9f7b3
 
b9f7b3
-# Return all ancestors of component $1 [ of type $2 ]
b9f7b3
+# Return all ancestors of component $1 [ of type $2 [ skipping types $3 during resolution ] ]
b9f7b3
 get_parent_components() {
b9f7b3
-    declare -a ancestors devlist
b9f7b3
-    declare current child parent
b9f7b3
+    declare -a ancestors devlist ignoretypes
b9f7b3
+    declare current child parent parenttype
b9f7b3
 
b9f7b3
     devlist=( "$1" )
b9f7b3
+    if [[ "$3" ]] ; then
b9f7b3
+        # third argument should, if present, be a space-separated list
b9f7b3
+        # of types to ignore when walking up the dependency tree.
b9f7b3
+        # Convert it to array
b9f7b3
+        ignoretypes=( $3 )
b9f7b3
+    else
b9f7b3
+        ignoretypes=()
b9f7b3
+    fi
b9f7b3
     while (( ${#devlist[@]} )) ; do
b9f7b3
         current=${devlist[0]}
b9f7b3
 
b9f7b3
@@ -318,6 +326,13 @@ get_parent_components() {
b9f7b3
                 if IsInArray "$parent" "${ancestors[@]}" ; then
b9f7b3
                     continue
b9f7b3
                 fi
b9f7b3
+                ### ...test if parent is of a correct type if requested...
b9f7b3
+                if [[ ${#ignoretypes[@]} -gt 0 ]] ; then
b9f7b3
+                    parenttype=$(get_component_type "$parent")
b9f7b3
+                    if IsInArray "$parenttype" "${ignoretypes[@]}" ; then
b9f7b3
+                        continue
b9f7b3
+                    fi
b9f7b3
+                fi
b9f7b3
                 ### ...and add them to the list
b9f7b3
                 devlist+=( "$parent" )
b9f7b3
                 ancestors+=( "$parent" )
b9f7b3
@@ -345,22 +360,24 @@ get_parent_components() {
b9f7b3
 }
b9f7b3
 
b9f7b3
 # find_devices <other>
b9f7b3
+# ${2+"$2"} in the following functions ensures that $2 gets passed down quoted if present
b9f7b3
+# and ignored if not present
b9f7b3
 # Find the disk device(s) component $1 resides on.
b9f7b3
 find_disk() {
b9f7b3
-    get_parent_components "$1" "disk"
b9f7b3
+    get_parent_components "$1" "disk" ${2+"$2"}
b9f7b3
 }
b9f7b3
 
b9f7b3
 find_multipath() {
b9f7b3
-    get_parent_components "$1" "multipath"
b9f7b3
+    get_parent_components "$1" "multipath" ${2+"$2"}
b9f7b3
 }
b9f7b3
 
b9f7b3
 find_disk_and_multipath() {
b9f7b3
-    find_disk "$1"
b9f7b3
-    is_true "$AUTOEXCLUDE_MULTIPATH" || find_multipath "$1"
b9f7b3
+    find_disk "$1" ${2+"$2"}
b9f7b3
+    is_true "$AUTOEXCLUDE_MULTIPATH" || find_multipath "$1" ${2+"$2"}
b9f7b3
 }
b9f7b3
 
b9f7b3
 find_partition() {
b9f7b3
-    get_parent_components "$1" "part"
b9f7b3
+    get_parent_components "$1" "part" ${2+"$2"}
b9f7b3
 }
b9f7b3
 
b9f7b3
 # The get_partition_number function
b9f7b3
@@ -413,6 +430,54 @@ get_partition_number() {
b9f7b3
     echo $partition_number
b9f7b3
 }
b9f7b3
 
b9f7b3
+# Extract the underlying device name from the full partition device name.
b9f7b3
+# Underlying device may be a disk, a multipath device or other devices that can be partitioned.
b9f7b3
+# Should we use the information in $LAYOUT_DEPS, like get_parent_component does,
b9f7b3
+# instead of string munging?
b9f7b3
+function get_device_from_partition() {
b9f7b3
+    local partition_block_device
b9f7b3
+    local device
b9f7b3
+    local partition_number
b9f7b3
+
b9f7b3
+    partition_block_device=$1
b9f7b3
+    test -b "$partition_block_device" || BugError "get_device_from_partition called with '$partition_block_device' that is no block device"
b9f7b3
+    partition_number=${2-$(get_partition_number $partition_block_device )}
b9f7b3
+    # /dev/sda or /dev/mapper/vol34_part or /dev/mapper/mpath99p or /dev/mmcblk0p
b9f7b3
+    device=${partition_block_device%$partition_number}
b9f7b3
+
b9f7b3
+    # Strip trailing partition remainders like '_part' or '-part' or 'p'
b9f7b3
+    # if we have 'mapper' in disk device name:
b9f7b3
+    if [[ ${partition_block_device/mapper//} != $partition_block_device ]] ; then
b9f7b3
+        # we only expect mpath_partX or mpathpX or mpath-partX
b9f7b3
+        case $device in
b9f7b3
+            (*p)     device=${device%p} ;;
b9f7b3
+            (*-part) device=${device%-part} ;;
b9f7b3
+            (*_part) device=${device%_part} ;;
b9f7b3
+            (*)      Log "Unsupported kpartx partition delimiter for $partition_block_device"
b9f7b3
+        esac
b9f7b3
+    fi
b9f7b3
+
b9f7b3
+    # For eMMC devices the trailing 'p' in the $device value
b9f7b3
+    # (as in /dev/mmcblk0p that is derived from /dev/mmcblk0p1)
b9f7b3
+    # needs to be stripped (to get /dev/mmcblk0), otherwise the
b9f7b3
+    # efibootmgr call fails because of a wrong disk device name.
b9f7b3
+    # See also https://github.com/rear/rear/issues/2103
b9f7b3
+    if [[ $device = *'/mmcblk'+([0-9])p ]] ; then
b9f7b3
+        device=${device%p}
b9f7b3
+    fi
b9f7b3
+
b9f7b3
+    # For NVMe devices the trailing 'p' in the $device value
b9f7b3
+    # (as in /dev/nvme0n1p that is derived from /dev/nvme0n1p1)
b9f7b3
+    # needs to be stripped (to get /dev/nvme0n1), otherwise the
b9f7b3
+    # efibootmgr call fails because of a wrong disk device name.
b9f7b3
+    # See also https://github.com/rear/rear/issues/1564
b9f7b3
+    if [[ $device = *'/nvme'+([0-9])n+([0-9])p ]] ; then
b9f7b3
+        device=${device%p}
b9f7b3
+    fi
b9f7b3
+
b9f7b3
+    test -b "$device" && echo $device
b9f7b3
+}
b9f7b3
+
b9f7b3
 # Returns partition start block or 'unknown'
b9f7b3
 # sda/sda1 or
b9f7b3
 # dm-XX