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

. /scripts/functions

run_scripts /conf/initramfs.conf

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

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=}"
		;;
	rootsubdir=*)
		ROOTSUBDIR="${x#rootsubdir=}"
		;;
	rootdelay=*)
		ROOTDELAY="${x#rootdelay=}"
		;;
	cryptopts=*)
		cryptopts="${x#cryptopts=}"
		;;
	modules=*)
		MODULES="${MODULES:+$MODULES }${x#modules=}"
		;;
	nfsroot=*)
		[ -n "$NFSROOT" ] || NFSROOT="${x#nfsroot=}"
		;;
	nbd=*)
		NBD="${x#nbd=}"
		;;
	netif=*)
		NETIF="${x#netif=}"
		;;
	BOOTIF=*)
		BOOTMAC="${x#BOOTIF=}"
		;;
	ip=*)
		[ -n "$IPOPTS" ] || 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
		;;
	*.*=*)
		module=${x%.*}
		param=${x#*.}
		echo "option $module $(substchar $param "," " ")" >> /etc/modprobe.d/boot-options
		;;
	esac
done

[ -n "${NORESUME}" ] || resume=${RESUME}
[ -n "${NORESUME2}" ] || resume2=${RESUME2}

AddUdevRule()
{
case $1 in
	LABEL=*|UUID=*)
		cat >> /etc/udev/rules.d/99-initramfs.rules <<__RULE__
ENV{ID_FS_USAGE}=="${3:-filesystem|other}", ENV{ID_FS_${1#=*}}=="${1#*=}", SYMLINK+="$2"
__RULE__
		;;
esac
}

AddUdevRule $ROOT root
AddUdevRule $resume resume

maybe_break top

run_scripts /scripts/init-top

[ "$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

case $ROOT in
	LABEL=*|UUID=*)	ROOT=$(/sbin/findfs "$ROOT" 2>/dev/null) || ROOT="/dev/root" ;;
	/dev/nfs)	BOOT=nfs ;;
esac

case "$resume" in
	LABEL=*|UUID=*) resume=$(/sbin/findfs "$resume" 2>/dev/null) || resume="/dev/resume" ;;
esac

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
