#!/bin/sh

exec 1>/dev/stdout

export PATH=/bin:/sbin:/usr/bin:/usr/sbin:/lib/udev

devices=$(echo $(/sbin/blkid -u filesystem -o device))
filesystems=$(echo $(/sbin/blkid -u filesystem -k))
boottargets=''

echo "Searching on $devices"

umount_all()
{
nets=$(ls /sys/class/net/)
mods=$(lsmod | cut -f1 -d' ' )

cat /proc/mounts | cut -f2 -d' '| uniq | sort -b -f -r \
        | while read mountpnt; do
                [ "$mountpnt" = "/proc" -o "$mountpnt" = "/dev" -o "$mountpnt" = "/" ] && continue
                echo "umounting $mountpnt"
                if [ -z "$1" ]; then
                         umount $mountpnt || umount -l $mountpnt
                fi
        done

        umount /proc; umount /dev
}

net_down()
{
        for n in $nets; do 
                echo "taking down $n"
                if [ -z "$1" ]; then
                         ip link set $n down
                fi
        done
}

modules_down()
{
        for m in $mods; do 
                echo "removing module $m"
                if [ -z "$1" ]; then
                         /sbin/modprobe -r --remove-dependencies $m
                fi
        done
}

in_list() 
{

        case $filesystems in
                *" $1 "*)
                        return 0
                        ;;
        esac

        return 1

}

f()
{
        if [ $1 = btrfs ]; then
            opt=subvol=/
        else
            am=$(/bin/findmnt -n -f -o target $3)
            opt=ro
        fi

        if [ -z "$am" ]; then
                am=$2
                /bin/mount -t $1 -o $opt $3 $2 > /dev/null 2>&1|| return 0
        fi

        [ -e $am/boot.cfg ] && . $am/boot.cfg || return 0

        [ -z "$boot_name" -o -z "$boot_kernel" -o -z "$boot_cmdline" ] && return 0
        [ -n "$boot_initramfs" -a ! -e $am/$boot_initramfs ] && return 0
        [ ! -e $am/$boot_kernel ] && return 0

        echo "$boot_name"
}

check_devices()
{

for dev in $devices; do
        o=''
        typed=$(/sbin/blkid -s TYPE -o value $dev)
        in_list $typed || continue

        mntd=$(mktemp -d)

        o=$(f $typed $mntd $dev)
        [ -n "$o" ] && boottargets="$boottargets $dev $o"

        mountpoint -q $mntd && /bin/umount $mntd
        mountpoint -q $mntd || rmdir $mntd
done

        echo "$boottargets"
}

opt=$(check_devices)
[ -z "$opt" ] && exit 0

[ -e /bootmenu_timeout ] && /bootmenu_timeout & ptm=$! >/dev/null 2>&1
echo $opt > /run/bootmenu
choice=$(whiptail --fb --menu Choose\ your\ boot\ partition 25 60 10 $opt 3>&1 1>&2 2>&3)
setterm -reset

[ -z "$ptm" ] || kill $ptm >/dev/null 2>&1
[ -z "$choice" -o "$choice" = "-" ] && exit 1

mntd=$(mktemp -d)
fst=$(/sbin/blkid -p -s TYPE -o value "$choice")

if [ $fst = btrfs ]; then 
    opt=subvol=/
else
    fm=$(/bin/findmnt -n -f -o target $choice)
    opt=ro
fi
if [ -z "$fm" ]; then
    fm=$mntd
    /bin/mount -t $fst -o $opt $choice $fm
fi

. $fm/boot.cfg

[ -z "$snapchoice" ] && snapchoice='root/@'
if [ $fst = btrfs ]; then
    snaps=$(find $fm -maxdepth 2 -mindepth 2 -type d -printf "%P .\n" | grep root/@ )
    [ $boot_snap = yes ] && [ -n "$snaps" ] && snapchoice=$(whiptail --clear --fb --menu Choose\ your\ snapshot 25 80 10 $snaps 3>&1 1>&2 2>&3)
fi
setterm -reset

if echo $boot_cmdline | grep -q 'subvol='; then
    sub=${boot_cmdline##*subvol=};sub=${sub%%,*}
    boot_cmdline=$(echo $boot_cmdline | eval sed 's%$sub%$snapchoice%')
else
    boot_cmdline=$(echo $boot_cmdline | eval sed 's%rootflags=%rootflags=subvol=$snapchoice,%')
fi

echo $boot_cmdline | grep -q root= && unset root_append || root_append="root=$choice"

echo "loading kernel"
if [ -n "$boot_initramfs" ]; then
    eval /sbin/kexec --initrd=$fm/$boot_initramfs --command-line="\"$boot_cmdline $root_append \"" -l $fm/$boot_kernel
else
    eval /sbin/kexec --command-line="\"$boot_cmdline $root_append \"" -l $fm/$boot_kernel
fi
/bin/umount $fm

exec > /dev/null
echo "stopping processes" 1>&2
/sbin/killall5 -15 -o $$ 2>&1
sleep 10
echo "unmounting filesystems" 1>&2
umount_all 2>&1
echo "stopping network" 1>&2
net_down 2>&1
echo "removing modules" 1>&2
modules_down  2>&1
exec /sbin/kexec -e
