Testing Your U-Boot Port
Free Embedded Linux Course — Chapter 3: All About Bootloaders
In the last few lectures of this free embedded Linux course we added a brand-new board directory, a defconfig, and a board header for our fictional EP-Falcon board. Files on disk are worthless until you prove they actually boot real hardware. This lecture closes that loop: we build U-Boot for EP-Falcon, write the images to an SD card, and read the boot log line by line so you know exactly what “it works” looks like — and what a broken port looks like too.
free linux device drivers course
free embedded systems course
free embedded linux course
u-boot testing
What You Will Learn
- How to select and build a U-Boot defconfig for a custom board
- How to write SPL and U-Boot proper images to an SD card correctly
- How to read a first boot log and confirm your port is sane
- Common build and boot failures in a free embedded linux device drivers course context, and how to fix them
Prerequisites
You should already have a cross toolchain installed, a board directory and defconfig for a custom board (as built earlier in this free embedded systems course), and an SD card reader. A little comfort with the Linux command line is assumed.
Selecting And Building The Defconfig
Every U-Boot port starts from a defconfig — a saved snapshot of Kconfig answers for one board. Selecting it seeds the build with sane defaults before you touch a single source file.
$ cd u-boot
$ export ARCH=arm
$ export CROSS_COMPILE=arm-linux-gnueabihf-
$ make ep_falcon_defconfig
$ make -j$(nproc)
On a modern U-Boot tree this produces at least three artifacts you care about: u-boot-spl.bin (the first-stage loader), u-boot.img (the wrapped second-stage image), and often a combined u-boot-sunxi-with-spl.bin-style image depending on the platform. For our EP-Falcon example we treat SPL and U-Boot proper as two separate files, which is the common case on TI, Rockchip, and Allwinner style SoCs.
defconfig ──► Kconfig .config ──► make -j
│
├──► u-boot-spl.bin (first stage, loaded by ROM)
└──► u-boot.img (second stage, loaded by SPL)
│
▼
SD card FAT / boot partition
Writing Images To The SD Card
Partition layout varies by SoC vendor, but a very common pattern is: SPL written at a fixed raw offset near the start of the card, and U-Boot proper placed either at another raw offset or inside a small FAT boot partition. Always check your SoC’s boot ROM documentation for the exact offset — guessing here is the single most common cause of a “dead” board.
# Identify the SD card device carefully before writing anything
$ lsblk
# Write SPL at the offset required by the EP-Falcon boot ROM (example: 8 KiB)
$ sudo dd if=u-boot-spl.bin of=/dev/sdX bs=512 seek=16 conv=fsync
# Write U-Boot proper at the next reserved offset (example: 512 KiB)
$ sudo dd if=u-boot.img of=/dev/sdX bs=512 seek=1024 conv=fsync
$ sync
Reading The First Boot Log
Connect a serial console at the baud rate your board header configured, insert the card, and power on. A healthy first boot on a fresh port looks roughly like this:
U-Boot SPL 2025.10 (Aug 12 2026 - 10:02:11)
Trying to boot from MMC1
U-Boot 2025.10 (Aug 12 2026 - 10:02:11 +0000)
CPU: EP-Falcon SoC rev 1.0
DRAM: 512 MiB
MMC: ep_falcon_mmc: 0
Loading Environment from FAT... OK
In: serial
Out: serial
Err: serial
Net: No ethernet found.
Hit any key to stop autoboot: 3
ep-falcon!>
Three lines tell you almost everything: the SPL banner confirms the ROM found and ran your first stage, the second U-Boot banner confirms SPL successfully handed off, and the custom prompt ep-falcon!> confirms your board header’s CONFIG_SYS_PROMPT is being picked up rather than a generic default.
Common Mistakes And Troubleshooting
| Symptom | Likely Cause | Fix |
|---|---|---|
| Nothing on serial at all | Wrong baud rate, or SPL never loaded | Check console config in board header; re-check SPL write offset |
| SPL banner prints, then hangs | U-Boot proper written at wrong offset, or DRAM init missing | Re-verify offsets against boot ROM docs; check SDRAM timing config |
| Boots but uses generic prompt | Board header not actually included by defconfig | Confirm CONFIG_SYS_BOARD and CONFIG_SYS_CONFIG_NAME match your files |
| Build fails with undefined reference | Board Kconfig missing a required symbol | Compare against a similar upstream board’s Kconfig entries |
Best Practices
- Change one thing at a time between boot attempts — combined changes make failures hard to isolate.
- Keep a known-good SD card image as a fallback while you experiment with a second card.
- Log every serial session to a file; scroll-back is not a substitute for a saved transcript.
Performance And Security Considerations
Build time drops significantly with -j$(nproc) parallel jobs on multi-core hosts. From a security standpoint, a bootloader that boots unconditionally to an interactive shell is convenient for bring-up but is also an open door — production images should disable the autoboot shell or gate it behind a password once the port is stable.
Summary And Key Takeaways
- A U-Boot port is only proven once it boots to a prompt on real hardware, not just when it compiles.
- SPL and U-Boot proper are written to specific offsets defined by the SoC boot ROM.
- A healthy boot log shows two distinct banners: SPL, then U-Boot proper.
Conclusion
Testing is where a board port stops being theory. Once you can reliably reproduce a clean boot log for EP-Falcon, you have a stable base to build on — and in the next lecture we will use that same base to explore U-Boot’s “Falcon mode,” a technique for skipping U-Boot proper entirely on production devices.
FAQ
Do I need a JTAG debugger to test a U-Boot port?
Not for basic testing. A serial console is enough to see boot logs; JTAG becomes useful only when SPL fails so early that nothing reaches the console.
Why does my board only show the SPL banner and nothing else?
This almost always means U-Boot proper was written at the wrong offset or the SPL cannot find it on the boot medium.
Can I test on QEMU before touching real hardware?
Yes, and it is good practice for the generic build steps, but board-specific offsets and boot ROM behaviour can only be validated on the actual SoC.
What baud rate should I use for the serial console?
Whatever your board header configured for CONFIG_BAUDRATE — 115200 is the common default, but always confirm against your own config.
Is dd safe for writing bootloader images?
Yes, provided you double-check the target device name first. Writing to the wrong device can silently corrupt your host’s own disks.
Continue The Free Embedded Linux Course
Next up: U-Boot Falcon mode, a technique for booting straight to a kernel.
