NAND firmware update

From ThinCan
Jump to: navigation, search

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.
Personal tools