[openwrt/openwrt] ath79: add Senao 'failsafe' sysupgrade procedure

LEDE Commits lede-commits at lists.infradead.org
Fri Jun 11 00:01:38 PDT 2021


ynezz pushed a commit to openwrt/openwrt.git, branch openwrt-21.02:
https://git.openwrt.org/e823fb1763a3b08c64ff68852279a28b33f4cc1a

commit e823fb1763a3b08c64ff68852279a28b33f4cc1a
Author: Michael Pratt <mcpratt at pm.me>
AuthorDate: Fri Feb 12 18:19:10 2021 -0500

    ath79: add Senao 'failsafe' sysupgrade procedure
    
    Use a similar upgrade method for sysupgrade.bin, like factory.bin,
    for Senao boards with the tar.gz OEM upgrade platform,
    and 'failsafe' image which is loaded on checksum failure.
    
    This is inspired by the OEM upgrade script /etc/fwupgrade.sh
    and the existing platforms for dual-boot Senao boards.
    
    Previously, if the real kernel was damaged or missing
    the only way to recover was with UART serial console,
    because the OKLI lzma-loader is programmed to halt.
    
    uboot did not detect cases where kernel or rootfs is damaged
    and boots OKLI instead of the failsafe image,
    because the checksums stored in uboot environment
    did not include the real kernel and rootfs space.
    
    Now, the stored checksums include the space for both
    the lzma-loader, kernel, and rootfs.
    Therefore, these boards are now practically unbrickable.
    
    Also, the factory.bin and sysupgrade.bin are now the same,
    except for image metadata.
    This allows for flashing OEM image directly from openwrt
    as well as flashing openwrt image directly from OEM.
    
    Make 'loader' partition writable so that it can be updated
    during a sysupgrade.
    
    tested with
    ENS202EXT v1
    EAP1200H
    EAP350 v1
    EAP600
    ECB350 v1
    ECB600
    ENH202 v1
    
    Signed-off-by: Michael Pratt <mcpratt at pm.me>
    (cherry picked from commit d5035f0d2694cb9c5a93ed72e3b6d2dd1770741e)
---
 target/linux/ath79/dts/ar724x_senao_loader-4k.dtsi |  1 -
 .../linux/ath79/dts/ar724x_senao_loader-64k.dtsi   |  1 -
 target/linux/ath79/dts/ar934x_senao_loader.dtsi    |  1 -
 target/linux/ath79/dts/qca955x_senao_loader.dtsi   |  1 -
 .../base-files/lib/upgrade/failsafe_datachk.sh     | 64 ++++++++++++++++++++++
 .../generic/base-files/lib/upgrade/platform.sh     | 14 +++++
 target/linux/ath79/image/common-senao.mk           |  1 +
 .../base-files/lib/upgrade/failsafe_datachk.sh     | 64 ++++++++++++++++++++++
 .../ath79/tiny/base-files/lib/upgrade/platform.sh  | 14 +++++
 9 files changed, 157 insertions(+), 4 deletions(-)

