First of all, this post is not about building an Angstrom distribution (Linux OS that is known to run well on embedded devices) from scratch. This about compiling a Linux kernel source which you can boot from using your Angstrom distro. I’m assuming that you already have a working Angstrom MMC with you. I used the one that came along with the BeagleBoard XM, pre-installed with Angstrom.
Before getting started, a few words regarding how the MicroSD card is structured. It has two partitions on it. A FAT partition and an ext partition. The FAT partition contains 4 files namely MLO, u-boot.bin, uEnv.txt and UIMAGE. The ext partition contains the root directory of the distribution. That means it contains ‘/‘.
The BeagleBoard boots from the Linux kernel within the /boot/ directory of the ext partition. That directory will contain a symbolic link called uImage which we will point to the kernel image we want the BB-XM to boot to.
It might be well to point out here that I tried 5 versions of the kernel from kernel.org and all of them failed to work and I was unable to debug the reason for that. However, it seems that there was a certain group of people working on patching up the kernel to make it compatible exactly for the BB-XM. We will be using their source in this post.
So let us get the tools ready. First you need to get the toolchain for doing the cross compilation. You can get it from here. Download the ones for ARM and GNU/Linux. You’ll need to register yourself to download it. Once downloaded, extract it to some convenient location and set your PATH environmental variable to point to there. Refer to the following figure:
Now we need to get the kernel source. As I said earlier, we are not going to use the source from kernel.org but instead, we are going to use the source from the following repository.
Clone that repository. At the time I was trying to compile the source, the stable branch was the 3.0 one. So I’ll be using the same for demonstrating in this post. Clone that repository and checkout the 3.0 branch. To checkout, run:
git checkout origin/beagleboard-3.0 -b beagleboard-3.0
Once you have checked out that branch, run the patch.sh file there.
It will fetch a few patches and apply them in the source. Once you are through with that, you need to setup the configuration of the kernel. Normally, we do this by using the default omap2plus_defconfig configurationgiven in the kernel source but, try as I might, it did not work for me. Hence we will use the config file created by running the patch.sh file as our kernel configuration. But first, after running the patch file, your directory will look like below:
You can see the configurations that the kernel provides. You can see omap2plus_defconfig there. Now I will explain the 4 steps of kernel compilation.
We need to give the kernel configuration. As stated before, we are going to use the configuration created by the patch.sh file. In order to do this, copy the configuration from the /patches/ directory to the .config file under the kernel source. Assuming you are in the kernel source directory (as given in the above figure) you would do:
cp ../patches/beagleboard/defconfig .config
However, keep in mind that this is not the standard way of doing things. Usually, we do the following:
make -j2 ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- <defconfig>
Where <defconfig> should be replaced by whichever configuration you want from the /arch/arm/configs/ directory.
We can access the configuration file of the kernel as a menu and manipulate several options such as which all modules we want enabled as well as whether certain modules should be compiled as ‘built-in’ to the kernel or compiled as a separate module. In order to get the menu, we do:
make -j2 ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- menuconfig
After making the necessary changes, save and quit.
Now we actually compile and make the Linux kernel image.
make -j2 ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- uImage
This will take a while. Once it is finished, you can get the kernel image called uImage under the /arch/arm/boot/ directory. Copy this image into the /boot/ directory of the ext partition of the MicroSD card. After copying, get the symbolic there called uImage to point to our new image. You can do this by:
sudo ln -sf <destination> <source>
Once that is done, we proceed to the next step.
Here we compile the corresponding modules of the kernel separately. In oder to do this, you run:
make -j2 ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- modules
This will also take a while depending on how many modules you selected to be compiled in the menuconfig interface. Once this is finished, you have to install these modules. For that, you do:
make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- INSTALL_MOD_PATH=<path to where you mounted the mmc root diectory> modules_install
This will install the compiled modules under /lib in the path given. The path that I would give in my system would be /media/Narcissus-rootfs. Refer to the following figure. You can see the different directories corresponding to the different versions of the kernel I tried compiling.
Now everything is set. There are a few more points to note however. You can find the following line in the uEnv.txt file within the FAT partition.
Change it into
One more thing. Within the /etc/inittab file of your MicroSD card’s root directory, you can find the following line:
S:2345:respawn:/sbin/getty 115200 ttyS2
Chang it into:
S:2345:respawn:/sbin/getty 115200 ttyO2
Basically, what you did in the above two steps is to replace the places where ttyS2 is present with ttyO2. I think this is because kernel versions from 2.6 onwards use ttyO2 as their console. If you do not do the above change, you might get the following error in the middle of booting the kernel:
INIT: Id “S” respawnin too fast: disabled for 5 minutes
You are good to go. You can now boot from the new kernel.