free linux development course
free linux device drivers course
free linux kernel development course
u-boot load kernel image
Having a properly wrapped kernel image is only half the job — U-Boot still has to get those bytes off storage or
off the network and into a specific spot in RAM before it can boot anything. This lecture in our free
embedded Linux course covers the two most common paths every embedded engineer ends up using constantly
during bring-up: loading from an SD card, and loading over the network with TFTP.
What You Will Learn
- How U-Boot’s storage device drivers are addressed
- Loading a file from a FAT partition with fatload
- Setting up TFTP for fast network-based bring-up
- Choosing safe RAM addresses for loaded images
- Debugging failed or corrupted loads
Prerequisites
You should already have a mkimage-wrapped kernel image (uImage or FIT) from the previous lecture, and a board
with either an SD card slot or a working Ethernet port connected to your development network.
Loading From an SD Card
U-Boot talks to SD/eMMC hardware through its mmc driver, and to whatever filesystem lives on a
partition through commands like fatload (FAT) or ext4load (ext4). A typical sequence
starts by making sure U-Boot has actually noticed the card:
U-Boot# mmc rescan
This re-initializes the mmc driver — useful if a card was hot-inserted, or simply to confirm the interface is
alive before trying to read from it. Next, load the image itself:
U-Boot# fatload mmc 0:1 ${ep_kernel_addr} ep-uImage
reading ep-uImage
9842240 bytes read in 187 ms (50.2 MiB/s)
The general form of the command is:
fatload <interface> [<dev>:<part>] [<addr> [<filename> [<bytes> [<pos>]]]]
Here mmc is the interface, 0:1 means device 0 (the first mmc controller, counting from
zero) and partition 1 (the first partition, counting from one — the off-by-one between device and partition
numbering trips up almost everyone the first time). ${ep_kernel_addr} expands to a RAM address you
defined earlier as an environment variable, and the final argument is the filename to load.
Choosing a Safe Load Address
The address you load into has to satisfy two conditions: it must be RAM the SoC’s boot ROM and U-Boot itself
aren’t currently occupying, and it must not overlap the address the kernel will later be decompressed or relocated
to when it actually starts running. Getting this wrong is one of the most common causes of a board that loads a
file successfully but then hangs or resets during bootm/booti. Always check your SoC’s
memory map and U-Boot’s own relocation address (visible early in the boot log) before picking load addresses for
your own scripts.
Loading Over the Network With TFTP
During active bring-up, re-flashing an SD card every time you rebuild a kernel gets old fast. The Trivial
File Transfer Protocol (TFTP) lets U-Boot pull a file directly from your development machine over Ethernet
instead, which is dramatically faster to iterate with.
On the host side, install and start a TFTP server, then place files to serve inside its root directory (commonly
/srv/tftp or /var/lib/tftpboot depending on distro):
$ sudo apt install tftpd-hpa
$ sudo cp ep-uImage /srv/tftp/
$ sudo systemctl status tftpd-hpa
You’ll also need to allow inbound UDP port 69 through any firewall between your development machine and the
board. On the U-Boot side, set static IPs for both ends and pull the file:
U-Boot# setenv ipaddr 192.168.1.42
U-Boot# setenv serverip 192.168.1.10
U-Boot# tftp ${ep_kernel_addr} ep-uImage
link up on port 0, speed 1000, full duplex
Using ethernet@30bd0000 device
TFTP from server 192.168.1.10; our IP address is 192.168.1.42
Filename 'ep-uImage'.
Load address: 0x82000000
Loading: #################################### 47.1 MiB/s
done
Bytes transferred = 9842240 (963040 hex)
Once loaded, the same iminfo check from the previous lecture confirms the header and checksum are
intact regardless of which transport got the bytes there.
+—————–+ +—————–+
| FAT partition | | tftpd server |
| ep-uImage | | /srv/tftp/ |
+—————–+ +—————–+
| |
mmc rescan setenv serverip
fatload mmc 0:1 … tftp …
| |
+—————-+—————–+
v
U-Boot RAM at load address
|
v
iminfo check
Real-World Use Cases
- SD card loading is what production and field devices actually use, since it needs no development host present.
- TFTP loading is the default choice during active kernel/driver development, since a rebuild-and-reboot cycle can take seconds instead of minutes.
- Many teams configure
bootcmdto try network boot first with a short timeout, then fall back to SD card — giving fast iteration during bring-up without losing standalone boot capability.
Common Mistakes and Troubleshooting
| Symptom | Likely Cause | Fix |
|---|---|---|
| fatload reports “File not found” | Wrong device:partition, or file not actually on that partition | Double check with fatls mmc 0:1 to list the partition’s contents |
| TFTP times out | Firewall blocking UDP 69, or wrong serverip | Verify tftpd is running and reachable with a quick ping first |
| TFTP transfer very slow | Half-duplex link or 10/100 negotiation issue | Check the “link up” line in the output for speed/duplex |
| Load succeeds but iminfo checksum fails | Corrupted file on the server or SD card | Re-copy the source file and retry the transfer |
Best Practices
- Standardize your load addresses in environment variables (as in the previous lecture) rather than typing raw hex repeatedly.
- Use static IPs for TFTP bring-up — DHCP adds a layer of failure modes you don’t need while debugging.
- Always verify a load with
iminfobefore booting, especially over an unreliable network link. - Keep a known-good SD card image around as a fallback while iterating over TFTP.
Performance Considerations
TFTP throughput is bounded by your link speed and by the protocol’s simple, unencrypted, mostly single-stream
design — gigabit Ethernet links commonly achieve tens of MiB/s, which is more than adequate for kernel images in
the tens of megabytes. SD card read speed depends heavily on the card class and the SoC’s mmc controller clock
configuration; a fast UHS card is not automatically fast if the controller is left running at a conservative default
frequency.
Summary and Key Takeaways
mmc rescanplusfatloadreads a wrapped image from an SD card partition.- TFTP loading trades the need for physical media for network speed, ideal during active development.
- Load address selection must avoid U-Boot’s own RAM footprint and the kernel’s later relocation target.
iminfois the universal integrity check regardless of transport used to load the image.
Conclusion
With a verified image sitting in RAM, U-Boot is one step away from actually running it. On production hardware
that image often needs to live in NAND flash rather than an SD card, which is exactly what the next lecture in this
free linux device drivers course covers — programming and reading back images from raw NAND.
FAQ
Why does mmc use 0:1 instead of just a partition number?
The first number selects which mmc controller/device, since a board can have more than one, and the second
selects the partition on that device — the format is device:partition.
Is TFTP secure enough to use in production?
No, TFTP has no authentication or encryption, which is why it’s a development-time convenience and production
devices instead boot from onboard storage or use signed network boot protocols.
Can I load a file without knowing its exact size in advance?
Yes, both fatload and tftp report the actual number of bytes transferred after completion, and you don’t need to
specify a size up front for a normal file load.
What if my board has no Ethernet port?
Then TFTP loading isn’t available and SD card or USB mass storage loading becomes the primary bring-up path
instead.
Does the load address need to match the address used when the image was created with mkimage?
The load address baked into the image header should match where you actually load it, since some boot paths
rely on that header value; keeping your mkimage build and your fatload/tftp commands referencing the same
environment variable avoids this getting out of sync.
Continue the Free Embedded Linux Bootloader Course
