Massflash with disk encryption on Xavier NX eMMC

Hi @JerryChang,
Yes, I confirm it is luks1.

eval ${GEN_LUKS_PASS_CMD} | ${CRYPTSETUP_BIN} \
		--type luks1 \
		-c aes-cbc-essiv:sha256 \
		-s 128 \
		--uuid "${__fsuuid}" \
		luksFormat \
		${loop_dev};
	chkerr "Add LUKS header on ${__localsysfile} failed.";

And our UDA partition size is 335544320 is is greater than you suggested. Is there any relation of partition table as we already said disk encryption is working when we do not use massflash and massflash also works when we do not use disk encryption.

We are trying to achieve altogether. Think it will make sense.

hello AkterHossain,

it looks some defects we may revise back to your details steps in comment #13,
please remove the quotes of -i ekb.key since it’s me to emphasize those input keys.
for example, #3. Populate internal flash image (Successful)
sudo ROOTFS_ENC=1 ./tools/kernel_flash/l4t_initrd_flash.sh --no-flash -p -i $XKEYS/ekb.key jetson-xavier-nx-devkit-emmc internal
and also, #5. Populate external flash image
sudo ROOTFS_ENC=1 ./tools/kernel_flash/l4t_initrd_flash.sh --no-flash -p -i $XKEYS/ekb.key --external-device nvme0n1p1 -S 220GiB -c ./tools/kernel_flash/flash_l4t_nvme_rootfs_enc.xml --external-only -- massflash 2 --appen jetson-xavier-nx-devkit-emmc external

also, please help to narrow down the issue for this step, #7. Massflash 2 devices concurrently
how about using massflash 1 for testing, can this single device flash command to flash successfully? then, please also confirm device has boot-up correctly.
i.e. sudo ./tools/kernel_flash/l4t_initrd_flash.sh --showlogs --flash-only -p -i $XKEYS/ekb.key --massflash 1

to ensure the image blob has created as encrypted correctly.
you may also check whether removing key assign for image flashing, and please share the logs for reference,
i.e. sudo ./tools/kernel_flash/l4t_initrd_flash.sh --showlogs --flash-only --massflash 1

Hi @JerryChang,
For initrd flash script, double quotes are mandatory. Here -p means additional parameters to pass on the subsequent flash.sh scripts. And when we use double quotes with our custom keys the disk are encrypting fine.

We also tested --massflash 1 and it is also works for only one device. As we already mentioned about ECID multiple times, ECID is unique per device and it is being used as passphrase for other keys. So when we generate image blob, only one ECID being used and hereby only one device is successfully flashed and booted but others are not.

We think you better help us guiding how to use generic passphrase instead of unique ECID. We think it would make sense to you.

1 Like

hello AkterHossain,

each device need an unique encryption key, it’s not suggest to use the same encryption key for all devices.
please also check developer guide, for the Disk Encryption Implementation in Jetson Linux,
please read the [To Enhance initrd to Unlock an Encrypted Rootfs] session for details.
recap as below…

The init script in the initrd follows these steps to check the encrypted root device, unlock it, and mount it:

3.Unlock the encrypted root device with the per-device unique passphrase.

hello AkterHossain,

furthermore,
you may modify the scripts, please have some modification to use the generic passphrase.
for example,
please modify initrd so the disk encryption can use the generic passphrase,
~/nvidia/nvidia_sdk/JetPack_<version>_<platform>/Linux_for_Tegra/tools/ota_tools/version_upgrade/init

please follow Modifying Jetson RAM Disk to modify the default configuration of a Jetson device’s RAM disk.

96 		# Unlock the encrypted dev
97 		nvluks-srv-app -u -c "${crypt_disk_uuid}" | LD_LIBRARY_PATH="/lib/cryptsetup" \
98 			/lib/cryptsetup/ld-linux-aarch64.so.1 \
99 			/sbin/cryptsetup luksOpen "${enc_dev}" "${enc_dm_name}";

you should update the disk_encryption_helper.func for using a generic passphrase also,
for example,
~/nvidia/nvidia_sdk/JetPack_<version>_<platform>/Linux_for_Tegra/tools/disk_encryption/disk_encryption_helper.func

491 	# Check ECID
492 	if [ "${__ecid}" == "" ]; then
493 		echo "ERROR: build_enc_root_fsimg: ECID is null ."
494 		exit 1
495 	fi;
...
497 	# Check gen_luks_passphrase.py
498 	local genpass_dir="${LDK_DIR}/tools/disk_encryption";
499 	local genpass_opt="";
500 	GEN_LUKS_PASS_CMD="${genpass_dir}/gen_luks_passphrase.py";
501 	if [ ! -f "${GEN_LUKS_PASS_CMD}" ]; then
502 		echo "ERROR ${GEN_LUKS_PASS_CMD} is not found."
503 		exit 1
504 	fi;
505 	if [ "${enc_rfs_keyfile}" != "" ]; then
506 		genpass_opt+="-k \"${enc_rfs_keyfile}\" ";
507 	fi;
508 	genpass_opt+="-u -e '${__ecid}' "
509 	genpass_opt+="-c '${__rootfsuuid}'";
510 	GEN_LUKS_PASS_CMD+=" ${genpass_opt}";

Hi @JerryChang,
Thank you for your update.

I didn’t see any script like nvluks-srv-app -u -c ... in Linux_for_Tegra/tools/ota_tools/version_upgrade/init file. Here is the details of this file.

initrd_dir=/mnt/initrd;
dhclient_flag="true";
count=0;

echo "Starting L4T initial RAM disk" > /dev/kmsg;

#Mount procfs, devfs, sysfs and debugfs
mount -t proc proc /proc
if [ $? -ne 0 ]; then
	echo "ERROR: mounting proc fail..." > /dev/kmsg;
	exec /bin/bash;
fi;
mount -t devtmpfs none /dev
if [ $? -ne 0 ]; then
	echo "ERROR: mounting dev fail..." > /dev/kmsg;
	exec /bin/bash;
fi;
mount -t sysfs sysfs /sys
if [ $? -ne 0 ]; then
	echo "ERROR: mounting sys fail..." > /dev/kmsg;
	exec /bin/bash;
fi;
mount -t debugfs none /sys/kernel/debug/
if [ $? -ne 0 ]; then
	echo "ERROR: mounting debugfs fail..." > /dev/kmsg;
	exec /bin/bash;
fi;

# create reboot command based on sysrq-trigger
if [ -e "/proc/sysrq-trigger" ]; then
	echo -e "#!/bin/bash \necho b > /proc/sysrq-trigger;" > /sbin/reboot;
	chmod 755 /sbin/reboot;
fi;

dev_regex='root=\/dev\/[abcdefiklmnprstv0-9]*'
uuid_regex='root=PARTUUID=[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}'
rootdev="$(cat /proc/cmdline | grep -oE "\<${dev_regex}|${uuid_regex}\>" | tail -1)"
if [ "${rootdev}" != "" ]; then
	if [[ "${rootdev}" =~ "PARTUUID" ]]; then
		rootdev=$(echo "${rootdev}" | sed -ne "s/root=\(.*\)/\1/p")
	else
		rootdev=$(echo "${rootdev}" | sed -ne "s/root=\/dev\/\(.*\)/\1/p")
	fi
	echo "Root device found: ${rootdev}" > /dev/kmsg;
