TX2 Cloning

What is the proper method to clone rootfs (APP) on the TX2 (and perhaps an image as a whole)? The equivalent command from the TX1 using R27.1 fails for lack of tegrarcm (I have not yet flashed, perhaps this is a generated file…but I’m preserving an R27.0.1 file system before moving on to R27.1). If tegrarcm is a generated file, then by what method can this be generated without flashing?

It’s using the flash.sh script now. First, read APP partition from TX2 board and save image to your file:

$ sudo ./flash.sh -r -k APP -G my_backup.img jetson-tx2 mmcblk0p1

Then rename my_backup.img to bootloader/system.img before flashing the saved image to new board:

$ sudo ./flash.sh -r -k APP jetson-tx2 mmcblk0p1

On R27.1 there is no “-G” parameter. Is that from the R27.1 driver package?

On the TX1 I used something like this calling tegraflash.py directly:

tegraflash.py --bl "${flash_base_dir}/bootloader/cboot.bin" --applet "${flash_base_dir}/bootloader/nvtboot_recovery.bin" --chip 0x21 --cmd "read APP ${raw_file}""

…originally from:
https://devtalk.nvidia.com/default/topic/898999/jetson-tx1/tx1-r23-1-new-flash-structure-how-to-clone-/post/4784149/#4784149

The original R27.0.1 included JetPack, but not the separate driver package, so I’m using R27.1 driver package for the clone attempt (I have a Fedora host).

Thanks for letting me know, let me check on the latest command in R27.1.

Here’s the patched flash.sh script including the -G cloning feature:

#!/bin/bash

# Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#  * Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
#  * Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
#  * Neither the name of NVIDIA CORPORATION nor the names of its
#    contributors may be used to endorse or promote products derived
#    from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#
# flash.sh: Flash the target board.
#	    flash.sh performs the best in LDK release environment.
#
# Usage: Place the board in recovery mode and run:
#
#	flash.sh [options] <target_board> <root_device>
#
#	for more detail enter 'flash.sh -h'
#
# Examples:
# ./flash.sh <target_board> mmcblk0p1			- boot <target_board> from eMMC
# ./flash.sh <target_board> mmcblk1p1			- boot <target_board> from SDCARD
# ./flash.sh <target_board> sda1			- boot <target_board> from USB device
# ./flash.sh -N <IPaddr>:/nfsroot <target_board> eth0	- boot <target_board> from NFS
# ./flash.sh -k LNX <target_board> mmcblk1p1		- update <target_board> kernel
# ./flash.sh -k EBT <target_board> mmcblk1p1		- update <target_board> bootloader
#
# Optional Environment Variables:
# BCTFILE ---------------- Boot control table configuration file to be used.
# BOARDID ---------------- Pass boardid to override EEPROM value
# BOOTLOADER ------------- Bootloader binary to be flashed
# BOOTPARTLIMIT ---------- GPT data limit. (== Max BCT size + PPT size)
# BOOTPARTSIZE ----------- Total eMMC HW boot partition size.
# CFGFILE ---------------- Partition table configuration file to be used.
# CMDLINE ---------------- Target cmdline. See help for more information.
# DEVSECTSIZE ------------ Device Sector size. (default = 512Byte).
# DTBFILE ---------------- Device Tree file to be used.
# EMMCSIZE --------------- Size of target device eMMC (boot0+boot1+user).
# FLASHAPP --------------- Flash application running in host machine.
# FLASHER ---------------- Flash server running in target machine.
# IGNOREFASTBOOTCMDLINE -- Block fastboot from filling unspecified kernel
#                          cmdline parameters with its defaults.
# INITRD ----------------- Initrd image file to be flashed.
# KERNEL_IMAGE ----------- Linux kernel zImage file to be flashed.
# MTS -------------------- MTS file name such as mts_si.
# MTSPREBOOT ------------- MTS preboot file name such as mts_preboot_si.
# NFSARGS ---------------- Static Network assignments.
#			   <C-ipa>:<S-ipa>:<G-ipa>:<netmask>
# NFSROOT ---------------- NFSROOT i.e. <my IP addr>:/exported/rootfs_dir.
# ODMDATA ---------------- Odmdata to be used.
# ROOTFSSIZE ------------- Linux RootFS size (internal emmc/nand only).
# ROOTFS_DIR ------------- Linux RootFS directory name.
# SCEFILE ---------------- SCE firmware file such as camera-rtcpu-sce.bin.
# SPEFILE ---------------- SPE firmware file path such as bootloader/spe.bin.
# FAB -------------------- Target board's FAB ID.
# TEGRABOOT -------------- lowerlayer bootloader such as nvtboot.bin.
# WB0BOOT ---------------- Warmboot code such as nvtbootwb0.bin
#
chkerr ()
{
	if [ $? -ne 0 ]; then
		if [ "$1" != "" ]; then
			echo "$1";
		else
			echo "failed.";
		fi;
		exit 1;
	fi;
	if [ "$1" = "" ]; then
		echo "done.";
	fi;
}

pr_conf()
{
	if [ "${zflag}" != "true" ]; then
		return 0;
	fi;
	echo "target_board=${target_board}";
	echo "target_rootdev=${target_rootdev}";
	echo "rootdev_type=${rootdev_type}";
	echo "rootfssize=${rootfssize}";
	echo "odmdata=${odmdata}";
	echo "flashapp=${flashapp}";
	echo "flasher=${flasher}";
	echo "bootloader=${bootloader}";
	echo "tegraboot=${tegraboot}";
	echo "wb0boot=${wb0boot}";
	echo "mtspreboot=${mtspreboot}";
	echo "mts=${mts}";
	echo "bctfile=${bctfile}";
	echo "cfgfile=${cfgfile}";
	echo "kernel_fs=${kernel_fs}";
	echo "kernel_image=${kernel_image}";
	echo "rootfs_dir=${rootfs_dir}";
	echo "nfsroot=${nfsroot}";
	echo "nfsargs=${nfsargs}";
	echo "kernelinitrd=${kernelinitrd}";
	echo "cmdline=${cmdline}";
	echo "boardid=${boardid}";
	exit 0;
}

