After update kernel modules, HDMI do not display

Hi, My environment is 35.3.1(Orin NX 8GB)
I use this command to update kernel module.
From How to flash kernel-dtb and kernel module without make system.img and rootfs?:

And then I run initrd to flash:

sudo ./tools/kernel_flash/l4t_initrd_flash.sh \
 --external-device nvme0n1p1 \
 -c ./tools/kernel_flash/flash_l4t_external.xml \
 -k kernel-dtb \
 --external-only --network usb0 --showlogs \
 p3509-a02+p3767-0000 nvme0n1p1

But after build kernel module and flash, HDMI do not display.

I delete this command and run produre again, then HDMI display ok.
So the reason is kernel module copy.

#sudo rsync -azPu  $OUTPATH/lib/modules/5.10.104-tegra rootfs/lib/modules/

But without this command, I cannot update kernel modules,
what should I do next?

You might want to look at these, which apply to both cross compile and native compile. Beware that you can normally install kernels and modules without flashing (also, they were written for older hardware and system releases, but still apply):

Note that you can name an alternate output location for modules. If you’ve propagated the configuration (either by building the Image target or modules_prepare target), then you can accumulate all the modules in that empty directory. An example build script (native compile):

# --- Setting Up: -------------------------------------------------------
# DO NOT BUILD AS ROOT/SUDO!!! You might need to install source code as root/sudo.
mkdir -p "${HOME}/build/kernel"
mkdir -p "${HOME}/build/modules"
mkdir -p "${HOME}/build/firmware"

export TOP="/usr/src/sources/kernel/kernel-4.9"
export TEGRA_KERNEL_OUT="${HOME}/build/kernel"
export TEGRA_MODULES_OUT="${HOME}/build/modules"
export TEGRA_FIRMWARE_OUT="${HOME}/build/firmware"
export TEGRA_BUILD="${HOME}/build"

# --- Notes: ------------------------------------------------------------
# It is assumed kernel source is at "/usr/src/sources/kernel/kernel-4.9".
# Check if you have 6 CPU cores, e.g., via "htop".
# If you are missing cores, then experiment with "sudo nvpmodel -m 0, -m 1, and -m 2".
# Perhaps use "htop" to see core counts.
# Using "-j 6" in hints below because of assumption of 6 cores.
# -----------------------------------------------------------------------

# Compile commands start in $TOP, thus:
cd $TOP

# Do not forget to provide a starting configuration. Probably copy of "/proc/config.gz",
# to $TEGRA_KERNEL_OUT, but also perhaps via:
make O=$TEGRA_KERNEL_OUT nconfig

# If building the kernel Image:
make -j 6 O=$TEGRA_KERNEL_OUT Image

# If you did not build Image, but are building modules:
make -j 6 O=$TEGRA_KERNEL_OUT modules_prepare

# To build modules:
make -j 6 O=$TEGRA_KERNEL_OUT modules

# To build device tree content:
make -j 6 O=$TEGRA_KERNEL_OUT dtbs

# To put modules in "$TEGRA_MODULES_OUT":
make -j 6 O=$TEGRA_KERNEL_OUT INSTALL_MOD_PATH=$TEGRA_MODULES_OUT modules_install

# To put firmware and device trees in "$TEGRA_FIRMWARE_OUT":
make -j 6 O=$TEGRA_KERNEL_OUT INSTALL_FW_PATH=$TEGRA_FIRMWARE_OUT

One does not normally bother to build all of the targets, especially firmware. If all you are doing is adding a module, then you need to propagate configuration before build, but there is no need to build the main kernel should the base configuration start as a match to that (such as via tegra_defconfig plus CONFIG_LOCALVERSION, or via “/proc/config.gz” and CONFIG_LOCALVERSION), then you can build the modules and install them as a file copy.

rsync is a reasonable way to copy modules. Flashing really is not needed though.

If you do flash, then modules must go to a subdirectory of “Linux_for_Tegra/rootfs/lib/modules/$(uname -r)/kernel”. Note that this “uname -r” is from the Jetson, and not from the host PC. When you see the “-tegra” suffix on a kernel version like 5.10.104, it means CONFIG_LOCALVERSION was set to “-tegra”, and this is the default. This is what determines the output of uname -r, so if you compile a 5.10.104 kernel with CONFIG_LOCALVERSION of “-tegra”, then this is what that kernel would reply with from the uname -r command: 5.10.104-tegra.

Note that initrd flash does change things. Install will probably need modification as the extlinux.conf seems to get edits overwritten in some cases on the newer software.

Something I hope NVIDIA comments on is the source of any extlinux.conf overwrite on the Jetson itself after hand editing that file (not from flashing).

Hi, linuxdev,
Thank for your reply,

As you mentioned, flashing is not a necessary operation, and I agree with that. However, could you please tell me how can I update kernel modules separately in the 5.3.1 SDK?

What’s more, I have success update kernel and dts with the copy command:

cp xx /boot/Image
cp xx /boot/dtb/kernel_tegra234-xxx.dtb

So, my compilation method is effective, but I don’t know how to update the modules.

This changes somewhat depending on if this is an eMMC model, versus an SD card model. But here is some starting background…

The operating system partition (Linux, the “APP” label) is the only partition which is not signed (for eMMC there are a lot of other partitions; on SD card models there is that content inside of QSPI memory). There are other partitions containing kernel and device tree content, all of which are signed and produced by flashing.