fi

if [[ "${rootdev}" == PARTUUID* ]]; then
	count=0;
	while [ ${count} -lt 50 ]; do
		sleep 0.2;
		count="$(expr ${count} + 1)"

		mount "${rootdev}" /mnt/;
		if [ $? -eq 0 ]; then
			break;
		fi
	done
	mountpoint /mnt/;
	if [ $? -ne 0 ]; then
		echo "ERROR: ${rootdev} mount fail..." > /dev/kmsg;
		exec /bin/bash;
	fi;
elif [[ "${rootdev}" == mmcblk* || "${rootdev}" == nvme* ]]; then
	if [ ! -e "/dev/${rootdev}" ]; then
		count=0;
		while [ ${count} -lt 50 ]
		do
			sleep 0.2;
			count=`expr $count + 1`;
			if [ -e "/dev/${rootdev}" ]; then
				break;
			fi
		done
	fi
	if [ -e "/dev/${rootdev}" ]; then
			echo "Found dev node: /dev/${rootdev}" > /dev/kmsg;
	else
		echo "ERROR: ${rootdev} not found" > /dev/kmsg;
		exec /bin/bash;
	fi
	mount /dev/${rootdev} /mnt/;
	if [ $? -ne 0 ]; then
		echo "ERROR: ${rootdev} mount fail..." > /dev/kmsg;
		exec /bin/bash;
	fi;
elif [[ "${rootdev}" == sd* ]]; then
	if [ ! -e "/dev/${rootdev}" ]; then
		while [ ${count} -lt 50 ]
		do
			sleep 0.2;
			count=`expr $count + 1`;
			if [ -e "/dev/${rootdev}" ]; then
				break;
			fi
		done
	fi
	if [ -e "/dev/${rootdev}" ]; then
			echo "Found dev node: /dev/${rootdev}" > /dev/kmsg;
	else
		echo "ERROR: ${rootdev} not found" > /dev/kmsg;
		exec /bin/bash;
	fi
	mount /dev/${rootdev} /mnt/;
	if [ $? -ne 0 ]; then
		echo "ERROR: ${rootdev} mount fail..." > /dev/kmsg;
		exec /bin/bash;
	fi;
elif [[ "${rootdev}" == "nfs" ]]; then
	eth=`cat /proc/cmdline | sed 's/.* ip=\([a-z0-9.:]*\) .*/\1/' | awk -F ":" '{print $6}'`;
	echo "Ethernet interface: $eth" > /dev/kmsg;
	ipaddr=`ifconfig "$eth" | grep -A1 "$eth" | grep "inet addr" | sed 's/.*addr:\([0-9\.]*\) .*/\1/'`;
	if [[ "$ipaddr" =~ [0-9]*.[0-9]*.[0-9]*.[0-9]* ]]; then
		echo "IP Address: $ipaddr" > /dev/kmsg;
		dhclient_flag="false";
	else
		while [ ${count} -lt 50 ]
		do
			sleep 0.2;
			ipaddr=`ifconfig "$eth" | grep -A1 "$eth" | grep "inet addr" | sed 's/.*addr:\([0-9\.]*\) .*/\1/'`;
			if [[ "$ipaddr" =~ [0-9]*.[0-9]*.[0-9]*.[0-9]* ]]; then
				echo "IP Address: $ipaddr" > /dev/kmsg;
				dhclient_flag="false";
				break;
			fi
			count=`expr $count + 1`;
		done
	fi
	if [ "$dhclient_flag" == "true" ]; then
		timeout 8s /sbin/dhclient $eth;
		if [ $? -ne 0 ]; then
			echo "ERROR: dhclient fail..." > /dev/kmsg;
			exec /bin/bash;
		fi;
	fi;
	nfsroot_path="`cat /proc/cmdline | sed -e 's/.*nfsroot=\([^ ,]*\)[ ,].*/\1 /'`";
	nfsroot_opts="`cat /proc/cmdline | sed -ne 's/.*nfsroot=\([^ ,]*\),\([^ ]*\).*/\2 /p'`";
	if [[ "${nfsroot_opts}" == "" ]]; then
		nfsroot_opts="nolock"
	fi
	mount -t nfs -o ${nfsroot_opts} ${nfsroot_path} /mnt/ &>/dev/kmsg;
	if [ $? -ne 0 ]; then
		echo "ERROR: NFS mount fail..." > /dev/kmsg;
		exec /bin/bash;
	fi;
elif [[ "${rootdev}" == "initrd" ]]; then
	echo "Mount initrd as rootfs and enter recovery mode" > /dev/kmsg;
	exec /bin/bash /bin/nv_recovery.sh
else
	echo "No root-device: Mount failed" > /dev/kmsg;
	exec /bin/bash;
fi

echo "Rootfs mounted over ${rootdev}" > /dev/kmsg;
mount -o bind /proc /mnt/proc;
mount -o bind /sys /mnt/sys;
mount -o bind /dev/ /mnt/dev;
cd /mnt;
cp /etc/resolv.conf etc/resolv.conf

echo "Switching from initrd to actual rootfs" > /dev/kmsg;
mount --move . /
exec chroot . /sbin/init 2;

Also I modified disk_encryption_helper.func as below:

        # Check ECID
	#if [ "${__ecid}" == "" ]; then
	#	echo "ERROR: build_enc_root_fsimg: ECID is null ."
	#	exit 1
	#fi;

	# Check gen_luks_passphrase.py
	local genpass_dir="${LDK_DIR}/tools/disk_encryption";
	local genpass_opt="";
	GEN_LUKS_PASS_CMD="${genpass_dir}/gen_luks_passphrase.py";
	if [ ! -f "${GEN_LUKS_PASS_CMD}" ]; then
		echo "ERROR ${GEN_LUKS_PASS_CMD} is not found."
		exit 1
	fi;
	if [ "${enc_rfs_keyfile}" != "" ]; then
		genpass_opt+="-k \"${enc_rfs_keyfile}\" ";
	fi;
	#genpass_opt+="-u -e '${__ecid}' "
	#genpass_opt+="-c '${__rootfsuuid}'";
	#GEN_LUKS_PASS_CMD+=" ${genpass_opt}";

	genpass_opt+="-g -c 'generic-key' ";
	GEN_LUKS_PASS_CMD+=" ${genpass_opt}";

But still no luck.

hello AkterHossain,

I’ve point-out incorrect file, please follow Modifying Jetson RAM Disk to modify the default configuration of a Jetson device’s RAM disk.

Hi @JerryChang,
Thanks for pointing out the correct file. I found two initrd file.

  1. $L4T/bootloader/initrd
  2. $L4T/rootfs/boot/initrd

Which one should I modify or both?

hello AkterHossain,

