|
|
9fdd73 |
diff --git a/usr/share/rear/finalize/Linux-i386/630_run_efibootmgr.sh b/usr/share/rear/finalize/Linux-i386/630_run_efibootmgr.sh
|
|
|
9fdd73 |
index dfbeddcb..7791312b
|
|
|
9fdd73 |
--- a/usr/share/rear/finalize/Linux-i386/630_run_efibootmgr.sh
|
|
|
9fdd73 |
+++ b/usr/share/rear/finalize/Linux-i386/630_run_efibootmgr.sh
|
|
|
9fdd73 |
@@ -1,28 +1,79 @@
|
|
|
9fdd73 |
# only useful for UEFI systems in combination with grub[2]-efi
|
|
|
9fdd73 |
is_true $USING_UEFI_BOOTLOADER || return 0 # empty or 0 means using BIOS
|
|
|
9fdd73 |
|
|
|
9fdd73 |
-# check if $TARGET_FS_ROOT/boot/efi is mounted
|
|
|
9fdd73 |
-[[ -d "$TARGET_FS_ROOT/boot/efi" ]]
|
|
|
9fdd73 |
-StopIfError "Could not find directory $TARGET_FS_ROOT/boot/efi"
|
|
|
9fdd73 |
-
|
|
|
9fdd73 |
-BootEfiDev="$( mount | grep "boot/efi" | awk '{print $1}' )"
|
|
|
9fdd73 |
-Dev=$( get_device_name $BootEfiDev ) # /dev/sda1 or /dev/mapper/vol34_part2 or /dev/mapper/mpath99p4
|
|
|
9fdd73 |
-ParNr=$( get_partition_number $Dev ) # 1 (must anyway be a low nr <9)
|
|
|
9fdd73 |
-Disk=$( echo ${Dev%$ParNr} ) # /dev/sda or /dev/mapper/vol34_part or /dev/mapper/mpath99p
|
|
|
9fdd73 |
-
|
|
|
9fdd73 |
-if [[ ${Dev/mapper//} != $Dev ]] ; then # we have 'mapper' in devname
|
|
|
9fdd73 |
- # we only expect mpath_partX or mpathpX or mpath-partX
|
|
|
9fdd73 |
- case $Disk in
|
|
|
9fdd73 |
- (*p) Disk=${Disk%p} ;;
|
|
|
9fdd73 |
- (*-part) Disk=${Disk%-part} ;;
|
|
|
9fdd73 |
- (*_part) Disk=${Disk%_part} ;;
|
|
|
9fdd73 |
- (*) Log "Unsupported kpartx partition delimiter for $Dev"
|
|
|
9fdd73 |
- esac
|
|
|
9fdd73 |
+LogPrint "Creating EFI Boot Manager entries..."
|
|
|
9fdd73 |
+
|
|
|
9fdd73 |
+local esp_mountpoint esp_mountpoint_inside boot_efi_parts boot_efi_dev
|
|
|
9fdd73 |
+
|
|
|
9fdd73 |
+# When UEFI_BOOTLOADER is not a regular file in the restored target system
|
|
|
9fdd73 |
+# (cf. how esp_mountpoint is set below) it means BIOS is used
|
|
|
9fdd73 |
+# (cf. rescue/default/850_save_sysfs_uefi_vars.sh)
|
|
|
9fdd73 |
+# which includes that also an empty UEFI_BOOTLOADER means using BIOS
|
|
|
9fdd73 |
+# because when UEFI_BOOTLOADER is empty the test below evaluates to
|
|
|
9fdd73 |
+# test -f /mnt/local/
|
|
|
9fdd73 |
+# which also returns false because /mnt/local/ is a directory
|
|
|
9fdd73 |
+# (cf. https://github.com/rear/rear/pull/2051/files#r258826856)
|
|
|
9fdd73 |
+# but using BIOS conflicts with USING_UEFI_BOOTLOADER is true
|
|
|
9fdd73 |
+# i.e. we should create EFI Boot Manager entries but we cannot:
|
|
|
9fdd73 |
+if ! test -f "$TARGET_FS_ROOT/$UEFI_BOOTLOADER" ; then
|
|
|
9fdd73 |
+ LogPrintError "Failed to create EFI Boot Manager entries (UEFI bootloader '$UEFI_BOOTLOADER' not found under target $TARGET_FS_ROOT)"
|
|
|
9fdd73 |
+ return 1
|
|
|
9fdd73 |
fi
|
|
|
9fdd73 |
-BootLoader=$( echo $UEFI_BOOTLOADER | cut -d"/" -f4- | sed -e 's;/;\\;g' ) # EFI\fedora\shim.efi
|
|
|
9fdd73 |
-Log efibootmgr --create --gpt --disk ${Disk} --part ${ParNr} --write-signature --label \"${OS_VENDOR} ${OS_VERSION}\" --loader \"\\${BootLoader}\"
|
|
|
9fdd73 |
-efibootmgr --create --gpt --disk ${Disk} --part ${ParNr} --write-signature --label "${OS_VENDOR} ${OS_VERSION}" --loader "\\${BootLoader}"
|
|
|
9fdd73 |
-LogIfError "Problem occurred with creating an efibootmgr entry"
|
|
|
9fdd73 |
|
|
|
9fdd73 |
-# ok, boot loader has been set-up - tell rear we are done using following var.
|
|
|
9fdd73 |
-NOBOOTLOADER=
|
|
|
9fdd73 |
+esp_mountpoint="$TARGET_FS_ROOT/boot/efi"
|
|
|
9fdd73 |
+# check if esp_mountpoint is mounted
|
|
|
9fdd73 |
+[[ -d "$esp_mountpoint" ]]
|
|
|
9fdd73 |
+StopIfError "Could not find directory $esp_mountpoint"
|
|
|
9fdd73 |
+
|
|
|
9fdd73 |
+# Mount point inside the target system
|
|
|
9fdd73 |
+esp_mountpoint_inside=/boot/efi
|
|
|
9fdd73 |
+
|
|
|
9fdd73 |
+boot_efi_parts=$( find_partition "fs:$esp_mountpoint_inside" fs )
|
|
|
9fdd73 |
+if ! test "$boot_efi_parts" ; then
|
|
|
9fdd73 |
+ LogPrint "Unable to find ESP $esp_mountpoint_inside in layout"
|
|
|
9fdd73 |
+ LogPrint "Trying to determine device currently mounted at $esp_mountpoint as fallback"
|
|
|
9fdd73 |
+ boot_efi_dev="$( mount | grep "$esp_mountpoint" | awk '{print $1}' )"
|
|
|
9fdd73 |
+ if ! test "$boot_efi_dev" ; then
|
|
|
9fdd73 |
+ LogPrintError "Cannot create EFI Boot Manager entry (unable to find ESP $esp_mountpoint among mounted devices)"
|
|
|
9fdd73 |
+ return 1
|
|
|
9fdd73 |
+ fi
|
|
|
9fdd73 |
+ if test $(get_component_type "$boot_efi_dev") = part ; then
|
|
|
9fdd73 |
+ boot_efi_parts="$boot_efi_dev"
|
|
|
9fdd73 |
+ else
|
|
|
9fdd73 |
+ boot_efi_parts=$( find_partition "$boot_efi_dev" )
|
|
|
9fdd73 |
+ fi
|
|
|
9fdd73 |
+ if ! test "$boot_efi_parts" ; then
|
|
|
9fdd73 |
+ LogPrintError "Cannot create EFI Boot Manager entry (unable to find partition for $boot_efi_dev)"
|
|
|
9fdd73 |
+ return 1
|
|
|
9fdd73 |
+ fi
|
|
|
9fdd73 |
+ LogPrint "Using fallback EFI boot partition(s) $boot_efi_parts (unable to find ESP $esp_mountpoint_inside in layout)"
|
|
|
9fdd73 |
+fi
|
|
|
9fdd73 |
+
|
|
|
9fdd73 |
+local bootloader partition_block_device partition_number disk efipart
|
|
|
9fdd73 |
+
|
|
|
9fdd73 |
+# EFI\fedora\shim.efi
|
|
|
9fdd73 |
+bootloader=$( echo $UEFI_BOOTLOADER | cut -d"/" -f4- | sed -e 's;/;\\;g' )
|
|
|
9fdd73 |
+
|
|
|
9fdd73 |
+for efipart in $boot_efi_parts ; do
|
|
|
9fdd73 |
+ # /dev/sda1 or /dev/mapper/vol34_part2 or /dev/mapper/mpath99p4
|
|
|
9fdd73 |
+ partition_block_device=$( get_device_name $efipart )
|
|
|
9fdd73 |
+ # 1 or 2 or 4 for the examples above
|
|
|
9fdd73 |
+ partition_number=$( get_partition_number $partition_block_device )
|
|
|
9fdd73 |
+ if ! disk=$( get_device_from_partition $partition_block_device $partition_number ) ; then
|
|
|
9fdd73 |
+ LogPrintError "Cannot create EFI Boot Manager entry for ESP $partition_block_device (unable to find the underlying disk)"
|
|
|
9fdd73 |
+ # do not error out - we may be able to locate other disks if there are more of them
|
|
|
9fdd73 |
+ continue
|
|
|
9fdd73 |
+ fi
|
|
|
9fdd73 |
+ LogPrint "Creating EFI Boot Manager entry '$OS_VENDOR $OS_VERSION' for '$bootloader' (UEFI_BOOTLOADER='$UEFI_BOOTLOADER') "
|
|
|
9fdd73 |
+ Log efibootmgr --create --gpt --disk $disk --part $partition_number --write-signature --label \"${OS_VENDOR} ${OS_VERSION}\" --loader \"\\${bootloader}\"
|
|
|
9fdd73 |
+ if efibootmgr --create --gpt --disk $disk --part $partition_number --write-signature --label "${OS_VENDOR} ${OS_VERSION}" --loader "\\${bootloader}" ; then
|
|
|
9fdd73 |
+ # ok, boot loader has been set-up - continue with other disks (ESP can be on RAID)
|
|
|
9fdd73 |
+ NOBOOTLOADER=''
|
|
|
9fdd73 |
+ else
|
|
|
9fdd73 |
+ LogPrintError "efibootmgr failed to create EFI Boot Manager entry on $disk partition $partition_number (ESP $partition_block_device )"
|
|
|
9fdd73 |
+ fi
|
|
|
9fdd73 |
+done
|
|
|
9fdd73 |
+
|
|
|
9fdd73 |
+is_true $NOBOOTLOADER || return 0
|
|
|
9fdd73 |
+LogPrintError "efibootmgr failed to create EFI Boot Manager entry for '$bootloader' (UEFI_BOOTLOADER='$UEFI_BOOTLOADER')"
|
|
|
9fdd73 |
+return 1
|
|
|
9fdd73 |
diff --git a/usr/share/rear/lib/layout-functions.sh b/usr/share/rear/lib/layout-functions.sh
|
|
|
9fdd73 |
index eacc708f..69f80ed7 100644
|
|
|
9fdd73 |
--- a/usr/share/rear/lib/layout-functions.sh
|
|
|
9fdd73 |
+++ b/usr/share/rear/lib/layout-functions.sh
|
|
|
9fdd73 |
@@ -271,12 +271,20 @@ get_child_components() {
|
|
|
9fdd73 |
done
|
|
|
9fdd73 |
}
|
|
|
9fdd73 |
|
|
|
9fdd73 |
-# Return all ancestors of component $1 [ of type $2 ]
|
|
|
9fdd73 |
+# Return all ancestors of component $1 [ of type $2 [ skipping types $3 during resolution ] ]
|
|
|
9fdd73 |
get_parent_components() {
|
|
|
9fdd73 |
- declare -a ancestors devlist
|
|
|
9fdd73 |
- declare current child parent
|
|
|
9fdd73 |
+ declare -a ancestors devlist ignoretypes
|
|
|
9fdd73 |
+ declare current child parent parenttype
|
|
|
9fdd73 |
|
|
|
9fdd73 |
devlist=( "$1" )
|
|
|
9fdd73 |
+ if [[ "$3" ]] ; then
|
|
|
9fdd73 |
+ # third argument should, if present, be a space-separated list
|
|
|
9fdd73 |
+ # of types to ignore when walking up the dependency tree.
|
|
|
9fdd73 |
+ # Convert it to array
|
|
|
9fdd73 |
+ ignoretypes=( $3 )
|
|
|
9fdd73 |
+ else
|
|
|
9fdd73 |
+ ignoretypes=()
|
|
|
9fdd73 |
+ fi
|
|
|
9fdd73 |
while (( ${#devlist[@]} )) ; do
|
|
|
9fdd73 |
current=${devlist[0]}
|
|
|
9fdd73 |
|
|
|
9fdd73 |
@@ -287,6 +295,13 @@ get_parent_components() {
|
|
|
9fdd73 |
if IsInArray "$parent" "${ancestors[@]}" ; then
|
|
|
9fdd73 |
continue
|
|
|
9fdd73 |
fi
|
|
|
9fdd73 |
+ ### ...test if parent is of a correct type if requested...
|
|
|
9fdd73 |
+ if [[ ${#ignoretypes[@]} -gt 0 ]] ; then
|
|
|
9fdd73 |
+ parenttype=$(get_component_type "$parent")
|
|
|
9fdd73 |
+ if IsInArray "$parenttype" "${ignoretypes[@]}" ; then
|
|
|
9fdd73 |
+ continue
|
|
|
9fdd73 |
+ fi
|
|
|
9fdd73 |
+ fi
|
|
|
9fdd73 |
### ...and add them to the list
|
|
|
9fdd73 |
devlist=( "${devlist[@]}" "$parent" )
|
|
|
9fdd73 |
ancestors=( "${ancestors[@]}" "$parent" )
|
|
|
9fdd73 |
@@ -312,26 +327,28 @@ get_parent_components() {
|
|
|
9fdd73 |
}
|
|
|
9fdd73 |
|
|
|
9fdd73 |
# find_devices <other>
|
|
|
9fdd73 |
+# ${2+"$2"} in the following functions ensures that $2 gets passed down quoted if present
|
|
|
9fdd73 |
+# and ignored if not present
|
|
|
9fdd73 |
# Find the disk device(s) component $1 resides on.
|
|
|
9fdd73 |
find_disk() {
|
|
|
9fdd73 |
- get_parent_components "$1" "disk"
|
|
|
9fdd73 |
+ get_parent_components "$1" "disk" ${2+"$2"}
|
|
|
9fdd73 |
}
|
|
|
9fdd73 |
|
|
|
9fdd73 |
find_disk_and_multipath() {
|
|
|
9fdd73 |
- res=$(find_disk "$1")
|
|
|
9fdd73 |
+ res=$(find_disk "$1" ${2+"$2"})
|
|
|
9fdd73 |
if [[ -n "$res" || "$AUTOEXCLUDE_MULTIPATH" =~ ^[yY1] ]]; then
|
|
|
9fdd73 |
echo $res
|
|
|
9fdd73 |
else
|
|
|
9fdd73 |
- find_multipath "$1"
|
|
|
9fdd73 |
+ find_multipath "$1" ${2+"$2"}
|
|
|
9fdd73 |
fi
|
|
|
9fdd73 |
}
|
|
|
9fdd73 |
|
|
|
9fdd73 |
find_multipath() {
|
|
|
9fdd73 |
- get_parent_components "$1" "multipath"
|
|
|
9fdd73 |
+ get_parent_components "$1" "multipath" ${2+"$2"}
|
|
|
9fdd73 |
}
|
|
|
9fdd73 |
|
|
|
9fdd73 |
find_partition() {
|
|
|
9fdd73 |
- get_parent_components "$1" "part"
|
|
|
9fdd73 |
+ get_parent_components "$1" "part" ${2+"$2"}
|
|
|
9fdd73 |
}
|
|
|
9fdd73 |
|
|
|
9fdd73 |
# Function returns partition number of partition block device name
|
|
|
9fdd73 |
@@ -358,6 +375,55 @@ get_partition_number() {
|
|
|
9fdd73 |
|
|
|
9fdd73 |
echo $number
|
|
|
9fdd73 |
}
|
|
|
9fdd73 |
+
|
|
|
9fdd73 |
+# Extract the underlying device name from the full partition device name.
|
|
|
9fdd73 |
+# Underlying device may be a disk, a multipath device or other devices that can be partitioned.
|
|
|
9fdd73 |
+# Should we use the information in $LAYOUT_DEPS, like get_parent_component does,
|
|
|
9fdd73 |
+# instead of string munging?
|
|
|
9fdd73 |
+function get_device_from_partition() {
|
|
|
9fdd73 |
+ local partition_block_device
|
|
|
9fdd73 |
+ local device
|
|
|
9fdd73 |
+ local partition_number
|
|
|
9fdd73 |
+
|
|
|
9fdd73 |
+ partition_block_device=$1
|
|
|
9fdd73 |
+ test -b "$partition_block_device" || BugError "get_device_from_partition called with '$partition_block_device' that is no block device"
|
|
|
9fdd73 |
+ partition_number=${2-$(get_partition_number $partition_block_device )}
|
|
|
9fdd73 |
+ # /dev/sda or /dev/mapper/vol34_part or /dev/mapper/mpath99p or /dev/mmcblk0p
|
|
|
9fdd73 |
+ device=${partition_block_device%$partition_number}
|
|
|
9fdd73 |
+
|
|
|
9fdd73 |
+ # Strip trailing partition remainders like '_part' or '-part' or 'p'
|
|
|
9fdd73 |
+ # if we have 'mapper' in disk device name:
|
|
|
9fdd73 |
+ if [[ ${partition_block_device/mapper//} != $partition_block_device ]] ; then
|
|
|
9fdd73 |
+ # we only expect mpath_partX or mpathpX or mpath-partX
|
|
|
9fdd73 |
+ case $device in
|
|
|
9fdd73 |
+ (*p) device=${device%p} ;;
|
|
|
9fdd73 |
+ (*-part) device=${device%-part} ;;
|
|
|
9fdd73 |
+ (*_part) device=${device%_part} ;;
|
|
|
9fdd73 |
+ (*) Log "Unsupported kpartx partition delimiter for $partition_block_device"
|
|
|
9fdd73 |
+ esac
|
|
|
9fdd73 |
+ fi
|
|
|
9fdd73 |
+
|
|
|
9fdd73 |
+ # For eMMC devices the trailing 'p' in the $device value
|
|
|
9fdd73 |
+ # (as in /dev/mmcblk0p that is derived from /dev/mmcblk0p1)
|
|
|
9fdd73 |
+ # needs to be stripped (to get /dev/mmcblk0), otherwise the
|
|
|
9fdd73 |
+ # efibootmgr call fails because of a wrong disk device name.
|
|
|
9fdd73 |
+ # See also https://github.com/rear/rear/issues/2103
|
|
|
9fdd73 |
+ if [[ $device = *'/mmcblk'+([0-9])p ]] ; then
|
|
|
9fdd73 |
+ device=${device%p}
|
|
|
9fdd73 |
+ fi
|
|
|
9fdd73 |
+
|
|
|
9fdd73 |
+ # For NVMe devices the trailing 'p' in the $device value
|
|
|
9fdd73 |
+ # (as in /dev/nvme0n1p that is derived from /dev/nvme0n1p1)
|
|
|
9fdd73 |
+ # needs to be stripped (to get /dev/nvme0n1), otherwise the
|
|
|
9fdd73 |
+ # efibootmgr call fails because of a wrong disk device name.
|
|
|
9fdd73 |
+ # See also https://github.com/rear/rear/issues/1564
|
|
|
9fdd73 |
+ if [[ $device = *'/nvme'+([0-9])n+([0-9])p ]] ; then
|
|
|
9fdd73 |
+ device=${device%p}
|
|
|
9fdd73 |
+ fi
|
|
|
9fdd73 |
+
|
|
|
9fdd73 |
+ test -b "$device" && echo $device
|
|
|
9fdd73 |
+}
|
|
|
9fdd73 |
+
|
|
|
9fdd73 |
# Returns partition start block or 'unknown'
|
|
|
9fdd73 |
# sda/sda1 or
|
|
|
9fdd73 |
# dm-XX
|