#!/bin/sh
#
# initramfs /init (busybox ash)
#

# color codes and some predefined texts
BOLD="\033[1m"
NORM="\033[0m"
RED="\033[31m"
GREEN="\033[32m"
YELLOW="\033[33m"
BLUE="\033[34m"
OK="${BOLD}${GREEN}OK${NORM}"
FAILED="${BOLD}${RED}FAILED${NORM}"
DONE="${BOLD}${GREEN}DONE${NORM}"

# helper functions

# check an exit value and print a colored status
checkReturn() {
	if [ $? -ne 0 ]
	then
		echo -e $FAILED
	else
		echo -e $OK
	fi
}

# print a colored done status
echoDone() {
	echo -e $DONE
}

# create tmpfs structure with mountpoints for squashfs and installation media
create_tmpfs() {
	echo -e -n " ${BOLD}${BLUE}*${NORM} Creating and mounting tmpfs... "
	mkdir /.tmpfs
	mount -t tmpfs tmpfs /.tmpfs
	checkReturn
	mkdir /.tmpfs/.cdrom
	mkdir /.tmpfs/.squashfs
}

# search for and mount the cdrom device
find_and_mount_cdrom() {
	echo -e " ${BOLD}${BLUE}*${NORM} Searching for the CRUX CD..."
	CRUXCD=""
	CDROM_DEVICES="`grep 'drive name:' /proc/sys/dev/cdrom/info | cut -d: -f2`"
	for DEV in $CDROM_DEVICES
	do
		DEV="/dev/$DEV"
		mount -r -t iso9660 $DEV /.tmpfs/.cdrom
		if [ $? -eq 0 ]
			then
			echo -e -n "   ${BOLD}${GREEN}*${NORM} Found media on $DEV"
			if [ -e /.tmpfs/.cdrom/crux-cd ]
			then
				echo ", CRUX CD."
				CRUXCD=$DEV
				ln -s $DEV /dev/cdrom
				break
			else
				echo ", but it's not the CRUX CD."
				umount /.tmpfs/.cdrom
			fi
		else
			echo -e "   ${BOLD}${YELLOW}*${NORM} No media found on $DEV."
		fi
	done
}

# makes sure there is an installation media in /.tmpfs/.cdrom
check_installation_media() {
	# check if the cdrom was mounted properly. if not, spawn a shell
	if [ ! -e /.tmpfs/.cdrom/crux-cd ]
	then
		echo -e " ${BOLD}${RED}*${NORM} The CRUX CD was not properly mounted!"
		echo " Spawning a shell for you to attempt to fix this problem. If"
		echo " you are able to find your cdrom device, mount it at"
		echo " /.tmpfs/.cdrom and then log out of this shell to continue."
		echo " If you are NOT able to fix the problem, installation will"
		echo " not be possible."
		echo
		/bin/sh
	fi

	# check again and stop if it's still not there
	if [ ! -e /.tmpfs/.cdrom/crux-cd ]
	then
		echo -e " ${BOLD}${RED}*${NORM} The CRUX CD still appears not to be"
		echo " found and installation will not continue."
		echo
		sleep 99999
		exit 1
	fi
}


