#!/bin/sh
# Daniel Robbins <drobbins@gentoo.org>
# Copyright 2003 Gentoo Technologies, Inc.
# Distributed under the GPL

. /etc/initrd.defaults
. /etc/initrd.scripts

USE_DEVFS_NORMAL=1

if [ "$$" != "1" ]
then
	echo "/linuxrc has to be run as the init process as the one"
	echo "with a PID of 1. Try adding init=\"/linuxrc\" to the"
	echo "kernel command line or running 'exec /linuxrc'."
	exit 1
fi

mount -o remount,rw /
mount -t proc proc /proc

[ -n "$QUIET" ] && echo "0" > /proc/sys/kernel/printk

CMDLINE=`cat /proc/cmdline`
# Scan CMDLINE for any specified real_root= or cdroot arguments
for x in ${CMDLINE}
do
	case "${x}" in
		real_root\=*)
			REAL_ROOT=`parse_opt "${x}"`
		;;
		cdroot)
			CDROOT=1
			REAL_ROOT=""
		;;
		devfs)
			USE_DEVFS_NORMAL=1
		;;
		nodevfs)
			USE_DEVFS_NORMAL=0
		;;
		loop\=*)
			LOOP=`parse_opt "${x}"`
		;;
		looptype\=*)
			LOOPTYPE=`parse_opt "${x}"`
		;;
		*)
		;;
	esac
done

# Scan CMDLINE for any "doscsi" or "noscsi"-type arguments
for x in $HWOPTS
do
	for y in $CMDLINE
	do
		if [ "$y" = "do${x}" ] 
		then
			MY_HWOPTS="${MY_HWOPTS} $x"
		elif [ "$y" = "no${x}" ] 
		then
			MY_HWOPTS="`echo ${MY_HWOPTS} | sed -e 's/${x}//g' -`"
		fi
	done
done

if [ -d "/lib/modules" ]
then
	echo -e "${GOOD}>>${NORMAL}${BOLD} Loading modules...${NORMAL}"
	# Load appropriate kernel modules
	for modules in $MY_HWOPTS
	do
		modules_scan $modules
		eval DO_`echo $modules | sed 's/-//'`=1
	done
else
	echo -e "${GREEN}>>${NORMAL}${BOLD} Skipping module load; no modules in the initrd!${NORMAL}"
fi

chooseKeymap() {
	echo -e "${GOOD}>>${NORMAL}${BOLD} Loading keymaps...${NORMAL}"
	cat /lib/keymaps/keymapList
	read -p "<< Load keymap: " keymap
	if [ -e /lib/keymaps/${keymap}.map ]
	then
		echo -e "${GOOD}>>${NORMAL}${BOLD} Loading the ''${keymap}'' keymap...${NORMAL}"
		loadkmap < /lib/keymaps/${keymap}.map
	elif [ "$keymap" = "" ]
	then
		echo -e "${GOOD}>>${NORMAL}${BOLD} Loading default US keymap...${NORMAL}"
		loadkmap < /lib/keymaps/us.map
	else
		echo -e "${BAD}!! ${NORMAL}${BOLD}Sorry, but keymap ''${keymap}'' is invalid!${NORMAL}"
		chooseKeymap
	fi
}

if [ "${DO_keymap}" ]
then
	chooseKeymap
fi

echo -e "${GOOD}>>${NORMAL}${BOLD} Mounting filesystems...${NORMAL}"

