Flashing Custom U-boot onto TX1

I know there are lot of resources out there for this problem however, the documentation seems convoluted, very hard to follow in my opinion.

I am in need of a custom u-boot since I need to driver (RTL8152) support during U-boot for PXE booting. I found the driver and from the u-boot sources I successfully ran the ‘make’ command.
Basically I finished the first step of the building from u-boot source tutorial.

Now I just need to flash this custom U-boot into my Jetson TX1. My custom u-boot source files are currently on the TX1.

I would like anyone to just give me a very simple run down on how to flash my TX1, I have a HOST pc as well, in case I need it.

Also on a side note, I tried using sudo ./flash.sh -k EBT p2371-2180 mmcblk0p1 and it came up with errors as shown below.

./flash.sh: line 546: /Linux_for_Tegra/kernel/dtc: cannot execute binary file: Exec format error
sed: can’t read temp.dts: No such file or directory
sed: can’t read temp.dts: No such file or directory
./flash.sh: line 549: /Linux_for_Tegra/kernel/dtc: cannot execute binary file: Exec format error
rm: cannot remove ‘temp.dts’: No such file or directory
Existing tbcfile(/Linux_for_Tegra/bootloader/nvtboot_cpu.bin) reused.
copying cfgfile(/Linux_for_Tegra/bootloader/t210ref/cfg/gnu_linux_tegraboot_emmc_full.xml) to flash.xml… done.
creating gpt(ppt.img)…
./flash.sh: line 1207: ./mkgpt: cannot execute binary file: Exec format error
creating gpt(ppt.img) failed.

I tried on both the TX1 and later on a host connecting to TX1 using minicom and errors were the same.

Just reading through the instructions. http://developer.download.nvidia.com/embedded/L4T/r24_Release_v2.0/BSP/l4t_quick_start_guide.txt?autho=1479779669_239403cbbd31eb355a3636be366c3a1b&file=l4t_quick_start_guide.txt
How do I connect my host and TX1, do I use the j21 serial pins (e.g. minicom).
How do I run the scripts such as ./flash.sh? If I was using the terminal from minicom then what is the point of connecting it to a host since Im pretty much running the script on the Jetson TX1.

You connect your host PC and the TX1 via a micro usb cable. And afterwards in order to flash the TX1 you’ll need to put it into recovery mode by holding the recovery button the on board and pressing the reset button. Using lsusb on your host, if you see a device listed as Nvidia that will be the TX1. You can run the flash.sh script from your host machine after that and it should flash the device.

If you choose to use a serial console instructions on J21 are here:

Minicom works for serial console, I like gtkTerm. Serial console is not used for flash, only for debugging and general easy text console access on a running Jetson. Serial console even allows command line access of u-boot to do things like select alternate boot entries.

@Joulecpa mentioned recovery mode. The gist of getting ready for flash.sh is that the driver package comes with an empty rootfs subdirectory (on host, not Jetson), and you populate that directory prior to running flash. You’d unpack the sample rootfs there using sudo, then run the apply_binaries.sh (also with sudo) to complete the rootfs directory. Then, if in recovery mode, you can do something like this:

sudo ./flash.sh -S 14580MiB jetson-tx1 mmcblk0p1

Okay I think I understand the flashing bit but just before flash, the building u-boot part.
Do you need to connect the host pc and carrier when running ./apply_binaries and “make” command in the u-boot source file?
It says connect the Host to the TX1 with a usb cable but when I do that I don’t see a terminal pop up so I can’t install any package or run any script whilst on the host pc.
Again when I run ./apply_binaries it comes with with something about not being able to read the dtc exec file. I read some previous posts and they say its something to do with not running the script on a host pc (e.g. x86 arch) since the files are for x86 arch. Which linuxdev you mentioned previously.
So again how am I supposed to run the ./apply_binaries script on the host pc?
Or does it mean that I download the Linux_For_Tegra package onto a host pc and set it all up on the host pc then I flash it onto the TX1 after making all the configurations to the u-boot source etc.
If so, that would make much more sense…

Because what I have been doing the whole time is downloading the Linux_For_Tegra R24 package from the official site to the Jetson TX1 and running all the scripts on the TX1.
But if the above is true then would I run the sudo ./flash.sh -S 14580MiB jetson-tx1 mmcblk0p1 command on the host pc? If I do that does it know it needs to flash the TX1 and not the Host pc?
Sorry if these questions are really dumb but I’m just really used to using Jetpack… I’m a windows person.

