#!/bin/sh

## hyphop ##

#= megaimage_online.sh - simple Krescue online installation system for VIM1|VIM2|VIM3|VIM3L|Edge Khadas boards

KRESCUE_ONLINE="
   __ __                           ____       ___
  / //_/______ ___ ______ _____   / __ \___  / (_)__  ___
 / ,< / __/ -_|_-</ __/ // / -_) / /_/ / _ \/ / / _ \/ -_)
/_/|_/_/  \__/___/\__/\_,_/\__/  \____/_//_/_/_/_//_/\__/

"

KRESCUE="https://dl.khadas.com/Firmware/Krescue"

# TEST 
#IP=172.22.1.2
#IP=172.23.0.183
# curl -fs $(usb_host_ip):8080/.m | sh -s -
#KRESCUE="http://$IP:8080/Firmware/Krescue"

KSYSTEM=$KRESCUE/system
KIMAGES=$KRESCUE/images
KMEGA=$KRESCUE/mega

USAGE="megaimage_online.sh - simple online - krescue system & images write

write krescue and mega installation images by one command line.
no deps, no root! extreme easy & fast!

# USAGE

    ./megaimage_online.sh [-n] [-h|-u] [-i|-l|-b][-Y][-A][-r] [Edge|VIM1|VIM2|VIM3|VIM3L|-X] [ --all | IMAGE.kresq  ] ... [ > DESTINATION ]

# ONLINE USAGE

    curl -sfL dl.khadas.com/.mega | sh -s - [ARGS] [ > DESTINATION ]
    wget -O-  dl.khadas.com/.mega | sh -s - [ARGS] [ > DESTINATION ]

NOTE:	unsafe and wrong destination autodetected and rejected!

# ONLINE IMAGE WRITE USAGE

    curl -sfL dl.khadas.com/.mega | sh -s - [ARGS] SOC_ID [ IMAGE_NAME ] > [ SD | MMC | FILE ]

# PARAMS and ARGS

    [Edge|VIM1|VIM2|VIM3|VIM3L|-X] # manual setup board name or -X for autodetect for Krescue system

    -l | --list               # list mode
    -L | --links              # links mode
    -n | --noop               # noop mode (stay only at begin)
    -u | --usage              # display full info or -h | --help # short info
    -a | --all                # get all images
    -A | --autoinstall        # autointall configure
    -b | --board              # detect board and exit
    -r | --ro                 # put system to RO mode (NOTE auotodetected if u write to emmc on VIM board)
    -Y | --yes                # force yes for unsafe writes
    -y | --force              # force yes for unsafe writes and ignore all errors (danger)
    -f | --full               # write only after full download image only
    -i | --info               # display info about device 

    IMAGE.kresq                 # image name from server list (u can check images list before by --list)
    http://..../IMAGE.kresq	# manual http link 
    ./IMAGE.kresq		# local file

"
ADVANCE="# ADVANCE usage - parameters

    -b | --board	# detect board only

## IMAGES MATCHES

    -m TAG1 TAG2	- only matched by tags
    -M TAG1 TAG2	- only matched by tags for selected devices [Edge|VIM1|VIM2|VIM3|VIM3L]
    -M [VIM+] TAG1 TAG2	- only matched by tags and manual set device [Edge|VIM1|VIM2|VIM3|VIMx|VIM.]

## CHECK ONLINE SYSTEM READY

    curl -sfL dl.khadas.com/.mega | sh -s - --list && echo ONLINE_OK

"

