Long story short, I would like to plug an USB pendrive to my Debian system (which is installed on the NAND memory on an ARM board) and overwrite the NAND with the image that's on the USB pendrive while the system is running. Is this possible? Unfortunately I can't boot from USB, so I somehow have to do this like an "open-heart surgery"


Edit: some additional info

Maybe it could be useful to add some additional info: I have to update 200+ boards. The actual procedure is:

  1. shutdown the board
  2. open the case
  3. insert a microSD (with a Debian installation) in the board's slot and a USB pendrive (with the new board's NAND image) in a board's USB port
  4. power on the board
  5. the board will boot the Debian installation on the microSD which will automatically copy the image that's on the USB stick to the board's NAND with a simple dd command: gunzip -c /mnt/pendrive/hda.img.gz | dd of=/dev/nand and when finished, the board will power off
  6. when the board powers off, disconnect the microSD and the USB pendrive
  7. re-assemble the case
  8. power on the board with the updated Debian installation

This procedure is necessary because the microSD slot is not accessible from the outside. Do this once... no problem. Do it 200+ times? Gosh!

I would like to speed up this process and also make it super simple so also a normal user could update the board. If something goes wrong no problem, I don't need backups, I have no data on the board, just the software that I'm distributing.

My goal is to have a new procedure which does something like this:

  1. The board is powered on and Debian is running
  2. I plug in the pendrive
  3. A script on the pendrive is launched. The script does a gunzip -c /mnt/pendrive/hda.img.gz | dd of=/dev/nand and when finished it powers off the board
  4. On the next power on, the updated Debian will boot from the NAND

This simpler proocedure would allow me to distribute some USB pendrives so that the users can update the boards without the need to bring to me all the 200+ boards. If this process somewhere fails and the Debian installation gets corrupted, the user just brings to me that board, and I'll follow the actual procedure.

Note that the board doesn't have Internet access, so I can't remotely login and launch updates.

  • If the NAND is RO while the system is running (e.g. actually running from a copy in tmpfs), then it should be safe to overwrite it. You'll have to write a script and get the end-user to run it in a root shell, because anyone who tried to implement a Windows style "autorun" in the unix/linux world would get laughed at mercilessly. – cas Nov 13 '15 at 0:10
  • I don't remember right now all the details, but most parts of the NAND are RO. Some mount points are mounted on tmpfs to reduce NAND wear and to reduce risk of corruption when the board is abruptly powered off. And right now we already have an update system for just our .jar running on the board. When a pendrive is inserted, a script on the pendrive is executed with root privileges in order to update the .jar and make configuration changes, so half of the work is done – user1527576 Nov 13 '15 at 21:11

You can do that if you will put all necessary for overwriting programs into tmpfs and execute them from there. Risky, and you should have backup handy if something wents wrong.

  • 2
    I have done this. It works. It's nerve racking. – coteyr Nov 12 '15 at 14:49
  • If you run it from separate battery and you see it's not going to die in next six hours, and you have access to UART to debug and restore, and you're not touching it's system board software (bootloader), then you're absolutely calm :-) – user140866 Nov 12 '15 at 14:54
  • And I should mention that I also have done this, including remotely updating small machines that far away from you (100km+) which could become completely unresponsive if something wents wrong. It's matter of practice plus having an exact same machine there for testing. – user140866 Nov 12 '15 at 14:58
  • unix.stackexchange.com/a/227318/103923 might be relevant, adjusted appropriately. It's for a different goal, but the "temporary system on a tmpfs" bit is the same. – Tom Hunt Nov 12 '15 at 15:59
  • Thanks for your answer, but my requirement is slightly different: instead of copying the directory structure to NAND, I would like to overwrite it with a NAND image file. I've added some more info in the question. – user1527576 Nov 12 '15 at 21:38

Never done it, sounds very risky, but it can work.

First, stop all services and all programs running at the moment and after that do the rsync.

Another thing that may help, is to chroot to the usb OS first, in order to have access to the correct libraries during your work.

  • So I should have another Linux installation on the USB pendrive in addition to the image file that should be copied to the NAND memory? And after plugging the pendrive i should stop everything on the main system (killall5 -9?), chroot to it, and launch the dd? – user1527576 Nov 12 '15 at 21:42
  • chroot idea is interesting too, although any plain dd can do things well, for example, you can carry on busybox dd statically linked with musl and that's all you'll need. You really should experiment with test board before you will do a mass update. – user140866 Nov 13 '15 at 2:55
  • Actually, after the updates you posted, chrooting is not necessary. Actually my entire post is useless :). I thought that you want to overwrite the the OS that was running at that moment. – cristi Nov 13 '15 at 8:42

Because your requirements changed, I answer again.

In your case, I would build a special busybox statically linked with these tools: ash, (core utils like ls mv cp rm), dd, vi and gzip/gunzip. Write a script then which you will run from USB (the USB drive will be formatted into any ext* filesystem, right?) which will use only that busybox binary from flash while running the commands, for example with your update command it will look like: /mnt/pendrive/busybox gunzip -c /mnt/pendrive/hda.img.gz | /mnt/pendrive/busybox dd of=/dev/nand.

Before running an update, I would execute a shell (if in interactive mode) from busybox before update with exec /mnt/pendrive/busybox ash -l, overwriting any shell you use in memory, because it will become unavailable after overwrite. Alternatively, if you plan to run it in batch mode, you should not use #!/bin/sh line, but should specify full path to busybox shell like #!/mnt/pendrive/busybox sh, or, when running it like /bin/sh /mnt/pendrive/script.sh, you should run it with actual busybox binary: /mnt/pendrive/busybox sh /mnt/pendrive/script.sh.

Remember, before update you should analyze and stop any system activity which can write something to NAND during update, so if you have some services running (even syslog) - you should shutdown them. Use correct tools for that, maybe you have a process supervisor running which will respawn them.

And probably poweroff should be instant, no unmounts or scripts that will shutdown services should not ever run. You can achieve that with echo o >/proc/sysrq-trigger, or appropriate shutdown command which will just call appropriate reboot() syscall immediately.

You can find more information about busybox there: http://busybox.net/. For execution safety (no shared libs requirement even in statically linked binary), I would build busybox with musl libc (http://www.musl-libc.org/).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.