A few issues with CBoot...patch attached

The stock cboot has a few issues which should be easy to fix…

  • The scripts embedded in u-boot on the Nano platform looked for both /boot/extlinux/extlinux.conf and /extlinux/extlinux.conf in the APP partition. This made it easier for other distros who normally place the boot files in their own partition and mount it as /boot in the rootfs. CBoot only looks for /boot/extlinux/extlinux.conf. The attached patch make CBoot look there first but then try /etxlinux/extlinux.conf before giving up.

While compiling to fix this issue, I ran across a few compile issues related to python.

  • bootloader/partner/t18x/cboot/build/get_branch_name.py looks for an environment variable TOP which it can’t find and causes an exception. I’m guessing it should have been TEGRA_TOP?
  • Even if it finds it, it tries to open a file ./repo/manifest.xml which doesn’t exist again causing na exception.
  • Then it uses the python2 “print” construct without the parenthesis… print prj.getAttribute("revision") which causes an exception when run under python 3.
  • bootloader/partner/t18x/cboot/scripts/add_version_info.py was trying to use struct.pack without encoding the string to “bytes” causing an exception.

The patch also fixes these issues.

diff -uprN c-boot-stock/bootloader/partner/common/lib/linuxboot/extlinux_boot.c c-boot/bootloader/partner/common/lib/linuxboot/extlinux_boot.c
--- c-boot-stock/bootloader/partner/common/lib/linuxboot/extlinux_boot.c	2020-04-23 03:41:07.000000000 -0600
+++ c-boot/bootloader/partner/common/lib/linuxboot/extlinux_boot.c	2020-05-17 11:37:46.639229788 -0600
@@ -32,6 +32,7 @@
 #include <tegrabl_auth.h>
 #define EXTLINUX_CONF_PATH			"/boot/extlinux/extlinux.conf"
+#define EXTLINUX_CONF_PATH_ALT		"/extlinux/extlinux.conf"
 static struct conf extlinux_conf;
@@ -230,12 +231,17 @@ static tegrabl_error_t load_and_parse_co
 	/* Read the extlinux.conf file */
