#!/bin/sh
# This script uses debootstrap to create a directory containing a stage2
# root area to be copied onto the target machine where on startup it will
# automatically be run to complete installation.
# It presumes that the target already has a way of booting a linux kernel.

# Lee McLouglin lee@lmmrtech.com

# Where to get Debian files from - pick one local to you!
url=http://ftp.uk.debian.org/debian

# This probably should not change unless you have a local repo
secure_url=http://security.debian.org/

# Unless you really know what you are doing then dont change the arch or dist
arch=armel
root=$arch-root
dist=lenny

# This MUST match the version of the kernel you are using on your target
kernel_version=2.6.35

# Either set eth=static and then also address, netmask and gateway
# OR set eth=dhcp
# Comment out which ever you are NOT using
# Target machine network details
eth=static
address=192.168.1.90
netmask=255.255.255.0
gateway=192.168.1.1
#eth=dhcp

# Target hostname
newhostname=debarm

# Optional extra packages
# Do NOT just fill this in with tons of packages. Many packages expect a
# complete system to run in and will fail in the cut-down stage2 system
extra_debs=openssh-server

# For fstab on target
root_partition=/dev/mmcblk0p2
root_fstype=ext4
root_fsargs=noatime

#
# DONT CHANGE ANYTHING BELOW HERE!!!!!!!!
#

# Comma seperated list to pass to debootsrap
extra_debs_required=udev

case "$(id -u)" in
0) ;;
*) echo "I must be run as root"
   exit 1
   ;;
esac

case "$1" in
-u) echo Will try to update an existing $root
   ;;
*)
   if [ -d $root ]; then
     echo $root already exists
     exit 1
   fi
   ;;
esac

case "$root" in
*arm*) ;;
*) echo "root variable seems wrong!"
   exit 1 ;;
esac

mkdir $root

case "$extra_debs" in
'') include="$extra_debs_required" ;;
*)  include="$extra_debs_required,$extra_debs" ;;
esac

echo Running debootstrap to retrieve the basic system for arch $arch
debootstrap \
	--verbose \
	--keep-debootstrap-dir \
	--print-debs \
	--download-only \
	--arch $arch \
	--include=$include \
	--foreign \
	$dist $root $url

cd $root

case "$(pwd)" in
*arm*) ;;
*) echo "pwd seems wrong!"
   exit 1 ;;
esac

# debootstrap doesn't create these

file=dev/console
echo Creating $file
mknod -m 600 $file c 5 1

file=etc/fstab
echo Creating $file
echo "$root_partition / $root_fstype $root_fsargs 0 1" > $file
echo "proc /proc proc none 0 0" >> $file

file=etc/hosts
echo Creating $file
echo "127.0.0.1 localhost $newhostname" > $file

file=etc/hostname
echo Creating $file
echo "$newhostname" > $file

#echo Creating inittab with just enough to get a shell and run debootstrap
#echo "id:1:initdefault:" > etc/inittab
#echo "si:1:respawn:/bin/bash -i" >> etc/inittab

file=etc/inittab
echo Creating $file to run stage2 automatically
echo "id:1:initdefault:" > $file
echo "si:1:respawn:/stage2" >> $file

#file=etc/apt/sources.list
#echo Creating $file
#echo "deb $url $dist main" > $file

file=etc/timezone
echo Creating $file
cp /$file $file

file=etc/localtime
echo Creating $file
cp /$file $file

file=etc/network/interfaces
echo Creating $file
case "$eth" in
static)
cat > $file <<EOF
# Used by ifup(8) and ifdown(8). See the interfaces(5) manpage or
# /usr/share/doc/ifupdown/examples for more information.

# We always want the loopback interface.
#
auto lo
iface lo inet loopback

auto eth0
iface eth0 inet static
  address $address
  netmask $netmask
  gateway $gateway

#auto eth0
#iface eth0 inet dhcp
EOF
;;
dhcp)
cat > $file <<EOF
# Used by ifup(8) and ifdown(8). See the interfaces(5) manpage or
# /usr/share/doc/ifupdown/examples for more information.

# We always want the loopback interface.
#
auto lo
iface lo inet loopback

#auto eth0
#iface eth0 inet static
#  address $address
#  netmask $netmask
#  gateway $gateway

auto eth0
iface eth0 inet dhcp
EOF
;;
*) echo Unknown ethernet type: $eth, aborting
   exit 1
   ;;
esac

file=etc/inittab.full
echo Creating $file
cat > etc/inittab.full <<EOF
# /etc/inittab: init(8) configuration.

# 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 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

# I always want a login on the console!
1:2345:respawn:/sbin/getty 115200 ttyS0

EOF

file=stage2
echo Creating $file script - run on first boot of target
cat > $file <<EOF
#!/bin/sh
# This script was created by the $0 script by Lee McLoughlin lee@lmmrtech.com
# It is ONLY to be used to install the 2nd stage of a debootstrap
echo
echo
echo Starting \$0
echo
echo
echo About to configure and install all required packages. This may take a while
echo
./debootstrap/debootstrap --second-stage

#echo
#echo
#echo Change root password
#echo
#passwd root

echo Cleaning /dev/.udev for udev
rm -rf /dev/.udev

echo Installing full inittab
# First move aside the temporary inittab
mv /etc/inittab /etc/inittab.stage2
# Now put the real one in place
mv /etc/inittab.full /etc/inittab

file=/etc/apt/sources.list
echo Creating \$file
echo "deb $url $dist main" > \$file
echo "deb-src $url $dist main" >> \$file

echo "deb $secure_url $dist/updates main" >> \$file
echo "deb-src $secure_url $dist/updates main" >> \$file

dir=/lib/modules/$kernel_version
file=\$dir/modules.dep
echo Creating empty \$file
mkdir -p \$dir
touch \$file

# Make sure that the stage2 script is not run accidentally
chmod 400 /stage2

echo
echo rebooting into Debian
echo "(Ignore any error about not being able to set the clock)"
echo
sync;sync;reboot
EOF
chmod 500 $file

cat <<EOF

If you are networking booting then make sure you have $root set as 
the root filestore area and boot the target.

If you are booting using an SD card then clean the SD and copy
the contents of $root to the root partition, usually the 1st, on the SD.
  e.g.: 
    mke2fs /dev/SOMEDISKn
    mount /dev/SOMEDISKn /MOUNTPOINT/debarm
    cp -rp $root/. /MOUNTPOINT/debarm
    sync
    sync
    umount /MOUNTPOINT/debarm

When you boot the target you will probably see a lot of kernel messages then
stage2 will automatically be started.

This will unpack and install all the required packages. Once completed it
will reboot into multi-user Debian with networking.

You can login as root with no password.

I STRONGLY advise that your first steps are to set a root password and then
to run:

apt-get update
apt-get install locales
dpkg-reconfigure locales

EOF

