Senao boards: How to force factory reset during/after a factory.bin flash

Hi all,

Alternative title: How to disable config restore after flash

I have a very unique situation with the board I have been porting to ath79. It is the ENS202EXT. The OEM software is actually a modified version of Openwrt Kamikaze. The factory.bin is designed to be accepted by either the OEM firmware upgrade, or the by OEM failsafe image. However, the process of flashing factory.bin is actually a "sysupgrade" of the old Openwrt, and it does not erase or overwrite the rootfs_data partition with the configuration, but rather saves it.

While flashing ath79 image from master branch, at some point in the kernel log you see
- config restore -
and a quick look at /etc/config folder (on UART, since network is down) shows all the ancient garbage config from the OEM version of Openwrt Kamikaze. For example this is the network config...

And this is what it should be (after factory reset)

So far I thought of two possible approaches

  1. in the makefile, add padding that would overwrite rootfs_data somehow
  2. a startup script for init.d that will run firstboot, destroy itself, and then reboot

I prefer option 1 or similar as this step of factory reset after flash is necessary for anyone wanting to put Openwrt on this board. To me, the ideal solution is some kernel option that will do this automatically on first boot after flash, but I don't know if that's possible.

This is an outdoor router and I have a couple of them up in trees and I prefer resetting them without the reset button :smiley:

are uboot variables/env available?

Divide the problem to two different things.

You cant change the OEM flash routine. It will likely include the OEM config on OEM sysupgrade in any case. Openwrt will then use that data when found after boot.

But you can sysupgrade from openwrt again and tell it to "not keep settings". That should cause openwrt defaults to be applied.

Yes, although I have experienced them being reset/erased with the OEM bootloader

For reasons you can read about in the pull request (kernel size), flash layout had to be changed drastically. It's not possible to sysupgrade from ar71xx kernel. Also I have not been able to sysupgrade to same version or same kernel version (if snapshot from master).

Ideally I would like the board to reset itself, otherwise I would have to reset it before being able to sysupgrade

bump

Also @rogerpueyo I am curious if you ever experienced this

@tmomas I know i said "very unique" but you never know, this might end up being useful for other boards as well

  IMAGE/factory.bin := append-squashfs-fakeroot-be | pad-to $$$$(BLOCKSIZE) | \
	append-kernel | pad-to $$$$(BLOCKSIZE) | append-rootfs | pad-rootfs | \
	check-size | engenius_ens202ext-factory

I would try the method 1 first, the padding one.
I don't know pad-rootfs does have an size argument or not, but you could try to pad to IMAGE_SIZE before check-size.
Please note that I don't know how many $ sign you have to use to get pad-to $$$$$$$$IMAGE_SIZE work. :smiley:

It would be $$(IMAGE_SIZE) since it is defined in the same makefile.

I also thought this would be the simplest method to work, unfortunately it doesn't for some reason.

