NAND firmware update
From ThinCan
This page describes how to update the firmware on MTD flash when we are running from it (ie root on JFFS2, CRAMFS or SQUASHFS).
This is a tricky procedure to get right (we must switch root to another partition and then unmount the old root to stop depending on the MTD root. If the old root is not un-mounted and the flash is erased, a random read, write or FS maintenance operation will bring the system down and probably leave the device bricked.
This procedure has been developed by Artec over many years and is been used in many of Artec's devices.
Requirements
- terminate all programs running from old root (including init!)
- close all open files, including /dev/console
- unmount all mounted mountpoints under old root
- unmount old root
- preferably have a minimal working system left to do the update!
Procedure
- generate a new minimal root file system in tmpfs (copy busybox, libc, dev nodes and other required things to /tmp). For example:
mkdir /tmp/tmp /tmp/proc /tmp/sys mkdir -p /tmp/mnt/usb /tmp/usr/bin /tmp/usr/sbin /tmp/usr/lib mkdir /tmp/oldroot mkdir /tmp/lib mkdir /tmp/etc cp -a /bin /tmp/bin cp -a /lib/* /tmp/lib cp -a /usr/lib/libpci* /tmp/usr/lib cp -a /etc/* /tmp/etc cp -a /dev /tmp/dev cp -a /sbin /tmp/sbin cp -a /usr/sbin/wrmsr /tmp/usr/sbin cp -a /usr/bin/imagewrite /tmp/usr/bin cp -a /usr/sbin/flash_eraseall /tmp/usr/sbin cp -a /usr/sbin/flashrom /tmp/usr/sbin cp -a /usr/sbin/nandwrite /tmp/usr/sbin
- unmount everything under old root (except /tmp where the new root is)
umount /sys umount /proc
- pivot_root to this new root file system:
pivot_root /tmp /tmp/oldroot</pre>
- switch shell to new root (otherwise it will be left confused about its location):
cd /
- re-mount /proc and /sys under new root:
mount /proc mount /sys mount /tmp</pre>
- generate a new /etc/inittab file in the new root FS. Keep all runonce and respawn lines, add a new restart line (if existing lines are removed, the init may kill our updater before re-spawning!):
grep -v restart /oldroot/etc/inittab > /etc/inittab echo "::restart:/bin/sh /bin/update-firmware2" >> /etc/inittab
- tell busybox init to reload inittab:
kill -HUP 1 sleep 1
- tell init reload itself. As we changed the restart parameter, our second stage script gets started instead of init as PID1 (this will kill ALL running processes, including us!)
kill -QUIT 1 sleep 5
- now, in second stage, all processes are gone, only /dev/console in old root is still open and connected to our stdin/stdout/stderr. This blocks un-mounting our old root. To close it, start third stage script to redirect console to new rootfs /dev/console (use exec to replace current process):
exec /bin/sh /bin/update-firmware3 </dev/console >/dev/console 2>&1
- now, in third stage, you should be able to unmount old root. First, it would be wise to re-mount /proc in new root.
umount /oldroot
- Now it is safe to erase and re-flash the root partition.