Android m5 on HTC Apache
Android m5 on the HTC Apache
This is still a work in progress, errors will be corrected as I move forward, as I’m writing this from memory until I can retrace each step in detail there’s bound to be a few.
Prerequisites:
- Linux Kernel 2.6.21 (Vanilla)
- Google Android SDK version m5
- A build system (Ubuntu 8.04 or other Debian distro recommended for easy toolchain setup)
- arm-linux-gnueabi- cross compiler
- HaRET 0.5.2 – Hardware reverse engineering tool from Kevin O’Connor, this lets us boot linux from CE.
- An HTC Apache to fiddle with
- An SD card with at least 128MB of space
- A pretty solid knowledge of Linux (building custom kernels, initrd’s from scratch)
- Lots of coffee and patience
You will also need a bunch of scripts/patches from various places, I will be assembling them all in the downloads section of this site, and inserting them into this writeup.
Setting up a cross-compiling build environment is outside the scope of this writeup, for ease of configuration/setup I recommend using Ubuntu 8.04 and the binaries provided by the link above at emdebian, of all the options I tried, this was the most easy to configure and the most trouble free.
Section 0: Setup
- Ensure the above prerequisites are satisfied. The coffee is especially important
- Even though we won’t be building the source, follow the setup steps on this page for building Android, the prerequisites covered here in the “Setting up your machine” section will save you trouble/headaches later. The areas about setting up Repo can be skipped unless you’d like to grab the Android source to play around with as well.
- Setup your cross compile environment, if you used Ubuntu and the emdebian binaries, this is a simple step, otherwise, this might take you a while. Unless you’re a somewhat seasoned developer, I do not recommend attempting to build your own cross compiling toolchain.
- Once you have your cross compile environment setup, move on to section 1.
Section 1: Building the kernel
- Extract the kernel to a directory on your build system and cd to the extracted directory.
- Patch the kernel with this file using -p1. This file is a diff between a vanilla 2.6.21 kernel, and 2.6.21-hh20 from handhelds.org, but it also includes the patched in Android drivers from a google groups user (unknown) that backported the m5 drivers for the Nokia n8xx series phones. It also includes a patch to pxafb.c that I manually patched in from from android zaurus’ 2.6.23 fb patch.
- Run make htcapache_static_defconfig to create the default hanhelds.org HTC Apache static config.
- Run make menuconfig or make xconfig and enable the Android power, power stats, binder, and logger drivers that were patched in to the Drivers->Android section. Enable the option to compile using EABI, and allow support for older versions of EABI. You can play around with other settings, ymmv.
- Make sure you export your cross compile variables before building the kernel. Export ARCH=arm and export CROSS_COMPILE=arm-linux-gnueabi- if you’re using the emdebian toolchain.
- Run make, go get a cup of coffee. Set the completed kernel aside.
Section 2: Building the initial ramdisk
- Download this initrd. It was extracted from Kevin O’Connor’s Apache Linux Launcher and will save several steps as it contains the init script we need (modified), and the devices in the /dev directory. The initrd also contains a statically linked busybox executable from Benno Leslie’s blog.
- Rename the initrd to intird.gz and gunzip it, then cpio -iv < initrd in a separate directory.
- You’ll notice basic links for busybox in the bin directory, and a short init script derived from Kevin’s, there is no boot directory as it is not necessary when we’re booting from HaRET and chrooting immediately.
- Remove the existing library directory and switch to the directory of the kernel you built earlier. Make modules_install INSTALL_MOD_PATH=/path/to/extracted/initrd to drop the libraries for your kernel into the extracted initrd directory structure.
- This is the only step necessary, now rebuild your initrd with the following convenient script, it should be copied to the extracted initrd directory before execution:
#!/bin/sh # packInitrd 0.1 # uwe.gansert@suse.de # # creates an initrd of the actual directory # usage: packInitrd find . | cpio -H newc -o > /tmp/initrd.img gzip -c /tmp/initrd.img > /tmp/initrd mv /tmp/initrd ./ ls -l
Section 3: Extracting the Android Binaries from the SDK (Credit goes to elinux.org)
- Once the SDK is extracted, add the bin directory to your path.
- Create a faux sdcard image with:
mksdcard -l card 100M card.img
- Start the emulator with the sdcard you just created specified:
emulator -sdcard card.img -console -debug-kernel
- Once the emulator is running, execute the following at another terminal, this will push our statically linked busybox binary to the emulator:
adb -d 1 push busybox /data/busybox
- In the emulator console, create links to busybox for tar and bzip2, then tar/bzip2 the system and dev directories to the /sdcard directory, grab /etc, /sbin too, then call an explicit sync after you tar/bzip the files, make sure you got the init and init.rc as well.
- Shutdown the emulator and mount the sdcard image as a loopback device on your build system.
Section 4: Creating the root filesystem
While this is still in development, I’m providing instructions to create a 100MB image file manually rather than allowing HaRET to create the disk image from a compressed rootfs, when things get to the point of packaging for redistribution that may change. I’m using the same naming schemes used by O’Connor’s Apache Linux loader package.
- Create a blank 100MB file with dd if=/dev/zero of=./linux-root.img bs=1k count=100000
- Run mkfs.ext2 -F ./linux-root.img to create a filesystem on the image file
- Mount the image file -o loop
- Create a bin, var, and boot directory in the root of your new disk image
- Copy your zImage and initrd to /mydiskimage/boot
- cd to the directory you built your kernel in earlier and make modules_install INSTALL_MOD_PATH=/mydiskimage/ you should have a lib directory in your image root after this step
- Copy the statically linked busbox binary to the /sbin folder of you image, and create symbolic links for: ln, ls, cd, mkdir, chmod, chown, cat, mount, umount, e2fsck, fsck.ext2, ps, chroot, rm, mv, cp, modprobe, insmod, lsmod, umask, and anything I missed that the boot process complains is missing the first time you try this.
- Tar up the /dev directory from your initrd extraction area and untar it to the root of your new root fs
- ln -s sbin/busybox init from your image root to create an init link in the root directory that points to busybox, this will bring us up to a shell.
- Umount the image, copy it, your zImage, and initrd along with this startup.txt and HaRET 0.5.2 to your sdcard
- Run HaRET, wait…….. you should see the kernel start to load in a short while, if you get a screen in a bit that says “Press Enter to Activate this Console” and you ls a directory, you’re ready to move on to the next step.
- From here on out you pretty much have to pre-script anything you want to do, there’s no support for the codekey, I’m guessing there’s something that can be done about this but I haven’t researched it yet. A shell without forward slash or numbers, or hyphens or underscores really sucks though, makes for some creative workarounds…
Section 5: So you got the shell up and running, time for some Android…
- Extract the android files you tar’d up earlier to the linux-root.img
- Rename the original binary init you got from the SDK to androidinit and create a link named “init” in the image root, point it to busybox again
- Edit the init.rc and find the sections that define the zygote and runtime services, both have “autostart 1″, you want this to be “autostart 0″ for both
- Obtain a statically linked copy of strace, (thanks again Benno) and stick it in your sbin directory
- Boot to linux, run the “startandroid” script that’s in your sbin directory
- You’ll see the boot script output scroll by, then you’ll see a ton of debug output from strace, then the red cylon eye cycling back and forth
- Two or three minutes of that, and you should be looking at a semi-working android m5 desktop, have fun!
- Oh yeah rebooting, hold the codekey and use the arrows to shift to a terminal, type reboot. This will keep you from mangling the filesystem of your linux-root.img.
Section 6: Miscellaneous/Gotchas
- Switch between terminals etc slowly, it’s flaky and you may crash it
- Keys aren’t fully mapped, check out the keymap for android in the usr directory, I’ve added one or two to it
- I haven’t researched the terminal issues regarding not being able to codekey numbers or other special chars (essential!)
Section 7: File Roundup
- My own kernel with patched in goodies
- The initrd I built from Kevin O’Connor’s
- The patch for a vanilla 2.6.21 kernel
- A statically linked binary of strace courtesy of Benno Leslie iirc.
- A statically linked binary of busybox courtesy of Benno Leslie.
- The script to start android once you’re running off of your linux-root.img
- The haret startup.txt script for use with the kernel, initrd and linux-root.img
- A random cat
Section 8: Credits
Thanks to:
- Kevin O’Connor and the other Handhelds.org maintainers
- elinux.org for their Android on Omap information
- Android Zaurus (from Japan? whose pxa framebuffer patch made m5 possible)
- Benno Leslie (Computer science guy from Australia iirc) for his blog and code contributions, and pioneering work getting Android on devices it shouldn’t run on.
- Anyone else I forgot
I will correct/update this space constantly, keep checking back, I should have the files inserted within the next day, files are up!
Joey