you should update this one, $L4T/bootloader/initrd
the image file under rootfs is create when flash process is running and system.img will be generated.
BTW, if you’ve include -r options to the flash command, it’ll re-use the exist system.img.

Hi @JerryChang,

Now I got Error: Return value 19 when running following command:

sudo ROOTFS_ENC=1 BOARDID=3668 BOARDSKU=0001 FAB=300 BOARDREV=B.0 ./tools/kernel_flash/l4t_initrd_flash.sh --no-flash --external-device nvme0n1p1 -S 200GiB -c ./tools/kernel_flash/flash_l4t_nvme_rootfs_enc.xml --external-only --massflash 5 --append jetson-xavier-nx-devkit-emmc external

Full log:
external.log (158.0 KB)

The full procedure I followed as below:

  1. Reset Linux_for_Tegra
cd ~/nvidia/4.6.1
sudo rm -rf ./Linux_for_Tegra ./trusty
tar xf ./jetson_linux_r32.7.1_aarch64.tbz2
tar xvjf ./secureboot_r32.7.1_aarch64.tbz2
cd ./Linux_for_Tegra/rootfs
sudo tar xpf ../../tegra_linux_sample-root-filesystem_r32.7.1_aarch64.tbz2
cd ..
sudo ./apply_binaries.sh

# create a defult user 
sudo ./tools/l4t_create_default_user.sh -u nvidia -p nvidia -n nvidia --accept-license
cd ..
tar xvf ./public_sources.tbz2
tar xvf ./Linux_for_Tegra/source/public/trusty_src.tbz2
  1. Update sector size in partition layout ./tools/kernel_flash/flash_l4t_nvme_rootfs_enc.xml . For 232GiB NVMe storage, use 488397168 as num_sectors .
<?xml version="1.0"?>
<!-- Nvidia Tegra Partition Layout Version 1.0.0 -->
<partition_layout version="01.00.0000">
    <device type="nvme" instance="0" sector_size="512" num_sectors="488397168">
        <partition name="master_boot_record" type="protective_master_boot_record">
        ...
        ...
  1. Modified disk_encryption_helper.func

bootpartuuid="";
bootpartuuid_ext=""
bootpartuuid_b_ext=""
bootpartuuidfile="${BL_DIR}/l4t-bootpart-uuid.txt";
uuidfile="${BL_DIR}/l4t-uuid.txt"
enc_user_disk_list=();
if [ ${rootfs_ab} -eq 1 ]; then
	bootpartuuid_b="";
fi;

#
# Generate the partition UUID of the boot partition
#
function bootpartuuid_gen() {
	local __boot_id="${1}";
	local __uuid="";
	local __uuidgen_installed="$(which uuidgen || true)";

	if [ "${__uuidgen_installed}" == "" ]; then
		echo "Error: uuidgen not installed! Please provide the UUID or install"
		echo "uuidgen. For example, to install uuidgen for Ubuntu distributions,"
		echo "execute the command 'sudo apt install uuid-runtime'. Otherwise a"
		echo "UUID can be provided by storing a UUID to the file"
		echo "${bootpartuuidfile}."
		usage allunknown 1;
	fi;

	__uuid="$(uuidgen)";
	setval "bootpartuuid${__boot_id}" __uuid;

	echo "${__uuid}" > "${bootpartuuidfile}${__boot_id}"
	echo "Generated UUID ${__uuid} for mounting boot APP${__boot_id} partition."
}

#
# Check the partition UUID of the boot partition
#
function bootpartuuid_chk_and_gen() {
	local __boot_id="${1}";
	local __uuid="";
	local __uuid_regex="([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})";

	# read UUID which stored in the file ${bootpartuuidfile} if the file exist
	if [ -f "${bootpartuuidfile}${__boot_id}" ]; then
		__uuid="$(sed -nr "s/^${__uuid_regex}$/\1/p" "${bootpartuuidfile}${__boot_id}")";

		if [ "${#__uuid}" != "36" ]; then
			echo "File ${bootpartuuidfile}${__boot_id} contains invalid UUID!"
			usage allunknown 1;
		fi;

		setval "bootpartuuid${__boot_id}" __uuid;
		echo "Using UUID ${__uuid} for mounting boot APP${__boot_id} partition."
	fi;

	# generate UUID if ${bootpartuuidfile} isn't present
	eval __uuid='$'{"bootpartuuid${__boot_id}"};
	if [ "${__uuid}" == "" ]; then
		bootpartuuid_gen "${__boot_id}";
	fi;
}

#
# Restore the partition UUID of the boot partition
#
function bootpartuuid_restore() {
	local ext="${1}"
	local _bootpartuuid="bootpartuuid${ext}"
	local _bootpartuuid_b

	bootpartuuid_chk_and_gen "${ext}";

	if [[ "${rootfs_ab}" == 1 ]]; then
		# get UUID for APP_b
		_bootpartuuid_b="bootpartuuid_b${ext}"
		bootpartuuid_chk_and_gen "_b${ext}";
	fi

	if [[ "${!_bootpartuuid}" == "" ]] || \
	   [[ "${rootfs_ab}" == 1 && "${!_bootpartuuid_b}" == "" ]]; then
		echo "No UUID found for boot partition! If the boot partition"
		echo "is not currently being mounted using a partition UUID,"
		echo "then flash the device by specifying the boot device that"
		echo "was specified when previously flashing the entire system"
		echo "(eg. /dev/mmcblk0p1). Otherwise, to mount the boot"
		echo "partition using a partition UUID please either:"
		echo "1. If you know the UUID for the root partition save it"
		echo "   to the file ${bootpartuuidfile},"
		echo "   or for boot B partition save it"
		echo "   to the file  ${bootpartuuidfile}_b"
		echo "2. Re-flash entire system to generate a new UUID."
		usage allunknown 1;
	fi;
}

#
# Common UUID gen function
#
function uuid_gen() {
	local __name="${1}";
	local __ret_uuid="${2}";
	local __uuid="";
	local uuidgen_installed="$(which uuidgen || true)";

	if [ "${uuidgen_installed}" == "" ]; then
		echo "Error: uuidgen not installed! Please provide the UUID or install"
		echo "uuidgen. For example, to install uuidgen for Ubuntu distributions,"
		echo "execute the command 'sudo apt install uuid-runtime'. Otherwise a"
		echo "UUID can be provided by storing a UUID to the file"
		echo "${uuidfile}."
		usage allunknown 1;
	fi

	__uuid="$(uuidgen)";
	setval "${__ret_uuid}" __uuid;

	echo "${__uuid}" > "${uuidfile}_${__name}";
	echo "Generated UUID ${__uuid} for mounting ${__name} partition.";
}

