Missing Linux Kernel Headers

I am using the Elroy Carrier with TX2i system. I have installed the 32.2.1 Board Support Package, which resulted in the kernel version (uname –r) being upgraded from “4.9.140-tegra” into “4.9.140-tegra+”, which I assume is expected behavior.

Afterwards, I tried compiling a module from its source code using “sudo make”. It was being compiled without problems before the BSP had been installed. However, after installing the BSP, the “sudo make” command complained about the “/lib/modules/4.9.140-tegra+/build” being a broken symlink (/usr/eadams/trunk_tx2_32.2.1/tegra_kernel_out), therefore I tried copying the symlink from the previous kernel version into the new kernel version. In other words, “/lib/modules/4.9.140-tegra/build” symlink goes into “/lib/modules/4.9.140-tegra+” folder and overwrites the broken symlink. I ran “sudo make” to compile the module again. It compiled successfully. When I inpected the newly compiled module using “modinfo ***” the vermagic line suggested that the newly compiled module is only compatible with “4.9.140-tegra” due to being compiled using the old linux headers. I have tried running the module with “modprobe ***”, and it complained about vermagic inconsistency with the “uname -r”. Therefore, I have tried “modprobe *** -force” in order to ignore the vermagic, expecting it to maybe work, however this time it threw an “exec format error”, implying the newly compiled module is not suitable to be run on the new kernel version no matter what.

From this, I assume that my only solution would be to obtain proper linux kernel headers, that is compatible with the “TX2 L4T r32.2.1 BSP”. Are these header files available to be downloaded from somewhere? I could not find them from the Connect Tech site. Is Connect Tech the only source from which I may expect to obtain these header files? Is there a method through which I can generate these header files?

If they are not available, what would you suggest me to do in order to be able to compile the module successfully?

Please find it from L4T 32.2.1 | NVIDIA Developer

I mean I have the base header files but I need the header files for the upgraded kernel after installing the BSP.

We provide the whole kernel source as a tarball on the website. This should help your case.

Sorry for what will be an oblivious question but what do I do with the kernel source in order to obtain the kernel headers? Does it also apply to an “upgraded” kernel (the one where + is appended to the “uname -r”) that is obtained from applying a BSP on a working system?

Sorry that could you give a brief explanation about what you want to do with kernel headers?

If you just want to build kernel modules, then our document has guidance for it.

Like I have explained in the post, I have the source code of a driver for some hardware that I intend to use, the compilation and installation process explained in the “readme.txt” simply suggests me to “sudo make” which ends up with the “/lib/modules/4.9.140-tegra+/build” directory being accessed, which points to nothing. I understand that the header files for the “4.9.140-tegra+” is different from “4.9.140-tegra”, and I need the header files for the former, rather than the latter, is that not true? Am I misunderstanding my goal?

Not true. They are just same file. Those strings can also be configured during kernel compilation. Does not really stand for anything special.

If that’s the case then why does placing the “/lib/modules/4.9.140-tegra/build” symlink into the “/lib/modules/4.9.140-tegra+” folder not work? After doing this the building process completes successfully, but I can not run the resulting module file.

I feel we are talking about different issue.

The location to load the module maybe different due to the uname -r result. But this has nothing to with the header files.

If your kernel modules already built out and fine, then header files should not matter.

It gets placed into the correct directory, and gets accessed successfully while using modprobe, but does not run, even while using the “–force” option which ignores the mismatch between module vermagic value and uname -r.

What error does modprobe give out?

using modprobe WITHOUT --force:
modprobe: ERROR: could not insert ‘ngrabber’: Invalid argument
these 4 lines also show up in dmesg:
ngrabber: disagrees about version of symbol _dev_info
ngrabber: Unknown symbol _dev_info (err -22)
ngrabber: disagrees about version of symbol _dev_err
ngrabber: Unknown symbol _dev_err (err -22)

using modprobe WITH --force:
modprobe: ERROR: could not insert ‘ngrabber’: Exec format error
nothing shows up in dmesg.

What is the result of “file ngrabber”?

ELF 64-bit LSB relocatable, ARM aarch64, version 1 (SYSV), BuildID[sha1]=62f8e1ac8104fece23fa86eca16b4cf6408ef81b, with debug_info, not stripped

Did you only build the kernel modules or you even rebuilt the kernel image?

I do not know I just followed instructions, how can I check if what you stated is true/false?

Maybe you can learn to build our original kernel source first.

https://docs.nvidia.com/jetson/archives/l4t-archived/l4t-3261/index.html#page/Tegra%20Linux%20Driver%20Package%20Development%20Guide/kernel_custom.html#wwpID0E0LB0HA

I feel the problem is your kernel module does not match the kernel image.

FYI, the above suggests the configuration has changed and old modules won’t work with the new configuration. The location where a kernel searches for modules (and you have a custom kernel) is compiled into the kernel itself. That location is:
/lib/modules/$(uname -r)/kernel

Run command “uname -r”, and you will see “4.9.140-tegra+”, where the 4.9.140 is the base kernel version, the “-tegra” is likely from config item “CONFIG_LOCALVERSION=-tegra”, and the EXTRAVERSION is enabled to append the “+”. For it to work with old modules you’d want to start with an exact match of kernel configuration, and match the original “CONFIG_LOCALVERSION=-tegra”, but remove the EXTRAVERSION. You could then add features with something like “make menuconfig”. This would mean module search would be in the original “uname -r” location of “4.9.140-tegra” (without the “+”), and the actual modules would be compatible (you can’t just copy modules across all configurations because the binary loading has expectations which might change when the wrong config is changed). Fixing that would mean no need for “/lib/modules/4.140-tegra+/”.

The official kernel source from NVIDIA does not enable EXTRAVERSION. This is common though for some externally supplied kernel software. If you look at your kernel build location and examine the “Makefile”, do you see a line such as this?
EXTRAVERSION = +

Remove the “+” and just leave it as:
EXTRAVERSION =

Be sure to completely clean any previous build source with something like “make mrproper”, and install a new kernel which started as an exact match to what the stock system was built with. You can do this via “make tegra_defconfig” if “CONFIG_LOCALVERSION” was set to “-tegra”, and then you could optionally add features via modules and know the configuration would be compatible with the original modules at:
/lib/modules/$(uname -r)/kernel

Two things would happen:

  • The modules already in place at "/lib/modules/4.9.140-tegra/kernel would have binary compatibility and versioning that kernel.
  • The kernel would search for modules using the “uname -r” of “4.9.140-tegra” instead of “4.9.140-tegra+”, so those modules would be found. You wouldn’t need to build or install any replacement modules, whereas the way you now have it you must build and reinstall all modules.