Success story: using reroot to upgrade MIPS online

Eugene Grosbein eugen at
Tue Feb 9 17:35:13 UTC 2016


Latest Quarterly Status Report
noted that "Root remount (reroot)" project is finished. I've tried to utilize it
to safely upgrade my MIPS32 TP-Link TL-WDR3600 running FreeBSD with new image online,
e.g. without console cable, and happy to report that it works flawlessly.

I've wrote simple script to perform upgrade.
Here is a transcript of such online upgrade session over telnet connection:

# upgrade
Verifying ftp://eugen@
Size: 7919104 bytes
Allocating 13443K for memory disk
Downloading ftp://eugen@
looking up
connecting to
setting passive mode
opening data connection
initiating transfer
remote size / mtime: 7919104 / 1455037602
newimage                                      100% of 7733 kB 4925 kBps 00m02s
Closing network connections and unmounting flash...
# Connection closed by foreign host.

If one has console cable connected (not required), here is what is written there:

Feb 10 00:07:56 tl-wdr3600 reroot: rerooted by user
Stopping inetd.
Shutting down local packages:.
Stopping cron.
Stopping sshd.
Writing entropy file:.
Writing early boot entropy file:/etc/rc.shutdown: WARNING: write failed (read-only fs?)
Trying to mount root from ufs:/dev/md2 []...
warning: no time-of-day clock registered, system time will not be set accurately

19+0 records in
19+0 records out
1245184 bytes transferred in 12.476816 secs (99800 bytes/sec)
101+1 records in
102+0 records out
6684672 bytWaiting (max 60 seconds) for system process `vnlru' to stop...done
Waiting (max 60 seconds) for system process `bufdaemon' to stop...done
Waiting (max 60 seconds) for system process `syncer' to stop...
Syncing disks, vnodes remaining...0 0 0 0 0 0 0 0 0 done
All buffers synced.
Uptime: 3m3s

Then the device performs full reboot starting with U-Boot loader running new kernel.

This first version works with some assumptions:

1. There is enough RAM free to download new image at once plus 20% of its size.
For example, it takes 11MB free RAM using 7.6MB new image for a device having 8MB flash.

2. Flash storage is partitioned with one or more partitions using GEOM_MAP feature
and GEOM_MAP correctly reports native flash block size as "stripesize", that is true for my device:

# geom map list
Geom name: flash/spi0
1. Name: map/u-boot
   Mediasize: 131072 (128K)
   Sectorsize: 512
   Stripesize: 65536

Flash block size is 65536 bytes in this case.

3. New image is accessible with FTP or HTTP(S) methods. Currently running image
has stock fetch(1) binary and kernel support for tmpfs(5) (required by reroot feature)
and md(4) (memory disk) support with mdconfig(8) binary to keep UFS file system
on memory disk that survives rerooting stage (no user tmpfs can survive it currently).

4. FTP/HTTP(S) server is capable to report image size without downloading so "fetch -s" works.
URL of image and login credentials are kept in the text file /etc/upgrade.conf"
using a format suitable for fetch(1), just like this:

FTP_PASSWORD='secret words'

Or, for HTTP:


hostname may be IP address or FQDN, if running system has working DNS resolver.
Refer to fetch(3) manual page for syntax details.

5. New image may partition flash storage in a different way comparing with current image,
it does not matter. However, currently active GEOM_MAP partition names
affected by upgrade must be specified in /etc/upgrade.conf using "layout" variable.
For example, my device has this partitioning:

# geom map status
      Name  Status  Components
map/u-boot     N/A  flash/spi0
map/kernel     N/A  flash/spi0
map/rootfs     N/A  flash/spi0
   map/cfg     N/A  flash/spi0
   map/ART     N/A  flash/spi0

That is, first there is U-Boot loader and its partition is unaffected with upgrade,
so it is not mentioned in /etc/upgrade.conf. Then, there are kernel and rootfs
partitions and new image spans over them, so they are recited in order:

layout='kernel rootfs'

Partitions cfg and ART are unaffected with upgrade too, so they are not mentioned.
Currently, it is supposed that new image covers contiguous paritions only.

There are actually two script: /usr/bin/upgrade and /etc/rc.upgrade.
The former creates "flashit" script calling dd to perform actial reflashing
after reroot and the latter is fixed script used as /etc/rc for reroot stage
to run generated "flashit" script. I've put them online for reference:

There are number of ways they may and should be improved.
For example, I'd like to know if it is possible to voluntary blink LEDs
during reflashing device so user has some information on the process.

More information about the freebsd-mips mailing list