Problem solved: support for uboot tools fw_printenv/fw_setenv on Linux For Tegra

does fw_printenv/fw_setenv work for UBOOT on Tegra Jetson?

The tools fw_printenv/fw_setenv in the uboot source tree normally work with mtd partitions and I have seen hints on the web for emmc support for these tools. Normally you configure these tools with the file tools/env/fw_env.config to tell it what device and address offset to use to read/write the uboot environment variables from linux.

It appears that the EMMC flash address used to store the uboot environment variables is not a visible partition after the kernel boots ( After booting linux I have dumped the entire /dev/mmcblk0 partition to a file and a search of this does not show the expected uboot environment data )

After looking through the uboot source code I determined the uboot partition/offset where the environment variables were stored and I can dump the raw environment byte stream with:
mmc dev 0 2
mmc read 80800000 1ff0 1
md 80800000

I do not understand the relationship with the uboot partitions and the /dev/mmcblk0pX partitions that are visible after the kernel boots. The flash is 16 GiB, but a dump of /dev/mmcblk0 shows a size of about 14.7 GiB, I am assuming this is because the entire flash is not visiable after the kernel boots.

Anyway, all i need is for uboot’s fw_printenv/fw_setenv linux tools to work, is this possible on the tegra?

This is something I’m interested in but am just starting to research, so I have some observations but not a real answer.

First is that the partitions are type GPT. Output of “fdisk -l” lists this. Also, within the L4T flash software bootloader subdirectory is the app which creates those partitions, mkgpt (arguments to this and output can be observed by logging a flash). U-boot itself used to look for a “.uimg” format kernel, but under L4T it uses zImage format instead…so any code in other u-boot source which refers to the uimg format is probably obsolete…kernel format itself could possibly be related to parition schemes. Note that at the end of u-boot and just prior to actual kernel load there is always an error about wrong image format for sysboot, along with the error that it cannot find the kernel…I highly suspect that this is old code left in from prior uimg format days. This means probably the code you are interested in also has deprecated code mixed with what is actually used.

Additionally, mmcblk0p1 was never intended to mean all of eMMC. A good illustration of this is that during installation of fastboot the “-k 6” parameter (a default) puts the kernel itself in the sixth partition…u-boot doesn’t care about this partition, but other partitions prior to this still exist for content such as the boot loader itself. We know for certain that mmcblk0p1 is used for eMMC flash, while mmcblk1p1 is used for SD card flash…the naming and use suggests that partition p1 of the device is used for root partition, but in a zero-based numbering scheme this means p0 should also exist, e.g., mmcblk0p0, and probably contains this other mystery data.

Problem solved…

Notes about allowing read / write of uboot environment on R21.2:

  1. There appears to be 4 hardware partitions in the flash memory:
    a) user partition
    b) boot partition #1 ( not sure what is loaded here, does not appear to be fastboot.bin )
    c) boot partition #2 ( first part appears to be unused, uboot environment stored in last 0x2000 bytes )
    d) an “rpmb” partition, don’t kow what this is, if someone can explain it I would love to know

  2. By default, the user partition is what is available for the user, and the part of it that is visible after the kernel boots is based on the argument “-v GP1” passed to “mkpgt” in the nvidia utility flash.sh, and the partitions defined in jetson-tk1_extlinux.conf.emmc. The flash.sh calls mkgpt with “-v GP1” which says that all partitions after the partition named “GP1” will be visible after the kernel boots. The kernel will create /dev entries in /dev/mmcblk0pX where ‘X’ varies from 0 up to the number of partitions defined after “GP1” in jetson-tk1_extlinux.conf.emmc. So the default configuration is that the “APP” partition will be the first partition visible in /dev/mmcblk0p1. We have customized our flash script to call mkgpt with the argument “-v PT”, and also customized the emmc configuration file to remove unneeded partitions to make more flash memory available. We also make the UBOOT ( EBT ) and kernel ( LNX ) partitions visible after the kernel boots. This, along with other software we developed, gives us the capability to flash a new uboot or kernel through a web page interface after the kernel is booted.

  3. By default the kernel marks the boot partitions as no access so by default, there is no /dev/mmc* partitions created for them. We want the capability to change the uboot environment variables which is stored in the 2nd boot partition. You can make the boot partitions available with 2 kernel changes:
    a) comment out line #4318 in drivers/mmc/host/sdhci-tegra.c, this will cause the kernel to create new /dev entries ( /dev/mmcblk0boot0 and /dev/mmcblk0boot1 ):

    host->mmc->caps2 |= MMC_CAP2_BOOTPART_NOACC;

    b) step a) above will make the boot partitions visible, but not writable. Read access is sufficient for fw_printenv to read the uboot environment, but if you want to use fw_setenv to set the uboot environment from user level, you need to make the 2nd boot partition writable. This can be done by changing the kernel source file drivers/mmc/core/mmc.c, line 355 from:

             mmc_part_add(card, part_size,
                 EXT_CSD_PART_CONFIG_ACC_BOOT0 + idx,
                 "boot%d", idx, true,
                 MMC_BLK_DATA_AREA_BOOT);
    

