Over the last two lectures in this free linux device drivers course we copied a
board directory for our example EP-Falcon board and registered it in Kconfig. That’s enough to run
make ep_falcon_defconfig, but not yet enough to produce a correct binary — the copied
files still describe the reference board, not EP-Falcon. This lecture finishes the port: the four
files every board directory should contain, the linker script fix that trips up almost everyone,
and the per-board configuration header.
u-boot configuration header
free linux device drivers course
u-boot linker script
What You Will Learn
- The four standard files every U-Boot board directory should contain, and what each is for
- Why a copied board directory’s linker script needs a manual path fix
- How the per-board configuration header under
include/configsfits alongside
Kconfig - A full checklist for confirming a new board actually builds cleanly
Prerequisites
- elch3_20 — Porting U-Boot To New Boards
- elch3_21 — U-Boot Kconfig And Defconfig Files
The Four Files Every Board Directory Should Have
Continuing the EP-Falcon example, our board directory is
board/vendor/ep-falcon/. By convention it should contain four specific files, each with
a distinct job:
| File | Purpose |
|---|---|
Kconfig |
Board-local configuration options (SoC, board name, config-header name) |
MAINTAINERS |
Records who currently maintains this board’s support, if anyone |
Makefile |
Builds the board-specific object files into the image |
README |
Free-form notes: hardware variants covered, known quirks, bring-up tips |
Since EP-Falcon was copied from a reference board on the same SoC, all four files already exist —
they just still describe the reference board. Update MAINTAINERS and
README immediately, even before the code compiles, so nobody mistakes the copy for the
original.
Editing The Board’s Kconfig
Inside board/vendor/ep-falcon/Kconfig, the settings that matter are scoped under an
if TARGET_EP_FALCON block — the same TARGET_EP_FALCON symbol we defined in
the architecture Kconfig in the previous lecture:
if TARGET_EP_FALCON
config SYS_CPU
default "armv7"
config SYS_BOARD
default "ep-falcon"
config SYS_VENDOR
default "vendor"
config SYS_SOC
default "am62x"
config SYS_CONFIG_NAME
default "ep_falcon"
endif
Each of these settings selects a different piece of the build: SYS_CPU pulls in the
matching CPU-variant code under arch, SYS_SOC pulls in SoC-specific code,
SYS_BOARD tells the build system which board/ subdirectory to compile, and
SYS_CONFIG_NAME determines which header under include/configs supplies the
rest of the configuration — we come back to that header shortly.
The Linker Script Trap
This is the single most common mistake after copying a board directory: u-boot.lds,
the linker script, almost always has a hard-coded path back to the reference board it came from. If
you leave it untouched, your build silently links against the wrong board’s object file:
diff --git a/board/vendor/ep-falcon/u-boot.lds b/board/vendor/ep-falcon/u-boot.lds
--- a/board/vendor/ep-falcon/u-boot.lds
+++ b/board/vendor/ep-falcon/u-boot.lds
@@ -36,7 +36,7 @@ SECTIONS
*(.__image_copy_start)
*(.vectors)
CPUDIR/start.o (.text*)
- board/vendor/ep-refdesign/built-in.o (.text*)
+ board/vendor/ep-falcon/built-in.o (.text*)
*(.text*)
}
Because this reference only shows up once, deep in a linker script most people never open, it’s
easy to miss during a copy-and-rename port. Grep for the old board’s name across the whole new
directory as a final check before you trust a build:
$ grep -rn "ep-refdesign" board/vendor/ep-falcon/
The Per-Board Configuration Header
Kconfig now covers most settings, but SYS_CONFIG_NAME from the board’s Kconfig still
points at a header under include/configs — for EP-Falcon that’s
include/configs/ep_falcon.h — which supplies whatever hasn’t yet migrated to Kconfig on
this particular board. The header’s own format is documented in U-Boot’s top-level README. As with
the board directory, you start by copying the reference board’s header, then make targeted edits —
not a rewrite:
diff --git a/include/configs/ep_falcon.h b/include/configs/ep_falcon.h
--- a/include/configs/ep_falcon.h
+++ b/include/configs/ep_falcon.h
@@ -1,5 +1,5 @@
/*
- * ep_refdesign.h
+ * ep_falcon.h, based on ep_refdesign.h
*
* SPDX-License-Identifier: GPL-2.0+
*/
Keep this diff small on a first pass — resist the urge to also start tuning memory timings or
peripheral options in the same edit. Get a booting image from the minimally-changed header first,
then iterate.
Build And Sanity-Check Checklist
$ make ep_falcon_defconfig
$ make -j$(nproc) 2>&1 | tee build.log
$ grep -i "ep-refdesign" build.log # should return nothing
$ ls -la u-boot.bin MLO 2>/dev/null # confirm expected images exist
If the reference board’s name still appears anywhere in the successful build log or object
listing, stop and re-check the linker script and Makefile before flashing anything to hardware.
Common Mistakes And Troubleshooting
| Symptom | Likely Cause | Fix |
|---|---|---|
| Build succeeds but board doesn’t boot | Linker script still points at the reference board’s object file | Fix the hard-coded path in u-boot.lds as shown above |
Build fails: cannot find ep_falcon.h |
SYS_CONFIG_NAME doesn’t match the header’s actual filename |
Confirm the Kconfig default and the header filename are identical |
| MAINTAINERS/README still describe old board | Files copied but never updated | Update immediately after copying, before any code changes |
Best Practices
- Grep the new board directory for every occurrence of the old board’s name before your first
build — the linker script is rarely the only place it appears. - Make one class of change at a time: Kconfig registration, then linker script, then
configuration header — verify a clean build after each, not just at the end. - Update
MAINTAINERSandREADMEearly; they cost nothing and save the
next engineer real confusion.
Performance Considerations
SPL images are size-constrained by on-chip SRAM, so any configuration header setting you carry
over from a larger reference board — extra debug logging, unused command support — can push SPL over
its size budget. Trim aggressively for the SPL-scoped options once the board boots, rather than
carrying every setting from the reference design indefinitely.
Summary And Key Takeaways
- Every board directory should carry updated
Kconfig,MAINTAINERS,
Makefile, andREADMEfiles, not just copied code. - The linker script’s hard-coded reference to the old board is the most commonly missed edit in a
copy-based port. - The per-board header under
include/configsstill matters alongside Kconfig for
settings that haven’t migrated yet.
Conclusion
With the board directory’s four standard files updated, the linker script corrected, and the
configuration header renamed and adjusted, EP-Falcon is now a genuinely independent U-Boot port
rather than a mislabeled copy of its reference design. From here, the next steps are board-specific:
DRAM timing tuning, pin muxing, and peripheral bring-up — each worth its own dedicated lecture as we
continue this free embedded Linux course.
Frequently Asked Questions
Why does the linker script even hard-code a board path?
It has to reference the compiled board object file by path somewhere, and that path isn’t
automatically derived — it’s written explicitly when the board directory is first created.
Can I skip updating MAINTAINERS for an internal, unpublished board?
You can, but it’s still useful internally — it documents who owns the port for your own team,
independent of whether the board is ever upstreamed.
Do I need both a board Kconfig block and a configuration header?
Currently yes for most boards — Kconfig has absorbed most settings, but the header still covers
whatever hasn’t been migrated for that particular board or SoC family.
What’s the fastest way to catch a stale reference to the old board?
Grep the entire new board directory (and build log) for the old board’s name after every build —
it’s the single fastest sanity check.
Should I trim configuration header settings before or after first boot?
After — get a minimally-changed header booting first, then trim and tune once you have a working
baseline to compare against.
Continue The Free Embedded Linux Course
With EP-Falcon booting, we move next to device-tree-driven peripheral bring-up.
