#!/bin/sh
#
# Copyright (c) 2014 Paratronic, All Right Reserved.
#

PATH=/bin:/sbin:/usr/bin:/usr/sbin

exec 2>/dev/console
exec 1>/dev/console

firmware_dir="$( cd "$( dirname "$0" )" && pwd )"

. "$firmware_dir/functions"
. /etc/channels

chroot_dir=/mnt/chrootfs
newroot=/mnt/newroot
rfs1_name=rootfs
rfs2_name=rootfs2
ubidev=/dev/ubi0
new_rfs=$firmware_dir/rootfs.ubifs
data_dev=ubi0:data

dtb_img=$firmware_dir/lns.dtb
kernel_img=$firmware_dir/uImage
bootpri_img=$firmware_dir/at91sam9x5ek-boot-linux-uimage-dt-3.6.2.bin
bootsec_img=$firmware_dir/u-boot.bin
bootenv_img='' # set to none to erase

# get the current software version
# (as it could be 2.0dev, we are removing everything from the 1st non number)
MAJOR=$(cut -d '-' -f1 < /etc/version | cut -d '.' -f1)
MINOR=$(cut -d '-' -f1 < /etc/version | cut -d '.' -f2 | sed 's/^\([0-9]\+\).*$/\1/')
REV=$(cut -d '-' -f1 < /etc/version | cut -d '.' -f3 | sed 's/^\([0-9]\+\).*$/\1/')
EXTRA=$(cut -d '-' -f1 < /etc/version | cut -d '.' -f2 | sed 's/^[0-9]\+\(.*$\)/\1/')
if [ -z "$EXTRA" ]; then
	EXTRA=$(cut -d '-' -f1 < /etc/version | cut -d '.' -f3 | sed 's/^[0-9]\+\(.*$\)/\1/')
fi

# force as number
[ "$MAJOR" -eq "$MAJOR" ] 2>/dev/null || MAJOR=0
[ "$MINOR" -eq "$MINOR" ] 2>/dev/null || MINOR=0
[ "$REV" -eq "$REV" ] 2>/dev/null || REV=0

# returns:
# 0 if the current version is lower than the given version
# 1 if the current version is equal than the given version
# 2 if the current version is greater than the given version
# (because -1 is not a legal number)
version_compare() {
	local check_major check_minor check_rev

	check_major=$(echo "$1" | cut -d '.' -f1)
	check_minor=$(echo "$1" | cut -d '.' -f2)
	check_rev=$(echo "$1" | cut -d '.' -f3)

	[ "$check_major" -eq "$check_major" ] 2>/dev/null || check_major=0
	[ "$check_minor" -eq "$check_minor" ] 2>/dev/null || check_minor=0
	[ "$check_rev" -eq "$check_rev" ] 2>/dev/null || check_rev=0

	[ "$MAJOR" -lt "$check_major" ] && return 0
	if [ "$MAJOR" -eq "$check_major" ]; then
		[ "$MINOR" -lt "$check_minor" ] && return 0
		if [ "$MINOR" -eq "$check_minor" ]; then
			[ "$REV" -lt "$check_rev" ] && return 0
			[ "$REV" -eq "$check_rev" ] && return 1
			[ "$REV" -gt "$check_rev" ] && return 2
		fi
		# $MINOR -gt $check_minor
		return 2
	fi
	# $MAJOR -gt $check_major

	return 2
}

log_reprog() {
	local msg

	# we can only log if version >= 1.6.4
	version_compare 1.6.4
	if [ $? -eq 0 ]; then
		return
	fi
	msg=""
	case "$LANG" in
		en*)
			case "$1" in
				start_upgrade) msg="Starting upgrade procedure" ;;
				mount_rw_err) msg="Error remounting / in read-write mode" ;;
			esac
			;;
		*)
			case "$1" in
				start_upgrade) msg="Démarrage d'une mise à jour" ;;
				mount_rw_err) msg="Erreur de remontage de / en lecture-écriture" ;;
			esac
			;;
	esac
	write_channel_cmd "$log_ch_path" "log_evt 39 v$MAJOR.$MINOR.$REV$EXTRA $msg" 1000 "log_evt commande_ok" 2>/dev/null 1>/dev/null
}

try_hard () {
	$@
	if [ $? -ne 0 ] ; then
		for i in 1 1 1 ; do
			sleep 1
			$@
			if [ $? -eq 0 ]; then
				break
			fi
		done
	fi
}

