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 <pepe2k@gmail.com>
This commit is contained in:
Piotr Dymacz
2022-11-04 22:48:01 +01:00
committed by John Crispin
parent b89ba787fe
commit 08e976af26
3 changed files with 126 additions and 1 deletions

View File

@@ -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
}

View File

@@ -63,6 +63,9 @@ boot() {
PART_NAME=rootfs_1
fi
;;
yuncore,ax840)
PART_NAME=rootfs_1
;;
*)
return 1
;;

View File

@@ -0,0 +1,116 @@
From 793e3c02cd7ce6392913031b1f546923d4277f50 Mon Sep 17 00:00:00 2001
From: Piotr Dymacz <pepe2k@gmail.com>
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 <pepe2k@gmail.com>
---
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