#!/bin/bash

function tftp_err()
{
	if [ "$quiet" = "0" ]; then
		echo "$1"
		exit 1
	fi
}

function tftp_fetch()
{
	if [ "$1" = "-q" ]; then
		quiet=1
		shift
	else
		quiet=0
	fi

	if [ ! -z "$local_dir" ]; then
		if [ -e $local_dir/$2 ]; then
			cp $local_dir/$2 $3
			return 0
		elif [ -e $local_dir/${2##*/} ]; then
			cp $local_dir/${2##*/} $3
			return 0
		else
			tftp_err "ERROR: can't find ${2##*/} in $local_dir"
			return 1
		fi
	fi
	echo "Fetching via tftp: $1:$2"
	if [ $tftp_block_size = 0 ]; then
		if ! tftp -g $1 -r $2 -l $3; then
		   tftp_err "ERROR: tftp failed. Aborting."
		   return 1
	   fi
	else
		if ! tftp -g $1 -r $2 -l $3 -b $tftp_block_size; then
		   tftp_err "ERROR: tftp failed. Aborting."
		   return 1
	   fi
	fi
	return 0
}

function find_mtd_partition()
{
	local arg=$1
	local out=$2
	for x in /sys/class/mtd/mtd*; do
		if [ -e $x/name ]; then
			name=$(cat $x/name)

			# 0x400 = MTD_WRITEABLE
			flags=$(cat $x/flags)
			if [ "$name" = "$arg" \
					-a $(($flags & 0x400)) != 0 ]; then
				eval $out=${x#*mtd/mtd}
				return 0
			fi
		fi
	done
	return 1
}

#From a given disk parition name, find the associated partition number & node
#argument 2 : (input) disk block
#argument 1 : (input) partition name to search for
#argument 3 : (output) partition number
#argument 3 : (output) partition node
#return : 0 if found, else 1
function find_disk_partition()
{
	local d_block=$1
	local p_name=${2#*.}
	local p_number=${2}_part_num
	local p_node=${2}_part_node
	local p_entry=

	[ -b /dev/$d_block ] && p_entry=$(sgdisk -p /dev/$d_block | sed -e '1,/Number/ d' | sed -n "/\<$p_name\>/p")
	[ -z "$p_entry" ] && return 1

	eval $p_number=$(echo $p_entry | sed -n 's/ .*//p')
	case "$d_block" in
		*[0-9] )
		eval $p_node=/dev/${d_block}p${!p_number}
		;;
		*[a-z] )
		eval $p_node=/dev/${d_block}${!p_number}
		;;
	esac

	return 0
}

function find_thumbdrive()
{
	thumbdrive=""
	local ret=1
	local block_dir dev dev_link old_sysfs

	if [ -d /sys/class/block ]; then
		unset old_sysfs
		block_dir="/sys/class/block"
	else
		old_sysfs=1
		block_dir="/sys/block"
	fi
	pushd "$block_dir" > /dev/null
	for dev in sd*; do
		[ "$old_sysfs" ] && dev_link="$dev/device" || dev_link="$dev"
		if [[ $(readlink "$dev_link") == *usb* ]]; then
			thumbdrive="$dev"
			if [ -e "${dev}/${dev}1" ]; then
				thumbdrive="${thumbdrive}1"
			fi
			ret=0
			break
		fi
	done
	popd > /dev/null
	return $ret
}

function get_mtd_attr()
{
	arg0=$1
	arg1=$2
	out=$3
	file=/sys/class/mtd/mtd${arg0}/$arg1
	if [ -e $file ]; then
		retval=$(cat $file)
		eval $out=$retval
	else
		echo $file
		return 1
	fi
	return 0
}

function flash_is_disk()
{
	local flash_type

	eval flash_type=\$${1}_flash_type
	[ "$flash_type" == "disk" ] && return 0 || return 1
}

function flash_is_nand()
{
	local flash_type

	eval flash_type=\$${1}_flash_type
	[ "$flash_type" == "nand" -o "$flash_type" == "mlc-nand" ] && return 0 || return 1
}

function flash_is_mtd()
{
	local part_name
	local part_node
	local part_num
	local sys_part_file
	local sys_part_name

	eval part_name=\$${1}_part_name
	eval part_node=\$${1}_part_node
	eval part_num=\$${1}_part_num
	sys_part_file=/sys/class/mtd/mtd${part_num}/name
	if [ -c "$part_node" -a -f $sys_part_file ]; then
		sys_part_name=$(cat ${sys_part_file})
		[ "$part_name" == "$sys_part_name" ] && return 0
	fi
	return 1
}

function check_root()
{
	# make sure that we are not reformatting the active rootfs
	if [ -h /dev/root ]; then
		rootdev=$(readlink /dev/root)
		while [ ! -z $1 ]; do
			if [[ $rootdev = ${1}* ]]; then
				echo ""
				echo "ERROR: please run stbutil from the initrd kernel."
				echo ""
				exit 1
			fi
			shift
		done
	fi
}

# create rootfs image at /mnt/hd
function write_rootfs()
{
	type="$1"

	echo ""
	echo "Writing rootfs..."
	echo ""

	if [ "$type" = "-linux" ]; then
		# Linux filesystems
		cd /mnt/hd
		mkdir {sys,proc,tmp,dev,mnt} mnt/{hd,flash,usb,nfs,cmnonvol}
		mknod dev/console c 5 1

		cd /
		for x in *; do
			if [ ! -e /mnt/hd/$x ]; then
				cp -a $x /mnt/hd/
			fi
		done
	else
		# DOS filesystems - no device nodes or symlinks
		rm -rf /tmp/stage
		mkdir /tmp/stage
		cd /tmp/stage
		mkdir {sys,proc,tmp,dev,mnt} mnt/{hd,flash,usb,nfs,cmnonvol}

		cd /
		for x in *; do
			if [ ! -e /tmp/stage/$x ]; then
				ln -s /$x /tmp/stage/
			fi
		done

		# erase any old versions present
		cd /tmp/stage
		for x in *; do
			rm -rf /mnt/hd/$x
		done

		cp -pLR * /mnt/hd/
	fi

	return 0
}

# copy ubi:ubivol to ext4
function write_ubi_to_ext4()
{
	local ubifs_file_path=$1
	local ubifs_part_node=$2
	local ubifs_vol_num=$3
	local ext4_part_node=$4
	local ubisquashfs=$5

	echo "1 4 1 7" > /proc/sys/kernel/printk
	ubiformat $ubifs_part_node --yes --flash-image=$ubifs_file_path -s 2048 > /dev/null
	ubiattach -p $ubifs_part_node -O 2048 -d 9 > /dev/null
	if [ -c /dev/ubi9_$ubifs_vol_num ]; then
		if [ "$ubisquashfs" == 1 ]; then
			ubiblock -c /dev/ubi9_$ubifs_vol_num > /dev/null
			mount -r -t squashfs /dev/ubiblock9_$ubifs_vol_num /mnt/flash > /dev/null
		else
			mount -r -t ubifs /dev/ubi9_$ubifs_vol_num /mnt/flash > /dev/null
		fi
		echo "7 4 1 7" > /proc/sys/kernel/printk
		mkfs.ext4 -FE stripe-width=32 $ext4_part_node
		tune2fs -c 0 -i 0 -o journal_data_ordered $ext4_part_node
		mount -t ext4 $ext4_part_node /mnt/hd
		echo "1 4 1 7" > /proc/sys/kernel/printk
		rm -rf /mnt/hd/lost+found/
		cp -ai /mnt/flash/. /mnt/hd/
		sync
		umount /mnt/hd
		umount /mnt/flash > /dev/null
	fi
	ubidetach -p $ubifs_part_node > /dev/null
	echo "7 4 1 7" > /proc/sys/kernel/printk
}

function refresh_bolt_cmdline()
{
	local rg_part_type=$def_boot
	local rg_apps_seal=n
	local RG_IDX=$(boltenv -g RG_IDX)
	local rg_root_node
	local rg_apps_node

	eval rg_root_node=$rg_root_eval
	eval rg_apps_node=$rg_apps_eval

	if flash_is_disk rg; then
		rg_part_type=ext4
		node_has_extfs $rg_apps_node && rg_apps_seal=y
	else
		if node_has_ubiblock_hsqs $rg_root_node; then
			rg_part_type=squashfs
		elif node_has_ubivol $rg_root_node; then
			rg_part_type=ubifs
		fi
		node_has_ubivol_apps $rg_root_node && rg_apps_seal=y
	fi

	eval help_cmdline=\$${rg_part_type}_help_cmdline
	eval bolt_cmdline=\$${rg_part_type}_bolt_cmdline
	bolt_cmdline=$(echo $bolt_cmdline | sed 's/ \([a-zA-Z0-9]*\)_apps//g')
	[ "$rg_apps_seal" == "y" ] && bolt_cmdline=$(echo $bolt_cmdline | sed "s/\<platformboot\>/& ${rg_part_type}_apps/")
}

function handle_kernel()
{
	local index=$1
	local kernelname=kernel${index}
	local kernel_part_node=kernel${index}_part_node
	local kernel_part_name=kernel${index}_bolt_name
	local cur_startup
	local cur_fstype

	echo "Writing kernel to ${!kernel_part_node}"
	echo

	rem_img=$(ls *.arm.kernel 2> /dev/null)
	if [ "$rem_img" == "" ]; then
		rem_img=vmlinuz-$plat
	fi

	if ! tftp_fetch "$tftphost" "$tftppath/$rem_img" "/tmp/vmlinuz"; then
		return 1
	fi
	if [ -f /tmp/vmlinuz ]; then
		if flash_is_mtd $kernelname; then
			flash_erase ${!kernel_part_node} 0 0
		fi
		if flash_is_nand kernel; then
			nandwrite -p ${!kernel_part_node} /tmp/vmlinuz
		else
			dd if=/tmp/vmlinuz of=${!kernel_part_node}
		fi
		rm -f /tmp/vmlinuz
	else
		echo ""
		echo "ERROR writing kernel to flash partition $index"
		echo ""
		return 1
	fi

	#3390 uses BOLT variables to track which bank is being used. Set the index to the bank being written.
	if [ "3390" == "${PLAT:0:4}" ]; then
		boltenv -s KL_IDX "$index"
		[ $? -ne 0 ] && echo "Failed to reset BOLT KL_IDX variable"
	fi

	cur_startup=$(boltenv -g STARTUP)
	[ $? -ne 0 ] && cur_startup=""
	cur_fstype=$(echo $cur_startup | sed -n 's/.*rootfstype=\([a-zA-Z0-9]*\).*/\1/p')
	[ -z "$cur_fstype" ] && cur_fstype=$def_boot
	eval help_cmdline=\$${cur_fstype}_help_cmdline

	echo ""
	echo "Finished writing kernel to flash partition $index."
	echo ""
	echo "To boot:"
	echo ""
	echo "  boot ${!kernel_part_name} $help_cmdline"
	echo ""
	return 0
}

# Install kernel to flash
function handle_opt_1()
{
	if ! handle_kernel 0; then
		return 1
	else
		return 0
	fi
}

# Install kernel to alternate flash partition
function handle_opt_13()
{
	if ! handle_kernel 1; then
		return 1
	else
		return 0
	fi
}

# Install UBIFS/EXT4 rootfs to flash
function handle_opt_2()
{
	check_root mtd ubi mmc
	rem_img=ubifs-$(($rootfs_flash_erasesize / 1024))k-$(($rootfs_flash_writesize))-${plat}-STB.img
	if ! tftp_fetch "$tftphost" "$tftppath/$rem_img" "/tmp/rootfs.img"; then
		exit 1
	fi
	if [ -f /tmp/rootfs.img ]; then
		if flash_is_mtd rootfs; then
			if [ "$rootfs_part_name" = "rootfs" ]; then
				# old style
				help_cmdline=ubiroot
			fi
			ubiformat $rootfs_part_node --yes --flash-image=/tmp/rootfs.img
		elif flash_is_disk rootfs; then
			write_ubi_to_ext4 /tmp/rootfs.img $nandsim_part_node 0 $rootfs_part_node 0
		fi
		rm -f /tmp/rootfs.img
	else
		echo ""
		echo "ERROR writing rootfs/boot_assist images to flash."
		echo ""
		exit 1
	fi

	echo ""
	echo "Finished writing rootfs/boot_assist images to flash."
	echo ""
	echo "Sample boot command line:"
	echo ""
	echo "  boot $tftphost:$tftppath/vmlinuz-$plat $help_cmdline"
	echo " Or: (if you have the kernel in flash using option 1)"
	echo "  boot flash0.kernel $help_cmdline"
	echo ""
	echo "To mount the filesystem now:"
	echo ""
	if flash_is_mtd rootfs; then
		echo "  ubiattach -m $rootfs_part_num"
		echo "  mount -t ubifs ubi0:rootfs /mnt/flash"
	elif flash_is_disk rootfs; then
		echo "  mount -t ext4 $rootfs_part_node /mnt/flash"
	fi
	echo ""
	return 0
}

# Install JFFS2 rootfs to flash
function handle_opt_3()
{
	check_root mtd ubi
	rem_img=jffs2-$(($rootfs_flash_erasesize / 1024))k-${plat}.img
	if ! tftp_fetch "$tftphost" "$tftppath/$rem_img" "/tmp/rootfs.img"; then
		exit 1
	fi
	if [ -f /tmp/rootfs.img ] && flash_is_mtd rootfs; then
		flash_erase -j $rootfs_part_node 0 0
		dd if=/tmp/rootfs.img of=$rootfs_part_node
		rm -f /tmp/rootfs.img
	else
		echo ""
		echo "ERROR writing rootfs to flash."
		echo ""
		exit 1
	fi

	echo ""
	echo "Finished writing rootfs to flash."
	echo ""
	echo "Sample boot command line:"
	echo ""
	echo "  boot $tftphost:$tftppath/vmlinuz-$plat 'rootfstype=jffs2 root=/dev/mtdblock${rootfs_part_num}'"
	echo ""
	echo "To mount the filesystem now:"
	echo ""
	echo "  mount -t jffs2 mtd${rootfs_part_num} /mnt/flash"
	echo ""
	return 0
}

# Install SQUASHFS rootfs to flash
function handle_opt_4()
{
	check_root mtd ubi mmc
	rem_img=squashfs-${plat}.img
	if ! tftp_fetch "$tftphost" "$tftppath/$rem_img" "/tmp/rootfs.img"; then
		exit 1
	fi
	if [ -f /tmp/rootfs.img ]; then
		if flash_is_disk rootfs; then
			dd if=/tmp/rootfs.img of=$rootfs_part_node
			help_cmdline="\"root=$root_part_node rootfstype=squashfs mmc_core.removable=0\""
		elif flash_is_nand rootfs; then
			imgsize=$(du -k /tmp/rootfs.img | sed 's/[ \t].*//')
			ubiformat $rootfs_part_node --yes
			ubiattach -m $rootfs_part_num -d 0
			# NOTE: ubiattach/mdev may run asynchronously
			while [ ! -e /dev/ubi0 ]; do
				sleep 1
			done
			ubimkvol /dev/ubi0 -N squashfs -s ${imgsize}KiB
			if ! find_mtd_partition squashfs newpart; then
				echo "ERROR: can't find new squashfs partition"
				exit 1
			fi
			if ! get_mtd_attr $newpart erasesize new_erasesize; then
				echo "ERROR: can't get gluebi erasesize"
				exit 1
			fi
			dd if=/tmp/rootfs.img of=/dev/mtdblock${newpart} bs=$new_erasesize
			ubidetach -d 0
			help_cmdline="\"ubi.mtd=$root_part_name rootfstype=squashfs root=/dev/mtdblock${newpart}\""
		else
			flash_erase $rootfs_part_node 0 0
			newpart=$rootfs_part_num
			dd if=/tmp/rootfs.img of=$rootfs_part_node
			help_cmdline="\"ubi.mtd=$root_part_name rootfstype=squashfs root=/dev/mtdblock${newpart}\""
		fi
		rm -f /tmp/rootfs.img
	else
		echo ""
		echo "ERROR writing rootfs to flash"
		echo ""
		exit 1
	fi

	echo ""
	echo "Finished writing rootfs to flash."
	echo ""
	echo "Sample boot command line:"
	echo ""
	echo "  boot $tftphost:$tftppath/vmlinuz-$plat $help_cmdline"
	echo ""
	echo "To mount the filesystem now:"
	echo ""
	if flash_is_disk rootfs; then
		echo "  mount -t squashfs $rootfs_part_node /mnt/flash"
	elif flash_is_nand rootfs; then
		echo "  ubiattach -m $rootfs_part_num"
		echo "  mount /dev/mtdblock${newpart} /mnt/flash"
		echo ""
		echo "OPTIONAL: Add a RW 'data' UBIFS to the same MTD partition:"
		echo ""
		echo "  ubiattach -m $rootfs_part_num"
		echo "  ubimkvol /dev/ubi0 -N data -m"
		echo "  mount -t ubifs ubi0:data /data"
	else
		echo "  mount /dev/mtdblock${newpart} /mnt/flash"
	fi
	echo ""
	return 0
}

# Install rootfs to hard drive
function handle_opt_5()
{
	check_root ${hdd_dev##*/}
	echo "Writing partition table..."

	sgdisk -Z ${hdd_dev} || true
	sgdisk ${hdd_dev} \
		-n 1:2048:8390655 -t 1:0700 -c 1:"rootfs" \
		-n 2:8390656:16779263 -t 2:8200 -c 2:"swap" \
		-n 3:16779264:33556479 -t 3:0700 -c 3:"application" \
		-N 4 -t 4:0700 -c 4:"video"

	# Give mdev time to create the device nodes
	sleep 2

	# Enable swap; mke2fs on multi-terabyte drives can malloc
	# upwards of 80MB
	mkswap ${hdd_dev}2
	swapon ${hdd_dev}2

	mkfs.ext4 -E stripe-width=32 ${hdd_dev}1
	mkfs.ext4 -E stripe-width=32 ${hdd_dev}3
	mkfs.ext4 -E stripe-width=32 -i 262144 ${hdd_dev}4

	tune2fs -c 0 -i 0 -o journal_data_ordered ${hdd_dev}1
	tune2fs -c 0 -i 0 -o journal_data_ordered ${hdd_dev}3
	tune2fs -c 0 -i 0 -o journal_data_writeback ${hdd_dev}4

	swapoff ${hdd_dev}2

	# mount and populate the partitions
	fstab=/etc/fstab-ext4

	mount ${hdd_dev}1 /mnt/hd
	write_rootfs -linux
	cp -f $fstab /mnt/hd/etc/fstab
	umount ${hdd_dev}1

	echo ""
	echo "Finished writing rootfs to hard drive."
	echo ""
	echo "Sample boot command line:"
	echo ""
	echo "  boot $tftphost:$tftppath/vmlinuz-$plat"
	echo ""
	echo "To mount the filesystem now:"
	echo ""
	echo "  mount ${hdd_dev}1 /mnt/hd"
	echo ""
	return 0
}

# Update rootfs on /dev/sdX1 (don't reformat other partitions)
function handle_opt_6()
{
	check_root ${hdd_dev##*/}

	mkfs.ext3 ${hdd_dev}1
	tune2fs -i 0 ${hdd_dev}1

	mount ${hdd_dev}1 /mnt/hd
	write_rootfs -linux
	umount ${hdd_dev}1

	echo ""
	echo "Finished refreshing the rootfs."
	echo ""
	return 0
}

function handle_opt_7()
{
	check_root $thumbdrive

	dev=/dev/${thumbdrive}

	mount ${dev} /mnt/hd
	if ! tftp_fetch "$tftphost" "$tftppath/vmlinuz-$plat" "/mnt/hd/vmlinuz-$plat"; then
		exit 1
	fi
	write_rootfs -dos
	umount ${dev}

	echo ""
	echo "Finished writing rootfs to USB thumbdrive."
	echo ""
	echo "Sample boot command line:"
	echo ""
	echo "  boot usbdisk0:vmlinuz-$plat 'rootwait root=/dev/$thumbdrive'"
	echo ""
	echo "To mount the filesystem now:"
	echo ""
	echo "  mount ${dev} /mnt/flash"
	echo ""
	return 0
}

function handle_rg()
{
	local index=$1
	local rgname=rg${index}
	local rg_part_node=rg${index}_part_node
	local rg_part_num=rg${index}_part_num

	local apps_part_node=apps${index}_part_node
	local ubisquashfs=0
	local rg_part_type=$def_boot
	local rg_apps_sign=0
	local cur_startup
	local bak_startup
	local cur_fstype

	check_root mtd ubi mmc
	rem_img=$(ls *.arm.rg.fs 2> /dev/null)
	if [ "$rem_img" == "" ]; then
		if [ -z $2 ]; then    # Second arg only set when we want legacy UBIFS behavior
			rem_img=ubi-squashfs-$(($rg_flash_erasesize / 1024))k-$(($rg_flash_writesize))-${plat}-RG.img
		else
			# Legacy behavior - UBIFS rootfs
			rem_img=ubifs-$(($rg_flash_erasesize / 1024))k-$(($rg_flash_writesize))-${plat}-RG.img
		fi
	fi
	if ! tftp_fetch "$tftphost" "$tftppath/$rem_img" "/tmp/rootfs.img"; then
		return 1
	fi
	if [ -f /tmp/rootfs.img ]; then
		if node_has_ubiblock_hsqs /tmp/rootfs.img $rg_flash_erasesize $rg_flash_subpagesize; then
			rg_part_type=squashfs
			ubisquashfs=1
		elif node_has_ubivol /tmp/rootfs.img $rg_flash_erasesize $rg_flash_subpagesize; then
			rg_part_type=ubifs
		else
			echo ""
			echo "ERROR parsing RG images for flash partition $index."
			echo ""
			return 1
		fi

		if node_has_ubivol_apps /tmp/rootfs.img $rg_flash_erasesize $rg_flash_subpagesize; then
			rg_apps_sign=1
		fi

		if flash_is_mtd $rgname; then
			ubiformat ${!rg_part_node} --yes --flash-image=/tmp/rootfs.img
		elif flash_is_disk rg; then
			rg_part_type=ext4
			write_ubi_to_ext4 /tmp/rootfs.img $nandsim_part_node 0 ${!rg_part_node} $ubisquashfs
		fi
		if flash_is_disk apps; then
			if [ "$rg_apps_sign" == 1 ]; then
				write_ubi_to_ext4 /tmp/rootfs.img $nandsim_part_node 1 ${!apps_part_node} $ubisquashfs
			elif node_has_extfs ${!apps_part_node}; then
				dd if=/dev/zero of=${!apps_part_node} seek=1080 bs=1 count=2 >/dev/null 2>&1
			fi
		fi
		rm -f /tmp/rootfs.img
	else
		echo ""
		echo "ERROR fetching RG rootfs/apps for flash partition $index."
		echo ""
		return 1
	fi

	#3390 uses BOLT variables to track which bank is being used. Set the index to the bank being written.
	if [ "3390" == "${PLAT:0:4}" ]; then
		cur_startup=$(boltenv -g STARTUP)
		[ $? -ne 0 ] && cur_startup=""

		bak_startup="$cur_startup"
		cur_fstype=$(echo $cur_startup | sed -n 's/.*rootfstype=\([a-zA-Z0-9]*\).*/\1/p')
		if [ "$cur_fstype" != "$rg_part_type" ]; then
			eval bolt_cmdline=\$${rg_part_type}_bolt_cmdline
			cur_startup="load -nz -raw -addr=\$DT_ADDRESS -max=0x10000 $bolt_devtree;\$PREBOOT;boot $bolt_kernel $bolt_cmdline"
		fi

		if echo $cur_startup | grep mmcblk0 >/dev/null; then
			if [ -n "$RG_BLK" ]; then
				echo $cur_startup | grep RG_BLK >/dev/null
				[ $? -ne 0 ] && cur_startup=$(echo $cur_startup | sed -n 's/mmcblk0p[0-9]*/mmcblk0p\$RG_BLK/p')
			else
				eval RG_BLK=\$rg${index}_part_num
				echo $cur_startup | grep "mmcblk0p$RG_BLK" >/dev/null
				[ $? -ne 0 ] && cur_startup=$(echo $cur_startup | sed -n "s/mmcblk0p[\$A-Z_0-9]*/mmcblk0p$RG_BLK/p")
			fi
		fi

		cur_startup=$(echo $cur_startup | sed 's/ \([a-zA-Z0-9]*\)_apps//g')
		if [ $rg_apps_sign -eq 1 ]; then
			cur_startup=$(echo $cur_startup | sed "s/\<platformboot\>/& ${rg_part_type}_apps/")
		fi

		if [ "$bak_startup" != "$cur_startup" ]; then
			# Save backup copy of the STARTUP string if not duplicate
			[ -n "$bak_startup" ] && boltenv -s BAK_STARTUP "$bak_startup" >/dev/null
			boltenv -s STARTUP "$cur_startup" >/dev/null
		fi

		boltenv -s RG_IDX "$index"
		[ $? -ne 0 ] && echo "Failed to reset BOLT RG_IDX variable"
	fi

	eval help_cmdline=\$${rg_part_type}_help_cmdline
	echo ""
	echo "Finished writing RG $rg_part_type rootfs to flash partition $index."
	echo ""
	echo "  boot $tftphost:$tftppath/vmlinuz-$plat $help_cmdline"
	echo ""
	echo "To mount the RG $rg_part_type rootfs/apps now:"
	echo ""
	if flash_is_mtd $rgname; then
		echo "  ubiattach -m ${!rg_part_num}"
		if [ "$ubisquashfs" == 1 ]; then
			echo "  ubiblock -c /dev/ubi0_0"
			[ $rg_apps_sign -eq 1 ] && echo "  ubiblock -c /dev/ubi0_1"
			echo "  mount -r -t squashfs /dev/ubiblock0_0 /mnt/flash"
			[ $rg_apps_sign -eq 1 ] && echo "  mount -r -t squashfs /dev/ubiblock0_1 /mnt/apps"
		else
			echo "  mount -r -t ubifs ubi0:rootfs /mnt/flash"
			[ $rg_apps_sign -eq 1 ] && echo "  mount -t ubifs ubi0:apps /mnt/apps"
		fi
	elif flash_is_disk rg; then
		echo "  mount -t ext4 ${!rg_part_node} /mnt/flash"
		[ $rg_apps_sign -eq 1 ] && echo "  mount -t ext4 ${!apps_part_node} /mnt/apps"
	fi

	echo ""
	echo "To unmount the RG $rg_part_type rootfs/apps then:"
	echo ""
	echo "  umount /mnt/flash"
	[ $rg_apps_sign -eq 1 ] && echo "  umount /mnt/apps"
	if flash_is_mtd $rgname; then
		if [ "$ubisquashfs" == 1 ]; then
			echo "  ubiblock -r /dev/ubi0_0"
			[ $rg_apps_sign -eq 1 ] && echo "  ubiblock -r /dev/ubi0_1"
		fi
		echo "  ubidetach -m ${!rg_part_num}"
	fi
	echo ""
	return 0
}

# Install UBI-SQUASHFS rootfs to RG flash partition
function handle_opt_8()
{
	if ! handle_rg 0; then
		return 1
	else
		return 0
	fi
}

# Install UBI-SQUASHFS rootfs to alternate RG flash partition
function handle_opt_12()
{
	if ! handle_rg 1; then
		return 1
	else
		return 0
	fi
}

function handle_cm()
{
	local index=$1
	local cmname=cm${index}
	local cm_part_node=cm${index}_part_node
	local cm_part_num=cm${index}_part_num
	local ubisquashfs=0
	local cm_part_type
	local cur_startup
	local cur_fstype

	check_root mtd ubi mmc
	rem_img=$(ls *.arm.ecos.fs 2> /dev/null)
	if [ "$rem_img" == "" ]; then
		if [ "3390" == "${PLAT:0:4}" ]; then
			if [ -z $2 ]; then   # Second arg only set when we want legacy UBIFS behavior
				rem_img=ubi-squashfs-$(($cm_flash_erasesize / 1024))k-$(($cm_flash_writesize))-${plat}-CM.img
			else
				# Legacy behavior - UBIFS rootfs
				rem_img=ubifs-$(($cm_flash_erasesize / 1024))k-$(($cm_flash_writesize))-${plat}-CM.img
			fi
		else
			rem_img=ubifs-$(($cm_flash_erasesize / 1024))k-$(($cm_flash_writesize))-${plat}-SVM.img
		fi
	fi
	if ! tftp_fetch "$tftphost" "$tftppath/$rem_img" "/tmp/rootfs.img"; then
		return 1
	fi
	if [ -f /tmp/rootfs.img ]; then
		if node_has_ubiblock_hsqs /tmp/rootfs.img $cm_flash_erasesize $cm_flash_subpagesize; then
			cm_part_type=squashfs
			ubisquashfs=1
		elif node_has_ubivol /tmp/rootfs.img $cm_flash_erasesize $cm_flash_subpagesize; then
			cm_part_type=ubifs
		else
			echo ""
			echo "ERROR parsing CM images for flash partition $index."
			echo ""
			return 1
		fi

		if flash_is_mtd $cmname; then
			ubiformat ${!cm_part_node} --yes --flash-image=/tmp/rootfs.img
		elif flash_is_disk cm; then
			cm_part_type=ext4
			write_ubi_to_ext4 /tmp/rootfs.img $nandsim_part_node 0 ${!cm_part_node} $ubisquashfs
		fi
		rm -f /tmp/rootfs.img
	else
		echo ""
		echo "ERROR fetching CM images for flash partition $index."
		echo ""
		return 1
	fi

	#3390 uses BOLT variables to track which bank is being used. Set the index to the bank being written.
	if [ "3390" == "${PLAT:0:4}" ]; then
		boltenv -s CM_IDX "$index"
		[ $? -ne 0 ] && echo "Failed to reset BOLT CM_IDX variable"
	fi

	cur_startup=$(boltenv -g STARTUP)
	[ $? -ne 0 ] && cur_startup=""
	cur_fstype=$(echo $cur_startup | sed -n 's/.*rootfstype=\([a-zA-Z0-9]*\).*/\1/p')
	[ -z "$cur_fstype" ] && cur_fstype=$def_boot
	eval help_cmdline=\$${cur_fstype}_help_cmdline

	echo ""
	echo "Finished writing CM $cm_part_type images to flash partition $index."
	echo ""
	echo "  boot $tftphost:$tftppath/vmlinuz-$plat $help_cmdline"
	echo ""
	echo "To mount the CM $cm_part_type images now:"
	echo ""

	if flash_is_mtd cm$index; then
		echo "  ubiattach -m ${!cm_part_num}"
		[ "$ubisquashfs" == 1 ] && echo "  ubiblock -c /dev/ubi0_0"
		if [ "$ubisquashfs" == 1 ]; then    # Second arg only set when we want legacy UBIFS behavior
			echo "  mount -r -t squashfs /dev/ubiblock0_0 /mnt/flash"
		else
			if flash_is_nand devtree; then
				echo "  mount -t ubifs ubi3:images /mnt/flash"
			else
				echo "  mount -t ubifs ubi1:images /mnt/flash"
			fi
		fi
	elif flash_is_disk cm; then
		echo "  mount -t ext4 ${!cm_part_node} /mnt/flash"
	fi
	echo ""
	echo "To unmount the CM $cm_part_type images then:"
	echo ""
	echo "  umount /mnt/flash"
	if flash_is_mtd $cmname; then
		[ "$ubisquashfs" == 1 ] && echo "  ubiblock -r /dev/ubi0_0"
		echo "  ubidetach -m ${!cm_part_num}"
	fi
	echo ""
	return 0
}

# Install CM UBI-SQUASHFS to CM flash partition
function handle_opt_9()
{
	if ! handle_cm 0; then
		return 1
	else
		return 0
	fi
}

# Install CM UBI-SQUASHFS to alternate CM flash partition
function handle_opt_11()
{
	if ! handle_cm 1; then
		return 1
	else
		return 0
	fi
}

function handle_dtb()
{
	local index=$1
	local devtreename=devtree${index}
	local devtree_part_node=devtree${index}_part_node
	local devtree_part_num=devtree${index}_part_num

	dt_owner="rg"
	echo "Writing $dt_owner devtree to ${!devtree_part_node}"
	echo

	rem_img=$(ls *.arm.devtree 2> /dev/null)
	if [ "$rem_img" == "" ]; then
		rem_img=$dt_owner.${plat}.dtb.tgz
	fi

	if ! tftp_fetch "$tftphost" "$tftppath/$rem_img" "/tmp/$dt_owner.${plat}.dtb.tgz"; then
		return 1
	fi
	dtbfile=/tmp/$dt_owner.${plat}.dtb.tgz
	if [ -f $dtbfile ]; then
		if flash_is_mtd $devtreename; then
			flash_erase ${!devtree_part_node} 0 0
		fi
		if flash_is_nand devtree; then
			nandwrite -p ${!devtree_part_node} $dtbfile
		else
			dd if=$dtbfile of=${!devtree_part_node}
		fi
		rm -f $dtbfile
		echo ""
		echo "Finished writing devtree $dtbfile to flash partition $index."
		echo ""
	else
		echo ""
		echo "ERROR writing devtree $dtbfile to flash partition $index."
		echo ""
		return 1
	fi

	#3390 uses BOLT variables to track which bank is being used.  Set the index to the bank being written.
	if [ "3390" == "${PLAT:0:4}" ]; then
		boltenv -s DT_IDX "$index"
		[ $? -ne 0 ] && echo "Failed to reset BOLT DT_IDX variable"
	fi

	echo ""
	echo "Finished writing $dt_owner devtree to flash partition $index."
	echo ""
	return 0
}

# Download and install the device tree tarball to its partition.
function handle_opt_10()
{
	if ! handle_dtb 0; then
		return 1
	else
		return 0
	fi
}

# Download and install the device tree tarball to its backup partition.
function handle_opt_14()
{
	if ! handle_dtb 1; then
		return 1
	else
		return 0
	fi
}

# Install UBIFS rootfs/apps to RG flash partition
function handle_opt_15()
{
	if ! handle_rg 0 ubifs; then
		return 1
	else
		return 0
	fi
}

# Install CM UBIFS to CM flash partition
function handle_opt_16()
{
	if ! handle_cm 0 ubifs; then
		return 1
	else
		return 0
	fi
}

# Install CM UBIFS to alternate CM flash partition
function handle_opt_17()
{
	if ! handle_cm 1 ubifs; then
		return 1
	else
		return 0
	fi
}

# Install UBIFS rootfs/apps to alternate RG flash partition
function handle_opt_18()
{
	if ! handle_rg 1 ubifs; then
		return 1
	else
		return 0
	fi
}

function handle_opt_0()
{
	local cur_startup
	local bak_startup
	local def_startup=0
	local upd_startup=0
	local cur_preboot
	local bak_preboot
	local def_preboot=0
	local upd_preboot=0

	cur_preboot=$(boltenv -g PREBOOT)
	[ $? -ne 0 ] && cur_preboot=""

	cur_startup=$(boltenv -g STARTUP)
	if [ $? -eq 0 ]; then
		echo "FYI, your STARTUP variable is set to the following:"
		echo "$cur_startup"
		echo
		if [ -n "$cur_preboot" ]; then
			echo "With PREBOOT set to the following:"
			echo "$cur_preboot"
		else
			echo "With PREBOOT unset"
		fi
		echo
	else
		cur_startup=""
	fi

	refresh_bolt_cmdline
	[ -z "$bolt_devtree" -o -z "$bolt_kernel" -o -z "$bolt_cmdline" ] && echo "Couldn't derive default STARTUP" && exit 1

	bak_startup="$cur_startup"
	cur_startup="load -nz -raw -addr=\$DT_ADDRESS -max=0x10000 $bolt_devtree;\$PREBOOT;boot $bolt_kernel $bolt_cmdline"
	[ "$bak_startup" == "$cur_startup" ] && def_startup=1

	bak_preboot="$cur_preboot"
	cur_preboot="dt add prop /ba rg-batt-mode s \"cpu-on\""
	[ "$bak_preboot" == "$cur_preboot" ] && def_preboot=1

	if [ $def_startup -eq 0 -o $def_preboot -eq 1 ]; then
		read -p "Set STARTUP to default value? (y/n) " -n 1 -r
		echo
		if [[ $REPLY =~ ^[Yy]$ ]]; then
			upd_startup=1
		fi
	fi
	if [ $upd_startup -eq 0 ]; then
		if [ $def_startup -eq 0 -o $def_preboot -eq 0 ]; then
			read -p "Set STARTUP to default ARM on battery value ? (y/n) " -n 1 -r
			echo
			if [[ $REPLY =~ ^[Yy]$ ]]; then
				upd_preboot=1
			fi
		fi
	fi

	if [ $upd_startup -eq 1 -o $upd_preboot -eq 1 ]; then
		if [ -n "$bak_startup" ]; then
			# Save backup copy of the STARTUP string if not duplicate
			if [ $def_startup -eq 0 ]; then
				boltenv -s BAK_STARTUP "$bak_startup"
			else
				echo "Not overwriting BAK_STARTUP with duplicate value"
			fi
		fi

		[ $def_startup -eq 0 ] && echo && boltenv -s STARTUP "$cur_startup"
		[ $upd_startup -eq 1 -a $def_preboot -eq 1 ] && echo && boltenv -u PREBOOT
		[ $upd_preboot -eq 1 -a $def_preboot -eq 0 ] && echo && boltenv -s PREBOOT "$cur_preboot"
	fi

	echo
}

function usage()
{
	cat << EOF

stbutil $version - Settop configuration utility
Copyright (C) 2019 Broadcom

Usage: stbutil [ -d <local_dir> ] [ -a <selection> ] [ -H <disk> ] [ <tftphost>[:<dir>] ]

Options:
	-d <local_dir>   Fetch images from LOCAL_DIR instead of tftp'ing them over the network
	-a <selection>   Use SELECTION as the menu item selection instead of prompting the user
	-H <disk>        Use hard drive DISK (default sda)
	-b <size>        Block size for TFTP transfers
	<tftphost>       TFTP server hostname
	<dir>            Directory (relative path) on TFTP server
	-p               Change platform value
	-u               Force UBIFS mode

Examples:
	stbutil
	stbutil linuxsrv:2631-1.0
	stbutil -d /mnt/usb
	stbutil -a1
	stbutil -a 1
	stbutil -d /mnt/usb -a 1
	stbutil -H sdb
	stbutil 192.168.0.6:
	stbutil -b 16000 192.168.0.6
	stbutil -p 3390b0-lattice-4.9

EOF
	exit 1
}

#
# MAIN
#
version=v5.32

rootfs_flash_erasesize=131072
rootfs_flash_writesize=2048

cm_flash_erasesize=131072
cm_flash_writesize=2048
cm_flash_subpagesize=2048

rg_flash_erasesize=131072
rg_flash_writesize=2048
rg_flash_subpagesize=2048

hdd_dev=/dev/sda

local_dir=
resp=
auto_resp=0
tftp_block_size=0

# Default fs to set for bootline.
def_boot=squashfs

if [ ! -e /etc/brcmstb.conf ]; then
	echo "ERROR: missing /etc/brcmstb.conf"
	TFTPHOST=
	TFTPPATH=
	PLAT="3390b0"
else
	source /etc/brcmstb.conf
fi

# Source rcS.util
if [ ! -e /etc/init.d/rcS.util ]; then
	echo "ERROR: missing /etc/init.d/rcS.util"
else
	. /etc/init.d/rcS.util
fi

# use default settings from brcmstb.conf
tftphost=$TFTPHOST
tftppath=$TFTPPATH
plat=$PLAT

# parse command line
while getopts "d:a:H:b:h:p:ru" opt; do
	case $opt in
		d)
			local_dir=$OPTARG
			;;
		a)
			resp=$OPTARG;
			auto_resp=1
			;;
		H)
			if [ -e /dev/$OPTARG ]; then
				hdd_dev=/dev/$OPTARG
			else
				echo "warning: /dev/$OPTARG does not exist"
			fi
			;;
		b)
			tftp_block_size=$OPTARG
			;;
		p)
			echo "Changing platform: $plat -> $OPTARG"
			plat=$OPTARG
			;;
		r)
			echo "Defaults to RDKM partition map"
			;;
		u)
			echo "UBIFS mode set"
			def_boot=ubifs
			;;
		h|?)
			usage
			;;
	esac
