#!/bin/busybox sh

/bin/busybox --install -s /bin

NEWROOT=/newroot
init=/sbin/init
cryptroot=
root=
rootdelay=
rootfstype=auto
ro="ro"
rootflags=
device=

# print the block device for a /dev path, UUID= or LABEL=
find_device() {
	case "$1" in
		UUID=*|LABEL=*) findfs "$1" 2>/dev/null ;;
		*             ) echo "$1" ;;
	esac
}

# like find_device, but retry for up to $rootdelay seconds
wait_device() {
	dev=$(find_device "$1")
	i=0
	while [ ! -b "$dev" ] && [ "$i" -lt "${rootdelay:-0}" ]; do
		echo ">> waiting for $1..." >&2
		sleep 1
		i=$((i+1))
		dev=$(find_device "$1")
	done
	echo "$dev"
}

mkdir -p $NEWROOT
mount -t proc     proc  /proc
mount -t sysfs    sysfs /sys
mount -t tmpfs    run   /run
mount -t devtmpfs dev   /dev

read -r cmdline < /proc/cmdline

for param in $cmdline; do
	case $param in
		init=*      ) init=${param#init=}             ;;
		cryptroot=* ) cryptroot=${param#cryptroot=}  ;;
		root=*      ) root=${param#root=}             ;;
		rootdelay=* ) rootdelay=${param#rootdelay=}   ;;
		rootfstype=*) rootfstype=${param#rootfstype=} ;;
		rootflags=* ) rootflags=${param#rootflags=}   ;;
		ro          ) ro="ro"                         ;;
		rw          ) ro="rw"                         ;;
		shell       ) shell=1                         ;;
		liveos      ) live=1                          ;;
	esac
done

# mdev
[ -f /proc/sys/kernel/hotplug ] && \
	which mdev > /proc/sys/kernel/hotplug
mdev -s

# load modules using modalias
find /sys -name 'modalias' -type f -exec cat '{}' + | sort -u | xargs modprobe -b -a 2>/dev/null

# load modules
for m in virtio virtio_ring virtio_pci virtio_blk virtio_scsi nvme \
	ata_piix sd_mod sr_mod cdrom loop squashfs isofs overlay mbcache \
	jbd jbd2 ext2 ext3 ext4 xfs btrfs f2fs reiserfs jfs fat vfat exfat ntfs3; do
	modprobe "$m" 2>/dev/null
done

# load modules detected by 'mkinitrd -a'
if [ -f /modules ]; then
	while read -r m; do
		modprobe "$m" 2>/dev/null
	done < /modules
fi

[ "$shell" ] && sh

[ "$rootflags" ] && rootflags="$rootflags,"
rootflags="$rootflags$ro"

if [ "$live" ]; then
	INITRAMFS=/run/initramfs
	MEDIA=$INITRAMFS/media
	LOWER=$INITRAMFS/lower
	UPPER=$INITRAMFS/upper
	WORK=$INITRAMFS/work
	SFSIMAGE=$MEDIA/liveos/rootfs.sfs

	mkdir -p $LOWER $MEDIA $UPPER $WORK

	# figure out media
	if [ -f /proc/sys/dev/cdrom/info ]; then
		CDROM=$(grep name /proc/sys/dev/cdrom/info | awk -F : '{print $2}' | awk '{print $1}')
	fi

	while [ "$wait" != 10 ]; do
		BLOCK=$(grep -E '[vsh]d|nvme|mmcblk' /proc/partitions | awk '{print $4}')
		for i in $CDROM $BLOCK; do
			mount -r /dev/"$i" $MEDIA >/dev/null 2>&1 || continue
			[ -d $MEDIA/liveos ] || { umount $MEDIA; continue; }
			MEDIAFOUND=1
			break 2
		done
		wait=$(( wait + 1 ))
		sleep 1
	done

	if [ ! "$MEDIAFOUND" ]; then
		echo "Media not found even after 10 seconds"
		sh
		echo "Cannot go further"
		sleep 99999
		exit 1
	fi

	# mount stuff
	loopdevice=$(losetup -f)
	losetup -f $SFSIMAGE
	mount -r "$loopdevice" $LOWER
	mount -t overlay overlay -o lowerdir=$LOWER,upperdir=$UPPER,workdir=$WORK $NEWROOT
	if [ -f $MEDIA/liveos/live.gz ]; then
		tar -xzf $MEDIA/liveos/live.gz -C $NEWROOT
	fi
else
	if [ "$cryptroot" ]; then
		if command -v cryptsetup >/dev/null 2>&1; then
			cryptroot_device=$(wait_device "${cryptroot%%:*}")
			cryptroot_name=${cryptroot#*:}
			cryptsetup luksOpen "$cryptroot_device" "$cryptroot_name"
		else
			echo "!! cryptroot= given but cryptsetup is not in the initramfs"
		fi
	fi

	[ "$root" ] || { echo "!! no root device specified"; exec sh; }

	device=$(wait_device "$root")

	if [ ! -b "$device" ]; then
		echo "!! device '$root' not found"
		exec sh
	fi

	if ! mount -n -t "$rootfstype" -o "$rootflags" "$device" $NEWROOT; then
		echo "!! failed to mount device '$device'"
		exec sh
	fi

fi

[ "$shell" ] && sh

pkill mdev

mount --move /sys $NEWROOT/sys
mount --move /proc $NEWROOT/proc
mount --move /dev $NEWROOT/dev
mount --move /run $NEWROOT/run

# execute live script if exist
if [ "$live" ] && [ -f $NEWROOT/"$MEDIA"/liveos/live.sh ]; then
	chroot $NEWROOT sh "$MEDIA"/liveos/live.sh
fi

# switch to newroot
exec switch_root $NEWROOT "$init" "$@"

echo ">> this is the end of initramfs"
echo ">> nothing further, here's the shell"
busybox sh