...
[    3.817454] init: - preinit -
[    4.984442] random: jshn: uninitialized urandom read (4 bytes read)
[    5.142587] random: jshn: uninitialized urandom read (4 bytes read)
[    5.339774] random: jshn: uninitialized urandom read (4 byte
[    6.156928] eth0: link up (1000Mbps/Full duplex)
[    6.168512] IPv6: ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready
[    6.180551] IPv6: ADDRCONF(NETDEV_CHANGE): eth0.1: link becomes ready
Press the [f] key and hit [enter] to enter failsafe mode
Press the [1], [2], [3] or [4] key and hit [enter] to select the debug level
[    6.244677] urandom_read: 4 callbacks suppressed
[    6.244686] random: procd: uninitialized urandom read (4 bytes read)
[   10.542417] jffs2_scan_eraseblock(): End of filesystem marker found at 0x10000
[   10.549807] jffs2_build_filesystem(): unlocking the mtd device...
[   10.549814] done.
[   10.558051] jffs2_build_filesystem(): erasing all blocks after the end marker...
[   45.323570] done.
[   45.333190] jffs2: notice: (545) jffs2_build_xattr_subsystem: complete building xattr subsystem, 0 of xdatum (0 unchecked, 0 orphan) and 0 of xref (0 dead, 0 orphan) found.
[   45.350438] mount_root: overlay filesystem has not been fully initialized yet
[   45.365125] mount_root: switching to jffs2 overlay
[   45.396614] overlayfs: upper fs does not support tmpfile.
- config restore -
[   45.885071] urandom-seed: Seed file not found (/etc/urandom.seed)
[   46.002811] eth0: link down
[   46.030753] procd: - early -
[   46.033977] procd: - watchdog -
[   46.702522] procd: - watchdog -
[   46.706171] procd: - ubus -
[   46.804637] random: ubusd: uninitialized urandom read (4 bytes read)
[   46.812638] random: ubusd: uninitialized urandom read (4 bytes read)
[   46.824488] procd: - init -
Please press Enter to activate this console.
[   47.745591] kmodloader: loading kernel modules from /etc/modules.d/*
...

I did make sure it came out right. Image size is expected to be 12032k

total 40164
    4 drwxr-xr-x  3 pi pi     4096 Jun 23 16:20 .
    4 drwxr-xr-x 37 pi pi     4096 Jun 24 22:07 ..
    4 -rw-r--r--  1 pi pi     1764 Jun 24 20:35 config.buildinfo
    4 -rw-r--r--  1 pi pi      263 Jun 24 20:35 feeds.buildinfo
 5140 -rw-r--r--  1 pi pi  5262260 Jun 24 20:35 openwrt-ath79-generic-engenius_ens202ext-initramfs-kernel.bin
    4 -rw-r--r--  1 pi pi     3661 Jun 24 20:35 openwrt-ath79-generic-engenius_ens202ext.manifest
12040 -rw-r--r--  1 pi pi 12328960 Jun 24 20:35 openwrt-ath79-generic-engenius_ens202ext-squashfs-factory
 5408 -rw-r--r--  1 pi pi  5537062 Jun 24 20:35 openwrt-ath79-generic-engenius_ens202ext-squashfs-factory.bin
 5508 -rw-r--r--  1 pi pi  5636883 Jun 24 20:35 openwrt-ath79-generic-engenius_ens202ext-squashfs-sysupgrade.bin
12032 -rw-r--r--  1 pi pi 12320768 Jun 23 16:20 openwrt-senao-ens202ext-root.squashfs
    4 -rw-r--r--  1 pi pi     3329 Jun 23 16:20 openwrt-senao-ens202ext-uImage-lzma.bin
    4 drwxr-xr-x  2 pi pi     4096 Jun 24 20:35 packages
    4 -rw-r--r--  1 pi pi      752 Jun 24 20:35 sha256sums
    4 -rw-r--r--  1 pi pi       22 Jun 24 20:35 version.buildinfo

How about creating such a factory.bin which already have an empry config inside it, and the appended config by the OEM hopefully got ignored? :upside_down_face:

Hmmm ... looks like the self-destruct OEM config cleaner is more roboust than the sysupgrade hack above. :thinking:

Unpackaging the OEM image for flashing reveals a file before-upgrade.sh

After looking around in the files on the OEM image from UART...

found the file /etc/fwupgrade.sh

In there you can see how it can accept a script, and also why the padding doesn't work

before_local="/etc/before-upgradelocal.sh"
after_local="/etc/after-upgradelocal.sh"
before="before-upgrade.sh"
after="after-upgrade.sh"
...
...
...
[ -f "${before}" ] && chmod a+x "${before}" && . "${before}"
...
...
...
mtd -j "/tmp/_sys/sysupgrade.tgz" write "${rootfs}" "rootfs"

the mtd option is very interesting...and frustrating in this situation

root@ENS202EXT:/# mtd

Usage: mtd [<options> ...] <command> [<arguments> ...] <device>[:<device>...]

The device is in the format of mtdX (eg: mtd4) or its label.
mtd recognizes these commands:
        unlock                  unlock the device
        refresh                 refresh mtd partition
        erase                   erase all data on device
        write <imagefile>|-     write <imagefile> (use - for stdin) to device
        jffs2write <file>       append <file> to the jffs2 partition on the device
Following options are available:
        -q                      quiet mode (once: no [w] on writing,
                                           twice: no status messages)
        -r                      reboot after successful command
        -f                      force write without trx checks
        -e <device>             erase <device> before executing the command
        -d <name>               directory for jffs2write, defaults to "tmp"
        -j <name>               integrate <file> into jffs2 data when writing an image

Example: To write linux.trx to mtd4 labeled as linux and reboot afterwards
         mtd -r write linux.trx linux

My solution for this board in particular, would be to make that file empty before the mtd write occurs. There might be other ways to get it done right...

Still, I would like to see a generic solution, like some way to detect whether the flash was factory or not, and to have the newly flashed Openwrt reset itself. That might also help in other situations where rootfs might become corrupted somehow...

Inspecting that fwupgrade.sh ... are you talkink about emptying that /tmp/_sys/sysupgrade.tgz?
Because I think hooking into $before or $after is a great way of hijacking the upgrade process. :smiley:

In the before-upgrade.sh I would overwrite that sysupgrade.tgz with an empty tar.gz archive.
The other way, in after-upgrade.sh I would just call mtd write "${rootfs}" "rootfs" - to write the roots image without that sysupgrade file to the flash again.

Thoughts?

This is what I have so far for before-upgrade.sh and its working. I suppose using find like this is overkill

#!/bin/sh
for file in `find / | grep sysupgrade.tgz`;
do rm -rf $file; touch $file; done
1 Like

It is! :smiley:

How about just a ...:

#!/bin/sh
cat /dev/null > /tmp/_sys/sysupgrade.tgz

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.