#
# Common UUID chk and gen function
#
function uuid_chk_and_gen() {
	local __name="${1}";
	local __ret_uuid="${2}";
	local __uuid="";
	local __uuid_regex="([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})";

	# Read UUID which stored in the file ${uuidfile} if the file exist.
	if [ -f "${uuidfile}_${__name}" ]; then
		__uuid="$(sed -nr "s/^${__uuid_regex}$/\1/p" "${uuidfile}_${__name}")";

		if [ "${#__uuid}" != "36" ]; then
			echo "File ${uuidfile}_${__name} contains invalid UUID!";
			usage allunknown 1;
		fi

		setval "${__ret_uuid}" __uuid;
		echo "Using UUID ${__uuid} for mounting ${__name} partition."
	else
		# Generate UUID if ${uuidfile} isn't present.
		uuid_gen "${__name}" "${__ret_uuid}";
	fi;
}

#
# Common UUID restore function
#
function uuid_restore {
	local __name="${1}";
	local __ret_uuid="${2}";

	uuid_chk_and_gen "${__name}" "${__ret_uuid}";
}

#
# Prepare dependent binary list for LUKS disk encrytption suport
#
function prepare_luks_bin_list() {
	# Usage:
	#	prepare_luks_bin_list {__ldk_path} \
	#		{__rootfs_path} \
	#		{__bin_list}
	#
	# This will set up the dependent binaries into {__bin_list}.
	local __ldk_path="${1}";
	local __rootfs_path="${2}";
	local __bin_list="${3}";
	local __QEMU_BIN="";
	local __libs_str="";
	local __libs_list=();

	# Check qemu
	if [ -f "${__ldk_path}/../qemu-aarch64-static" ]; then
		__QEMU_BIN="${__ldk_path}/../qemu-aarch64-static";
	elif [ -f "/usr/bin/qemu-aarch64-static" ]; then
		__QEMU_BIN="/usr/bin/qemu-aarch64-static";
	else
		if [ -z "${__QEMU_BIN}" ]; then
			echo "ERROR qemu not found! To install - please run: " \
				"\"sudo apt-get install qemu-user-static\""
			exit 1
		fi;
	fi;

	# Check rootfs
	if [ ! -e "${__rootfs_path}/etc/lsb-release" ]; then
		echo "rootfs has not been extracted."
		exit 1
	fi;

	# Install QEMU to rootfs
	install --owner=root --group=root "${__QEMU_BIN}" "${__rootfs_path}/usr/bin/"

	# Get the dependent binary list
	pushd "${__rootfs_path}" > /dev/null 2>&1;
	__libs_str="$(LC_ALL=C chroot . ldd /sbin/cryptsetup)";
	popd > /dev/null 2>&1;

	__libs_str="$(echo "${__libs_str}" | awk '{print $(NF-1)}')";
	__libs_list=(${__libs_str// /});

	eval "${__bin_list}=("${__libs_list[@]}")";

	# Clean up
	rm -f "${__rootfs_path}/usr/bin/qemu-aarch64-static";
}

#
# Update the initrd for LUKS support
#
function prepare_luks_initrd() {
	# Usage:
	#	prepare_luks_initrd {__kernelinitrd} \
	#	{__rootfs_path} \
	#	{__rootfsuuid} \
	#	{__bin_list}
	#
	# This script assume that it is in the folder where the initrd is extracted.
	# This script modify the content of initrd.
	local __params=("${@}");
	local __kernelinitrd="${__params[0]}";
	local __rootfs_path="${__params[1]}";
	local __rootfsuuid="${__params[2]}";
	local __params_len=${#__params[@]};
	local __bin_list=();
	local script_name=prepare_luks_initrd;

	echo "${script_name}: Begin to copy binaries into initrd"

	for ((i=3; i<${__params_len}; i++)); do
		__bin_list+=("${__params[${i}]}")
	done

	if [ ! -e "${__kernelinitrd}" ]; then
		echo "${script_name}: initrd doesn't exist? "
		return 1
	fi

	if [ ! -e "${__rootfs_path}/etc/lsb-release" ]; then
		echo "${script_name}: rootfs has not been extracted"
		return 1
	fi

	# Extract the initrd
	gunzip -c "${__kernelinitrd}" | cpio -i
	if [ $? -ne 0 ]; then return 1; fi

	local src;
	local dst;

	# Copy all the binaries
	install -o 0 -g 0 -m 0755 -d "lib/cryptsetup"
	for bin in "${__bin_list[@]}"
	do
		src="${__rootfs_path}${bin}"
		if [[ ${bin} == *"lib"* ]]; then
			dst="lib/cryptsetup/";
		elif [[ ${bin} == *"sbin"* ]]; then
			dst="sbin/";
		fi;
		install -o 0 -g 0 -D "${src}" "${dst}"
	done

	# Add /etc/crypttab
	echo "crypt_root UUID=${__rootfsuuid}" > etc/crypttab
	for enc_usr_disk in "${enc_user_disk_list[@]}"
	do
		local __dm_name;
		local __fsuuid;
		__dm_name="$(echo "${enc_usr_disk}" | awk -F " " '{print $1}')";
		__fsuuid="$(echo "${enc_usr_disk}" | awk -F " " '{print $2}')";
		echo "${__dm_name} UUID=${__fsuuid}" >> etc/crypttab;
	done

	# Add locking path /run/cryptsetup
	install -o 0 -g 0 -m 0755 -d "run/cryptsetup"

	# Package the initrd
	find . | cpio -H newc -o | gzip -9 -n > "${__kernelinitrd}"
	if [ $? -ne 0 ]; then return 1; fi

	echo "${script_name}: Finish copying binaries into initrd"
}

#
# Validate FS size
#
function validate_fs_size () {
	local __fssize="${1}";
	local __bcnt=$(( ${__fssize} / 512 ));
	local __bcntdiv=$(( ${__fssize} % 512 ));
	if [ ${__bcnt} -eq 0 ] || [ ${__bcntdiv} -ne 0 ]; then
		echo "Error: file system size has to be 512 bytes allign.";
		exit 1;
	fi;
}

#
# Create disk image with specific pattern
#
function create_disk_image_with_pattern () {
	local __pattern="${1}";
	local __imgfile="${2}";
	local __fssize="${3}";

	if [ -f "${__imgfile}" ]; then
		rm -f "${__imgfile}";
	fi;

	if [ "${__pattern}" != "" ] && [ "${__pattern}" != "0" ]; then
		local __fc=$(printf '%d' ${__pattern});
		local __fillc=$(printf \\\\$(printf '%02o' ${__fc}));
		< /dev/zero head -c ${__fssize} | tr '\000' ${__fillc} > ${__imgfile};
		chkerr "making ${__imgfile} with fillpattern($__fillc}) failed.";
	else
		truncate --size ${__fssize} ${__imgfile};
		chkerr "making ${__imgfile} with zero fillpattern failed.";
	fi;
}

#
# Convert to sparse image
#
function convert_to_sparse_image () {
	local __pattern="${1}";
	local __imgfile="${2}";

	if [ "${__pattern}" != "" ] && [ -x mksparse ]; then
		echo -e -n "\tConverting RAW image to Sparse image... ";
		mv -f "${__imgfile}" "${__imgfile}.raw";
		if [ "${BLBlockSize}" != "" ]; then
			blblksizeoption="-b $BLBlockSize";
		fi;
		./mksparse ${blblksizeoption} --fillpattern=${__pattern} ${__imgfile}.raw ${__imgfile}; chkerr;
	fi;
}

#
# Building the boot file system image for boot partition (APP)
#
function build_boot_fsimg () {
	local __localsysfile="${1}";
	local __fillpat="${2}";
	local __bootfssize="${3}";
	local __bootfs_type="${4}";
	local __bootfs_dir="${5}";
	local __cmdline="${6}";
	local __do_sign="${7}";
	local _extlinux_conf="extlinux/extlinux.conf"

	echo "Making ${__localsysfile}... ";

	validate_fs_size "${__bootfssize}";

	if [ ! -f "${__bootfs_dir}/${_extlinux_conf}" ]; then
		echo "${__bootfs_dir}/${_extlinux_conf} is not found, exiting...";
		exit 1
	fi;

	create_disk_image_with_pattern "${__fillpat}" "${__localsysfile}" "${__bootfssize}";

	loop_dev="$(losetup --show -f "${__localsysfile}")";
	chkerr "mapping ${__localsysfile} to loop device failed.";
	mkfs -t ${__bootfs_type} "${loop_dev}" > /dev/null 2>&1;
	chkerr "formating ${__bootfs_type} filesystem on ${__localsysfile} failed.";
	mkdir -p mnt;
	chkerr "make ${__localsysfile} mount point failed.";
	mount "${loop_dev}" mnt;
	chkerr "mount ${__localsysfile} failed.";

	# Processing partition data.
	mkdir -p "mnt/dtb";	chkerr "make ${__localsysfile}/dtb failed.";
	cp -f "${kernel_fs}" "mnt";
	chkerr "Copying ${kernel_fs} failed.";
	if [ -f "${dtbfilename}" ]; then
		cp -f "${dtbfilename}" "mnt/dtb/${dtbfilename}";
		chkerr "populating ${dtbfilename} to ${__localsysfile}/dtb failed.";
	fi;

	pushd mnt > /dev/null 2>&1;
	echo -n -e "\tpopulating bootfs from ${__bootfs_dir} ... ";
	(cd ${__bootfs_dir}; tar cf - *) | tar xf - ; chkerr;

	# Populate extlinux.conf if "${__cmdline}" exists
	if [ "${__cmdline}" != "" ]; then
		# Add the "${__cmdline}" at the APPEND line if it does not exist.
		echo -n -e "\tpopulating ${_extlinux_conf} ... ";
		rootfs_found=$(grep -cE "${__cmdline}" "./${_extlinux_conf}");
		if [ "${rootfs_found}" == "0" ];then
			sed -i "/^[ \t]*APPEND/s|\$| ${__cmdline}|" "./${_extlinux_conf}";
			chkerr;
		fi;
	fi;
	if [ "${__do_sign}" = "True" ]; then
		local kernel_fs_basename;
		kernel_fs_basename=$(basename "${kernel_fs}");
		echo -n -e "\tgenerating sig file of ${kernel_fs_basename} ... ";
		signimage "./${kernel_fs_basename}" "True" "kernel" "${minratchet_configname}"; chkerr;
		echo -n -e "\tgenerating sig file of ${dtbfilename} ... ";
		signimage "./dtb/${dtbfilename}" "True" "kernel_dtb" "${minratchet_configname}"; chkerr;
		echo -n -e "\tgenerating sig file of initrd ... ";
		signimage "./initrd" "True" "data"; chkerr;
		echo -n -e "\tgenerating sig file of ${_extlinux_conf} ... ";
		# Signing tool will pad extlinux.conf with 0x80 to be 16-byte aligned.
		# This pad byte of 0x80 may cause some utilities fail to read the entire
		# extlinux.conf.
		# So, pad extlinux.conf to 16-byte aligned with linefeed.
		pad_file_aligned "${_extlinux_conf}" 16 "\x0a";
		signimage "${_extlinux_conf}" "True" "data"; chkerr;
	fi
	# Create a symbolic link of boot dir, so bootloader can find binaries
	# in /boot under boot partition
	ln -s ./ ./boot;
	popd > /dev/null 2>&1;

	echo -e -n "\tSync'ing ${__localsysfile} ... ";
	sync; sync; sleep 5;	# Give FileBrowser time to terminate gracefully.
	echo "done.";

	umount mnt > /dev/null 2>&1;
	losetup -d "${loop_dev}" > /dev/null 2>&1;
	rmdir mnt > /dev/null 2>&1;

	convert_to_sparse_image "${__fillpat}" "${__localsysfile}";
	echo "${__localsysfile} built successfully. ";
}

#
# Building the encrypted root file system image for APP_ENC partition
#
function build_enc_root_fsimg () {
	local __localsysfile="${1}";
	local __fillpat="${2}";
	local __rootfssize="${3}";
	local __rootfs_type="${4}";
	local __rootfs_dir="${5}";
	local __rootfsuuid="${6}";
	local __bootpartuuid="${7}";
	local __ecid="${8}";

	echo "Making ${__localsysfile}... ";

	local CRYPTSETUP_BIN="";
	local GEN_LUKS_PASS_CMD="";
	# Check cryptsetup
	if [ -f "/sbin/cryptsetup" ]; then
		CRYPTSETUP_BIN="/sbin/cryptsetup";
	else
		if [ -z "${CRYPTSETUP_BIN}" ]; then
			echo "ERROR cryptsetup not found! To install - please run: " \
				"\"sudo apt-get install cryptsetup\""
			exit 1
		fi;
	fi;

	# Check ECID
	#if [ "${__ecid}" == "" ]; then
	#	echo "ERROR: build_enc_root_fsimg: ECID is null ."
	#	exit 1
	#fi;

	# Check gen_luks_passphrase.py
	local genpass_dir="${LDK_DIR}/tools/disk_encryption";
	local genpass_opt="";
	GEN_LUKS_PASS_CMD="${genpass_dir}/gen_luks_passphrase.py";
	if [ ! -f "${GEN_LUKS_PASS_CMD}" ]; then
		echo "ERROR ${GEN_LUKS_PASS_CMD} is not found."
		exit 1
	fi;
	if [ "${enc_rfs_keyfile}" != "" ]; then
		genpass_opt+="-k \"${enc_rfs_keyfile}\" ";
	fi;
	#genpass_opt+="-u -e '${__ecid}' "
	#genpass_opt+="-c '${__rootfsuuid}'";
	genpass_opt+="-g -c 'generic-key' "
	GEN_LUKS_PASS_CMD+=" ${genpass_opt}";

	validate_fs_size "${__rootfssize}";
	create_disk_image_with_pattern "${__fillpat}" "${__localsysfile}" "${__rootfssize}";

	loop_dev="$(losetup --show -f "${__localsysfile}")";
	chkerr "mapping ${__localsysfile} to loop device failed.";
	local __l4t_enc_root_dm="l4t_enc_root";
	local __l4t_enc_root_dm_dev="/dev/mapper/${__l4t_enc_root_dm}"
	# Add the LUKS header
	eval ${GEN_LUKS_PASS_CMD} | ${CRYPTSETUP_BIN} \
		--type luks1 \
		-c aes-cbc-essiv:sha256 \
		-s 128 \
		--uuid "${__rootfsuuid}" \
		luksFormat \
		${loop_dev};
	chkerr "Add LUKS header on ${__localsysfile} failed.";

	# Unlock the encrypted root image
	if [ -e "${__l4t_enc_root_dm_dev}" ]; then
		umount "${__l4t_enc_root_dm_dev}"
		${CRYPTSETUP_BIN} luksClose ${__l4t_enc_root_dm}
	fi
	eval ${GEN_LUKS_PASS_CMD} | ${CRYPTSETUP_BIN} \
		luksOpen ${loop_dev} ${__l4t_enc_root_dm};
	chkerr "Unlock ${__localsysfile} failed.";

	mkfs -t ${__rootfs_type} ${__l4t_enc_root_dm_dev} > /dev/null 2>&1;
	chkerr "formating ${__rootfs_type} filesystem on ${__localsysfile} failed.";
	mkdir -p mnt;
	chkerr "make ${__localsysfile} mount point failed.";
	mount ${__l4t_enc_root_dm_dev} mnt;
	chkerr "mount ${__localsysfile} failed.";

	# Processing partition data.
	pushd mnt > /dev/null 2>&1;
	echo -n -e "\tpopulating rootfs from ${__rootfs_dir} ... ";
	(cd ${__rootfs_dir}; tar --exclude=boot -cf - *) | tar xf - ; chkerr;

	# Update root in /etc/fstab
	cp etc/fstab etc/fstab.tmp;
	head -n -1 etc/fstab.tmp > etc/fstab;
	echo "/dev/mapper/crypt_root / ext4 defaults 0 1" >> etc/fstab;
	rm etc/fstab.tmp;

	# Update /etc/fstab if "${__bootpartuuid}" exists
	if [ "${__bootpartuuid}" != "" ]; then
		echo "PARTUUID=${__bootpartuuid} /boot ext4 defaults 0 1" >> etc/fstab;
	fi;

	# Update /etc/fstab and add mount point if ${enc_user_disk_list} is not empty
	for enc_usr_disk in "${enc_user_disk_list[@]}"
	do
		local __dm_name;
		__dm_name="$(echo "${enc_usr_disk}" | awk -F " " '{print $1}')";
		mkdir -p "mnt/${__dm_name}";
		echo "/dev/mapper/${__dm_name} /mnt/${__dm_name} ext4 defaults 0 2" >> etc/fstab;
	done
	popd > /dev/null 2>&1;

	echo -e -n "\tSync'ing ${__localsysfile} ... ";
	sync; sync; sleep 5;	# Give FileBrowser time to terminate gracefully.
	echo "done.";

	umount mnt > /dev/null 2>&1;
	${CRYPTSETUP_BIN} luksClose ${__l4t_enc_root_dm};
	losetup -d "${loop_dev}" > /dev/null 2>&1;
	rmdir mnt > /dev/null 2>&1;

	convert_to_sparse_image "${__fillpat}" "${__localsysfile}";
	echo "${__localsysfile} built successfully. ";
}

#
# Building a common encrypted file system image
#
function build_enc_fsimg () {
	local __localsysfile="${1}";
	local __fillpat="${2}";
	local __fssize="${3}";
	local __fs_type="${4}";
	local __fsuuid="${5}";
	local __ecid="${6}";
	local __src_dir="${7}";

	echo "Making ${__localsysfile}... ";

	local CRYPTSETUP_BIN="";
	local GEN_LUKS_PASS_CMD="";
	# Check cryptsetup
	if [ -f "/sbin/cryptsetup" ]; then
		CRYPTSETUP_BIN="/sbin/cryptsetup";
	else
		if [ -z "${CRYPTSETUP_BIN}" ]; then
			echo "ERROR cryptsetup not found! To install - please run: " \
				"\"sudo apt-get install cryptsetup\"";
			exit 1;
		fi;
	fi;

	# Check ECID
	#if [ "${__ecid}" == "" ]; then
	#	echo "ERROR: build_enc_fsimg: ECID is null .";
	#	exit 1;
	#fi;

	# Check gen_luks_passphrase.py
	local genpass_dir="${LDK_DIR}/tools/disk_encryption";
	local genpass_opt="";
	GEN_LUKS_PASS_CMD="${genpass_dir}/gen_luks_passphrase.py";
	if [ ! -f "${GEN_LUKS_PASS_CMD}" ]; then
		echo "ERROR ${GEN_LUKS_PASS_CMD} is not found.";
		exit 1;
	fi;
	if [ "${enc_rfs_keyfile}" != "" ]; then
		genpass_opt+="-k \"${enc_rfs_keyfile}\" ";
	fi;
	#genpass_opt+="-u -e '${__ecid}' "
	#genpass_opt+="-c '${__rootfsuuid}'";
	genpass_opt+="-g -c 'generic-key' "
	GEN_LUKS_PASS_CMD+=" ${genpass_opt}";

	validate_fs_size "${__fssize}";
	create_disk_image_with_pattern "${__fillpat}" "${__localsysfile}" "${__fssize}";

	loop_dev="$(losetup --show -f "${__localsysfile}")";
	chkerr "mapping ${__localsysfile} to loop device failed.";
	local __l4t_enc_disk_dm="l4t_enc_disk";
	local __l4t_enc_disk_dm_dev="/dev/mapper/${__l4t_enc_disk_dm}"
	# Add the LUKS header.
	eval ${GEN_LUKS_PASS_CMD} | ${CRYPTSETUP_BIN} \
		--type luks1 \
		-c aes-cbc-essiv:sha256 \
		-s 128 \
		--uuid "${__fsuuid}" \
		luksFormat \
		${loop_dev};
	chkerr "Add LUKS header on ${__localsysfile} failed.";

	# Unlock the encrypted filesystem image.
	if [ -e "${__l4t_enc_disk_dm_dev}" ]; then
		umount ${__l4t_enc_disk_dm_dev}
		${CRYPTSETUP_BIN} luksClose ${__l4t_enc_disk_dm}
	fi
	eval ${GEN_LUKS_PASS_CMD} | ${CRYPTSETUP_BIN} \
		luksOpen ${loop_dev} ${__l4t_enc_disk_dm};
	chkerr "Unlock ${__localsysfile} failed.";

	mkfs -t ${__fs_type} ${__l4t_enc_disk_dm_dev} > /dev/null 2>&1;
	chkerr "formating ${__fs_type} filesystem on ${__localsysfile} failed.";
	mkdir -p mnt;
	chkerr "make ${__localsysfile} mount point failed.";
	mount ${__l4t_enc_disk_dm_dev} mnt;
	chkerr "mount ${__localsysfile} failed.";

	# Processing partition data.
	if [ "${__src_dir}" != "" ]; then
		pushd mnt > /dev/null 2>&1;
		echo -n -e "\tpopulating fs from ${__src_dir} ... ";
		(cd ${__src_dir}; tar -cf - *) | tar xf - ; chkerr;
		popd > /dev/null 2>&1;
	fi;

	echo -e -n "\tSync'ing ${__localsysfile} ... ";
	sync; sync; sleep 5;	# Give FileBrowser time to terminate gracefully.
	echo "done.";

	umount mnt > /dev/null 2>&1;
	${CRYPTSETUP_BIN} luksClose ${__l4t_enc_disk_dm};
	losetup -d "${loop_dev}" > /dev/null 2>&1;
	rmdir mnt > /dev/null 2>&1;

	convert_to_sparse_image "${__fillpat}" "${__localsysfile}";
	echo "${__localsysfile} built successfully. ";
}

#
# Create a encrypted user disk image if the attribuate "encrypted" is true.
#
function create_enc_user_disk() {
	local __disk_name="${1}";
	local __cfg_file="${2}";
	local __fillpat="${3}";
	local __fs_type="${4}";
	local __ecid="${5}";
	local __src_dir="${6}"
	local __disk_ext="${7}"
	local __disk_enc_enabled="false";

	get_attr_from_PT_table "${__disk_name}" "encrypted" "${__cfg_file}" __disk_enc_enabled;

	if [ "${__disk_enc_enabled}" == "true" ]; then
		local __disk_size;
		local __img_name;
		local __fs_uuid;

		# Prepare parameters for UDA disk encryption.
		uuid_restore "${__disk_name}${__disk_ext}" __fs_uuid;
		get_value_from_PT_table "${__disk_name}" "size" "${__cfg_file}" __disk_size;
		get_value_from_PT_table "${__disk_name}" "filename" "${__cfg_file}" __img_name;

		# Store disk name and UUID in the list.
		enc_user_disk_list+=("crypt_${__disk_name} ${__fs_uuid}");

		# Build encrypted UDA disk image.
		if [ "${target_partname}" = "" ]; then
			build_enc_fsimg "${__img_name}" "${__fillpat}" "${__disk_size}" \
					"${__fs_type}" "${__fs_uuid}" "${__ecid}" \
					"${__src_dir}";
		fi;
	fi;
}
  1. Used common ECID in flash.sh
...
# ECID=$(./${rcmcmd} ${inst_args} --uid | grep BR_CID | cut -d' ' -f2);
ECID="0x880219116404c0831800000009038240"
...
  1. Updated initrd
#!/bin/bash

# Copyright (c) 2014-2020, 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.
initrd_dir=/mnt/initrd;
dhclient_flag="true";
count=0;

echo "Starting L4T initial RAM disk" > /dev/kmsg;

#Mount procfs, devfs, sysfs and debugfs
mount -t proc proc /proc
if [ $? -ne 0 ]; then
	echo "ERROR: mounting proc fail..." > /dev/kmsg;
	exec /bin/bash;
fi;
mount -t devtmpfs none /dev
if [ $? -ne 0 ]; then
	echo "ERROR: mounting dev fail..." > /dev/kmsg;
	exec /bin/bash;
fi;
mount -t sysfs sysfs /sys
if [ $? -ne 0 ]; then
	echo "ERROR: mounting sys fail..." > /dev/kmsg;
	exec /bin/bash;
fi;
mount -t debugfs none /sys/kernel/debug/
if [ $? -ne 0 ]; then
	echo "ERROR: mounting debugfs fail..." > /dev/kmsg;
	exec /bin/bash;
fi;

# create reboot command based on sysrq-trigger
if [ -e "/proc/sysrq-trigger" ]; then
	echo -e "#!/bin/bash \necho b > /proc/sysrq-trigger;" > /sbin/reboot;
	chmod 755 /sbin/reboot;
fi;

dev_regex='root=\/dev\/[abcdefklmnpsv0-9]*'
uuid_regex='root=PARTUUID=[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}'
rootdev="$(cat /proc/cmdline | grep -oE "\<${dev_regex}|${uuid_regex}\>" | tail -1)"
if [ "${rootdev}" != "" ]; then
	if [[ "${rootdev}" =~ "PARTUUID" ]]; then
		rootdev=$(echo "${rootdev}" | sed -ne "s/root=\(.*\)/\1/p")
	else
		rootdev=$(echo "${rootdev}" | sed -ne "s/root=\/dev\/\(.*\)/\1/p")
	fi
	echo "Root device found: ${rootdev}" > /dev/kmsg;
fi

if [ -e "/etc/crypttab" ]; then
	ext4uuid_regex='root=UUID=[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}';
	encrootcmd="$(cat /proc/cmdline | grep -oE "\<${dev_regex}|${ext4uuid_regex}\>" | tail -1)";
	rootext4uuid="$(echo ${encrootcmd} | awk -F "=" '{print $3}')";

	while read crypttab_line
	do
		enc_dm_name="$(echo "${crypttab_line}" | awk -F " " '{print $1}')";
		crypt_dev="$(echo "${crypttab_line}" | awk -F " " '{print $2}')";
		crypt_disk_uuid="$(echo "${crypt_dev}" | awk -F "=" '{print $2}')";
		enc_dev_match_root=$(echo "${crypt_dev}" | grep -cE "${rootext4uuid}");
		enc_dev=$(blkid | grep -E "${crypt_disk_uuid}" | awk -F ":" '{print $1}');

		# isLuks
		LD_LIBRARY_PATH="/lib/cryptsetup" \
			/lib/cryptsetup/ld-linux-aarch64.so.1 \
			/sbin/cryptsetup isLuks "${enc_dev}";
		if [ $? -ne 0 ]; then
			echo "ERROR: encrypted dev ${enc_dev} is not LUKS device.";
			exec /bin/bash;
		fi;

		# Unlock the encrypted dev
		nvluks-srv-app -g -c 'generic-key' | LD_LIBRARY_PATH="/lib/cryptsetup" \
			/lib/cryptsetup/ld-linux-aarch64.so.1 \
			/sbin/cryptsetup luksOpen "${enc_dev}" "${enc_dm_name}";
		if [ $? -ne 0 ]; then
			echo "ERROR: fail to unlock the encrypted dev ${enc_dev}.";
			exec /bin/bash;
		fi;

		if [ ${enc_dev_match_root} -eq 1 ]; then
			mount "/dev/mapper/${enc_dm_name}" /mnt/;
		else
			mount "/dev/mapper/${enc_dm_name}" "/mnt/mnt/${enc_dm_name}";
		fi;
	done < /etc/crypttab;
elif [[ "${rootdev}" == PARTUUID* ]]; then
	count=0;
	while [ ${count} -lt 50 ]; do
		sleep 0.2;
		count="$(expr ${count} + 1)"

		mount "${rootdev}" /mnt/;
		if [ $? -eq 0 ]; then
			break;
		fi
	done
	mountpoint /mnt/;
	if [ $? -ne 0 ]; then
		echo "ERROR: ${rootdev} mount fail..." > /dev/kmsg;
		exec /bin/bash;
	fi;
elif [[ "${rootdev}" == mmcblk* || "${rootdev}" == nvme* ]]; then
	if [ ! -e "/dev/${rootdev}" ]; then
		count=0;
		while [ ${count} -lt 50 ]
		do
			sleep 0.2;
			count=`expr $count + 1`;
			if [ -e "/dev/${rootdev}" ]; then
				break;
			fi
		done
	fi
	if [ -e "/dev/${rootdev}" ]; then
			echo "Found dev node: /dev/${rootdev}" > /dev/kmsg;
	else
		echo "ERROR: ${rootdev} not found" > /dev/kmsg;
		exec /bin/bash;
	fi
	mount /dev/${rootdev} /mnt/;
	if [ $? -ne 0 ]; then
		echo "ERROR: ${rootdev} mount fail..." > /dev/kmsg;
		exec /bin/bash;
	fi;
elif [[ "${rootdev}" == sd* ]]; then
	if [ ! -e "/dev/${rootdev}" ]; then
		while [ ${count} -lt 50 ]
		do
			sleep 0.2;
			count=`expr $count + 1`;
			if [ -e "/dev/${rootdev}" ]; then
				break;
			fi
		done
	fi
	if [ -e "/dev/${rootdev}" ]; then
			echo "Found dev node: /dev/${rootdev}" > /dev/kmsg;
	else
		echo "ERROR: ${rootdev} not found" > /dev/kmsg;
		exec /bin/bash;
	fi
	mount /dev/${rootdev} /mnt/;
	if [ $? -ne 0 ]; then
		echo "ERROR: ${rootdev} mount fail..." > /dev/kmsg;
		exec /bin/bash;
	fi;
elif [[ "${rootdev}" == "nfs" ]]; then
	eth=`cat /proc/cmdline | sed 's/.* ip=\([a-z0-9.:]*\) .*/\1/' | awk -F ":" '{print $6}'`;
	echo "Ethernet interface: $eth" > /dev/kmsg;
	ipaddr=$(ifconfig "${eth}" | grep -A1 "${eth}" | grep "inet " | sed 's/.*addr:\([0-9\.]*\) .*/\1/;s/.*inet \([0-9\.]*\) .*/\1/');
	if [[ "$ipaddr" =~ [0-9]*.[0-9]*.[0-9]*.[0-9]* ]]; then
		echo "IP Address: $ipaddr" > /dev/kmsg;
		dhclient_flag="false";
	else
		while [ ${count} -lt 50 ]
		do
			sleep 0.2;
			ipaddr=$(ifconfig "${eth}" | grep -A1 "${eth}" | grep "inet " | sed 's/.*addr:\([0-9\.]*\) .*/\1/;s/.*inet \([0-9\.]*\) .*/\1/');
			if [[ "$ipaddr" =~ [0-9]*.[0-9]*.[0-9]*.[0-9]* ]]; then
				echo "IP Address: $ipaddr" > /dev/kmsg;
				dhclient_flag="false";
				break;
			fi
			count=`expr $count + 1`;
		done
	fi
	if [ "$dhclient_flag" == "true" ]; then
		timeout 8s /sbin/dhclient $eth;
		if [ $? -ne 0 ]; then
			echo "ERROR: dhclient fail..." > /dev/kmsg;
			exec /bin/bash;
		fi;
	fi;
	nfsroot_path="`cat /proc/cmdline | sed -e 's/.*nfsroot=\([^ ,]*\)[ ,].*/\1 /'`";
	nfsroot_opts="`cat /proc/cmdline | sed -ne 's/.*nfsroot=\([^ ,]*\),\([^ ]*\).*/\2 /p'`";
	if [[ "${nfsroot_opts}" == "" ]]; then
		nfsroot_opts="nolock"
	fi
	mount -t nfs -o ${nfsroot_opts} ${nfsroot_path} /mnt/ &>/dev/kmsg;
	if [ $? -ne 0 ]; then
		echo "ERROR: NFS mount fail..." > /dev/kmsg;
		exec /bin/bash;
	fi;
else
	echo "No root-device: Mount failed" > /dev/kmsg;
	exec /bin/bash;
fi

# Disable luks-srv TA
nvluks-srv-app -n > /dev/null 2>&1;

echo "Rootfs mounted over ${rootdev}" > /dev/kmsg;
mount -o bind /proc /mnt/proc;
mount -o bind /sys /mnt/sys;
mount -o bind /dev/ /mnt/dev;
cd /mnt;
cp /etc/resolv.conf etc/resolv.conf

echo "Switching from initrd to actual rootfs" > /dev/kmsg;
mount --move . /
exec chroot . /sbin/init 2;
  1. Run qspi flashing without any error
sudo ROOTFS_ENC=1 BOARDID=3668 BOARDSKU=0001 FAB=300 BOARDREV=B.0 ./tools/kernel_flash/l4t_initrd_flash.sh --no-flash jetson-xavier-nx-devkit-qspi internal
  1. Finally run external flashing script
sudo ROOTFS_ENC=1 BOARDID=3668 BOARDSKU=0001 FAB=300 BOARDREV=B.0 ./tools/kernel_flash/l4t_initrd_flash.sh --no-flash --external-device nvme0n1p1 -S 200GiB -c ./tools/kernel_flash/flash_l4t_nvme_rootfs_enc.xml --external-only --massflash 5 --append jetson-xavier-nx-devkit-emmc external

hello AkterHossain,

according to failure here, could you please check image file, system_root_encrypted.img has created correctly?

[   7.6652 ] File system_root_encrypted.img open failed
[   7.8128 ] 
Error: Return value 19

Hi @JerryChang,
I think no. These system files are generated so far:
image

Hello @JerryChang

Any update on this?

My colleague @AkterHossain and I tried all the proposed solutions with no success

This is a very important step in our roadmap,

The requirement:
we need to use the mass flashing functionality with enabling the disk encryption on the emmc and the nvme

System Setup:
Host Machine: Ubuntu 18.04.6 LTS
Device: Jetson Xavier NX emmc
External Storage: WD Blue SN550 NVMe 250 GB

Could you please let us know if this requirement is achievable in L4t 32.7.1 if so please share with us the tested steps to achieve mass flashing with disc encryption in the emmc and the nvme

Thanks,

hello HusamAlqaza, AkterHossain,

it’s currently not support to use generic passphrase, please have unique ECID to enable disk encryption.

Hi @JerryChang,
It is not mandatory to have generic passphrase in our requirements. We are keenly seeking a solution or workflow to achieve massflash with enabling disk encryption regardless of unique or generic passphrase.

Since multiple members from our team tried your documented approach and got the same Error: ECID is null, then we tried generic passphrase as a workaround.

Do you understand our requirements? Could you please reach your feature team and let us know if is it possible to do massflash with disk encryption in 4.6.1/32.7.1?

as you can see from the developer guide,

The Jetson Linux reference implementation only generates per-device encrypted disk images.

Thank you @JerryChang for your clearance.

Now we know it is NOT possible to achieve massflash with enabling disk encryption since disk encryption is only possible for per-device flashing.