done
shift $(($OPTIND - 1))
if [ ! -z "$1" ]; then
	tftparg="$1"
	if [[ "$tftparg" = *:* ]]; then
		tftphost=${tftparg%%:*}
		tftppath=${tftparg#*:}
	else
		tftphost=$tftparg
		tftppath=""
	fi
fi


# Make sure emmcflash partitions are created first
if [ -b /dev/mmcblk0 ]; then
	part_names_pri="macadr nvram nvram1 devtree0 devtree1 debug cmnonvol0 cmnonvol1 rgnonvol0 rgnonvol1"
	part_string_pri="-n 1:128:+64K -c 1:macadr -n 2::+64K -c 2:nvram -n 3::+64K -c 3:nvram1 -n 4::+128K -c 4:devtree0 -n 5::+128K -c 5:devtree1 -n 6::+65024K -c 6:debug -n 7::+32M -c 7:cmnonvol0 -n 8::+32M -c 8:cmnonvol1 -n 9::+32M -c 9:rgnonvol0 -n 10::+32M -c 10:rgnonvol1"

	rootfs_part_names_sec="kernel rootfs"
	rootfs_part_string_sec="-n 1:1024:+196096K -c 1:debug -n 2::+64M -c 2:kernel -n 3::+1G -c 3:rootfs"

	rootfs_part_names_pri="$part_names_pri $rootfs_part_names_sec"
	rootfs_part_string_pri="$part_string_pri -n 11::+64M -c 11:kernel -n 12::+1G -c 12:rootfs"

	rgcmfs_part_names_sec="kernel0 kernel1 cm0 cm1 rdkbnvram0 rdkbnvram1 rg0 rg1 apps0 apps1"
	rgcmfs_part_string_sec="-n 1:1024:+196096K -c 1:debug -n 2::+32M -c 2:kernel0 -n 3::+32M -c 3:kernel1 -n 4::+128M -c 4:cm0 -n 5::+128M -c 5:cm1 -n 6::+128M -c 6:rdkbnvram0 -n 7::+128M -c 7:rdkbnvram1 -n 8::+256M -c 8:rg0 -n 9::+256M -c 9:rg1 -n 10::+128M -c 10:apps0 -n 11::+128M -c 11:apps1"

	rgcmfs_part_names_pri="$part_names_pri $rgcmfs_part_names_sec"
	rgcmfs_part_string_pri="$part_string_pri -n 11::+32M -c 11:kernel0 -n 12::+32M -c 12:kernel1 -n 13::+128M -c 13:cm0 -n 14::+128M -c 14:cm1 -n 15::+128M -c 15:rdkbnvram0 -n 16::+128M -c 16:rdkbnvram1 -n 17::+256M -c 17:rg0 -n 18::+256M -c 18:rg1 -n 19::+128M -c 19:apps0 -n 20::+128M -c 20:apps1"

	find_mtd_partition flash0.bolt bolt_part_num
	if [ $? -ne 0 ]; then
		find_mtd_partition flash0.fsbl bolt_part_num
	fi
	if [ $? -eq 0 ]; then
		# emmcflash is secondary flash
		emmc="emmcflash0."
		if find_disk_partition mmcblk0 rootfs; then
			part_names="debug $rootfs_part_names_sec"
			part_string="$rootfs_part_string_sec"
		else
			part_names="debug $rgcmfs_part_names_sec"
			part_string="$rgcmfs_part_string_sec"
		fi
	else
		# emmcflash is prinmary flash
		emmc="flash0."
		if find_disk_partition mmcblk0 rootfs; then
			part_names="$rootfs_part_names_pri"
			part_string="$rootfs_part_string_pri"
		else
			part_names="$rgcmfs_part_names_pri"
			part_string="$rgcmfs_part_string_pri"
		fi
	fi

	for part_name in $part_names; do
		if ! find_disk_partition mmcblk0 $part_name; then
			create_emmc_part=y
			break
		fi
	done

	if [ "$create_emmc_part" == "y" ]; then
		echo "1 4 1 7" > /proc/sys/kernel/printk
		sgdisk -Z /dev/mmcblk0 > /dev/null || true
		sgdisk -g -a 1 /dev/mmcblk0 $part_string > /dev/null
		echo "7 4 1 7" > /proc/sys/kernel/printk
	fi
fi

# Check for BOLT IDXs variables and default to zero if absent
bolt_atomic_set="boltenv "
IDX=$(boltenv -g DT_IDX)
[ $? -ne 0 ] && bolt_atomic_set+="-s DT_IDX 0 "
IDX=$(boltenv -g KL_IDX)
[ $? -ne 0 ] && bolt_atomic_set+="-s KL_IDX 0 "
IDX=$(boltenv -g CM_IDX)
[ $? -ne 0 ] && bolt_atomic_set+="-s CM_IDX 0 "
IDX=$(boltenv -g RG_IDX)
[ $? -ne 0 ] && bolt_atomic_set+="-s RG_IDX 0 "
if [ "$bolt_atomic_set" != "boltenv " ]; then
	eval $bolt_atomic_set >/dev/null
	[ $? -ne 0 ] && echo "Failed to initialize BOLT indices variable to defaults" && exit 1
fi

# Check for BOLT RG_BLK variable
RG_BLK=$(boltenv -g RG_BLK)
[ $? -ne 0 ] && RG_BLK=

####################
#Determine MTD/eMMC locations
if [ "3390" == "${PLAT:0:4}" ]; then
	BLOCKS="devtree devtree0 devtree1 rgnonvol rgnonvol0 rgnonvol1 kernel kernel0 kernel1 rootfs cm cm0 cm1 rg rg0 rg1 apps apps0 apps1"
else
	BLOCKS="rgnonvol rgnonvol0 rgnonvol1 kernel kernel0 kernel1 rootfs cm cm0 cm1 rg rg0 rg1 apps apps0 apps1"
fi

for b in $BLOCKS; do
	# Remove trailing number for common property name
	c=$(echo ${b} | sed 's/[0-9]*$//')

	# grep /proc/mtd to find partition name and get corresponding mtdN
	p_block=$(grep "\<${b}\>" /proc/mtd | cut -f 1 -d ':')

	if [ -n "$p_block" ]; then
		c_type=$(cat /sys/class/mtd/${p_block}/type | cut -f 2 -d '-')
		[ "$c_type" == "ubi" ] && continue

		eval ${c}_flash_type=$c_type
		eval ${b}_part_node=/dev/$p_block
		eval ${b}_part_num=$(echo $p_block | sed -n 's/.*\([^0-9]\)//p')
		b_name=$(cat /sys/class/mtd/${p_block}/name)
		eval ${b}_part_name="$b_name"

		if [ "$c" == "devtree" -o "$c" == "kernel" -o "$c" == "rootfs" -o "$c" == "rg" ]; then
			c_name=$(echo $b_name | sed 's/[0-9]*$//')
			if [ "$c" == "$b" ]; then
				eval ${b}_bolt_name=$b_name
			elif [ "$c" == "devtree" ]; then
				eval ${b}_bolt_name="$c_name\\\$DT_IDX"
			elif [ "$c" == "kernel" ]; then
				eval ${b}_bolt_name="$c_name\\\$KL_IDX"
			else
				eval ${b}_bolt_name="$c_name\\\$RG_IDX"
			fi
		fi

		if [ "$c" == "rgnonvol" ]; then
			flash_is_nand rgnonvol && rgnonvol_part_type=ubifs || rgnonvol_part_type=jffs2
		elif [ "$c" == "rootfs" -o "$c" == "cm" -o "$c" == "rg" ]; then
			eval ${c}_flash_erasesize=$(cat /sys/class/mtd/${p_block}/erasesize)
			eval ${c}_flash_writesize=$(cat /sys/class/mtd/${p_block}/writesize)
			eval ${c}_flash_subpagesize=$(cat /sys/class/mtd/${p_block}/subpagesize)
		fi

		[ "$b" == "rootfs" ] && break
	elif find_disk_partition mmcblk0 $b; then
		eval ${c}_flash_type=disk

		if [ "$c" == "devtree" -o "$c" == "kernel" ]; then
			if [ "$c" == "$b" ]; then
				eval ${b}_bolt_name=${emmc}${b}
			elif [ "$c" == "devtree" ]; then
				eval ${b}_bolt_name="${emmc}${c}\\\$DT_IDX"
			else
				eval ${b}_bolt_name="${emmc}${c}\\\$KL_IDX"
			fi
		elif [ "$c" == "rootfs" -o "$c" == "rg" ]; then
			if [ "$c" != "$b" -a -n "$RG_BLK" ]; then
				eval ${b}_bolt_node="/dev/mmcblk0p\\\$RG_BLK"
			else
				eval ${b}_bolt_node=\$${b}_part_node
			fi
		fi

		if [ "$c" == "rgnonvol" ]; then
			rgnonvol_part_type=ext4
		fi

		[ "$b" == "rootfs" ] && break
	fi
done

[ -z "$devtree_bolt_name" ] && bolt_devtree="$devtree0_bolt_name" || bolt_devtree="$devtree_bolt_name"
[ -z "$kernel_bolt_name" ] && bolt_kernel="$kernel0_bolt_name" || bolt_kernel="$kernel_bolt_name"

if flash_is_mtd rootfs || flash_is_mtd rg || flash_is_mtd rg0; then
	if [ -z "$rootfs_part_node" ]; then
		if [ -z "$rg_part_node" ]; then
			rg_root_eval="/dev/mtd\$((${rg0_part_node##*d}+\$RG_IDX))"
			rg_node_name="$rg0_bolt_name"
		else
			rg_root_eval="$rg_part_node"
			rg_node_name="$rg_bolt_name"
		fi
	else
		rg_root_eval="$rootfs_part_node"
		rg_node_name="$rootfs_bolt_name"
	fi

	squashfs_bolt_cmdline="\"ubi.mtd=$rg_node_name ubi.block=0,rootfs rootfstype=squashfs root=/dev/ubiblock0_0 ro platformboot squashfs_apps ${rgnonvol_part_type}_data coherent_pool=1M \$XARGS\""
	squashfs_help_cmdline="\"ubi.mtd=$rg_node_name ubi.block=0,rootfs rootfstype=squashfs root=/dev/ubiblock0_0\""
	ubifs_bolt_cmdline="\"ubi.mtd=$rg_node_name rootfstype=ubifs root=ubi0:rootfs platformboot ubifs_apps ${rgnonvol_part_type}_data coherent_pool=1M \$XARGS\""
	ubifs_help_cmdline="\"ubi.mtd=$rg_node_name rootfstype=ubifs root=ubi0:rootfs\""

elif flash_is_disk rootfs || flash_is_disk rg; then
	if [ -z "$rootfs_part_node" ]; then
		if [ -z "$rg_part_node" ]; then
			rg_root_eval="/dev/mmcblk0p\$((${rg0_part_node##*p}+\$RG_IDX))"
			rg_apps_eval="/dev/mmcblk0p\$((${rg0_part_node##*p}+\$RG_IDX+2))"
			if [ -z "$RG_BLK" ]; then
				IDX=$(boltenv -g RG_IDX)
				eval rg_node_name=\$rg${IDX}_bolt_node
				IDX=
			else
				rg_node_name="$rg0_bolt_node"
			fi
		else
			rg_root_eval="$rg_part_node"
			rg_node_name="$rg_bolt_node"
		fi
	else
		rg_root_eval="$rootfs_part_node"
		rg_node_name="$rootfs_bolt_node"
	fi

	ext4_bolt_cmdline="\"root=$rg_node_name rootfstype=ext4 rootwait mmc_core.removable=0 platformboot ext4_apps ${rgnonvol_part_type}_data coherent_pool=1M \$XARGS\""
	ext4_help_cmdline="\"root=$rg_node_name rootfstype=ext4 rootwait mmc_core.removable=0\""
fi

if flash_is_disk rootfs || flash_is_disk cm || flash_is_disk rg; then
	echo "1 4 1 7" > /proc/sys/kernel/printk
	if ! lsmod | grep nandsim >/dev/null; then
		if kmodloader 2>/dev/null; then
			insmod nandsim first_id_byte=0xec second_id_byte=0xa1 third_id_byte=0x00 fourth_id_byte=0x15
		else
			modprobe nandsim first_id_byte=0xec second_id_byte=0xa1 third_id_byte=0x00 fourth_id_byte=0x15
		fi

		mkdir -p /mnt/hd/
	fi
	echo "7 4 1 7" > /proc/sys/kernel/printk
	nandsim_part_node=/dev/$(cat /proc/mtd | sed -n '/NAND simulator/p' | sed -n 's/:.*/\1/p')
	if [ ! -c $nandsim_part_node ]; then
		if flash_is_disk rootfs; then
			rootfs_part_node=
			rootfs_flash_type=
		fi
		if flash_is_disk cm; then
			cm0_part_node=
			cm1_part_node=
			rootfs_flash_type=
		fi
		if flash_is_disk rg; then
			rg0_part_node=
			rg1_part_node=
			rootfs_flash_type=
		fi
	fi
fi



# construct menu

[ -z $kernel0_part_node ] && suf1="(not available)"

if [ -z $rootfs_part_node ]; then
	suf2="(not available)"
	suf3="$suf2"
	suf4="$suf2"
fi

if flash_is_disk rootfs; then
	suf3="(not available)"
elif flash_is_nand rootfs; then
	suf3="(not available)"
	suf4="(uses UBI)"
fi

if [ ! -e $hdd_dev ]; then
	hdd_dev=""
	suf5="(not available)"
fi

if [ ! -e ${hdd_dev}1 ]; then
	suf6="(not available)"
fi

if ! find_thumbdrive; then
	suf7="(not available)"
fi

[ -z $rg0_part_node ] && suf8="(not available)"
[ -z $cm0_part_node ] && suf9="(not available)"
[ -z $devtree0_part_node ] && suf10="(not available)"
[ -z $cm1_part_node ] && suf11="(not available)"
[ -z $rg1_part_node ] && suf12="(not available)"
[ -z $kernel1_part_node ] && suf13="(not available)"
[ -z $devtree1_part_node ] && suf14="(not available)"

while :; do

	echo ""
	echo "stbutil $version"
	echo "-------------"
	echo ""
	if [ -z "$local_dir" ]; then
		echo "Using TFTP server:     $tftphost"
		echo "Using TFTP path:       $tftppath"
	else
		echo "Using local directory: $local_dir"
	fi
	echo "Linux build target:    $plat"

	echo ""
	echo "Primary Linux flash:   ${rg_flash_type:-none}"
	echo "Default FS to boot:    $def_boot"

	echo ""
	echo "0) Set baremetal automatic boot command in BOLT"
	echo "1) Install non-initrd kernel image to ${kernel_flash_type}flash $suf1"
	echo "2) Install UBIFS rootfs to ${rootfs_flash_type}flash (RW/RO) $suf2"
	echo "3) Install JFFS2 rootfs to ${rootfs_flash_type}flash (RW/RO) $suf3"
	echo "4) Install SQUASHFS rootfs to ${rootfs_flash_type}flash (RO) $suf4"
	echo "5) Format/partition entire HDD, then install rootfs $suf5"
	echo "6) Update rootfs on first HDD partition $suf6"
	echo "7) Install kernel/rootfs to USB thumbdrive $suf7"
	if [ "3390" == "${PLAT:0:4}" ]; then
		echo "8) Install SQUASHFS RG rootfs to ${rg_flash_type}flash (RO) $suf8"
		echo "9) Install SQUASHFS CM images to ${cm_flash_type}flash (RO) $suf9"
		echo "10) Install RG device tree binary to ${devtree_flash_type}flash $suf10"
		echo "11) Install SQUASHFS CM images to backup ${cm_flash_type}flash partition (RO) $suf11"
		echo "12) Install SQUASHFS RG images to backup ${rg_flash_type}flash partition (RO) $suf12"
		echo "13) Install non-initrd kernel to backup ${kernel_flash_type}flash partition $suf13"
		echo "14) Install RG device tree binary to backup ${devtree_flash_type}flash partition $suf14"
		echo "15) Install UBIFS RG rootfs to ${rg_flash_type}flash"
		echo "16) Install UBIFS CM images to ${cm_flash_type}flash"
		echo "17) Install UBIFS CM images to backup ${cm_flash_type}flash partition"
		echo "18) Install UBIFS RG images to backup ${rg_flash_type}flash partition"
	fi

	echo "q) Exit"
	echo ""
	echo -n "Selection: "

	if [ -z "$resp" ]; then
		read resp
	else
		echo $resp
	fi
	echo ""

	if [ "3390" == "${PLAT:0:4}" ]; then
		start_arg=0
		max_arg=18
	else
		start_arg=1
		max_arg=7
	fi

	max_arg_tens=$((max_arg / 10))
	max_arg_ones=$((max_arg % 10))
	if [ $max_arg_tens -ne 0 ]; then
		max_arg_single=9
	else
		max_arg_single=$max_arg
	fi

	case $resp in
		[$start_arg-$max_arg_single]|[1-$max_arg_tens][0-$max_arg_ones])
			sufname='$'suf${resp}
			eval suf=$sufname
			if [[ "$suf" = *"not available"* ]]; then
				echo "ERROR: option is not available on this system"
			else
				eval handle_opt_${resp}
				[ $? -eq 0 ] && exit 0
			fi
			;;
		q|0)
			if [ "3390" == "${PLAT:0:4}" ]; then
				handle_opt_0
			fi
			exit 0
			;;
		*)
			echo "ERROR: invalid selection"
			;;
	esac
	resp=""
	if [ $auto_resp = 1 ]; then
		exit 0
	fi
done
