Browse Source

Merge pull request #237 from kacf/fix_bbb_uefi

MEN-3952: beaglebone: Implement workaround for broken U-Boot and kernel.
2.3.x
Kristian Amlie 4 years ago
committed by GitHub
parent
commit
b9437ced86
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 75
      configs/beaglebone_black_base_config
  2. 4
      configs/beaglebone_black_debian_emmc_config
  3. 1
      configs/beaglebone_black_debian_sdcard_config
  4. 53
      mender-convert-modify
  5. 2
      modules/disk.sh
  6. 32
      modules/probe.sh
  7. 19
      scripts/test/run-tests.sh

75
configs/beaglebone_black_base_config

@ -1,39 +1,70 @@
# Binaries generated with the following script: # At the time of writing, the binaries below were uploaded manually. However,
# https://github.com/mendersoftware/mender-convert-integration-scripts/blob/master/build-uboot-bbb.sh # they are simply a vanilla U-Boot build of v2020.07, from Ubuntu 18.04, using
# these commands:
# There are reported issues with GRUB bootloader integration, fallback to U-boot. # make CROSS_COMPILE=arm-linux-gnueabihf- am335x_boneblack_vboot_defconfig
MENDER_GRUB_EFI_INTEGRATION=n # make CROSS_COMPILE=arm-linux-gnueabihf-
# make CROSS_COMPILE=arm-linux-gnueabihf- envtools
BEAGLEBONE_BLACK_BINARIES="beaglebone_black_uefi-2020.07.tar.gz"
BEAGLEBONE_BLACK_BINARIES_URL="${MENDER_STORAGE_URL}/mender-convert/uboot/beaglebone/${BEAGLEBONE_BLACK_BINARIES}"
# We will write a modified bootloader # At the time of writing, the binaries below were uploaded manually. They are
MENDER_COPY_BOOT_GAP=n # simply a dump of the deb package from the link below, with the addition of the
# initrd file, which is not part of the package, but which is generated when
# installed on a live Beaglebone device.
# Original deb URL: http://repos.rcn-ee.com/debian/pool/main/l/linux-upstream/linux-image-4.19.94-ti-r51_1buster_armhf.deb
BEAGLEBONE_EFI_COMPATIBLE_KERNEL="linux-image-4.19.94-ti-r51_1buster_armhf-deb-dump.tar.xz"
BEAGLEBONE_EFI_COMPATIBLE_KERNEL_URL="${MENDER_STORAGE_URL}/mender-convert/beaglebone/kernel/${BEAGLEBONE_EFI_COMPATIBLE_KERNEL}"
BEAGLEBONE_EFI_COMPATIBLE_KERNEL_VERSION=4.19.94-ti-r51
# 4MB alignment MENDER_IGNORE_UBOOT_BROKEN_UEFI=1
MENDER_PARTITION_ALIGNMENT="4194304" MENDER_IGNORE_MISSING_EFI_STUB=1
BEAGLEBONE_BLACK_BINARIES="${BEAGLEBONE_BLACK_CONFIG}-2018.07.tar.gz" function beaglebone_fix_broken_uefi_uboot() {
BEAGLEBONE_BLACK_BINARIES_URL="${MENDER_STORAGE_URL}/mender-convert/uboot/beaglebone/${BEAGLEBONE_BLACK_BINARIES}" log_warn "Attempting to work around broken UEFI support in U-Boot by forcing a newer U-Boot version."
function platform_modify() {
mkdir -p work/bbb/binaries mkdir -p work/bbb/binaries
run_and_log_cmd "wget -q ${BEAGLEBONE_BLACK_BINARIES_URL} -P work/bbb/binaries" run_and_log_cmd "wget -q ${BEAGLEBONE_BLACK_BINARIES_URL} -P work/bbb/binaries"
run_and_log_cmd "tar xzvf work/bbb/binaries/${BEAGLEBONE_BLACK_BINARIES} -C work/bbb/binaries" run_and_log_cmd "tar xzvf work/bbb/binaries/${BEAGLEBONE_BLACK_BINARIES} -C work/bbb/binaries"
# Mask udisks2.service, otherwise it will mount the inactive part and we
# might write an update while it is mounted which often result in
# corruptions.
#
# TODO: Find a way to only blacklist mmcblk0pX devices instead of masking
# the service.
run_and_log_cmd "sudo ln -sf /dev/null work/rootfs/etc/systemd/system/udisks2.service"
# Place u-boot and MLO into rootfs/boot # Place u-boot and MLO into rootfs/boot
run_and_log_cmd "sudo mkdir -p work/rootfs/boot" run_and_log_cmd "sudo mkdir -p work/rootfs/boot"
run_and_log_cmd "sudo cp work/bbb/binaries/MLO work/boot/" run_and_log_cmd "sudo cp work/bbb/binaries/MLO work/boot/"
run_and_log_cmd "sudo cp work/bbb/binaries/u-boot.img work/boot/" run_and_log_cmd "sudo cp work/bbb/binaries/u-boot.img work/boot/"
run_and_log_cmd "sudo cp work/bbb/binaries/fw_env.config work/rootfs/etc/"
run_and_log_cmd "sudo cp work/bbb/binaries/uboot-git-log.txt work/boot"
run_and_log_cmd "sudo install -m 755 work/bbb/binaries/fw_printenv work/rootfs/sbin/fw_printenv" run_and_log_cmd "sudo install -m 755 work/bbb/binaries/fw_printenv work/rootfs/sbin/fw_printenv"
run_and_log_cmd "sudo ln -fs /sbin/fw_printenv work/rootfs/sbin/fw_setenv" run_and_log_cmd "sudo ln -fs /sbin/fw_printenv work/rootfs/sbin/fw_setenv"
} }
function beaglebone_fix_broken_uefi_kernel() {
log_warn "Attempting to work around kernel without EFI stub by using a newer kernel."
mkdir -p work/bbb/kernel
run_and_log_cmd "wget -q $BEAGLEBONE_EFI_COMPATIBLE_KERNEL_URL -P work/bbb/kernel"
mkdir -p work/bbb/kernel/extract
run_and_log_cmd "tar xJf work/bbb/kernel/$BEAGLEBONE_EFI_COMPATIBLE_KERNEL -C work/bbb/kernel/extract"
run_and_log_cmd "cp -r work/bbb/kernel/extract/* work/rootfs/"
run_and_log_cmd "ln -sf vmlinuz-$BEAGLEBONE_EFI_COMPATIBLE_KERNEL_VERSION work/rootfs/boot/kernel"
run_and_log_cmd "ln -sf initrd.img-$BEAGLEBONE_EFI_COMPATIBLE_KERNEL_VERSION work/rootfs/boot/initrd"
}
function beaglebone_fix_broken_uefi() {
if ! is_uboot_with_uefi_support work/boot-gap.bin; then
beaglebone_fix_broken_uefi_uboot
fi
if ! is_efi_compatible_kernel work/rootfs/boot/$kernel_imagetype; then
beaglebone_fix_broken_uefi_kernel
fi
}
PLATFORM_MODIFY_HOOKS+=(beaglebone_fix_broken_uefi)
function disable_udisks2_service() {
# Mask udisks2.service, otherwise it will mount the inactive part and we
# might write an update while it is mounted which often result in
# corruptions.
#
# TODO: Find a way to only blacklist mmcblk0pX devices instead of masking
# the service.
run_and_log_cmd "sudo ln -sf /dev/null work/rootfs/etc/systemd/system/udisks2.service"
}
PLATFORM_MODIFY_HOOKS+=(disable_udisks2_service)