flash_rfs() {
	local err

	err=0

	for i in $(seq 1 10) ; do
		rfs2_id=$(ubi_get_vol_nb "$rfs2_name")

		echo_both "Found volume id=$rfs2_id"
		if [ "x$rfs2_id" = "x" ] ; then
			# no secondary rfs, create it
			echo_both Creating New root file system volume
			ubimkvol "$ubidev" -N "$rfs2_name" -m
			if [ $? -ne 0 ] ; then
				echo_both "ERROR: Unable to create a new RFS."
				log crit "ERROR: Unable to create a new RFS."
				err=1
				continue
			fi
			rfs2_id=$(ubi_get_vol_nb "$rfs2_name")
			if [ "x$rfs2_id" = "x" ] ; then
				echo_both "ERROR: can't find new RFS."
				err=1
				continue
			fi
		fi

		echo_both Flashing new root filesystem...
		ubiupdatevol "/dev/$rfs2_id" "$new_rfs"
		if [ $? -ne 0 ] ; then
			echo_both "Error while flashing new root FS."
			log crit "Error while flashing new root FS."
			err=1
			ubirmvol "$ubidev" -N "$rfs2_name"
		else
			err=0
			break
		fi
	done

	if [ $err -eq 1 ]; then
		exit 1
	fi

}

flash_part() {
	local type part file

	part="$1"
	shift
	file="$1"

	type="$(cat "/sys/class/mtd/mtd$part/type")"

	if [ "$type" != "nand" ] && [ "$type" != "nor" ]; then
		echo_both "Can't find flash type part=$part file=$file"
		return 1
	fi

	if [ ! -f "$file" ]; then
		log err "File $file doesn't exists"
		return 1
	fi

	if [ ! -s "$file" ]; then
		log err "File $file is empty"
		return 1
	fi

	len="$(wc -c < "$file")"
	sum="$(md5sum "$file" | cut -d ' ' -f1)"

	[ "$len" -eq "$len" ] 2>/dev/null
	if [ $? -ne 0 ]; then
		log err "Unable to get file $file length"
		return 1
	fi

	echo_both "Size to flash: $len"
	echo_both "Checksum: $sum"

	for i in $(seq 1 10) ; do
		if [ "$type" = "nand" ]; then
			echo_both "Checking if version changed..."
			check=$(nanddump "/dev/mtd$part" --bb=skipbad -l $len -a | md5sum | cut -d ' ' -f1)
			retval=$?
			if [ $? -ne 0 ]; then
				echo_both "ERROR: nanddump returned $retval"
				continue
			fi
			if [ x"$check" = x"$sum" ]; then
				echo_both "Same version, skipping."
				break
			fi

			echo_both Erasing...
			flash_erase "/dev/mtd$part" 0 0
			retval=$?
			if [ $? -ne 0 ]; then
				echo_both "ERROR: flash_erase returned $retval"
				continue
			fi

			echo_both Flashing...
			nandwrite -p -m "/dev/mtd$part" "$file"
			retval=$?
			if [ $? -ne 0 ]; then
				echo_both "ERROR: nandwrite returned $retval"
				continue
			fi

			echo_both Verifiying Checksum...
			check=$(nanddump "/dev/mtd$part" --bb=skipbad -l $len -a | md5sum | cut -d ' ' -f1)
			retval=$?
			if [ $? -ne 0 ]; then
				echo_both "ERROR: nanddump returned $retval"
				continue
			fi
		else
			echo_both "Checking if version changed..."
			check=$(dd if="/dev/mtd$part" bs=$len count=1 | md5sum | cut -d ' ' -f1)
			retval=$?
			if [ $? -ne 0 ]; then
				echo_both "ERROR: dd returned $retval"
				continue
			fi
			if [ x"$check" = x"$sum" ]; then
				echo_both "Same version, skipping."
				break
			fi

			echo_both Flashing...
			flashcp "$file" "/dev/mtd$part"
			retval=$?
			if [ $? -ne 0 ]; then
				echo_both "ERROR: flashcp returned $retval"
				continue
			fi

			echo_both Verifiying Checksum...
			check=$(dd if="/dev/mtd$part" bs=$len count=1 | md5sum | cut -d ' ' -f1)
			retval=$?
			if [ $? -ne 0 ]; then
				echo_both "ERROR: dd returned $retval"
				continue
			fi
		fi
		if [ x"$check" = x"$sum" ]; then
			echo_both Checksum OK.
			break;
		else
			echo_both "Wrong Checksum! $check instead of $sum"
			sleep 2
		fi
	done
}

