NSLU2-Linux
view · edit · print · history

How to build a new Debian/NSLU2 image

Debian developers, please flesh out this page. We want this page to be instructions for experienced NSLU2-Linux developers to build the absolute latest Debian packages, kernel and installer for the NSLU2-Linux target devices (with the intention being to make it easy to add support to Debian for a new device, or a new kernel feature).

General Notes

  • The instructions on this page assume that you are running Debian on your build machine.
  • These instructions are currently preliminary - this wiki page is a work in progress (as are all wiki pages by definition).

Cross-compilation toolchain

First, if want to compile the kernel on any machine other than an arm-based architecture, you need to build yourself a cross-compilation toolchain. A cross-compilation toolchain is recommended because compilation of the kernel on the NSLU2 will take many many hours. There are three options listed here for obtaining a cross-compilation toolchain.

emDebian

(I haven't tested this on lenny, only in a sid chroot.)

emDebian has been developed specifically for this purpose, and apparently works well these days. To use emDebian, add

deb http://www.emdebian.org/debian/ unstable main

and install the cross-compilation toolchain (example for armel shown)

apt-get install libc6-armel-cross libc6-dev-armel-cross binutils-arm-linux-gnueabi gcc-4.1-arm-linux-gnueabi

Create your own cross-compilation toolchain

(This procedure works for etch - I have not got it working for lenny yet.)

You can also manually create a toolchain by following the instructions at http://wiki.debian.org/BuildingCrossCompilers. Note that you will have to redo the manual procedure every time gcc or binutils is updated. Rod Whitby has very kindly automated the steps required to build this toolchain in a Makefile which works great!

crosstool

You can also compile yourself a cross-compilation toolchain for arm by using crosstool 0.43. It take about 1 hour on a intel P4 2.6 Ghz. When you have done, don't forget to add your new cross-compilation toolchain into your path.

Instructions for building the Debian kernel

The Debian Linux Kernel Handbook is a good resource if you get stuck.

This section uses 2.6.18 as an example, because it was the latest kernel version at the time of writing. The instructions for building the kernel depend on whether the source is obtained from the subversion repository or from a released version of a Debian kernel.

Source code from the Debian subversion repository

The example used here checks out the trunk version of the Debian kernel support code from the Debian repository. If you want another distribution (e.g. sid), replace 'trunk' with 'sid' in the instructions below. Note that trunk or sid may not always build.

Create a directory (e.g. ~/src), and change directories to your new directory. Download the appropriate kernel source tar ball from the Debian Build Server and unpack it in ~/src. Note that the kernel tarball must have a version number x.y.z, not x.y.z.a, because the Debian patches apply against the original release of a particular kernel version.

$ mkdir ~/src
$ cd ~/src
$ wget http://kernel-archive.buildserver.net/debian-kernel/pool/main/l/linux-2.6/linux-2.6_2.6.20.orig.tar.gz
$ tar xzvf linux-2.6_2.6.20.orig.tar.gz

Change directories to the Linux Kernel source directory, and check out the Debian Linux kernel support source tree from the subversion repository

$ cd linux-2.6-2.6.20
$ svn co svn://svn.debian.org/svn/kernel/dists/trunk/linux-2.6/debian debian

Install the build-dependencies for the linux-2.6 package.

$ sudo apt-get build-dep linux-2.6

Source code from a released Debian kernel

To download the source code for the latest kernel for a distribution (e.g. stable, testing, or unstable) either use apt-get, e.g.

$ apt-get -t [stable | testing | unstable] source linux-2.6

or download the .tar.gz, .diff.gz, and .dsc files for the kernel from a Debian mirror or from the Debian linux-source package page and unpack the source using dpkg, e.g.

$ wget http://ftp.debian.org/debian/pool/main/l/linux-2.6/linux-2.6_2.6.18-6.dsc \
       http://ftp.debian.org/debian/pool/main/l/linux-2.6/linux-2.6_2.6.18.orig.tar.gz \
       http://ftp.debian.org/debian/pool/main/l/linux-2.6/linux-2.6_2.6.18-6.diff.gz
$ dpkg-source -x linux-2.6_2.6.18-6.dsc linux-2.6.18-6
$ cd linux-2.6.18-6

You can also checkout a released version of the Debian kernel from the subversion repository by finding the revision number of the version using the checkin comments at http://svn.debian.org/wsvn/kernel. If you do this, then follow the instructions for setting up the build environment in "Source code from the Debian subversion repository" above.

Customizing and building the kernel

From this point on, the instructions are the same. There are three methods for customizing and building the kernel presented here. The first is completely manual, the second uses make menuconfig and friends, and the third uses make-kpkg.

Manually customize and build the kernel
  • The kernel defconfig files are under debian/arch and are organized by architecture (arm, i386, etc.) and flavour (e.g. for the arm architecture: iop32x, ixp4xx, etc.). For example, kernel options for all arm architecture flavours are in debian/arch/arm/config, and kernel options specific to the ixp4xx flavour are in debian/arch/arm/config.ixp4xx. Kernel config options for all architectures are in debian/arch/config. Remember to make check the Kconfig dependencies.
  • Kernel patches are in debian/patches. Patch application is controlled by the files in debian/patches/series/. The file names in this directory refer to the Debian kernel source revision number, and the patches in these files are applied in the order listed. To enable a patch, precede the patch file name with a '+', and to disable a patch, precede the patch file name with a '-'. Make changes to the kernel source by adding new patches to debian/patches, and then add the patch to the latest revision file in debian/patches/series.

Once you are happy with your changes, compile the kernel using the Debian make files. For example, to compile the arm ixp4xx kernel, do

$ cd ~/src/linux-2.6-2.6.18
$ fakeroot debian/rules clean
$ fakeroot debian/rules debian/control
$ fakeroot debian/rules debian/build debian/stamps > ../kernel-build.log 2>&1
$ fakeroot make -f debian/rules.gen binary-arch-arm-none-ixp4xx >> ../kernel-build.log 2>&1

For other makefile targets, look in debian/rules.gen. The list of currently supported flavours for arm can be found in debian/arch/arm/defines.

Using make menuconfig to customize the kernel

Another way of customizing the kernel configuration is to use the setup build rules, and make menuconfig and friends.

$ cd ~/src/linux-2.6-2.6.18
$ fakeroot debian/rules clean
$ fakeroot debian/rules debian/control
$ fakeroot debian/rules debian/build debian/stamps > ../kernel-build.log 2>&1
$ fakeroot make -f debian/rules.gen setup-arm-none-ixp4xx >> ../kernel-build.log 2>&1
$ cd debian/build/build-arm-none-ixp4xx/
$ make ARCH=arm menuconfig
$ cd ../../..
$ fakeroot make -f debian/rules.gen binary-arch-arm-none-ixp4xx >> ../kernel-build.log 2>&1
Using make-kpkg
apt-get source linux-2.6
cp /boot/config-2.6.26-1-ixp4xx .config (in kernel source root)
make ARCH=arm oldconfig or make ARCH=arm silentoldconfig
make-kpkg --rootcmd=fakeroot --revision=0 \
   --append-to-version=-custom --arch=armel \
   --cross-compile=/usr/bin/arm-linux-gnueabi- kernel-image --initrd

Installing the kernel

The methods above will result in a Debian package in the directory above the current directory, e.g.

linux-image-2.6.18-3-ixp4xx_2.6.18-6_arm.deb

Copy the .deb file to the NSLU2 and install the package: dpkg -i pkgname.deb

Build the Debian Installer

Instructions for building the Debian Installer can be found at http://wiki.debian.org/DebianInstaller/Build. Other useful documents are http://people.debian.org/~fjp/talks/debconf6/paper/ and http://kitenet.net/~joey/blog/entry/my_debian-installer_test_methods.html.

Daily builds of the installer for ARM are at http://people.debian.org/~kmuto/d-i/images/daily/ but are not guaranteed to work. The status of the daily builds are at http://people.debian.org/~joeyh/d-i/build-logs.html.

Here are some preliminary instructions on building a Debian installer image for the NSLU2. They are a bit cryptic because they are pretty much a dump of my notes. I will get round to polishing them soon.

Build and install the kernel that you want use with the installer

Build udebs...
Download linux-kernel-di-arm-2.6.dsc and linux-kernel-di-arm-2.6.tar.gz
apt-get install kernel-wedge fakeroot gcc
dpkg-source -x linux-kernel-di-arm-2.6_1.7.dsc
cd linux-kernel-di-arm-2.6-1.7/
vi kernel-versions
Remove all kernel versions except flavour ixp4xx
Change kernel version to the version desired/built
dpkg-buildpackage -rfakeroot -d -b
-d ignores unmet build-depends (required if you are changing the version of the kernel used)

Build the installer image...
apt-get source debian-installer or check out a copy from the subversion repository
cd debian-installer-yyyymmdd or installer
cp ../*.udeb build/localudebs/

Edit build/config/arm.cfg

Add any udebs to build/pkg-lists/netboot/local if the kernel version you want to use with 
the installer doesn't match the version of the kernel in testing/unstable
ext3-modules-${kernel:Version}
md-modules-${kernel:Version}
nic-modules-${kernel:Version}
scsi-core-modules-${kernel:Version}
usb-storage-modules-${kernel:Version}

sudo apt-get build-dep debian-installer

fakeroot make build_ixp4xx_netboot

The image will be in build/dest/ixp4xx/netboot and will be called di-nslu2.bin

Modify an existing installer image initramfs

Rather than building the install image yourself, depending on what you want to do, it may be easier to use an existing image and modify the initramfs. To do this, follow these instructions.

Unpack the image with slugimage

$ slugimage -u -i di-nslu2.bin

Endian swap the init ramdisk

$ devio '<< ramdisk.gz; xp $ 4' > ramdisk-swap.gz

Unpack the ramdisk as root

$ su -c 'mkdir initrd'
$ cd initrd
$ su -c 'zcat ../ramdisk-swap.gz | cpio -i'

Modify the ramdisk in the way that you want. NB, make all of your changes as root. For instance, to copy the NPE-B microcode to the ramdisk you would do (1/12/2007 These instruction are obsolete, but still work.)

$ cd initrd
$ cd lib
$ su -c 'mkdir firmware'
$ cd firmware
$ su -c 'cp <path to microcode>/NPE-B.01000201 .'
$ su -c 'ln -s NPE-B.01000201 NPE-B'

Then regenerate the ramdisk. Run the following commands in the root directory of the ramdisk.

$ find . | cpio --quiet -o -H newc | gzip -9 > ../new-ramdisk-swap.gz
$ cd ..

Pad to 6291440 bytes (6*1024*1024 - 16) and endian swap the new ramdisk

$ dd if=new-ramdisk-swap.gz of=new-ramdisk-swap-pad.gz ibs=6291440 conv=sync
$ devio '<< new-ramdisk-swap-pad.gz; xp $ 4' > new-ramdisk.gz

Create new di image

$ slugimage -L apex.bin -r new-ramdisk.gz -k vmlinuz -p -o di-nslu2-new.bin
$ sudo upslug2 -i di-nslu2-new.bin

Note: If you are building your own kernel, you must byte-swap it too before using it with slugimage:

$ devio '<< vmlinuz; xp $ 4' > vmlinuz-swap

Adding NPE driver to an existing Debian Installer image

The Intel NPE microcode is not DFSG compliant, and therefore cannot be distributed with the official Debian Installer images. Thus the NPE driver is not included in the official Debian installer image. This section documents the procedure to add the driver and microcode to an existing Debian Installer image so that you don't have to use a USB to Ethernet adapter to install Debian.

You need to manually download the nic-modules-....udeb and unpack it. It can be found at http://packages.debian.net/unstable/nic-modules-2.6.18-4-ixp4xx-di/arm/download (version name used in the script may be out of date). You will also need the NPE microcode 'NPE-B.01000201', one place to obtain it is from the current debian installer past the click through license on this site. Alternatively, follow the instructions from the accesslib README. You can extract it by following the script below up to the 'add firmware' section. Place the NPE microcode, nic-modules-....udeb and the di-nslu2.bin in a directory, cd to that directory and run the script below.

Also, because depmod is not run afterwards, you need to add a script that manually loads the module. Something like:

$ make-kpkg --arch arm --cross-compile arm-linux-gnu- binary-arch
cat > lib/debian-installer-startup.d/S05ixp400
#!/bin/sh

depmod
modprobe ixp4xx_mac || true
^D

chmod +x lib/debian-installer-startup.d/S05ixp400

Putting all of the above together, a script can be created to add the firmware and nic modules to a nightly build of the debian-installer

#!/bin/bash
set -e

# unpack the firmware
mkdir di-unpack
cd di-unpack
slugimage -u -i ../$1
devio '<< ramdisk.gz; xp $ 4' > ramdisk-swap.gz

#unpack the initramfs
mkdir initrd
cd initrd
zcat ../ramdisk-swap.gz | cpio -i

#add the npe modules
dpkg-deb -x ../../nic-modules-2.6.18-4-ixp4xx-di_1.8_arm.udeb .

#add the firmware
mkdir lib/firmware
cp ../../NPE-B.01000201 lib/firmware/
cd lib/firmware
#make link in firmware dir
ln -s NPE-B.01000201 NPE-B
cd ../..

#update module dependencies
depmod -b `pwd` 2.6.18-4-ixp4xx

#ensure the driver gets loaded
cat <<EOF > lib/debian-installer-startup.d/S05ixp400
#!/bin/sh

modprobe ixp4xx_mac || true

EOF
chmod 0755 lib/debian-installer-startup.d/S05ixp400

# build a new initramfs
find . | cpio --quiet -o -H newc | gzip -9 > ../new-ramdisk-swap.gz
cd ..

# pad to 6*1024*1024 - 16 bytes and byte swap
dd if=new-ramdisk-swap.gz of=new-ramdisk-swap-pad.gz ibs=6291440 conv=sync
devio '<< new-ramdisk-swap-pad.gz; xp $ 4' > new-ramdisk.gz

# build new firmware
slugimage -L apex.bin -r new-ramdisk.gz -k vmlinuz -p -o ../di-nslu2-ixp4xx_npe.bin

Copy the above into a file (e.g. add_npe_driver.sh) and run as root with bash ./add_npe_driver.sh di-nslu2.bin. This will create the modified image in di-nslu2-ixp4xx_npe.bin