U-Boot Software Update in the Field

Hi,

I am putting together an embedded system based on a Jetson TX1, using L4T 28.2, and I have been working on remote software update features recently. The boot flow of the system is fairly standard I believe, in that I see it go through TegraBoot, cboot, U-Boot, then Linux and finally my application. I have the kernel update and application update working fine so far and I would like to add the ability to update U-Boot as well.

If I take the standard boot.img that is present after I flash the software over USB and place it in mmcblk0p13, everything boots ok. However, if I make some changes to U-Boot, rebuild it, and re-generate the boot.img file with the following command, I notice it is missing a signature of some sort, causing cboot to not load it and the unit to then go into fastboot mode.

# cd $L4T/bootloader
./mkbootimg --kernel ./t210ref/p2371-2180/u-boot.bin --ramdisk initrd --board mmcblk0p1 --output boot.img --cmdline "root=/dev/mmcblk0p1 rw rootwait OS=l4t fbcon=map:0 net.ifnames=0"

Here is the cboot output when I install the binary generated via the above command:

[0003.129] Gpio keyboard init success
[0003.133] bct_init bctinit
[0003.135] bct_init bctinit
[0003.140] bct_init bctinit
[0003.143] bct_init bctinit
[0003.346] decompressor handler not found
[0003.349] load_bmp_blob: panelresolution=1080 type=3
[0003.354] bl_battery_charging: connected to external power supply
[0003.366] fastboot: usb cable is not connected
[0003.370] bct_init bctinit
[0003.373] device_query_partition_size: failed to open partition sdmmc3_user:MSC !
[0003.380] MSC Partition not found
[0003.384] bct_init bctinit
[0003.386] bct_init bctinit
[0003.390] blob_init: USP partition does not have valid Blob
[0003.395] kfs_getpartname: name = LNX
[0003.399] Loading kernel from LNX
[0003.425] Verifying boot image in OdmNonSecureSBK mode
[0003.448] Failed to validate boot-image
[0003.451] Failed while loading kernel and ramdisk images
[0003.457] Failed to boot Android
[0003.460] starting fastboot mode
[0003.466] fastboot cmd_init done.
[0003.469] platform does not support off-mode-charge
[0003.474] usbdcd_init Initialize USBF driver
[0003.478]  usbdcd_phy_open oscfreq = 5
[0003.487] usbdcd_start Start the initialized controller
[0003.495] -- suspend --

I noticed that the signature seems to be applied only during actual flashing and I haven’t yet been able to figure out which tool I can use to generate the signature on the boot.img file without flashing. I’m not trying to use any secure boot mechanism if that makes a difference.

I would like to be able to generate a fully valid boot.img file containing U-Boot, which I could then remotely install to the device, without having to actually flash a device with it first. Please let me know if that is possible, and if so, which set of commands I could use to achieve that.

Thank you,

Chris Richardson

Do you make any change to u-boot?

Hi WayneWWW,

Thank you for the response. Yes we do have local product-specific changes to U-Boot. However, even with these changes I am able to use the boot.img that is generated once USB flashing is complete, to update one of our boards remotely. However, I can’t build the boot.img file completely without actually flashing a unit here, and I would like to avoid that.

Thank you,

Chris Richardson

So I should be able to reproduce the issue if I directly build u-boot w/o any patch, right?

Could you share your steps to remotely update u-boot?

Hi WayneWWW,

Thanks for the response. I think you should be able to reproduce it yes. While testing the commands below, I noticed that the boot.img placed on the device actually differs from the final boot.img on the host PC after flashing. There are 16 bytes of data different between the two, at address 0x6b8, and for the working case I tested the other day I actually copied the 16 bytes of differing data off the device and inserted it into the boot.img file on my PC, which is how I ended up getting it to work. Here is the difference between the source boot.img and the data written to the eMMC:

Good:

000005a0  00 00 00 00 4c 4e 58 00  00 88 67 00 00 00 00 00  |....LNX...g.....|
000005b0  b1 ba ef be ad de ed fe  aa aa aa aa aa aa aa aa  |................|
000005c0  aa aa aa aa aa aa aa aa  aa aa aa aa aa aa aa aa  |................|
*
000006b0  aa aa aa aa aa aa aa aa  a4 25 26 0b 29 e4 01 cd  |.........%&.)...|
000006c0  20 cc e5 91 8e 01 49 68  ee ee ee ee ee ee ee ee  | .....Ih........|
000006d0  ee ee ee ee ee ee ee ee  ee ee ee ee ee ee ee ee  |................|
*
000007c0  ee ee ee ee ee ee ee ee  00 00 00 00 00 00 00 00  |................|

Bad:

000005a0  00 00 00 00 4c 4e 58 00  00 88 67 00 00 00 00 00  |....LNX...g.....|
000005b0  b1 ba ef be ad de ed fe  aa aa aa aa aa aa aa aa  |................|
000005c0  aa aa aa aa aa aa aa aa  aa aa aa aa aa aa aa aa  |................|
*
000006b0  aa aa aa aa aa aa aa aa  ee ee ee ee ee ee ee ee  |................|
000006c0  ee ee ee ee ee ee ee ee  ee ee ee ee ee ee ee ee  |................|
*
000007c0  ee ee ee ee ee ee ee ee  00 00 00 00 00 00 00 00  |................|
000007d0  cc cc cc cc cc cc cc cc  cc cc cc cc cc cc cc cc  |................|

