Resolving mysterious kernel/firmware problems via apt-get install firmware-linux

If you recently upgraded your kernel to the 2.6.29 Debian package, you might have noticed some (e.g. graphics) drivers stopped working or are working slower. In my case, this was the radeon driver, which inexplicably seemed to cause lots of slowdowns in some applications and games. A quick look into dmesg revealed the reason:

  [drm] Initialized radeon 1.29.0 20080528 on minor 0
  agpgart-intel 0000:00:00.0: AGP 2.0 bridge
  agpgart-intel 0000:00:00.0: putting AGP V2 device into 4x mode
  pci 0000:01:00.0: putting AGP V2 device into 4x mode
  [drm] Setting GART location based on new memory map
  [drm] Loading R200 Microcode
  platform radeon_cp.0: firmware: requesting radeon/R200_cp.bin
  radeon_cp: Failed to load firmware "radeon/R200_cp.bin"
  [drm:radeon_do_init_cp] *ERROR* Failed to load firmware!

As noted in the changelog file, the radeon firmware R200_cp.bin has been removed from the kernel, and is now available in the separate firmware-linux Debian package. So the simple fix for this issues is:

  $ apt-get install firmware-linux
  $ dpkg -L firmware-linux | grep R200_cp.bin
  /lib/firmware/radeon/R200_cp.bin

After restarting X, the dmesg output looks more sane again:

  agpgart-intel 0000:00:00.0: AGP 2.0 bridge
  agpgart-intel 0000:00:00.0: putting AGP V2 device into 4x mode
  pci 0000:01:00.0: putting AGP V2 device into 4x mode
  [drm] Setting GART location based on new memory map
  [drm] Loading R200 Microcode
  platform radeon_cp.0: firmware: requesting radeon/R200_cp.bin
  [drm] writeback test succeeded in 2 usecs

Coreboot hacking: How to solder a PLCC socket on your board

Desoldering station.

When trying to port coreboot (previously LinuxBIOS) to a new mainboard you're often confronted with a big problem: the BIOS/ROM chip on the respective motherboard is soldered onto the board (i.e., not in a socket).

This means that you cannot easily (hot-)swap the chip during development or for recovery purposes. So you basically have exactly one try to flash the ROM chip with a fully working/booting coreboot image. If that goes wrong your board is bricked.

Desoldering the chip

This makes it pretty much impossible to develop a coreboot port for such boards (and soldered-on ROM chips are becoming more and more common, unfortunately).

However, I've recently tried to replace the soldered-on (PLCC) ROM chip on one of my boards with a socket. What sounds pretty scary at first, especially given that I have almost non-existant soldering skills, turned out to be really not that hard. Also, it can be done with relatively cheap and readily available equipment.

I have written a short HOWTO for desoldering chips and soldering on sockets in the coreboot wiki, and also finished a video showing most of the process, which I hope will be helpful for others:

Place the PLCC chip


The video is CC-BY-SA 3.0, music is taken from ccmixter.org and is CC-NC 3.0 licensed. Video editing was done using Kino (which uses ffmpeg2theora for Ogg Theora export).

