In-system update of propretiary NVidia bootloaders

Hello,

we are working with a modified partition layout within 28.1.0 for TX2, for which i wrote an in-system updater, which by now is capable to update u-boot/kernel/dtb/rootfs. I implemented this by looking at what the flash.sh script does and use the provided tools to create the according images, which can be programmed in-system using raw writes / dd.
The missing parts are the closed source NVidia bootloaders MB1/MB2/CBoot in /dev/mmcblk0boot0, which are needed because of the Pinmux .cfg files linked to MB1. I don’t see how, with 28.1.0, MB1 could be updated in-system, as it seems to me that only an USB update via the flash.sh script is supported (where the MB1 image is prepared, USB downloaded and encrypted + programmed on the target).

Q1: Is it possible to realize an in-system update of the MB1/MB2/CBoot bootloaders within 28.1.0, considering a custom partition layout (only on the sdmmc_user device partition), and could you provide a detailed how-to including the necessary tools?

Q2: I thought that the .cfg Pin I/O settings are only relevant for the MB1/MB2/CBoot stages and afterwards the settings would anyway be overloaded by the u-boot/kernel .dtb. So i checked if the .cfg update is mandatory at all by disabling a GPIO only in the .cfg, but leaving it enabled in the kernel .dtb, and the result was that the function behind the GPIO wasn’t working anymore, which strongly points to that it is mandatory and my understanding was wrong. Can you explain to me why, is it because of pad voltages and why aren’t those reflected by the .dtb, from which the .cfg’s were generated? If the kernel .dtb settings would actually come through, the importance of the .cfg update could be reduced to something nice to have.

Btw, i found that meanwhile 28.2.1 has added new tools (nv_update_engine) for in-system updates of the bootloaders, and it was adjusted the full proper way using redundant partitions, which is nice to play safe, but hard to integrate it to our custom setup (modifications in sdmmc_boot and sdmmc_user + a new Linux_for_Tegra environment). I already started experimenting with it, and by now it is only working with the unmodified 28.2.1 Linux_for_Tegra cfg/u-boot/kernel/sample-rootfs, as soon as i exchange one part of it with our devel version, like u-boot, its failing (e. g. when trying to update MB2). I’m now starting to reverse engineer how i can get it to work, but i feel that it will be very time consuming and i would be happier with a positive answer for Q1.

Regards,
Goran

Hi Goran,

Sorry that we cannot give positive answer to Q1.

Could you elaborate more about Q2? What is your usecase? Why do you need to update those on device?

hello DblG,

I haven’t tried to have in-system update of the MB1/MB2/CBoot bootloaders for l4t-r28.1.
HOWEVER, there’s encrypt process in the bootloader stage.
you might check flashing logs and found these binaries has been encrypted and flashed.
for example,

[  11.6611 ] Append 256 to mb1_prod.bin.encrypt
[  11.6615 ] Writing partition mb1 with mb1_prod.bin.encrypt
[  11.6618 ] [................................................] 100%
[  11.6978 ] Append 480 to nvtboot_sigheader.bin.encrypt
[  11.7079 ] Writing partition mb2 with nvtboot_sigheader.bin.encrypt
[  11.7084 ] [................................................] 100%
...
[ 174.4123 ] Append 80 to cboot_sigheader.bin.encrypt
[ 174.4308 ] Writing partition cpu-bootloader with cboot_sigheader.bin.encrypt

since it’s not a simple process by updating the partition, may I know what’s your use-case.
thanks

Hey guys,

thanks for your replies.

To answer the question you both had, the use case is to write an in-system updater for our own firmware using a custom partition layout, i. e. firmware images need to be downloaded to the target and updated in-target. If in the future we need to change something about the I/O Pinmux, even if the probability for that is low, that should also be updated and become effective.

Q2 was about my own understanding why the kernel .dtb does not overload .cfg settings being applied during the early boot stages, as a GPIO disabled by .cfg used during run-time does not work anymore even if it is enabled by kernel .dtb.

By now i couldn’t find out how to create encrypted images with 28.1.0. I see that with 28.2.1 there is a bootloader/signed folder where the encrypted update files are generated and remain, but with 28.1.0 it looks like e. g. mb1_prod.bin gets USB downloaded to the target and encrypted there.

Anyway, meanwhile i found a way to update .cfg modifications. The partition to be updated is MB1_BCT. Checking my test case with the disabled GPIO, i could in-target read out an MB1_BCT image with enabled GPIO from its offset within sdmmc_boot, and write it back to a firmware state where the GPIO was disabled, with the result that the GPIO is working again. So i have a basic solution for my problem already, but still need to find out if there is a better way to generate the MB1_BCT image for our updater. Some hints regarding commands to generate the MB1_BCT image with the tools provided by Linux_for_Tegra would be very welcome.

Just if you’re interested, the reason that 28.2.1 nv_update_engine was not working with our rootfs is that it relies on udisks/udev to access partitions, which we are not using by now. But as it currently looks like, we anyway won’t need to use nv_update_engine.

Regards,
Goran

Hi,

just a short update and a question:

I found that i could generate the MB1_BCT image with the following command:

tegrabct_v2 --chip 0x18 --mb1bct mb1_cold_boot_bct.cfg --sdram P3310_A00_8GB_Samsung_8GB_lpddr4_204Mhz_A02_l4t.cfg --misc tegra186-mb1-bct-misc-si-l4t.cfg --scr mobile_scr.cfg --pinmux tegra186-mb1-bct-pinmux-quill-p3310-1000-c03.cfg.cpusid_off --pmc tegra186-mb1-bct-pad-quill-p3310-1000-c03.cfg.cpusid_off --pmic tegra186-mb1-bct-pmic-quill-p3310-1000-c03.cfg.devel --brcommand tegra186-mb1-bct-bootrom-quill-p3310-1000-c03.cfg --prod tegra186-mb1-bct-prod-quill-p3310-1000-c03.cfg

This gives me the mb1_cold_boot_bct_MB1.bct image file, which is nearly what i need. The problem is that this file can’t be written to the beginning of the MB1_BCT partition, it has to be written to the partition offset + 400. But when doing this, it bricks the TX2, as within the first 400 bytes, there seems to be some kind of 16 byte checksum starting from byte 8 changing with the data payload. For example, when changing the GPIO, the first 400 bytes of the partition look like this when comparing:

0000 0000: 47 53 48 56 00 00 00 00 AB 6E 34 8A 20 D1 14 FC GSHV… ½n4è Ð.³
0000 0010: F3 DA 0F 40 61 15 8A 59 00 00 00 00 00 00 00 00 ¾┌.@a.èY …

0000 0000: 47 53 48 56 00 00 00 00 04 98 F7 D2 1C 48 05 BE GSHV… .ÿ¸Ê.H.¥
0000 0010: 52 11 2F F2 86 58 BB 26 00 00 00 00 00 00 00 00 R./‗åX╗& …

Can you tell me how to generate a complete partition image or how to generate that 16-byte checksum?

Addendum: I see that the .encrypt version of mb1_cold_boot_bct_MB1.bct would be needed, now i just need to find out how to generate it.

Addendum2: I discovered the following forum thread, which is also about how to create signed/encrypted images (with 28.2):

https://devtalk.nvidia.com/default/topic/1035622/jetson-tx2/in-system-update-of-dtb-in-r28-2/post/5262418/

There you suggest to run tegraflash.py (meaning the whole USB flash process). With 28.1.0 it does not leave the .encrypt files behind, and it is also not a solution for me, as i need to create the image within our own updater build environment, therefore i need to extract the necessary tools from the Linux_for_Tegra environment. Looking up the commands the python script calls also didn’t help, as i only came as far as to create the unencrypted image and i could add the header. But the commands for signing/encrypting were not working, as needed input files were missing:

tegrabct_v2 to generate the image … working
tegrahost_v2 --align mb1_cold_boot_bct_MB1.bct … working
tegrahost_v2 --appendsigheader … working
tegrabct_v2 … --updatefwinfo flash.cfg.bin … not working, flash.cfg.bin missing
tegrabct_v2 … --updatestorageinfo flash.cfg.bin … not working, flash.cfg.bin missing
tegrasign_v2 --key None --list mb1_cold_boot_bct_MB1_sigheader.bct_list.xml … not working, .xml missing
tegrahost_v2 --updatesigheader mb1_cold_boot_bct_MB1_sigheader.bct.encrypt mb1_cold_boot_bct_MB1_sigheader.bct.hash zerosbk … not working, .hash missing

So you could really help me out if you could tell me the 28.1.0 command sequence to create the mb1_cold_boot_bct_MB1_sigheader.bct.encrypt file. Thats all from me for today, thanks in advance.

Regards,
Goran

hello DblG,

you could refer to Topic 1035668 for the commands to generate sign files.
for example,

sudo ./tegraflash.py --bl nvtboot_recovery_cpu.bin  --chip 0x18 --applet mb1_recovery_dev.bin  --cfg flash.xml  --sdram_config P3310_A00_8GB_Samsung_8GB_lpddr4_204Mhz_A02_l4t.cfg --sdram_config P3310_A00_8GB_Samsung_8GB_lpddr4_204Mhz_A02_l4t.cfg --misc_config tegra186-mb1-bct-misc-si-l4t.cfg --pinmux_config tegra186-mb1-bct-pinmux-quill-p3310-1000-a00.cfg --pmic_config tegra186-mb1-bct-pmic-quill-p3310-1000-a00.cfg --pmc_config tegra186-mb1-bct-pad-quill-p3310-1000-a00.cfg --prod_config tegra186-mb1-bct-prod-quill-p3310-1000-a00.cfg --scr_config minimal_scr.cfg --scr_cold_boot_config mobile_scr.cfg --br_cmd_config tegra186-mb1-bct-bootrom-quill-p3310-1000-a00.cfg --dev_params emmc.cfg  --cfg  flash.xml --bins "mb2_bootloader nvtboot_recovery.bin; mts_preboot preboot_d15_dev_cr.bin; mts_bootpack mce_mts_d15_dev_cr.bin; bpmp_fw bpmp.bin; bpmp_fw_dtb tegra186-a02-bpmp-quill-p3310-1000-a00-00-te770d-ucm2.dtb; tlk tos.img; eks eks.img; bootloader_dtb tegra186-quill-p3310-1000-a00-00-base.dtb"  --cmd "sign"