to:
mmc_part_add(card, part_size,
EXT_CSD_PART_CONFIG_ACC_BOOT0 + idx,
/* allow write to uboot env in 2nd boot partition */
“boot%d”, idx, ( idx < 1 ) ? true : false,
MMC_BLK_DATA_AREA_BOOT);

  1. Finally, configure fw_printenv / fw_setenv to allow the tools to read/write the uboot environment variables in the 2nd boot partition ( i.e. /dev/mmcblk0boot1 ) The source for these tools is in the uboot source tree under the directory tools/env. When installing on the target create the configuration file /etc/fw_env.config with the following line to tell the tools the /dev entry, byte offset and size where the uboot environment variables are located:

     /dev/mmcblk0boot1       0x3fe000        0x2000
    

You will have to use sudo to have adequate permission to run the tools.

Example usage:

   sudo fw_setenv my_uboot_env_name this_is_a_test
   sudo fw_printenv my_uboot_env_name

How to flash a new u-boot.bin[u-boot-dtb-tegra.bin] after the kernel is booted.

I Have followed the following steps, but unable to boot the system, once reboot command is given

dd if=/dev/zero of=/home/ubuntu/flash.img bs=512 count=8192
dd if=/home/ubuntu/u-boot.bin of=/home/ubuntu/flash.img conv=notrunc
dd if=/home/ubuntu/flash.img of=/dev/mmcblk0p3

What was the source of your u-boot.bin, and what is your goal? The dd steps to copy and create an image to flash look basically correct, provided the image used to create the dd output is correct, but one part makes me wonder if this is what you actually need.

In particular, you mentioned the dtb blob file, u-boot-dtb-tegra.bin. This is not part of the u-boot.bin executable binary, this remains separate (as an ordinary file, not a partition) and is loaded by the u-boot executable at startup from the /boot directory (this file does not require flash to update). Is this dtb the part you wanted to update?

If it is the dtb you wanted to update or alter, then take a look at /boot/extlinux/extlinux.conf, you’ll see a line “FDT” which is the firmware dtb reference…the path named on this line is how u-boot knows where to find the dtb file. On the assumption that this dtb is what you really want to update, simply put it in /boot with a slightly altered file name from the original and edit this one line in extlinux.conf. If that wasn’t your goal, it would be useful to know what your actual goal is in order to better answer.

mmcblk0p1 is the u-boot partition.
Look here at page 3
http://developer.download.nvidia.com/mobile/tegra/l4t/r21.1.0/Tegra_Linux_Driver_Package_UBoot_R21.1.pdf

Hi,

source of u-boot.bin:

u-boot$ git branch -av

  • l4t/l4t-r21.4 105d2f3 ARM: tegra: update board_info property name

u-boot Makefile:

VERSION = 2014
PATCHLEVEL = 10
SUBLEVEL =
EXTRAVERSION = -rc2
NAME =

Goal:

Want to flash/copy u-boot.bin[u-boot-dtb-tegra.bin], after Linux kernel booted, Ubuntu GUI has come up on Jetson tk1 board.

Note: Do not want to flash using recovery mode specified in the http://developer.download.nvidia.com/mobile/tegra/l4t/r21.1.0/Tegra_Linux_Driver_Package_UBoot_R21.1.pdf

