diff mbox series

[OpenWrt-Devel,RFC] sysupgrade: Cross-flashing NOR/NAND proof of concept

Message ID 20190612004208.26914-1-lede@allycomm.com
State Superseded
Headers show
Series [OpenWrt-Devel,RFC] sysupgrade: Cross-flashing NOR/NAND proof of concept | expand

Commit Message

Jeff Kletsky June 12, 2019, 12:42 a.m. UTC
From: Jeff Kletsky <git-commits@allycomm.com>

Certain devices can have both NOR- and NAND-resident firmware, such as
the GL.iNet GL-AR300M. These devices can be booted with either firmware.
The GL-AR300M boot loader will automatically fail-over to NOR firmware
after three failed boots, providing end-user benefits when bad flashes
or other "no boot" situations occur.

THIS IS A PROOF OF CONCEPT

The "tricks" are that:

  * The kernel and software for both the NOR- and NAND-resident
    variants need to be able to read/write raw MTD as well as UBI.

  * The existing sysupgrade paths already prevent flashing of a
    NOR-intended image onto a NAND-based device, as well as the other
    way around. As such, even if a approach like this is accepted
    after these board names are "in the wild", sysupgrade will be
    "safe" on "old" builds against future additions to SUPPORTED_DEVICES.

  * The MTD partitioning for both variants need to define both NOR and
    NAND partitioning in a way that:

      * Early init does not try to mount the "wrong" root file system

      * sysupgrade can locate the "other" partitions

    This was accomplished in the commit sequence for the GL-AR300M
    (linked below) by defining the partitions in a common DTSI with a
    "neutered" partition label, prefixing it with nor_ or nand_, then
    setting the label as appropriate within the DTS for the specific
    build.

It can be used with buildable code for the GL.iNet AR300M that is
being prepared for submission and is presently available at

  https://github.com/jeffsf/openwrt/tree/ath79-nand-2019-06-11

or the latest, similarly named branch. Note that the above code has
not implemented SUPPORTED_DEVICES to allow cross-flashing, so that
sysupgrade -F will be required for those cases (at this time).

It intentionally does *not* switch to the flashed partition at this time.

Past removing my comments/notes in the source, I'd be interesting in
finding out if there are cases that I haven't thought of.

Run-tested-on: GL.iNet AR300M

Signed-off-by: Jeff Kletsky <git-commits@allycomm.com>
---
 .../ath79/base-files/lib/upgrade/platform.sh  | 65 +++++++++++++++++++
 1 file changed, 65 insertions(+)

Comments

Chuanhong Guo June 12, 2019, 9:29 a.m. UTC | #1
Hi!

On Wed, Jun 12, 2019 at 8:42 AM Jeff Kletsky <lede@allycomm.com> wrote:
>
> From: Jeff Kletsky <git-commits@allycomm.com>
>   * The kernel and software for both the NOR- and NAND-resident
>     variants need to be able to read/write raw MTD as well as UBI.
>
>   * The existing sysupgrade paths already prevent flashing of a
>     NOR-intended image onto a NAND-based device, as well as the other
>     way around. As such, even if a approach like this is accepted
>     after these board names are "in the wild", sysupgrade will be
>     "safe" on "old" builds against future additions to SUPPORTED_DEVICES.

Why would someone do such a cross-flashing at the first place?
If you want to recover the firmware in SPI NAND with a firmware in SPI
NOR, You could just flash a initramfs image of the NAND variant into
NOR flash. (And vice versa)

>
>   * The MTD partitioning for both variants need to define both NOR and
>     NAND partitioning

GL-AR300M has an NOR-only variant and by adding SPI NAND node into the
NOR variant you'll add some unnecessary error messages into kernel
log.

Regards,
Chuanhong Guo
diff mbox series

Patch

diff --git a/target/linux/ath79/base-files/lib/upgrade/platform.sh b/target/linux/ath79/base-files/lib/upgrade/platform.sh
index b6f720fd0a..110d459b27 100644
--- a/target/linux/ath79/base-files/lib/upgrade/platform.sh
+++ b/target/linux/ath79/base-files/lib/upgrade/platform.sh
@@ -32,6 +32,67 @@  redboot_fis_do_upgrade() {
 	fi
 }
 
+nand_nor_do_upgrade() {
+	local upgrade_file="$1"
+
+	local magic
+	local found_nor_part
+
+	# If here, the metadata check has already passed (or --force)
+	# ath79:nand so far only uses uImage and tar files
+
+	magic=$(get_magic_long "$upgrade_file")
+	case "$magic" in
+
+	"27051956")	#define IH_MAGIC 0x27051956 /* [U-Boot] Image Magic Number */
+
+		found_nor_part="Not yet"
+		for pn in "$PART_NAME" "nor_${PART_NAME}" ; do		# firmware
+
+			if [ "$(find_mtd_index "$pn")" ] ; then
+				PART_NAME="$pn"
+				found_nor_part=''
+				>&2 printf "Running NOR upgrade\n"
+				default_do_upgrade "$upgrade_file"
+			fi
+		done
+		if [ -n "$found_nor_part" ] ; then
+			>&2 printf "ERROR: UPGRADE FAILED: Unable to locate '$PART_NAME' or 'nor_${PART_NAME}'\n"
+			sleep 5
+			exit 1
+		fi
+		;;
+
+
+	*)	# has to be a tar file of some sort
+
+		for pn in "$CI_KERNPART" "nand_${CI_KERNPART}" ; do	# kernel
+
+			if [ "$(find_mtd_index "$pn")" ] ; then
+				CI_KERNPART="$pn"
+				break
+			fi
+		done
+		for pn in "$CI_UBIPART" "nand_${CI_UBIPART}" ; do	# ubi
+
+			if [ "$(find_mtd_index "$pn")" ] ; then
+				CI_UBIPART="$pn"
+				break
+			fi
+		done
+		for pn in "$CI_ROOTPART" "nand_${CI_ROOTPART}" ; do	#rootfs
+
+			if [ "$(find_mtd_index "$pn")" ] ; then
+				CI_ROOTPART="$pn"
+				break
+			fi
+		done
+		>&2 printf "Running NAND upgrade\n"
+		nand_upgrade_tar "$upgrade_file"
+		;;
+	esac
+}
+
 platform_check_image() {
 	return 0
 }
@@ -47,6 +108,10 @@  platform_do_upgrade() {
 	ubnt,routerstation-pro)
 		redboot_fis_do_upgrade "$ARGV" kernel
 		;;
+	glinet,gl-ar300m-nand |\
+	glinet,gl-ar300m-nor)
+		nand_nor_do_upgrade "$ARGV"
+		;;
 	*-nand)
 		nand_do_upgrade "$ARGV"
 		;;