@ -19,34 +19,34 @@
# No input parameters and these work on the assumption that boot and root parts
# No input parameters and these work on the assumption that boot and root parts
# are mounted at work/boot and work/rootfs
# are mounted at work/boot and work/rootfs
probe_arch( ) {
probe_arch( ) {
# --dereference, means to follow symlinks because 'ls' could be a symlink
# --dereference, means to follow symlinks because 'ls' could be a symlink
# to busybox
# to busybox
file_info = ""
file_info = ""
for location in bin/ls usr/bin/ls; do
for location in bin/ls usr/bin/ls; do
if [ -L work/rootfs/${ location } ] ; then
if [ -L work/rootfs/${ location } ] ; then
location = $( readlink work/rootfs/${ location } )
location = $( readlink work/rootfs/${ location } )
fi
fi
if [ -e work/rootfs/${ location } ] ; then
if [ -e work/rootfs/${ location } ] ; then
file_info = $( file -b --dereference work/rootfs/${ location } )
file_info = $( file -b --dereference work/rootfs/${ location } )
break
break
fi
fi
done
done
if [ -z " ${ file_info } " ] ; then
if [ -z " ${ file_info } " ] ; then
log_fatal "Sorry, not able to determine target architecture"
log_fatal "Sorry, not able to determine target architecture"
fi
fi
target_arch = "unknown"
target_arch = "unknown"
if grep -q x86-64 <<< " ${ file_info } " ; then
if grep -q x86-64 <<< " ${ file_info } " ; then
target_arch = "x86-64"
target_arch = "x86-64"
elif grep -Eq "ELF 32-bit.*ARM" <<< " ${ file_info } " ; then
elif grep -Eq "ELF 32-bit.*ARM" <<< " ${ file_info } " ; then
target_arch = "arm"
target_arch = "arm"
elif grep -Eq "ELF 64-bit.*aarch64" <<< " ${ file_info } " ; then
elif grep -Eq "ELF 64-bit.*aarch64" <<< " ${ file_info } " ; then
target_arch = "aarch64"
target_arch = "aarch64"
else
else
log_fatal " Unsupported architecture: ${ file_info } "
log_fatal " Unsupported architecture: ${ file_info } "
fi
fi
echo " ${ target_arch } "
echo " ${ target_arch } "
}
}
# Prints GRUB EFI name depending on target architecture
# Prints GRUB EFI name depending on target architecture
@ -54,23 +54,23 @@ probe_arch() {
# No input parameters and these work on the assumption that boot and root parts
# No input parameters and these work on the assumption that boot and root parts
# are mounted at work/boot and work/rootfs
# are mounted at work/boot and work/rootfs
probe_grub_efi_name( ) {
probe_grub_efi_name( ) {
efi_name = ""
efi_name = ""
arch = $( probe_arch)
arch = $( probe_arch)
case " ${ arch } " in
case " ${ arch } " in
"x86-64" )
"x86-64" )
efi_name = "grub-efi-bootx64.efi"
efi_name = "grub-efi-bootx64.efi"
; ;
; ;
"arm" )
"arm" )
efi_name = "grub-efi-bootarm.efi"
efi_name = "grub-efi-bootarm.efi"
; ;
; ;
"aarch64" )
"aarch64" )
efi_name = "grub-efi-bootaa64.efi"
efi_name = "grub-efi-bootaa64.efi"
; ;
; ;
*)
*)
log_fatal " Unknown arch: ${ arch } "
log_fatal " Unknown arch: ${ arch } "
; ;
; ;
esac
esac
echo " $efi_name "
echo " $efi_name "
}
}
# Prints Debian arch name depending on target architecture
# Prints Debian arch name depending on target architecture
@ -78,23 +78,23 @@ probe_grub_efi_name() {
# No input parameters and these work on the assumption that boot and root parts
# No input parameters and these work on the assumption that boot and root parts
# are mounted at work/boot and work/rootfs
# are mounted at work/boot and work/rootfs
probe_debian_arch_name( ) {
probe_debian_arch_name( ) {
deb_arch = ""
deb_arch = ""
arch = $( probe_arch)
arch = $( probe_arch)
case " ${ arch } " in
case " ${ arch } " in
"x86-64" )
"x86-64" )
deb_arch = "amd64"
deb_arch = "amd64"
; ;
; ;
"arm" )
"arm" )
deb_arch = "armhf"
deb_arch = "armhf"
; ;
; ;
"aarch64" )
"aarch64" )
deb_arch = "arm64"
deb_arch = "arm64"
; ;
; ;
*)
*)
log_fatal " Unknown arch: ${ arch } "
log_fatal " Unknown arch: ${ arch } "
; ;
; ;
esac
esac
echo " ${ deb_arch } "
echo " ${ deb_arch } "
}
}
# Prints GRUB EFI target name depending on target architecture
# Prints GRUB EFI target name depending on target architecture
@ -104,23 +104,23 @@ probe_debian_arch_name() {
# No input parameters and these work on the assumption that boot and root parts
# No input parameters and these work on the assumption that boot and root parts
# are mounted at work/boot and work/rootfs
# are mounted at work/boot and work/rootfs
probe_grub_efi_target_name( ) {
probe_grub_efi_target_name( ) {
efi_target_name = ""
efi_target_name = ""
arch = $( probe_arch)
arch = $( probe_arch)
case " $arch " in
case " $arch " in
"x86-64" )
"x86-64" )
efi_target_name = "bootx64.efi"
efi_target_name = "bootx64.efi"
; ;
; ;
"arm" )
"arm" )
efi_target_name = "bootarm.efi"
efi_target_name = "bootarm.efi"
; ;
; ;
"aarch64" )
"aarch64" )
efi_target_name = "bootaa64.efi"
efi_target_name = "bootaa64.efi"
; ;
; ;
*)
*)
log_fatal " Unknown arch: ${ arch } "
log_fatal " Unknown arch: ${ arch } "
; ;
; ;
esac
esac
echo " $efi_target_name "
echo " $efi_target_name "
}
}
# Prints path to the Linux kernel image
# Prints path to the Linux kernel image
@ -128,36 +128,36 @@ probe_grub_efi_target_name() {
# $1 - directory in which the search is performed
# $1 - directory in which the search is performed
#
#
probe_kernel_image( ) {
probe_kernel_image( ) {
kernel_image_path = ""
kernel_image_path = ""
for image in vmlinuz zImage bzImage; do
for image in vmlinuz zImage bzImage; do
# Linux kernel image type and naming varies between different platforms.
# Linux kernel image type and naming varies between different platforms.
#
#
# The wildcard at the end is important, because it is common to suffix the
# The wildcard at the end is important, because it is common to suffix the
# Linux kernel version to the image type/name, e.g:
# Linux kernel version to the image type/name, e.g:
#
#
# vmlinuz-4.14-x86_64
# vmlinuz-4.14-x86_64
# vmlinuz-3.10.0-862.el7.x86_64
# vmlinuz-3.10.0-862.el7.x86_64
# vmlinuz-4.15.0-20-generic
# vmlinuz-4.15.0-20-generic
#
#
#Search for kernels, resolve symlinks, ignore invalid and select the latest if many
#Search for kernels, resolve symlinks, ignore invalid and select the latest if many
kernels = $( sudo find ${ 1 } -name ${ image } * ! -name '*-rescue-*' ! -name '*.old' \
kernels = $( sudo find ${ 1 } -name ${ image } * ! -name '*-rescue-*' ! -name '*.old' \
-exec readlink -f { } \; | awk -F '/' '{print $NF,$0}' | sort -k1rV | uniq)
-exec readlink -f { } \; | awk -F '/' '{print $NF,$0}' | sort -k1rV | uniq)
kernel_image_path = $( head -n 1 <<< " $kernels " | cut -f2- -d' ' )
kernel_image_path = $( head -n 1 <<< " $kernels " | cut -f2- -d' ' )
n = $( wc -l <<< " $kernels " )
n = $( wc -l <<< " $kernels " )
if [ " $n " -gt "1" ] ; then
if [ " $n " -gt "1" ] ; then
msg = $( awk '{printf " %s\n", $2}' <<< ${ kernels } )
msg = $( awk '{printf " %s\n", $2}' <<< ${ kernels } )
log_warn " Found multiple kernel images: \n\n ${ msg } \n "
log_warn " Found multiple kernel images: \n\n ${ msg } \n "
log_warn " Selecting newest kernel image: \n\n ${ kernel_image_path } \n "
log_warn " Selecting newest kernel image: \n\n ${ kernel_image_path } \n "
log_warn "Set MENDER_GRUB_KERNEL_IMAGETYPE to override selected kernel"
log_warn "Set MENDER_GRUB_KERNEL_IMAGETYPE to override selected kernel"
fi
fi
#kernel_image_path=$(sudo find ${1} -name ${image}* ! -name '*-rescue-*' | sort -rV | head -n 1 )
#kernel_image_path=$(sudo find ${1} -name ${image}* ! -name '*-rescue-*' | sort -rV | head -n 1 )
if [ -n " ${ kernel_image_path } " ] ; then
if [ -n " ${ kernel_image_path } " ] ; then
break
break
fi
fi
done
done
echo " ${ kernel_image_path } "
echo " ${ kernel_image_path } "
}
}
# Prints path to the initrd/initramfs image
# Prints path to the initrd/initramfs image
@ -165,33 +165,33 @@ probe_kernel_image() {
# $1 - directory in which the search is performed
# $1 - directory in which the search is performed
#
#
probe_initrd_image( ) {
probe_initrd_image( ) {
initrd_image_path = ""
initrd_image_path = ""
for image in initramfs initrd; do
for image in initramfs initrd; do
# initrd/initramfs naming varies between different platforms.
# initrd/initramfs naming varies between different platforms.
#
#
# The wildcard at the end is important, because it is common to suffix the
# The wildcard at the end is important, because it is common to suffix the
# Linux kernel version to the image name, e.g:
# Linux kernel version to the image name, e.g:
#
#
# initrd.img-4.15.0-20-generic
# initrd.img-4.15.0-20-generic
#
#
#Search for initrd, resolve symlinks, ignore invalid and select the latest if many
#Search for initrd, resolve symlinks, ignore invalid and select the latest if many
initrds = $( sudo find ${ 1 } -name ${ image } * ! -name '*-rescue-*' ! -name '*.old' \
initrds = $( sudo find ${ 1 } -name ${ image } * ! -name '*-rescue-*' ! -name '*.old' \
-exec readlink -f { } \; | awk -F '/' '{print $NF,$0}' | sort -k1rV | uniq)
-exec readlink -f { } \; | awk -F '/' '{print $NF,$0}' | sort -k1rV | uniq)
initrd_image_path = $( head -n 1 <<< " $initrds " | cut -f2- -d' ' )
initrd_image_path = $( head -n 1 <<< " $initrds " | cut -f2- -d' ' )
n = $( wc -l <<< " $initrds " )
n = $( wc -l <<< " $initrds " )
if [ " $n " -gt "1" ] ; then
if [ " $n " -gt "1" ] ; then
msg = $( awk '{printf " %s\n", $2}' <<< ${ initrds } )
msg = $( awk '{printf " %s\n", $2}' <<< ${ initrds } )
log_warn " Found multiple initrd images: \n\n ${ msg } \n "
log_warn " Found multiple initrd images: \n\n ${ msg } \n "
log_warn " Selecting newest initrd: \n\n ${ initrd_image_path } \n "
log_warn " Selecting newest initrd: \n\n ${ initrd_image_path } \n "
log_warn "Set MENDER_GRUB_INITRD_IMAGETYPE to override selected initrd"
log_warn "Set MENDER_GRUB_INITRD_IMAGETYPE to override selected initrd"
fi
fi
if [ -n " ${ initrd_image_path } " ] ; then
if [ -n " ${ initrd_image_path } " ] ; then
break
break
fi
fi
done
done
echo " ${ initrd_image_path } "
echo " ${ initrd_image_path } "
}
}
# Prints Linux kernel image name
# Prints Linux kernel image name
@ -202,36 +202,36 @@ probe_initrd_image() {
# No input parameters and these work on the assumption that boot and root parts
# No input parameters and these work on the assumption that boot and root parts
# are mounted at work/boot and work/rootfs
# are mounted at work/boot and work/rootfs
probe_kernel_in_boot_and_root( ) {
probe_kernel_in_boot_and_root( ) {
kernel_imagetype_path = ""
kernel_imagetype_path = ""
# Important to check rootfs/boot first, because it might be possible that
# Important to check rootfs/boot first, because it might be possible that
# they are stored in both partitions, and in this case we want to find the
# they are stored in both partitions, and in this case we want to find the
# image in the rootfs first and use that, to avoid copying it over from
# image in the rootfs first and use that, to avoid copying it over from
# boot part when it is already there.
# boot part when it is already there.
for boot in work/rootfs/boot work/boot; do
for boot in work/rootfs/boot work/boot; do
kernel_imagetype_path = $( probe_kernel_image ${ boot } )
kernel_imagetype_path = $( probe_kernel_image ${ boot } )
if [ -n " ${ kernel_imagetype_path } " ] && [ " ${ boot } " = = "work/boot" ] ; then
if [ -n " ${ kernel_imagetype_path } " ] && [ " ${ boot } " = = "work/boot" ] ; then
log_info "Found Linux kernel image in boot part, moving to rootfs/boot"
log_info "Found Linux kernel image in boot part, moving to rootfs/boot"
sudo cp ${ kernel_imagetype_path } work/rootfs/boot
sudo cp ${ kernel_imagetype_path } work/rootfs/boot
break;
break
elif [ -n " ${ kernel_imagetype_path } " ] ; then
elif [ -n " ${ kernel_imagetype_path } " ] ; then
break;
break
fi
fi
done
done
if [ -z " ${ kernel_imagetype_path } " ] ; then
if [ -z " ${ kernel_imagetype_path } " ] ; then
log_warn "Unfortunately we where not able to find the Linux kernel image."
log_warn "Unfortunately we where not able to find the Linux kernel image."
log_fatal "Please specify the image name using MENDER_GRUB_KERNEL_IMAGETYPE"
log_fatal "Please specify the image name using MENDER_GRUB_KERNEL_IMAGETYPE"
fi
fi
log_info " Found Linux kernel image: \n\n\t ${ kernel_imagetype_path } \n "
log_info " Found Linux kernel image: \n\n\t ${ kernel_imagetype_path } \n "
kernel_imagetype = $( basename ${ kernel_imagetype_path } )
kernel_imagetype = $( basename ${ kernel_imagetype_path } )
if [ " ${ MENDER_GRUB_EFI_INTEGRATION } " = = "y" ] ; then
if [ " ${ MENDER_GRUB_EFI_INTEGRATION } " = = "y" ] ; then
check_efi_compatible_kernel ${ kernel_imagetype_path }
check_efi_compatible_kernel ${ kernel_imagetype_path }
fi
fi
echo " ${ kernel_imagetype } "
echo " ${ kernel_imagetype } "
}
}
# Prints initrd/initramfs image name
# Prints initrd/initramfs image name
@ -242,82 +242,82 @@ probe_kernel_in_boot_and_root() {
# No input parameters and these work on the assumption that boot and root parts
# No input parameters and these work on the assumption that boot and root parts
# are mounted at work/boot and work/rootfs
# are mounted at work/boot and work/rootfs
probe_initrd_in_boot_and_root( ) {
probe_initrd_in_boot_and_root( ) {
initrd_image_path = ""
initrd_image_path = ""
# Important to check rootfs/boot first, because it might be possible that
# Important to check rootfs/boot first, because it might be possible that
# they are stored in both partitions, and in this case we want to find the
# they are stored in both partitions, and in this case we want to find the
# image in the rootfs first and use that, to avoid copying it over from
# image in the rootfs first and use that, to avoid copying it over from
# boot part when it is already there.
# boot part when it is already there.
for boot in work/rootfs/boot work/boot; do
for boot in work/rootfs/boot work/boot; do
initrd_image_path = $( probe_initrd_image ${ boot } )
initrd_image_path = $( probe_initrd_image ${ boot } )
if [ -n " ${ initrd_image_path } " ] && [ " ${ boot } " = = "work/boot" ] ; then
if [ -n " ${ initrd_image_path } " ] && [ " ${ boot } " = = "work/boot" ] ; then
sudo cp ${ initrd_image_path } work/rootfs/boot
sudo cp ${ initrd_image_path } work/rootfs/boot
break;
break
elif [ -n " ${ initrd_image_path } " ] ; then
elif [ -n " ${ initrd_image_path } " ] ; then
break;
break
fi
fi
done
done
if [ -n " ${ initrd_image_path } " ] ; then
if [ -n " ${ initrd_image_path } " ] ; then
log_info " Found initramfs image: \n\n\t ${ initrd_image_path } \n "
log_info " Found initramfs image: \n\n\t ${ initrd_image_path } \n "
initrd_imagetype = $( basename ${ initrd_image_path } )
initrd_imagetype = $( basename ${ initrd_image_path } )
else
else
log_info "Unfortunately we where not able to find the initrd image."
log_info "Unfortunately we where not able to find the initrd image."
log_info " Please specify the image name using MENDER_GRUB_INITRD_IMAGETYPE \
log_info " Please specify the image name using MENDER_GRUB_INITRD_IMAGETYPE \
( only required if your board is using this) "
( only required if your board is using this) "
initrd_imagetype = ""
initrd_imagetype = ""
fi
fi
echo " ${ initrd_imagetype } "
echo " ${ initrd_imagetype } "
}
}
check_for_broken_uboot_uefi_support( ) {
check_for_broken_uboot_uefi_support( ) {
if ! is_uboot_with_uefi_support " $@ " ; then
if ! is_uboot_with_uefi_support " $@ " ; then
local log_level = log_fatal
local log_level = log_fatal
if [ " $MENDER_IGNORE_UBOOT_BROKEN_UEFI " = 1 ] ; then
if [ " $MENDER_IGNORE_UBOOT_BROKEN_UEFI " = 1 ] ; then
log_level = log_warn
log_level = log_warn
fi
$log_level 'Detected a U-Boot version in the range v2018.09 - v2019.07. These U-Boot versions are known to have broken UEFI support, and therefore the MENDER_GRUB_EFI_INTEGRATION feature is unlikely to work. This only affects newly flashed devices using the partition image (extension ending in "img"). The Mender artifact should still work to upgrade an existing, working device. There are two possible workarounds for this issue: 1) Use either an older or a newer image that works, and use a Mender artifact afterwards to up/down-grade it to the version you want. 2) If the device has a non-UEFI U-Boot port in mender-convert, use that (look for a board specific file in `configs`) . If you want to ignore this error and force creation of the image, set the MENDER_IGNORE_UBOOT_BROKEN_UEFI=1 config option.'
fi
fi
$log_level 'Detected a U-Boot version in the range v2018.09 - v2019.07. These U-Boot versions are known to have broken UEFI support, and therefore the MENDER_GRUB_EFI_INTEGRATION feature is unlikely to work. This only affects newly flashed devices using the partition image (extension ending in "img"). The Mender artifact should still work to upgrade an existing, working device. There are two possible workarounds for this issue: 1) Use either an older or a newer image that works, and use a Mender artifact afterwards to up/down-grade it to the version you want. 2) If the device has a non-UEFI U-Boot port in mender-convert, use that (look for a board specific file in `configs`) . If you want to ignore this error and force creation of the image, set the MENDER_IGNORE_UBOOT_BROKEN_UEFI=1 config option.'
fi
}
}
is_uboot_with_uefi_support( ) {
is_uboot_with_uefi_support( ) {
local path = " $1 "
local path = " $1 "
# Broken UEFI support in range v2018.09 - v2019.07 (see MEN-2404)
# Broken UEFI support in range v2018.09 - v2019.07 (see MEN-2404)
local regex = 'U-Boot 20(18\.(09|1[0-2])|19\.0[1-7])'
local regex = 'U-Boot 20(18\.(09|1[0-2])|19\.0[1-7])'
if egrep -qr " $regex " " $path " ; then
if egrep -qr " $regex " " $path " ; then
return 1
return 1
fi
fi
return 0
return 0
}
}
check_efi_compatible_kernel( ) {
check_efi_compatible_kernel( ) {
if ! is_efi_compatible_kernel " $@ " ; then
if ! is_efi_compatible_kernel " $@ " ; then
local log_level = log_fatal
local log_level = log_fatal
if [ " $MENDER_IGNORE_MISSING_EFI_STUB " = 1 ] ; then
if [ " $MENDER_IGNORE_MISSING_EFI_STUB " = 1 ] ; then
log_level = log_warn
log_level = log_warn
fi
$log_level 'Detected a kernel which does not have an EFI stub. This kernel is not supported when booting with UEFI. Please consider using a U-Boot port if the board has one (look for a board specific file in `configs`), or find a kernel which has the CONFIG_EFI_STUB turned on. To ignore this message and proceed anyway, set the MENDER_IGNORE_MISSING_EFI_STUB=1 config option.'
fi
fi
$log_level 'Detected a kernel which does not have an EFI stub. This kernel is not supported when booting with UEFI. Please consider using a U-Boot port if the board has one (look for a board specific file in `configs`), or find a kernel which has the CONFIG_EFI_STUB turned on. To ignore this message and proceed anyway, set the MENDER_IGNORE_MISSING_EFI_STUB=1 config option.'
fi
}
}
is_efi_compatible_kernel( ) {
is_efi_compatible_kernel( ) {
kernel_path = " $1 "
kernel_path = " $1 "
case " $( probe_arch) " in
case " $( probe_arch) " in
arm| aarch64)
arm | aarch64)
# On ARM, as of version 2.04, GRUB can only boot kernels which have an EFI
# On ARM, as of version 2.04, GRUB can only boot kernels which have an EFI
# stub in them. See MEN-2404.
# stub in them. See MEN-2404.
if ! file -k $kernel_path | fgrep -q 'EFI application' ; then
if ! file -k $kernel_path | fgrep -q 'EFI application' ; then
return 1
return 1
fi
fi
; ;
; ;
*)
*)
# Other platforms are fine.
# Other platforms are fine.
:
:
; ;
; ;
esac
esac
return 0
return 0
}
}