I also tried to upload the video to Vimeo, but first they told me to install the Flash 10 abomination (and there's no way I will do that). After browsing the help/forum pages a bit I found a traditional, non-flash upload form, but that then tells me that I cannot upload Ogg Theora videos. WTF?

Soldering the socket

The Ogg Theora video support feature request has been open for more that a year. Until that issue is fixed I'll just use other video services, thanks...

Building an ARM cross-toolchain with binutils, gcc, newlib, and gdb from source

I've been planning to write about building custom ARM toolchains for a while (I used stuff from gnuarm.com in the past, but I switched to the lastest and greatest upstream versions at some point). Among other things, recent upstream versions now have ARM Cortex support.

First you will need a few base utilities and libs:

  $ apt-get install flex bison libgmp3-dev libmpfr-dev autoconf texinfo build-essential

Then you can use my tiny build-arm-toolchain script, which will download, build, and install the whole toolchain:

  $ cat build-arm-toolchain
  #!/bin/sh
  # Written by Uwe Hermann <uwe@hermann-uwe.de>, released as public domain.

  TARGET=arm-elf                         # Or: TARGET=arm-none-eabi
  PREFIX=/tmp/arm-cortex-toolchain       # Install location of your final toolchain
  PARALLEL="-j 2"                        # Or: PARALLEL=""

  BINUTILS=binutils-2.19.1
  GCC=gcc-4.3.3
  NEWLIB=newlib-1.17.0
  GDB=gdb-6.8

  export PATH="$PATH:$PREFIX/bin"

  mkdir build

  wget -c http://ftp.gnu.org/gnu/binutils/$BINUTILS.tar.bz2
  tar xfvj $BINUTILS.tar.bz2
  cd build
  ../$BINUTILS/configure --target=$TARGET --prefix=$PREFIX --enable-interwork --enable-multilib \
    --with-gnu-as --with-gnu-ld --disable-nls
  make $PARALLEL
  make install
  cd ..
  rm -rf build/* $BINUTILS $BINUTILS.tar.bz2

  wget -c ftp://ftp.gnu.org/gnu/gcc/$GCC/$GCC.tar.bz2
  tar xfvj $GCC.tar.bz2
  cd build
  ../$GCC/configure --target=$TARGET --prefix=$PREFIX --enable-interwork --enable-multilib \
    --enable-languages="c" --with-newlib --without-headers --disable-shared --with-gnu-as --with-gnu-ld
  make $PARALLEL all-gcc
  make install-gcc
  cd ..
  rm -rf build/* $GCC.tar.bz2

  wget -c ftp://sources.redhat.com/pub/newlib/$NEWLIB.tar.gz
  tar xfvz $NEWLIB.tar.gz
  cd build
  ../$NEWLIB/configure --target=$TARGET --prefix=$PREFIX --enable-interwork --enable-multilib \
    --with-gnu-as --with-gnu-ld --disable-nls
  make $PARALLEL
  make install
  cd ..
  rm -rf build/* $NEWLIB $NEWLIB.tar.gz

  # Yes, you need to build gcc again!
  cd build
  ../$GCC/configure --target=$TARGET --prefix=$PREFIX --enable-interwork --enable-multilib \
    --enable-languages="c,c++" --with-newlib --disable-shared --with-gnu-as --with-gnu-ld
  make $PARALLEL
  make install
  cd ..
  rm -rf build/* $GCC

  wget -c ftp://ftp.gnu.org/gnu/gdb/$GDB.tar.bz2
  tar xfvj $GDB.tar.bz2
  cd build
  ../$GDB/configure --target=$TARGET --prefix=$PREFIX --enable-interwork --enable-multilib
  make $PARALLEL
  make install
  cd ..
  rm -rf build $GDB $GDB.tar.bz2

The final toolchain is located in /tmp/arm-cortex-toolchain per default, and is ca. 170 MB in size. I explicitly created the build script in such a way that it minimizes the amount of disk space used during the build (ca. 1.2 GB or so, compared to more than 3 GB in the "naive" approach).

Using the "-j 2" option for make (see script) you can speed up the build quite a bit on multi-core machines (ca. 30 minutes vs. 60 minutes on an AMD X2 dual-core box). Also, you can change the script to build for other target variants if you want to (arm-elf or arm-none-eabi, for example).

Checkout the blog entry How to build arm gnu gcc toolchain for Mac OS X by Piotr Esden-Tempski for similar instructions for Mac OS X users.

Oh, and while I'm at it — does anybody have any idea why there are no pre-built toolchains for embedded (microcontroller) ARM targets in Debian? There are some toolchains for other microcontroller architectures (avr, m68hc1x, h8300, z80) but not too much other stuff. Is there some specific reason for the missing ARM toolchains (other than "nobody cared enough yet")?

I have heard about Emdebian, but from a quick look that seems to be more intended for toolchains with Linux/libc, not for microcontroller firmware (i.e. no MMU, no Linux, no libc etc.), but maybe I'm wrong?

How to use the full size of your (x)term when connecting to some other box serially with minicom

minicom terminal size 1

Just as a reminder for myself, as I'll probably need this more often in the future (and maybe it's helpful for others):

Per default, if you use a big xterm (232x74 in my case) where you start minicom, the $COLUMNS and $LINES environment variables will be 80x24 nevertheless, and those applications which honor them (vim, for example) will be too small and not use the full xterm size of 232x74.

  $ minicom
  $ echo $COLUMNS; echo $LINES
  80
  24

minicom terminal size 2

You can fix that like this:

  $ eval `resize`
  $ echo $COLUMNS; echo $LINES
  232
  74

After you do eval `resize` the variables are updated and vim will use the full xterm size. That's all.