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

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

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

mnt_pseudofs() {
    mount -t proc none /proc
    mount -t sysfs none /sys
    mount -t devtmpfs none /dev
    mount -t tmpfs none /tmp
}

setup_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() {
    # setup daemon
    mdevd &
    # trigger uevents
    mdevd-coldplug
}

setup_udev() {
    udevd --daemon
    udevadm trigger --action=add --type=subsystems
    udevadm trigger --action=add --type=devices
    udevadm settle
}

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

    # avoid race condition
    until [ -e "$device" ]; do sleep 0.5; done

    printf "%s\n" "$device"
}

unlock_luks() {
    cryptsetup $luks_args luksOpen $(findfs_sh "$luks_root") ${luks_name:-luks_root} || panic "failed to unlock luks container"
}

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

mnt_rootfs() {
    mount ${root_type:+-t $root_type} $root_args $(findfs_sh "$root") /mnt/root || panic "failed to mount rootfs"
}

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
}

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

/sbin/busybox --install -s

. /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) setup_mdev ;;
    mdevd) setup_mdevd ;;
    udev) setup_udev ;;
    *) panic "devmgr option broken" ;;
esac

# TODO handle situations when LUKS on LVM
[ "$luks" = 1 ] && unlock_luks
[ "$lvm" = 1 ] && trigger_lvm
mnt_rootfs
cleanup
boot_system