USAGE(){ echo "$USAGE

$ADVANCE

ONLINE USAGE

    curl -sfL dl.khadas.com/.mega | sh -s - [ARGS]

ONLINE DEVICE INFO

    curl -sfL dl.khadas.com/.mega | sh -s - -i

    > [i] DEVICE INFO
    > [i] BOARD NAME: VIM3L
    > [i] eMMC: /dev/mmcblk0
    > [i] SD card: /dev/mmcblk1

ONLINE DEVICE INFO CHECK OUTPUT TYPE (its safe nothing write to DISK)

    curl -sfL dl.khadas.com/.mega | sh -s - -i > /dev/mmcblk1

    > [i] DEVICE INFO
    > [i] BOARD NAME: VIM3L
    > [i] eMMC: /dev/mmcblk0
    > [i] SD card: /dev/mmcblk1
    > [i] OUTPUT: /dev/mmcblk1  (SD card)

ONLINE Detect VIM / Edge  board NAME

    curl -sf https://dl.khadas.com/.mega | sh -s - -b
    
    > Edge | VIM1 | VIM2 | VIM3 | VIM3L | [e] VIM board not detected

ONLINE WRITE Krescue to SD for VIM2

    curl -sf https://dl.khadas.com/.mega | sh -s - VIM2 | sudo dd bs=1M of=/dev/sdX

ONLINE WRITE Krescue to SD on VIM device

    curl -sf https://dl.khadas.com/.mega | sh -s - VIM2 > /dev/mmcblk?

ONLINE WRITE Krescue to SD on VIM device -X autodetect krescue board name ( Edge | VIM1 | VIM2 | VIM3 | VIM3L )

    curl -sf https://dl.khadas.com/.mega | sh -s - -X > /dev/mmcblk?

ONLINE WRITE Krescue to eMMC on VIM board

    curl -sfL dl.khadas.com/.mega | sh -s - -Y -X > /dev/mmcblk?

ONLINE WRITE Krescue to eMMC on VIM board + os image + autoinstall

usafe writes -Y & autodetec board -X & autoinstall -A & match by (lakka) name and board id -M

    curl -sfL dl.khadas.com/.mega | sh -s - -A -Y -X -M lakka > /dev/mmcblk?

ONLINE WRITE Krescue to SD on VIM board + os image + autoinstall

autodetec board -X & autoinstall -A 

    curl -sfL dl.khadas.com/.mega | sh -s - -A -X VIM2.VIM1.COREELEC.9.2.1.emmc.kresq > /dev/mmcblk?

ONLINE GENERATE MEGA SD image (Krescue + openwrt)

    curl -sf https://dl.khadas.com/.mega | sh -s - VIM2 VIMx.OpenWrt.servers.test.emmc.kresq

CHECK ONLINE images list 

best way to check online connection and all images list ! plz start always from this command!

    curl -sf https://dl.khadas.com/.mega | sh -s - --list 

ABOUT

    + https://dl.khadas.com/Firmware/Krescue/mega/README.megaimage_online.txt
    + $KMEGA
    + $KSYSTEM
    + https://github.com/hyphop/khadas-rescue/blob/master/docs/README-linux-krescue-mega.md

" >&2
exit 1
}

HELP(){ echo "$USAGE">&2
exit 1
}

#echo "[i] ARGS: $@">&2

#NOOP=


SILENT=

GET=$(which curl)
### CURL
[ "$GET" ] && {
GET="curl -jkfL"
SILENT="-s"
PROGRESS="-#"
}

[ "$GET" ] || {
    GET=$(which wget)
## WGET
    [ "$GET" ] && {
    SILENT="-q"
    PROGRESS=""
    GET="wget -O-"
    }
}

BOARD=

#SOC_ID="$(cat /sys/devices/soc0/soc_id 2>/dev/null)"

grep -q -e "CPU architecture: 8" -e "AArch64" -e "aarch64" /proc/cpuinfo && {

## detect cpu nums
CPUs=$(cat /sys/devices/system/cpu/possible)
CPUS=${CPUs#*-}
CPUS=$((CPUS+1))

for c in $CPUS; do
case "$c" in
    8)
    BOARD=VIM2
    ;;
    6)
    BOARD=VIM3
    ;;
    *)
    # S912  - VIM2
    # S905X - VIM1
    grep -q S905X /sys/devices/soc0/soc_id 2>/dev/null && {
    BOARD=VIM1
    break
    }
    grep -q S905X /proc/cpuinfo && {
    BOARD=VIM1
    break
    }
    grep -q VIM\$ /proc/cpuinfo && {
    BOARD=VIM1
    break
    }
    grep -q S905D3 /proc/cpuinfo && {
    BOARD=VIM3L
    break
    }
#    [ -d /sys/devices/armv8_pmuv3 ] && {
#    BOARD=VIM3L
#    break
#    }
#    # armv8_cortex_a53/	VIM2 / VIM1
#    [ -d /sys/devices/armv8_cortex_a53 ] && {
#    BOARD=VIM1
#    break
#    }
#    [ -d /sys/devices/armv8_* ] && {
#    BOARD=VIM1
#    break
#    }
    grep -q 450 /sys/class/misc/mali/device/uevent 2>/dev/null && {
    BOARD=VIM1
    break
    }
    grep -q khadas_board=VIM1 /proc/cmdline && {
    BOARD=VIM1
    break
    }
    ### may be ;)
    BOARD=VIM3L
    ;;
