Using Qemu to update packages on rootfs


#1

Hi,

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 http://security.debian.org 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) <ftpmaster@debian.org>"
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) <ftpmaster@debian.org>"
/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 http://deb.debian.org/debian stretch InRelease                                                                                         
Get:2 http://security.debian.org stretch/updates InRelease [94.3 kB]                                                                         
Get:3 http://deb.debian.org/debian stretch Release [118 kB]                                                                                  
Ign:5 http://obs.linaro.org/qcom/stretch ./ InRelease                                                                
Ign:7 http://obs.linaro.org/linaro-overlay-stretch/Debian_9.0 ./ InRelease
Get:8 http://obs.linaro.org/qcom/stretch ./ Release [952 B]
Get:9 http://obs.linaro.org/linaro-overlay-stretch/Debian_9.0 ./ Release [1035 B]
Get:10 http://obs.linaro.org/qcom/stretch ./ Release.gpg [228 B]
Get:11 http://obs.linaro.org/linaro-overlay-stretch/Debian_9.0 ./ 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 https://bugs.launchpad.net/ubuntu/+source/network-manager-openvpn/+bug/1618363 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?

Thanks,
Barry


#2

/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).


#3

Initial results with this look promising. Thanks.

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


#4

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

#5

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.


#6

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).