Script: Mount "Alternate" NAND Firmware (Linksys +?)

Working on a new NAND device, I find myself wanting to get changes from one firmware install to the other, or edit the other when it is crashing. The following works on my EA8300 and might be useful for others. Modify the MTD partitions as appropriate, perhaps a couple other things. Hopefully it will save you some time of figuring out the various steps in mounting them.

The ROM will appear at /alt/rom
The overlay itself at /alt/overlay
Combined (and writable) at /alt/firmware

#!/bin/sh

if [ "$( cat /sys/devices/virtual/ubi/ubi0/mtd_num )" = "11" ] ; then
	altpart=13
else
	altpart=11
fi

mkdir -p /alt/rom
mkdir -p /alt/overlay
mkdir -p /alt/firmware

ubiattach -m ${altpart}

ubiblock --create /dev/ubi1_0
mount -t squashfs -o ro /dev/ubiblock1_0 /alt/rom

mount -t ubifs /dev/ubi1_1 /alt/overlay

mount -t overlay overlay -o noatime,lowerdir=/alt/rom,upperdir=/alt/overlay/upper,workdir=/alt/overlay/work /alt/firmware
6 Likes

I have been trying to do the same for the WRT3200ACM, but this seems to be out of my abilities... could you please give me a tip about how to proceed?

This is the MTD map for my device:

dev:    size   erasesize  name
mtd0: 00200000 00020000 "u-boot"
mtd1: 00020000 00020000 "u_env"
mtd2: 00040000 00020000 "s_env"
mtd3: 00040000 00020000 "devinfo"
mtd4: 001e0000 00020000 "sysdiag"
mtd5: 05000000 00020000 "kernel1"
mtd6: 04a00000 00020000 "ubi"
mtd7: 05000000 00020000 "kernel2"
mtd8: 04a00000 00020000 "rootfs2"
mtd9: 05600000 00020000 "syscfg"
mtd10: 005c0000 00020000 "unused_area"

And these are the (current) relevant mount points:

ubi1:syscfg on /tmp/syscfg type ubifs (rw,relatime,ubi=1,vol=0)
/dev/ubi0_1 on /overlay type ubifs (rw,relatime,ubi=0,vol=1)

The value at "/sys/devices/virtual/ubi/ubi0/mtd_num" is "6"...

I also tried to execute "/usr/sbin/fw_printenv", but I do not know how to interpret the info:

