That worked nicely and reliably. On my new Linksys EA8500 router the MTD "partitions" (?) are set differently, and I can see neither "firmware" nor "linux". That leaves me with several questions:
What is the "mtd" way of flashing a Linksys EA8500?
If "sysupgrade" was to be used in this case, which "partition" would it flash?
Does "sysupgrade" rely on mtd at all? I was looking at that shell script, but could not find any references to "mtd".
mtd is a low-level flashing tool that could be directly used with the simplest old routers (like 1043) that had simple strucutre and unified kernel+rootfs image and no dual-booting.
With newer routers, with more complex flash structure, possibly dual-firmware features, and possible flashing kernel separately from the rootfs, using mtd directly is not possible.
There is none.
(or maybe: investigate the EA8500 sysupgrade steps, mimic them, and use mtd for those steps that it can do. And then do the other steps with other tools)
(kernel1 and rootfs1) or (kernel2 and rootfs2), depending which partition is active (1 or 2). And then it would toggle the active partition marker in u-boot-env etc.
For some routers, for the low-level flashing work. Depends on the target.
I had to bite the bullet and read the code... There is a shell script "/lib/upgrade/linksys.sh" which I think has the answer to my question. It turns out it checks the magic number of the image. If the magic number is "27051956", it performs an mtd flash of either "kernel1" or "kernel2" partition. If the image has the magic number of "73797375", then a more elaborate process takes place.
Any idea what "73797375" magic number represents? A google search returns nothing on this.
"sysu" = First 4 letters from the word "sysupgrade"...
Found at the beginning of the image, evaluated by /lib/upgrade/common.sh. Just a logic to see that it is a sysupgrade image.
If yes, then the nand_upgrade_tar routine in /lib/upgrade/nand.sh gets called to perform the actual upgrade (to write kernel and rootfs separately to the correct partitions, etc.). Note that the rootfs is ubifs formatted and needs to be written with ubifs tools.
Looking at the below function from linksys.sh, one part looks a little suspicious. "cur_boot_part" gets assigned a value, and that value is validated in the "if" statement. However, after the "if" statement, the value is reassigned again, this time without any checks. I am no shell scripting guru, but this does not look quite right to me.
linksys_get_target_firmware() {
local cur_boot_part mtd_ubi0
cur_boot_part=$(/usr/sbin/fw_printenv -n boot_part)
if [ -z "${cur_boot_part}" ] ; then
mtd_ubi0=$(cat /sys/devices/virtual/ubi/ubi0/mtd_num)
case $(egrep ^mtd${mtd_ubi0}: /proc/mtd | cut -d '"' -f 2) in
kernel1|rootfs1)
cur_boot_part=1
;;
kernel2|rootfs2)
cur_boot_part=2
;;
esac
>&2 printf "Current boot_part='%s' selected from ubi0/mtd_num='%s'" \
"${cur_boot_part}" "${mtd_ubi0}"
fi
cur_boot_part=`/usr/sbin/fw_printenv -n boot_part`
case $cur_boot_part in
1)
fw_setenv -s - <<-EOF
boot_part 2
auto_recovery yes
EOF
printf "kernel2"
return
;;
2)
fw_setenv -s - <<-EOF
boot_part 1
auto_recovery yes
EOF
printf "kernel1"
return
;;
*)
return
;;
esac
}