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

panic() {
    printf "panic >> %s\n" "$1"
    sh -l
}

# 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
    mount -t tmpfs none /tmp
}

# 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 device in /sys/bus/usb/devices/*; do
        case ${device##*/} in
            [0-9]*-[0-9]*)
                printf add > "${device}/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
}

# shell findfs
findfs_sh() {
    case "${1%%=*}" in
        LABEL)
            printf "/dev/disk/by-label/%s\n" "${1##*=}"
            ;;
        UUID)
            printf "/dev/disk/by-uuid/%s\n" "${1##*=}"
            ;;
        PARTUUID)
            printf "/dev/disk/by-partuuid/%s\n" "${1##*=}"
            ;;
        /dev/*)
            printf "%s\n" "$1"
            ;;
        *)
            panic "findfs option broken"
            ;;
    esac
}

# unlock LUKS container
unlock_luks() {
    # TODO investigate this
    # avoid race condition
    [ "$devmgr" != "udev" ] && sleep 1.5

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

# manually trigger LVM
trigger_lvm() {
    lvm vgchange --quiet --sysinit -a y > /dev/null
}

# mount rootfs to /mnt/root
mnt_rootfs() {
    # mount rootfs
    mount $root_type $root_args $(findfs_sh "$root") /mnt/root || panic "failed to mount rootfs"
}

# kill and unmount
cleanup() {
    case "$devmgr" in
        mdev) { printf "" > /proc/sys/kernel/hotplug || killall uevent; } > /dev/null 2>&1 ;;
        mdevd) killall mdevd ;;
        udev) udevadm control --exit ;;
    esac

    # TODO re-do
    # if debug mode off then restore kernel logging
    [ "$debug" = 0 ] && printf 1 > /proc/sys/kernel/printk

    # unmount pseudofs's
    umount /dev /sys /proc /tmp
}

# 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 "failed to source config"

# TODO re-do
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