4
configs/beaglebone_black_debian_emmc_config

@ -1,7 +1,3 @@
# Binaries generated with the following script:
# https://github.com/mendersoftware/mender-convert-integration-scripts/blob/master/build-uboot-bbb.sh
BEAGLEBONE_BLACK_CONFIG="beaglebone_black_debian_emmc"
source configs/beaglebone_black_base_config source configs/beaglebone_black_base_config
MENDER_STORAGE_TOTAL_SIZE_MB="3648" MENDER_STORAGE_TOTAL_SIZE_MB="3648"
MENDER_DEVICE_TYPE="beaglebone-emmc" MENDER_DEVICE_TYPE="beaglebone-emmc"

1
configs/beaglebone_black_debian_sdcard_config

@ -1,4 +1,3 @@
BEAGLEBONE_BLACK_CONFIG="beaglebone_black_debian_sdcard"
source configs/beaglebone_black_base_config source configs/beaglebone_black_base_config
MENDER_DEVICE_TYPE="beaglebone-sdcard" MENDER_DEVICE_TYPE="beaglebone-sdcard"
MENDER_STORAGE_DEVICE_BASE="/dev/mmcblk0p" MENDER_STORAGE_DEVICE_BASE="/dev/mmcblk0p"

53
mender-convert-modify

