#!/sbin/busybox sh
#
# tiny init script

panic() {
    printf "panic >> %s\n" "$@" && sh
}

# parse_cmdline() {
# TODO parse /proc/cmdline
#}

# mount pseudofs's
mnt_pseudofs() {
    mount -t proc none /proc
    mount -t sysfs none /sys
    mount -t devtmpfs none /dev
}

# setup mdev
use_mdev() {
    # setup hotplugger
    if [ -e /proc/sys/kernel/hotplug ]; then
	printf /sbin/mdev >/proc/sys/kernel/hotplug
    else
	uevent mdev &
    fi

    # trigger mdev
    mdev -s

    # trigger uevent for usb devices
    for u in /sys/bus/usb/devices/*; do
	case ${u##*/} in
	    [0-9]*-[0-9]*)
	    printf add > "${u}/uevent"
            ;;
        esac
    done

    # load drivers
    find /sys -name "modalias" -type f -exec sort -u "{}" "+" | xargs modprobe -qba
}

# setup mdevd
use_mdevd() {
    # setup daemon
    mdevd &
    # trigger uevents
    mdevd-coldplug

    # TODO investigate this
    # avoid race condition
    sleep 1.5
}

# setup udev
use_udev() {
    udevd --daemon
    udevadm trigger --action=add --type=subsystems
    udevadm trigger --action=add --type=devices
    udevadm settle
}

# unlock LUKS container
unlock_luks() {
    # TODO implement POSIX findfs
    # find device of luks root
    luks_root="$(findfs $luks_root)"

    # TODO improve mapper name ( crypttab or config option )
    # unlock luks container
    cryptsetup $luks_args luksOpen "$luks_root" luks_root || panic "failed to unlock luks container"
}

# manually trigger LVM if udev disabled
trigger_lvm() {
    lvm vgchange --sysinit -a y
}

# mount rootfs to /mnt/root
mnt_rootfs() {
    # merge mount flags
    [ -n "$root_args" ] && mount_args="$root_args"
    [ -n "$root_type" ] && mount_args="$mount_args -t $root_type"

    # mount rootfs    
    mount $mount_args "$root" /mnt/root || panic "failed to mount rootfs"
}

# kill and unmount
cleanup() {
    # stop mdev
    [ "$devmgr" = "mdev" ] && { printf "" >/proc/sys/kernel/hotplug || killall uevent; } >/dev/null 2>&1
    # stop mdevd
    [ "$devmgr" = "mdevd" ] && killall mdevd
    # stop udev
    [ "$devmgr" = "udev" ] && udevadm control --exit
    # if debug mode off then restore kernel logging
    [ "$debug" = 0 ] && printf 1 >/proc/sys/kernel/printk
    umount /dev /sys /proc
}

# exec /mnt/root/sbin/init
boot_system() {
    exec switch_root /mnt/root /sbin/init || panic "failed to boot system"
}

# install busybox
/sbin/busybox --install -s

# source config
. /config || panic "config doesn't exists"

if [ "$debug" = 1 ]; then
    # debug shell commands 
    set -x
else
    # silence is golden
    printf 0 >/proc/sys/kernel/printk
fi

#parse_cmdline
mnt_pseudofs

case "$devmgr" in
    mdev) use_mdev ;;
    mdevd) use_mdevd ;;
    udev) use_udev ;;
    *) panic "devmgr option broken" ;;
esac

# TODO handle situations when LUKS on LVM
[ "$use_luks" = 1 ] && unlock_luks
[ "$use_lvm" = 1 ] && [ "$devmgr" != "udev" ] && trigger_lvm
mnt_rootfs
cleanup
boot_system