Explanation on : u-boot executable at startup from the /boot directory:

u-boot is not part of /boot directory, u-boot will search for /boot directory and read extlinux.conf to load zImage and device tree file.

Let me paraphrase your goal to be sure I have this correct. You want to update u-boot with your git version on a running system, not with the flash process. Is this correct? If so, this is probably workable if the location of u-boot and anything u-boot needs to refer to is known ahead of time (along with sufficient space).

If so, consider that you can clone images of individual partitions. Although the clone article focuses on rootfs or an entire eMMC of all partitions, there is an ability to clone and restore individual partitions other than just those. This requires recovery mode, but I see no reason why you couldn’t flash normally using the alternate u-boot from git to test with first, and if it works, copy this partition via clone (in case flash makes alterations other than padding…a clone would take into account those alterations), and possibly use this at any later time via dd on a running system to replace the u-boot.bin.

Even if you desire to install this new u-boot binary from a running system, have you tested it first via recovery mode flash? This way you would know if the binary itself works with the rest of the system. A failed install detail versus a missing u-boot build detail would be verifiable.

For reference, the clone article is here…note the information particularly about partition table cloning and how image names in the table refer to and make access to various partitions possible:
[url]http://elinux.org/Jetson/Cloning[/url]

Hi,

The goals is to to update u-boot with L4T git version on a running system, not with the flash process.

Modified flash.sh : to say all the partitions after BCT need to visible & removed the unwanted partitions/ customized partitions

GPT:

if [ ! -z “${bootpartsize}” -a ! -z “${emmcsize}” ]; then
echo "creating gpt(${localpptfile})… “;
MKGPTOPTS=”-c ${localcfgfile} -P ${localpptfile} “;
MKGPTOPTS+=”-t ${emmcsize} -b ${bootpartsize} -s 4KiB “;
MKGPTOPTS+=”-a GPT -v BCT “;
MKGPTOPTS+=”-V ${MKGPTCMD} ";
./mkgpt ${MKGPTOPTS};
chkerr “creating gpt(${localpptfile}) failed.”;
fi;

Tegra124 (Jetson TK1) # mmc part

Partition Map for MMC device 0 – Partition Type: EFI

Part Start LBA End LBA Name
Attributes
Type GUID
Partition GUID
1 0x00000000 0x00000fff “PPT”
attrs: 0x0001000000000001
type: ebd0a0a2-b9e5-4433-87c0-68b6b72699c7
guid: 7369c667-ff51-ec4a-29cd-baabf2fbe346
2 0x00001000 0x00001fff “PT”
attrs: 0x0002000000000001
type: ebd0a0a2-b9e5-4433-87c0-68b6b72699c7
guid: f854c27c-e81b-8de7-765a-2e63339fc99a
3 0x00002000 0x00003fff “EBT”
attrs: 0x0003000000000001
type: ebd0a0a2-b9e5-4433-87c0-68b6b72699c7
guid: b70d3266-5831-5aa3-255d-051758e95ed4
4 0x00004000 0x01c03fff “APP”
attrs: 0x0004000000000001
type: ebd0a0a2-b9e5-4433-87c0-68b6b72699c7
guid: c6cdb2ab-b49b-1154-0e82-7441213ddc87

changed setenv bootpart to 4 and root=/dev/mmcblk0p4 in /boot/extlinux/extlinux.conf…

After booting…at Linux command prompt

Able to read /dev/mmcblk0p3 and write back using dd command.

But I want to update u-boot.bin with change of time stamp[compilation time]…reboot fails.

Explanation on the statement:
I see no reason why you couldn’t flash normally using the alternate u-boot from git to test with first, and if it works, copy this partition via clone (in case flash makes alterations other than padding…a clone would take into account those alterations), and possibly use this at any later time via dd on a running system to replace the u-boot.bin.

Answer:
I have already flashed u-boot using flash.sh , they were working fine.
The same tested & working u-boot only , want to flash from Linux command line.

Is it correct that your new u-boot.bin (in the modified layout after regular flash) boots and functions correctly?

