Roll Your Own Embedded Linux System with Buildroot

The time between getting a new piece of hardware and seeing a first shell prompt can be one of the most frustrating experiences for embedded Linux developers. Buildroot can help reduce your frustration.

It all started when I ordered an ARM-based development board for
my FemtoLinux project, which is a Linux flavor specifically designed
for ultra-small systems. Initially, I played with the idea of simply
using a Linksys WRT router supported by an OpenWrt open-source project
for development. But eventually, I decided that because it is a commercial
project and development time is important, I was going to spend an extra
$100–$200 for a real development board with official Linux support, which
would come with everything that an embedded Linux developer would need:
cross-compiler toolchain, Linux sources and
embedded Linux distribution (at least, that's what I thought I would be getting).
If you're on a budget and looking for a cheap embedded board for your hobby project,
using a Linksys WRT router is not such a bad idea.

Choosing the right embedded Linux development
board deserves an article of its own, but for now, suffice it to say that
when you decide to use WRT, you should be prepared to build your software
development environment yourself and expect to get support from the
community. With a commercial board, I was expecting to receive it from the
vendor, but I didn't. The vendor's idea of Linux support turned out to
be just a list of kernel patches, forcing me to evaluate, choose and configure
an embedded Linux development environment for this board by myself, which
turned out to be quite an interesting and educational experience.

Embedded Linux Distributions

First, let's start with some basic terminology. An embedded Linux
distribution is quite different from the PC distributions you are used
to, such as Ubuntu or Fedora Core. It typically includes at least the
following components:

Cross-compiler toolchain for your target architecture, which is at least
gcc, g++ and ld. It usually runs on one architecture, but produces
binaries for a different architecture—x86 and ARM, respectively, in my
case, hence the term cross-compiler toolchain.

Kernel sources with a BSP (Board Support Package) for your board.

Filesystem skeleton—that is, /bin, /etc with all the standard
configuration files, such as /etc/fstab, /etc/inittabe and so on.

Applications—init and shell as a bare minimum, but most people
will need more in order to do something useful.

Currently, the two most widely used embedded Linux distributions are
OpenEmbedded and Buildroot. This article is about Buildroot, as that's
the one I am most familiar with and naturally the one I used in my
project. Buildroot's biggest advantage is its simplicity and flexibility,
which are important if you are going to do some kernel hacking or
other low-level development. If, on the other hand, you are an embedded
application developer, OpenEmbedded certainly is a viable choice as well.

Buildroot

Even though you may not have heard of Buildroot before, it's actually
not a new project. It has been around for many years, most of the time
under the name of uClinux. Initially, uClinux was an effort to port the Linux
kernel to processors without an MMU, such as the Motorola MC68328. However,
it eventually expanded beyond that, adding support for more processors,
a binary format for MMU-less systems and more userland capabilities,
including a libc flavor specifically designed for low memory
systems—uClibc. Eventually, it evolved into one of the more-advanced
and easy-to-use embedded Linux distributions.

This is where the confusion started,
as people used the name uClinux to refer both to the MMU-less CPU
kernel support and the embedded distribution, which were two quite
different things. The fact that many MMU-less patches (the whole
armnommu architecture support, for instance) eventually were included
in the standard kernel tree added to the confusion as well. Finally,
the embedded Linux distribution part was split into a different project
called Buildroot. uClibc development continued separately, and the
parent uClinux Project somewhat lost its momentum.

From the Buildroot Web site: “Buildroot is a set of Makefiles and patches
that makes it easy to generate a cross-compilation toolchain and root
filesystem for your target Linux system using the uClibc C library.” This
is not entirely correct, as it also supports (to some extent, as you
will see later) other libc flavors, such as glibc. It works with many
embedded CPUs, including ARM, MIPS and PowerPC.

If you want to get started with Buildroot, download the tarball, extract
it and run make help from its root directory. If this all looks familiar
to you, wait till you run make menuconfig.

Figure 1. Buildroot Main Menu

As you already may have guessed, Buildroot uses the same Makefile
infrastructure as the Linux kernel to configure and build everything,
including applications and libraries. The usual sequence of commands is:

make clean
make menuconfig
make

The first one is important if you are going to change some configuration
parameters—incremental building may or may not work in this case.
Initially,
I was going to recommend that you start working with some default configuration,
by running, for instance, make
integrator926_defconfig, which should
configure Buildroot for the Integrator ARM reference board. However, it
turns out that as Buildroot development moved forward, most of the default
configurations somehow lagged behind and currently do not work out of
the box. I suggest you run make menuconfig, and choose the following
options manually:

Target architecture: arm.

Target Architecture Variant: arm926t.

Kernel: same version as Linux headers.

And, go over the other parameters and check for others that you may want or need to modify.
Be careful when you do so, and always save your latest working configuration
(the .config file). It is very easy to end up with a nonworking
configuration.

Buildroot configuration options can be divided roughly into hardware-,
build-process- and software-related, while software-related options can
be divided further into kernel, toolchain and packages.

Hardware options are the “Target Architecture” that defines your CPU core
(ARM, MIPS and so on). “Target Architecture Variant” defines the exact
CPU you are using, and “Target Options” defines board-related
parameters, such as UART baud rate and so on. You hopefully should know your
hardware parameters, and there is not much to add here, except that for the
ARM architecture, I suggest using EABI and making sure you use the
same ABI convention everywhere.

If you are running Buildroot for the first time, you probably should avoid
changing the “Build options”. These options probably are okay the way they
are; the only thing you may want to change is the “Number of jobs to
run simultaneously” if your build PC is a multicore system.
Also, choose “build packages with debugging symbols” if you
want to
debug some of the pre-installed applications.

Remember, in order to build the kernel and software packages,
Buildroot first needs to build the cross-compiler toolchain for your
hardware. The Toolchain menu allows you to choose the gcc version and
other toolchain-related parameters. The wrong toolchain configuration can
lead to some very weird errors, so be careful. By default, Buildroot
builds its own toolchain and works with uClibc. There is an option to
work with an external toolchain, which can be glibc-based, but that's
beyond the scope of this article, so you should set “Toolchain
type” to
“Buildroot toolchain”. You can change the gcc, binutils, uClibc and kernel
headers (but not the kernel itself) versions from this menu. You also
can decide to compile the C++ (g++) compiler and gdb support (gdbserver for the
target and gdb client for the host or a standalone gdb for the target),
which is probably something you are going to need. All the other options
are better left alone at this stage.

“Package selection for the target” is where you get to choose what software
components you want as part of your embedded filesystem image. This
is where you can experiment relatively freely—even if you select an
application that's not supported on your hardware or with the particular
Linux and gcc versions that you chose, it's easy to find the problematic
application and disable it.

First, there is BusyBox. It deserves an
article of its own, but basically, it's a collection of standard Linux
utilities (such as shell and init), optimized for low memory footprint
systems. You can start by creating a filesystem with just BusyBox.
It contains everything you need in order to boot and verify that your
system is working. Later, you can add more packages, ranging
from the MySQL or SQLite databases to the VLC and MPlayer media players,
as well as Perl, Python and many others.

The “Target filesystem options” allow you to choose the type of filesystem
image. Pretty much all the commonly used (in the embedded world) filesystems are
supported, including: cramfs, squashfs, jffs2, romfs and ext2.

If you just want to experiment or prefer to create the filesystem image
manually (if you are using some rare unsupported filesystem, such as
yaffs2), you can choose the “tar the root filesystem” option, which will
create a tar archive with your filesystem. For some unknown reason,
bootloader configuration also is found under this menu (only Das U-Boot
is supported for now), but I'll skip this one, assuming you have a
working bootloader already.

The last menu is “Kernel”, which is optional. In case you are
interested only in application development, choosing the right kernel headers
(see above) is enough. If you decide to modify the kernel, remember to
keep the kernel version and the kernel headers version (in the Toolchain menu)
in sync.

When you are finished, exit menuconfig, and run make. Buildroot
automatically will download everything it needs, compile it and
eventually create the filesystem image in the output/images/
directory. If you want to modify something in the filesystem image,
for example, to change the IP address of your system, you can modify
the filesystem skeleton directory tree, which is usually located in
target/generic/target_busybox_skeleton. Note that if you are not using
BusyBox, or if your hardware platform has its own filesystem tree skeleton,
this location can be different.

As Linux continues to play an ever increasing role in corporate data centers and institutions, ensuring the integrity and protection of these systems must be a priority. With 60% of the world's websites and an increasing share of organization's mission-critical workloads running on Linux, failing to stop malware and other advanced threats on Linux can increasingly impact an organization's reputation and bottom line.

Most companies incorporate backup procedures for critical data, which can be restored quickly if a loss occurs. However, fewer companies are prepared for catastrophic system failures, in which they lose all data, the entire operating system, applications, settings, patches and more, reducing their system(s) to “bare metal.” After all, before data can be restored to a system, there must be a system to restore it to.

In this one hour webinar, learn how to enhance your existing backup strategies for better disaster recovery preparedness using Storix System Backup Administrator (SBAdmin), a highly flexible bare-metal recovery solution for UNIX and Linux systems.