validateIP ()
{
	local ip=$1;
	local ret=1;

	if [[ $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
		OIFS=${IFS};
		IFS='.';
		ip=($ip);
		IFS=${OIFS};
		[[ ${ip[0]} -le 255 && ${ip[1]} -le 255 && \
		   ${ip[2]} -le 255 && ${ip[3]} -le 255 ]];
		ret=$?;
	fi;
	if [ ${ret} -ne 0 ]; then
		echo "Invalid IP address: $1";
		exit 1;
	fi;
}

netmasktbl=(\
	"255.255.255.252" \
	"255.255.255.248" \
	"255.255.255.240" \
	"255.255.255.224" \
	"255.255.255.192" \
	"255.255.255.128" \
	"255.255.255.0" \
	"255.255.254.0" \
	"255.255.252.0" \
	"255.255.248.0" \
	"255.255.240.0" \
	"255.255.224.0" \
	"255.255.192.0" \
	"255.255.128.0" \
	"255.255.0.0" \
	"255.254.0.0" \
	"255.252.0.0" \
	"255.248.0.0" \
	"255.240.0.0" \
	"255.224.0.0" \
	"255.192.0.0" \
	"255.128.0.0" \
	"255.0.0.0" \
);

validateNETMASK ()
{
	local i;
	local nm=$1;
	for (( i=0; i<${#netmasktbl[@]}; i++ )); do
		if [ "${nm}" = ${netmasktbl[$i]} ]; then
			return 0;
		fi;
	done;
	echo "Error: Invalid netmask($1)";
	exit 1;
}

validateNFSargs ()
{
	local a=$2;

	OIFS=${IFS};
	IFS=':';
	a=($a);
	IFS=${OIFS};

	if [ ${#a[@]} -ne 4 ]; then
		echo "Error: Invalid nfsargs($2)";
		exit 1;
	fi;
	validateIP ${a[0]};
	if [ "${serverip}" = "" ]; then
		validateIP ${a[1]};
	fi;
	validateIP ${a[2]};
	validateNETMASK ${a[3]};
	if [ "$1" != "" ]; then
		eval "$1=$2";
	fi;
	return 0;
}

validateNFSroot ()
{
	if [ "$2" = "" ]; then
		return 1;
	fi;
	OIFS=${IFS};
	IFS=':';
	local var=$1;
	local a=($2);
	IFS=${OIFS};
	if [ ${#a[@]} -ne 2 ]; then
		echo "Error: Invalid nfsroot($2)";
		exit 1;
	fi;
	validateIP ${a[0]};
	if [[ "${a[1]}" != /* ]]; then
		echo "Error: Invalid nfsroot($2)";
		exit 1;
	fi;
	eval "${var}=$2";
	return 0;
}

usage ()
{
	state=$1;
	retval=$2;

	if [[ $state == allunknown ]]; then
		echo -e "
Usage: sudo ./flash.sh [options] <target_board> <rootdev>
  Where,
	target board: Valid target board name.
	rootdev: Proper root device.";

	elif [[ $state == rootdevunknown ]]; then
		echo -e "
Usage: sudo ./flash.sh [options] ${target_board} <rootdev>
  Where,
    rootdev for ${target_board}:
	${ROOT_DEV}";

	else
		echo "
Usage: sudo ./flash.sh [options] ${target_board} ${target_rootdev}";
	fi;

	cat << EOF
    options:
        -b <bctfile> --------- nvflash boot control table config file.
        -c <cfgfile> --------- nvflash partition table config file.
        -d <dtbfile> --------- device tree file.
        -e <emmc size> ------- Target device's eMMC size.
        -f <flashapp> -------- Path to flash application: nvflash or tegra-rcm.
        -h ------------------- print this message.
        -i ------------------- pass user kernel commandline as-is to kernel.
        -k <partition id> ---- partition name or number specified in flash.cfg.
        -m <mts preboot> ----- MTS preboot such as mts_preboot_si.
        -n <nfs args> -------- Static nfs network assignments
                               <Client IP>:<Server IP>:<Gateway IP>:<Netmask>
        -o <odmdata> --------- ODM data.
        -p <bp size> --------- Total eMMC HW boot partition size.
        -r ------------------- skip building and reuse existing system.img.
        -t <tegraboot> ------- tegraboot binary such as nvtboot.bin
        -u <dbmaster> -------- PKC server in <user>@<IP address> format.
        -w <wb0boot> --------- warm boot binary such as nvtbootwb0.bin
        -x <tegraid> --------- Tegra CHIPID. default = 0x18(jetson-tx2)
                               0x21(jetson-tx1), 0x40(jetson-tk1).
        -y <fusetype> -------- PKC for secureboot, NS for non-secureboot.
        -z <sn> -------------- Serial Number of target board.
        -B <boardid> --------- BoardId.
        -C <cmdline> --------- Kernel commandline arguments.
                               WARNING:
                               Each option in this kernel commandline gets
                               higher preference over the same option from
                               fastboot. In case of NFS booting, this script
                               adds NFS booting related arguments, if -i option
                               is omitted.
        -F <flasher> --------- Flash server such as fastboot.bin.
        -G <file name> ------- Read partition and save image to file.
        -I <initrd> ---------- initrd file. Null initrd is default.
        -K <kernel> ---------- Kernel image file such as zImage or Image.
        -L <bootloader> ------ Bootloader such as cboot.bin or u-boot-dtb.bin.
        -M <mts boot> -------- MTS boot file such as mts_si.
        -N <nfsroot> --------- i.e. <my IP addr>:/my/exported/nfs/rootfs.
        -P <end of PPT + 1> -- Primary GPT start address + size of PPT + 1.
        -R <rootfs dir> ------ Sample rootfs directory.
        -S <size> ------------ Rootfs size in bytes. Valid only for internal
                               rootdev. KiB, MiB, GiB short hands are allowed,
                               for example, 1GiB means 1024 * 1024 * 1024 bytes.
        -T <its file> -------- ITS file name. Valid only for u-boot.
        --no-flash ----------- perform all steps except physically flashing the board.
                               This will create a system.img.
EOF
	exit $retval;
}

setdflt ()
{
	local var="$1";
	if [ "${!var}" = "" ]; then
		eval "${var}=$2";
	fi;
}

setval ()
{
	local var="$1";
	local val="$2";
	if [ "${!val}" = "" ]; then
		echo "Error: missing $val not defined.";
		exit 1;
	fi;
	eval "${var}=${!val}";
}

mkfilesoft ()
{
	local var="$1";
	local varname="$1name";

	eval "${var}=$2";
	if [ "${!var}" = "" -o ! -f "${!var}" ]; then
		if [ "$3" != "" -a -f "$3" ]; then
			eval "${var}=$3";
		fi;
	fi;
	if [ "${!var}" != "" ]; then
		if [ ! -f ${!var} ]; then
			echo "Warning: missing $var (${!var}), continue... ";
			eval "${var}=\"\"";
			eval "${varname}=\"\"";
			return 1;
		fi;
		eval "${var}=`readlink -f ${!var}`";
		eval "${varname}=`basename ${!var}`";
	fi;
	return 0;
}

mkfilepath ()
{
	local var="$1";
	local varname="$1name";

	eval "${var}=$2";
	setdflt "${var}" "$3";
	if [ "${!var}" != "" ]; then
		eval "${var}=`readlink -f ${!var}`";
		if [ ! -f "${!var}" ]; then
			echo "Error: missing $var (${!var}).";
			usage allknown 1;
		fi;
		eval "${varname}=`basename ${!var}`";
	fi;
}

mkdirpath ()
{
	local var="$1";
	eval "${var}=$2";
	setdflt "$1" "$3";
	if [ "${!var}" != "" ]; then
		eval "${var}=`readlink -f ${!var}`";
		if [ ! -d "${!var}" ]; then
			echo "Error: missing $var (${!var}).";
			usage allknown 1;
		fi;
	fi;
}

getsize ()
{
	local var="$1";
	local val="$2";
	if [[ ${!val} != *[!0-9]* ]]; then
		eval "${var}=${!val}";
	elif [[ (${!val} == *KiB) && (${!val} != *[!0-9]*KiB) ]]; then
		eval "${var}=$(( ${!val%KiB} * 1024 ))";
	elif [[ (${!val} == *MiB) && (${!val} != *[!0-9]*MiB) ]]; then
		eval "${var}=$(( ${!val%MiB} * 1024 * 1024 ))";
	elif [[ (${!val} == *GiB) && (${!val} != *[!0-9]*GiB) ]]; then
		eval "${var}=$(( ${!val%GiB} * 1024 * 1024 * 1024))";
	else
		echo "Error: Invalid $1: ${!val}";
		exit 1;
	fi;
}

validatePartID ()
{
	local idx=0;
	declare -A cf;

	while read aline; do
		if [ "$aline" != "" ]; then
			arr=( $(echo $aline | tr '=' ' ') );
			if [ "${arr[1]}" == "name" ]; then
				if [ "${arr[3]}" == "id" ]; then
					cf[$idx,1]="${arr[2]}";
					cf[$idx,0]="${arr[4]}";
				else
					cf[$idx,0]="${arr[2]}";
				fi
				idx=$((idx+1));
			fi
		fi;
	done < $4;

	if [ "${arr[3]}" == "id" ]; then
		for ((i = 0; i < idx; i++)) do
			if [ "\"$3\"" = "${cf[$i,0]}" -o  \
			     "\"$3\"" = "${cf[$i,1]}" ]; then
				eval "$1=${cf[$i,0]}";
				eval "$2=${cf[$i,1]}";
			return 0;
			fi;
		done;
		echo "Error: invalid partition id ($3)";
		exit 1;
	else
		return 0;
	fi;
}

cp2local ()
{
	local src=$1;
	if [ "${!src}" = "" ]; then return 1; fi;
	if [ ! -f "${!src}" ]; then return 1; fi;
	if [ "$2" = "" ];      then return 1; fi;
	if [ -f $2 -a ${!src} = $2 ]; then
		local sum1=`sum ${!src}`;
		local sum2=`sum $2`;
		if [ "$sum1" = "$sum2" ]; then
			echo "Existing ${src}($2) reused.";
			return 0;
		fi;
	fi;
	echo -n "copying ${src}(${!src})... ";
	cp -f ${!src} $2;
	chkerr;
	return 0;
}

chsuffix ()
{
	local var="$1";
	local fname=`basename "$2"`;
	local OIFS=${IFS};
	IFS='.';
	na=($fname);
	IFS=${OIFS};
	eval "${var}=${na[0]}.${3}";
}

build_fsimg ()
{
	echo "Making $1... ";
	local loop_dev="${LOOPDEV:-/dev/loop0}";
	if [ ! -b "${loop_dev}" ]; then
		echo "${loop_dev} is not block device. Terminating..";
		exit 1;
	fi;
	loop_dev=`losetup --find`;
	if [ $? -ne 0 ]; then
		echo "Cannot find loop device. Terminating..";
		exit 1;
	fi;
	umount "${loop_dev}" > /dev/null 2>&1;
	losetup -d "${loop_dev}" > /dev/null 2>&1;
	rm -f $1;	chkerr "clearing $1 failed.";
	rm -rf mnt;	chkerr "clearing $4 mount point failed.";

	local bcnt=$(( $3 / 512 ));
	local bcntdiv=$(( $3 % 512 ));
	if [ $bcnt -eq 0 -o $bcntdiv -ne 0 ]; then
		echo "Error: $4 file system size has to be 512 bytes allign.";
		exit 1;
	fi
	if [ "$2" != "" -a "$2" != "0" ]; then
		local fc=`printf '%d' $2`;
		local fillc=`printf \\\\$(printf '%02o' $fc)`;
		< /dev/zero head -c $3 | tr '\000' ${fillc} > $1;
		chkerr "making $1 with fillpattern($fillc}) failed.";
	else
		truncate --size $3 $1;
		chkerr "making $1 with zero fillpattern failed.";
	fi;
	losetup "${loop_dev}" $1 > /dev/null 2>&1;
	chkerr "mapping $1 to loop device failed.";
	if [ "$4" = "FAT32" ]; then
		mkfs.msdos -I -F 32 "${loop_dev}" > /dev/null 2>&1;
	else
		mkfs -t $4 "${loop_dev}" > /dev/null 2>&1;
	fi;
	chkerr "formating $4 filesystem on $1 failed.";
	mkdir -p mnt;		chkerr "make $4 mount point failed.";
	mount "${loop_dev}" mnt;	chkerr "mount $1 failed.";
	mkdir -p mnt/boot/dtb;	chkerr "make $1/boot/dtb failed.";
	cp -f "${kernel_fs}" mnt/boot;
	chkerr "Copying ${kernel_fs} failed.";
	if [ -f "${dtbfilename}" ]; then
		cp -f "${dtbfilename}" "mnt/boot/dtb/${dtbfilename}";
		chkerr "populating ${dtbfilename} to $1/boot/dtb failed.";
	fi;
	if [ "$4" = "FAT32" ]; then
		touch -f mnt/boot/cmdline.txt > /dev/null 2&>1;
		chkerr "Creating cmdline.txt failed.";
	fi;
	if [ "$5" != "" ]; then
		pushd mnt > /dev/null 2>&1;
		echo -n -e "\tpopulating rootfs from $5 ... ";
		(cd $5; tar cf - *) | tar xf - ; chkerr;
		popd > /dev/null 2>&1;
	fi;
	echo -e -n "\tSync'ing $1 ... ";
	sync; sync; sleep 5;	# Give FileBrowser time to terminate gracefully.
	echo "done.";
	umount "${loop_dev}" > /dev/null 2>&1;
	losetup -d "${loop_dev}" > /dev/null 2>&1;
	rmdir mnt > /dev/null 2>&1;

	if [ "$2" != "" -a -x mksparse ]; then
		echo -e "\tConverting RAW image to Sparse image... ";
		mv -f $1 $1.raw;
		./mksparse -v --fillpattern=$2 $1.raw $1; chkerr;
	fi;
	echo "$1 built successfully. ";
}

append_bootargs_to_dtb ()
{
	local trgdtbfilename="${1}";
	if [ "${flashappname}" != "tegraflash.py" ]; then
		return 1;
	fi;
	default_cmd="console=tty0 OS=l4t ";
	dtc -I dtb -O dts "${trgdtbfilename}" -o temp.dts;
	sed -i '/bootargs/d' temp.dts;
	for string in ${default_cmd}; do
		lcl_str=`echo $string | sed "s|\(.*\)=.*|\1|"`;
		[[ "${cmdline}" =~ $lcl_str ]] || cmdline+=" ${string}";
	done
	sed -i "/chosen {/ a \\\t\\tbootargs=\"${cmdline} console=ttyS0,115200n8 \";" temp.dts;
	sed -i "/stdout-path = \"/ a \\\t\\tplugin-manager {\n\\t\t\todm-data {\n\t\t\t\tl4t;\n\t\t\t};\n\t\t};" temp.dts;
	dtc -I dts -O dtb temp.dts -o "${trgdtbfilename}";
	rm temp.dts;
}

get_fuse_level ()
{
	local fuselevel="x";
	local ECID;

	if [ -f "${BL_DIR}/tegrarcm_v2" ]; then
		pushd "${BL_DIR}" > /dev/null 2>&1;
		ECID=$(./tegrarcm_v2 --uid | grep BR_CID | cut -d' ' -f2);
		popd > /dev/null 2>&1;
		fuselevel="${ECID:2:1}";
	fi;

	case ${fuselevel} in
	0|1) echo "fuselevel_nofuse";;
	8|a|b|d|e|f) echo "fuselevel_production";;
	*) echo "fuselevel_unknown";;
	esac;
}

function get_full_path ()
{
	local val="$1";
	local result="$2";
	local fullpath;
	fullpath=$(readlink -f ${val});	# null if path is invalid
	if [ "${fullpath}" == "" ]; then
		echo "Invalid path/filename ${val}";
		exit 1;
	fi;
	eval "${result}=${fullpath}";
}

#
# XXX: This EEPROM read shall be replaced with new FAB agnostic function.
#
get_board_version ()
{
	local args="";
	local __board_id=$1;
	local __board_version=$2;
	local boardid;
	local boardversion;
	args+="--chip ${CHIPID} ";
	args+="--applet \"${LDK_DIR}/${SOSFILE}\" ";
	args+="--cmd \"dump eeprom boardinfo cvm.bin\" ";
	args+="${SKIPUID} ";
	SKIPUID="";
	local cmd="./tegraflash.py ${args}";
	pushd "${BL_DIR}" > /dev/null 2>&1;
	if [ "${dbmaster}" != "" ]; then
		local keyfile;
		if [[ ${dbmaster} =~ ^/ ]]; then
			keyfile="${dbmaster}";
		else
			keyfile=`readlink -f "../${dbmaster}"`;
		fi;
		cmd+="--key \"${keyfile} \"";
	fi;
	echo "${cmd}";
	eval "${cmd}";
	chkerr "Reading board information failed.";
	boardid=`./chkbdinfo -i cvm.bin`;
	boardversion=`./chkbdinfo -f cvm.bin`;
	chkerr "Parsing board information failed.";
	popd > /dev/null 2>&1;
	eval ${__board_id}="${boardid}";
	eval ${__board_version}="${boardversion}";
}

if [ $# -lt 2 ]; then
	usage allunknown 1;
fi;

# if the user is not root, there is not point in going forward
if [ "${USER}" != "root" ]; then
	echo "flash.sh requires root privilege";
	exit 1;
fi
nargs=$#;
target_rootdev=${!nargs};
nargs=$(($nargs-1));
ext_target_board=${!nargs};

if [ ! -r ${ext_target_board}.conf ]; then
	echo "Error: Invalid target board - ${ext_target_board}.";
	usage allunknown 1;
fi

# set up LDK_DIR path
LDK_DIR=$(cd `dirname $0` && pwd);
LDK_DIR=`readlink -f "${LDK_DIR}"`;

source ${ext_target_board}.conf

# set up path variables
BL_DIR="${LDK_DIR}/bootloader";
TARGET_DIR="${BL_DIR}/${target_board}";
KERNEL_DIR="${LDK_DIR}/kernel";
export PATH="${KERNEL_DIR}:${PATH}";		# preference on our DTC
DTB_DIR="${KERNEL_DIR}/dtb";
if [ "${BINSARGS}" = "" -a "${BINS}" != "" ]; then			#COMPAT
	BINARGS="--bins \"";						#COMPAT
fi;									#COMPAT
if [ "${BINSARGS}" != "" ]; then
	SKIPUID="--skipuid";
fi;

# get the fuse level and update the data accordingly
declare -F -f process_fuse_level > /dev/null 2>&1;
if [ $? -eq 0 ]; then
	fuselevel="${FUSELEVEL}";
	if [ "${fuselevel}" = "" ]; then
		fuselevel=$(get_fuse_level);
	fi;
	process_fuse_level "${fuselevel}";
fi;

# Determine rootdev_type
#
rootdev_type="external";
if [[ "${target_rootdev}" == mmcblk0p* ]]; then
	rootdev_type="internal";
elif [ "${target_rootdev}" = "eth0" -o "${target_rootdev}" = "eth1" ]; then
	rootdev_type="network";
elif [[ "${target_rootdev}" != mmcblk1p* && \
	"${target_rootdev}" != sd* ]]; then
	echo "Error: Invalid target rootdev($target_rootdev).";
	usage rootdevunknown 1;
fi;

read_part_name="";
no_flash=0;
opstr+="b:c:d:e:f:hik:m:n:o:p:rs:t:u:w:x:y:z:B:C:F:G:I:K:L:M:N:P:R:S:T:Z:-:";
while getopts "${opstr}" OPTION
do
	case $OPTION in
	b) BCTFILE=${OPTARG}; ;;
	c) CFGFILE=${OPTARG}; ;;
	d) DTBFILE=${OPTARG}; ;;
	e) EMMCSIZE=${OPTARG}; ;;
	f) FLASHAPP=${OPTARG}; ;;
	h) usage allunknown 0; ;;
	i) IGNOREFASTBOOTCMDLINE="ignorefastboot"; ;;
	k) target_partname=${OPTARG}; ;;	# cmdline only
	m) MTSPREBOOT=${OPTARG}; ;;
	n) NFSARGS=${OPTARG}; ;;
	o) ODMDATA=${OPTARG}; ;;
	p) BOOTPARTSIZE=${OPTARG}; ;;
	r) reuse_systemimg="true"; ;;		# cmdline only
	t) TEGRABOOT=${OPTARG}; ;;
	u) dbmaster="${OPTARG}"; ;;
	w) WB0BOOT=${OPTARG}; ;;
	x) tegraid=${OPTARG}; ;;
	y) fusetype=${OPTARG}; ;;
	z) sn=${OPTARG}; ;;
	B) BOARDID=${OPTARG}; ;;
	C) CMDLINE="${OPTARG}"; ;;
	F) FLASHER=${OPTARG}; ;;
	G) read_part_name=${OPTARG}; ;;
	I) INITRD=${OPTARG}; ;;
	K) KERNEL_IMAGE=${OPTARG}; ;;
	L) BOOTLOADER=${OPTARG}; ;;
	M) MTS=${OPTARG}; ;;
	N) NFSROOT=${OPTARG}; ;;
	P) BOOTPARTLIMIT=${OPTARG}; ;;
	R) ROOTFS_DIR=${OPTARG}; ;;
	S) ROOTFSSIZE=${OPTARG}; ;;
	Z) zflag="true"; ;;			# cmdline only
	-) case ${OPTARG} in
	   no-flash) no_flash=1; ;;
	   esac;;
	*) usage allunknown 1; ;;
	esac;
done

#
# Handle -G option for reading partition image to file
#
if [ "${read_part_name}" != "" ]; then
	# Exit if path is invalid
	get_full_path ${read_part_name} read_part_name;
fi;

# get the board version and update the data accordingly
declare -F -f process_board_version > /dev/null 2>&1;
if [ $? -eq 0 ]; then
	board_version="${FAB}";
	if [ "${board_version}" = "" ]; then
		get_board_version board_id board_version;
	fi;
	process_board_version "${board_id}" "${board_version}";
fi;

###########################################################################
# System default values: should be defined AFTER target_board value.
#
ROOTFS_TYPE="${ROOTFS_TYPE:-ext4}";
DEVSECTSIZE="${DEVSECTSIZE:-512}";		# default sector size = 512
BOOTPARTLIMIT="${BOOTPARTLIMIT:-10485760}";	# 1MiB limit
fillpat="${FSFILLPATTERN:-0}";			# no cmdline: default=0
boardid="${BOARDID}";
if [ "${tegraid}" = "" ]; then
	tegraid="${CHIPID}";
fi;

if [ -z "${DFLT_KERNEL}" ]; then
	if [[ "${target_board}" == ardbeg* ]]; then
		DFLT_KERNEL=${KERNEL_DIR}/zImage;
	else
		DFLT_KERNEL=${KERNEL_DIR}/Image;
	fi;
else
	basekernel=`basename "${DFLT_KERNEL}"`;
	if [ "${DFLT_KERNEL}" = "${basekernel}" ]; then
		DFLT_KERNEL="${KERNEL_DIR}/${DFLT_KERNEL}";
	fi;
fi;
if [ -z "${DFLT_KERNEL_FS}" ]; then
	DFLT_KERNEL_FS=${DFLT_KERNEL};
fi;
if [ -z "${DFLT_KERNEL_IMAGE}" ]; then
	DFLT_KERNEL_IMAGE=${DFLT_KERNEL};
fi;

###########################################################################
# System mandatory vars:
#
setval     odmdata	ODMDATA;	# .conf mandatory
setval     rootfs_type	ROOTFS_TYPE;
setval     devsectsize	DEVSECTSIZE;
getsize    rootfssize	ROOTFSSIZE;	# .conf mandatory
getsize    emmcsize	EMMCSIZE;	# .conf mandatory
getsize    bootpartsize	BOOTPARTSIZE;	# .conf mandatory
getsize    bootpartlim	BOOTPARTLIMIT;
mkfilepath flashapp	"${FLASHAPP}"	"${BL_DIR}/nvflash";
mkfilepath flasher	"${FLASHER}"	"${TARGET_DIR}/fastboot.bin";
mkfilepath bootloader	"${BOOTLOADER}"	"${TARGET_DIR}/fastboot.bin";
mkdirpath  rootfs_dir	"${ROOTFS_DIR}"	"${LDK_DIR}/rootfs";
mkfilepath kernel_image	"$KERNEL_IMAGE" "${DFLT_KERNEL_IMAGE}";
mkfilepath kernel_fs	"$KERNEL_IMAGE" "${DFLT_KERNEL_FS}";
mkfilepath bctfile	"${BCTFILE}"	"${TARGET_DIR}/BCT/${EMMC_BCT}";
mkfilepath cfgfile	"${CFGFILE}"	"${TARGET_DIR}/cfg/${EMMC_CFG}";
mkfilepath dtbfile	"${DTBFILE}"	"${DTB_DIR}/${DTB_FILE}";

if [[ "${bootloadername}" == u-boot* ]]; then
	bootloader_is_uboot=1;
else
	bootloader_is_uboot=0;
fi;
if [[ "${kernel_imagename}" == u-boot* ]]; then
	kernel_image_is_uboot=1;
else
	kernel_image_is_uboot=0;
fi;
if [ ${bootloader_is_uboot} -eq 1 -o ${kernel_image_is_uboot} -eq 1 ]; then
	using_uboot=1;
else
	using_uboot=0;
fi;
case "${target_board}" in
t210ref)
	uboot_replaces_tboot=0;
	uboot_in_tboot_img=1;
	if [ "${tegraid}" = "" ]; then
		tegraid="0x21";
	fi;
	;;
t186ref)
	uboot_replaces_tboot=0;
	uboot_in_tboot_img=0;
	if [ "${tegraid}" = "" ]; then
		tegraid="0x18";
	fi;
	;;
*)
	uboot_replaces_tboot=1;
	uboot_in_tboot_img=0;
	;;
esac;

mkfilesoft kernelinitrd	"${INITRD}"	"";
if [ ${using_uboot} -eq 0 -o ${uboot_replaces_tboot} -eq 0 ]; then
	mkfilesoft tegraboot	"${TEGRABOOT}"	"${TARGET_DIR}/nvtboot.bin";
	mkfilesoft wb0boot	"${WB0BOOT}"	"${TARGET_DIR}/nvtbootwb0.bin";
fi
mkfilesoft mtspreboot	"${MTSPREBOOT}"	"${BL_DIR}/mts_preboot_si";
mkfilesoft mts		"${MTS}"	"${BL_DIR}/mts_si";
mkfilesoft mb1file	"${MB1FILE}"	"${BL_DIR}/mb1_prod.bin";
mkfilesoft bpffile	"${BPFFILE}"	"${BL_DIR}/bpmp.bin";
mkfilesoft bpfdtbfile	"${BPFDTBFILE}" "${TARGET_DIR}/${BPFDTB_FILE}";
if [ "${bpfdtbfile}" = "" -a "${BPMPDTB_FILE}" != "" ]; then		#COMPAT
	mkfilesoft bpfdtbfile	"${BL_DIR}/${BPMPDTB_FILE}"	"";	#COMPAT
fi;									#COMPAT
mkfilesoft nctfile	"${NCTFILE}"	"${TARGET_DIR}/cfg/${NCT_FILE}";
mkfilesoft tosfile	"${TOSFILE}"	"${TARGET_DIR}/tos.img";
mkfilesoft eksfile	"${EKSFILE}"	"${TARGET_DIR}/eks.img";
mkfilesoft fbfile	"${FBFILE}"	"";
mkfilesoft bcffile	"${BCFFILE}"	"";
mkfilesoft sosfile	"${SOSFILE}"	"";
mkfilesoft mb2blfile	"${MB2BLFILE}"	"";
mkfilesoft scefile	"${SCEFILE}"	"${BL_DIR}/camera-rtcpu-sce.bin";
mkfilesoft spefile	"${SPEFILE}"	"${BL_DIR}/spe.bin";

mkfilesoft misc_config    "${TARGET_DIR}/BCT/${MISC_CONFIG}" "";
mkfilesoft pinmux_config  "${TARGET_DIR}/BCT/${PINMUX_CONFIG}" "";
mkfilesoft pmic_config    "${TARGET_DIR}/BCT/${PMIC_CONFIG}" "";
mkfilesoft pmc_config     "${TARGET_DIR}/BCT/${PMC_CONFIG}" "";
mkfilesoft prod_config    "${TARGET_DIR}/BCT/${PROD_CONFIG}" "";
mkfilesoft scr_config     "${TARGET_DIR}/BCT/${SCR_CONFIG}" "";
mkfilesoft dev_params     "${TARGET_DIR}/BCT/${DEV_PARAMS}" "";
mkfilesoft bootrom_config "${TARGET_DIR}/BCT/${BOOTROM_CONFIG}" "";

if [ ${using_uboot} -eq 0 -o ${uboot_replaces_tboot} -eq 0 ]; then
	mkfilesoft tbcfile	"${TBCFILE}"	 "";
	mkfilesoft tbcdtbfile	"${TBCDTB_FILE}" "${DTB_DIR}/${DTB_FILE}";
fi

if [ "${rootdev_type}" = "network" ]; then
	if [ "${NFSROOT}" = "" -a "${NFSARGS}" = "" ]; then
		echo "Error: network argument(s) missing.";
		usage allknown 1;
	fi;
	if [ "${NFSROOT}" != "" ]; then
		validateNFSroot nfsroot "${NFSROOT}";
	fi;
	if [ "${NFSARGS}" != "" ]; then
		validateNFSargs nfsargs "${NFSARGS}";
	fi;
	if [ "${nfsroot}" != "" ]; then
		nfsdargs="root=/dev/nfs rw netdevwait";
		cmdline+="${nfsdargs} ";
		if [ "${nfsargs}" != "" ]; then
			nfsiargs="ip=${nfsargs}";
			nfsiargs+="::${target_rootdev}:off";
		else
			nfsiargs="ip=:::::${target_rootdev}:on";
		fi;
		cmdline+="${nfsiargs} ";
		cmdline+="nfsroot=${nfsroot} ";
	fi;
elif [ "${flashappname}" = "tegraflash.py" ]; then
	cmdline+="root=/dev/${target_rootdev} rw rootwait ";
fi;

if [ "${CMDLINE_ADD}" != "" ]; then
	cmdline+="${CMDLINE_ADD} ";
fi;

if [ "${CMDLINE}" != "" ]; then
	for string in ${CMDLINE}; do
		lcl_str=`echo $string | sed "s|\(.*\)=.*|\1|"`
		if [[ "${cmdline}" =~ $lcl_str ]]
		then
			cmdline=`echo "$cmdline" | sed "s|$lcl_str=[0-9a-zA-Z:/]*|$string|"`
		else
			cmdline+="${string} ";
		fi
	done
fi;

if [ "${IGNOREFASTBOOTCMDLINE}" != "" ]; then
	cmdline+="${IGNOREFASTBOOTCMDLINE} ";
fi;

if [ ${using_uboot} -eq 1 ]; then
	if [ "${rootdev_type}" = "network" ]; then
		SYSBOOTFILE="${TARGET_DIR}/${SYSBOOTFILE}.nfs";
	elif [[ "${target_rootdev}" == mmcblk1p* ]]; then
		SYSBOOTFILE="${TARGET_DIR}/${SYSBOOTFILE}.sdcard";
	elif [[ "${target_rootdev}" == sd* ]]; then
		SYSBOOTFILE="${TARGET_DIR}/${SYSBOOTFILE}.usb";
	else
		SYSBOOTFILE="${TARGET_DIR}/${SYSBOOTFILE}.emmc";
	fi;
	mkfilesoft sysbootfile "${SYSBOOTFILE}";
fi;

##########################################################################
pr_conf;	# print config and terminate if requested.
##########################################################################

pushd $BL_DIR > /dev/null 2>&1;

### Localize files and build TAGS ########################################
# BCT_TAG:::
#
cp2local bctfile "${BL_DIR}/${bctfilename}";
if [ "${BINSARGS}" != "" ]; then
	# Build up BCT parameters:
	if [ "${misc_config}" != "" ]; then
		cp2local misc_config "${BL_DIR}/${misc_configname}";
		BCTARGS+="--misc_config ${misc_configname} ";
	fi;
	if [ "${pinmux_config}" != "" ]; then
		cp2local pinmux_config "${BL_DIR}/${pinmux_configname}";
		BCTARGS+="--pinmux_config ${pinmux_configname} ";
	fi;
	if [ "${pmic_config}" != "" ]; then
		cp2local pmic_config "${BL_DIR}/${pmic_configname}";
		BCTARGS+="--pmic_config ${pmic_configname} ";
	fi;
	if [ "${pmc_config}" != "" ]; then
		cp2local pmc_config "${BL_DIR}/${pmc_configname}";
		BCTARGS+="--pmc_config ${pmc_configname} ";
	fi;
	if [ "${prod_config}" != "" ]; then
		cp2local prod_config "${BL_DIR}/${prod_configname}";
		BCTARGS+="--prod_config ${prod_configname} ";
	fi;
	if [ "${scr_config}" != "" ]; then
		cp2local scr_config "${BL_DIR}/${scr_configname}";
		BCTARGS+="--scr_config ${scr_configname} ";
	fi;
	if [ "${bootrom_config}" != "" ]; then
		cp2local bootrom_config "${BL_DIR}/${bootrom_configname}";
		BCTARGS+="--br_cmd_config ${bootrom_configname} ";
	fi;
	if [ "${dev_params}" != "" ]; then
		cp2local dev_params "${BL_DIR}/${dev_paramsname}";
		BCTARGS+="--dev_params ${dev_paramsname} ";
	fi;
	if [ "${BCT}" = "" ]; then
		BCT="--sdram_config";
	fi;
elif [ "${BCT}" = "" ]; then
	BCT="--bct";
fi;

# EBT_TAG:
#
if [ ${using_uboot} -eq 1 -a ${uboot_in_tboot_img} -eq 1 ]; then
	bootloaderdir=`dirname "${bootloader}"`;
	uboot_elf="${bootloaderdir}/u-boot";
	uboot_entry=`"${LDK_DIR}/elf-get-entry.py" "${uboot_elf}"`;
	chkerr "Could not determine entry point of bootloader binary";

	"${BL_DIR}/gen-tboot-img.py" "${bootloader}" ${uboot_entry} "${BL_DIR}/${bootloadername}";
	chkerr "Failed to add TBOOT header to bootloader";
else
	cp2local bootloader "${BL_DIR}/${bootloadername}";
fi;
EBT_TAG+="-e s/fastboot.bin/${bootloadername}/ ";
EBT_TAG+="-e s/EBTFILE/${bootloadername}/ ";

# LNX_TAG:
#
localbootfile=boot.img;
rm -f initrd; touch initrd;
if [ "$kernelinitrd" != "" -a -f "$kernelinitrd" ]; then
	echo -n "copying initrd(${kernelinitrd})... ";
	cp -f "${kernelinitrd}" initrd;
	chkerr;
fi;
if [ ${using_uboot} -eq 1 ]; then
	mkdir -p "${rootfs_dir}/boot" > /dev/null 2>&1;
	echo -e -n "\tpopulating kernel to rootfs... ";
	cp -f "${kernel_fs}" "${rootfs_dir}/boot"; chkerr;
	echo -e -n "\tpopulating initrd to rootfs... ";
	cp -f initrd "${rootfs_dir}/boot"; chkerr;
	echo -e -n "\tpopulating ${sysbootfilename} to rootfs... ";
	cp -f "${dtbfile}" "${rootfs_dir}/boot"; chkerr;
	echo -e -n "\tpopulating ${dtbfile} to rootfs... ";
	mkdir -p "${rootfs_dir}/boot/extlinux"; chkerr;
	cp -f "${sysbootfile}" "${rootfs_dir}/boot/extlinux/extlinux.conf";
	sed -i "s|fbcon=map:.|${CMDLINE_ADD}|" "${rootfs_dir}/boot/extlinux/extlinux.conf";
	chkerr;
fi

LNX_TAG+="-e s/LNXNAME/kernel/ ";
LNX_TAG+="-e s/LNXSIZE/67108864/ ";
if [ ${using_uboot} -eq 1 -a ${kernel_image_is_uboot} -eq 0 ]; then
	LNX_TAG+="-e /filename=${localbootfile}/d ";
	LNX_TAG+="-e /LNXFILE/d ";
else
	echo -n "Making Boot image... ";
	MKBOOTARG+="--kernel ${kernel_image} ";
	MKBOOTARG+="--ramdisk initrd ";
	MKBOOTARG+="--board ${target_rootdev} ";
	MKBOOTARG+="--output ${localbootfile} ";
	./mkbootimg ${MKBOOTARG} --cmdline "${cmdline}" > /dev/null 2>&1;
	chkerr;
	LNX_TAG+="-e s/LNXFILE/${localbootfile}/ ";
fi;

# NCT_TAG:
#
if [ "${bcffile}" != "" ]; then
	cp2local bcffile "${BL_DIR}/${bcffilename}";
	NCTARGS+="--boardconfig ${bcffilename} ";
	NCT_TAG+="-e /NCTFILE/d ";
	NCT_TAG+="-e s/NCTTYPE/data/ ";
elif [ "${boardid}" != "" ]; then
	NCTARGS+="--boardid $boardid";
	NCT_TAG+="-e /NCTFILE/d ";
	NCT_TAG+="-e s/NCTTYPE/data/ ";
elif [ "${nctfile}" != "" ]; then
	cp2local nctfile "${BL_DIR}/${nctfilename}";
	NCT_TAG+="-e s/name=NXT/name=NCT/ ";
	NCT_TAG+="-e s/NCTFILE/${nctfilename}/ ";
	NCT_TAG+="-e s/NCTTYPE/config_table/ ";
	NCTARGS+="--nct ${nctfilename}";
else
	NCT_TAG+="-e /NCTFILE/d ";
	NCT_TAG+="-e s/NCTTYPE/data/ ";
fi;

# SOS_TAG: XXX: recovery is yet to be implemented.
#
SOS_TAG+="-e /SOSFILE/d ";
if [ "${sosfile}" != "" ]; then
	cp2local sosfile "${BL_DIR}/${sosfilename}";
	SOSARGS+="--applet ${sosfilename} ";
else
	SOS_TAG+="-e /filename=recovery.img/d ";
fi;

# NVC_TAG:== MB2
#
if [ "${tegraboot}" != "" ]; then
	cp2local tegraboot "${BL_DIR}/${tegrabootname}";
	NVC_TAG+="-e s/NXC/NVC/ ";
	NVC_TAG+="-e s/MB2NAME/mb2/ ";
	NVC_TAG+="-e s/type=data\s\+#TEGRABOOT/type=bootloader/ ";
	NVC_TAG+="-e s/NVCTYPE/bootloader/ ";
	NVC_TAG+="-e s/MB2TYPE/mb2_bootloader/ ";
	NVC_TAG+="-e s/#filename=nvtboot.bin/filename=${tegrabootname}/ ";
	NVC_TAG+="-e s/NVCFILE/${tegrabootname}/ ";
	NVC_TAG+="-e s/MB2FILE/${tegrabootname}/ ";
else
	NVC_TAG+="-e s/NVCTYPE/data/ ";
	NVC_TAG+="-e s/MB2TYPE/data/ ";
	NVC_TAG+="-e /NVCFILE/d ";
	NVC_TAG+="-e /MB2FILE/d ";
	NVC_TAG+="-e /filename=nvtboot.bin/d ";
fi;

# MB2BL_TAG:== tboot_recovery
#
if [ "${mb2blfile}" != "" ]; then
	cp2local mb2blfile "${BL_DIR}/${mb2blfilename}";
	if [ "${BINSARGS}" != "" ]; then
		BINSARGS+="mb2_bootloader ${mb2blfilename}; ";
	fi;
fi;

# MPB_TAG:
#
if [ "${mtspreboot}" != "" ]; then
	cp2local mtspreboot "${BL_DIR}/${mtsprebootname}";
	MPB_TAG+="-e s/MXB/MPB/ ";
	MPB_TAG+="-e s/MPBNAME/mts-preboot/ ";
	MPB_TAG+="-e s/type=data\s\+#MTSPREBOOT/type=mts_preboot/ ";
	MPB_TAG+="-e s/MPBTYPE/mts_preboot/ ";
	MPB_TAG+="-e s/#filename=mts_preboot_si/filename=${mtsprebootname}/ ";
	MPB_TAG+="-e s/MPBFILE/${mtsprebootname}/ ";
	if [ "${BINSARGS}" != "" ]; then
		BINSARGS+="mts_preboot ${mtsprebootname}; ";
	else
		MTSARGS+="--preboot ${mtsprebootname} ";
	fi;
else
	MPB_TAG+="-e s/MPBTYPE/data/ ";
	MPB_TAG+="-e /#filename=mts_preboot_si/d ";
	MPB_TAG+="-e /MPBFILE/d ";
fi;

# MBP_TAG:
#
if [ "${mts}" != "" ]; then
	cp2local mts "${BL_DIR}/${mtsname}";
	MBP_TAG+="-e s/MXP/MBP/ ";
	MBP_TAG+="-e s/MBPNAME/mts-bootpack/ ";
	MBP_TAG+="-e s/type=data\s\+#MTSBOOTPACK/type=mts_bootpack/ ";
	MBP_TAG+="-e s/MBPTYPE/mts_bootpack/ ";
	MBP_TAG+="-e s/#filename=mts_si/filename=${mtsname}/ ";
	MBP_TAG+="-e s/MBPFILE/${mtsname}/ ";
	if [ "${BINSARGS}" != "" ]; then
		BINSARGS+="mts_bootpack ${mtsname}; ";
	else
		MTSARGS+="--bootpack ${mtsname} ";
	fi;
else
	MBP_TAG+="-e s/MBPTYPE/data/ ";
	MBP_TAG+="-e /#filename=mts_si/d ";
	MBP_TAG+="-e /MBPFILE/d ";
fi;

# MB1_TAG:
#
if [ "${mb1file}" != "" ]; then
	cp2local mb1file "${BL_DIR}/${mb1filename}";
	MB1_TAG+="-e s/MB1NAME/mb1/ ";
	MB1_TAG+="-e s/MB1TYPE/mb1_bootloader/ ";
	MB1_TAG+="-e s/MB1FILE/${mb1filename}/ ";
else
	MB1_TAG+="-e s/MB1TYPE/data/ ";
	MB1_TAG+="-e /MB1FILE/d ";
fi;

# BPF_TAG:
#
if [ "${bpffile}" != "" ]; then
	cp2local bpffile "${BL_DIR}/${bpffilename}";
	BPF_TAG+="-e s/BXF/BPF/ ";
	BPF_TAG+="-e s/BPFNAME/bpmp-fw/ ";
	BPF_TAG+="-e s/BPFFILE/${bpffilename}/ ";
	BPF_TAG+="-e s/BPFSIGN/true/ ";
	if [ "${BINSARGS}" != "" ]; then
		BINSARGS+="bpmp_fw ${bpffilename}; ";
	fi;
else
	BPF_TAG+="-e /BPFFILE/d ";
	BPF_TAG+="-e s/BPFSIGN/false/ ";
fi;

# BPFDTB_TAG:
if [ "${bpfdtbfile}" != "" ]; then
	cp2local bpfdtbfile "${BL_DIR}/${bpfdtbfilename}";
	BPFDTB_TAG+="-e s/BPFDTB-NAME/bpmp-fw-dtb/ ";
	BPFDTB_TAG+="-e s/BPFDTB-FILE/${bpfdtbfilename}/ ";
	BPFDTB_TAG+="-e s/BPMPDTB-SIGN/true/ ";
	BPFDTB_TAG+="-e s/BPMPDTB/${bpfdtbfilename}/ ";			#COMPAT
	if [ "${BINSARGS}" != "" ]; then
		BINSARGS+="bpmp_fw_dtb ${bpfdtbfilename}; ";
	fi;
else
	BPFDTB_TAG+="-e /BPFDTB-FILE/d ";
	BPFDTB_TAG+="-e s/BPMPDTB-SIGN/false/ ";
fi;

# SCE_TAG:
if [ "${scefile}" != "" ]; then
	cp2local scefile "${BL_DIR}/${scefilename}";
	SCE_TAG+="-e s/SCENAME/sce-fw/ ";
	SCE_TAG+="-e s/SCESIGN/true/ ";
	SCE_TAG+="-e s/SCEFILE/${scefilename}/ ";
	SCE_TAG+="-e s/SCEFIRMWARE/${scefilename}/ ";			#COMPAT
else
	SCE_TAG+="-e s/SCESIGN/flase/ ";
	SCE_TAG+="-e /SCEFILE/d ";
fi;

# SPE_TAG:
if [ "${spefile}" != "" ]; then
	cp2local spefile "${BL_DIR}/${spefilename}";
	SPE_TAG+="-e s/SPENAME/spe-fw/ ";
	SPE_TAG+="-e s/SPETYPE/spe_fw/ ";
	SPE_TAG+="-e s/SPEFILE/${spefilename}/ ";
	SPE_TAG+="-e s/spe.bin/${spefilename}/ ";
else
	SPE_TAG+="-e s/SPETYPE/data/ ";
	SPE_TAG+="-e /SPEFILE/d ";
fi;

# WB0_TAG:
#
if [ "${wb0boot}" != "" ]; then
	cp2local wb0boot "${BL_DIR}/${wb0bootname}";
	WB0_TAG+="-e s/WX0/WB0/ ";
	WB0_TAG+="-e s/SC7NAME/sc7/ ";
	WB0_TAG+="-e s/WB0SIZE/20480/ ";
	WB0_TAG+="-e s/type=data\s\+#WB0BOOT/type=WB0/ ";
	WB0_TAG+="-e s/WB0TYPE/WB0/ ";
	WB0_TAG+="-e s/#filename=warmboot.bin/filename=${wb0bootname}/ ";
	WB0_TAG+="-e s/WB0FILE/${wb0bootname}/ ";
else
	WB0_TAG+="-e s/WB0TYPE/data/ ";
	WB0_TAG+="-e s/WB0SIZE/20480/ ";
	WB0_TAG+="-e /WB0FILE/d ";
	WB0_TAG+="-e /filename=warmboot.bin/d ";
fi;

# TOS_TAG:
#
if [ "${tosfile}" != "" ]; then
	cp2local tosfile "${BL_DIR}/${tosfilename}";
	TOS_TAG+="-e s/TXS/TOS/ ";
	TOS_TAG+="-e s/TOSNAME/secure-os/ ";
	TOS_TAG+="-e s/TOSFILE/${tosfilename}/ ";
	if [ "${BINSARGS}" != "" ]; then
		BINSARGS+="tlk ${tosfilename}; ";
	fi;
else
	TOS_TAG+="-e /TOSFILE/d ";
fi;

# EKS_TAG:
#
EKS_TAG+="-e s/EXS/EKS/ ";
if [ "${eksfile}" != "" ]; then
	cp2local eksfile "${BL_DIR}/${eksfilename}";
	EKS_TAG+="-e s/EKSFILE/${eksfilename}/ ";
	if [ "${BINSARGS}" != "" ]; then
		BINSARGS+="eks ${eksfilename}; ";
	fi;
else
	EKS_TAG+="-e /EKSFILE/d ";
fi;

# FB_TAG:
#
if [ "${fbfile}" != "" ]; then
	chsuffix fbfilebin ${fbfilename} "bin";
	fbfilexml="reserved_fb.xml";
	cp2local fbfile "${BL_DIR}/${fbfilename}";
	FB_TAG+="-e s/FBFILE/${fbfilebin}/ ";
	FB_TAG+="-e s/FX/FB/ ";
	FB_TAG+="-e s/FBNAME/fusebypass/ ";
	FB_TAG+="-e s/FBTYPE/fuse_bypass/ ";
	FB_TAG+="-e s/FBSIGN/true/ ";
	if [ "${flashappname}" = "tegraflash.py" ]; then
		FBARGS+="--fb ${fbfilebin} "
		FBARGS+="--cmd \"parse fusebypass ${fbfilename} ";
		FBARGS+="non-secure;flash;reboot\" ";
	fi;
else
	FB_TAG+="-e s/FBTYPE/data/ ";
	FB_TAG+="-e s/FBSIGN/false/ ";
	FB_TAG+="-e /FBFILE/d ";
	if [ "${flashappname}" = "tegraflash.py" ]; then
		FBARGS+="--cmd \"flash;reboot\" ";
	fi;
fi;

# DTB_TAG: Kernel DTB
#
if [ "${dtbfile}" != "" ]; then
	cp2local dtbfile "${BL_DIR}/${dtbfilename}";
	append_bootargs_to_dtb "${dtbfilename}";
	DTB_TAG+="-e s/DXB/DTB/ ";
	DTB_TAG+="-e s/KERNELDTB-NAME/kernel-dtb/ ";
	DTB_TAG+="-e s/#filename=tegra.dtb/filename=${dtbfilename}/ ";
	DTB_TAG+="-e s/DTBFILE/${dtbfilename}/ ";
	DTB_TAG+="-e s/KERNELDTB-FILE/${dtbfilename}/ ";
	DTB_TAG+="-e s/KERNEL-DTB/${dtbfilename}/ ";			#COMPAT
	if [ "${flashappname}" = "tegraflash.py" ]; then
		if [ "${tegraid}" != "0x18" ]; then
			DTBARGS+="--bldtb ${dtbfilename} ";
		fi
	else
		DTBARGS+="--dtbfile ${dtbfilename} ";
	fi;
else
	DTB_TAG+="-e /tegra.dtb/d ";
	DTB_TAG+="-e /DTBFILE/d ";
	DTB_TAG+="-e /KERNELDTB-FILE/d ";
fi;

# APP_TAG: RootFS
#
localsysfile=system.img;
APP_TAG+="-e s/size=1073741824/size=${rootfssize}/ ";
APP_TAG+="-e s/APPSIZE/${rootfssize}/ ";
APP_TAG+="-e /recovery.img/d ";
if [ "${reuse_systemimg}" = "true" ]; then
	APP_TAG+="-e s/filename=system.img/filename=${localsysfile}/ ";
	APP_TAG+="-e s/APPFILE/${localsysfile}/ ";
	if [ "${read_part_name}" == "" ]; then
		echo "Reusing existing ${localsysfile}... ";
		if [ ! -e "${localsysfile}" ]; then
			echo "file does not exist.";
			exit 1;
		fi;
		echo "done.";
	fi;
elif [ "${rootdev_type}" = "internal" ]; then
	APP_TAG+="-e s/filename=system.img/filename=${localsysfile}/ ";
	APP_TAG+="-e s/APPFILE/${localsysfile}/ ";
	if [ "${target_partname}" = "" -o "${target_partname}" = "APP" ]; then
		build_fsimg "$localsysfile" "$fillpat" \
		    "$rootfssize" "$rootfs_type" "$rootfs_dir";
	fi;
elif [ "${rootdev_type}" = "network" -o "${rootdev_type}" = "external" -a \
	${using_uboot} -eq 1 ]; then
	echo -n "generating /boot/extlinux/extlinux.conf files... ";
	APP_TAG+="-e s/filename=system.img/filename=${localsysfile}/ ";
	APP_TAG+="-e s/APPFILE/${localsysfile}/ ";
	NFSCONV="-e s/NFSARGS/${nfsiargs}/ ";
	NFSCONV+="-e s%NFSROOT%${nfsroot}% ";
	sed ${NFSCONV} < "${rootfs_dir}/boot/extlinux/extlinux.conf" > ./extlinux.conf;
	mv ./extlinux.conf "${rootfs_dir}/boot/extlinux/extlinux.conf";
	echo "done.";

	echo "generating system.img for booting... ";
	tmpdir=`mktemp -d`;
	mkdir -p "${tmpdir}/boot/extlinux" > /dev/null 2>&1;
	cp -f "${rootfs_dir}/boot/extlinux/extlinux.conf" "${tmpdir}/boot/extlinux" > /dev/null 2>&1;
	cp -f "${kernel_fs}" "${tmpdir}/boot" > /dev/null 2>&1;
	cp -f "${dtbfile}" "${tmpdir}/boot" > /dev/null 2>&1;
	cp -f initrd "${tmpdir}/boot" > /dev/null 2>&1;
	build_fsimg "$localsysfile" "$fillpat" \
		    "$rootfssize" "$rootfs_type" "$tmpdir";
else
	APP_TAG+="-e /filename=system.img/d ";
	APP_TAG+="-e /system.img/d ";
	APP_TAG+="-e /APPFILE/d ";
fi;

# TBC_TAG:== EBT
#
if [ "${tbcfile}" != "" ]; then
	cp2local tbcfile "${BL_DIR}/${tbcfilename}";
	TBC_TAG+="-e s/TXC/TBC/ ";
	TBC_TAG+="-e s/TBCNAME/cpu-bootloader/ ";
	TBC_TAG+="-e s/TBCTYPE/bootloader/ ";
	TBC_TAG+="-e s/TBCFILE/${tbcfilename}/ ";
else
	TBC_TAG+="-e s/TBCTYPE/data/ ";
	TBC_TAG+="-e /TBCFILE/d ";
fi;

# TBCDTB_TAG:== Bootloader DTB
#
if [ "${tbcdtbfile}" != "" ]; then
	cp2local tbcdtbfile "${BL_DIR}/${tbcdtbfilename}";
	append_bootargs_to_dtb "${tbcdtbfilename}";
	TBCDTB_TAG+="-e s/TBCDTB-NAME/bootloader-dtb/ ";
	TBCDTB_TAG+="-e s/TBCDTB-FILE/${tbcdtbfilename}/ ";
	if [ "${BINSARGS}" != "" ]; then
		BINSARGS+="bootloader_dtb ${tbcdtbfilename}; ";
	fi;
else
	TBCDTB_TAG+="-e s/TBCTYPE/data/ ";
	TBCDTB_TAG+="-e /TBCDTB-FILE/d ";
fi;

# EFI_TAG: Minimum FAT32 partition size is 64MiB (== 1 FAT cluster)
#
localefifile=efi.img;
efifs_size=$(( 64 * 1024 * 1024 ));
EFI_TAG+="-e s/size=67108864\s\+#EFISIZE/size=${efifs_size}/ ";
EFI_TAG+="-e s/EFISIZE/${efifs_size}/ ";
if [ "${bootloadername}" = "uefi.bin" ]; then
	build_fsimg $localefifile "" $efifs_size "FAT32" "";
	EFI_TAG+="-e s/EXI/EFI/ ";
	EFI_TAG+="-e s/#filename=efi.img/filename=${localefifile}/ ";
	EFI_TAG+="-e s/EFIFILE/${localefifile}/ ";
else
	EFI_TAG+="-e /EFIFILE/d ";
fi;

# GPT_TAG: tag should created before cfg and actual img should be
#	   created after cfg.
#
localpptfile=ppt.img;
localsptfile=gpt.img;
if [ ! -z "${bootpartsize}" -a ! -z "${emmcsize}" ]; then
	bplmod=$(( ${bootpartlim} % ${devsectsize} ));
	if [ ${bplmod} -ne 0 ]; then
		echo "Error: Boot partition limit is not modulo ${devsectsize}";
		exit 1;
	fi;
	bpsmod=$(( ${bootpartsize} % ${devsectsize} ));
	if [ ${bpsmod} -ne 0 ]; then
		echo "Error: Boot partition size is not modulo ${devsectsize}";
		exit 1;
	fi;
	gptsize=$(( ${bootpartlim} - ${bootpartsize} ));
	if [ ${gptsize} -lt ${devsectsize} ]; then
		echo "Error: No space for primary GPT.";
		exit 1;
	fi;
	GPT_TAG+="-e s/size=2097152\s\+#BCTSIZE/size=${bootpartsize}/ ";
	GPT_TAG+="-e s/size=8388608\s\+#PPTSIZE/size=${gptsize}/ ";
	GPT_TAG+="-e s/PPTSIZE/${gptsize}/ ";
	GPT_TAG+="-e s/#filename=ppt.img/filename=${localpptfile}/ ";
	GPT_TAG+="-e s/#filename=spt.img/filename=${localsptfile}/ ";
else
	GPT_TAG+="-e s/PPTSIZE/16896/ ";
fi;

# CFG:
#
if [[ ${cfgfile} =~ \.xml$ ]]; then
	localcfgfile=flash.xml;
else
	localcfgfile=flash.cfg;
fi;
echo -n "copying cfgfile(${cfgfile}) to ${localcfgfile}... ";
if [ "${BINSARGS}" != "" ]; then
	# Close BINSARGS before get used for the first time.
	BINSARGS+="\"";
	BINSCONV+="-e s/\"[[:space:]]*/\"/ ";
	BINSCONV+="-e s/\;[[:space:]]*\"/\"/ ";
	BINSARGS=`echo "${BINSARGS}" | sed ${BINSCONV}`;
fi;
CFGCONV+="${EBT_TAG} ";
CFGCONV+="${LNX_TAG} ";
CFGCONV+="${SOS_TAG} ";
CFGCONV+="${NCT_TAG} ";
CFGCONV+="${NVC_TAG} ";
CFGCONV+="${MB2BL_TAG} ";
CFGCONV+="${MPB_TAG} ";
CFGCONV+="${MBP_TAG} ";
CFGCONV+="${MB1_TAG} ";
CFGCONV+="${BPF_TAG} ";
CFGCONV+="${BPFDTB_TAG} ";
CFGCONV+="${SCE_TAG} ";
CFGCONV+="${SPE_TAG} ";
CFGCONV+="${TOS_TAG} ";
CFGCONV+="${EKS_TAG} ";
CFGCONV+="${FB_TAG}  ";
CFGCONV+="${WB0_TAG} ";
CFGCONV+="${APP_TAG} ";
CFGCONV+="${EFI_TAG} ";
CFGCONV+="${DTB_TAG} ";
CFGCONV+="${TBC_TAG} ";
CFGCONV+="${TBCDTB_TAG} ";
CFGCONV+="${GPT_TAG} ";
cat ${cfgfile} | sed ${CFGCONV} > ${localcfgfile}; chkerr;

# GPT:
# mkgpt need to update as per new flash_t186_l4t.xml,
# currently skipping mkgpt as gpt partition is taken care by tegraflash.
if [ ! -z "${bootpartsize}" -a ! -z "${emmcsize}" -a \
    "${tegraid}" != "0x18" ]; then
	echo "creating gpt(${localpptfile})... ";
	MKGPTOPTS="-c ${localcfgfile} -P ${localpptfile} ";
	MKGPTOPTS+="-t ${emmcsize} -b ${bootpartsize} -s 4KiB ";
	MKGPTOPTS+="-a GPT -v GP1 ";
	MKGPTOPTS+="-V ${MKGPTCMD} ";
	./mkgpt ${MKGPTOPTS};
	chkerr "creating gpt(${localpptfile}) failed.";
fi;

# FLASH:
#
cp2local flasher	"${BL_DIR}/${flashername}";
cp2local flashapp	"${BL_DIR}/${flashappname}";

if [ "${target_partname}" != "" ]; then
	validatePartID target_partid target_partname $target_partname $localcfgfile;
	tmp_updateid="${target_partid}:${target_partname}";
	sigheader=0;
	sigext=bin;
	case ${target_partname} in
	BCT) target_partfile="${bctfilename}";
	     FLASHARGS="${BCT} ${target_partfile} --updatebct SDRAM ";
	     ;;
	mb2) target_partfile="nvtboot.bin";
	     need_sign=1;
	     sigheader=1;
	     ;;
	bpmp-fw)
	     target_partfile="${bpffile}";
	     need_sign=1;
	     sigheader=1;
	     ;;
	bpmp-fw-dtb)
	     target_partfile="${bpfdtbfile}";
	     need_sign=1;
	     sigheader=1;
	     sigext=dtb;
	     ;;
	PPT) target_partfile="${localpptfile}"; ;;
	EBT) target_partfile="${bootloadername}"; need_sign=1; ;;
	cpu-bootloader)
	     target_partfile="${tbcfilename}";
	     need_sign=1;
	     sigheader=1;
	     ;;
	secure-os)
	     target_partfile="${tosfilename}";
	     need_sign=1;
	     sigheader=1;
	     sigext=img;
	     ;;
	eks) target_partfile="${eksfilename}";
	     need_sign=1;
	     sigheader=1;
	     sigext=img;
	     ;;
	LNX) target_partfile="${localbootfile}";
	     pre_cmds="write DTB ${dtbfilename}; ";
	     ;;
	kernel)
	     target_partfile="${localbootfile}";
	     pre_cmds="write kernel-dtb ${dtbfilename}; ";
	     ;;
	kernel-dtb) target_partfile="${dtbfilename}"; ;;
	NCT) target_partfile="${nctfilename}"; ;;
	SOS) target_partfile="${sosfilename}"; ;;
	NVC) target_partfile="${tegrabootname}"; need_sign=1; ;;
	MPB) target_partfile="${mtsprebootname}"; ;;
	MBP) target_partfile="${mtsname}"; ;;
	BPF) target_partfile="${bpffilename}"; ;;
	APP) target_partfile="${localsysfile}"; ;;
	DTB) target_partfile="${dtbfilename}"; ;;
	EFI) target_partfile="${localefifile}"; ;;
	TOS) target_partfile="${tosfilename}"; ;;
	EKS) target_partfile="${eksfilename}"; ;;
	FB)  target_partfile="${fbfilename}"; ;;
	WB0) target_partfile="${wb0bootname}"; ;;
	GPT) target_partfile="${localsptfile}"; ;;
	spe-fw)
	     target_partfile="${spefilename}";
	     need_sign=1;
	     sigheader=1;
	     ;;
	*)   echo "*** Update ${tmp_updateid} is not supported. ***";
	     exit 1; ;;
	esac;
	if [ "${read_part_name}" != "" ]; then
		target_partfile="${read_part_name}";
		echo "*** Reading ${tmp_updateid} and storing to ${target_partfile} ***";
	else
		echo "*** Updating ${tmp_updateid} with ${target_partfile} ***";
	fi;
	if [ "${FLASHARGS}" = "" ]; then
		FLASHARGS+=" --bl ${flashername} ${DTBARGS} ";
		FLASHARGS+=" --chip ${tegraid} --applet ${sosfilename} ";
	fi;

	if [ ${need_sign} -eq 1 ]; then
		pf_dir="$(dirname "${target_partfile}")";
		pf_fn="$(basename "${target_partfile}")";
		if [ ${sigheader} -eq 1 ]; then
			sighdr="_sigheader.${sigext}.encrypt";
			target_partfile=`echo "${pf_fn}" | awk -F '.' '{print $1}'`;
			target_partfile="${pf_dir}/signed/${target_partfile}${sighdr}";
		else
			target_partfile="${pf_dir}/signed/${pf_fn}.encrypt";
		fi;
		FLASHARGS+=" --cfg ${localcfgfile} ";
		FLASHARGS+=" ${BCT} ${bctfilename} ";
		pre_cmds+="sign; ";
	fi
	FLASHARGS+="$BCT ${bctfilename} ";
	FLASHARGS+="${BCTARGS} ";
	FLASHARGS+="--cfg  ${localcfgfile} ${BINSARGS} ";
	FLASHARGS+=" --cmd \"";
	FLASHARGS+="${pre_cmds}";
	if [ "${read_part_name}" != "" ]; then
		FLASHARGS+="read ${target_partname} ${target_partfile};\"";
	else
		FLASHARGS+="write ${target_partname} ${target_partfile};\"";
	fi
	echo "./${flashappname} ${FLASHARGS}";
	cmd="./${flashappname} ${FLASHARGS}";
	eval ${cmd};
	chkerr "Failed to flash/read ${target_board}.";
	if [ "${read_part_name}" != "" ]; then
		echo "*** The ${tmp_updateid} has been read successfully. ***";
		if [ "${target_partname}" = "APP" -a -x mksparse ]; then
			echo -e "\tConverting RAW image to Sparse image... ";
			mv -f ${target_partfile} ${target_partfile}.raw;
			./mksparse -v --fillpattern=0 ${target_partfile}.raw ${target_partfile};
		fi;
	else
		echo "*** The ${tmp_updateid} has been updated successfully. ***";
	fi;
	exit 0;
