mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-29 18:19:02 +00:00
8ad45992ac
The tar extraction depends on the order in which the files
are added to the tar file. Since the order is not guaranteed
and depends on the host system, the combined mtd write fails
with sysupgrade images built on some systems.
Fix by changing to tar file order independent mtd write.
Fixes: 86e18f6706
("ipq806x: add support for OpenMesh A42")
Signed-off-by: Marek Lindner <mareklindner@neomailbox.ch>
Signed-off-by: Sven Eckelmann <sven@narfation.org>
107 lines
4.1 KiB
Bash
107 lines
4.1 KiB
Bash
# The U-Boot loader of the OpenMesh devices requires image sizes and
|
|
# checksums to be provided in the U-Boot environment.
|
|
# The OpenMesh devices come with 2 main partitions - while one is active
|
|
# sysupgrade will flash the other. The boot order is changed to boot the
|
|
# newly flashed partition. If the new partition can't be booted due to
|
|
# upgrade failures the previously used partition is loaded.
|
|
|
|
platform_do_upgrade_openmesh() {
|
|
local tar_file="$1"
|
|
local restore_backup
|
|
local primary_kernel_mtd
|
|
|
|
local setenv_script="/tmp/fw_env_upgrade"
|
|
|
|
local kernel_mtd="$(find_mtd_index $PART_NAME)"
|
|
local kernel_offset="$(cat /sys/class/mtd/mtd${kernel_mtd}/offset)"
|
|
local total_size="$(cat /sys/class/mtd/mtd${kernel_mtd}/size)"
|
|
|
|
# detect to which flash region the new image is written to.
|
|
#
|
|
# 1. check what is the mtd index for the first flash region on this
|
|
# device
|
|
# 2. check if the target partition ("inactive") has the mtd index of
|
|
# the first flash region
|
|
#
|
|
# - when it is: the new bootseq will be 1,2 and the first region is
|
|
# modified
|
|
# - when it isnt: bootseq will be 2,1 and the second region is
|
|
# modified
|
|
#
|
|
# The detection has to be done via the hardcoded mtd partition because
|
|
# the current boot might be done with the fallback region. Let us
|
|
# assume that the current bootseq is 1,2. The bootloader detected that
|
|
# the image in flash region 1 is corrupt and thus switches to flash
|
|
# region 2. The bootseq in the u-boot-env is now still the same and
|
|
# the sysupgrade code can now only rely on the actual mtd indexes and
|
|
# not the bootseq variable to detect the currently booted flash
|
|
# region/image.
|
|
#
|
|
# In the above example, an implementation which uses bootseq ("1,2") to
|
|
# detect the currently booted image would assume that region 1 is booted
|
|
# and then overwrite the variables for the wrong flash region (aka the
|
|
# one which isn't modified). This could result in a device which doesn't
|
|
# boot anymore to Linux until it was reflashed with ap51-flash.
|
|
local next_boot_part="1"
|
|
case "$(board_name)" in
|
|
openmesh,a42)
|
|
primary_kernel_mtd=8
|
|
;;
|
|
openmesh,a62)
|
|
primary_kernel_mtd=10
|
|
;;
|
|
*)
|
|
echo "failed to detect primary kernel mtd partition for board"
|
|
return 1
|
|
;;
|
|
esac
|
|
[ "$kernel_mtd" = "$primary_kernel_mtd" ] || next_boot_part="2"
|
|
|
|
local board_dir=$(tar tf $tar_file | grep -m 1 '^sysupgrade-.*/$')
|
|
board_dir=${board_dir%/}
|
|
|
|
local kernel_length=$(tar xf $tar_file ${board_dir}/kernel -O | wc -c)
|
|
local rootfs_length=$(tar xf $tar_file ${board_dir}/root -O | wc -c)
|
|
# rootfs without EOF marker
|
|
rootfs_length=$((rootfs_length-4))
|
|
|
|
local kernel_md5=$(tar xf $tar_file ${board_dir}/kernel -O | md5sum); kernel_md5="${kernel_md5%% *}"
|
|
# md5 checksum of rootfs with EOF marker
|
|
local rootfs_md5=$(tar xf $tar_file ${board_dir}/root -O | dd bs=1 count=$rootfs_length | md5sum); rootfs_md5="${rootfs_md5%% *}"
|
|
|
|
#
|
|
# add tar support to get_image() to use default_do_upgrade() instead?
|
|
#
|
|
|
|
# take care of restoring a saved config
|
|
[ "$SAVE_CONFIG" -eq 1 ] && restore_backup="${MTD_CONFIG_ARGS} -j ${CONF_TAR}"
|
|
|
|
mtd -q erase inactive
|
|
tar xf $tar_file ${board_dir}/root -O | mtd -n -p $kernel_length $restore_backup write - $PART_NAME
|
|
tar xf $tar_file ${board_dir}/kernel -O | mtd -n write - $PART_NAME
|
|
|
|
# prepare new u-boot env
|
|
if [ "$next_boot_part" = "1" ]; then
|
|
echo "bootseq 1,2" > $setenv_script
|
|
else
|
|
echo "bootseq 2,1" > $setenv_script
|
|
fi
|
|
|
|
printf "kernel_size_%i 0x%08x\n" $next_boot_part $kernel_length >> $setenv_script
|
|
printf "vmlinux_start_addr 0x%08x\n" ${kernel_offset} >> $setenv_script
|
|
printf "vmlinux_size 0x%08x\n" ${kernel_length} >> $setenv_script
|
|
printf "vmlinux_checksum %s\n" ${kernel_md5} >> $setenv_script
|
|
|
|
printf "rootfs_size_%i 0x%08x\n" $next_boot_part $((total_size-kernel_length)) >> $setenv_script
|
|
printf "rootfs_start_addr 0x%08x\n" $((kernel_offset+kernel_length)) >> $setenv_script
|
|
printf "rootfs_size 0x%08x\n" ${rootfs_length} >> $setenv_script
|
|
printf "rootfs_checksum %s\n" ${rootfs_md5} >> $setenv_script
|
|
|
|
# store u-boot env changes
|
|
mkdir -p /var/lock
|
|
fw_setenv -s $setenv_script || {
|
|
echo "failed to update U-Boot environment"
|
|
return 1
|
|
}
|
|
}
|