How to Buildroot Custom Board Support-Free Embedded Linux Course online

PREV_LEC | NEXT_LEC

Buildroot Custom Board Support

Boot your Buildroot image under QEMU, then create a real board support package for a new device

Chapter 6
Free Embedded Systems Course
~18 min read

In the previous lecture of this free linux device drivers course you configured and built a Buildroot image. A build you cannot boot is not very useful, so this lecture starts there — running that image under QEMU and reading the boot log like a working embedded engineer would. From there we go a step further and do the thing you will actually do on the job: create a brand-new board support package (BSP) so Buildroot can build for hardware it has never heard of, which is one of the most practical skills covered anywhere in this free embedded systems course.

Buildroot BSP free embedded systems course QEMU boot board defconfig free linux development course

What You Will Learn

Booting a Buildroot-built image under QEMU Reading a kernel boot log for the signals that matter Where board-specific files belong in a Buildroot tree Basing a new board on an existing close reference design Pinning and patching U-Boot for your own board

Prerequisites

This lecture continues directly from the previous one in this free linux kernel development course — you should already have a Buildroot checkout with a completed build under output/images/. You will also need qemu-system-arm installed on your host to boot the image.

Booting the Image Under QEMU

Buildroot’s QEMU-targeted defconfigs produce artifacts that map directly onto QEMU’s command-line flags: a kernel image, a device tree blob, and a root filesystem image. Boot them together like this:

qemu-system-arm -M vexpress-a9 -m 256 \
  -kernel output/images/zImage \
  -dtb output/images/vexpress-v2p-ca9.dtb \
  -drive file=output/images/rootfs.ext2,if=sd \
  -append "console=ttyAMA0,115200 root=/dev/mmcblk0" \
  -serial stdio -net nic,model=lan9118 -net user

A second, blank QEMU window opens alongside your terminal — that is the emulated framebuffer, and it stays black here because nothing writes to it in a minimal console-only image. Close it, or just type poweroff at the target’s shell prompt, when you are done. If that black window causes QEMU to hang or misbehave on your host, it is almost always an old QEMU/SCSI emulation issue — updating your host’s QEMU package resolves it.

What to Look for in the Boot Log
Booting Linux …………………. kernel has started executing Machine model: ………………… device tree was parsed correctly VFS: Mounted root (ext2 …) ……. rootfs image was found and is valid Starting mdev / udev …………… device node manager came up Starting network ………………. init scripts are running in order buildroot login: ………………. init reached a shell prompt — success

Log in as root with no password on the default QEMU configurations — this is intentionally insecure and exists purely for fast local development, never for anything resembling a shipped product.

From QEMU Reference Design to Real Hardware

Once you can boot a stock QEMU configuration, the natural next step in any free embedded systems course is bringing up a board Buildroot does not already know about. Buildroot gives you three well-defined places to put everything specific to your new board, so your customizations stay cleanly separated from Buildroot’s own source tree and survive a fresh checkout:

LocationPurpose
board/<org>/<device>/Patches, binary blobs, kernel/U-Boot config fragments, post-build/post-image scripts specific to this board
configs/<device>_defconfigThe board’s top-level Buildroot configuration, discoverable via make help
package/<org>/<package>/Any application packages that only make sense for this board

The fastest reliable way to bring up a new board is to base it on whichever existing supported board is architecturally closest, then diff away from there. Let’s create a fictional custom board, ep-relay, based on Buildroot’s BeagleBone support, since it targets a similar SoC family:

# Always start with a clean state when switching targets
make clean
make beaglebone_defconfig

# Create the directory where ep-relay's board-specific files will live
mkdir -p board/ep/ep-relay

Pinning and Patching U-Boot for a New Board

Chapter 3 of this course walked through building U-Boot by hand and patching it for a custom board. Buildroot lets you fold that same customization into the automated pipeline instead of doing it manually every time. Copy your board’s bootloader patch into its board directory, then point Buildroot’s U-Boot package at the exact upstream version and patch location through menuconfig:

cp ~/ep-relay-uboot-fixes.patch board/ep/ep-relay/

make menuconfig
# Bootloaders --->
#   U-Boot
#     U-Boot version: (custom git repository / tag, or a released version)
#     Custom U-Boot version: 2025.01
#     Additional patch directories: board/ep/ep-relay
#     Board defconfig name: ep-relay

