This is about the packaging and extracting of files in tar archives (the source as a whole is a tar archive, and this contains another tar archive which is the kernel itself).
Incidentally, whenever JetPack/SDK Manager is used on the host PC for flashing the Jetson, it creates this directory:
~/nvidia/nvidia_sdk/JetPack...version.../Linux_for_Tegra/
That “<release_package>
” is named after the JetPack version, and is what determines my notation “JetPack...version...
”. This is where you find things labeled with “Linux_for_Tegra/
”. The “Linux_for_Tegra/
” content, aside from what populates the “Linux_for_Tegra/rootfs/
”, is the “driver package” which performs the flash. The “Linux_for_Tegra/rootfs/
” is a purely Ubuntu filesystem with NVIDIA drivers on top of it. Just go to “cd ~nvidia/nvida_sdk
”, and then run “ls
” to see which L4T releases your flash has set up for.
I would be careful about installing the kernel with the copy to “/boot/Image
”, but here is a short list of what is going on…
The Image
is the uncompressed kernel. The kernel normally resides on the Jetson at “/boot/Image
”, although flashing will also put the kernel in eMMC for an eMMC model (the “/boot/Image
” takes priority over the partition version if security fuses are not burned). The command “uname -r
” depends on the combination of the kernel version and the setting of CONFIG_LOCALVERSION
during its build, and modules are searched for (by that specific kernel) at “/lib/modules/$(uname -r)/kernel
”. Sometimes you can just build a module and copy that in. Once you copy a new Image
in things get more complicated (not terribly complicated, but you are now at risk of not being able to boot if it goes wrong). Flashing to add the kernel typically is needed if your kernel is going into a partition.
So far as getting the source goes, on the R32.4.7 page, the Nano source is the “Driver Package (BSP) Sources”, which provides a file with a lot of other content. Only the subcontent of “public_sources.tbz2
” is the kernel source. It is a package within a package.
To list what is in the original public_sources.tbz2
you can do this:
tar --list -j -f ./public_sources.tbz2
The “--list
” shows content instead of extracting. The “-j
” says this is bzip2
compressed file (the .tbz2
is a contraction of .tar.bz2
; they are the same). The -f
is for naming a file. Note that the file within this file which you are interested in, and which is the kernel source, is:
kernel_src.tbz2
A very important note is that kernel_src.tbz2
needs the full path within the archive named, so what you really extract is:
Linux_for_Tegra/source/public/kernel_src.tbz2
You can extract that from the original, and then extract everything from kernel_src.tbz2
to get the actual source, and quoting the name of that file with single quotes to avoid the /
becoming issues at times:
# Subpackage:
tar -jvx -f public_sources.tbz2 'Linux_for_Tegra/source/public/kernel_src.tbz2'
# You could now move `kernel_src.tbz2` somewhere else, but if you were in
# "~/nvidia/nvidia_sdk/JetPack...version.../" when you extract, then this would
# automatically place the kernel source file at
# "./Linux_for_Tegra/source/public/kernel_src.tbz2"
# Regardless of where it is, the kernel source itself can be extracted:
cd Linux_for_Tegra/source/public
tar xjvf ./kernel_src.tbz2
# You could have used mv on kernel_src.tbz2 instead of cd to there.
(x
is extract, v
is verbose, j
is again for bzip2
; I’m naming the file to be extracted rather than extracting everything in the first command; second command just extracts all from kernel_src.tbz2
)
Note that kernel source in itself does not require root ownership. It works perfectly well as a regular user. However, if the original source is owned by root, and all modification and change and temporary content is to a separate location, then you have a guarantee that your source is pristine at all times. The “--owner root --group root
” isn’t really necessary, but when unpacked to “Linux_for_Tegra/rootfs/
”, you will find the destination requires root. You only need to unpack to that location if you are including it as part of flash. When you are updating after flash, manually adding or editing a kernel, you don’t need that extraction location. You could just use the command I gave. You can prefix unpacking of the kerel_src with "
sudo …`" if you want it to have root ownership,
Please note that if you’ve flashed once via JetPack, then apply_binaries.sh
has already been run and it doesn’t need to be run again in most circumstances (this is what overlays the NVIDIA content onto a previously pure Ubuntu rootfs). In cases where the “Linux_for_Tegra/
” has bee updated with new alternate content which apply_binaries.sh
would add, then it might be useful for adding your customization. For a running Jetson none of this is needed since you’re just copying a file to the Jetson. The case where this is most useful is if you want to flash a number of Jetsons with this modification, e.g., for manufacturing. For your case you can just unpack the kernel source as a whole in some custom location, build, and then make copies of content to the Jetson rather than using the special unpacking.
The part the documents are good at is the cross compile itself. It tells you what to install on the host PC, and the steps to take. For that you just unpack the kernel source to your favorite location without the special setup.
Cross compiling is the same as regular compile except for the environment settings and the cross tools. Some notes on comparison:
- You set
ARCH
to arm64
for cross-compile, and do not set this during native compile.
- You don’t set
CROSS_COMPILE
on native compile.
- You probably do want to use an alternate temporary output location via “
O=/some/where
” in both cases.
- You probably need to install “
sudo apt-get install libncurses5-dev
” in both cases.
- You will want a
TEGRA_MODULES_OUT
location for some temporary module output in both cases. No difference.
I’ll give an example to illustrate native compile. I will assume you have this temporary location, which is a bad idea if you do not have enough disk space on the Jetson, but which is perfect if you have the disk space (disk space is a big reason to cross-compile):
mkdir ~/temporary
mkdir ~/temporary/kernel
mkdir ~/temporary/modules
export TEGRA_KERNEL_OUT=~/temporary/kernel
export TEGRA_MODULES_OUT=~/temporary/modules
# Now just follow build steps. You could make sure the original source
# is pristine:
cd /where/ever/kernel/source/is
# `pwd` just echos where you are at the moment. TOP is the traditional
# name for the root of any source compile.
export TOP=`pwd`
# This makes that location pristine. You want it owned by root. You won't
# use sudo anymore after this.
sudo make mrproper
make O=$TEGRA_KERNEL_OUT tegra_defconfig
# Note that the "-j #" option says how many cores to use. If you have 6 cores,
# then probably you'd use "-j 6".
# This nconfig is just if you want adjustments over the default config. Use
# the "m" key for module format if it is available:
make O=$TEGRA_KERNEL_OUT nconfig
# Don't forget that in nconfig you can edit CONFIG_LOCALVERSION. nconfig
# has a symbol search function, and you could search for "localversion" (search
# is case insensitive and knows about the prefixed "CONFIG_". You could set
# CONFIG_LOCALVERSION to "-tegra" if you are only adding modules. If modifying
# integrated features with "=y", then there is more to the story.
make O=$TEGRA_KERNEL_OUT -j 6 Image
make O=$TEGRA_KERNEL_OUT -j 6 modules
make O=$TEGRA_KERNEL_OUT modules_install INSTALL_MOD_PATH=$TEGRA_MODULES_OUT
# Now look for Image:
cd $TEGRA_KERNEL_OUT
find . -name Image
# Or just browse the module location; this includes the full path, which mirrors
# where anything would be copied to. You only need to copy one file if you
# just build a new module, but all modules might be listed. Ignore any that you
# did not add:
cd $TEGRA_MODULES_OUT
cd lib/modules
# There will be a subdirectory named after what this kernel Image expects.
# This is just an example, it might differ for you:
cd 4.9.140-tegra
cd kernel
find . -name '*.ko'
Just remember that the biggest issue on native compile is having enough disk space. You probably want at least 5 GB spare space, and that is after you’ve copied the source code in. You could copy the kernel_src.tbz2
in and unpack it, then check:
df -H -T -t ext4
(this lists ext4
partitions; RAM pseudo partitions don’t count; if you have only eMMC or only SD card, then this is the same: “df -H -T /
”)
Also to emphasize, you don’t need ARCH
or CROSS_COMPILE
when natively compiling. In fact, even if you name ARCH
with the architecture of the native system, it is likely that the code will think arm64
is foreign. You don’t want that when working on arm64
.