@ -133,25 +133,28 @@ if [ "${MENDER_GRUB_EFI_INTEGRATION}" == "y" ]; then
mender_rootfsa_part=${MENDER_ROOTFS_PART_A_NUMBER} mender_rootfsa_part=${MENDER_ROOTFS_PART_A_NUMBER}
mender_rootfsb_part=${MENDER_ROOTFS_PART_B_NUMBER} mender_rootfsb_part=${MENDER_ROOTFS_PART_B_NUMBER}
mender_grub_storage_device=${MENDER_GRUB_STORAGE_DEVICE} mender_grub_storage_device=${MENDER_GRUB_STORAGE_DEVICE}
kernel_imagetype=${kernel_imagetype} kernel_imagetype=kernel
initrd_imagetype=${initrd_imagetype} initrd_imagetype=initrd
EOF EOF
# For partuuid support grub.cfg expects dedicated variables to be added run_and_log_cmd "ln -s ${kernel_imagetype} work/rootfs/boot/kernel"
if [ "${MENDER_ENABLE_PARTUUID}" == "y" ]; then run_and_log_cmd "ln -s ${initrd_imagetype} work/rootfs/boot/initrd"
rootfsa_partuuid=$(disk_get_partuuid_from_device "${root_part_a_device}")
rootfsb_partuuid=$(disk_get_partuuid_from_device "${root_part_b_device}") # For partuuid support grub.cfg expects dedicated variables to be added
log_info "Using root partition A partuuid in grubenv: $rootfsa_partuuid" if [ "${MENDER_ENABLE_PARTUUID}" == "y" ]; then
log_info "Using root partition B partuuid in grubenv: $rootfsb_partuuid" rootfsa_partuuid=$(disk_get_partuuid_from_device "${root_part_a_device}")
cat <<- EOF >> work/grub-mender-grubenv-${MENDER_GRUBENV_VERSION}/mender_grubenv_defines rootfsb_partuuid=$(disk_get_partuuid_from_device "${root_part_b_device}")
log_info "Using root partition A partuuid in grubenv: $rootfsa_partuuid"
log_info "Using root partition B partuuid in grubenv: $rootfsb_partuuid"
cat <<- EOF >> work/grub-mender-grubenv-${MENDER_GRUBENV_VERSION}/mender_grubenv_defines
mender_rootfsa_uuid=${rootfsa_partuuid} mender_rootfsa_uuid=${rootfsa_partuuid}
mender_rootfsb_uuid=${rootfsb_partuuid} mender_rootfsb_uuid=${rootfsb_partuuid}
EOF EOF
else else
cat <<- EOF >> work/grub-mender-grubenv-${MENDER_GRUBENV_VERSION}/mender_grubenv_defines cat <<- EOF >> work/grub-mender-grubenv-${MENDER_GRUBENV_VERSION}/mender_grubenv_defines
mender_kernel_root_base=${MENDER_STORAGE_DEVICE_BASE} mender_kernel_root_base=${MENDER_STORAGE_DEVICE_BASE}
EOF EOF
fi fi
if [ -n "${MENDER_GRUB_KERNEL_BOOT_ARGS}" ]; then if [ -n "${MENDER_GRUB_KERNEL_BOOT_ARGS}" ]; then
cat <<- EOF > work/grub-mender-grubenv-${MENDER_GRUBENV_VERSION}/11_bootargs_grub.cfg cat <<- EOF > work/grub-mender-grubenv-${MENDER_GRUBENV_VERSION}/11_bootargs_grub.cfg
@ -174,8 +177,8 @@ EOF
sudo rm -rf work/boot/EFI/systemd sudo rm -rf work/boot/EFI/systemd
sudo rm -rf work/boot/NvVars sudo rm -rf work/boot/NvVars
for empty_dir in $(cd work/boot; find . -maxdepth 1 -type d -empty); do for empty_dir in $(cd work/boot; find . -maxdepth 1 -type d -empty); do
sudo rmdir work/boot/$empty_dir sudo rmdir work/boot/$empty_dir
sudo rm work/rootfs/boot/$empty_dir sudo rm work/rootfs/boot/$empty_dir
done done
log_info "Installing GRUB" log_info "Installing GRUB"
@ -193,18 +196,18 @@ EOF
run_and_log_cmd "sudo mkdir -p work/boot/EFI/BOOT" run_and_log_cmd "sudo mkdir -p work/boot/EFI/BOOT"
run_and_log_cmd "sudo cp work/${efi_name} -P work/boot/EFI/BOOT/${efi_target_name}" run_and_log_cmd "sudo cp work/${efi_name} -P work/boot/EFI/BOOT/${efi_target_name}"
fi
# Copy dtb directory to the boot partition for use by the bootloader. # Copy dtb directory to the boot partition for use by the bootloader.
if [ -d work/rootfs/boot/dtbs ]; then if [ -d work/rootfs/boot/dtbs ]; then
# Look for the first directory that has dtb files. First check the base # Look for the first directory that has dtb files. First check the base
# folder, then any subfolders in versioned order. # folder, then any subfolders in versioned order.
for candidate in work/rootfs/boot/dtbs $(find work/rootfs/boot/dtbs/ -maxdepth 1 -type d | sort -V -r); do for candidate in work/rootfs/boot/dtbs $(find work/rootfs/boot/dtbs/ -maxdepth 1 -type d | sort -V -r); do
if [ $(find $candidate -maxdepth 1 -name '*.dtb' | wc -l) -gt 0 ]; then if [ $(find $candidate -maxdepth 1 -name '*.dtb' | wc -l) -gt 0 ]; then
run_and_log_cmd "sudo cp -r $candidate work/boot/dtb" run_and_log_cmd "sudo cp -r $candidate work/boot/dtb"
break break
fi fi
done done
fi
fi fi
run_and_log_cmd "sudo mkdir -p work/rootfs/data/mender" run_and_log_cmd "sudo mkdir -p work/rootfs/data/mender"

