Cross-compiling Custom Kernels for Little Linux Plug Computers
Cross-compiling HappinessLittle Linux plug computers come ready-to-use. But they're still Linux, which means hackable. Today we learn how to build a custom kernel for a plug computer.
You can install gcc and other build tools on the plug itself, and build a kernel there, but it takes forever. You'll be much happier cross-compiling kernels on your fast desktop Linux system.
Get a compiler
Strangely, the ARM v.5 cross-compiler isn't available in many distros (two exceptions are Gentoo and NetBSD). The "armel" tools on Ubuntu only support ARM v.7 and greater. So you may need to go elsewhere.
You'll also need UBoot's mkimage program: package uboot-mkimage on Ubuntu or uboot-tools on Fedora. Or you can try building mkimage from source.
Download a kernel
A current Linux kernel from Kernel.org will usually build fine. Stick to 2.6.36 and later: there were some network driver issues in 2.6.35, and kernels before that didn't have device IDs for some of the newer plug models. Extract it in the usual way: tar xvf linux-18.104.22.168.tar.bz2.
You may choose to apply the plug-specific patches from sheeva.with-linux.com. However, the patches there don't always apply cleanly, and you may not actually need them. As I write this, the patches for 22.214.171.124 cover wireless access point mode (only important if you're going to be using your plug as a wireless router), SD cards (important if you have a plug model that uses them) and a default configuration for Guruplugs. It's your choice whether or not to try the patches.
Set up a kernel build environment
The next step is finding the right build flags. The kernel build uses the CROSS_COMPILE= argument to tell it where to look for the compiler and other important build components. This will be prepended to commands like gcc, ld and so forth.
Confused? Here's an example. Most of the ARM cross-compilers install everything into one subdirectory. Suppose you installed to /usr/local/CodeSourcery. Search there for a "bin" directory containing programs like gcc, ld etc.:
$ find /usr/local/CodeSourcery -name '*gcc' | grep bin /usr/local/CodeSourcery/Sourcery_G++_Lite/arm-none-eabi/bin/gcc /usr/local/CodeSourcery/Sourcery_G++_Lite/bin/arm-none-eabi-gcc
Okay, we have two candidates. Let's look at them:
$ ls /usr/local/CodeSourcery/Sourcery_G++_Lite/arm-none-eabi/bin README.txt ar as c++ g++ gcc ld nm objcopy objdump ranlib strip $ ls /usr/local/CodeSourcery/Sourcery_G++_Lite/bin arm-none-eabi-addr2line arm-none-eabi-gcc-4.4.1 arm-none-eabi-objdump arm-none-eabi-ar arm-none-eabi-gcov arm-none-eabi-ranlib arm-none-eabi-as arm-none-eabi-gdb arm-none-eabi-readelf arm-none-eabi-c++ arm-none-eabi-gdbtui arm-none-eabi-run arm-none-eabi-c++filt arm-none-eabi-gprof arm-none-eabi-size arm-none-eabi-cpp arm-none-eabi-ld arm-none-eabi-sprite arm-none-eabi-g++ arm-none-eabi-nm arm-none-eabi-strings arm-none-eabi-gcc arm-none-eabi-objcopy arm-none-eabi-stri
You might think the first directory looks simpler; but sadly, it won't work. In fact, /usr/local/CodeSourcery/Sourcery_G++_Lite/arm-none-eabi/bin/README.txt says clearly that the directory is only for internal use by the compiler and shouldn't be used directly.
So the right answer is:
CROSS_COMPILE=/usr/local/CodeSourcery/Sourcery_G++_Lite/bin/arm-none-eabi-Now the kernel build will use program names like /usr/local/CodeSourcery/Sourcery_G++_Lite/bin/arm-none-eabi-gcc. Adjust this for wherever you installed your cross-compiler.