fi;

if [ -f odmsign.func ]; then
	source odmsign.func;
	odmsign;
	if [ $? -ne 0 ]; then
		exit 1;
	fi;
fi;

FLASHARGS+="--bl ${flashername} ${BCT} ${bctfilename} ";
FLASHARGS+="--odmdata ${odmdata} ";
FLASHARGS+="${DTBARGS}${MTSARGS}${SOSARGS}${NCTARGS}${FBARGS} ";
if [ "${flashappname}" = "tegraflash.py" ]; then
	FLASHARGS+="--cfg ${localcfgfile} ";
	FLASHARGS+="--chip ${tegraid} ";
	FLASHARGS+="${BCTARGS} ";
	FLASHARGS+="${BINSARGS} ";
	FLASHARGS+="${SKIPUID} ";
else
	FLASHARGS+="--configfile ${localcfgfile} ";
	FLASHARGS+="--setbct --create --wait -s 0 --go ";
fi;
flashcmd="./${flashappname} ${FLASHARGS}";
echo "${flashcmd}";
flashcmdfile="${BL_DIR}/flashcmd.txt";
echo "saving flash command in ${flashcmdfile}";
echo "${flashcmd}" | tee "${flashcmdfile}";

if [ ${no_flash} -ne 0 ]; then
	echo "*** no-flash flag enabled. Exiting now... *** ";
	exit 0;
