Blog
Friday 03 October 2014
Looking at the build status for Cattle on Debian, I noticed that the test suite fails on some of the more exotic architectures. Here’s the error message:
ERROR:tape.c:282:test_tape_decrease_current_value: assertion failed: (cattle_tape_get_current_value (tape) == 127)
Not exactly helpful. It would be much easier to debug the issue if I had interactive access to a computer running Debian on one of those architectures… Luckily, turns out that I do!
$ egrep '^Processor|^Hardware' /proc/cpuinfo
Processor : ARMv7 Processor rev 0 (v7l)
Hardware : SMDK4x12
The computer in question is my Samsung Galaxy SIII smartphone which, with a bit of work, can be used as a Debian development host, and a pretty good one at that.
The procedure I’m about to describe will work on most Android
smartphones and tablets, provided that root access is available and busybox
has the right commands compiled in.
If, like me, you’re running CyanogenMod on your device, you already have everything you need. Note that I’ve only tested this on CM 11, though.
First of all, you’re going to need a computer running Debian. Other
Unix–like operating systems will work as well, but obtaining and
running debootstrap
on them is probably going to be a little
convoluted, so it’s left as an exercise to the reader.
Start with
$ dd if=/dev/zero of=debian.img bs=1M count=1024
$ sudo mkfs.ext4 -F debian.img
This will create a debian.img
file, 1GB in size, which will
contain your Debian system. 1GB is enough for the base system,
build-essential
and a bunch of other libraries with 250MB to
spare. Mount the image with
$ sudo mount -o loop debian.img /mnt
and complete the first stage of the bootstrap process with
$ sudo debootstrap --arch=armhf --variant=minbase --foreign unstable /mnt http://ftp.debian.org/debian
$ sync
$ sudo umount /mnt
Now push debian.img
to your Android device and launch a
terminal emulator. Become root by running
$ su
and navigate to the directory you’ve saved your image to. Now for the interesting bits:
# mount -o rw,remount rootfs /
# mknod /dev/block/loop99 b 7 99
# mount -o ro,remount rootfs /
This creates the loopback device you’re going to use to mount the image on Android. It will be automatically deleted on reboot, so don’t bother removing it when you’re done.
# mkdir debian
# losetup /dev/block/loop99 debian.img
# mount -t ext4 /dev/block/loop99 debian
Your image is now mounted on debian/
. A few filesystems are
needed on top of that for the system to work properly:
# mount -o bind /dev debian/dev
# mount -t devpts none debian/dev/pts
# mount -t proc none debian/proc
# mount -t sysfs none debian/sys
Now you can finally complete the installation!
# chroot debian /bin/bash
# export PATH=/usr/sbin:/usr/bin:/sbin:/bin
# /debootstrap/debootstrap --second-stage
Once the bootstrap is complete, you can perform any customization you might want. I immediately created an unprivileged user; then, after setting up DNS with
# echo "nameserver 208.67.222.222" >/etc/resolv.conf
# echo "nameserver 208.67.220.220" >>/etc/resolv.conf
and configuring software repositories with
# echo "deb http://ftp.debian.org/debian unstable main" >/etc/apt/sources.list
I was able to install openssh-server
, which is crucial because,
by this point, I could no longer bear to type Unix commands on a tiny virtual
keyboard :)
Once the OpenSSH daemon is running, you can either login from a computer connected to the same wireless network or directly from the Android device by using something like
$ ssh user@127.0.0.1
I prefer the second approach: I just connect the phone to my laptop with the USB cable, start a shell on the device with
$ adb shell
and login to the Debian system using the command above.
Once you’re done with your Debian work, you need to stop any daemon you’ve started inside the chroot and umount all the filesystem in reverse order from a privileged Android shell, like
# sync
# umount debian/sys
# umount debian/proc
# umount debian/dev/pts
# umount debian/dev
# umount debian
Doing this every time would become tedious, of course, so I've created a couple of shell scripts that do everything for me; they even support multiple Debian chroots running concurrently, because why not :)
You can grab the scripts, along with some documentation, from the Git repository.
Once you’re inside the chroot, it’s actually easy to forget you’re working on a phone: everything behaves exactly like it would on an Intel computer, if only a little slower. This is not a watered–down version of Debian, it’s the real deal. Kudos to all the developers who have have made such an impressive thing possible!
Now on to hunt the actual bug :)