There isnt much to it. Note that you have to have an OABI kernel i.e. and OABI toolchain (such as the one you can get off TimeSys, or create one using BuildRoot), since Debian ARM packages are OABI.
I really just followed the instructions at
http://www.aurel32.net/info/debian_arm_qemu.php - it probably helps if you are on Ubuntu to begin with. Then I choose 'base' install only while installing debian. Got the networking to work (as described on that site) and did a tar of the entire file system, copied to a NFS mounted host disk. It ends up being about 200MB or so.
Then it becomes a matter of shrinking it to a reasonable size. Mostly this consists of removing APT caches and locales. Finally I replace a few crucial files such as inittab, fstab, rc.local and hosts with my own - mostly these are copied from BuildRoot or OpenEmbedded attempts at building RFS's.
The jffs2 file end up being about 45MB - including Python, TCL, SQLite and some tools I needed (these were installed using apt-get on the QEMU host prior to tarring the file system.
Note there some referrence to OpenEmbedded in the clean-up script below. I am just using some tools from there, in particular mkfs.jffs2, nothing more. You can find those elsewhere.
40MB is acceptable to us - its about 3x bigger than OE's root filesystem but we plan to stick a 256MB chip on the board because we need some data storage. The big advantage I see is that we have other Linux nodes in our system that will run Ubuntu - so we get very similar environments on our embedded products as master nodes. Plus, you cant beat Debian for ARM package selection.
I see some major drawbacks. I still would like to eliminate udev. It really serves no purpose on an embedded system and slows down the boot sequence. First attempts at that have failed badly. Seem to me I should be able to prepare a /dev permanently. Mounting a JFFS2 is slow, and since I now need a 50MB partition instead of a 10MB partition, it is 5x slower. Lastly, the future is in EABI and unless Debian has an EABI repository... But for now we can not use EABI - without going into a lengthy explanation, a kernel compiled with EABI fails to serve VLAN ethernet devices properly...and after spending 2 days debugging the network stack, we cant work out why.
I added my inittab below the script:
#!/bin/sh
# run this as root !
# 19.03.2006
# Gertjan Hofman
#
# Script to post-install Honeywell specific changes to the pristine OpenEmbedded created filesystem
case $# in
1) echo ; echo Creating $1.jffs2 image ;;
*) echo "Usage: add_rfs_mod <OE tar filename> "
exit 1 ;;
esac
# set up variables:
# =================== START OF DEFINITIONS ====================
SUDO=""
# where the output root filesystem is:
ROOT=rootfs
# where our files are:
INSTALL_FILE_ROOT=$PWD/post_install_files
# location of OpenEmbedded created binaries
OE_TMP=/free/openembedded/openembedded/tmp
OE_I386_BIN=$OE_TMP/staging/i686-linux/usr/bin/
# location of OE output images (tar filesystem)
OE_IMAGES=$OE_TMP/deploy/glibc/images/at91sam9260ek/
# =================== END OF DEFINITIONS ====================
# create a folder and untar the QEMU RFS
$SUDO rm -rf ${ROOT}
$SUDO mkdir ${ROOT}
# ok - going into folder:
cd ${ROOT}
$SUDO tar -xf ../$1
# remove docs
echo "Removing doc/man pages"
$SUDO rm -rf usr/share/doc
$SUDO rm -rf usr/share/man
$SUDO rm -rf usr/share/doc-base
$SUDO rm -rf var/cache/apt
$SUDO rm -rf var/lib/apt/lists
$SUDO rm -rf var/log/installer/cdebconf
# save some locales (which one are we using ?)
# note: this is now done by using apt-get install localepurge on the QEMU host
# and running localepurge
echo "Purging locales"
$SUDO rm -rf usr/share/locale/fr
$SUDO rm -rf usr/share/locale/de
$SUDO rm -rf usr/share/locale/ru
$SUDO rm -rf usr/share/locale/pl
$SUDO rm -rf usr/share/locale/sv
$SUDO rm -rf usr/share/locale/es
$SUDO rm -rf usr/share/locale/ca
$SUDO rm -rf usr/share/locale/ja
$SUDO rm -rf usr/share/locale/tr
$SUDO rm -rf usr/share/locale/vi
$SUDO rm -rf usr/share/locale/cs
$SUDO rm -rf usr/share/locale/nl
$SUDO rm -rf usr/share/locale/hu
echo "Empty sys and proc"
# empty sys and proc
$SUDO rm -rf sys/*
$SUDO rm -rf proc/*
echo "cleaning udev"
# this gives problems..get rid of it.
$SUDO rm -f etc/udev/rules.d/*persistent-net.rules
$SUDO rm -f etc/udev/rules.d/*persistent-net-generator.rules
# remove dev udev remnants
$SUDO rm -fr dev/.udev
# remove kernel mods, we have none:
$SUDO rm -rf lib/modules/2.6.18-6-versatile
echo "Removing timezone info"
# remove timezone info we dont need:
$SUDO du -a usr/share/zoneinfo/ | grep -v America | awk '{print $2}' | xargs rm -rf
#entropy is low, so random blocks, but urandom never does...
echo "replacing dev/random with urandom"
$SUDO rm dev/random
$SUDO ln -s urandom dev/random
# re-instate some folder structures for apt in case we ever use apt-get
$SUDO mkdir var/cache/apt
$SUDO mkdir -p var/lib/apt/lists/partial
$SUDO mkdir -p var/cache/apt/archives/partial
echo "creating xauth dummy"
# create a dummy xauth file
$SUDO mkdir -p usr/X11R6/bin
$SUDO cp ${INSTALL_FILE_ROOT}/usr/X11R6/bin/xauth usr/X11R6/bin
OUTNAME=`date +%H-%M-%S-%F`
OUTNAME=`date +%Y-%m-%d-%H-%M`
echo Updating etc
$SUDO cp ${INSTALL_FILE_ROOT}/etc/fstab etc/
# add NFS mounts for testing:
#$SUDO echo "192.168.0.3:/arm /arm nfs exec,dev,suid 1 1" >> etc/fstab
#$SUDO echo "192.168.0.3:/home /pc_home nfs auto 0 0" >> etc/fstab
#$SUDO echo "/dev/mtdblock4 /permanent jffs2 auto,noatime 0 0" >> ${ROOT}/etc/fstab
# add serial to inittab
$SUDO echo "T3:23:respawn:/sbin/getty -L ttyS0 115200 vt100" >> etc/inittab
echo Updating host file
$SUDO echo "192.168.0.3 evo05 evolution05" >> etc/hosts
$SUDO echo "192.168.0.20 proto01" >> etc/hosts
$SUDO echo "192.168.0.21 proto02" >> etc/hosts
$SUDO echo "192.168.0.22 proto03" >> etc/hosts
$SUDO echo "192.168.0.23 proto04" >> etc/hosts
$SUDO echo "192.168.0.24 proto05" >> etc/hosts
$SUDO echo "192.168.0.25 proto06" >> etc/hosts
echo Creating mountpoints
# create mount points
$SUDO mkdir pc_home
$SUDO mkdir arm
$SUDO mkdir permanent
$SUDO mkdir mnt/flash01
$SUDO mkdir mnt/flash02
$SUDO mkdir mnt/flash03
# make a link to a partition which will be permanent - /dev/mtdblock4
# not sure this is a good idea...
#$SUDO ln -s /permanent/usr_local ${ROOT}/usr/local
echo Adding login pic
# add login pic:
$SUDO cp ${INSTALL_FILE_ROOT}/etc/issue etc/
$SUDO cp ${INSTALL_FILE_ROOT}/etc/issue.net etc/
$SUDO cp ${INSTALL_FILE_ROOT}/etc/inittab etc/
# copy over a small termcap file for ncurses (top, nano etc)
#$SUDO cp ${INSTALL_FILE_ROOT}/etc/termcap ${ROOT}/etc/
# add execution of /etc/rc.local:
#echo \
#"if [ -x /etc/rc.local ]; then
# echo \"Running local boot scripts (/etc/rc.local)\"
# /etc/rc.local
#fi"\
#>> ${ROOT}/etc/init.d/finish
echo "Copy over rc.local"
# copy over the rc.local file:
$SUDO cp ${INSTALL_FILE_ROOT}/etc/rc.local etc/
echo "Creating usr-local-bin with executables"
# create usr_local_bin:
$SUDO mkdir -p usr/local/bin
# copy over the ptpd executable:
$SUDO cp ${INSTALL_FILE_ROOT}/usr/local/bin/ptpd usr/local/bin
# copy over configure_vlan.tcl:
cp ${INSTALL_FILE_ROOT}/usr/local/bin/configure_vlan.tcl usr/local/bin/
# return to up directory.
cd ..
# finally, create RFS image
$SUDO rm -f $OUTNAME.jffs2
echo Creating filesystem
$SUDO ${OE_I386_BIN}/mkfs.jffs2 -x lzo \
--root=${ROOT} --faketime --output=$OUTNAME.jffs2 \
--pad --little-endian --eraseblock=0x20000 -n --squash-uids
echo Created $OUTNAME.jffs2 filesystem
======================= INITTAB ===================
# /etc/inittab: init(8) configuration.
# $Id: inittab,v 1.91 2002/01/25 13:35:21 miquels Exp $
# The default runlevel.
id:2:initdefault:
# Boot-time system configuration/initialization script.
# This is run first except when booting in emergency (-b) mode.
si::sysinit:/etc/init.d/rcS
# What to do in single-user mode.
~~:S:wait:/sbin/sulogin
# /etc/init.d executes the S and K scripts upon change
# of runlevel.
#
# Runlevel 0 is halt.
# Runlevel 1 is single-user.
# Runlevels 2-5 are multi-user.
# Runlevel 6 is reboot.
l0:0:wait:/etc/init.d/rc 0
l1:1:wait:/etc/init.d/rc 1
l2:2:wait:/etc/init.d/rc 2
l3:3:wait:/etc/init.d/rc 3
l4:4:wait:/etc/init.d/rc 4
l5:5:wait:/etc/init.d/rc 5
l6:6:wait:/etc/init.d/rc 6
# Normally not reached, but fallthrough in case of emergency.
z6:6:respawn:/sbin/sulogin
# What to do when CTRL-ALT-DEL is pressed.
ca:12345:ctrlaltdel:/sbin/shutdown -t1 -a -r now
# Action on special keypress (ALT-UpArrow).
#kb::kbrequest:/bin/echo "Keyboard Request--edit /etc/inittab to let this work."
# What to do when the power fails/returns.
pf::powerwait:/etc/init.d/powerfail start
pn::powerfailnow:/etc/init.d/powerfail now
po::powerokwait:/etc/init.d/powerfail stop
# /sbin/getty invocations for the runlevels.
#
# The "id" field MUST be the same as the last
# characters of the device (after "tty").
#
# Format:
# <id>:<runlevels>:<action>:<process>
#
# Note that on most Debian systems tty7 is used by the X Window System,
# so if you want to add more getty's go ahead but skip tty7 if you run X.
#
1:2345:respawn:/sbin/getty 38400 tty1
2:23:respawn:/sbin/getty 38400 tty2
3:23:respawn:/sbin/getty 38400 tty3
4:23:respawn:/sbin/getty 38400 tty4
5:23:respawn:/sbin/getty 38400 tty5
6:23:respawn:/sbin/getty 38400 tty6
# Example how to put a getty on a serial line (for a terminal)
#
#T0:23:respawn:/sbin/getty -L ttyAMA0 9600 vt100
#T1:23:respawn:/sbin/getty -L ttyS1 9600 vt100
# Example how to put a getty on a modem line.
#
#T3:23:respawn:/sbin/mgetty -x0 -s 57600 ttyS3
# for a serial term console:
T0:23:respawn:/sbin/getty -L ttyS0 115200 vt100