fi;

echo "*** Flashing target device started. ***"
eval "${flashcmd}";
chkerr "Failed flashing ${target_board}.";
echo "*** The target ${target_board} has been flashed successfully. ***"
if [ "${rootdev_type}" = "internal" ]; then
	echo "Reset the board to boot from internal eMMC.";
elif [ "${rootdev_type}" = "network" ]; then
	if [ "${nfsroot}" != "" ]; then
		echo -n "Make target nfsroot(${nfsroot}) exported ";
		echo "on the network and reset the board to boot";
	else
		echo -n "Make the target nfsroot exported on the ";
		echo -n "network, configure your own DHCP server ";
		echo -n "with \"option-root=<nfsroot export path>;\" ";
		echo "properly and reset the board to boot";
	fi;
else
	echo -n "Make the target filesystem available to the device ";
	echo -n "and reset the board to boot from external ";
	echo "${target_rootdev}.";
fi;
echo;
exit 0;

# vi: ts=8 sw=8 noexpandtab

Due to TX2’s increased eMMC size of 32GB, currently cloning uses mksparse format, so the image won’t be mountable on the host under loopback, however we are looking into raw format.

As it turns out this script does produce both a raw image for the purpose of generating the sparse image and the resulting sparse image (when looking at it earlier I missed the fact that there was both the “.img” file and also a “.img.raw” file).