U-boot is pre-built and available in binary format in the bootloader subdirectory of the driver package (this is the one which provides the Linux_for_Tegra subdirectory). The only operation which flash.sh would do is to first pad the end of the binary with NULL bytes to fit a specific size. flash.sh takes care of this for you.

The only time you need to build u-boot is if you are modifying the existing source, e.g., adding a new driver or some configuration change. Anyone doing so is probably already adept at bare metal programming…else there is a steep learning curve.

Plugging in a USB “device”, such as a camera or mass storage external hard drive only produces a pop-up if the device is some standard class with functions generic drivers service. The Jetson is purely a custom driver…no driver will pop up to ask what you want to do since the installer is the only driver which understands a Jetson. Flash software (the driver package) looks to see if the Jetson is connected at the time it runs. Either flash will proceed (flash software found the Jetson in recovery mode), or flash will fail (either the Jetson wasn’t connected with the micro-B USB cable, or the Jetson was not in recovery mode). You can use lsusb to see if USB knows the Jetson is connected; for a JTX1 this will produce output when recovery mode is valid, else it will be blank: “lsusb -d 0955:7721”.

When you unpack the driver package it has subdirectory “Linux_for_Tegra/”. If you go there the file “apply_binaries.sh” exists. To run this against the default “Linux_for_Tegra/rootfs/” subdirectory this works:

sudo ./apply_binaries.sh

Note that the driver package and apply_binaries.sh are intended to be installed on a desktop host, not on a Jetson. When apply_binaries.sh is run, it applies nVidia-specific hardware access files into the rootfs folder of the desktop PC host. The act of running flash.sh creates a file from the rootfs and some boot files which is then transferred to the Jetson over the micro-B USB cable when in recovery mode. So both flash.sh and apply_binaries.sh install/run on the host, not on the Jetson…the effect on a Jetson is indirect, but it does eventually propagate to the Jetson once everything is prepared on the host (which can be slow). As mentioned before, bootloader is taken care of by flash.sh, you don’t need to do anything for normal flash.

In cases where you were doing bootloader programming (and very few people will do this) the configuration and building would indeed be on the host, not on the Jetson. You’d be using a bare metal cross compiler and more or less need to be an expert on the topic to add a driver from scratch.

FYI, flash.sh never modifies your host. It does take up some hard disk space (actually, a lot of hard disk space since each image it processes is about 15GB). There is a front end package called JetPack, which an Ubuntu PC desktop can run. This only runs flash.sh and does not have its own flash app. What JetPack does differently is that it also offers to set up some user applications on both the Jetson and the host. In the case of the Jetson it does this after a flash over ethernet. JetPack is quite capable of helping to select and install some user space applications without actually flashing. This is true for applications which can be installed to aid development on both Jetson and host. To use this you must use Ubuntu 14.04. If you just flash with flash.sh, then any standard x86_64 Linux PC can do this…I use Fedora, so I use flash.sh, but cannot use JetPack.

Okay I think I finally understand how to do all this, very good explanation.
Just one thing though, let’s say all I want to do is just enable a driver for U-boot.
To do so I would take the following steps:
make menuconfig => enable driver through interface.
run make

Once I do these two steps how do I tie the rest in together. As you said sudo ./flash.sh script will be looking at the rootfs folder, how do I apply the u-boot source changes that are made above to the rootfs so that my custom U-boot gets flashed not the default.

After running the “make” command in the u-boot source files the following files are made.

MKIMAGE u-boot.img
CAT u-boot-dtb.bin
MKIMAGE u-boot-dtb.img
Is it possible to copy this image onto the jetson tx1 and flash it using ./flash.sh?

There are configuration files used for determining many defaults (such as bootloader binary)…see the “.conf” files in the root of the driver package (the Linux_for_Tegra directory). Depending on arguments you could follow the bash script flash.sh to see what is used.

Probably better for your case, open up flash.sh (e.g., run “less flash.sh” to view the file read-only). Notice that after the first block of comments (the license) are a number of comments on how to use the flash.sh script, along with examples. Specifically, look for “Optional Environment Variables” (if using “less” to view you can type “/Optional Environment Variables” to search). One of those is “BOOTLOADER”. If you have correctly named the path to your bootloader binary by setting this environment variable it should use this instead of defaults.