If there is no change, including timestamp, are you able to read this partition and put it back in place with dd and still have it work? FYI, if dd uses the correct block size and count the notrunc is not necessary. If for some reason the dd copy were to copy any excess it could overwrite partition data or part of the wrong partition. By what method are you choosing the bs and count for dd?

This is a pretty old thread at this point but I have been looking into this recently and recalled seeing someone having issues with replacing u-boot.

@JaiAtEcon: I think the missing piece is that uboot needs to be prepended with a “TBOOT header”. While wrapping my head around what flash.sh was doing (in order to customize the system) I discovered that it does the following when setting up uboot:

  1. Calls `${L4T}/elf-get-entry.py /path/to/uboot` to get the uboot entry point. Here the file used is the uboot elf file (not the u-boot-dtb.bin file)
  2. Calls `${L4T}/bootloader/gen-tboot-img.py /path/to/u-boot-dtb.bin ${UBOOT_ENTRY} /path/to/new/u-boot-dtb.bin`

In addition, I think you need to patch uboot with: tools/env/fw_env.h: Correct include order · OE4T/u-boot-tegra@9f64e48 · GitHub

Hope that helps.

Sorry for the bump of such an old thread but I was wondering where to find elf-get-entry.py and gen-tboot-img.py. I have looked in both r21.5, r21.4, r21.3, r21.2, and r21.1 for them and wasn’t able to find it. I also checked the flash script for their call location but couldn’t find that either. Thanks.

I see them as present in any of the TX1 driver packages directly in the “Linux_for_Tegra” directory. Note: This means they were probably not used with, nor intended for the TK1.

Found them, thank you. While they weren’t of any help, I was able to make a few small adjustments to flash uboot via linux. The first being that I had to give myself write access to both boot partitions (it seems like just the first is needed from looking at hexdumps of images but I need to flash it to confirm). Do you know if uboot’s variables were swapped to this first partition? Thanks in advance for your help.

I do not know which partition the fw_setenv/fw_printenv might use. You might run “sudo gdisk -l /dev/mmcblk0” though and look at those labels. I’m unsure which partitions you’re specifically referring to, but most of the software uses those labels to refer to partitions.

If we were talking about the TX1 there is this information on T-Boot:
[url]http://http.download.nvidia.com/tegra-public-appnotes/t210-nvtboot-flow.html[/url]

…I don’t know if there is a similar do equivalent doc specific to the TK1. Does anyone know of a T-Boot document similar to the above URL (specific to nvtboot)?

There are a set of documents here, one of which is a general document about boot flow:
[url]http://http.download.nvidia.com/tegra-public-appnotes/[/url]
[url]http://http.download.nvidia.com/tegra-public-appnotes/tegra-boot-flow.html[/url]

I think nvtboot is very similar (or the same) between the TK1 and the TX1, but significantly different when talking about the TX2. Much of what you read in the TX1 doc will likely apply to the TK1. Whether you’ll find information specific to the setting and printing of env within the boot loader and the partitions I don’t know. Even so, many of the details you are interested in will be found there (e.g., there is a section which talks about BCT redundancy).

Thanks for your links. My previous error was simply not knowing uboot had to save its environment before linux would be able to see it after a fresh flash so I got that fixed. But back to flashing uboot, I can successfully flash my new uboot via usb and all is well. Flashing via linux results in a non booting system with uboot failing to appear. I hexdumped the EBT partition after both flashes and noticed some extra data at the end of the partition after the flash via USB. Do you know how this gets there? Ive looked through the flash script and did not notice anywhere that would append data to uboot.bin or even the EBT partition itself. Ive also tried using elf-get-entry.py and gen-tboot-header.py but neither worked with any uboot, even default uboots provided by the TX1’s driver package. If I can figure out how that uboot footer is being created, the jetson will boot. Thanks in advance again.

In part during a regular flash via flash.sh the “bootloader/ardbeg/u-boot.bin” has NULL bytes appended to the end and the result becomes “bootloader/u-boot.bin”. This latter is the version used in boot, and I assume some of those NULL bytes are edited somewhere during the flash process, but I could not tell you what does the edit. I am guessing this is part of the saved flash environment settings.

Okay, thank you. Have you been able to flash uboot via linux?

I have not tried to flash just u-boot.

Gotcha, thank you. I’ll post back when I figure it out.