Using Qemu to update packages on rootfs



I am trying to build a rootfs for the DB410c with the networking modified, Theia IDE installed, and packages updated.
The following topic has been very helpful:

However, it has been a bumpy ride to get Qemu to working. I have updated my host machine to Ubuntu 18.10 but I was still getting the following error:

$ sudo cp /usr/bin/qemu-aarch64-static mnt-point/usr/bin
$ uname -a
Linux thinkabit1 4.18.0-17-generic #18-Ubuntu SMP Wed Mar 13 14:34:40 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
$ sudo chroot mnt-point/
# uname -a
Linux thinkabit1 4.18.0-17-generic #18-Ubuntu SMP Wed Mar 13 14:34:40 UTC 2019 aarch64 GNU/Linux
# apt-get update
Get:1 stretch/updates InRelease [94.3 kB]                                                                         
0% [1 InRelease gpgv 94.3 kB] [Waiting for headers] [Waiting for headers] [Waiting for headers]gpgv: Signature made Tue Apr  9 18:21:53 2019 UTC
gpgv:                using RSA key D21169141CECD440F2EB8DDA9D6D8F6BC857C906
gpgv: Good signature from "Debian Security Archive Automatic Signing Key (8/jessie) <>"
gpgv: Signature made Tue Apr  9 18:21:53 2019 UTC
gpgv:                using RSA key A1BD8E9D78F7FE5C3E65D8AF8B48AD6246925553
gpgv: Good signature from "Debian Archive Automatic Signing Key (7.0/wheezy) <>"
/usr/bin/apt-key: 596: /usr/bin/apt-key: cannot create /dev/null: Permission denied
terminate called after throwing an instance of 'std::runtime_error'
  what():  random_device::random_device(const std::string&)
qemu: uncaught target signal 6 (Aborted) - core dumped
Aborted (core dumped)

I did a chmod on /dev/null and that moved things to a new error:

# chmod 777 /dev/null
# apt update
Ign:1 stretch InRelease                                                                                         
Get:2 stretch/updates InRelease [94.3 kB]                                                                         
Get:3 stretch Release [118 kB]                                                                                  
Ign:5 ./ InRelease                                                                
Ign:7 ./ InRelease
Get:8 ./ Release [952 B]
Get:9 ./ Release [1035 B]
Get:10 ./ Release.gpg [228 B]
Get:11 ./ Release.gpg [228 B]
0% [2 InRelease gpgv 94.3 kB]terminate called after throwing an instance of 'std::runtime_error'
  what():  random_device::random_device(const std::string&)
qemu: uncaught target signal 6 (Aborted) - core dumped
Aborted (core dumped)

This seemed to be an issue with /dev/urandom permissions.

From I found the following solution:

mknod random c 1 8
mknod urandom c 1 9

Have other people seen these issues? Or did I do something wrong early on that caused these permission issues?



/dev is normally automatically managed by udev so perhaps the base file system doesn’t contain any device nodes at all.

You could try a bind mount to bring /dev from your host into the chroot:

mount --bind /dev mnt-point/dev

I’ve not needed this when I’ve applied this technique but I only use it on rootfs images I build myself and these might be different to the db410c ones (although my notes fo mention cp /etc/resolv.conf mnt-point/etc/resolve.conf to get networking going).


Initial results with this look promising. Thanks.

The nodejs-dev package is still complaining so I may be back… :grin:


I seem to be making good progress now with Qemu. I am sure it can be improved but the recipe I have currently is:

# Install required tools
sudo apt-get install android-tools-adb
sudo apt-get install android-tools-fastboot
sudo apt install android-tools-fsutils
sudo apt install qemu-user-static

# Converting from Android sparse format to raw format
gunzip linaro-stretch-developer-qcom-snapdragon-arm64-20171016-283.img.gz 
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
e2fsck -f linaro-stretch-developer-qcom-snapdragon-arm64-20171016-283.img.raw
resize2fs linaro-stretch-developer-qcom-snapdragon-arm64-20171016-283.img.raw

# mount 
mkdir mnt-point
sudo mount -t ext4 -o loop linaro-stretch-developer-qcom-snapdragon-arm64-20171016-283.img.raw mnt-point
# sudo mount --bind /dev mnt-point/dev
sudo mount -t proc -o nosuid,noexec,nodev proc mnt-point/proc
sudo mount -t sysfs -o nosuid,noexec,nodev sysfs mnt-point/sys
sudo mount -t devtmpfs -o mode=0755,nosuid devtmpfs mnt-point/dev
sudo mount -t devpts -o gid=5,mode=620 devpts mnt-point/dev/pts

# Qemu
sudo cp /usr/bin/qemu-aarch64-static mnt-point/usr/bin

# update system
sudo chroot mnt-point apt -y update
sudo chroot mnt-point apt -y install locales
sudo chroot mnt-point apt -y upgrade
sudo chroot mnt-point apt -y install build-essential autoconf libtool cmake pkg-config git python3-dev swig3.0 libpcre3-dev nodejs-dev
sudo chroot mnt-point apt -y install python3-pip
sudo chroot mnt-point pip3 install --upgrade pip

# unmount 
sudo umount mnt-point/dev/pts
sudo umount mnt-point/dev
sudo umount mnt-point/proc
sudo umount mnt-point/sys
sudo umount mnt-point

# Converting from raw format to Android sparse format 
img2simg linaro-stretch-developer-qcom-snapdragon-arm64-20171016-283.img.raw linaro-stretch-developer-qcom-snapdragon-arm64-20171016-283_martha.img


Some quick notes on your recipe since I’ve had to replicate this process a few times recently.

  1. While the truncate syntax is simpler than dd, without a + or - argument (truncate -s 1G file vs truncate -s +1G file) the program sets the file to the specified size rather than extending or shrinking it. In other words, if the image was over 2GB and you issued truncate -s 2G image.raw you would have lost data and likely corrupted the image. I find the command dd if=/dev/zero bs=1G count=1 >> image.raw (or some variation thereof), while more verbose, more explicit with a more predictable result. Yes, I’m deliberately ignoring the “why does a program called truncate extend anything” argument because pedantry.

  2. Since at the end you convert back to a sparse image, it’s a good idea to pad the image’s free space with zeros with something like dd if=/dev/zero of=/mount/point/zeros bs=1M (adjust the block size to something reasonable for you) and then delete the resulting file. This will result in a smaller sparse image more often than not.

  3. During my testing I didn’t need to mount any directories other than /proc otherwise openjdk would fail to update via apt. However my host machine is different from yours (Debian 9.8). I did however bind mount a temp build folder that lives outside the image in order to avoid unnecessarily adding data to the raw image while compiling for the target.


To be honest I’d be tempted just to let resize2fs handle the whole thing (it knows the difference between a file and a partition… so all the stuff about not-growing a partition automatically doesn’t apply): resize2fs image.raw 3G

An idea I haven’t tested in a while but, assuming you’ve not done anything to the image to disable the automatic partition resize on first boot, I think you can leave this to resize2fs as well: resize2fs -M image.raw

This will shrink away any unused space in the image. This won’t make the sparse image a lot smaller than filling the image with zeros but it will flash quicker (because we don’t have to write all the zeros to the MMC).