2
modules/disk.sh

@ -100,7 +100,7 @@ disk_align_sectors() {
# $2 - destination file # $2 - destination file
# $3 - offset in number of 512 sectors # $3 - offset in number of 512 sectors
disk_write_at_offset() { disk_write_at_offset() {
run_and_log_cmd "dd if=${1} of=${2} seek=${3} conv=sparse,notrunc status=none" run_and_log_cmd "dd if=${1} of=${2} seek=${3} conv=notrunc status=none"
} }
# Create file system image from directory content # Create file system image from directory content

32
modules/probe.sh

@ -272,33 +272,46 @@ probe_initrd_in_boot_and_root() {
} }
check_for_broken_uboot_uefi_support() { check_for_broken_uboot_uefi_support() {
if ! is_uboot_with_uefi_support "$@"; then
local log_level=log_fatal
if [ "$MENDER_IGNORE_UBOOT_BROKEN_UEFI" = 1 ]; then
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
}
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
fi
return 0
}
check_efi_compatible_kernel() {
if ! is_efi_compatible_kernel "$@"; then
local log_level=log_fatal local log_level=log_fatal
if [ "$MENDER_IGNORE_UBOOT_BROKEN_UEFI" = 1 ]; then if [ "$MENDER_IGNORE_MISSING_EFI_STUB" = 1 ]; then
log_level=log_warn log_level=log_warn
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.' $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
} }
check_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 'EFI application'; then if ! file -k $kernel_path | fgrep -q 'EFI application'; then
local log_level=log_fatal return 1
if [ "$MENDER_IGNORE_MISSING_EFI_STUB" = 1 ]; then
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
;; ;;
*) *)
@ -306,4 +319,5 @@ check_efi_compatible_kernel() {
: :
;; ;;
esac esac
return 0
} }

