As an example here is the entry you will find in a newly flashed TK1 with R21.6:
LABEL primary
MENU LABEL primary kernel
LINUX /boot/zImage
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=0 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
Note that the “APPEND” key/value pair is one very long line…line breaks would break the file.
The “LINUX /boot/zImage” is the kernel which would load if this entry is picked. I could add this “nearly exact copy but with zImage change” to get a second entry which does everything the same other than using a new kernel:
LABEL custom
MENU LABEL custom kernel
LINUX /boot/zImage-custom
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=0 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
…for this to work I’d have to create file “/boot/zImage-custom” from some alternate kernel.
Because this would be a second entry, you would be able to pick “1” or “2” during boot, and if you did not pick before a timeout, then “1” would be used (“1” is the DEFAULT).
Note that “MENU LABEL” is something a human will see from a serial console while in U-Boot. The “LABEL” is what the actual boot loader uses.
During boot, in early U-Boot, you can hit any key at the right time and it will drop into the U-Boot shell. From there you could experiment with U-Boot commands (not what you want for this case, but for illustration you could run “help”). This is prior to kernel selection though, and you could continue boot with the “boot” command at the U-Boot prompt. A very short time later you would be offered a chance to pick entry 1 (“primary kernel”) or entry 2 (“custom kernel”). You might have to backspace to get rid of whatever character you used to halt boot there, but then a “2” would load zImage-custom.
If you like the result, then you could edit the “DEFAULT” key/value pair and change it from “primry” to “custom”…after that, unless you select an entry manually, boot will always use “custom”.
It isn’t recommended, but you could just change “DEFAULT” to custom without testing. If it breaks the system, then your only ways to fix it are to use a serial cable or to use a clone/edit/flash. That serial console is an extremely valuable and safe way to test kernels.
Here’s an example extlinux.conf I’d recommend everyone have if planning to experiment:
TIMEOUT 30
DEFAULT primary
MENU TITLE Jetson-TK1 eMMC boot options
LABEL primary
MENU LABEL primary kernel
LINUX /boot/zImage
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=0 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
LABEL <b>custom</b>
MENU LABEL <b>custom kernel</b>
LINUX /boot/zImage<b>-custom</b>
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=0 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
LABEL <b>sdcard</b>
MENU LABEL <b>SD Card primary</b>
LINUX /boot/zImage
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=0 lane_owner_info=6 emc_max_dvfs=0 touch_id=0@0 board_info=0x0177:0x0000:0x02:0x43:0x00 net.ifnames=0 <b>root=/dev/mmcblk1p1</b> rw rootwait tegraboot=sdmmc gpt
LABEL <b>sda1</b>
MENU LABEL <b>SDA1</b>
LINUX /boot/zImage
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=0 lane_owner_info=6 emc_max_dvfs=0 touch_id=0@0 board_info=0x0177:0x0000:0x02:0x43:0x00 net.ifnames=0 <b>root=/dev/sda1</b> rw rootwait tegraboot=sdmmc gpt
Note that the “root=/dev/something” is edited for sda1 or sdcard entries (you have to scroll over the “APPEND” key/value pair to see this). In every case there is a unique “LABEL” and a descriptive “MENU LABEL”. “DEFAULT” is the label which occurs if you don’t intervene during boot with a serial console. This above example leaves entries to boot to an SD card or the first GPT partition of a SATA device should you ever need it. There is no error in having this even if you don’t have a SATA or SD card rootfs because it won’t use this until you select it…but if you ever get in trouble having this before the trouble occurs can be a huge time saver in recovery or just quick rootfs testing.
About serial console: The 9-Pin D-sub connector has a terminal always connected to it as a simple string of bytes. A serial terminal program from another computer provides the display and keyboard software…none of which needs to survive on the Jetson for it to work since the PC is doing that work. Here are some examples of 9-Pin D-Sub to USB serial UARTs which use the FTDI chipset which would work:
https://www.newegg.com/Product/ProductList.aspx?Submit=ENE&N=100168426&IsNodeId=1&Description=db9&bop=And&SrchInDesc=ftdi&Page=1&PageSize=36&order=BESTMATCH