mkdir /newroot
if [ "${CDROOT}" -eq "1" ]
then
	mount -t tmpfs tmpfs /newroot
	mkdir /newroot/dev /newroot/mnt /newroot/mnt/cdrom /newroot/mnt/livecd /newroot/tmp /newroot/tmp/.initrd /newroot/mnt/gentoo
	[ ! -e /newroot/dev/.devfsd ] && mount -t devfs devfs /newroot/dev
	devfsd /newroot/dev -np
	sleep 1

	findcdmount /newroot/dev/cdroms/*
	# not in /dev/cdroms try /dev/ide/cd
	if [ "${REAL_ROOT}" = "" ]
	then
		findcdmount /newroot/dev/ide/cd/*
	fi

	if [ "${REAL_ROOT}" = "" ]
	then
		exec /bin/ash

		# Undo stuff		
		# kill_devfsd # We run devfsd with -np now
		sleep 1
		umount /newroot/dev/
		sleep 1
		umount /newroot
		# shouldn't be anything in here b/c it was on tmpfs
		rm -rf /newroot/*
		CDROOT=0
		echo "Could not find CD to boot, gonna need something else"
	fi
fi

# Don't do else b/c we set CDROOT=0 if it fails to detect
if [ "${CDROOT}" -eq "0" -a "${USE_DEVFS_NORMAL}" -eq "1" ]
then
	[ ! -e /dev/.devfsd ] && mount -t devfs devfs /dev
	devfsd /dev -np
fi

echo -e "${GOOD}>>${NORMAL}${BOLD} Determining root device...${NORMAL}"

while true
do
	while [ "${got_good_root}" != "1" ]
	do
		
		if [ "${REAL_ROOT}" = "shell" ]
		then
			/bin/ash

			REAL_ROOT=""
			got_good_root=0
			continue
		elif [ "${REAL_ROOT}" = "" ]
		then
			# No REAL_ROOT determined/specified. Prompt user for root block device.
			echo -e "${BAD}>>${NORMAL} The root block device is unspecified or not detected."
			echo "   Please specify a device to boot, or \"shell\" for a shell."
			echo -n "boot() :: "
			read REAL_ROOT
			got_good_root=0
		elif [ -b "${REAL_ROOT}" ]
		then
			got_good_root=1
		else
			echo -e "${BAD}>>${NORMAL} Block device ${REAL_ROOT} is not a valid root device..."
			REAL_ROOT=""
			got_good_root=0
		fi
	done

	if [ "${CDROOT}" -eq "1" -a "${got_good_root}" = "1" ]
	then
		break
	else
		echo -e "${GOOD}>>${NORMAL}${BOLD} Mounting root...${NORMAL}"

		mount -o rw ${REAL_ROOT} /newroot
		if [ "$?" = "0" ]
		then
			break
		else
			echo -e "${BAD}>> ${NORMAL}Could not mount specified ROOT, try again"
			got_good_root=0
			REAL_ROOT=""
		fi
	fi
done

[ -n "$QUIET" ] && echo "6" > /proc/sys/kernel/printk
check_loop() {
	if [ "${LOOP}" = "" -o ! -e "mnt/cdrom/${LOOP}" ]
	then
		echo "Invalid loop location: ${LOOP}"
		echo "Please export LOOP with a valid location, or reboot and pass a proper loop=..."
		echo "kernel command line!"
		/bin/ash
	fi
}

if [ "${CDROOT}" = "1" ]
then
	echo -e "${GOOD}>>${NORMAL}${BOLD} Filling tmpfs...${NORMAL}"
	cd /newroot

	# Failsafe if some idiot didn't set loop type
	if [ "${LOOPTYPE}" = "" ]
	then
		echo -e "${WARN}** ${NORMAL}${BOLD}Warning: loop type unspecified!${NORMAL}"
		if [ "${LOOP}" = "/livecd.loop" ]
		then
			LOOPTYPE="normal"
		elif [ "${LOOP}" = "/zisofs" ]
		then
			LOOPTYPE="zisofs"
		elif [ "${LOOP}" = "/livecd.squashfs" ]
		then
			LOOPTYPE="squashfs"
		elif [ "${LOOP}" = "/livecd.gcloop" ]
		then
			LOOPTYPE="gcloop"
		else
			LOOPTYPE="noloop"
		fi
	fi

	if [ "${LOOPTYPE}" != "noloop" ]
	then
	    check_loop
	    if [ "${DO_cache}" ]
	    then
		echo -e "${GOOD}>>${NORMAL}${BOLD} Copying loop file for caching...${NORMAL}"
		cp -a /newroot/mnt/cdrom/${LOOP} /newroot/mnt/${LOOP}
		if [ $? -ne 0 ]
		then
			echo -e "${BAD}!!${NORMAL}${BOLD} Failed to cache the loop file! Lack of space?"
			rm -rf /newroot/mnt/livecd.* 2>/dev/null
			rm -rf /newroot/mnt/zisofs 2>/dev/null
		else
			LOOPEXT="../"
		fi
	    fi
	fi

	if [ "${LOOPTYPE}" = "normal" ]
	then
		# bind-mount /dev/ so that loop devices can be found
		mount -o bind /newroot/dev /dev

		echo -e "${GOOD}>>${NORMAL}${BOLD} Mounting loop filesystem...${NORMAL}"
		mount -t ext2 -o loop,ro /newroot/mnt/cdrom/${LOOPEXT}${LOOP} /newroot/mnt/livecd
		if [ "$?" != "0" ]
		then
			echo "FAILED TO MOUNT LOOP FILESYSTEM, barfing out to shell"
			/bin/ash
		fi
		FS_LOCATION="mnt/livecd"
		umount /dev
	elif [ "${LOOPTYPE}" = "squashfs" ]
	then
		mount -o bind /newroot/dev /dev
		echo -e "${GOOD}>>${NORMAL}${BOLD} Mounting squashfs filesystem...${NORMAL}"
		mount -t squashfs -o loop,ro /newroot/mnt/cdrom/${LOOPEXT}${LOOP} /newroot/mnt/livecd
		if [ "$?" != "0" ]
		then
			echo "FAILED TO MOUNT LOOP FILESYSTEM, barfing out to shell"
			/bin/ash
		fi
		FS_LOCATION="mnt/livecd"
		umount /dev
	elif [ "${LOOPTYPE}" = "gcloop" ]
	then
		echo -e "${GOOD}>>${NORMAL}${BOLD} Mounting gcloop filesystem...${NORMAL}"
		mount -o bind /newroot/dev /dev
		echo " " | losetup -E 19 -e ucl-0 -p0 /newroot/dev/loop0 /newroot/mnt/cdrom/${LOOPEXT}${LOOP}
		if [ "$?" != "0" ]
		then
			echo "FAILED TO losetup THE LOOP DEVICE"
			/bin/ash
		fi
		mount -t ext2 -o ro /newroot/dev/loop0 /newroot/mnt/livecd
		FS_LOCATION="mnt/livecd"
		umount /dev
	elif [ "${LOOPTYPE}" = "zisofs" ]
	then
		FS_LOCATION="mnt/cdrom/${LOOPEXT}${LOOP}"
	elif [ "${LOOPTYPE}" = "noloop" ]
	then
		FS_LOCATION="mnt/cdrom"
	fi

	echo -e "${GOOD}>>${NORMAL}${BOLD} Filling filesystem...${NORMAL}"
	for x in ${ROOT_LINKS}
	do
		ln -s "${FS_LOCATION}/${x}" "${x}"
	done
	mkdir initrd proc tmp sys
	chmod 1777 tmp
	(cd /newroot/${FS_LOCATION}; cp -a ${ROOT_TREES} /newroot)
else
	mkdir -p /newroot/tmp/.initrd
fi

[ ! -e /newroot/dev/console ] && mknod /newroot/dev/console c 5 1
echo -ne "${GOOD}>>${NORMAL}${BOLD} Booting"

cd /newroot
pivot_root . tmp/.initrd
echo -n '.'

if [ "${USE_DEVFS_NORMAL}" -eq "1" -a "${CDROOT}" -eq "0" ]
then
	umount /tmp/.initrd/proc || echo '*: Failed to unmount the initrd /proc!'
	mount -n --move /tmp/.initrd/dev dev || echo '*: Failed to move over the /dev tree!'
	rm /tmp/.initrd/dev -rf || '*: Failed to remove the initrd /dev!'
elif [ "${CDROOT}" -eq "1" ]
then
	# If automount at boot was on with devfs, we'll want to umount it
	# also umount proc
	mount -t proc proc /proc
	umount /tmp/.initrd/proc > /dev/null 2>&1 || echo "*: Failed to unmount /tmp/.initrd/proc!"
	umount /dev > /dev/null 2>&1
	umount /proc > /dev/null 2>&1
fi
echo -n '.'

# /usr/src/linux/Documentation/initrd.txt 
# here's the line it says we should do:
#       exec chroot . /sbin/init </dev/console >/dev/console 2>&1

exec <dev/console >dev/console 2>&1
echo '.'
exec chroot . /bin/sh <<- EOF
 	umount /tmp/.initrd || echo "*: Failed to unmount the initrd!"
	/sbin/blockdev --flushbufs /dev/ram0 >/dev/null 2>&1
 	exec /sbin/init
EOF

echo "A fatal error has probably occured since /sbin/init did not"
echo "boot correctly. Trying to open a shell..."
echo
exec /bin/bash
exec /bin/sh
exec /bin/ash
exec sh
