Quick instructions
- Install qemubuilder package, version 0.48 or newer.
- Grab kernel image from here.
- Create a configuration file for qemubuilder, using following template:
ARCH=armel MEMORY_MEGS=256 KERNEL_IMAGE=$DIR/vmlinuz-2.6.26-versatile-qemu BASEPATH=$DIR/base.qemu MIRRORSITE=$MIRROR BUILDPLACE=$DIR/build BUILDRESULT=$DIR/result
Replace $DIR with a full path to some directory, and $MIRROR with your debian mirror. Create empty directories $DIR/build and $DIR/result.
- Ensure that your /etc/resolf.conf file contains a proper nameserver line that points to a working DNS server (and not to 127.0.0.1 – that won’t work inside qemu environment).
- Run
sudo qemubuilder --config $DIR/config --create
($DIR/config is the path to your qemubuilder configuration file)
- Bind-mount just-created $DIR/base.qemu:
mkdir $DIR/mnt mount -o loop $DIR/base.qemu $DIR/mnt
- Edit $DIR/mnt/pbuilder-run file and ensure that it properly mounts all pseudo-filesystems:
... mount -n proc /proc -t proc mount -n sysfs /sys -t sysfs mount -n devpts /dev/pts -t devpts ...
- Create $DIR/mnt/etc/apt/apt.conf.d/20no-pdiffs file with the following line:
Acquire::PDiffs "false";
This disables pdiffs – those are terribly slow inside qemu. If you are traffic- or bandwidth-limited, better to set up local apt-cacher.
- Unmount $DIR/base.qemu:
umount $DIR/mnt
That’s all. Now you can build binary-armel packages using
sudo qemubuilder --config $DIR/config --build filname.dsc
Read man pbuilder for build options. Also don’t forget to run
sudo qemubuilder --config $DIR/config --update
sometimes to keep your build environment up to date.
Long story
I own a Neo Freerunner device. Being a (unfortunately not very active) Debian Developer, I naturaly want to run and enhance Debian on Freerunner.
I’m going to build debian packages for Freerunner. To do that correctly, a clean build environment is required. For native backage builds, such an environment is provided by pbuilder package. To cross-build packages for armel archutecture, qemubuilder should provide the same.
I found some initial instructions to set up qemubuilder on DebianOnFreeRunner Debian Wiki page. It suggested to use debian-installer versatile netboot kernel with qemu. That did not work for me:
VFS: Unable to mount root fs on unknown-block(0,0)
I thought that proper driver may be inside initrd, and tried to use initrd image from the same URL. That also did not work – this time with
/init: exec: line 20: /pbuilder-run: not found
At this moment I asked for an advice in the smartphones-userland mailing list, and got a reply suggesting to use kernel from here. With this kernel (and initrd) things became better a bit – debootstrap second stage completed inside qemu. But then it failed again, being unable to reach network to install build-essential. It tried to load network driver with modprobe, but that could not work because debootstrap does not install any kernel modules into the target image.
Next attempt was to make debootstrap to include linux-image-2.6.26-1-versatile package. For that, debootstrap provides --include command-line option. But how to pass it to debootstrap called from qemubuilder --create? I looked into qemubuilder sources and found that debootstrap command-line is hardcoded. Not good. I fooled it by creating /usr/local/sbin/debootstrap containing
exec /usr/sbin/debootstrap --include=linux-image-2.6.26-1-versatile "$@"
That failed again, this time because of debootstrap second stage being unable to unpack packages. Bind-mounted qemu’s filesystem to the host, looked inside /debootstrap/debootstrap.log there, and found
Unpacking linux-image-2.6.26-1-versatile (from .../linux-image-2.6.26-1-versatile_2.6.26-12_armel.deb) ... Ok, Aborting, since the bootloader might not handle an initrd/initramfs image. dpkg: error processing var/cache/apt/archives/linux-image-2.6.26-1-versatile_2.6.26-12_armel.deb (--unpack): subprocess pre-installation script returned error exit status 1
This could be likely fixed by putting do_initrd = yes into /etc/kernel-img.conf, but how to make qemubuilder to do that? I did not want to change qemubuilder‘s C source this time.
Also, I recognized a more generic problem. Kernel image and kernel modules must exactly match each other. Because of that, using whatever external kernel to boot qemu, while using debian’s kernel-image package to provide modules, is a broken design – simply because it’s unclear how to keep those two in sync.
Using debian’s kernel-image to provide all components does not look good, because debian’s kernel makes hard use of initrd, and initrd image is not included into the package (it is built during package installation). So to take all components from debian’s kernel-image to provide, one needs already-running debian armel system to build initrd. Although possible with downloadable images, this does not look good to me.
So I decided to build a kernel that will work with qemubuilder without any modules, and make that available to whoever needs it.
To do so, I downloaded complete armel debian qemu installation from already mentioned location, booted it, and did this:
apt-get install linux-source-2.6.26 build-essential ncurses-dev tar xjf /usr/src/linux-source-2.6.26 cd linux-source-2.6.26 cp /boot/config-2.6.26-1-versatile ./.config make menuconfig
Starting with debian’s default configuration, I wanted to build disk, filesystem, and network drivers into the kernel. I typed lsmod on another virtual console, and found that I need to switch from M to * the following options:
- SCSI device support (under Device drivers : SCSI support)
- SCSI disk support (under Device drivers : SCSI support)
- SYM53C8XX Version 2 SCSI support (under Device drivers : SCSI support : SCSI low-level drivers)
- SMC 91C9x/91c1xxx support (under Device drivers : Network drivers : Ethernet (10 or 100 Mbit)
- Ext3 journalling file system support (under File systems)
Resulting kernel configuration file is here, and compiled kernel image is here.
With this kernel things work much better: both qemubuilder --create and qemubuilder --update complete successfully (but only if host /etc/resolv.conf is ok – while running qemubuilder --create , /etc/resolv.conf file is copied from host to the qemu filesystem, so that file should contain nameserver line(s) that will be valid within qemu, in particular not point to 127.0.0.1).
My first attempts to build binary-armel packages failed – qemu hanged after installing build-depends. After some experiments, found that it may be fixed by ensuring that all pseudo-filesystems are mounted – see above for instructions.
7 Responses to “Setting up armel qemubuilder”
Sorry, the comment form is closed at this time.
English
Thanks! This saved my day. Especially note about psudo-filesystems. Having pseudo fs working, I was able to run sshd inside qemu and now can debug why it hungs in progress of building my package.
Seems this should be fixed in qemubuilder – having all pseudo fs mounted, I have no more problems with building…
Sure, not mounting pseudo fs is a bug in qemubuilder, I will try not to forget to report to BTS when I get a free minute …
Heya!
Your kernel definitely is the best I could get for qemubuilder/armel. However it OOPSES here with http://random.christoph-egger.org/armel so this is actually not working any more …
I can’t reproduce any crashes.
What are you doing to make it crash? Which qemu and qemubuilder versions?
Just the qemu (0.10.3-1) and qemubuilder (0.55) versions from unstable and an qemubuilder –update
Just for the record: Downloading your config and building a make oldconfig default version of 2.6.29.4 has resulted in a booting Kernel[0] for me!
[0] http://alioth.debian.org/~christoph-guest/zImage-2.6.29.4