There is also the content in “/boot” of the Linux (“APP”/rootfs) partition. That content is not signed. SD card models have no ability to burn security fuses, but that other content is still signed, and in the case of security fuses not burned, there is a NULL key for the default. Only signed partitions are accepted, but content named in extlinux.conf for existence within “/boot” takes precedence if named (and that part is unsigned). Burning fuses means “/boot” content is rejected.

So naming device tree or kernel as a file via extlinux.conf means that content is what is used, and is simple to adjust versus using partitions.

This is complicated in some cases by the initrd. An initial ramdisk (initrd) is essentially a miniature filesystem in RAM, and more or less a complete Linux system. Unlike normal boot, it’s purpose is only to load certain kernel modules, like an adapter, and then to transfer to the actual root filesystem. The kernel itself is in the initrd, and a minimal list of modules are there (think of things needed for running within the initrd, plus things which will be needed in the future when pivoting to the actual root filesystem, e.g., a driver for some unusual filesystem format). I don’t know all of the details, but the initrd might contain some content which will overwrite the extlinux.conf.

Normally one would start by editing extlinux.conf, and instead of removing the old content, adding a second boot entry which points at the new kernel (if it’s just modules, then there is no need for this, you just copy modules). Then, if the alternate boot entry works, you’d simply edit the extlinux.conf to make this the default entry. You might or might not leave the old kernel and modules since it would serve as a backup, e.g., if a system update did something to overwrite the new configuration.

The combination of the kernel version and the “CONFIG_LOCALVERSION” (a text string) during compile of the kernel (the Image file…an integration of many kernel features) determines the output of the command “uname -r”. It is different from earlier Jetsons (there is a newer kernel), but an example would be “4.9.337-tegra”. In that example “4.9.337” is the kernel version, and the kernel was compiled with “CONFIG_LOCALVERSION=-tegra”. Loadable modules are searched for in a subdirectory of this:
/lib/modules/$(uname -r)/kernel
(in that example “/lib/modules/4.9.337-tegra/kernel”)

If you do not change the Image file (the integrated kernel), then modules will remain searched for in the same place. Assuming the module is compiled to match that’ kernel’s configuration, then you can load that module from that location with no further action (you would probably run “sudo depmod -a” to register the change or reboot or both).

During kernel build one has to configure prior to compiling. You would always start by matching the existing kernel’s configuration, including CONFIG_LOCALVERSION. This means any added modules will be compatible and the Image itself won’t need change. If you run into features which require changing the kernel Image itself (not all features can be a module), then you need to recompile all of these: The kernel Image, the modules, and a new uname -r via CONFIG_LOCALVERSION.

If you were to add a completely new kernel Image file, then I’d recommend leaving the old one there, and adding a new boot entry instead of replacing the old one (except if you are confident this new kernel will boot…flashing as a means of recovery is much more problematic compared to picking a different boot entry to the old kernel).

An example would be the rename the new Image to Image-custom, and placing it at “/boot/Image-custom”. The new “CONFIG_LOCALVERSION” could be “-custom”. When that kernel runs, it will look for modules at (it won’t be 4.9.337, but I’m using that as an example):
/lib/modules/4.9.337-custom/kernel

In that case you would copy or install all modules as a complete tree of modules at that location.

rsync is a good way to copy to that location. Using an SD card or USB thumb drive, if available, is also a way to copy this to the Jetson, and then use sudo to recursively copy this at the right location.

UEFI is a bit different on the newer Jetsons. I’ve seen some people editing extlinux.conf and having the initrd overwrite their edits. I have not tried this myself on the Orin (I don’t have an NX or Nano Orin). Maybe someone from NVIDIA can comment on where to edit extlinux.conf such that alternate entries won’t get overwritten. Even so, if you use a different boot entry, and if the Image file is renamed, it wouldn’t harm anything…it’d just boot to the original entry.

So the question comes down to this:

  • Did you use the same CONFIG_LOCALVERSION (“-tegra”)?
  • Are you adding a module, or did you have to change the original configuration for items which cannot be made as a module?
  • A restatement of the second point: Did you start by matching the original kernel configuration, which means using either “/proc/config.gz” (after decompressing and renaming “.config”), or use the build target “tegra_defconfig” (this is what stock systems ship with)?

The above changes the answer to installing. Hopefully the Image file has not changed. Then it is very simple.

Incidentally, if you build kernel modules, then the modules appear in some subdirectory. A contrived example is maybe you get “drivers/net/something.ko”. If your module directory is “/lib/modules/4.9.337-tegra/kernel”, then this means your new module would go here:
/lib/modules/4.9.337-tegra/kernel/drivers/net/something.ko
…the subdirectory of the driver produced in kernel build matches the subdirectory of the module’s base path of “/lib”.

You are using l4t_initrd_flash.sh, and I do not have an external device, so I have never experimented with this. It is quite possible the kernel and modules still go on eMMC…it just depends on whether this is a chain load or a pivot root (they reach the same boot via different paths). So it is important to know the above questions in the bullet points even if it is an initrd flash.

Once that is answered, someone familiar with Orin l4t_initrd_flash.sh could answer how to modify extlinux.conf for a second entry if this fails (failing would just use the original boot entry if you don’t overwrite the original Image file).

Thank you for help,
Now the problem is been solved!

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.