From 08e976af26c96056900a1ceb9e2829c4735ddb4c Mon Sep 17 00:00:00 2001 From: Piotr Dymacz Date: Fri, 4 Nov 2022 22:48:01 +0100 Subject: [PATCH] ipq807x: include support for dual-image in YunCore AX840 This adds support for dual-image ('rootfs' partitions rotation), for the YunCore AX840 board. Implementation details are included in the 'base-files' patch this commit adds: 0060-base-files-minimal-support-for-QCA-runtime-failsafe.patch Fixes: WIFI-12537 Signed-off-by: Piotr Dymacz --- .../base-files/lib/upgrade/platform.sh | 8 +- .../files/etc/init.d/certificates | 3 + ...mal-support-for-QCA-runtime-failsafe.patch | 116 ++++++++++++++++++ 3 files changed, 126 insertions(+), 1 deletion(-) create mode 100644 patches/base/0060-base-files-minimal-support-for-QCA-runtime-failsafe.patch diff --git a/feeds/ipq807x/ipq807x/base-files/lib/upgrade/platform.sh b/feeds/ipq807x/ipq807x/base-files/lib/upgrade/platform.sh index 2d31643ff..32393db74 100755 --- a/feeds/ipq807x/ipq807x/base-files/lib/upgrade/platform.sh +++ b/feeds/ipq807x/ipq807x/base-files/lib/upgrade/platform.sh @@ -160,7 +160,6 @@ platform_do_upgrade() { qcom,ipq5018-mp03.3|\ wallys,dr6018|\ wallys,dr6018-v4|\ - yuncore,ax840|\ yuncore,fap650|\ tplink,ex447|\ tplink,ex227|\ @@ -212,5 +211,12 @@ platform_do_upgrade() { PART_NAME="inactive" platform_do_upgrade_dualboot_datachk "$1" ;; + yuncore,ax840) + [ -f /proc/boot_info/rootfs/upgradepartition ] && { + CI_UBIPART="$(cat /proc/boot_info/rootfs/upgradepartition)" + CI_BOOTCFG=1 + } + nand_upgrade_tar "$1" + ;; esac } diff --git a/feeds/tip/certificates/files/etc/init.d/certificates b/feeds/tip/certificates/files/etc/init.d/certificates index 3d2cc617a..a627c8e87 100755 --- a/feeds/tip/certificates/files/etc/init.d/certificates +++ b/feeds/tip/certificates/files/etc/init.d/certificates @@ -63,6 +63,9 @@ boot() { PART_NAME=rootfs_1 fi ;; + yuncore,ax840) + PART_NAME=rootfs_1 + ;; *) return 1 ;; diff --git a/patches/base/0060-base-files-minimal-support-for-QCA-runtime-failsafe.patch b/patches/base/0060-base-files-minimal-support-for-QCA-runtime-failsafe.patch new file mode 100644 index 000000000..6785aeb82 --- /dev/null +++ b/patches/base/0060-base-files-minimal-support-for-QCA-runtime-failsafe.patch @@ -0,0 +1,116 @@ +From 793e3c02cd7ce6392913031b1f546923d4277f50 Mon Sep 17 00:00:00 2001 +From: Piotr Dymacz +Date: Sun, 6 Nov 2022 10:22:42 +0100 +Subject: [PATCH] base-files: minimal support for QCA runtime failsafe upgrade + +During research, when working on support for YunCore AX840 board it was +found that this vendor decided to use Qualcomm-made, so called 'runtime +failsafe' based upgrades from QSDK (see e.g. [1] and [2]). + +It turned out that vendor firmware makes use of dual-image feature +controlled by SBL (not only by U-Boot as usual). This mode allows to +switch between two copies of firmware in case of a failed upgrade and +works not only with kernel/rootfs but apparently, also with other parts +of the firmware, like APPS (U-Boot), Wi-Fi (ath11k) firmware, etc. +Here, we will focus only on the firmware (in our case, UBI on NAND). + +Two, equal in size, UBI partitions are used: the 'rootfs' is always the +active one (for booting) and 'rootfs_1' is used for storing new firmware +during the regular 'sysupgrade'. Partition names are swapped, probably +by the 'SBL' (closed-source, second level bootloader), based on layout +in 'MIBIB' and content of 'BOOTCONFIG'/'BOOTCONFIG1' partitions (the +second one seems to be only a backup, as mentioned in related kernel +driver) and then provided by 'SMEM' to U-Boot and kernel. For example: + +- when primary 'rootfs' partition is #0: + 0x000000000000-0x000003c00000 : "rootfs" (used for booting) + 0x000003c00000-0x000007800000 : "rootfs_1" + +- when primary 'rootfs' partition is #1: + 0x000000000000-0x000003c00000 : "rootfs_1" + 0x000003c00000-0x000007800000 : "rootfs" (used for booting) + +The whole solution requires support in several other places, including +kernel (detecting crash) and U-Boot (partition swap) but this requires +more research and apparently, YunCore doesn't even use all of that in a +proper way, resulting only in a rotation of firmware partitions during +upgrade (without the part responsible for reverting in case of fail +during the upgrade). + +This patch adds only a small part of the solution, making 'dual-image' +feature kind of working, resulting in rotation between 'rootfs' and +'rootfs_1' partitions (areas on NAND) between subsequent updates. This +requires also 'CONFIG_BOOTCONFIG_PARTITION' support in the kernel and +in simple terms, works as follows: + +1. Get name of target 'rootfs' partition for upgrade from: + '/proc/boot_info/rootfs/upgradepartition' + +2. Perform upgrade and in case of success change 'primaryboot' flag + (1 -> 0, 0 -> 1) for 'rootfs' partition in 'BOOTCONFIG' + +3. Write back updated 'BOOTCONFIG' content to flash: + from '/proc/boot_info/getbinary_bootconfig' to mtd partitions + ('0:BOOTCONFIG' and '0:BOOTCONFIG1') + +This topic definitely requires additional research if a proper solution +(kernel crash and/or failed upgrade detection) is needed so more changes +might come in future. + +[1] https://git.codelinaro.org/clo/qsdk/oss/kernel/linux-ipq-5.4/-/commit/67225a559ca8e61e87c36a1c9940a085b3950c97 +[2] https://git.codelinaro.org/clo/qsdk/oss/system/openwrt_repo/-/blob/NHSS.QSDK.12.1.5.r2/target/linux/ipq60xx/base-files/lib/upgrade/platform.sh#L175 + +Signed-off-by: Piotr Dymacz +--- + package/base-files/files/lib/upgrade/nand.sh | 25 ++++++++++++++++++++ + 1 file changed, 25 insertions(+) + +diff --git a/package/base-files/files/lib/upgrade/nand.sh b/package/base-files/files/lib/upgrade/nand.sh +index ab3db4cdf2..349d287841 100644 +--- a/package/base-files/files/lib/upgrade/nand.sh ++++ b/package/base-files/files/lib/upgrade/nand.sh +@@ -15,6 +15,9 @@ CI_ROOTPART="${CI_ROOTPART:-rootfs}" + # ipq807x qsdk kernel misbehaves + CI_IPQ807X=0 + ++# update BOOTCONFIG partitions (rotate rootfs/rootfs_1) ++CI_BOOTCFG=0 ++ + ubi_mknod() { + local dir="$1" + local dev="/dev/$(basename $dir)" +@@ -216,9 +219,31 @@ nand_upgrade_prepare_ubi() { + return 0 + } + ++nand_qca_update_bootconfig() { ++ local primary="0" ++ local mtdnum ++ local part ++ ++ [ -f /proc/boot_info/rootfs/primaryboot ] || return ++ [ -f /proc/boot_info/getbinary_bootconfig ] || return ++ ++ [ "$(cat /proc/boot_info/rootfs/primaryboot)" = "0" ] && primary="1" ++ echo "$primary" > /proc/boot_info/rootfs/primaryboot 2>/dev/null ++ ++ for part in "0:BOOTCONFIG" "0:BOOTCONFIG1"; do ++ mtdnum="$(find_mtd_index "$part")" ++ [ -c "/dev/mtd${mtdnum}" ] && { ++ mtd -qq write /proc/boot_info/getbinary_bootconfig \ ++ "/dev/mtd${mtdnum}" 2>/dev/null &&\ ++ echo "partition '$part' updated" ++ } ++ done ++} ++ + nand_do_upgrade_success() { + local conf_tar="/tmp/sysupgrade.tgz" + sync ++ [ "$CI_BOOTCFG" = 1 ] && nand_qca_update_bootconfig + [ -f "$conf_tar" ] && nand_restore_config "$conf_tar" + echo "sysupgrade successful" + umount -a +-- +2.38.1 +