#!/bin/sh

PATH=/bin:/sbin:/usr/bin:/usr/sbin
export PATH

echo "Loading, please wait..."

[ -d /dev ] || mkdir -m 0755 /dev
[ -d /root ] || mkdir -m 0700 /root
[ -d /sys ] || mkdir /sys
[ -d /proc ] || mkdir /proc
[ -d /tmp ] || mkdir /tmp
mkdir -p /var/lock
mount -t sysfs -o nodev,noexec,nosuid none /sys
mount -t proc -o nodev,noexec,nosuid none /proc

mount -t tmpfs -o size=10M,mode=0755 udev /dev
[ -e /dev/console ] || mknod /dev/console c 5 1
[ -e /dev/null ] || mknod /dev/null c 1 3
mkdir /dev/.initramfs
mkdir /dev/pts
mkdir /dev/shm

echo > /proc/sys/kernel/hotplug

BOOT=local
if [ -r /conf/initramfs.conf ]; then
	. /conf/initramfs.conf
fi

. /scripts/functions

# Parse command line options
break=
init=/sbin/init
quiet=n
readonly=y
rootmnt=/root
debug=
cryptopts=${CRYPTOPTS}
panic=

for x in $(cat /proc/cmdline); do
	case $x in
	init=*)
		init=${x#init=}
		;;
	root=*)
		ROOT=${x#root=}
		;;
	rootflags=*)
		ROOTFLAGS="-o ${x#rootflags=}"
		;;
	rootfstype=*)
		ROOTFSTYPE="${x#rootfstype=}"
		;;
	rootdelay=*)
		ROOTDELAY="${x#rootdelay=}"
		;;
	cryptopts=*)
		cryptopts="${x#cryptopts=}"
		;;
	nfsroot=*)
		NFSROOT="${x#nfsroot=}"
		;;
	ip=*)
		IPOPTS="${x#ip=}"
		;;
	boot=*)
		BOOT=${x#boot=}
		;;
	resume=*)
		RESUME="${x#resume=}"
		;;
	noresume)
		NORESUME=y
		;;
	resume2=*)
		RESUME2="${x#resume2=}"
		;;
	noresume2)
		NORESUME2=y
		;;
	panic=*)
		panic="${x#panic=}"
		;;
	quiet)
		quiet=y
		;;
	ro)
		readonly=y
		;;
	rw)
		readonly=n
		;;
	debug)
		debug=y
		exec >/tmp/initramfs.debug 2>&1
		set -x
		;;
	debug=*)
		debug=y
		set -x
		;;
	break=*)
		break=${x#break=}
		;;
	break)
		break=premount
		;;
	esac
done

if [ -z "${NORESUME}" ]; then
	resume=${RESUME}
fi
if [ -z "${NORESUME2}" ]; then
	resume2=${RESUME2}
fi

maybe_break top

case $ROOT in
LABEL=*)
	echo "ENV{ID_FS_USAGE}==\"filesystem|other\", ENV{ID_FS_LABEL}==\"${ROOT#LABEL=}\", SYMLINK+=\"root\"" > /etc/udev/rules.d/99-root.rules
	ROOT="/dev/root"
	;;
UUID=*)
	ROOT="/dev/disk/by-uuid/${ROOT#UUID=}"
	;;
/dev/nfs)
	BOOT=nfs
	;;
esac

case "$resume" in
LABEL=*)
	echo "ENV{ID_FS_USAGE}==\"filesystem|other\", ENV{ID_FS_LABEL}==\"${resume#LABEL=}\", SYMLINK+=\"resume\"" > /etc/udev/rules.d/99-resume.rules
	resume="/dev/resume"
	;;
UUID=*)
	resume="/dev/disk/by-uuid/${resume#UUID=}"
	;;
esac

if [ -r /scripts/init-top ]; then
	. /scripts/init-top
fi

[ "$quiet" != "y" ] && log_begin_msg "Starting udevd"
mkdir -p /dev/.udev/db/
udevd --daemon
mkdir -p /dev/.udev/queue/
udevadm trigger --attr-match dev
udevadm settle || true
[ "$quiet" != "y" ] && log_end_msg

maybe_break modules
log_begin_msg "Loading essential drivers"
load_modules
log_end_msg

maybe_break premount

[ "$quiet" != "y" ] && log_begin_msg "Finishing udevd initialization"
udevadm trigger
udevadm settle || true
[ "$quiet" != "y" ] && log_end_msg

run_scripts /scripts/init-premount

maybe_break mount
log_begin_msg "Mounting root file system"
. /scripts/${BOOT}
parse_numeric ${ROOT}
mountroot
log_end_msg

maybe_break bottom

[ "$quiet" != "y" ] && log_begin_msg "Stopping udevd"

# Stop udevd, we'll miss a few events while we run init, but we catch up
udevadm settle
kill `cat /dev/.udev/udevd.pid`
for proc in /proc/[0-9]*; do
    [ -x $proc/exe ] || continue
    [ "$(readlink $proc/exe 2>/dev/null)" != /sbin/udevd ] ||
    	kill ${proc#/proc/}
done

# ignore any failed event because the init script will trigger again all events
nuke /dev/.udev/queue/

# Read udev config from the real filesystem if possible
if [ -e $rootmnt/etc/udev/udev.conf ]; then
    . $rootmnt/etc/udev/udev.conf
elif [ -e /etc/udev/udev.conf ]; then
    . /etc/udev/udev.conf
fi

# Move /dev created in initramfs to the real filesystem if this is enabled
# in the udev configuration.
if [ "$use_initramfs_dev" = 1 ]; then

	# Pass udev version from initramfs to the real system.
	udev_version="$(/sbin/udevd --version 2>/dev/null)"
	printf '%s\n' "${udev_version:-105}" >/dev/.initramfs/udev_version

	# Optionally move the real filesystem's /dev to beneath our tmpfs
	if [ -z "$no_static_dev" ]; then
		mkdir -m 0700 /dev/.static/
		mkdir /dev/.static/dev/
		mount -o bind $rootmnt/dev /dev/.static/dev
	fi

	# Now move it all to the real filesystem
	mount -o move /dev $rootmnt/dev

	# create a temporary symlink to the final /dev for other initramfs
	# scripts
	nuke /dev
	ln -s $rootmnt/dev /dev
fi

[ "$quiet" != "y" ] && log_end_msg

run_scripts /scripts/init-bottom

while [ ! -x ${rootmnt}${init} ]; do
	panic "Target filesystem doesn't have ${init}"
done

umount /sys
umount /proc

# Chain to real filesystem
maybe_break init
# If /dev was not moved to the real filesystem, unmount it
[ "$use_initramfs_dev" = 1 ] || umount -l /dev
exec run-init ${rootmnt} ${init} "$@" <${rootmnt}/dev/console >${rootmnt}/dev/console
