#!/bin/sh
# --- T2-COPYRIGHT-NOTE-BEGIN ---
# This copyright note is auto-generated by scripts/Create-CopyPatch.
# 
# T2 SDE: target/share/install/init
# Copyright (C) 2020 The T2 SDE Project
# 
# More information can be found in the files COPYING and README.
# 
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License. A copy of the
# GNU General Public License can be found in the file COPYING.
# --- T2-COPYRIGHT-NOTE-END ---

# T2 SDE: target/share/install/init
# Partially based on linuxrc.c, Copyright (C) 2003, 2004 Clifford Wolf and Rene Rebe
# Converted from C to shell, heavily cleaned and improved for the T2 SDE by:

# Only print important stuff to console
# klogctl(8, NULL, 3);

doboot() {
	if [ ! -e /sbin/init ]; then
	 	echo "Can't find /sbin/init."
		exit_linuxrc=0
	fi

	if [ $exit_linuxrc = 1 ]; then
		echo "finished ... continuing execution of second stage"
		# we re-use all stage1 stuff, mounts, udev, you name it!
		exec /sbin/init
	fi
}

trymount() {
	# try best match / detected rootfs first, all the others thereafter
	local filesystems=`disktype $1 2>/dev/null |
	      sed -e '/file system/!d' -e 's/file system.*//' -e 's/ //g' \
	          -e 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/' \
	          -e 's/fat32/vfat/'
	      sed '1!G ; $p ; h ; d' /proc/filesystems | sed /^nodev/d`
	for fs in $filesystems; do
		mount -t $fs -o ro $1 $2 && return
	done
}

filter_for() {
	case "$1" in
		*.bz2)	echo bunzip2 ;;
		*.zst)	echo unzstd ;;
		*.gz)	echo gunzip ;;
		*) echo cat ;;
	esac
}

select_stage2() {
	# choices
	case $1 in
	  http://*|ftp://*)
		# the last sed is a uniq
		images=`fget $1/ | sed 's/[<>"]/\n/g' | sed -n '/stage2/p' |
sed 'h;:b
$b
N; /^\(.*\)\n\1$/ {g; bb
}
$b
P; D'`
		;;
	  *)
		mkdir -p /mnt/source
		trymount $1 /mnt/source
		images=`cd /mnt/source; ls stage2*.tar*`
		umount /mnt/source
		;;
	esac

	[ "$images" ] || return 1

	mem=`sed -n '/MemTotal/{s/.* \([[:digit:]]*\) .*/\1/p}' /proc/meminfo`
	if [ $mem -le 512000 ]; then
		echo "Deleting /lib/firmware to save memory"
		rm -rf /lib/firmware
	fi

	echo "Select a second stage image file:"
	i=1; default=$i
	for x in $images; do
		if [[ "$x" = *ext* ]]; then
			[ $mem -gt 384000 ] && default=$i
		else
			[ $mem -le 384000 ] && default=$i
		fi
		echo "     $((i++)). $x"
	done
	[ $mem -le 64000 ] && autoload=0
	echo -n "Enter number or image file names (default=$default): "

	in=; [ $autoload = 0 ] && read in || echo
	[ "$in" ] || in=$default

	i=1
	for x in $images; do
		if [ "$((i++))" = "$in" ]; then
			i=${x%.tar.*} # add base "stage2.tar.*"?
			if [ "$i" != "stage2" ]; then
				x="stage2.${x#stage2*.} $x"
			fi
			eval $2=\"$x\"
			return
		fi
	done
	eval $2=\"$in\"
}

httpload() {
	baseurl=
	filename=
	url=

	echo -en "\nEnter base URL (e.g. http://1.2.3.4/t2): "

	read baseurl
	[ "$baseurl" ] || return

	select_stage2 "$baseurl" filename
	if [ -z "$filename" ]; then
		echo "Failure retrieving the second stage image."
		return
	fi

	exit_init=1
	export ROCK_INSTALL_SOURCE_URL=$baseurl
	exit_linuxrc=1

	echo "Extracting second stage filesystem ..."
	filter=`filter_for "$filename"`
	mv /bin/{,.}tar
	for f in $filename; do
		url=$baseurl/$f
		fget $url | $filter | (cd /; .tar x)
	done
	rm /bin/.tar

	doboot
}

load_modules() {
	echo "TODO: implement module loading shell"
}