-	pr_info("Loading extlinux.conf ...\n");
+	pr_info("Trying to load extlinux.conf from %s ...\n", EXTLINUX_CONF_PATH);
 	err = tegrabl_fm_read(fm_handle, EXTLINUX_CONF_PATH, NULL, conf_load_addr, &file_size, NULL);
 	if (err != TEGRABL_NO_ERROR) {
-		pr_error("Failed to find/load %s\n", EXTLINUX_CONF_PATH);
-		goto fail;
+		pr_error("Failed to find/load primary %s\n", EXTLINUX_CONF_PATH);
+		pr_info("Trying to load extlinux.conf from %s ...\n", EXTLINUX_CONF_PATH_ALT);
+		err = tegrabl_fm_read(fm_handle, EXTLINUX_CONF_PATH_ALT, NULL, conf_load_addr, &file_size, NULL);
+		if (err != TEGRABL_NO_ERROR) {
+			pr_error("Failed to find/load secondary %s\n", EXTLINUX_CONF_PATH_ALT);
+			goto fail;
+		}
 	/* Parse extlinux.conf file */
diff -uprN c-boot-stock/bootloader/partner/t18x/cboot/build/get_branch_name.py c-boot/bootloader/partner/t18x/cboot/build/get_branch_name.py
--- c-boot-stock/bootloader/partner/t18x/cboot/build/get_branch_name.py	2020-04-23 03:41:07.000000000 -0600
+++ c-boot/bootloader/partner/t18x/cboot/build/get_branch_name.py	2020-05-17 11:06:34.719878642 -0600
@@ -13,13 +13,16 @@ import os
 import sys
 from xml.dom.minidom import parse
-top_dir =  os.environ['TOP']
+top_dir =  os.environ['TEGRA_TOP']
 manifest_file = top_dir + '/.repo/manifest.xml'
-xml_tree = parse(manifest_file)
-collection = xml_tree.documentElement
-projects = collection.getElementsByTagName("default")
+    xml_tree = parse(manifest_file)
+    collection = xml_tree.documentElement
+    projects = collection.getElementsByTagName("default")
-for prj in projects:
-    if prj.getAttribute("remote") == "origin":
-        print prj.getAttribute("revision")
-        break
+    for prj in projects:
+        if prj.getAttribute("remote") == "origin":
+            print(prj.getAttribute("revision"))
+            break
+    pass
diff -uprN c-boot-stock/bootloader/partner/t18x/cboot/scripts/add_version_info.py c-boot/bootloader/partner/t18x/cboot/scripts/add_version_info.py
--- c-boot-stock/bootloader/partner/t18x/cboot/scripts/add_version_info.py	2020-04-23 03:41:07.000000000 -0600
+++ c-boot/bootloader/partner/t18x/cboot/scripts/add_version_info.py	2020-05-17 11:05:03.464312214 -0600
@@ -40,4 +40,4 @@ if __name__ == "__main__":
         version_string = '-'.join([str(item) for item in text])
         sys.stdout.write('Appending version string: %s to %s\n' %
                                         (version_string, binfile))
-        f.write(struct.pack('%ds' % (length), version_string))
+        f.write(struct.pack('%ds' % (length), version_string.encode('utf-8')))

Hi gtj,

Thanks for sharing the patch.

While compiling to fix this issue, I ran across a few compile issues related to python.

This issue sounds nothing to do with the patch you added. Do you mean you could hit the compilation error by using the source from tarball?

Correct. I tried to compile the stock tarball before making any changes and hit the python issues. I had to fix those before actually changing and compiling for the extlinux.conf location fix.

Thanks for pointing out. Let me try it on our side too…

Hi gtj,

We can build cboot success.
List steps for you reference:

  1. Download Xavier-NX C-Boot sources
  2. Set compiler toolchain:
    $ export CROSS_COMPILE=[path]/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-
  3. Extract the CBoot-standalone source
    mkdir cboot tar xpvf cboot_src_t194.tbz2 -C cboot
    $ cd cboot
  4. Set the TEGRA_TOP environment:
    $ export TEGRA_TOP=$PWD
  5. Build T194 CBoot bnary:
    make -C ./bootloader/partner/t18x/cboot PROJECT=t194 TOOLCHAIN_PREFIX="{CROSS_COMPILE}" DEBUG=2 BUILDROOT="${PWD}"/out NV_TARGET_BOARD=t194ref NV_BUILD_SYSTEM_TYPE=l4t NOECHO=@

Hi gtj,

I am also wondering why does this python script still run on your side. This sounds like a tool for NV internal build tool because I saw .repo/manifest.xml.

Could you also share how did you hit error in this file?

Yeah that was my thought as well.

With Python3 as the default python and using using your steps exactly I get.

make: Entering directory '/usr/src/jetson-nano/Linux_for_Tegra186_32.4.2/sources/c-boot-stock/bootloader/partner/t18x/cboot'
LKROOT=. LKINC=". " make -rR -f ./engine.mk -I. 
make[1]: Entering directory '/usr/src/jetson-nano/Linux_for_Tegra186_32.4.2/sources/c-boot-stock/bootloader/partner/t18x/cboot'
PROJECT = t194
TARGET = t194
TEGRA_TOP = /usr/src/jetson-nano/l4t-nx/sources/c-boot-stock
TOOLCHAIN_PREFIX = /opt/x-tools/aarch64-linux-gnu/bin/aarch64-linux-gnu-
LIBGCC = /opt/x-tools/gcc-linaro-7.4.1-2019.02-x86_64_aarch64-linux-gnu/bin/../lib/gcc/aarch64-linux-gnu/7.4.1/libgcc.a
including app/kernel_boot/../../../../common/lib/linuxboot/../file_manager/../fs/ext2/../../bcache
  File "./build/get_branch_name.py", line 24
    print prj.getAttribute("revision")
SyntaxError: invalid syntax
make[1]: *** No rule to make target '/usr/src/jetson-nano/l4t-nx/sources/c-boot-stock/usr/src/jetson-nano/Linux_for_Tegra186_32.4.2/sources/c-boot-stock/bootloader/partner/t18x/cboot/platform/t194/platform.c', needed by '/usr/src/jetson-nano/l4t-nx/sources/c-boot-stock/out/build-t194/usr/src/jetson-nano/Linux_for_Tegra186_32.4.2/sources/c-boot-stock/bootloader/partner/t18x/cboot/platform/t194/platform.o'.  Stop.

The issue is ./bootloader/partner/t18x/cboot/build/get_branch_name.py is written for Python2 and most distributions now are setting Python3 as the default since Python2 is no longer supported.

Changing print prj.getAttribute("revision") to print(prj.getAttribute("revision")) fixes that issue.

Then I hit…

Traceback (most recent call last):
  File "./build/get_branch_name.py", line 16, in <module>
    top_dir =  os.environ['TOP']
  File "/usr/lib64/python3.8/os.py", line 675, in __getitem__
    raise KeyError(key) from None
KeyError: 'TOP'

Changing TOP to TEGRA_TOP gets by that issue but then…

Traceback (most recent call last):
  File "./build/get_branch_name.py", line 18, in <module>
    xml_tree = parse(manifest_file)
  File "/usr/lib64/python3.8/xml/dom/minidom.py", line 1959, in parse
    return expatbuilder.parse(file)
  File "/usr/lib64/python3.8/xml/dom/expatbuilder.py", line 910, in parse
    with open(file, 'rb') as fp:
FileNotFoundError: [Errno 2] No such file or directory: '/usr/src/jetson-nano/l4t-nx/sources/c-boot-stock/.repo/manifest.xml'

Now, I don’t know whether TEGRA_TOP is the correct variable or not but wrapping the whole thing in try/except/pass got by those errors.

The last issue was…

 412551	  17176	 161256	 590983	  90487	/usr/src/jetson-nano/Linux_for_Tegra186_32.4.2/sources/c-boot-stock/out/build-t194/lk.elf
Appending version string: t194-94e99627 to /usr/src/jetson-nano/Linux_for_Tegra186_32.4.2/sources/c-boot-stock/out/build-t194/lk.bin
Traceback (most recent call last):
  File "./scripts/add_version_info.py", line 43, in <module>
    f.write(struct.pack('%ds' % (length), version_string))
struct.error: argument for 's' must be a bytes object
make[2]: *** [make/build.mk:7: /usr/src/jetson-nano/Linux_for_Tegra186_32.4.2/sources/c-boot-stock/out/build-t194/lk.bin] Error 1

That needed f.write(struct.pack('%ds' % (length), version_string)) changed to f.write(struct.pack('%ds' % (length), version_string.encode('utf-8')))

I see. So this issue is for python3.

We will check this issue.

It appears that none of my changes made it into the latest cboot. :(