Md at

tales of a debian maintainer

Installing Debian on the Sheevaplug

This document explains how to use deboostrap --foreign to build from scratch and install a minimal Debian system on the Sheevaplug (but it is equally applicable to many other embedded systems).

The only piece missing to be able to install from bare metal is a working kernel and initramfs pair, so this document assumes that you already have a kernel which can mount the root file system from a USB key. For the Sheevaplug, the factory kernel in the internal NAND flash will work fine.

The Debian kernel package puts us in a chicken and egg situation: it cannot mount the root without an initramfs (because all drivers are modular), but we cannot build one until we can boot the system. I suppose that, as an exercise of style, somebody could create a minimal initramfs with busybox and the kernel modules needed to mount the root and then mount it manually, but if you really lack a working kernel then it's probably faster to boot the file system image for the first time using qemu and the "versatile" debian-installer target.

The first step is to run the first stage of debootstrap on another system (which does not need to be ARM), to build a temporary root file system. I use the --variant and --include options to build the smallest possible system with network support, but they can be omitted.

debootstrap \
         --foreign --arch=armel \
         --variant=minbase \
                   net-tools,ifupdown,iproute,whiptail,vim-tiny \
         sid ./target/

As usual when using debootstrap, some manual configuration is needed:

cd target/
echo > etc/hostname
vi etc/network/interfaces
vi etc/resolv.conf
echo LANG=C > etc/default/locale
echo ' localhost' > etc/hosts
cat <<END > etc/fstab
/dev/root / ext3 noatime 0 1
tmpfs /tmp tmpfs defaults 0 0
#/tmp /var/tmp none bind 0 0
#tmpfs /var/run tmpfs defaults 0 0
#debugfs /sys/kernel/debug/ debugfs defaults 0 0

I took some hints from to reduce writes to the flash file system:

# the blkid cache is evil anyway
ln -s /dev/null etc/
# this link will be created anyway by the package
ln -s /var/lib/initscripts/nologin etc/nologin
# it's better to not use a static mtab with modern kernels
ln -s /proc/mounts etc/mtab
# unless you plan to use multiple removable network interfaces, persistent
# interface names are not needed
: > etc/udev/rules.d/75-persistent-net-generator.rules

Two small workarounds are needed:

# if this is not set then the preinst of linux-image-* will die trying
# to ask a debconf question in the debootstrap second stage
echo 'do_initrd = yes' > etc/kernel-img.conf

# a workaround for bug #520742
: > etc/udev/disabled

Now you can format a USB pen drive and copy the root file system on it:

mke2fs /dev/sdb1
tune2fs -i 0 -c 0 /dev/sdb1

mount /dev/sdb1 /mnt/
rsync -aH target/ /mnt/
umount /mnt/

After powering the plug press a key to get to the U-Boot prompt and use the factory kernel to boot from USB:

setenv bootargs console=ttyS0,115200 root=/dev/sda1 rootdelay=10 panic=10 init=/bin/bash
run bootcmd

Then you can run the second stage of debootstrap, finish the bare minimal configuration and start init:

./debootstrap/debootstrap --second-stage
# disable the gettys for /dev/tty[1-6], which do not exist
vi /etc/inittab
# and add one for the serial console
echo 'T0:2345:respawn:/sbin/getty -L ttyS0 115200 linux' >> /etc/inittab
# do not forget to set the root password or you will not be able to login...
vi /etc/shadow
rm /etc/udev/disabled
exec /bin/bash
mount / -o ro,remount
exec /sbin/init

Congratulations, now you can login on the system and start to install the packages you like:

echo 'deb unstable main' > /etc/apt/sources.list
echo 'APT { Install-Recommends "false"; };' > /etc/apt/apt.conf.d/no-recommends
apt-get update

# dash is much faster
apt-get install dash
dpkg-divert --add /bin/sh
ln -sf dash /bin/sh

# I do not like these, YMMV
rm /vmlinuz /initrd.img
rmdir /selinux /srv

# the kernel is able to read the time from the RTC by itself, and this
# will allow using a read only root
echo HWCLOCKACCESS=no >> /etc/default/rcS
# faster boot
echo CONCURRENCY=shell >> /etc/default/rcS
# useless on this platform
mv /etc/rcS.d/ /etc/rcS.d/

dpkg-reconfigure tzdata

apt-get install openssh-server screen iptables wget less

U-Boot requires that the kernel and initramfs have a special header:

apt-get uboot-mkimage
cd /boot/
mkimage -A arm -O linux -T kernel  -C none -a 0x00008000 -e 0x00008000 \
  -n Linux-2.6.29-2 -d vmlinuz-2.6.29-2-kirkwood uImage
mkimage -A arm -O linux -T ramdisk -C gzip -a 0x00000000 -e 0x00000000 \
  -n initramfs -d initrd.img-2.6.29-2-kirkwood uInitrd

Now you can reboot and configure u-boot to boot from the USB device. This is the variables scheme I like and it is not mandatory in any way, so I recommend that you read and understand the existing configuration before modifying it (some lines have been broken for readability):

setenv bootargs_nand $(bootargs)
setenv bootcmd_nand $(bootcmd)
setenv bootargs_root root=/dev/sda1
setenv bootargs_misc 'ro panic=10
setenv bootcmd_usb 'usb start; ext2load usb 0:1 0x00200000 /boot/uImage;
  ext2load usb 0:1 0x01100000 /boot/uInitrd'
setenv bootcmd 'setenv bootargs $(console) $(bootargs_root) $(bootargs_misc)
  $(bootargs_more); run bootcmd_usb; bootm 0x00200000 0x01100000'

Since now you are not using anymore the Marvell kernel tree it is mandatory to set these two variables and reboot:

setenv mainlineLinux yes
setenv arcNumber 2097

Installation to SD is identical, but requires an updated version of U-Boot with SD support. Due to a kernel bug which prevents autoloading the driver you will need to add mvsdio and mmc_block to /etc/initramfs-tools/modules and rebuild the initramfs.

(Yes, the naming theme I use at home is "african dictators"...)


This is the blog of Marco d'Itri.

1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30          

See also:

My blogroll:

W3C HTML 4.01
W3C CSS 2.0     

Powered by