esac
done
}

AUTOINSTALL=
ONEONLY=
RO=
YES=
FORCE=
FULLONLY=

SD=
EMMC=

INFO(){
    echo "[i] DEVICE INFO">&2
    [ "$BOARD" ] && \
    echo "[i] BOARD NAME: $BOARD">&2
    [ "$BOARD" ] || \
    echo "[i] BOARD NAME: NOT DETECTED">&2


    [ "$BOARD" ] &&  {
	for d in /sys/block/mmcblk?; do
	    [ -d "$d" ] && {
		D=${d##*/}
		[ -d "$d/${D}boot0" ] || {
		T="SD card   "
		SD="/dev/$D"
		}
		[ -d "$d/${D}boot0" ] && {
		T="eMMC      "
		EMMC="/dev/$D"
		}
		echo "[i] $T: /dev/$D">&2
	    }
	done
    }

    OT=
    T="$(readlink /proc/$$/fd/1)"
    [ -b "$T" ] && {
	[ "$T" = "$SD" ] && OT=" (SD card)"
	[ "$T" = "$EMMC" ] && OT=" (eMMC)"
	echo "[i] OUTPUT    : $T $OT">&2
    }


    exit 0
}

for i in $@; do
case "$i" in
    -i|--info)
    INFO
    exit 0
    ;;
    -n|--noop)
    NOOP=1
    shift
    ;;
    -f|--full)
    FULLONLY=1
    ;;
    -A|--autoinstall)
    AUTOINSTALL=1
    shift
    ;;
    -r|--ro)
    RO=1
    shift
    ;;
    -Y|--yes)
    YES=1
    shift
    ;;
    -y|--force)
    YES=2
    FORCE=1
    shift
    ;;
    -b|--board)
    [ "$BOARD" ] || {
    echo "[e] VIM board not detected">&2
    exit 1
    }
    echo "$BOARD"
    exit 0
    ;;
    -h|--help)
    HELP
    ;;
    -u|--usage|--about)
    USAGE
    ;;
esac
done

[ "$1" ] || USAGE

Q="$1"

CMD(){
    echo "# $@">&2
    $@
}

QM=

[ "$BOARD" ] && {
    echo "[i] $BOARD detected">&2
}

CHKOUT(){
    T="$(readlink /proc/$$/fd/1)"
    [ -b "$T" ] && {
	echo "[e] rejected STDOUT output to BLOCKDEV $T">&2
	exit 1
    }
}

WRONG_NAME(){
    echo "[e] wrong krescue sys name: $@">&2
    echo "[i] plz use [ Edge | VIM1 | VIM2 | VIM3 | VIM3 | -X ] or read --help">&2
    exit 1
}

case $Q in
    "-")
    NOOP=1
    ;;
    -l|--list)
    #curl -# -sjkLf
    CHKOUT
    CMD $GET $KIMAGES | egrep -o \"V.+.kresq\" | egrep -o V.+.kresq
    exit
    ;;
    -L|--links)
    CHKOUT
    echo "# $KIMAGES">&2
    for i in $($GET $KIMAGES | egrep -o \"V.+.kresq\" | egrep -o V.+.kresq); do
	echo "$KIMAGES/$i"
    done
    exit
    ;;
    -e|*Edge*|*EDGE*|*edge*)
    [ -f "$Q" ] || \
    Q=Edge.krescue.sd.img.gz
    QM=Edge
    ;;
    -1|*vim1*|*VIM1*)
    [ -f "$Q" ] || \
    Q=VIM1.krescue.sd.img.gz
    QM=VIM1
    ;;
    -2|*vim2*|*VIM2*)
    [ -f "$Q" ] || \
    Q=VIM2.krescue.sd.img.gz
    QM=VIM2
    ;;
    -3l|-3L|*vim3l*|*VIM3L*)
    [ -f "$Q" ] || \
    Q=VIM3L.krescue.sd.img.gz
    QM=VIM3L
    ;;
    -3|*vim3*|*VIM3*)
    [ -f "$Q" ] || \
    Q=VIM3.krescue.sd.img.gz
    QM=VIM3
    ;;
    -X|--auto|-x)
    
    [ "$BOARD" ] || {
	echo "[w] board name not detected">&2
	exit 1
    }
    [ "$Q" = "-x" ] && YES=1

    Q="$BOARD.krescue.sd.img.gz"
    QM="$BOARD"
    ;;