CASset=max
MALLOC_len=5
MPmode=SMP
SMT-2D=NIFNG4702AB6X01
altFwSize=0x5000000
altKernAddr=0x5a00000
altKernSize=0x0600000
altnandboot=setenv bootargs console=ttyS0,115200 root=/dev/mtdblock8 ro rootdelay=1 rootfstype=jffs2 earlyprintk $mtdparts;nand read $defaultLoadAddr $altKernAddr $altKernSize; bootm $defaultLoadAddr
autoload=no
baudrate=115200
boot_order=hd_scr usb_scr mmc_scr hd_img usb_img mmc_img pxe net_img net_scr
boot_part_ready=3
bootargs_dflt=$console $nandEcc $mtdparts_lgcy $bootargs_root nfsroot=$serverip:$rootpath ip=$ipaddr:$serverip$bootargs_end $mvNetConfig video=dovefb:lcd0:$lcd0_params clcd.lcd0_enable=$lcd0_enable clcd.lcd_panel=$lcd_panel
bootargs_end=:10.4.50.254:255.255.255.0:Armada38x:eth0:none
bootargs_root=root=/dev/nfs rw
bootcmd_auto=stage_boot $boot_order
bootcmd_fdt=tftpboot 0x2000000 $image_name;tftpboot $fdtaddr $fdtfile;setenv bootargs $console $nandEcc $mtdparts $bootargs_root nfsroot=$serverip:$rootpath ip=$ipaddr:$serverip$bootargs_end $mvNetConfig video=dovefb:lcd0:$lcd0_params clcd.lcd0_enable=$lcd0_enable clcd.lcd_panel=$lcd_panel; bootz 0x2000000 - $fdtaddr;
bootcmd_fdt_boot=tftpboot 0x2000000 $image_name; setenv bootargs $console $nandEcc $mtdparts $bootargs_root nfsroot=$serverip:$rootpath ip=$ipaddr:$serverip$bootargs_end $mvNetConfig video=dovefb:lcd0:$lcd0_params clcd.lcd0_enable=$lcd0_enable clcd.lcd_panel=$lcd_panel; bootz 0x2000000 - $fdtaddr;
bootcmd_fdt_edit=tftpboot $fdtaddr $fdtfile; fdt addr $fdtaddr; setenv bootcmd $bootcmd_fdt_boot
bootcmd_lgcy=tftpboot 0x2000000 $image_name;setenv bootargs $console $nandEcc $mtdparts_lgcy $bootargs_root nfsroot=$serverip:$rootpath ip=$ipaddr:$serverip$bootargs_end  video=dovefb:lcd0:$lcd0_params clcd.lcd0_enable=$lcd0_enable clcd.lcd_panel=$lcd_panel;  bootm $loadaddr; 
bootdelay=3
cacheShare=no
console=console=ttyS0,115200
defaultLoadAddr=0x2000000
device_partition=0:1
disaMvPnp=no
eeeEnable=no
enaClockGating=no
enaCpuStream=no
enaFPU=yes
enaMonExt=no
enaWrAllo=no
eth1addr=00:50:43:00:02:01
eth1mtu=1500
eth2addr=00:50:43:00:00:01
eth2mtu=1500
eth3addr=00:50:43:02:00:00
eth3mtu=1500
ethact=egiga0
ethaddr=60:38:E0:BC:34:E0
ethmtu=1500
ethprime=egiga0
fdt_addr=2040000
fdt_skip_update=no
fdtaddr=0x1000000
fdtfile=armada-38x-modular.dtb
fileaddr=2000000
filesize=2740100
firmwareName=rango.img
flash_alt_image=tftpboot $defaultLoadAddr $firmwareName && nand erase $altKernAddr $altFwSize && nand write $defaultLoadAddr $altKernAddr $filesize
flash_pri_image=tftpboot $defaultLoadAddr $firmwareName && nand erase $priKernAddr $priFwSize && nand write $defaultLoadAddr $priKernAddr $filesize
ide_path=/
image_name=uImage
initrd_name=uInitrd
ipaddr=192.168.1.1
kernel_addr_r=2080000
lcd0_enable=0
lcd0_params=640x480-16@60
lcd_panel=0
limit_dram_size=yes
loadaddr=0x02000000
loads_echo=0
mtddevname=uboot
mtddevnum=0
mtdids=nand0=armada-nand
mtdparts=mtdparts=armada-nand:2048K(uboot)ro,128K(u_env),256K(s_env),256K@8064K(devinfo),1920K@8320K(sysdiag),80m@10m(kernel),74m@16m(rootfs),80m@90m(alt_kernel),74m@96m(alt_rootfs),160m@10m(ubifs),-@170m(syscfg)
mvNetConfig=mv_net_config=4,(00:50:43:11:11:11,0:1:2:3),mtu=1500
mv_pon_addr=00:50:43:01:00:00
nandEcc=nfcConfig=4bitecc
nandboot=setenv bootargs console=ttyS0,115200 root=/dev/mtdblock6 ro rootdelay=1 rootfstype=jffs2 earlyprintk $mtdparts;nand read $defaultLoadAddr $priKernAddr $priKernSize; bootm $defaultLoadAddr
netbsd_en=no
netmask=255.255.255.0
netretry=no
partition=nand0,0
pcieTune=no
pexMode=RC
priFwSize=0x5000000
priKernAddr=0x0a00000
priKernSize=0x0600000
pxe_files_load=:default.arm-armadaxp-db:default.arm-armadaxp:default.arm
pxefile_addr_r=3100000
ramdisk_addr_r=2880000
rootpath=/srv/nfs/
run_script=no
sata_delay_reset=0
sata_dma_mode=yes
script_addr_r=3000000
script_name=boot.scr
sd_detection_dat3=no
serverip=192.168.1.254
standalone=fsload 0x2000000 $image_name;setenv bootargs $console $nandEcc $mtdparts_lgcy root=/dev/mtdblock0 rw ip=$ipaddr:$serverip$bootargs_end; bootm 0x2000000;
stderr=serial
stdin=serial
stdout=serial
update_both_images=tftpboot $defaultLoadAddr $firmwareName && nand erase $priKernAddr $priFwSize && nand erase $altKernAddr $altFwSize && nand write $defaultLoadAddr $priKernAddr $filesize && nand write $defaultLoadAddr $altKernAddr $filesize
usb0Mode=host
usbActive=0
usbType=2
vxworks_en=no
yuk_ethaddr=00:00:00:EE:51:81
boot_part=1
bootcmd=run nandboot
auto_recovery=yes

Looks like the two file systems are in mtd6 and mtd8

helps confirm that and was a good thing to check.

I'd try, first cut

if [ "$( cat /sys/devices/virtual/ubi/ubi0/mtd_num )" = "6" ] ; then
	altpart=8
else
	altpart=6
fi


In the U-Boot environment, the nandboot and altnandboot variables are probably the ones that change which partition is booted in a production device. There is a lot of cruft in many environments that may have been left over from their development work. That those two variables include references to 6 and 8 seem consistent with the layout and your other observations.

1 Like

These are the UBI devices right after booting the device:

