#!/usr/lib/klibc/bin/sh.shared
# 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.
#
# INSTALL_MEDIA_DEV can be passed as a boot parameter to force only 
# one device or set of devices to be scanned.

set -e

# Add klibc path
PATH=/usr/lib/klibc/bin:$PATH

# The identification of this floppy and the desired root floppy.
SYSTEM="debian-installer"
ROOT_LABEL="Root floppy"
ROOT_FS="ext2"

MODULE_DIR="/lib/modules/*"


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

mount -t proc proc proc
mount -t sysfs sysfs sys


# TODO: no modprobe in klibc
if ! insmod $MODULE_DIR/kernel/drivers/block/floppy.ko 2>/dev/null; then
	abort "Cannot load floppy module"
fi

makedev () {
    [ -e "$1" ] || mknod "$1" "$2" "$3" "$4"
}

mkdir -p 755 /dev

for i in 0 1 2 3 4 5 6 7; do
	if sys_dev=$(cat /sys/block/fd$i/dev 2>/dev/null); then
		case $sys_dev in
			2:0) makedev  /dev/fd"$i" b 2 0 ;;	    
			2:1) makedev  /dev/fd"$i" b 2 1 ;;	    
			2:2) makedev  /dev/fd"$i" b 2 2 ;;	    
			2:3) makedev  /dev/fd"$i" b 2 3 ;;	    
			2:128) makedev  /dev/fd"$i" b 2 128 ;;	    
			2:129) makedev  /dev/fd"$i" b 2 129 ;;	    
			2:130) makedev  /dev/fd"$i" b 2 130 ;;	    
			2:131) makedev  /dev/fd"$i" b 2 131 ;;
			*) echo "Unknown device major:minor for /dev/fd$i" ;;
		esac
	fi
done
debugshell "after hardware detection"

echo
echo
echo
echo
echo

# no grep in klibc, replaced by this horrible hack in sh
test_disk_lbl () {
    n=$1
    nb_words=$2
    str=$3
    shift 3
    shift $n
    if ([ "$nb_words" = "1" ] && [ "$str" = "$1" ]) || \
       ([ "$nb_words" = "2" ] && [ "$str" = "$1 $2" ])  || \
       ([ "$nb_words" = "3" ] && [ "$str" = "$1 $2 $3" ]) ; then
	    return 0
    fi
    return 1   
}

try_mount () {
    # TO REMOVE, there is a bug somewhere in the kernel, the first
    # mount command fail when changing floppy disk
    # so we have to launch mount twice
	local dev=$1
	local fs=$2
	local dir=$3
	mount -o ro -t $fs $dev $dir 2> /dev/null || true
	umount $dir 2> /dev/null || true
	if mount -o ro -t $fs $dev $dir 2> /dev/null; then
		return 0
	fi
	return 1
}

LOADED=0
while [ "$LOADED" = 0 ]; do
	MOUNTED=0
	nb_timeout=3
	while [ "$MOUNTED" = 0 ]; do
		echo
		echo "Insert the $ROOT_LABEL."
		
		OLDPRINTK=$(cat /proc/sys/kernel/printk)
		echo 0 > /proc/sys/kernel/printk
		echo -n "Press Enter when ready"
		if [ $nb_timeout = 0 ]; then
			echo -n ":"
			read line
		else
			# boot floppy has no USB keyboard driver
			# so we use a timeout instead
			READ_TIMEOUT=30 #seconds
			echo -n ", or wait $READ_TIMEOUT seconds: "
			if read -t $READ_TIMEOUT line; then
				# it is not a usb keyboard so
				# we no longer need a timeout
				nb_timeout=0
			else
				nb_timeout=$(($nb_timeout -1))
			fi
		fi
		echo ""
		echo $OLDPRINTK > /proc/sys/kernel/printk
		
		# 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
			DEVS=/dev/fd?
		elif [ -e "$INSTALL_MEDIA_DEV" ]; then
			DEVS="$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 try_mount $dev $ROOT_FS floppy; then
					if [ -e floppy/disk.lbl ] ; then
						disk_lbl=$(cat floppy/disk.lbl)
						if ! test_disk_lbl 0 1 "System:" $disk_lbl || \
							! test_disk_lbl 1 1 "$SYSTEM" $disk_lbl; then
							ERR="$ERR; $dev: not a $SYSTEM floppy"
						elif ! test_disk_lbl 2 3 "Label: $ROOT_LABEL" $disk_lbl; then
							ERR="$ERR; $dev: not the $ROOT_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 ! mount -t tmpfs -o size=100M tmpfs mnt 2>/dev/null && \
		! mount -t shm shm mnt 2>/dev/null; then
		echo "Cannot mount mnt"
		continue
	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..
	echo 0 > /tmp/zcat_failure
	cd mnt
	(zcat ../floppy/initrd.gz || echo 1 > /tmp/zcat_failure ) | cpio -i -V || \
	 abort "failed to extract initrd (may be out of space on ram disk)"
	cd ..

	if [ "$(cat /tmp/zcat_failure)" = 0 ]; then
		LOADED=1
	else
		echo "install media seems to be bad!" >&2
		debugshell "bad media mounted"
		umount mnt
	fi
	
	umount floppy
done

debugshell "filesystem loaded and set up"

# dev will be unmounted by debian-installer-startup
umount proc

echo "Starting the installer..."
exec run-init mnt /init