#    http://*)
#    ;;
    *)
    WRONG_NAME "$Q"
    ;;
esac

shift
#[ "$1" ] || HELP

IMAGES=

[ "$NOOP" ] && echo "[i] NOOP mode - only test">&2

UNSAFE(){
    echo "[w] plz use -Y or -y for unsafe writes $@">&2
    exit 1
}

UNSAFE2(){
    echo "[w] use sudo or login as root for unsafe writes $@">&2
    [ "$FORCE" ] && echo "[w] force mode ignore all">&2
    [ "$FORCE" ] || {
    exit 1
    }
}

REMOUNTRO(){
    echo "[i] system goto RO only ">&2
    ## check sysrq
    [ -e /proc/sys/kernel/sysrq ] || {
	echo "[w] uuups !!! RO fail !!! wait 5 sec !! or CTRL+C for escape">&2
	[ "$FORCE" ] || {
	    echo "[i] plz use -y for ignore all errors and warnings">&2
	    exit 1
	}
	sleep 5
    }
    # prepare for ...
    [ -e /proc/sys/kernel/sysrq ] && {
    echo 1 > /proc/sys/kernel/sysrq || UNSAFE2 "$@"
    }
    # ro mode for all fs
    # and save write for blockdev
    [ -e /proc/sysrq-trigger ] && {
    echo u > /proc/sysrq-trigger || UNSAFE2 "$@"
    }
    # more silent
    echo 1 > /proc/sys/kernel/printk
}


MEGA(){
echo "[i] OUTPUT > $O">&2
src="$KSYSTEM/$Q"

[ -e "$Q" ] && {
    echo "[i] read Krescue system ($QM) from local file $Q">&2
    [ "$NOOP" ] || {
    gzip -dc "$Q"
    }
}
[ -e "$Q" ] || {
echo "[i] download Krescue system ($QM) from $src">&2
    [ "$NOOP" ] || {
    #curl -jkLf
    $GET "$src" | gzip -dc
    }
}

images=0
for i in $IMAGES ; do
    [ "$i" ] && {
    
    src="$KIMAGES/$i"

	case "$i" in
	    http:*|https:*)
	    src="$i"
	    ;;
	esac

	case "$src" in
	    *.kresq|*.zst|*.zstd)
	    ;;
	    *)
	    echo "[w] unknown image type: $src">&2
	    continue
	esac


	    [ -e "$i" ] && {
	    echo "[i] read local file $i">&2
	    [ "$NOOP" ] || \
	    cat "$i" && images=$((images+1))
	    }
	    [ -e "$i" ] || {
	    echo "[i] download image $src">&2
	    [ "$NOOP" ] || \
	    #curl -jkLf
	    $GET "$src" && images=$((images+1))
	    }
	
    }

    ## need only one image
    [ "$AUTOINSTALL" ] && break
    [ "$ONEONLY" ] && break

done

    [ "$AUTOINSTALL" ] && {
    echo "[i] autoinstall configure (total images: $images)">&2
    AUTOCONFIG=
    [ "$images" -gt "0" ] && AUTOCONFIG="autoinstall: 1"

    [ "$NOOP" ] || \
	echo "
##KRESCUE_CONFIG##
$AUTOCONFIG
##KRESCUE-CONFIG##
"
    }
}

MATCH=
MATCHES=
M=
for i in $@; do
case $i in
    --all|-a)
    #curl -sjkLf
    IMAGES=$(echo $($GET $KIMAGES 2>/dev/null | egrep -o \"V.+.kresq\" | egrep -o V.+.kresq))
    echo "[i] mega write all images">&2
    echo "< $IMAGES">&2
    shift
    [ "$1" ] && HELP
    ;;
    --math|-m)
	shift
	echo "[i] mega write matched by: $@">&2
        MATCH=1
    ;;
    -M)
	shift
	case "$1" in
	    VIM*|vim*)
	    QM="$1"
	    M=1
	    shift
	    ;;
	    Edge*|edge*|EDGE*)
	    QM="$1"
	    M=1
	    shift
	    ;;
	esac

	echo "[i] mega write matched for $QM by: $@">&2
        MATCH=2
    ;;
    *.kresq)
    ;;
    *)
    [ "$MATCH" ] && {
	[ "$M" ] && {
	M=
	continue
	}
	MATCHES="$MATCHES -e $i"
	continue
    }
    HELP