getdevice() {
	device=
	devicelist=

	# if no dev, wait for devices to appear, default Linux USB settle delay is 5s
	local i=0; local default=
	while [ -z "$devicelist" -a $i -le 6 ]; do
		# with udev the above links are not created yet, so try to find
		# device based on sysfs
		local j=1
		for x in /sys/block/*/device; do
			[ -e "$x" ] || continue
			x=${x#/sys/block/}; x=${x%/device}
			[[ "$x" = fd* ]] && continue
			local dev=/dev/$x; [ -L "$dev" ] && dev=$(readlink "$dev")

			x=${x#/dev/}
			local vendor="$(cat /sys/block/$x/device/vendor 2>/dev/null)"
			local model="$(cat /sys/block/$x/device/model 2>/dev/null)"

			# all partitions
			local devs=`echo ${dev}*`
			local parts=""
			if [ "$devs" != "$dev" ]; then
				parts=1
				echo "        $dev     $vendor $model" # header
				vendor=""
				model=""
			fi
			for d in $devs; do
				if [ -z "$parts" -o "$d" != "$dev" ]; then
					echo "     $j. $d${vendor:+     $vendor $model}"
					devicelist="$devicelist $d"
					[ -z "$default" -a "$(< /sys/block/$x/removable)" == 1 ] && default=$j
					: $((j++))
				fi
			done
		done

		if [ -z "$devicelist" ]; then
			echo "Waiting for devices to appear."
	 	 	sleep 1
		fi

		: $((i++))
	done

	if [ -z "$devicelist" ]; then
		echo "No device found."
		return
	fi

	[ "$default" ] || default=1
	echo -en "\nEnter number or device file name (default=$default): "

	in=; [ $autoload = 0 ] && read in || echo
	[ "$in" ] || in=$default
	while [ -z "$device" ]; do
		[ -z "$in" ] && return
		if [ -e $in ]; then
			device=$in
		else
			local i=1
			for x in $devicelist; do
				[ $in = $i ] && device=$x && break
				: $((i++))
			done
		fi

		if [ -z "$device" ]; then
			echo -n "No such device found. Try again (enter=back): "
			read in
		fi
	done

	eval $1=$device
}

load_ramdisk_file() {
	devicefile=
	filename=

	echo -e "\nSelect a device for loading the second stage system from:\n"

	getdevice devicefile
	if [ -z "$devicefile" ]; then
		echo "No device detected."
		return
	fi

	select_stage2 $devicefile filename
	if [ -z "$filename" ]; then
		echo "No image found."
		return
	fi

	exit_linuxrc=1
	echo "Using $devicefile:$filename"

	mkdir -p /mnt/source || exit_linuxrc=0
	trymount $devicefile /mnt/source || exit_linuxrc=0

	echo "Extracting second stage filesystem ..."
	filter=`filter_for "$filename"`
	mv /bin/{,.}tar
	for f in $filename; do
		if ! $filter < /mnt/source/$f | (cd /; .tar x); then
			echo "Error extracting $f."
			exit_linuxrc=0
		fi
	done

	umount /mnt/source || exit_linuxrc=0

	export ROCK_INSTALL_SOURCE_DEV=$devicefile
	export ROCK_INSTALL_SOURCE_FILE=$filename
	doboot
}

activate_swap() {
	echo -ne "\nEnter file name of swap device: "

	read in
	[ "$in" ] && swapon $in
}

net_config() {
	echo -n "Interfaces: "; ls -A /sys/class/net/

	echo -n "Enter interface name (eth0): "
	read dev; [ "$dev" ] || dev="eth0"

	echo -n "Enter IP address (auto): "
	read ip
	if [ "$ip" ]; then
		echo -n "Enter default gateway (none): "
		read gw
		ipconfig $ip::$gw:::$dev:none 
	else
		# let the link autoneg.
		ipconfig :::::$dev:none > /dev/null 2>&1 ; sleep 4
		echo "Auto configuration via DHCP, BOOTP, RARP ..."
		ipconfig -d $dev -t 10
	fi
}

exec_sh() {
	echo "Exit the shell to return to the 1st stage loader."
	sh
}

load_modules_disk() {
	mkdir /mnt_floppy

	trymount /dev/floppy/0 /mnt_floppy
	load_modules /mnt_floppy

	umount /mnt_floppy
	rmdir  /mnt_floppy
}

# try to auto-load from a disc, first
autoload=1

echo "
T2 SDE installer (1st stage - loader) ...

The T2 install system boots up in two stages. You are now in the first stage
and if everything goes right, you will not spend much time here. Just 
configure the installation source so the second stage boot system can be
loaded and you can start the installation."
exit_init=0
while [ $exit_init = 0 ]; do
	echo -n "
     0. Load second stage system from local device
     1. Load second stage system from network
     2. Configure network interfaces
     3. Load kernel modules from this disk
     4. Load kernel modules from another disk
     5. Activate already formatted swap device
     6. Run shell (for experts!)

What do you want to do [0-8] (default=0)? "

	in=; [ $autoload = 0 ] && read in || echo
	[ "$in" ] || in=0
	case $in in
	  0)	load_ramdisk_file ;;
	  1)	httpload ;;
	  2)	net_config ;;
	  3)	load_modules ;;
	  4)	load_modules_disk ;;
	  5)	activate_swap ;;
	  6)	exec_sh ;;
	  *)    echo "No such option." ;;
	esac
	# only try autoload once
	autoload=0
done

exec /sbin/init /sbin/init

echo -e "\nPanic: Can't start /sbin/init!\n\n"