19
scripts/test/run-tests.sh

@ -15,7 +15,9 @@ fi
WORKSPACE=./tests WORKSPACE=./tests
BBB_DEBIAN_IMAGE_URL="http://debian.beagleboard.org/images/bone-debian-9.5-iot-armhf-2018-08-30-4gb.img.xz" BBB_DEBIAN_SDCARD_IMAGE_URL="https://debian.beagleboard.org/images/bone-debian-10.3-iot-armhf-2020-04-06-4gb.img.xz"
# Not on official home page, but found via https://elinux.org/Beagleboard:BeagleBoneBlack_Debian:
BBB_DEBIAN_EMMC_IMAGE_URL="https://rcn-ee.com/rootfs/bb.org/testing/2020-09-21/buster-console/bone-debian-10.5-console-armhf-2020-09-21-1gb.img.xz"
RASPBIAN_IMAGE_URL="http://downloads.raspberrypi.org/raspbian_lite/images/raspbian_lite-2019-09-30/2019-09-26-raspbian-buster-lite.zip" RASPBIAN_IMAGE_URL="http://downloads.raspberrypi.org/raspbian_lite/images/raspbian_lite-2019-09-30/2019-09-26-raspbian-buster-lite.zip"
@ -101,19 +103,22 @@ else
fi fi
if [ "$1" == "--all" -o "$1" == "--only" -a "$2" == "beaglebone" ]; then if [ "$1" == "--all" -o "$1" == "--only" -a "$2" == "beaglebone" ]; then
wget --progress=dot:giga -N ${BBB_DEBIAN_IMAGE_URL} -P input/ wget --progress=dot:giga -N ${BBB_DEBIAN_SDCARD_IMAGE_URL} -P input/
convert_and_test "beaglebone" \ convert_and_test "beaglebone-sdcard" \
"release-1" \ "release-1" \
"input/bone-debian-9.5-iot-armhf-2018-08-30-4gb.img.xz" || test_result=$? "input/bone-debian-10.3-iot-armhf-2020-04-06-4gb.img.xz" \
"--config configs/beaglebone_black_debian_sdcard_config" || test_result=$?
echo >&2 "----------------------------------------" echo >&2 "----------------------------------------"
echo >&2 "Running the uncompressed test" echo >&2 "Running the uncompressed test"
echo >&2 "----------------------------------------" echo >&2 "----------------------------------------"
rm -rf deploy rm -rf deploy
unxz --force "input/bone-debian-9.5-iot-armhf-2018-08-30-4gb.img.xz" wget --progress=dot:giga -N ${BBB_DEBIAN_EMMC_IMAGE_URL} -P input/
convert_and_test "beaglebone" \ unxz --force "input/bone-debian-10.5-console-armhf-2020-09-21-1gb.img.xz"
convert_and_test "beaglebone-emmc" \
"release-1" \ "release-1" \
"input/bone-debian-9.5-iot-armhf-2018-08-30-4gb.img" || test_result=$? "input/bone-debian-10.5-console-armhf-2020-09-21-1gb.img" \
"--config configs/beaglebone_black_debian_emmc_config" || test_result=$?
fi fi
if [ "$1" == "--all" -o "$1" == "--only" -a "$2" == "ubuntu" ]; then if [ "$1" == "--all" -o "$1" == "--only" -a "$2" == "ubuntu" ]; then

Loading…
Cancel
Save