Clone a dragonboard to other dragonboard units

Loopback mounting the image involves:

  • Decompressing
  • Converting from Android sparse format to raw format: simg2img rootfs.img rootfs.img.raw
  • Mounting: mkdir mountpoint && sudo mount -o loop rootfs.img.raw mountpoint

Once you have the filesystem mounted any programs you need to run that using the target architecture (such as apt-get) need to run with qemu using steps are described here (see the appendix on using chroot): QemuUserEmulation - Debian Wiki .

Note that the above instructions only work on distros that provide qemu-aarch64-static (which in practice usually means Debian or one of its derivatives such as Ubuntu) otherwise you cannot copy the emulator into the rootfs (and probably don’t have the kernel setup to allow it to run alien binaries using the emulator).

Once you are done with the changes umount, convert back using img2simg (if it crashes then you probably need a newer version) and you are good to go.

BTW if the qemu instructions don’t gel for you, another option is to run chroot natively on an AArch64 device. In other words put the rootfs image into a large SD card, mount it on the DB410C and run chroot natively to modify the rootfs.

1 Like

Alright, this is a bit lengthy, but it attempts to describe a reproducible process to edit the 96boards Linaro image while hopefully minimizing complexity. This is a rough (unrefined) process, so if anyone has good input I’d be happy to amend. I was able to:

  1. Download the Linaro rootfs from http://releases.linaro.org/96boards/dragonboard410c/linaro/debian/latest/linaro-buster-developer-dragonboard-410c-528.img.gz (note this image lacks a GUI)
  2. Expand and convert from sparse to raw with simg2img rootfs.img rootfs.img.raw
  3. Mount with sudo mount -o loop rootfs.img.raw mountpoint
  4. Modify rootfs
  5. Repackage
  6. Flash and boot the target

If you’re going to be adding to the image you’ll probably want to expand its size lest you run out of disk (file) space. The method I used was (with rootfs umounted):

  1. Append data (zeros) to the end of your raw image file. In this case we add 1GB: dd if=/dev/zero bs=1G count=1 >> rootfs.img.raw. I have also seen some use fallocate.
  2. Run filesystem check: e2fsck -f rootfs.img.raw
  3. Resize the fs to match the new file size: resize2fs rootfs.img.raw

Alternatively you could mount a temp folder from your host inside the chroot jail and avoid expanding and shrinking your image. This seems like a good idea when building things from source as it’s easy to control where your build products go, but it seems a bit more complicated when you need more room for other OS related stuff (like running apt).

If you haven’t already, set up QEMU as described in @danielt’s link (QemuUserEmulation - Debian Wiki). The takeaway is that you’ll be able to execute chroot mountpoint which will run qemu under the hood for you, or something.

Now you are in your emulated arm64 environment and can run aarch64 binaries, including apt-get to manipulate packages, “natively” build and install your own program, etc. I proved it to myself by cross-compiling a “hello world” in the host environment, copying it over to the chroot, running file on it to get something like ELF 64-bit LSB shared object, ARM aarch64, then running it.

Now it’s time to button everything up and get it on your DB410c. After cleaning up any unwanted files, unmounting, and reconverting to sparse, I used fastboot to flash only the rootfs leaving the bootloader and that other thing alone.

I lack the background knowledge to know exactly which parts of the following are required and which aren’t. In particular I’m not extremely clear on how to re-shrink the altered rootfs gracefully. It seems that converting to a sparse image “handles” the free space with its metadata magic. I did:

  1. Unmount everything related to rootfs. I wanted to do an apt upgrade to have the latest-greatest and openjdk made me mount /proc (mount -t proc proc /proc) in the chroot. You’ll have to unmount any nested mounts before unmounting rootfs.
  2. Convert to sparse: img2simg rootfs.img.raw rootfs.img. Caution: you might overwrite your original rootfs.img.
  3. Put your Dragonboard in fastboot mode with these instructions and flash with fastboot using the microUSB host on the DB410c: fastboot flash rootfs rootfs.img.
  4. Boot the Dragonboard and cry tears of joy while not having to compile for hours!

The enterprising engineer can now crate a development pipeline that uses the ARM architecture without having to compile on the target as well as (perhaps crudely) generating a customized image that can be flashed to many targets.

Alright, now it’s time for someone take this apart.

Sort of.

The new space will be filled with zeros and img2simg detects this and
writes it out in a much smaller form… however when you flash it with
fastboot the zeros will be written to the media so the flashing part
will take longer than with the orignal image (by more than just the cost
of the new stuff you added).

If you want to minimise flashing time try using the -M option to
resize2fs to shrink it down as much as possible. However if it is only a
few boards then I wouldn’t worry about it.

Sorry my last comment was sent by e-mail and discourse ripped out the quoting (so I’ve just edited to put the quote back).

I certainly wasn’t replying to this bit… it looks like a pretty good summary of this technique to me. I was just filling in the details about shrinking file system images if you want to do that!

This is a really interesting thread for me as I have been looking to have a Dragonboard image that I can easily share. I have arrived at a very similar process to yourself. The only difference is the step to expand the size of the image. I have used truncate (truncate(1) - Linux man page).
Here it is in the context how get up to the modify rootfs step.

$ sudo apt-get install android-tools-adb
$ sudo apt-get install android-tools-fastboot
$ sudo apt install android-tools-fsutils
$ simg2img linaro-stretch-developer-qcom-snapdragon-arm64-20171016-283.img linaro-stretch-developer-qcom-snapdragon-arm64-20171016-283.img.raw
# resize disk
$ truncate -s 2G linaro-stretch-developer-qcom-snapdragon-arm64-20171016-283.img.raw
$ mkdir mnt-point
$ sudo mount -t ext4 -o loop linaro-stretch-developer-qcom-snapdragon-arm64-20171016-283.img.raw mnt-point
$ sudo resize2fs /dev/loop0

After modifying the rootfs then my steps to create an image for flashing is very similar:

$ sudo umount mnt-point
$ img2simg linaro-stretch-developer-qcom-snapdragon-arm64-20171016-283.img.raw linaro-stretch-developer-qcom-snapdragon-arm64-20171016-283_bb.img

I would like to thank you for this gude, it really helped me to get started! I would just like to add that I had problems (SSLError malloc failure with python’s pip) using qemu-user-static package from Ubuntu since it’s pretty outdated (version 2.11.1(Debian 1:2.11+dfsg-1ubuntu7.26)). I had to compile qemu 5.0.0 on my own with flags: ./configure --static --disable-system --enable-linux-user --enable-kvm. Then I added aarch64 entry to binfmt with ./qemu-binfmt-conf.sh --debian --qemu-path /usr/local/bin. I also had to copy qemu-aarch64 to chroot jail: cp $(which qemu-aarch64) /mnt/$(which qemu-aarch64).