#!/bin/sh
# This is a special init for the boot floppy image.
# It loads the main d-i initrd from either a second floppy, or a USB
# storage device.
#
# Throughout we use BOOT_DEBUG to turn on debugging. 1 = minimal,
# 2 = set -x, with 3 you'll get shells in strategic places.
#
# INSTALL_MEDIA_DEV can be passed as a boot parameter to force only 
# one device or set of devices to be scanned.

# The identification of this floppy and the desired root floppy.
SYSTEM=debian-installer
LABEL="boot floppy"
ROOT_LABEL="root floppy"

abort () {
	echo $1 >&2
	echo "Giving up!" >&2
	sleep 5000
	exit
}

debugshell () {
	if [ "$BOOT_DEBUG" -gt 2 ]; then
		echo "This is a debug shell ($1)."
		sh
	fi
}

if [ "$BOOT_DEBUG" -gt 1 ]; then
	set -x
fi

if [ -n "$INSTALL_MEDIA_DEV" ] && echo "$INSTALL_MEDIA_DEV" | grep -qv floppy; then
	NO_FLOPPY=1
fi
if [ -n "$INSTALL_MEDIA_DEV" ] && echo "$INSTALL_MEDIA_DEV" | grep -qv scsi; then
	NO_SCSI=1
fi

mount -t proc proc proc

modprobe vfat >/dev/null
modprobe loop >/dev/null

debugshell "before hardware detection"

if [ ! "$NO_FLOPPY" ]; then
	modprobe floppy >/dev/null
fi
if [ ! "$NO_SCSI" ]; then
	if [ -x /usr/sbin/usb-discover ]; then
		/usr/sbin/usb-discover
	fi
	# This is currently needed or usb-storage won't load (for ide_fix_driveid).
	modprobe ide-core >/dev/null
	modprobe usb-storage >/dev/null
	modprobe sd_mod >/dev/null
fi

debugshell "after hardware detection"

echo
echo
echo
echo
echo

LOADED=0
while [ "$LOADED" = 0 ]; do
	MOUNTED=0
	while [ "$MOUNTED" = 0 ]; do
		echo
		echo "Insert the $ROOT_LABEL or plug in a USB storage device."
		GOTLINE=0
		while [ "$GOTLINE" = 0 ]; do
			OLDPRINTK=$(cat /proc/sys/kernel/printk)
			echo 0 > /proc/sys/kernel/printk
			echo -n "Press Enter when ready, or type a command: "
			read line
			echo $OLDPRINTK > /proc/sys/kernel/printk
			if [ -n "$line" ]; then
				# inexpensive and easy and it makes this a lot more flexible!
				eval "$line" || true
			else
				GOTLINE=1
			fi
		done

		# Look for any storage devices we can find.
		# Only ones that we have modules loaded for should exist,
		# so this is not at brute-force as it may seem.
		# It's done each time through the loop as USB devices may
		# be inserted at any time.
		DEVS=""
		if [ -z "$INSTALL_MEDIA_DEV" ]; then
			if [ -d /dev/floppy ]; then
				DEVS=/dev/floppy/?
			fi
			if [ -d /dev/scsi ]; then
				DEVS="$DEVS `find /dev/scsi`"
			fi
		else
			DEVS="`find $INSTALL_MEDIA_DEV`"
		fi
		
		ERR=""
		for dev in $DEVS; do
			if [ "$MOUNTED" = 0 ] && [ -b $dev ]; then
				# XXX as a mount point, /floppy is not
				# quite right, as this may be USB storage,
				# whatever.
				if mount $dev -o ro -tvfat floppy 2>/dev/null; then
					if [ -e floppy/disk.lbl ] && grep -q "^System: " floppy/disk.lbl; then
						if ! grep -q "^System: $SYSTEM$" floppy/disk.lbl; then
							ERR="$ERR; $dev: not a $SYSTEM floppy"
						elif grep -q "^Label: $LABEL$" floppy/disk.lbl; then
							ERR="$ERR; $dev: still the $LABEL"
						else
							cat floppy/disk.lbl
							MOUNTED=1
						fi
					else
						echo "The disk has no label, continuing anyway."
						MOUNTED=1
					fi
					if [ "$MOUNTED" = 0 ]; then
						umount floppy || echo "umount failed!"
					fi
				else
					ERR="$ERR; $dev: cannot mount"
				fi
			fi
		done

		if [ "$MOUNTED" = 0 ]; then
			if [ -n "$ERR" ]; then
				# ERR begins with a semicolon
				echo "Cannot find $ROOT_LABEL$ERR"
			else
				echo "No devices found!"
			fi
		fi
	done

	if grep -q tmpfs /proc/filesystems; then
		mount -t tmpfs -o size=100M tmpfs mnt
	else
		mount -t shm shm mnt
	fi
	
	echo -n "Loading.."
	# pipe_progress adds dots to the above line while there is
	# activity. But we must be sure to catch errors from the zcat.
	# Hard to do in a pipeline..
	rm -f /tmp/zcat_failure
	(zcat floppy/initrd.gz || echo 1 > tmp/zcat_failure ) | pipe_progress > mnt/tmp-initrd || abort "failed to extract initrd (may be out of space on ram disk)"
	if [ ! -e /tmp/zcat_failure ]; then
		LOADED=1
	else
		rm -f /tmp/zcat_failure
		echo "install media seems to be bad!" >&2
		debugshell "bad media mounted"
		umount mnt
	fi
	umount floppy
done

echo "Setting up filesystem..."
umount /initrd # the original initrd
mount -o loop mnt/tmp-initrd /initrd
cp -a /initrd/* mnt || abort "failed copying filesystem (may be out of space on ram disk)"
rm -f mnt/tmp-initrd
umount /initrd

debugshell "filesystem loaded and set up"

# dev will be unmounted by rcS
umount proc

echo "Starting the installer..."
cd mnt
pivot_root . initrd
mount -t proc proc proc
mount -t devfs devfs dev

# If this is missing, things can get *really* weird.
if [ ! -x /usr/sbin/chroot ]; then
	abort "Bad initrd! Cannot chroot."
fi

# Close all open files on the initrd, and run busybox init.
rm -f sbin/init # probably not busybox init
ln -s ../bin/busybox sbin/init
debugshell "before chroot"
exec /usr/sbin/chroot . /sbin/init <dev/console >dev/console 2>&1
