Kernel Customisation Jetson Orin NX BSP Install

Here is a short bit on “CONFIG_LOCALVERSION”:
https://forums.developer.nvidia.com/t/how-to-fix-xorg-conf-in-jetson-orin/229155/12

I am not including the cross compile options. If cross compiling, what follows is still correct, but you’d also need to cross compile setup.

Before I add other information, it is good to be aware that there is an optional “O=/some/where” argument in kernel compile. This is for temporary external locations such that you can keep the original kernel source clean. I like to make the kernel source owned by root, readable by everyone, but writable only by root (with sudo). Then, for the original source, I do this to make sure it is pristine (the exception is if I’m making this my kernel headers link…a different topic):
sudo make mrproper
(the source itself is now “pristine”)

Then, for all builds, I use a regular user. That user should not be able to write in the source directory. You would create an empty directory, and all configuration and output would go there. As an example, you could “mkdir ~/kernel”. Then you set an environment variable to that location for consistency and ease of use. Example:

mkdir ~/kernel
cd ~/kernel
export TEGRA_KERNEL_OUT=`pwd`
# verify:
echo $TEGRA_KERNEL_OUT

Now go back to the kernel source. You can set basic configuration via:
make O=$TEGRA_KERNEL_OUT tegra_defconfig

Then you can use an application such as menuconfig or nconfig (my favorite, it has a symbol search, but otherwise is the same as menuconfig). Example:
make O=$TEGRA_KERNEL_OUT nconfig
(note that from now on all make commands include “O=$TEGRA_KERNEL_OUT”)

You can edit CONFIG_LOCALVERSION either in the editor or on command line with a regular editor. The only reason you can do this with a regular editor is because CONFIG_LOCALVERSION has no dependencies. Unless you absolutely know a feature has no dependencies, you should never edit the “.config” file manually.

For manual edit, you would edit “$TEGRA_KERNEL_OUT/.config”, search for CONFIG_LOCALVERSION, and set it like this (I am assuming you use “-tegra”, the default, but this is not always the case):
CONFIG_LOCALVERSION="-tegra"
(quotes are optional)

If your kernel source is version 5.10.104, and if your CONFIG_LOCALVERSION is “-tegra”, then the output of “uname -r” will be “5.10.104-tegra”. This is the source code version, plus append of CONFIG_LOCALVERSION. The reason this matters is because this is part of where the kernel looks for loadable modules. Modules are found at:
/lib/modules/$(uname -r)/kernel

Regarding build targets “menuconfig” and “nconfig”: These are very much the same thing, and are how you change configuration. This is used because they understand dependencies. Every feature and driver has a “symbol”, and you are editing symbols. One symbol can depend on another, or it might be incompatible with some other symbol. In the editor, if you add or change something with the “y” key, then it is a change to the integrated kernel (the “Image”). If you add or change something withttps://forums.developer.nvidia.com/t/how-to-fix-xorg-conf-in-jetson-orin/229155/12h the “m” key, then it is in the form of a module.

You probably should stick to module format when possible. Because of how modules are found and loaded, this means you’d also need to have a matching CONFIG_LOCALVERSION (in this case “-tegra”). On the other hand, if you are changing a feature with the integrated kernel (the Image file), then you need to change CONFIG_LOCALVERSION and build and install all modules again (but to the new location caused by change in “uname -r”).

tegra_defconfig” is just a build target. Assuming you are starting with clean source, and no configuration, you might start with that as a build target. Then you can use an editor, e.g., nconfig, to make edits. Edits can include CONFIG_LOCALVERSION if desired. Example, building from the original. I will call the top of the kernel source “$TOP”, and the temporary output location “TEGRA_KERNEL_OUT” (you could use a different name, it is arbitrary, picked because it is used with much documentation).

mkdir ~/kernel
cd ~/kernel
export TEGRA_KERNEL_OUT=`pwd`

# I assume you already set TOP to the location of the kernel source.
cd $TOP

# This is your only use of sudo in build:
sudo make mrproper
https://forums.developer.nvidia.com/t/topic/193640/11
# From now on we use O=$TEGRA_KERNEL_OUT.
make O=$TEGRA_KERNEL_OUT tegra_defconfig
make O=$TEGRA_KERNEL_OUT nconfig

# Symbol search is case insensitive, and does not need the leading "CONFIG_", although
# you can use that if you want. Look at the key bindings shown at the bottom. Now
# perform a symbol search for "localversion". Or simply go there if you know where it is.
# Set this up, hit the enter key, then enter the string (assumes you're going to reuse the
# original kernel Image, and work only on modules):
-tegra

# So now base configuration is the default, and module search is to the original module
# location. Kind of nice that any module build only needs to be copied as a file. Make
# whatever edits you need from now on in the nconfig editor. Search by symbol name
# if you need. Use the "m" key to enable. If the "m" key is not allowed, then you must
# change CONFIG_LOCALVERSION, e.g., it could be:
-custom

Now save and exit nconfig. If you are using a script, then things are ready to go. If you are manually building (which is what I trust), and if you are only building modules:

make O=$TEGRA_KERNEL_OUT modules_prepare
# I am assuming 12 CPU cores, but adjust "-j number" to the number of cores.
make O=$TEGRA_KERNEL_OUT -j 12 modules

If you want more information on manual build, just ask. On the other hand, here is some more information:

Important note: There are different ways to install kernels and modules. Things have changed somewhat in Orin. Probably you will run into official docs whereby kernels are added via flash, but often you don’t need to flash. If installing only new modules, then no flash will ever be needed (well, an exception occurs if you need an initrd to contain a module for an alternate filesystem type). Most of the details are in installing the entire kernel (which in turn means also installing all new modules). I will advise you to always leave the original kernel, device tree, and modules in place. Then create an alternate boot entry if the kernel Image is changing such that you have a fallback boot option. If it is just a module, then it is quite simple.