Booting from USB clone without UART and medkit

tl;dr cloning an existing installation from eMMC and booting from USB without UART and medkit


Connecting UART is a bit of pain - device stored/mounted inside a utility box that is out of easy reach, having to open/close the device, disconnecting/reconnecting cabling, fumbling with the UART connectors - I was looking for a more convenient (lazy) way to get clones of the existing and known working installation from the eMMC onto another drive for booting.

Inspired by Turris Documentation and

First tried with the already installed mSATA SSD but that did not work since u-boot implementation in OpenWrt/TOS does not support GPT and I did not want to revert the SSD’s partition table to legacy MBR (good’ol DOS times).

As per online doc then procured a mPCIe to USB 2.0 adapter

The irony of course being that the router needed to be opened for installing the adapter…

Caveats:

  • adapter occupies a mPCIe slot (the one over the sim card slot) and with a mSATA in place the 2.4GHz Wlan card been the collateral
  • due to the design of dd the target drive/partition needs to be same size or larger, but cannot be smaller, than the eMMC partition (/dev/mmcblk0p1)
  • (s)low read speed of USB device
  • if other USB drives are connected to the router at the same time the /dev/sd* designation may change and could potentially mess things up

That out of the way, being logged into the running TOS installation on the eMMC via ssh:

  • created primary MBR partition (/dev/sdb1) on the USB drive (with fdisk, suggested reboot)
  • mkdir /mnt/sdb1
  • dd status=progress if=/dev/mmcblk0p1 of=/dev/sdb1
  • btrfstune -u /dev/sdb1
  • mount /dev/sdb1 /mnt/sdb1
  • btrfs fi resize max /mnt/sdb1
  • btrfs quota rescan -w /mnt/sdb1
  • umount /dev/sdb1
  • btrfsck /dev/sdb1

Good to go with fw_setenv -s (script file content below) & reboot from ssh

usbboot setenv bootargs "$bootargs cfg80211.freg=$regdomain"; usb start; btrload usb 0 0x01000000 boot/zImage @; btrload usb 0 0x02000000 boot/dtb @; bootz 0x01000000 - 0x02000000
bootargs earlyprintk console=ttyS0,115200 rootfstype=btrfs rootwait root=/dev/sdb1 rootflags=subvol=@,commit=5 rw
bootcmd i2c dev 1; i2c read 0x2a 0x9 1 0x00FFFFF0; setexpr.b rescue *0x00FFFFF0; if test $rescue -ge 1; then echo BOOT RESCUE; run rescueboot; else echo BOOT eMMC FS; run usbboot; fi
scsiboot setenv bootargs "$bootargs cfg80211.freg=$regdomain"; scsi scan; btrload scsi 0:1 0x01000000 boot/zImage @; btrload scsi 0:1 0x02000000 boot/dtb @; bootz 0x01000000 - 0x02000000

Then after having booted from the USB device sort schnapps

  • touch /etc/schnapps/config | echo 'ROOT_DEV="/dev/sdb1"' > /etc/schnapps/config

It is also possible to generate the USB installation with a medkit file, be that vanilla or one generated/exported by schnapps, without UART but vis ssh from a running installation on the eMMC. Which is faster in terms of speed and more independent of the target’s drive size than dd.

Caveat:

  • requires a storage medium that provides the medkit file

Steps from running router installation via ssh:

  • created primary MBR partition (/dev/sdb1) on the USB drive (with fdisk, suggested reboot)
  • mkdir /mnt/tmp /mkdir/usb
  • mkfs.btrfs /dev/sdb1
  • mount /dev/sdb1 /mnt/usb
  • btrfs su c /mnt/sdb1/@
  • mount /dev/${medium with medkit} /mnt/tmp (unless it is already mounted of course)
  • tar -C /mnt/sdb1/@ -xzvf /mnt/tmp/${medkit file} (medkit file either vanilla or from schnapps exported)
  • umount /dev/sdb1 /dev/${medium with medkit} (unless the medium with the medkit should not be demounted)
  • rm -r /mnt/tmp /mnt/usb
  • btrfsck /dev/sdb1

Proceed with the remainder of the u-boot env, reboot and schnapps conf


If the USB device contains more than one partition such needs to specified in the u-boot env → change from usb 0 stanzas to usb 0:X with X being the partition number on the drive.