Arch Linux is my preferred distribution of GNU/Linux and I enjoy using it on all my devices. I recently discovered how to make this possible thanks to this blog post. I did things slightly differently for my current Android device, which is a Verizon branded Galaxy Nexus. I will document how I did this for my future reference and for anyone else that wanders into my neck of the internet. Make no mistake though, the author of that post deserves all the credit for making most of this process. I stress that this as much for my own reference as it is for anyone who might find this useful.
For this little howto, I expect you've:
- rooted your phone
- have busybox installed
- have some terminal emulator app
- have adb installed on your Linux computer (for which you also have root access)
- have successfully interfaced adb with your rooted device
- basically know your way around a Linux terminal
If any of those things have not been done, there are numerous articles online that explain it adequately. So go do that, right now, I'll wait.
The following steps can get kinda involved. At its core, the job is simple:
- Get the OS files for the device
- Make a filesystem image of those files
- Send said filesystem image to the device
- Mount the filesystem image on the device
- Mount pseudo-filesystems within the image's root filesystem
- chroot into the image's root filesystem
1. Downloading the OS
We'll need an OS image for your device. Most Android devices use ARM processors so we'll be using Arch Linux ARM. They've got most of the packages of the main Arch, but all ported to ARM processors. However, there is a catch. In the same way on x86 we have 32 and 64 bit variants. There are many variants of ARM. The ARM version of Arch Linux supports ARM v5, ARM v6, and ARM v7. In addition, some ARM processors support extra instructions in the same way x86 has SSE, AVX, and who knows what else. Full disclosure, I don't fully grok the difference between the ARM processors ,so let's just say the closer the version of ARM we get from Arch Linux ARM's website, the better of we'll be in terms of performance and compatibility.
Let's take my device as an example. It's a Galaxy Nexus which according to Wikipedia has a TI OMAP System on a Chip (SoC) with a ARM Cortex-A9 MPCore. Clicking on that last link tells us that that particular line of chips has multiple cores and implements the ARM v7 instruction set. Now taking a look at the list of OS archives and images that Arch Linux ARM has, we have all the information we need. The one labeled omap-smp-latest is our best bet for the Galaxy Nexus. The SMP in that label indicates Symmetric Multiprocessing.
Your device may, and most likely is, different than mine, but I've just shown you how to fish so to speak, so you'll just have to go through the process outlined above to find your device's OS. A word of warning: the following steps depend on using an OS that ends in tar.gz from the list of OS's. The ones ending in img.gz are already formatted to a specific structure for a specific device, which is mostly likely not your android device. They certainly won't work with these instructions if at all. Also, your android device may not be and ARM device, which will be apparent by reading your devices specs on Wikipedia or the manufacturer's website. In that case Arch Linux ARM is not for you. The following may be useful, but you're on your own getting an OS archive.
I didn't need to do this for my device, but it may be to go to the Arch Linux ARM home page and look through their platforms section. You might find something that matches the processor of your device. Other hardware is not as important to match because we'll use almost none (or in fact none) of the drivers that come with it. We're after the juicy packages and libraries, not the kernel.
2. Making the Filesystem Image
Linux filesystems operate exclusively on special devices called block devices that are located
/dev. Unfortunately for us, that's no good because one cannot transfer a block
device like a file. Fortunatly for us, there is a trick to make a fake block device point to a
normal file on our filesystem. First thing we need is a file that will act as a block device.
This will create a 2GB file called
linux.img of whatever happened to be on some
unallocated sectors of your disk. For those unfamiliar with this command (which definitely includes
|if=/dev/zero||The input file for reading data is
|of="linux.img"||The output file for writing data is
|obs=1M||The size of each write done be 1MB.|
|seek=2048||Seek 2048 times forward, each time advancing by
|count=0||Write out 0 bytes after seeking|
The neat trick is that it doesn't matter what is on the image we created because the filesystem we'll put on it assumes nothing about the data it didn't write. Not that useful to know, but cool nonetheless.
The filesystem we'll use is ext2 because every Android (and your main Linux) kernel should support it. To setup the filesystem:
Make sure that is executed such that
linux.img is in the current directory. Now this
filesystem exists, but we can't mount it. As I said before, only block devices can be mounted. Enter
the magic of loop devices:
This creates a block device at
/dev/loop256 whose only purpose is to point to files and
make them look like block devices. The exact meaning of the arguments eludes me.
losetup is what tells our loop device to point to the image of the
filesystem we just made. Now mount the filesystem in the usual way.
I'm going to assume you're experienced enough with Linux to know or figure what the above means, but
the effect is to make the filesystem inside
linux.img accessible as a regular old
linux. We are ready to extract the OS into this folder:
3. Sending the Image to the Device
DING! Your image is ready to go. Make sure your android device is connected with USB, unmount the image, and push it to the device:
Of course it doesn't matter how the image gets into the device, but this method is convenient and reasonably speedy.
4. Mounting the Image on the Device
Crack open your Android terminal app and gain root like so:
You may be prompted to allow your app super user permissions, which you need to allow. Mounting the image on the device is the exact same process as above:
Now is a good time to double check that there is a root filesystem with sane folders (i.e. bin, usr,
lib, etc...) within the
5. Mounting Other Filesystems
The following makes the chrooted Linux system play nice with the real OS (Android). Replace
/sdcard/linux with wherever you mounted
chroot into the image
Now to see if all this work pays off:
If everything is working, you should be presented with the default prompt for Arch. It's likely that
there may be some glitch's due to environment variables that are inherited your Android shell
session. For me, I had to set the
/bin to actual execute any
commands. I also got weird shell behavior until I set the
TERM to something like
xterm and set the
Quick tip: set the contents of the
/etc/resolv.conf file to
22.214.171.124. This enables DNS lookups (through Google's DNS) within your chroot.
The rest is up to you. You can use it like any other Arch Linux system that only has text. One of the first things I would suggest is to script the process of mounting, chrooting, and setting up the shell because those get reset whenever the device or shell resets (except mounting which persists until reboot).
chrooted environments like ours are fascinating to me. We have a Linux system within a Linux system which grants us special advantages. Because chrooting is only changing the appearance of the filesystem to applications, system calls still go to the real (Android) kernel. This means memory management, filesystems, graphics, sound, drivers, and everything else done by the kernel is still done with the native Android kernel, which is ideal in my situation because struggling with drivers on your phone would be a nightmare.
However, the userspace of Android is absolutely hopeless. It is there to support dalvik (which runs all your apps) and not a whole lot else. The biggest place this is apparent is their use of a standard C library called bionic. This means standard Linux binaries will not work on Android even if they are targeting the right version of ARM. A recompile is necessary with the Android Native Development Kit (NDK) which is not designed for compiling standard Linux applications.
This is where installing the chrooted environment finds its use. The standard libraries are fully
compatible with Android. All we had to do was make them available. With chrooting, it is easy to
call any of the standard (linked against glibc) binaries and trick the linker into using our
standard library. With this, all packages we get with
pacman work out of the box, and
anything we compile that targets the correct instruction set of ARM will run natively within the