erase_part() {
	local part

	part=$1

	echo_both Erasing...
	flash_erase "/dev/mtd$part" 0 0
	retval=$?
	if [ $? -ne 0 ]; then
		echo_both "ERROR: flash_erase returned $retval while erasing part mtd$part"
		return 1
	else
		echo_both "Erased Ok."
	fi

	return 0
}

verify_checksum() {
	local file checksum

	file="$1"
	shift
	checksum="$1"
	shift

	if [ -f "$file" ] ; then
		sum="$(md5sum "$file" | cut -d ' ' -f1)"
		if [ "$sum" != "$checksum" ]; then
			log err "Wrong checksum for file $file ! USB key must be corrupted !"
			echo_both "Wrong checksum for file $file ! USB key must be corrupted !"
			sleep 5
			rm /tmp/control/start_reprog
			touch /tmp/control/reboot_reprog
			sleep 3
			reboot
			exit
		fi
	fi
}

# Reprog phase 1:
# Flash RFS on a second UBI volume
# if ok, flash the kernel, dtb, bootloaders...
# substitute init with this script
# reboot for phase 2
phase1() {
	killall lns_ihm 2>/dev/null
	killall lighttpd 2>/dev/null
	touch /tmp/control/start_reprog

	lcd_on
	console_on
	clear_console

	log_reprog "start_upgrade"

	# verify images checksums
	verify_checksum "$new_rfs" "f26e736b88a71fbb0b7836842138bb4e"
	verify_checksum "$kernel_img" "b145d9e5780cba609a9cdfde62e3d0fb"
	verify_checksum "$dtb_img" "a8e3766de20858cefc12740ff496eea3"
	verify_checksum "$bootpri_img" "907928b947105ca847eda67e773ca393"
	verify_checksum "$bootsec_img" "230d78db1ee10c0f16c3d0e541148509"
	verify_checksum "$bootenv_img" "@BOOTENV_CKSUM@"

	if [ -e "$new_rfs" ] ; then
		mount -oremount,rw /
		if [ $? -ne 0 ]; then
			log_reprog "mount_rw_err"
			echo_both "Failed to remount RFS in RW mode. Aborting"
			rm /tmp/control/start_reprog
			sleep 3
			reboot
		fi
		flash_rfs

		# make some room by removing a big app
		rm -f /usr/bin/lns_ihm

		echo_both "Copying $0 for phase 2"
		cp "$0" /update.sh
		if [ $? -ne 0 ]; then
			echo_both "Failed to copy $0."
		fi
		cp "$firmware_dir/functions" /sbin
		if [ $? -ne 0 ]; then
			echo_both "Failed to copy $firmware_dir/functions"
		fi
		cd /sbin
		ln -sf /update.sh init
		if [ $? -ne 0 ]; then
			echo_both "Failed to link update.sh"
		fi
		# removing now unused logs
		rm -f /var/log/conf-manager.log*
		rm -f /var/log/default.log*
		rm -f /var/log/user.log*
		sync
	fi
	for mtd in $(seq 0 32) ; do
		if [ ! -d "/sys/class/mtd/mtd$mtd" ]; then
			# no more device
			break
		fi
		if [ ! -e "/sys/class/mtd/mtd$mtd/name" ]; then
			continue
		fi
		case "$(cat "/sys/class/mtd/mtd$mtd/name")" in
			"dtb") dtb_part_nb="$mtd" ;;
			"kernel") kernel_part_nb="$mtd" ;;
			"bootpri") bootpri_part_nb="$mtd" ;;
			"bootsec") bootsec_part_nb="$mtd" ;;
			"bootenv") bootenv_part_nb="$mtd" ;;
			*) continue ;;
		esac
	done

	if [ -e "$kernel_img" ] ; then
		echo_both Flashing kernel...
		flash_part "$kernel_part_nb" "$kernel_img"
	fi
	if [ -e "$dtb_img" ]; then
		echo_both Flashing device tree...
		flash_part "$dtb_part_nb" "$dtb_img"
	fi
	if [ -e "$bootpri_img" ]; then
		echo_both Flashing primary bootloader...
		flash_part "$bootpri_part_nb" "$bootpri_img"
	fi
	if [ -e "$bootsec_img" ]; then
		echo_both Flashing secondary bootloader...
		flash_part "$bootsec_part_nb" "$bootsec_img"
	fi
	if [ -e "$bootenv_img" ]; then
		echo_both Flashing secondary bootloader environment...
		flash_part "$bootenv_part_nb" "$bootenv_img"
	else
		if [ x"$bootenv_img" = x"none" ]; then
			erase_part "$bootenv_part_nb"
		fi
	fi

	echo_both Rebooting...
	sync
	touch /tmp/control/reboot_reprog
	sleep 5
	reboot
}