diff --git a/target/linux/ath79/dts/ar724x_senao_loader-4k.dtsi b/target/linux/ath79/dts/ar724x_senao_loader-4k.dtsi
index 501ff26859..0dff79eb46 100644
--- a/target/linux/ath79/dts/ar724x_senao_loader-4k.dtsi
+++ b/target/linux/ath79/dts/ar724x_senao_loader-4k.dtsi
@@ -56,7 +56,6 @@
 			partition at a0000 {
 				label = "loader";
 				reg = <0xa0000 0x1000>;
-				read-only;
 			};
 
 			fwconcat1: partition at a1000 {
diff --git a/target/linux/ath79/dts/ar724x_senao_loader-64k.dtsi b/target/linux/ath79/dts/ar724x_senao_loader-64k.dtsi
index 54dbec18b3..831f0385a9 100644
--- a/target/linux/ath79/dts/ar724x_senao_loader-64k.dtsi
+++ b/target/linux/ath79/dts/ar724x_senao_loader-64k.dtsi
@@ -56,7 +56,6 @@
 			partition at a0000 {
 				label = "loader";
 				reg = <0xa0000 0x10000>;
-				read-only;
 			};
 
 			fwconcat1: partition at b0000 {
diff --git a/target/linux/ath79/dts/ar934x_senao_loader.dtsi b/target/linux/ath79/dts/ar934x_senao_loader.dtsi
index 35e5f13535..8247cc85dc 100644
--- a/target/linux/ath79/dts/ar934x_senao_loader.dtsi
+++ b/target/linux/ath79/dts/ar934x_senao_loader.dtsi
@@ -60,7 +60,6 @@
 			partition at a0000 {
 				label = "loader";
 				reg = <0x0a0000 0x010000>;
-				read-only;
 			};
 
 			fwconcat1: partition at b0000 {
diff --git a/target/linux/ath79/dts/qca955x_senao_loader.dtsi b/target/linux/ath79/dts/qca955x_senao_loader.dtsi
index 77eabde80a..846d3ed0af 100644
--- a/target/linux/ath79/dts/qca955x_senao_loader.dtsi
+++ b/target/linux/ath79/dts/qca955x_senao_loader.dtsi
@@ -58,7 +58,6 @@
 			partition at a0000 {
 				label = "loader";
 				reg = <0x0a0000 0x010000>;
-				read-only;
 			};
 
 			fwconcat1: partition at b0000 {
diff --git a/target/linux/ath79/generic/base-files/lib/upgrade/failsafe_datachk.sh b/target/linux/ath79/generic/base-files/lib/upgrade/failsafe_datachk.sh
new file mode 100644
index 0000000000..de84233de1
--- /dev/null
+++ b/target/linux/ath79/generic/base-files/lib/upgrade/failsafe_datachk.sh
@@ -0,0 +1,64 @@
+# U-Boot with the datachk patchset requires image sizes, offsets,
+# and checksums to be provided in the U-Boot environment.
+# This script is based on the dualboot version for devices that come with 2 OS partitions.
+# For Senao boards with a "failsafe" partition image, the process is almost the same.
+# Instead of booting a secondary instalation on checksum failure,
+# the failsafe image is booted instead.
+# These boards also use the OKLI lzma kernel loader and mtd-concat
+# So the kernel check is for the loader, the rootfs check is for kernel + rootfs
+
+platform_do_upgrade_failsafe_datachk() {
+	local setenv_script="/tmp/fw_env_upgrade"
+
+	local flash_base=0x9f000000
+
+	local kernel_mtd=$(find_mtd_index ${KERNEL_PART:-kernel})
+	local rootfs_mtd=$(find_mtd_index ${ROOTFS_PART:-rootfs})
+
+	local kernel_offset=$(cat /sys/class/mtd/mtd${kernel_mtd}/offset)
+	local rootfs_offset=$(cat /sys/class/mtd/mtd${rootfs_mtd}/offset)
+
+	if [ -n "$IMAGE_LIST" ]; then
+		KERNEL_FILE=$($IMAGE_LIST | grep $KERNEL_FILE)
+		ROOTFS_FILE=$($IMAGE_LIST | grep $ROOTFS_FILE)
+	fi
+
+	local kernel_size=$($IMAGE_CMD $KERNEL_FILE | wc -c)
+	local rootfs_size=$($IMAGE_CMD $ROOTFS_FILE | wc -c)
+
+	# rootfs without JFFS2
+	local rootfs_blocks=$((rootfs_size / 4096))
+	rootfs_size=$((rootfs_blocks * 4096))
+
+	local kernel_md5=$($IMAGE_CMD $KERNEL_FILE | md5sum | cut -d ' ' -f1)
+	local rootfs_md5=$($IMAGE_CMD $ROOTFS_FILE | dd bs=4k count=$rootfs_blocks iflag=fullblock | md5sum | cut -d ' ' -f1)
+
+	# prepare new u-boot-env vars
+	printf "vmlinux_start_addr 0x%08x\n" $((flash_base + kernel_offset)) >> $setenv_script
+	printf "vmlinux_size 0x%08x\n" ${kernel_size} >> $setenv_script
+	printf "vmlinux_checksum %s\n" ${kernel_md5} >> $setenv_script
+
+	printf "rootfs_start_addr 0x%08x\n" $((flash_base + rootfs_offset)) >> $setenv_script
+	printf "rootfs_size 0x%08x\n" ${rootfs_size} >> $setenv_script
+	printf "rootfs_checksum %s\n" ${rootfs_md5} >> $setenv_script
+
+	# store u-boot-env
+	mkdir -p /var/lock
+	fw_setenv -s $setenv_script || {
+		echo 'failed to update U-Boot environment'
+		exit 1
+	}
+
+	# sysupgrade
+	sleep 2
+	sync
+	echo 3 > /proc/sys/vm/drop_caches
+	$IMAGE_CMD $KERNEL_FILE | mtd $MTD_ARGS write - ${KERNEL_PART:-kernel}
+	sleep 2
+	sync
+	if [ -n "$UPGRADE_BACKUP" ]; then
+		$IMAGE_CMD $ROOTFS_FILE | mtd $MTD_ARGS $MTD_CONFIG_ARGS -j $UPGRADE_BACKUP write - ${ROOTFS_PART:-rootfs}
+	else
+		$IMAGE_CMD $ROOTFS_FILE | mtd $MTD_ARGS write - ${ROOTFS_PART:-rootfs}
+	fi
+}
diff --git a/target/linux/ath79/generic/base-files/lib/upgrade/platform.sh b/target/linux/ath79/generic/base-files/lib/upgrade/platform.sh
index 575761d079..19699332fc 100644
--- a/target/linux/ath79/generic/base-files/lib/upgrade/platform.sh
+++ b/target/linux/ath79/generic/base-files/lib/upgrade/platform.sh
@@ -47,6 +47,20 @@ platform_do_upgrade() {
 	adtran,bsap1840)
 		redboot_fis_do_upgrade "$1" vmlinux_2
 		;;
+	engenius,eap1200h|\
+	engenius,eap300-v2|\
+	engenius,eap600|\
+	engenius,ecb600|\
+	engenius,ens202ext-v1|\
+	engenius,enstationac-v1)
+		IMAGE_LIST="tar tzf $1"
+		IMAGE_CMD="tar xzOf $1"
+		KERNEL_PART="loader"
+		ROOTFS_PART="fwconcat0"
+		KERNEL_FILE="uImage-lzma.bin"
+		ROOTFS_FILE="root.squashfs"
+		platform_do_upgrade_failsafe_datachk "$1"
+		;;
 	jjplus,ja76pf2)
 		redboot_fis_do_upgrade "$1" linux
 		;;
diff --git a/target/linux/ath79/image/common-senao.mk b/target/linux/ath79/image/common-senao.mk
index 9b5903d8e7..6784cf9aae 100644
--- a/target/linux/ath79/image/common-senao.mk
+++ b/target/linux/ath79/image/common-senao.mk
@@ -36,4 +36,5 @@ define Device/senao_loader_okli
   IMAGES += factory.bin
   IMAGE/factory.bin := append-kernel | pad-to $$$$(BLOCKSIZE) | append-rootfs | pad-rootfs | \
 	check-size | senao-tar-gz $$$$(SENAO_IMGNAME)
+  IMAGE/sysupgrade.bin := $$(IMAGE/factory.bin) | append-metadata
 endef
diff --git a/target/linux/ath79/tiny/base-files/lib/upgrade/failsafe_datachk.sh b/target/linux/ath79/tiny/base-files/lib/upgrade/failsafe_datachk.sh
new file mode 100644
index 0000000000..de84233de1
--- /dev/null
+++ b/target/linux/ath79/tiny/base-files/lib/upgrade/failsafe_datachk.sh
@@ -0,0 +1,64 @@
+# U-Boot with the datachk patchset requires image sizes, offsets,
+# and checksums to be provided in the U-Boot environment.
+# This script is based on the dualboot version for devices that come with 2 OS partitions.
+# For Senao boards with a "failsafe" partition image, the process is almost the same.
+# Instead of booting a secondary instalation on checksum failure,
+# the failsafe image is booted instead.
+# These boards also use the OKLI lzma kernel loader and mtd-concat
+# So the kernel check is for the loader, the rootfs check is for kernel + rootfs
+
+platform_do_upgrade_failsafe_datachk() {
+	local setenv_script="/tmp/fw_env_upgrade"
+
+	local flash_base=0x9f000000
+
+	local kernel_mtd=$(find_mtd_index ${KERNEL_PART:-kernel})
+	local rootfs_mtd=$(find_mtd_index ${ROOTFS_PART:-rootfs})
+
+	local kernel_offset=$(cat /sys/class/mtd/mtd${kernel_mtd}/offset)
+	local rootfs_offset=$(cat /sys/class/mtd/mtd${rootfs_mtd}/offset)
+
+	if [ -n "$IMAGE_LIST" ]; then
+		KERNEL_FILE=$($IMAGE_LIST | grep $KERNEL_FILE)
+		ROOTFS_FILE=$($IMAGE_LIST | grep $ROOTFS_FILE)
+	fi
+
+	local kernel_size=$($IMAGE_CMD $KERNEL_FILE | wc -c)
+	local rootfs_size=$($IMAGE_CMD $ROOTFS_FILE | wc -c)
+
+	# rootfs without JFFS2
+	local rootfs_blocks=$((rootfs_size / 4096))
+	rootfs_size=$((rootfs_blocks * 4096))
+
+	local kernel_md5=$($IMAGE_CMD $KERNEL_FILE | md5sum | cut -d ' ' -f1)
+	local rootfs_md5=$($IMAGE_CMD $ROOTFS_FILE | dd bs=4k count=$rootfs_blocks iflag=fullblock | md5sum | cut -d ' ' -f1)
+
+	# prepare new u-boot-env vars
+	printf "vmlinux_start_addr 0x%08x\n" $((flash_base + kernel_offset)) >> $setenv_script
+	printf "vmlinux_size 0x%08x\n" ${kernel_size} >> $setenv_script
+	printf "vmlinux_checksum %s\n" ${kernel_md5} >> $setenv_script
+
+	printf "rootfs_start_addr 0x%08x\n" $((flash_base + rootfs_offset)) >> $setenv_script
+	printf "rootfs_size 0x%08x\n" ${rootfs_size} >> $setenv_script
+	printf "rootfs_checksum %s\n" ${rootfs_md5} >> $setenv_script
+
+	# store u-boot-env
+	mkdir -p /var/lock
+	fw_setenv -s $setenv_script || {
+		echo 'failed to update U-Boot environment'
+		exit 1
+	}
+
+	# sysupgrade
+	sleep 2
+	sync
+	echo 3 > /proc/sys/vm/drop_caches
+	$IMAGE_CMD $KERNEL_FILE | mtd $MTD_ARGS write - ${KERNEL_PART:-kernel}
+	sleep 2
+	sync
+	if [ -n "$UPGRADE_BACKUP" ]; then
+		$IMAGE_CMD $ROOTFS_FILE | mtd $MTD_ARGS $MTD_CONFIG_ARGS -j $UPGRADE_BACKUP write - ${ROOTFS_PART:-rootfs}
+	else
+		$IMAGE_CMD $ROOTFS_FILE | mtd $MTD_ARGS write - ${ROOTFS_PART:-rootfs}
+	fi
+}
diff --git a/target/linux/ath79/tiny/base-files/lib/upgrade/platform.sh b/target/linux/ath79/tiny/base-files/lib/upgrade/platform.sh
index b02ab9a080..6d05b88d45 100644
--- a/target/linux/ath79/tiny/base-files/lib/upgrade/platform.sh
+++ b/target/linux/ath79/tiny/base-files/lib/upgrade/platform.sh
@@ -5,6 +5,9 @@
 PART_NAME=firmware
 REQUIRE_IMAGE_METADATA=1
 
+RAMFS_COPY_BIN='fw_setenv'
+RAMFS_COPY_DATA='/etc/fw_env.config'
+
 platform_check_image() {
 	return 0
 }
@@ -13,6 +16,17 @@ platform_do_upgrade() {
 	local board=$(board_name)
 
 	case "$board" in
+	engenius,eap350-v1|\
+	engenius,ecb350-v1|\
+	engenius,enh202-v1)
+		IMAGE_LIST="tar tzf $1"
+		IMAGE_CMD="tar xzOf $1"
+		KERNEL_PART="loader"
+		ROOTFS_PART="fwconcat0"
+		KERNEL_FILE="uImage-lzma.bin"
+		ROOTFS_FILE="root.squashfs"
+		platform_do_upgrade_failsafe_datachk "$1"
+		;;
 	*)
 		default_do_upgrade "$1"
 		;;



More information about the lede-commits mailing list