A useful option would be to clone only raw (a sparse image is smaller than a raw image if the file system is not full, but both images together still require much more disk space than just a raw image…plus I find something like bzip2 has better compression than a sparse image). There are some mount programs capable of working directly with a sparse image, but Fedora is not one of them. The mksparse program can be used later if desired to convert a raw image to a sparse image. I have not tested this with the TX2 image, but here is a mksparse summary for creating sparse from raw for those interested:

sudo mksparse -v --fillpattern=0 system.img.raw system.img

Something which would be very nice is the corollary to the mksparse utility: sparse2raw.

Does anyone know the exact maximum size root partition for the JTX2 (e.g., “-S 14580MiB” is the max on a TX1 or TK1)?

After asking around, it seems that the maximum someone’s been successful with is around 28GiB. At 30GiB and above, there is an error with one of the tools due to the file size. In this case it’s recommended to create an additional partition from the eMMC instead of one 32GB partition.

Please explain how the “APP” partition works in this topic. Is it one of the tiny partitions (normally invisible?) Or does “APP” contain the entire root partition of the TX2?

APP is the largest partition and contains the root filesystem (typically Ubuntu).

That exists. It’s called “cat” :-)

I presume that writing blocks of zeros to the flash is going to take longer than writing nothing, so if the time of actual-flashing is important (rather than just time of transferring bits) then a sparse file might still make sense.