show_programming_screen() {
	local tts
	tts=$1

	# the lower board need quite some time to flash itself
	# for 162KB, it was 12sec.
	echo_lcd "Programming."
	echo_lcd
	echo_lcd -n "Please Wait."
	printf "Waiting for lower board"
	for i in $(seq 1 $tts) ; do
		sleep 1
		echo_lcd -n "."
		printf "."
	done
	echo_lcd
}

get_lower_board_version() {
	local MAX_TRIES root mc_path STM32_VERSION

	root="$1"
	mc_path="$2"
	MAX_TRIES="$3"

	while [ $MAX_TRIES -ne 0 ]; do
		"$root"/usr/bin/purge_channel "$mc_path/0"
		sleep 1
		STM32_VERSION="$("$root"/usr/bin/write_channel_cmd "$mc_path"/1 info_produit 1000 info_produit)"
		if [ $? -ne 0 ]; then
			log err "Failed to read stm32 version"
			echo_lcd "Failed to read stm32 version"
		else
			break
		fi
		MAX_TRIES=$(( MAX_TRIES - 1 ))
	done
	echo "$STM32_VERSION"
}

update_lower_board() {
	local LOWER_BOARD_FW MAX_TRIES WAIT_SEC lower_failed multichannel_path

	LOWER_BOARD_FW="$newroot/LNS.bix"
	MAX_TRIES=10
	WAIT_SEC=20
	multichannel_path=/tmp/multichannel/SPI
	lower_failed=0
	BIX_VERSION=""

	# Lower board firmware
	if [ -e "$LOWER_BOARD_FW" ] ; then
		BIX_VERSION=$(head -1 "$LOWER_BOARD_FW" | tr "\000" "\n"| head -1 | cut -d ' ' -f4)

		mkdir -p "$multichannel_path"
		/etc/init.d/S*multichannel.sh start

		echo_lcd
		echo_lcd
		echo_lcd "New firmware for lower board."
		echo_lcd
		echo_lcd "Transfering firmware. Please wait."
		echo_lcd
		while [ $MAX_TRIES -ne 0 ]; do
			printf "Flashing lower board: "
			flash_lower_board "$LOWER_BOARD_FW" "$multichannel_path"
			if [ $? -ne 0 ] ; then
				# damned ! it failed. What can we do ?
				echo_lcd "Problem communicating with lower board."
				echo_lcd
				echo_lcd "Flash procedure FAILED."
				echo "Failed!"
				log err "Failed flashing lower board"
			else
				echo_lcd "Firmware transfered to lower board."
				echo_lcd
				echo "OK"
				break
			fi

			MAX_TRIES=$(( MAX_TRIES - 1 ))
			# there must be a bug somewhere, sometime the lower board
			# fails on "run update"
			# so we discuss on a dummy channel, wait a little and retry
			if [ $MAX_TRIES -gt 0 ]; then
				echo_lcd "Retrying in 1 sec."
				echo_lcd
				purge_channel "$multichannel_path/0"
				sleep 1
			else
				echo_lcd "Failed. Lower board won't be flashed"
				echo_lcd
				lower_failed=1
			fi
		done
		if [ $lower_failed -eq 0 ]; then
			show_programming_screen $WAIT_SEC
		fi
	fi

	# If the lower board has been flashed all right, we can use the new multichannel version
	# And if it has failed, we also have to try the new version.
	if [ $lower_failed -eq 1 ]; then
		# in this case, we may have flashed a non-compatible multichannel version
		# so we have to try with the new multichannel daemon
		echo_both "Retrying with newer multichannel version"
	fi
	# Switching to the new multichannel version
	killall multichannel
	sleep 1
	killall -9 multichannel
	sleep 1
	"${newroot}"/usr/bin/multichannel "${newroot}"/etc/multichannel.conf &
	sleep 3

	STM32_VERSION=$(get_lower_board_version "$newroot" "$multichannel_path" 2)
	printf "STM32 version: %s\n" "$STM32_VERSION"

	if [ -n "$STM32_VERSION" ]; then
		# There's life !
		lower_failed=0

		STM32_VERSION="$(echo "$STM32_VERSION" |  cut -d ' ' -f4)"

		echo "version read $STM32_VERSION vs BIX: $BIX_VERSION"
		# even if bix_version is not set, it doesn't hurt to reboot lowerboard
		if [ "$STM32_VERSION" != "$BIX_VERSION" ]; then
			# Hack to program STM32 with bad bootloader
			# Send spi command "Write Enable for Volatile Status Register" (0x50)
			# to have a correct status register on bootloader start
			echo "."
			echo_lcd "VERSION DIFFERENT"
			echo_lcd "STM32: $STM32_VERSION"
			echo_lcd "BIX  : $BIX_VERSION"
			"$newroot"/usr/bin/write_channel_cmd "$multichannel_path"/1 "run SPI" 1000 "run SPI" 2>/dev/null 1>/dev/null
			"$newroot"/usr/bin/write_channel_cmd "$multichannel_path"/37 "command 1 1 1 0x50" 1000 "commande_ok" 2>/dev/null 1>/dev/null
			"$newroot"/usr/bin/write_channel_cmd "$multichannel_path"/1 "reboot" 1000 "reboot" 2>/dev/null 1>/dev/null
			show_programming_screen $WAIT_SEC
			# even if it didn't worked, we can't do anything else.
		fi
	fi
	# else... well, we can't talk to lower board, so we can't do anything.
	# let's not be stuck in reprog.

	if [ $lower_failed -eq 0 ]; then
		echo_lcd "Done."
		log notice "Lower board flashed ok."
		echo "Done."
	fi
	clear_console
	lcd_off

	killall multichannel
	sleep 1
	killall -9 multichannel
	return $lower_failed
}