Hi JerryChang,

thanks for your hint.

Using tegraflash.py with --cmd “sign” creates the bootloader/signed folder containing mb1_cold_boot_bct_MB1_sigheader.bct.encrypt. It could be a solution to generate this file within Linux_for_Tegra using the python script and copy it over to our updater build environment, but for our build process it would be better if the file could be created directly in the updater build environment with the necessary extracted tegra tools.

I wasn’t successful by now to reach the goal to create mb1_cold_boot_bct_MB1_sigheader.bct.encrypt by looking at the commands tegraflash.py calls, as strangely there seems something to be missing. I’m using the following command sequence:

1. tegraparser_v2 --pt flash.cfg
2. tegrabct_v2 --chip 0x18 --mb1bct mb1_cold_boot_bct.cfg --sdram P3310_A00_8GB_Samsung_8GB_lpddr4_204Mhz_A02_l4t.cfg --misc tegra186-mb1-bct-misc-si-l4t.cfg --scr mobile_scr.cfg --pinmux tegra186-mb1-bct-pinmux-quill-p3310-1000-c03.cfg --pmc tegra186-mb1-bct-pad-quill-p3310-1000-c03.cfg --pmic tegra186-mb1-bct-pmic-quill-p3310-1000-c03.cfg --brcommand tegra186-mb1-bct-bootrom-quill-p3310-1000-c03.cfg --prod tegra186-mb1-bct-prod-quill-p3310-1000-c03.cfg
3. tegrabct_v2 --chip 0x18 --mb1bct mb1_cold_boot_bct_MB1.bct --updatefwinfo flash.bin
4. tegrabct_v2 --chip 0x18 --mb1bct mb1_cold_boot_bct_MB1.bct --updatestorageinfo flash.bin
5. tegrahost_v2 --align mb1_cold_boot_bct_MB1.bct
6. tegrahost_v2 --appendsigheader mb1_cold_boot_bct_MB1.bct zerosbk
  1. gives me flash.bin, 2. is for mb1_cold_boot_bct_MB1.bct, 3. - 5. patch it a little bit around, and 6. creates mb1_cold_boot_bct_MB1_sigheader.bct.
7. tegrasign_v2 --key None --list mb1_cold_boot_bct_MB1_sigheader.bct_list.xml
8. tegrahost_v2 --updatesigheader mb1_cold_boot_bct_MB1_sigheader.bct.encrypt mb1_cold_boot_bct_MB1_sigheader.bct.hash zerosbk

I couldn’t find any traces on how the input file mb1_cold_boot_bct_MB1_sigheader.bct_list.xml needed for signing the BCT is generated. I checked the bcl_list.xml file generated for br_bct_BR.bct and tried to edit it as follows:

<?xml version="1.0"?>
<!-- Auto generated by tegrabct -->
<file_list>
        <file name="mb1_cold_boot_bct_MB1_sigheader.bct" offset="400" length="49168" type="bct">
                <sbk encrypt="1" sign="1" encrypt_file="mb1_cold_boot_bct_MB1_sigheader.bct.encrypt" hash="mb1_cold_boot_bct_MB1_sigheader.bct.hash" />
                <pkc signature="mb1_cold_boot_bct_MB1_sigheader.bct.sig" signed_file="mb1_cold_boot_bct_MB1_sigheader.bct.signed" />
        </file>
</file_list>

But when using 7. and 8. with it it didn’t give me a correctly signed mb1_cold_boot_bct_MB1_sigheader.bct.encrypt.

It seems, that if i had a good version of the .bct_list.xml file, also signing/encrypting would work. Can you tell me how to generate a good one, or how it needs to be edited for mb1_cold_boot_bct?

Regards,
Goran

hello DblG,

please refer to TX2 MB1 Platform Configuration, we only support platform configuration via flashing the device.
thanks

JerryChang,

that wasn’t the answer i was hoping for.
Anyway, i was able to figure out the contents of the .xml needed to sign the image by debugging tegraflash.py. If anybody is interested, command sequence 1-8 from my previous comment generates a signed/encrypted MB1_BCT image when using the following .xml sign tree:

<?xml version="1.0"?>
<file_list>
  <file name="mb1_bct_cold_boot_MB1_sigheader.bct" offset="384">
    <sbk encrypt="1" encrypt_file="mb1_bct_cold_boot_MB1_sigheader.bct.encrypt" hash="mb1_bct_cold_boot_MB1_sigheader.bct.hash" sign="1" />
    <pkc signature="mb1_bct_cold_boot_MB1_sigheader.bct.sig" signed_file="mb1_bct_cold_boot_MB1_sigheader.bct.signed" />
  </file>
</file_list>

Regards,
Goran