root@router:~# ls -l /dev/ubi*
crw-------    1 root     root      250,   0 Jan  1  1970 /dev/ubi0
crw-------    1 root     root      250,   1 Jan  1  1970 /dev/ubi0_0
crw-------    1 root     root      250,   2 Jan  1  1970 /dev/ubi0_1
crw-------    1 root     root      249,   0 Jan  1  1970 /dev/ubi1
crw-------    1 root     root      249,   1 Jan  1  1970 /dev/ubi1_0
crw-------    1 root     root       10,  59 Jan  1  1970 /dev/ubi_ctrl
brw-------    1 root     root      254,   0 Jan  1  1970 /dev/ubiblock0_0

Following your advice, I ran the "ubiattach -m 8" command, wich responded with "UBI device number 2, total 592 LEBs (75169792 bytes, 71.6 MiB), available 0 LEBs (0 bytes), LEB size 126976 bytes (124.0 KiB)". And now, I have the following UBI devices:

root@router:~# ls -l /dev/ubi*
crw-------    1 root     root      250,   0 Jan  1  1970 /dev/ubi0
crw-------    1 root     root      250,   1 Jan  1  1970 /dev/ubi0_0
crw-------    1 root     root      250,   2 Jan  1  1970 /dev/ubi0_1
crw-------    1 root     root      249,   0 Jan  1  1970 /dev/ubi1
crw-------    1 root     root      249,   1 Jan  1  1970 /dev/ubi1_0
crw-------    1 root     root      247,   0 Mar 27 23:40 /dev/ubi2
crw-------    1 root     root      247,   1 Mar 27 23:40 /dev/ubi2_0
crw-------    1 root     root      247,   2 Mar 27 23:40 /dev/ubi2_1
crw-------    1 root     root       10,  59 Jan  1  1970 /dev/ubi_ctrl
brw-------    1 root     root      254,   0 Jan  1  1970 /dev/ubiblock0_0

Now I create the ROM device and mount it:

root@router:~# ubiblock --create /dev/ubi2_0
root@router:~# ls -l /dev/ubi*
crw-------    1 root     root      250,   0 Jan  1  1970 /dev/ubi0
crw-------    1 root     root      250,   1 Jan  1  1970 /dev/ubi0_0
crw-------    1 root     root      250,   2 Jan  1  1970 /dev/ubi0_1
crw-------    1 root     root      249,   0 Jan  1  1970 /dev/ubi1
crw-------    1 root     root      249,   1 Jan  1  1970 /dev/ubi1_0
crw-------    1 root     root      247,   0 Mar 27 23:51 /dev/ubi2
crw-------    1 root     root      247,   1 Mar 27 23:51 /dev/ubi2_0
crw-------    1 root     root      247,   2 Mar 27 23:51 /dev/ubi2_1
crw-------    1 root     root       10,  59 Jan  1  1970 /dev/ubi_ctrl
brw-------    1 root     root      254,   0 Jan  1  1970 /dev/ubiblock0_0
brw-------    1 root     root      254,   1 Mar 27 23:51 /dev/ubiblock2_0
root@router:~# mount -t squashfs -o ro /dev/ubiblock2_0 mnt

And it effectively contains the ROM from my previous installation:

root@router:~# cat mnt/etc/banner
  _______                     ________        __
 |       |.-----.-----.-----.|  |  |  |.----.|  |_
 |   -   ||  _  |  -__|     ||  |  |  ||   _||   _|
 |_______||   __|_____|__|__||________||__|  |____|
          |__| W I R E L E S S   F R E E D O M
 -----------------------------------------------------
 OpenWrt 18.06.1, r7258-5eb055306f
 -----------------------------------------------------

So far so good... now lets go for the overlay:

root@router:~# umount mnt
root@router:~# mount -t ubifs /dev/ubi2_1 mnt
root@router:~# ls -l mnt/
drwxr-xr-x   11 root     root           736 Aug 21  2018 upper
drwxr-xr-x    3 root     root           224 Jan  1  1970 work

And, after inspecting it's contents, I can see that it is indeed my old overlay partition.

This is great news, now in case of a disastrous configuration, users could boot on the "alternate" partition, fix the configuration from there, then go back to the current "partition". Many thanks for your help!

3 Likes

@jeff @eduperez I wonder if you gentlemen can help.

This alternative partition mounting doesn't seem to work on Linksys EA7300v2 as described here: https://github.com/openwrt/luci/issues/4861

Actual mount command fails and I wonder if you can provide any insight on how to debug this.

1 Like

I do not know what can be happening, but I posted a message asking for more info.

Thanks for this. I have configured my primary "kernel" partition as I want it. I would like to back this up to alt_kernel before making changes, so I always have a "last good working copy". Is this the right way to do that? I don't really want to manually edit the alternate. Just use it for complete backup of firmware and current settings.