#!/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}"

# helper functions

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

# search for and mount the crux media, populate a tmpfs from it,
# and prepare /newroot for switch_root at the end of the script
find_and_mount_media() {
	echo -e " ${BOLD}${BLUE}*${NORM} Searching for the CRUX media..."
	mkdir -p /media
	CRUXMEDIA=""
	MMC_DEVICES="`grep -E 'mmcblk' /proc/partitions | awk '{ print $4 }'`"
	BLOCK_DEVICES="`grep -E '[sh]d' /proc/partitions | awk '{ print $4 }'`"
	for DEV in $MMC_DEVICES $BLOCK_DEVICES
	do
		DEV="/dev/$DEV"
		mount -r $DEV /media 2> /dev/null
		if [ $? -eq 0 ]
			then
			echo -e -n "   ${BOLD}${GREEN}*${NORM} Found media on $DEV"
			if [ -e /media/crux-media ]
			then
				echo ", CRUX media."
				CRUXMEDIA=$DEV
				ln -s $DEV /dev/media
				break
			else
				echo ", but it's not the CRUX media."
				umount /media
			fi
		else
			echo -e "   ${BOLD}${YELLOW}*${NORM} No media found on $DEV."
		fi
	done

	# check if the media was mounted properly. if not, spawn a shell
	if [ ! -e /media/crux-media ]
	then
		echo
		echo -e " ${BOLD}${RED}*${NORM} The CRUX media was not properly mounted!"
		echo " Spawning a shell for you to attempt to fix this problem. If"
		echo " you are able to find the correct device, mount it at"
		echo " /media 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 /media/crux-media ]
	then
		echo
		echo -e " ${BOLD}${RED}*${NORM} The CRUX media still appears not to be"
		echo " found and installation will not continue."
		echo
	else
		# configure modules
		MODULES="`find /media/crux/kernel -type f -name 'modules-*.tar.*'`"
		if [ ! -z "$MODULES" ]; then
			tar -C /tmp -xf $MODULES
			cd /lib && ln -s /tmp/lib/* .
			depmod
		fi
		# configure pkgutils
		PKGUTILS="`find /media/crux/core -type f -name 'pkgutils#*.pkg.tar.*'`"
		if [ ! -z "$PKGUTILS" ]; then
			tar -C /tmp -xf $PKGUTILS
			cd /usr/bin && ln -s /tmp/usr/bin/* .
			cd /etc && ln -s /tmp/etc/* .
		fi
	fi
}

/bin/busybox --install -s /bin

#
# main script
#

echo ""
echo -e "${BOLD}CRUX-ARM 2.7.1 - ${BLUE}http://crux-arm.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

echo -e -n " ${BOLD}${BLUE}*${NORM} Creating and mounting /dev/pts... "
mkdir /dev/pts
mount -t devpts devpts /dev/pts
checkReturn

echo -e -n " ${BOLD}${BLUE}*${NORM} Starting kernel log daemon... "
klogd
checkReturn

echo -e -n " ${BOLD}${BLUE}*${NORM} Setting hostname... "
hostname crux
checkReturn

echo -e -n " ${BOLD}${BLUE}*${NORM} Loading network loopback device... "
ip addr add 127.0.0.1/8 dev lo broadcast + scope host && \
ip link set lo up && \
echo "127.0.0.1 localhost crux" > /etc/hosts
checkReturn

echo -e -n " ${BOLD}${BLUE}*${NORM} Saving boot messages... "
dmesg > /var/log/boot
checkReturn

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

# if root=/dev/XXX was specified on the command line, use that as the new root
# instead of searching for the media and using it. if it fails, fall back to the media
grep -q "root=/dev/*" /proc/cmdline
if [ $? -eq 0 ]
then
	for opt in `cat /proc/cmdline`
	do
		echo "$opt" | grep -q "root="
		if [ $? -eq 0 ]
		then
			ROOTDEV=`echo $opt | cut -d'=' -f2`
		fi
	done
	mkdir -p /newroot
	# check the specified root device to see if it has an init
	mount $ROOTDEV /newroot
	if [ $? -ne 0 ]
	then
		echo -e " ${BOLD}${RED}*${NORM} Unable to mount the specified root device! Falling back to the live media."
		find_and_mount_media
	else
		if [ -x /newroot/sbin/init ]
		then
			echo -e " ${BOLD}${BLUE}*${NORM} Mounted root device $ROOTDEV."
		else
			echo -e " ${BOLD}${RED}*${NORM} The specified root device ($ROOTDEV) does not appear to be usable! Falling back to the live media."
			umount /newroot
			find_and_mount_media
		fi
	fi
else
	find_and_mount_media
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

# End of file