I have not had to use custom bootloaders, but there are some details which might need to be experimented with. First, when flash.sh runs, it pads bootloader binaries by adding NULL bytes to the end of the file if the file does not match some criteria. I have not dissected how this is used in the script, so it is possible you may need to set up one of the other variables for bootloader size…and perhaps the script will take care of NULL byte padding, or perhaps when naming a custom bootloader you need to do this manually…I don’t know. Try it, watch the flash messages, and experiment.

Note that it is possible to flash some partitions individually, but if your u-boot uses a partition size different than the original partition size for the boot loader, then you have to flash everything which occurs after that partition anyway. Changing any partition size other than the last partition (I think that’s rootfs, at least for all cases I know about) implies moving other partitions around to avoid truncating one of them. If you want to flash a bootloader I’d recommend just flashing everything. You can always clone the rootfs if you need to and have this as a copy…the “-r” reuse option to flash.sh lets you avoid generating system.img and just use the one currently there (and the one there can either be from a previous flash or from a reference clone).

The JTK1 is slightly different in cloning, but the information is still valid. See this:

Commands specific to the JTX1 are here…note that flash.sh takes care of a lot of size details, using this is often preferable than directly running a subset of the flash.sh components:

I didn’t know size was such an issue, I’ll keep experimenting and report back after.

Okay so I did what you told me to do and looked through the file flash.sh.
I’m guessing that this part of the script sets the path for “where to look”.

LDK_DIR=$(cd dirname $0 && pwd)
LDK_DIR=readlink -f "${LDK_DIR}"
BL_DIR="{LDK_DIR}/bootloader"; TARGET_DIR="{BL_DIR}/{target_board}" mkfilepath bootloader "{BOOTLOADER}" “${TARGET_DIR}/fastboot.bin”;

TARGET_DIR would be something like bootloader/p2371-2180.
If changed TARGET_DIR to the path that leads to my bootloader binary there should be no problems?
If so, how specific do I need to make it, the bootloader binary are located in /Linux_For_Tegra/bootloader/t210ref/p2371-2180.
Also why does it say fastboot.bin? Should it not lead to boot.bin, boot-dtb.bin and boot.dtb?

While flashing the new u-boot onto the TX1 (e.g running sudo ./flash.sh EBT p2371-2180 mmcblk0p1 command)
I got the following message.
Writing partition
[ 1.4549 ] tegradevflash --write EBT /home/ubuntu/Linux_for_Tegra/bootloader/signed/u-boot-dtb.bin.encrypt
[ 1.4555 ] Cboot version 00.01.0000
[ 2.1883 ] Writing partition EBT with /home/ubuntu/Linux_for_Tegra/bootloader/signed/u-boot-dtb.bin.encrypt

I’m wondering why does it go into /bootloader/signed/ instead of /bootloader/t210ref/p2371-2180.
Now I’m getting the suspicion that the flash script is actually not using the bootloader binary that are made.

I’m not where I can look right now, but did you look at variable “BOOTLOADER”? Many variables are concatenated, sometimes you don’t want to change an entire path (as mentioned I am not where I can look right now, but if you change a whole path you may be changing more than you bargained for).

Just FYI, a Jetson in recovery mode is a device instead of a host. Your host runs a driver while flashing a recovery mode Jetson…this is through the driver package (a custom driver). Part of what that driver does is load software onto the Jetson which makes it capable of responding to flash commands. Even though the Jetson is now a device, it is still a computer of sorts…it still needs to boot, but it needs to boot to recovery mode operation. fastboot.bin is used to reach recovery mode, but is not installed permanently…this version of fastboot.bin goes away as soon as a flash operation is completed. There is a different stage which loads u-boot to eMMC, fastboot makes this possible. You don’t want to alter the script environment so far as fastboot.bin goes.

After further testing I have found out that there was nothing wrong with the flash script, and that the TX1 was being flashing with my custom boot loader. However, the only reason why I was still getting the “Ethernet not found error” was due to the fact that the USB ethernet is being initialized whereas the PCI port is.
So I might have to just use a PCI ethernet adapter…

Thanks for the help anyway.
Do correct me if I am wrong with my deduction above.