Buildroot applies every patch in the directory you list, in filename order, before building U-Boot — so if you have more than one patch, prefix them with numbers (0001-..., 0002-...) to guarantee the order you intend. The “board defconfig name” field tells Buildroot’s U-Boot package which <name>_defconfig inside the U-Boot source tree to build with, which is a separate concept from Buildroot’s own top-level defconfig — do not confuse the two when you are debugging a bootloader that will not build.

# Save your work as a proper board defconfig so it is reproducible
make savedefconfig
cp defconfig configs/ep-relay_defconfig
make ep-relay_defconfig   # sanity check: reload it and confirm nothing was lost

Common Mistakes and Troubleshooting

  • Skipping make clean before switching boards: stale per-architecture toolchain artifacts from BeagleBone can leak into your ep-relay build and cause confusing link errors.
  • Confusing the Buildroot defconfig with the U-Boot defconfig: they are two different Kconfig trees with similarly-named files — a build failure inside the U-Boot package almost always means the wrong one was set.
  • Forgetting to number multiple patches: Buildroot applies patches in lexical filename order; unordered patches can apply cleanly but produce a subtly wrong result.
  • Assuming the QEMU black framebuffer window means the boot failed: check the serial console output in your terminal first, not the graphical window.
  • Not committing the board directory to version control: board files, patches, and the saved defconfig together are what make your BSP reproducible for a teammate.

Best Practices

  • Base a new board on the closest existing supported board rather than starting from a blank configuration — it dramatically reduces the number of things you need to debug from scratch.
  • Keep U-Boot and kernel version pins explicit in menuconfig rather than letting them float to “whatever the default was,” matching the same discipline you used pinning the Buildroot release itself.
  • Commit board/<org>/<device>/ and your saved defconfig together as a single reviewable unit whenever you add board support.

Performance and Security Considerations

Booting under QEMU during BSP development is significantly faster than round-tripping to real hardware for every change — save the real-hardware cycle for final validation once QEMU boots cleanly. On the security side, treat the default root-with-no-password QEMU configuration as a development-only convenience: before any board configuration ships, add a real root password or SSH key-based login, and audit which network services your _defconfig silently pulled in as package dependencies.

Summary and Key Takeaways

  • Buildroot’s QEMU images boot with a straightforward kernel + device tree + rootfs command line, and the boot log tells you exactly where a failure occurred.
  • New boards get their own directory under board/<org>/<device>/, their own configs/<device>_defconfig, and optionally their own packages.
  • Basing a new board on the closest existing supported board is the fastest reliable bring-up path.
  • U-Boot version and patches are configured per-board through menuconfig, mirroring the manual bootloader work from earlier in this course.
  • Always save and commit a defconfig — it is the artifact that makes your BSP reproducible.

With a booting image and a real custom board directory in place, you now have the full Buildroot workflow this free linux kernel development course set out to teach: pin a release, configure with Kconfig, build, boot, and extend to new hardware. The same three-directory pattern — board/, configs/, package/ — scales from a single QEMU experiment all the way to a shipped product line.

FAQ

Why does QEMU open a second black window?

That is the emulated graphics framebuffer. It stays black when the target never writes to it, which is normal for a minimal console-only image.

Can I use a real board immediately instead of QEMU?

Yes, but QEMU is strongly recommended first — it gives you a fast, hardware-independent way to confirm your configuration boots before you debug real-board specific issues like storage or clocking.

What is the difference between Buildroot’s top-level defconfig and U-Boot’s board defconfig?

Buildroot’s defconfig configures the overall build; U-Boot’s own board defconfig (set inside the Bootloaders menu) tells the U-Boot source tree itself which board configuration to compile. They are unrelated Kconfig trees that happen to use similar terminology.

Do I have to base a new board on an existing one?

No, but it is by far the fastest path. Starting completely from scratch means resolving toolchain, kernel, and bootloader configuration for genuinely new silicon with no reference point.

Where should board-specific patches live?

Under board/<org>/<device>/, referenced from the relevant package’s “additional patch directories” option in menuconfig.

Is the default root login safe to leave in a shipped product?

No. It exists purely for fast development iteration; production configurations should always add authentication before shipping.

Continue the Free Embedded Systems Course

Next: comparing Buildroot with Yocto for larger, multi-board products.

Next Lecture Browse the Full Course
PREV_LEC | NEXT_LEC

2 Comments

Leave a Reply

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