When executing the flash.sh
script (doesn’t matter if from the terminal or via the sdk-manager) a recovery image for OTA (over the air) updates is created. This is done by this script:
${L4T}/tools/ota_tools/version_upgrade/ota_make_recovery_img_dtb.sh
The recovery image needs some but not all binaries from ${L4T}/rootfs
, the exact filelist can be found inside of recovery_copy_binlist.txt
One of those files is /usr/bin/w
, used to displays information about the users currently on the machine, and their processes. But if we take a closer look…
$ ls -lah ${L4T}/rootfs/usr/bin/w
lrwxrwxrwx 1 root root 19 Apr 26 2018 w -> /etc/alternatives/w
/usr/bin/w
isn’t the actual executable but a symbolic link. In fact /etc/alternatives/w
is another symlink:
$ ls -lah ${L4T}/rootfs/etc/alternatives/w
lrwxrwxrwx 1 root root 17 Apr 26 2018 w -> /usr/bin/w.procps
So ${L4T}/rootfs/usr/bin/w.procps
is the actual executable that should be copied!
Now, how does ota_make_recovery_img_dtb.sh
handle this? Starting from line 65:
# Copy all the binary
while read -r path
do
_src="$(echo "${path}" | cut -d ':' -f 2)"
_dst="$(echo "${path}" | cut -d ':' -f 3)"
cp -f "${_src}" "${_initrd_dir}/${_dst}"
check_error "cp -fv ${_src} ${_initrd_dir}/${_dst}"
done
Big oof. The link gets de-referenced and so the script copies /etc/alternatives/w
from our host system (the ubuntu machine running the flash) instead of ${L4T}/rootfs/usr/bin/w
from the rootfs system
Frankly, this let’s me question the quality of the rest of the code. To circumvent this issue I’ve added a bit of shell-fu on my end:
# Copy all the binary
while read -r path
do
_src="$(echo "${path}" | cut -d ':' -f 2)"
_dst="$(echo "${path}" | cut -d ':' -f 3)"
# If _src is absolute link follow until you find the actual file
while [ -L ${_src} ] & [[ $(readlink ${_src}) = /* ]]; do
_src="${_rootfs_dir}$(readlink ${_src})"
done
cp -f "${_src}" "${_initrd_dir}/${_dst}"
check_error "cp -fv ${_src} ${_initrd_dir}/${_dst}"
done
-L
checks if the source file is a symbolic link, than the destination is read via readlink
. Note, that when the symlink is relative nothing has to be done, so we check if it’s absolute (= if the destination starts with /
). Than take the destination and append it to the rootfs-string
If the destination is in turn another symlink this has to be repeated (while-loop).
Fun-fact: This bug is the only thing preventing someone to execute flash.sh
from other distributions than Ubuntu (as other distros don’t use /etc/alternatives
so the script fails, complaining it can’t find w
).
After adding my fix I was able to successfully flash a Jetson NX from Arch Linux :)