Yes, you could replace the kernel. Before doing so though, you should ask yourself if there is anything Grinch is configured for which is “non-standard”, and which it is needed? Sorry, this gets a bit long, but it might make your life easier in the long run. This includes steps to keep the Grinch kernel available in addition to the new kernel (you may want to remove Grinch at a later date, but not until you know the new kernel is sufficient). This goes with the assumption that you might have something developed or installed which you want to keep functional (if not, then you could perhaps just flash with the most recent release and ignore everything which follows…let me know if you just want to flash).
Note also that before you go about major changes, if there is some valuable work installed, that you could also clone the TK1 as additional backup before you start making changes.
History and trivia (optional, just for fun, explains how Grinch was different from the production kernel): Long ago (I think it was back in 2013) the TK1 was the first of the GPU-enabled embedded systems, and although other Tegra devices had been running for a long time on Linux, this was the first time that NVIDIA was selling such devices directly to the public (NVIDIA had only made reference platforms for third party partners prior to that…I think the TK1 reference accidentally turned out to be so popular with end users it actually created what you see today as NVIDIA’s publicly sold embedded systems for the average person). This was also the first Tegra device with a GPU. There were all kinds of drivers and kernel support which people were finding they needed, e.g., some particular camera driver or filesystem type, and they had to be back-ported from a newer kernel to the current kernel. This was done by Santyago (he did some amazing work!), and intended for L4T R19.x users (this was probably the single most successful/popular third party contribution ever). Later on much of this was made available by default (in L4T R21.x) due to a newer kernel and much (not all) of the back-port content was no longer needed. See the URL for a list of features back-ported.
Your TK1 is probably using L4T R21.x (I hope so…R19.x is astonishingly old). See “head -n 1 /etc/nv_tegra_release
”. This largely does not need a Grinch back port. However, it does not mean that a feature you wanted was necessarily enabled by default (you might need to enable something prior to build). In a few cases Grinch would still be required. You need to know the L4T release in order to download the right kernel source version (which can then be configured, and you may at times want to look at the Grinch config while figuring out some configuration issue).
Note that the file “/proc/config.gz
” is not a real file, and exists only in RAM. This is a reflection of the running system’s config at the time of compile (with one exception, the value of “CONFIG_LOCALVERSION
”). Unlike the kernel build command “make tegra_defconfig
”, this is a guaranteed exact match to what you are actually running (once “CONFIG_LOCALVERSION
” is updated). You will want to save a copy of config.gz
for future reference even when the Jetson is not running that kernel. Save a copy of this somewhere safe with name “config-grinch-21.3.4.gz
” (save uname -r
as part of the config name…the base version 3.10.40
is removed, and the suffix of the rest of uname -r
is included…which also happens to be the CONFIG_LOCALVERSION
value at the time the kernel was built).
Although you are not replacing the Grinch kernel, save this somewhere safe for later use as well (something could go wrong). Name it like the config file. The kernel is probably a zImage format, and would be in “/boot
”. Save a copy of this zImage (adjust if not “z
” prefix) as “zImage-grinch-21.3.4
”. You could make an archive directory on your host PC named “3.10.40
”, and add the zImage and config.gz there (with the uname -r
built in to the file names). If you have these saved, then it is simple to add them back in. Technically, you could also save a recursive copy of everything in “/lib/modules/3.10.40-grinch-21.3.4/
” in your archive directory as well (a subdirectory of your “3.10.40/
” named “modules/3.10.40-grinch-21.3.4/
”).
Note that in 32-bit days a zImage
was always used. This is a smaller byte size than is Image
, and is compressed. However, the bootloader remained 32-bit even when the 64-bit TX1 came out, and the compressed zImage
began to be used as Image
instead. This seems to have been done because it was possible the decompression software in the bootloader could not handle a 64-bit address space. Whenever you build a zImage
, you also build Image
, which is then compressed to become zImage
. For the TK1 you can always use the zImage
.
FYI, when you build a kernel the uname -r
is a combination of the base kernel release version and the CONFIG_LOCALVERSION
as the suffix. Modules are searched for by that kernel at “/lib/modules/$(uname -r)/
”. If modules are to be found by the kernel as it loads, then uname -r
and CONFIG_LOCALVERSION
become important.
A combination of the config and “uname -r
” and the source code implies the ability to build an exact match at a later time should you lose something. Any modification you ever make to a kernel will most likely start with an exact match to the running kernel, and then edits will be made to the configuration which was originally an exact match. If the new kernel works as intended, then you’d save a safe copy somewhere of the new config.gz
(along with its “uname -r
”). The cycle can then start again where you start with an exact match and easily make edits for something new.
When switching to the “regular” (non-Grinch) kernel be sure to keep the Grinch kernel in place, and simply add your new kernel as a second entry in extlinux.conf
without removing the Grinch kernel (I’m not sure, but at that time extlinux.conf
might have still been located in “/boot/extlinux.conf
” instead of “/boot/extlinux/extlinux.conf
”).
Why replace the old working kernel before you know the new kernel works when you can have both and pick between them? The serial console allows you to pick which kernel to boot while you test things (there is a very short moment during boot where you can hit a key in serial console and pick which kernel entry to boot with, else it will boot a default). Do you have serial console available? This is extremely valuable when changing kernels in case something goes wrong.
Here is the URL which has the complete historic listing of releases (you might need to go there, log in, and go there again if forwarding does not work):
https://developer.nvidia.com/embedded/linux-tegra-archive
Because of your “uname -r
” I am going to pretend your L4T release is R21.3.4 (however, be certain to examine “head -n 1 /etc/nv_tegra_release
” to know for certain). Substitute if your version differs. R21.3.4 is a patch release to R21.3, and so the L4T R21.3 URL is here:
https://developer.nvidia.com/linux-tegra-r213
(note that if you just flash you could go to release R21.8…this is the final version published for the TK1 prior to its end of life for new feature development…everything went 64-bit after that)
There is a “Documentation” link there telling how to cross-compile a kernel. One difficulty you might run into is an actual need to downgrade your host o/s to Ubuntu 14.04 or 16.04, or to otherwise have cross tools of a sufficiently old version that kernel build works. Natively compiling on the TK1 most likely avoids that problem since it is already that old.
The “driver package” is the flash software, the “sample file system” is what an image is created from after adding some NVIDIA-specific drivers. There are also a set of “source packages”, and the “kernel sources” will be what you are interested in. Assuming building directly on the TK1 you probably won’t need anything extra for the build, except perhaps “sudo apt-get install libncurses5-dev
” (which is used for the menu based editor of kernel configuration).
The download provides “kernel_src.tbz2
”. Assuming you have enough disk space you can unpack this in any new empty directory. If not enough space, then you could mount an SD card somewhere, and unpack to the SD card mount point. Unpack produces subdirectory “kernel/
”.
You will want to keep that location clean, and so create two empty subdirectories for intermediate work. I will assume that you unpacked the kernel source at “/usr/local/src
”, but it could be some other preferred location. This produces “/usr/local/src/kernel
” (I will refer to this as the TOP
directory). Two example empty build locations would be constructed like this (I am assuming in the home directory, but this could also be on an SD card mount if low on space):
# Make empty directories:
sudo mkdir /usr/local/src
sudo mkdir /usr/local/src/kernel
mkdir ~/kernel_out
mkdir ~/modules_out
# Set environment variables for ease of use:
# TOP:
cd /usr/local/src/kernel
export TOP=`pwd`
# Verify:
echo $TOP
# TEGRA_KERNEL_OUT:
cd ~/kernel_out
export TEGRA_KERNEL_OUT=`pwd`
# Verify:
echo $TEGRA_KERNEL_OUT
# INSTALL_MOD_PATH:
cd ~/modules_out
export INSTALL_MOD_PATH=`pwd`
# Unpack kernel source:
cd /usr/local/src
sudo tar xvfj /where/ever/it/is/kernel_src.tbz2
# Verify content, "`ls`" will show files and not an empty location:
cd $TOP
ls
# NOTE: The TK1 SoC is the 12x series, and the SoC specific to the TK1
# reference board is the 124. The following reference to "tegra12" is a
# reference to the the TK1 series of devices.
#
# Note that defconfig would not be needed if you had the config.gz from the original
# kernel...the Grinch config.gz cannot be used here since it is a different kernel source.
# Start with the defconfig:
make O=$TEGRA_KERNEL_OUT tegra12_defconfig
# Assuming you have installed the earlier mentioned `ncurses5-dev`,
# "`sudo apt-get install libncurses5-dev`", then edits can be made:
make O=$TEGRA_KERNEL_OUT nconfig
# The only edit we will make is to CONFIG_LOCALVERSION. Note nconfig shows a
# hot key list for functions at the bottom. You can "search" for "localversion". Then
# set to "-tegra", which is what "uname -r" would use for a default kernel.
# Save and exit from nconfig. Verify the change:
grep CONFIG_LOCALVERSION $TEGRA_KERNEL_OUT/.config
# Build zImage:
make -j 4 O=$TEGRA_KERNEL_OUT zImage
# Build modules:
make -j 4 O=$TEGRA_KERNEL_OUT modules
# Install modules to alternate path:
make O=$TEGRA_KERNEL_OUT modules_install INSTALL_MOD_PATH=$TEGRA_MODULES_OUT
At this point you should be able to find zImage
:
find $TEGRA_KERNEL_OUT -name zImage
You should be able to see an entire new set of kernel modules named after the base kernel version and “-tegra
”. Make sure there is no “+
” on the end of the following location (this can be fixed if it is there):
cd $TEGRA_MODULES_OUT
cd lib/modules
ls
# You should see subdirectory "3.10.40-tegra" if the base version is "3.10.40", and if
# CONFIG_LOCAVERSION is "-tegra".
Assuming all went well, then you can copy the zImage to “/boot/zImage-3.10.40-tegra
”. Note that I named the zImage after the “uname -r
” so it would not collide with the other kernel.
Technically, we could have directly installed modules. Had we not used “INSTALL_MOD_PATH
” during “modules_install
”, then the final install location would have been directly created. You can do this now if you want, but it is important to verify first there is no “+
” on the end of the directory name. To install modules:
cd $TOP
make O=$TEGRA_KERNEL_OUT modules_install
This is equivalent to recursively copying the “3.10.40-tegra/
” subdirectory of “$TEGRA_MODULES_OUT/lib/modules/3.10.40-tegra/
” to “/lib/modules/
” without the “$TEGRA_MODULES_OUT
” prefix.
If you see a “+
” on the end of that directory, then you’ll have to make an adjustment and build again, or else make adjustments to the actual install procedure.
Assuming no adjustments are needed, you would then edit “extlinux.conf
” (in this early release it might be at either of “/boot/extlinux.conf
” or “/boot/extlinux/extlinux.conf
”. The existing extlinux.conf
will have a Grinch entry, and we will merely supplement that entry instead of replacing the entry. The Grinch entry might look something like this, and will be copy and pasted, followed by editing for the new entry (the entry might differ slightly, I am just illustrating):
LABEL grinch
MENU LABEL primary kernel
LINUX /boot/zImage-3.10.40-grinch-21.3.4
FDT /boot/tegra124-jetson_tk1-pm375-000-c00-00.dtb
APPEND console=ttyS0,115200n8 console=tty1 no_console_suspend=1 lp0_vec=2064@0xf46ff000 mem=2015M@2048M memtype=255 ddr_die=2048M@2048M section=256M pmuboard=0x0177:0x0000:0x02:0x43:0x00 tsec=32M@3913M otf_key=c75e5bb91eb3bd947560357b64422f85 usbcore.old_scheme_first=1 core_edp_mv=1150 core_edp_ma=4000 tegraid=40.1.1.0.0 debug_uartport=lsport,3 power_supply=Adapter audio_codec=rt5640 modem_id=0 android.kerneltype=normal fbcon=map:1 commchip_id=0 usb_port_owner_info=2 lane_owner_info=6 emc_max_dvfs=0 touch_id=0@0 board_info=0x0177:0x0000:0x02:0x43:0x00 net.ifnames=0 root=/dev/mmcblk0p1 rw rootwait tegraboot=sdmmc gpt
You would add a blank line following this, and paste a copy of the Grinch entry. Then edit the new entry to reflect some new names and labels:
LABEL notgrinch
MENU LABEL original kernel
LINUX /boot/zImage-3.10.40-tegra
FDT /boot/tegra124-jetson_tk1-pm375-000-c00-00.dtb
APPEND console=ttyS0,115200n8 console=tty1 no_console_suspend=1 lp0_vec=2064@0xf46ff000 mem=2015M@2048M memtype=255 ddr_die=2048M@2048M section=256M pmuboard=0x0177:0x0000:0x02:0x43:0x00 tsec=32M@3913M otf_key=c75e5bb91eb3bd947560357b64422f85 usbcore.old_scheme_first=1 core_edp_mv=1150 core_edp_ma=4000 tegraid=40.1.1.0.0 debug_uartport=lsport,3 power_supply=Adapter audio_codec=rt5640 modem_id=0 android.kerne3.10.40-grinch-21.3.4ltype=normal fbcon=map:1 commchip_id=0 usb_port_owner_info=2 lane_owner_info=6 emc_max_dvfs=0 touch_id=0@0 board_info=0x0177:0x0000:0x02:0x43:0x00 net.ifnames=0 root=/dev/mmcblk0p1 rw rootwait tegraboot=sdmmc gpt
The part which changed is the “LABEL
”, and the name of the “LINUX
” line naming the kernel file name. At the top of extlinux.conf
there is a “DEFAULT
” name which corresponds to a “LABEL
”. If you have serial console and can manually pick an entry, then do not change “DEFAULT
” to “notgrinch
” until you’ve tested that this will work for you…simply use serial console instead to pick entry “2” with label “original kernel
”.
If you do not have a serial console available, then you can change the “DEFAULT
” from whatever it is which points to the Grinch kernel, to instead be “DEFAULT notgrinch
”. If things go bad and it won’t boot, then you could use a serial console (even if you have to order one) and recover directly without difficulty simply by picking the Grinch kernel during boot. Otherwise you would need to flash again (perhaps with a clone to cheat and make it faster/easier).
A particular note is needed about the “FDT
” entry. I am just listing the one which is stock for an R21.6 TK1. The device tree file could have changed with Grinch. Likely the non-Grinch device tree name is the same between R21.3 and R21.6, which is “/boot/tegra124-jetson_tk1-pm375-000-c00-00.dtb
”. The original addition of Grinch probably did not remove “/boot/tegra124-jetson_tk1-pm375-000-c00-00.dtb
”, and that file will likely still be there even if the Grinch tree differs. You would want to edit FDT
of the new kernel to point at the one which was intended for the non-Grinch kernel. If you don’t have this, then it is possible the Grinch device tree will work, but there is no guarantee.
If you wanted to back up the Grinch kernel to your host PC, then you should probably back up:
- The relevant
zImage
.
- The relevant
FDT
entry device tree file.
- The
uname -r
the kernel uses.
- The recursive content for modules at “
/lib/modules/$(uname -r)/
”
- The
extlinux.conf
entry.
This is a lot of information for something considered obsolete, but it might be useful for people in the future. If you don’t have something important to save, then you might consider simply flashing R21.8. If you want to safely flash R21.8, but have a way out if it won’t work for you, then you could clone your R21.3.4 first.