And we’re marching on.
Here’s a little recap of my Nexus 7 kernel development efforts so far.
For my grandma’s world famous kernel-pie, you’ll need:
- abootimg to create/unpack/update the boot image
- buildroot to compile a basic initrd that can be flashed with a kernel. Lazy pricks can find one here (no warranties!!!).
- fastboot to flash/boot your stuff. Instead of messing around with the source code, you can just grab the binary (if you don’t have it already). Please note that Google only distributes 32-bit versions (old-school, baby!!!). Debian jessie has a package android-tools-fastboot (native 64bit!) available.
- Optionally, my version of bootimg.cfg – it has earlyprintk enabled.
- A stock image of *shudder* Android (flo [WiFi] is codenamed razor, deb [3G version] is called razorg… d’uh). Any version should do, all we need is boot.img. Plus it’s always good to keep it handy for debugging purposes (e.g. in case one of the proprietary firmware blobs … has paths hardcoded).
- crosstool-ng to generate the cross compiler. Since ct-ng relies on GNU software to handle the build process, it can be a bit temperamental on OSX hosts. Also, clang turned out to be quite a diva and I had to install a whole bunch of extra libraries and tools on the Mac trying to get it to work on OSX. To reduce potential issues, I opted to go back to using a virtual machine running debian jessie. Lazy pricks can download a prebuilt 64bit cross-toolchain here (no warranties!!!).
The kernel is a bit more tricky. Up until version 3.16 (linux-next), there is no support for the APQ8064 platform. Currently, linux-next compiles fine (with some patchwork) and boots up nicely, but that’s about it. The guys from CodeAurora have their own fork of the the linux-next repo over at linaro.org where they stage their additions before submitting them to kOrg in the tree integration-linux-qcomlt.
Since I don’t want to duplicate the kernel developers’ work load (and hell will freeze over before I submit someone else’s patches as mine), I decided to stick with the linaro-tree / integration-linux-qcomlt for now.
Building the toolchain
Grab yourself a recent enough release of ct-ng (1.18.0 if you’re feeling a little queazy, git-master if you got balls) and configure it.
Main things to set:
- Architecture: armv7-a
- Target CPU: cortex-a5 (imo, only available in git-master, cortex-a9 should do fine as well)
- Tune CPU: cortex-a5 (see above)
- FPU: neon-vfpv4
- To save yourself time, point the kernel-headers to where you checked out your kernel sources
- If your make version is >3.91, you’ll need this patch for now, otherwise eglibc will complain about make being too old.
Adapting the code
Whoever came up with the idea of device trees: THANK. YOU. For one, it is a blessing for hardware manufacturers – create one basic template and just turn on the stuff you need for a specific board / device. Second, it forces those manufacturers to play by kernel standards (at least more than hardcoded BSPs), making all our lives so much easier. Just for the fun of it, look at this commit, which removes TONS of code Realtek submitted to get their RTL8187SE chip to play nice with the kernel, as a patch with roughly 1.500 loc was submitted and you’ll get an idea how messy unvetted, vendor supplied BSPs can be.
Tell the kernel we’re working in the qcom-dominion:
Then, copy arch/arm/boot/dts/qcom-apq8064-ifc6410.dts to arch/arm/boot/dts/qcom-apq8064-nexus7.dts.
Edit arch/arm/boot/dts/qcom-apq8064-nexus7.dts and set the model / compatible strings accordingly.
It doesn’t matter what you call it, but just make sure you extend the struct qcom_dt_match in arch/arm/mach-qcom/board.c accordingly.
Edit qcom-apq8064-nexus7.dts – best of luck, that’s where I’m stuck at the moment 😀
Compile your dtb with
Final touches on the kernel
The guys over at #armlinux mentioned, that the bootloader will hand over incorrect memory mappings. In order to counter that, you need this little gem, which shifts the memory info in the atags by 2MB.
Compile the fixup with
gcc -c fixup.S -o fixup.o objcopy -O binary fixup.o ~/minefield/fixup.bin
Since the Nexus 7 lk bootloader no likey device trees, you need to attach the dtb-blob to the kernel, which needs to be prepended by the fixup. Makes me feel like Dr. Frankenstein every time I test a new blob…
cat ~/minefield/fixup.bin arch/arm/boot/zImage \ arch/arm/boot/dts/qcom-apq8064-nexus7.dtb > ~/minefield/zImage.dtb
Compiling the boot.img
Fastboot / lk either contain a bug or the usage-message is misleading, but the Nexus 7 won’t boot the kernel itself; you have to pack it together with an initrd. Grab one of Android’s stock boot.img, disassemble it with abootimg to get a hold of the bootimg.cfg and then fumble it back together:
abootimg --create ~/minefield/kernel_boot.img \ -k ~/minefield/zImage.dtb \ -r ~/minefield/rootfs.cpio.gz \ -f ~/minefield/bootimg.cfg
Then have fastboot load the image and boot it. This way, your flashed kernel will be left untouched and you can just reset the device in case something went wrong:
fastboot boot ~/minefield/kernel_boot.img
If you did everything right, you’ll see your serial console spring to life.
- Support for some of the Nexus hardware is still at a very early stage so critical bits like the PMIC8921 extender are still being discussed on the kernel mailing lists. Unfortunately, especially the PM8921 is crucial to get the USB-Port and various other tidbits to work
- The bootloader hands over a lot of hardcoded parameters. It is yet unclear if they will cause issues. It seems telling the kernel to ignore the bootloader cmdline and only use its own cmdline is the only way to get rid of the garbage.
- …I’m sure there’s plenty more lurking around the corner!