esac
done

    [ "$MATCH" ] && {
	[ "$MATCH" -lt "2" ] && {
        IMAGES=$(echo $($GET $KIMAGES 2>/dev/null | egrep -o \"V.+.kresq\" | egrep -o V.+.kresq | egrep -i $MATCHES ))
	}
	[ "$MATCH" -gt "1" ] && {
        IMAGES=$(echo $($GET $KIMAGES 2>/dev/null | egrep -o \"V.+.kresq\" | egrep -o V.+.kresq | grep -i $QM. | egrep -i $MATCHES ))
	}
	echo "[i] MATCHES $QM: $MATCHES">&2
	[ "$IMAGES" ] || {
	    echo "[e] not have any matches by $MATCHES">&2
	    exit 1
	}
	echo "[i] MATCHED $IMAGES">&2
    }

T="$(readlink /proc/$$/fd/1)"
O="$(basename $Q)"
O="${O%.img.gz}.mega.img"

DEV=${T#/dev/}
D=${T#/dev/mmcblk}
PIPE=
case $T in
    /dev/pts*)
    ;;
    /dev/tty*)
    ;;
    *pipe:*)
    O="PIPE"
    PIPE=1
    ;;
    ## detect partitions write
    /dev/mmcblk0p*|/dev/mmcblk1p*|/dev/mmcblk2p*|/dev/sd??)
	echo "[e] dont write to partitions: $T">&2
	exit 1
    ;;
    /dev/*)
    [ -b "$T" ] || {
	echo "[e] block device not exist: $T">&2
	exit 1
    }
    ## detect wrong system write
    [ "$BOARD" ] || {
	grep -q $T /proc/mounts && {
	echo "[e] wrong write to $T mounted device or system disk writes">&2
	echo "[e] plz umount $T at first and try again">&2
	exit 1
	}
    }

    ## auto goto RO
    [ "$BOARD" ] && {
	## detect root or bootable dev write
	[ -d /sys/block/$DEV/rootfs -o -d /sys/block/$DEV/${DEV}boot0 ] && {
	    echo "[i] auto detect unsafe write to rootfs bootable device and set force system RO">&2
	    [ "$YES" ] || UNSAFE $T

	    ## write only if same
	    [ "$QM" = "$BOARD" ] || {
		echo "[e] selected wrong board $QM == valid board name is $BOARD">&2
		echo "[i] plz use -X key for replace valid board NAME">&2
		exit 1
	    }

	    RO=1
	    ONEONLY=1
	    AUTOINSTALL=1
	}

	## detect mount
	grep -q $T /proc/mounts && {
	    echo "[w] auto detect unsafe write to mounted disk $T">&2
	    echo "[i] try umount it">&2
	    for m in $(grep $T /proc/mounts | egrep -o '/dev/\S+'); do
		echo "[i] unmount $m">&2
		umount $m || {
		    [ "$YES" ] || UNSAFE $T
		}
	    done
	}

	## check mount again
	grep -q $T /proc/mounts && {
	    echo "[w] auto detect unsafe write and set force system RO">&2
	    [ "$YES" ] || UNSAFE $T
	    RO=1
	    ONEONLY=1
	    AUTOINSTALL=1
	}

	## detect emmc write
	grep -q "MMC" /sys/class/mmc_host/mmc$D/mmc$D\:*/type 2>/dev/null && {
	    echo "[i] auto detect emmc write force system RO + autoinstall + only one image ">&2
	    [ "$YES" ] || UNSAFE $T
	    RO=1
	    ONEONLY=1
	    AUTOINSTALL=1
	}

    }
    
    O="$T"
    ;;
    *)
    O="$T"
esac

[ "$RO" ] && {
    [ "$BOARD" ] || {
    echo "[w] no need RO mode ! its only for VIM board users">&2
    RO=
    }
}

[ "$MATCH" ] || IMAGES="$@"

[ "$NOOP" ] && {
    MEGA "$@"
    return
}

[ "$RO" ] && REMOUNTRO

[ "$PIPE" ] && {
    MEGA
    sync
    exit
}

MEGA > $O
sync

## END ##

