Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 10 Feb 2016 00:28:15 +0700
From:      Eugene Grosbein <eugen@grosbein.net>
To:        "freebsd-mips@freebsd.org" <freebsd-mips@freebsd.org>
Subject:   Success story: using reroot to upgrade MIPS online
Message-ID:  <56BA21AF.50207@grosbein.net>

next in thread | raw e-mail | index | archive | help
Hi!

Latest Quarterly Status Report https://www.freebsd.org/news/status/report-2015-10-2015-12.html
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@192.168.0.66//home/tftpboot/tl-wdr3600.factory.bin
Size: 7919104 bytes
Allocating 13443K for memory disk
Downloading ftp://eugen@192.168.0.66//home/tftpboot/tl-wdr3600.factory.bin
looking up 192.168.0.66
connecting to 192.168.0.66:21
setting passive mode
opening data connection
initiating transfer
remote size / mtime: 7919104 / 1455037602
newimage                                      100% of 7733 kB 4925 kBps 00m02s
vfs.root.mountfrom="ufs:/dev/md2"
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?)
Terminated
.
Trying to mount root from ufs:/dev/md2 []...
warning: no time-of-day clock registered, system time will not be set accurately

REPROGRAMMING FLASH
DO NOT REBOOT OR POWER OFF THE DEVICE
STAGE 1: WRITING BLOCKS 2-20
19+0 records in
19+0 records out
1245184 bytes transferred in 12.476816 secs (99800 bytes/sec)
STAGE 2: WRITING BLOCKS 21-125
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
Rebooting...

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
Providers:
1. Name: map/u-boot
   Mediasize: 131072 (128K)
   Sectorsize: 512
   Stripesize: 65536
[skip]

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:

url="ftp://username@hostname/path/to/tl-wdr3600.factory.bin"
FTP_PASSWORD='secret words'

Or, for HTTP:

url="http://hostname/path/to/tl-wdr3600.factory.bin"
HTTP_AUTH='basic:realm:username:password'

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:

http://www.grosbein.net/freebsd/mips/upgrade/rc.upgrade
http://www.grosbein.net/freebsd/mips/upgrade/upgrade

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.



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?56BA21AF.50207>