You’ll notice that going from raw to sparse uses “bootloader/mksparse”. There is a kind of run-length encoding where empty blocks are not included when going from raw to sparse…reversing from sparse to raw with cat only works for subsets of the file system. If the original did not have sparse sections in the middle of data, then cat would work to some degree. The problem with sparse files for me is the need to loopback mount and adjust with rsync…this is why I keep the original raw file instead of the sparse file (I can always use mksparse to create a sparse file).

The way I underestand it:

Sparse files in a file system is when blocks containing all zeros are simply not stored on disk. However, reading them from the file system will return zeros.

“cat” reads a file from beginning to end, and thus will “unpack” those zero blocks to actual zero data. The output of “cat” can then be piped to a file on disk, which will be full (blocks of zeros will take up space on the disk.)

Witness:

nvidia@tegra-ubuntu:~$ df
Filesystem     1K-blocks     Used Available Use% Mounted on
/dev/mmcblk0p1  28768380 15328888  11955104  57% /
...
nvidia@tegra-ubuntu:~$ dd if=/dev/zero of=foo.sparse bs=4096 seek=32768 count=1
1+0 records in
1+0 records out
4096 bytes (4.1 kB, 4.0 KiB) copied, 0.00121155 s, 3.4 MB/s
nvidia@tegra-ubuntu:~$ ls -l foo.sparse
-rw-rw-r-- 1 nvidia nvidia 134221824 Jun 23 00:03 foo.sparse
nvidia@tegra-ubuntu:~$ df
Filesystem     1K-blocks     Used Available Use% Mounted on
/dev/mmcblk0p1  28768380 15328892  11955100  57% /
...
nvidia@tegra-ubuntu:~$ cat foo.sparse > foo.full
nvidia@tegra-ubuntu:~$ ls -l foo.full
-rw-rw-r-- 1 nvidia nvidia 134221824 Jun 23 00:04 foo.full
nvidia@tegra-ubuntu:~$ df
Filesystem     1K-blocks     Used Available Use% Mounted on
/dev/mmcblk0p1  28768380 15459968  11824024  57% /
...
nvidia@tegra-ubuntu:~$

