Boot Linux Kernel via TFTP-Free Embedded Linux Course online

PREV_LEC NEXT_LEC

Boot Linux Kernel via TFTP
A practical, board-agnostic walkthrough for embedded Linux developers using U-Boot

If you’ve been following this free embedded Linux course, in the previous lecture we set up an NFS root filesystem so you could edit files on your host and see the changes instantly on the target. But there’s still one manual step slowing you down: copying a new kernel image to an SD card every time you rebuild it. This lecture closes that gap. We’ll TFTP boot a Linux kernel straight from your development host into U-Boot’s memory, over the network, with zero SD card re-flashing. If you’re building a free linux kernel development course workflow around fast iteration, this is the single change that saves the most time per day.

free linux kernel development course
free linux device drivers course
free embedded linux course
free embedded systems course
TFTP boot Linux kernel
U-Boot netboot

What You Will Learn

  • How TFTP fits into an embedded Linux development workflow, and why it beats SD-card reflashing
  • How to set up a TFTP server on your Linux host in minutes
  • How to TFTP boot a Linux kernel and device tree from U-Boot, on both 32-bit and 64-bit ARM targets
  • How to combine a TFTP-loaded kernel with the NFS root filesystem from the previous lecture
  • How to read and fix the most common TFTP boot failure, the dreaded repeating “T” timeout
  • Security and performance considerations before you ever ship a TFTP-enabled bootloader

Prerequisites

  • A board running U-Boot with a working Ethernet connection to your development host
  • The NFS root filesystem staging area built in the previous lecture of this free linux device drivers course
  • A built kernel image and device tree blob for your target
  • Basic comfort with Linux networking (static IPs, subnets)

Why TFTP Boot a Linux Kernel Instead of Flashing

Every time you change a driver, rebuild the kernel, and want to test it, flashing that image onto an SD card and reinserting it into the board is slow and it wears out the card over many cycles. When you TFTP boot a Linux kernel, U-Boot instead pulls the kernel and device tree directly from your host’s RAM over Ethernet into the board’s RAM, in a few seconds, every single time. Paired with an NFS root filesystem, you get a fully network-served development loop: rebuild the kernel, rebuild a module, reboot the board, and none of it ever touches removable storage.

This is the standard workflow used by kernel and driver engineers, and it’s exactly the kind of practice this free linux kernel development course focuses on: fast, repeatable iteration over ad-hoc manual steps.

Setting Up a TFTP Server on Your Host

Modern Debian-based distributions make this simple with tftpd-hpa. Install and configure it to serve a directory you control:

$ sudo apt install tftpd-hpa
$ sudo mkdir -p /srv/tftp
$ sudo nano /etc/default/tftpd-hpa

Set the serve directory and options inside that file:

TFTP_USERNAME="tftp"
TFTP_DIRECTORY="/srv/tftp"
TFTP_ADDRESS=":69"
TFTP_OPTIONS="--secure"

Restart the service and confirm it’s active before moving on — a huge fraction of TFTP boot failures trace back to this one step being skipped:

$ sudo systemctl restart tftpd-hpa
$ sudo systemctl status tftpd-hpa

Copy your freshly built kernel image and device tree into the serve directory:

$ cp arch/arm64/boot/Image /srv/tftp/
$ cp arch/arm64/boot/dts/vendor/my-board.dtb /srv/tftp/
TFTP Boot Data Flow
Dev Host (TFTP server, /srv/tftp)
|
| Ethernet
v
Target Board (U-Boot)
1. dhcp / setenv ipaddr, serverip
2. tftpboot -> Image (into RAM)
3. tftpboot -> my-board.dtb (into RAM)
4. booti / bootz (kernel + dtb from RAM)
|
v
Linux kernel boots, mounts NFS root over the same link

Configuring U-Boot Network Variables

On the target, drop into the U-Boot prompt and either use DHCP or set static addressing. DHCP is the quicker path when your lab network already hands out leases:

=> dhcp

If you prefer fixed addressing, which is more predictable for a dedicated bench setup, set it manually:

=> setenv ipaddr 10.0.0.20
=> setenv serverip 10.0.0.10
=> saveenv

Calling saveenv here matters — without it, every one of these variables resets the next time the board power-cycles, and you’ll be retyping them constantly.

TFTP Boot: Loading the Kernel and Device Tree

With networking configured, pull the kernel image and device tree into RAM at addresses appropriate for your SoC’s memory map (check your board’s documentation — these examples use generic, non-conflicting offsets):

=> tftpboot 0x82000000 Image
=> tftpboot 0x83000000 my-board.dtb

Then point the kernel command line at the NFS root filesystem you built in the previous lecture, and boot:

=> setenv bootargs console=ttyS0,115200 root=/dev/nfs rw 
   nfsroot=10.0.0.10:/srv/nfsroot ip=10.0.0.20:10.0.0.10::255.255.255.0
=> booti 0x82000000 - 0x83000000

On a 32-bit ARM target using the older zImage format, swap booti for bootz, with a compressed image path instead:

=> tftpboot 0x82000000 zImage
=> tftpboot 0x83000000 my-board.dtb
=> bootz 0x82000000 - 0x83000000

Reading a Successful TFTP Boot Log

A clean TFTP boot log looks like this — note the transfer completes and hands control straight to the kernel:

=> tftpboot 0x82000000 Image
eth0: link up, 1000Mbps full-duplex
Using ethernet@ff0e0000 device
TFTP from server 10.0.0.10; our IP address is 10.0.0.20
Filename 'Image'.
Load address: 0x82000000
Loading: #################################################
         2.1 MiB/s
done
Bytes transferred = 24805376 (17a7c00 hex)

Troubleshooting a Failed TFTP Boot

The most common failure when you TFTP boot a Linux kernel shows up as a repeating string of the letter T instead of a progress bar:

=> tftpboot 0x82000000 Image
Using ethernet@ff0e0000 device
TFTP from server 10.0.0.10; our IP address is 10.0.0.20
Filename 'Image'.
Load address: 0x82000000
Loading: T T T T T T

Each T is a retransmitted request timing out. Work through these in order:

  • Wrong server IP. Double-check serverip matches your host’s actual address on the interface connected to the board, not a VPN or Wi-Fi interface.
  • TFTP daemon not running. Re-check with systemctl status tftpd-hpa; restart it if it’s inactive or failed.
  • Firewall blocking UDP port 69. Most host firewalls block TFTP by default. On a UFW-managed host: sudo ufw allow 69/udp.
  • File not present or wrong permissions in the TFTP serve directory — confirm the filename in the log matches exactly, including case.
  • Board and host on different subnets with no route between them — for a lab bench, a direct switch or crossover link avoids this entirely.

Common Mistakes

Mistake Effect Fix
Kernel and DTB loaded at overlapping addresses Silent corruption, kernel fails to boot or panics early Leave generous spacing between load addresses; check your SoC’s memory map
Forgetting saveenv Network settings vanish on reboot Always saveenv after setting ipaddr/serverip
Using zImage boot command with an Image file, or vice versa U-Boot reports an invalid image format Match bootz to zImage, booti to Image
Testing over a busy shared network Intermittent, hard-to-reproduce timeouts Use a dedicated link or switch for bench TFTP traffic

Best Practices

  • Wrap your tftpboot and bootargs sequence into a U-Boot boot script (boot.scr) once it’s stable, so a bare run netboot reproduces the exact sequence every time.
  • Keep your NFS root and TFTP server directories on the same host for a single-machine dev loop.
  • Version your Image/zImage and .dtb filenames if you’re regularly switching between kernel branches, to avoid loading a stale build by accident.

Security Considerations

TFTP has no authentication and no encryption — anyone on the same network segment can request any file your server exposes. This is acceptable for an isolated bench or lab network, but a TFTP-enabled boot path must never be left reachable on a production network or shipped in a released product. Restrict the TFTP server to a dedicated development VLAN, and disable network boot in U-Boot entirely (or lock the boot menu) before deployment.

Performance Considerations

TFTP is noticeably slower than reading from local eMMC or NVMe, since every packet is acknowledged individually over UDP. For a development loop where you’re loading a kernel dozens of times a day, that few extra seconds still beats physically reflashing an SD card — but for anything beyond a bench setup, this is strictly a development-time tool, not a production boot mechanism.

Summary and Key Takeaways

  • TFTP boot lets U-Boot pull a kernel and device tree over Ethernet, skipping SD card reflashing entirely.
  • Combined with NFS root, it gives you a fully network-served embedded Linux development loop.
  • A repeating “T” in the load progress almost always means server IP, daemon status, or firewall rules.
  • Never leave a TFTP-enabled boot path reachable outside an isolated development network.

Mastering this workflow is one of the highest-leverage skills in this free linux kernel development course, because it directly shortens every single build-test cycle you’ll run for the rest of your embedded Linux work.

Frequently Asked Questions

What is TFTP boot in U-Boot?

It’s the process where U-Boot uses the Trivial File Transfer Protocol to fetch a kernel image and device tree from a server on the network directly into the board’s RAM, instead of reading them from local storage.

Why does my TFTP boot show a row of “T” characters?

Each T represents a timed-out retransmission. It almost always means the TFTP daemon isn’t running, the server IP is wrong, or a firewall is blocking UDP port 69.

Do I need DHCP to TFTP boot a Linux kernel?

No. You can use DHCP for convenience, or set ipaddr and serverip manually for a predictable static bench setup.

What’s the difference between bootz and booti?

bootz boots a compressed zImage, typically used on 32-bit ARM targets. booti boots the uncompressed Image format used on modern 64-bit ARM (arm64) kernels.

Is TFTP boot safe to leave enabled in production?

No. TFTP has no authentication or encryption. It should be restricted to an isolated lab network and disabled entirely before a product ships.

Can I combine TFTP boot with an NFS root filesystem?

Yes — this is the standard embedded Linux development pattern. The kernel and device tree load over TFTP, then the kernel mounts its root filesystem over NFS using the bootargs shown in this lecture.

Why should I use saveenv after setting ipaddr and serverip?

Without saveenv, U-Boot’s environment resets to defaults on the next power cycle, and you’ll have to retype your network settings every time you reboot the board.

Keep building your embedded Linux skills

This lecture is part of EmbeddedPathashala’s free embedded Linux course — follow along for the full free linux device drivers course and free linux kernel development course series.

PREV_LEC NEXT_LEC

2 Comments

Leave a Reply

Your email address will not be published. Required fields are marked *