# populate a tmpfs from the squashfs image in /.tmpfs/.cdrom
# and prepare /newroot for switch_root at the end of the script
copy_squashfs() {
	echo -e -n " ${BOLD}${BLUE}*${NORM} Mounting squashfs filesystem... "
	mount -r -t squashfs -o loop /.tmpfs/.cdrom/crux.squashfs /.tmpfs/.squashfs
	checkReturn

	echo -e " ${BOLD}${BLUE}*${NORM} Populating root filesystem..."
	mkdir -p /newroot
	echo -e -n "   ${BOLD}${BLUE}*${NORM} Mounting new root filesystem... "
	mount -t tmpfs tmpfs /newroot
	checkReturn
	echo -e -n "   ${BOLD}${BLUE}*${NORM} Copying files from squashfs... "
	cp -af /.tmpfs/.squashfs/* /newroot/
	checkReturn
	echo -e -n "   ${BOLD}${BLUE}*${NORM} Copying devices from rootfs... "
	cp -af /dev/* /newroot/dev/
	checkReturn
	mkdir -p /newroot/dev/pts /newroot/cdrom

	echo -e -n " ${BOLD}${BLUE}*${NORM} Unmounting squashfs filesystem... "
	umount /.tmpfs/.squashfs
	checkReturn
	rmdir /.tmpfs/.squashfs

	# disassociate the loopback device associated with the squashfs filesystem
	/bin/losetup -d /dev/loop0

	# the cdrom gets unmounted here and remounted after switch_root
	umount /.tmpfs/.cdrom
	rmdir /.tmpfs/.cdrom

	echo -e -n " ${BOLD}${BLUE}*${NORM} Unmounting tmpfs... "
	umount /.tmpfs
	checkReturn
	rmdir /.tmpfs
}

# main script
echo ""
echo -e "${BOLD}CRUX 2.6 - ${BLUE}http://crux.nu/${NORM}"
echo ""

exec >/dev/console </dev/console 2>&1

echo -e -n " ${BOLD}${BLUE}*${NORM} Mounting "
echo -e -n "${BOLD}${GREEN}/proc${NORM}"
mount -t proc proc /proc

PRINTK="`cat /proc/sys/kernel/printk`"
echo "0" > /proc/sys/kernel/printk

echo -e ", ${BOLD}${GREEN}/sys${NORM}."
mount -t sysfs sysfs /sys

echo -e -n " ${BOLD}${BLUE}*${NORM} Populating /dev via mdev... "
mdev -s
checkReturn
echo -e -n "   ${BOLD}${BLUE}*${NORM} Registering mdev as hotplug agent... "
echo "/bin/mdev" > /proc/sys/kernel/hotplug
checkReturn

if [ -d /lib/modules ]
then
	echo -e -n " ${BOLD}${BLUE}*${NORM} Loading modules... "
	# IDE support
	modprobe ide-core

	# general cdrom/disk support
	modprobe cdrom
	modprobe ide-cd_mod
	modprobe ide-gd_mod
	modprobe sr_mod
	modprobe sd_mod

	# IDE
	load_ide_modules() {
		echo -e -n "${BOLD}${BLUE}IDE${NORM}"
		for mod in aec62xx alim15x3 amd74xx atiixp \
			cmd64x cs5520 cs5530 cs5535 ide-pci-generic hpt366 it8213 \
			it821x jmicron ns87415 opti621 pdc202xx_new piix rz1000 sc1200 \
			serverworks siimage sis5513 slc90e66 tc86c001 triflex trm290 \
			via82cxxx
		do
			modprobe $mod
		done
		echo -n ", "
	}

	# SCSI
	load_scsi_modules() {
		echo -e -n "${BOLD}${BLUE}SCSI${NORM}"
		for mod in scsi_transport_fc scsi_transport_iscsi scsi_transport_sas \
			scsi_transport_spi 3w-9xxx 3w-xxxx 53c700 BusLogic NCR53c406a a100u2w \
			aacraid advansys aha152x aha1542 aha1740 aic79xx aic7xxx aic94xx arcmsr \
			atp870u dc395x dmx3191d dpt_i2o dtc eata fdomain gdth hptiop in2000 \
			initio ipr ips lpfc megaraid megaraid_mbox megaraid_sas nsp32 pas16 \
			psi240i qla1280 qla2xxx qla4xxx qlogicfas qlogicfas408 seagate \
			sim710 stex sym53c416 sym53c8xx t128 tmscsim u14-34f ultrastor \
			wd7000 mptsas mptspi
		do
			modprobe $mod > /dev/null 2>&1
		done
		echo -n ", "
	}

	# USB
	load_usb_modules() {
		echo -e -n "${BOLD}${BLUE}USB${NORM}"
		for mod in ehci-hcd ohci-hcd uhci-hcd sl811-hcd usb-storage usbhid
		do
			modprobe $mod
		done
		echo -n ", "
	}

	# SATA
	load_sata_modules() {
		echo -e -n "${BOLD}${BLUE}SATA${NORM}"
		for mod in libata ata_piix sata_promise sata_sil sata_svw sata_via sata_nv \
			sata_sx4 sata_sis sata_uli sata_qstor ahci
		do
			modprobe $mod
		done
		echo -n ", "
	}

	# FireWire
	load_firewire_modules() {
		echo -e -n "${BOLD}${BLUE}FireWire${NORM}"
		for mod in core ohci sbp2
		do
			modprobe firewire-$mod
		done
		echo -n ", "
	}

	grep -q "libata" /proc/cmdline
	C1=$?
	grep -q "sata" /proc/cmdline
	C2=$?
	if [ $C1 -eq 0 -o $C2 -eq 0 ]
	then
		MODORDER="sata ide scsi usb firewire"
	else
		MODORDER="ide sata scsi usb firewire"
	fi

	for MODS in $MODORDER
	do
		grep -q "no$MODS" /proc/cmdline
		[ $? -ne 0 ] && load_${MODS}_modules
	done

	echoDone
else
	echo -e " ${BOLD}${YELLOW}*${NORM} No modules were found in the initial RAM filesystem."
fi

grep -q "initrd_debug" /proc/cmdline
if [ $? -eq 0 ]
then
	echo "initrd_debug specified. Here's a shell."
	echo "Boot process will continue when you exit the shell."
	/bin/sh
else
	grep -q "devicetimeout=*" /proc/cmdline
	if [ $? -eq 0 ]
	then
		for opt in `cat /proc/cmdline`
		do
			echo $opt | grep -q "devicetimeout"
			if [ $? -eq 0 ]
			then
				DEVTIMEOUT=`echo $opt | cut -d= -f2`
			fi
		done
	else
		DEVTIMEOUT=10
	fi
	echo -e " ${BOLD}${BLUE}*${NORM} Waiting $DEVTIMEOUT seconds for devices to settle..."
	sleep $DEVTIMEOUT
fi

create_tmpfs

# if root=/dev/XXX was specified on the command line, use that as the new root
# instead of searching for the cdrom and using it. if it fails, fall back to
# the cdrom
grep -E -q "(nfs)?root=." /proc/cmdline
if [ $? -eq 0 ]
then
	#echo "root= or nfsroot= was specified"
	for opt in `cat /proc/cmdline`
	do
		[ "${opt%%=*}" == "root" ] && ROOTDEV="${opt#*=}"
		[ "${opt%%=*}" == "nfsroot" ] && NFSROOT="${opt#*=}"
		[ "${opt%%=*}" == "mountopts" ] && MOUNTOPTS="${opt#*=}"
	done
	if [ -n "$NFSROOT" ]
	then
		MOUNTOPTS=${MOUNTOPTS:-nolock}
		echo -e " ${BOLD}${BLUE}*${NORM} Mounting NFS root from $NFSROOT with options: $MOUNTOPTS."
		mount ${MOUNTOPTS:+-o $MOUNTOPTS} $NFSROOT /.tmpfs/.cdrom
	else
		MOUNTOPTS=${MOUNTOPTS:-defaults}
		echo -e " ${BOLD}${BLUE}*${NORM} Mounting root device $ROOTDEV with options: $MOUNTOPTS."
		mount ${MOUNTOPTS:+-o $MOUNTOPTS} $ROOTDEV /.tmpfs/.cdrom
	fi
	if [ $? -ne 0 ]
	then
		echo -e " ${BOLD}${RED}*${NORM} Unable to mount the specified root device! Falling back to the live CD."
		find_and_mount_cdrom
	fi

	# check if root device is ready to boot or contains a squashfs image
	if [ -x /.tmpfs/.cdrom/sbin/init ]
	then
		echo -e " ${BOLD}${BLUE}*${NORM} $ROOTDEV contains a bootable filesystem."
		mkdir -p /newroot
		mount --bind /.tmpfs/.cdrom /newroot
	else
		if [ -f /.tmpfs/.cdrom/crux.squashfs ]
		then
			echo -e " ${BOLD}${BLUE}*${NORM} $ROOTDEV contains a squashfs filesystem."
			copy_squashfs
		else
			echo -e " ${BOLD}${RED}*${NORM} The specified root device ($ROOTDEV) does not appear to be usable! Falling back to the live CD."
			find_and_mount_cdrom
		fi
	fi

else
	find_and_mount_cdrom
	check_installation_media
	copy_squashfs
fi

echo -e " ${BOLD}${BLUE}*${NORM} Switching root.\n"
echo "$PRINTK" > /proc/sys/kernel/printk
echo > /proc/sys/kernel/hotplug
umount /sys
umount /proc
exec /bin/switch_root /newroot /sbin/init

echo "Something's broken, here's a shell."
exec /bin/sh