Note that in the first case, “Available” goes down by 4 kB; after creating a full file, Available goes down by 131076 kB, representing that the initially sparse file foo.sparse was un-packed to a full file foo.full that allocates the full storage on disk.

Where does one run the flash.sh script from? Host or TX2? Where can the resultant image reside, on the host or only on a drive connected to the TX2, separate from the emmc?

There are more than a dozen small partitions after the APP one, IIRC. Does the flash.sh script copy those at the same time to the resultant image?

How does one grab the contents of the sliding “code window” in order to copy it to the hard drive (and replace the 3 “flash.sh” files already on the host?

All of the flash commands are run from the PC host when the TX2 is in recovery mode and connected by the micro-B USB cable. A clone places the file on the PC host, so the host needs plenty of extra free disk space before starting the clone.

Do note that each command to flash or clone requires recovery mode to be restarted before starting a new command. E.G., cloning two partitions in a row won’t work without going into a fresh recovery mode between clones.

Naming the “APP” partition just clones the rootfs. You can name each partition and clone each. On a TK1 there is an “ALL” target which clones everything, I don’t know if that works on a TX2 though (generally you’d want the rootfs). Somewhere under the covers partition names are converted to a starting offset address and span. This is documented for the TK1, and may even be the same on a TX2, but I have not looked…offsets can be used essentially like the “dd” command over the entire disk (or any subset of the disk).

Btw, the driver package creates the “Linux_for_Tegra/” subdirectory on the host when it is unpacked. It is this directory which contains the flash.sh script. So far as which flash.sh to use you’d use the one quoted here (this adds an option used in cloning, otherwise the script is the same as the default flash.sh):
https://devtalk.nvidia.com/default/topic/1000105/jetson-tx2/tx2-cloning/post/5111893/#5111893

Thanks, linuxdev.

One of the questions is, how do I get the updated flash.sh? download from somewhere or is there a method to copy/paste the lines in the forum’s “code window?”

I used copy and paste (then “chmod ugo+x flash.sh”). I suspect the next L4T release (estimated in July) will probably have the change added in already.

How does one copy and paste nearly 700 lines and without line numbers? I looked for a forum function but must have passed right over it.

I hope the flash.sh can do ALL partitions (disk image) at once, then do it again as a “golden” backup copy. On the hard drive I can select the other image and use gparted to move all the small partitions to the end of the disk (hoping the relative numbers change properly!) and then resize rootfs, all on the nvme drive. Place the nvme drive back onto the TX2, mod the extlinux.conf, and see if we’re in business.

To copy that file I highlight the first line with the mouse, then hold down the shift key and hit the “page down” many times (followed by “copy”). I think one reason people quote in code blocks so often is that the spam filters disallow many file attachments…plus it isn’t obvious that attachments can be made since they can only be added after a post is made.

There are assumptions in the boot environment which make me doubt that moving partitions around will work. Some parts of boot will refer to the GPT partition label, and those parts should be ok with moving partitions around. In a case where offsets are used to refer to a partition this will fail…but it is worth trying, just beware it may not be possible to move hidden partitions around randomly. When flashing to mmcblk0p1 and renaming “root=” in extlinux.conf only the rootfs goes to the renamed “root=” device…hidden partitions remain on the eMMC. If you want to accomplish more than using a separate device for rootfs you may need to describe a use-case for better answers.

Cloning one partition at a time and then concatenating them should be the same as using clone of ALL. Typically though the flash.sh with “-r” will do a fresh flash of the hidden partitions and boot environment even if the rootfs is reused. Restoring from “ALL” would be different on a TX2 versus a TK1, but there is still some useful information here:
http://elinux.org/Jetson/Cloning