A Physicist lost on the Web

Dumping my occasional ramblings on technology, science, music & the web.

An unexpected adventure: Updating a Sheevaplug to a new kernel

I'm the proud owner Sheevaplug, and for many years, it has been doing its duties faithfully, running Gentoo and serving music, git, svn, printers and many other useful things. This weekend, I finally decided to do a kernel update and replace my oldish 3.6.1 kernel with something more recent.

Well, after rebooting, it turns out that things are not as easy as I thought. I had already prepared myself for finally updating U-Boot (I was still running the ancient Marvell version which was preinstalled), but even after updating to the latest 2013.10.2 version from here, the darn thing refused to boot and just hung after "decompressing linux...".

Tl;dr

Want a >= 3.9 kernel on your sheevaplug? Bummer, won't work like it always did. Turns out you have to

  1. Make sure that flattened device tree is enabled (CONFIG_ARCH_KIRKWOOD_DT) — best start out with a fresh make kirkwood_defconfig)
  2. Activate CONFIG_ARM_APPENDED_DTB and CONFIG_ARM_ATAG_DTB_COMPAT
  3. Append the proper device tree blob to the zImage and rebuild the uImage

Part (3) is simplified by a little script I've posted below. Doing this, you stand a chance of getting a kernel image that actually gets further than "uncompressing..." and boots.

The full story

After some research, it turned out that things have gotten more complicated. Starting from 3.9, much of the machine-specific kernel code for all the different Kirkwood based devices in the kernel was replaced with something called flattened device tree. Basically, what happens is that the kernel is supplied with description of the hardware layout together with the command arguments, removing the need for hardcoding this information.

The device tree blob itself is created when the kernel is compiled and can be found under arch/arm/boot/dts/kirkwood-sheevaplug.dtb, but the bootloader is reponsible for loading it and passing it to the kernel. According to the U-Boot manual, the third argument of bootm is meant for this, but I couldn't get it to work, and some research leads to the suspicion that this functionality might simply be missing from the sheevaplug version (at least the one that I installed).

Luckily, it turns out the kernel overlords have foreseen this situation and have added a kernel option which makes the kernel use a device tree which is appended to the zImage instead of that passed by the bootloader. The parameter is called CONFIG_ARM_APPENDED_DTB and you can find it under 'Boot options -> Use appended device tree'. Be sure to also enable CONFIG_ARM_ATAG_DTB_COMPAT ("Supplement..." just below this option) — otherwise, the kernel will not use the command line supplied by the bootloader.

As it is not entirely trivial to build a uImage from the modified zImage, I have created a small shell script which does that job

#!/bin/sh

usage() {
   echo 'usage: build_kernel.sh /path/to/boot/stuff name'
   exit
}

image_path=$1
name=$2

zImage="/tmp/zImage.$name"
uImage="uImage.$name"

test -d "$image_path" || usage
test -n "$name" || usage

cat "$image_path/zImage" "$image_path/dts/kirkwood-sheevaplug.dtb" > "$zImage"
mkimage -A arm -O linux -C none  -T kernel -a 0x00008000 -e 0x00008000 \
   -n "$name" -d "$zImage" "$uImage"

Just pass the path to the generated zImage and device tree blob (arch/arm/boot in the kernel source directory) as first and the image name as second parameter. The result is uImage suitable for usage by U-Boot.

Using this configuration on top the kirkwood default configuration (make kirkwood_defconfig) has finally gotten me shiny new 3.15.2 kernel.

comments powered by Disqus