For our normal software build/install, I have a bunch of scripts and software I am using for this, but here are some steps you could take to do something similar. For this test, it is easiest for me to have the root fs mounted over NFS. I don’t show some of the commands, such as flashing the board or copying the boot.img file over to the NFS root fs, since it will depend on the paths you have set up for everything and I’m sure you have your own scripts for all of that.

Non-working example:

Host PC:

## First build U-Boot, making sure the output goes to L4T/bootloader/t210ref/p2171-2180/, command not shown here
# Now generate boot.img which does not work.
./mkbootimg --kernel ./t210ref/p2371-2180/u-boot.bin --ramdisk initrd --board mmcblk0p1 --output boot.img --cmdline "root=/dev/mmcblk0p1 rw rootwait OS=l4t fbcon=map:0 net.ifnames=0"
## Copy boot.img over to NFS root fs, command not shown here.

Device:

# Copy boot.img over to our U-Boot partition.  Please make sure your U-Boot is at mmcblk0p13, which I believe is the default.
dd if=boot.img of=/dev/mmcblk0p13
# Reboot; you may need sudo of course depending on your root fs.
shutdown -r now
# Now cboot will not boot into U-Boot due to the signature failing.

Working example:

Host PC:

## First build U-Boot, making sure the output goes to L4T/bootloader/t210ref/p2171-2180/, not shown here
# Now generate boot.img which does work, by flashing the unit with the normal NVIDIA flash script.  Command not shown here.
## Copy 16 bytes at offset 0x6b8 from good U-Boot on device over to boot.img on Host PC.  Command not shown here.
## Copy boot.img over to NFS root fs, command not shown here.

Device:

## To see the 16 bytes we need to replace in boot.img above we can dump the U-Boot on the device.
## Read existing U-Boot partition from device.  My boot.img is 532480 bytes; you may have to adjust the size here.
#dd if=/dev/mmcblk0p13 of=boot_good.img bs=1024 count=520
#dd if=boot_good.img of=/dev/mmcblk0p13

# Or we can use the boot.img we spliced the 16 bytes into ourselves.
dd if=boot.img of=/dev/mmcblk0p13

# Reboot; you may need sudo of course depending on your root fs.
shutdown -r now
# Now cboot will boot into U-Boot successfully either way you did it above.

Thank you,

Chris Richardson

Hi WayneWWW,

I should have also posted that there is a bunch of extra data that gets inserted into boot.img as part of flashing, such as the LNX tag and the big block of AA AA AA AA … and EE EE EE EE … I couldn’t find a way to generate this data without flashing the unit, and even then, I can’t find a way to generate that 16 bytes of data that is inserted in between the AA/EE blocks. I’m hoping you can help with that part, and my apologies if my repro method is a bit difficult. It’s hard to figure out another decent repro without using all the software and scripts I have.

Thanks,

Chris Richardson

Thanks for sharing.

Just one more question here. So the working case and the not working one is actually the same uboot.bin but different boot.img, right?

hello cjwti,

please note that there are several partitions being signed due to bootloader update.
Hence you should add one more step to sign your boot.img before overwrite that partition.

please also refer to below steps, you should be able to update u-boot remotely.
thanks

  1. customize your u-boot.bin
  2. replace it with $OUT/bootloader/t210ref/p2371-2180/u-boot.bin
  3. running mkbootimg binary as below
sudo ./mkbootimg --kernel t210ref/p2371-2180/u-boot.bin --ramdisk initrd --board mmcblk0p1 --output boot.img
  1. perform tegraflash.py python scripts to sign all necessary binaries.
sudo ./tegraflash.py --cfg flash.xml --chip 0x21 --skipuid  --bl cboot.bin --bct  P2180_A00_LP4_DSC_204Mhz.cfg --odmdata 0x84000 --bldtb tegra210-jetson-tx1-p2597-2180-a01-devkit.dtb --applet nvtboot_recovery.bin --boardconfig board_config_p2597-devkit.xml --cmd "sign"
  1. copy boot.img.encrypt to the target device
  2. using dd commands to update your LNX partition.
sudo dd if=/boot.img.encrypt of=/dev/mmcblk0p13
  1. warm-reboot the device then it should takes effect
sudo reboot

Hi WayneWWW and JerryChang,

Thank you both very much for the help. WayneWWW, to confirm, yes the same u-boot.bin was being used in both cases.

JerryChang, thank you for the tegraflash.py command arguments, that is exactly what I needed, and everything now works as expected. For some odd reason, none of the binaries in the ./signed folder were ever being updated by my usual flash.sh invocations, and so I thought those binaries were irrelevant for my use case. Once I ran that command, it updated most of the binaries in ./signed to today’s date, so at least that is a partially solved mystery for me as well.

Thank you again!

Chris Richardson