panic() {
	lcd_on
	echo_lcd
	echo_lcd
	echo_lcd "FATAL ERROR !"
	echo_lcd
	echo_lcd "LOWER BOARD UPDATE FAILED."
	echo_lcd
	echo_lcd "If it's the first time, try to reset the LNS."
	echo_lcd
	echo_lcd "Otherwise, nothing can be done."
	sleep 30
	if [ ! -e /proc/sysrq-trigger ] ; then
		mount -n -t proc none /proc
	fi
	echo r > /proc/sysrq-trigger
	echo e > /proc/sysrq-trigger
	echo i > /proc/sysrq-trigger
	echo s > /proc/sysrq-trigger
	echo u > /proc/sysrq-trigger
	echo b > /proc/sysrq-trigger
	# this *should* be unreacheable code
	# but in case mount proc failed,
	# we just exit, the kernel will then panic and reboot.
	sleep 1
	exit 1
}

# Reprog phase 2:
# chroot to tmpfs
# atomically exchange UBI RFS1/2 volumes
# boot on RFS
phase2() {
	# we start by upgrading the old lower board
	# software with the old interface.
	# that way, even if there's a protocol change,
	# everything should work
	mount -n -t proc none /proc
	mount -n -t tmpfs none /tmp
	mount -n -t devtmpfs none /dev
	mount -n -t sysfs none /sys
	mount -n -oremount,rw /
	rm -fr "$newroot" "$chroot_dir"
	mkdir -p "$newroot"
	mount -n -tubifs ubi0:rootfs2 "$newroot"

	# tel the STM32 that we are up and running
	echo "19" > "/sys/class/gpio/export"
	echo out > "/sys/class/gpio/pioA19/direction"
	echo 1 > "/sys/class/gpio/pioA19/value"

	# Try to convert the old config
	if [ -e "$newroot/usr/bin/import_lns_config.sh" ]; then
		mount -n -tubifs "$data_dev" "$newroot"/data


		# migrate old photo/video directories
		if [ ! -e "$newroot/data/media" ]; then
			mkdir -p "$newroot/data/media"
		fi
		for i in photos videos; do
			if [ -e "$newroot/data/$i" ]; then
				mv -f "$newroot/data/$i" "$newroot/data/media/"
			fi
		done

		chroot "$newroot" import_lns_config.sh --dev-friendly /data/config/lns.xml /data/config/lns.xml.new
		if [ -e "$newroot/data/config/lns.xml.new" ]; then
			sync
			mv "$newroot/data/config/lns.xml" "$newroot/data/config/lns.xml.old"
			mv "$newroot/data/config/lns.xml.new" "$newroot/data/config/lns.xml"
			sync
		fi
		try_hard umount -n "$newroot"/data
	fi

	# make some place for the new kernel modules by removing
	# old kernel modules and big applications/libs
	rm -fr /lib/modules/
	find /usr/ -size +1024k -print0 | xargs -0 rm -f
	sync

	# those modules are for our kernel
	cp -a "${newroot}/lib/modules" /lib/
	if [ $? -ne 0 ]; then
		# there's still not enough space.
		# we MUST have at least some space
		# for chrooting, so we remove all modules.
		# We won't have any display, but at least we
		# won't get stuck here.
		rm -fr /lib/modules/
	fi

	console_on
	stty -F /dev/ttyS3 57600 raw
	lcd_on
	clear_console
	update_lower_board
	if [ $? -ne 0 ]; then
		# this is really annoying.
		# what can we do beside crying ?
		panic
	fi
	umount -n /tmp
	umount -n /dev
	umount -n /sys
	umount -n /proc
	try_hard umount -n "$newroot"
	echo Populating new root FS
	mkdir -p "$chroot_dir"
	mount -n -t tmpfs -osize=70% none "$chroot_dir"
	if [ $? -ne 0 ]; then
		# this is really annoying.
		# what can we do beside crying ?
		panic
	fi
	cd "$chroot_dir"
	mkdir -p bin lib sbin dev sys proc tmp mnt usr/sbin usr/sbin data
	cp -dp /bin/* bin/
	cp -dp /sbin/* sbin/
	cp -dp /lib/* lib/
	cp -dp /usr/sbin/ubi* usr/sbin/
	cp "$firmware_dir/functions" .


	echo Changing root
	pivot_root . mnt

	echo Mounting proc and sys
	mount -n -t devtmpfs none dev
	mount -n -t proc none proc
	mount -n -t sysfs none sys

	echo_both Redirecting I/O
	exec 0</dev/console
	exec 1>/dev/console
	exec 2>/dev/console

	cat >/swap_rfs.sh<< EOF
#!/bin/sh

. /functions

force_reboot() {
	if [ ! -e /proc/sysrq-trigger ] ; then
		mount -n -t proc none /proc
	fi
	echo r > /proc/sysrq-trigger
	echo e > /proc/sysrq-trigger
	echo i > /proc/sysrq-trigger
	echo s > /proc/sysrq-trigger
	echo u > /proc/sysrq-trigger
	echo b > /proc/sysrq-trigger

	# this *should* be unreacheable code
	# but in case mount proc failed,
	# we just exit, the kernel will then panic and reboot.
	sleep 1
	exit 1
}

umount_or_reboot() {
	umount \$@
	if [ \$? -ne 0 ]; then
		sleep 1
		umount \$@
		if [ \$? -ne 0 ] ; then
			force_reboot
		fi
	fi
}

try_hard () {
	\$@
	if [ \$? -ne 0 ] ; then
		for i in 1 1 1 ; do
			sleep 1
			\$@
			if [ \$? -eq 0 ]; then
				break
			fi
		done
	fi
}

for i in \$(cut -d' ' -f2 /proc/mounts | grep '/mnt' | sort -r ) ; do
	echo_both Unmounting \$i
	umount_or_reboot \$i
done
echo_both Atomically swaping new and old root file systems
echo_both ubirename $ubidev $rfs1_name $rfs2_name $rfs2_name $rfs1_name
try_hard ubirename $ubidev $rfs1_name $rfs2_name $rfs2_name $rfs1_name
if [ \$? -ne 0 ] ; then
	echo_both ERROR on ubirename. ABORTING.
	force_reboot
fi

echo_both Mounting new RFS
mount -n -oro -t ubifs ubi0:$rfs1_name /mnt

echo_both Changing root
# clear console now, otherwise the messages will stay there
clear_console
cd /mnt
pivot_root . tmp

echo Mount /dev
mount -n -t devtmpfs none dev

echo Redirecting I/O
exec 0</dev/console
exec 1>/dev/console
exec 2>/dev/console

echo Umounting proc and sys
cd /
umount_or_reboot /tmp/proc
umount_or_reboot /tmp/sys
umount_or_reboot /tmp/dev
# NB: we can't unmount the tmpfs we're on.
# anyway, it will be already there

# removing files from tmpfs
rm -fr /tmp/bin /tmp/sbin /tmp/lib /tmp/usr/sbin

# flag to force sending the configuration to the lower board
# in an early stage
touch /tmp/new_lower_fimware

echo Booting new system
exec chroot . /sbin/init

EOF
	chmod +x /swap_rfs.sh

	echo_both Chroot in new root
	exec chroot . /swap_rfs.sh
}

self=$(basename "$0")

if [ "$self" = "init" ] ; then
	phase2
else
	phase1
fi
