Raspberrypi and Buildroot - johnosbb/Automation GitHub Wiki

Buildroot Configuration

Buildroot is an invaluable open-source tool for embedded Linux development, streamlining the creation of highly customized and minimal Linux systems, perfect for resource-constrained devices like the Raspberry Pi. It achieves this by automating the entire build process, from fetching source code to compiling the cross-compilation toolchain, bootloader, Linux kernel, and ultimately generating a root filesystem image. For Raspberry Pi users, Buildroot offers "defconfigs" (default configurations) tailored for various models, such as raspberrypi_defconfig (for older models), raspberrypi3_defconfig, and raspberrypi5_defconfig. These defconfigs provide an excellent starting point, pre-selecting the necessary components and settings to get a functional Linux image for your specific Raspberry Pi hardware, which you can then further customize using make menuconfig to include desired applications and features.

Downloading Buildroot

You can download buildroot from here. Or, you can download stable releases as compressed tarballs from the official Buildroot website's download page: buildroot downloads

Configuring for a specific Pi Model

Raspberry Pi models from the original Pi 1 through to the latest Pi 5 are well-supported, allowing you create highly optimized and compact embedded systems for a wide range of applications.

To configure for the Raspberry Pi 3 model we would run:

make raspberrypi3_defconfig

Customizing the Configuration

In Buildroot, an overlay is a mechanism that allows you to customize your build without directly modifying the Buildroot source code. Think of it as a transparent layer placed on top of the standard Buildroot directories. When Buildroot goes to look for a file (like a package definition, a board configuration, or a root filesystem file), it first checks your overlay directories. If the file exists there, Buildroot uses the version from your overlay; otherwise, it falls back to its own internal files. This "lookup" order is crucial.

The simplist form of overlay is the Root Filesystem Overlay (BR2_ROOTFS_OVERLAY). This is a simpler type of overlay specifically for the root filesystem. The directory specified by BR2_ROOTFS_OVERLAY (or multiple directories separated by spaces) contains files and directories that will be copied directly on top of the generated root filesystem.

For example, if you have:

my_rootfs_overlay/
├── etc/
│   └── my_custom_file.conf
└── usr/
    └── bin/
        └── my_script.sh

These files will end up in /etc/my_custom_file.conf and /usr/bin/my_script.sh on your target device, potentially overwriting existing files in the root filesystem if they have the same path.

You configure this in make menuconfig under "Filesystem images" -> "Root filesystem overlays".

Creating an Root Filesystem Overlay directory overlay:

cd buildroot_pi
mkdir overlay
mkdir -p overlay/etc/network

Configure the overlay location in menuconfig. Under System Configuration select the option for overlay.

image

image

Configuring for a Static IP Address

place an interfaces file in overlay/etc/network

auto eth0
iface eth0 inet static
    address 192.168.1.178
    netmask 255.255.255.0
    gateway 192.168.1.254
    hostname $(hostname)

Buildroot Packages

In Buildroot, the concept of "packages" is central to building your embedded Linux system. A package represents a piece of software (like BusyBox, OpenSSH, or a custom application) that Buildroot can download, configure, compile, and install onto your target device's root filesystem. Buildroot provides a vast collection of pre-defined packages, each with its own .mk file (Makefile fragment) that specifies its version, download location, dependencies, and build steps. Users enable or disable these packages primarily through Buildroot's intuitive make menuconfig interface. Navigating the hierarchical menus, typically under "Target packages," allows you to select or deselect specific software components. When a package is enabled (marked with [*]), Buildroot automatically ensures all its necessary build-time and run-time dependencies are also included. Conversely, disabling a package removes it and any of its unique dependencies, resulting in a smaller, more optimized final image. This granular control over packages empowers developers to create highly customized and minimal systems, only including what's strictly required for their application, thereby saving valuable flash and RAM resources on embedded devices like the Raspberry Pi.

Buildroot can be a little unpredictable about when newly added packages are included in the rootfs, so after turning on a package we may need to force its inclusion in the rootfs, for example, to enable ssh access one would run the commands below:

make dropbear-reinstall
make openssh-reinstall
make

Saving your Configuration

Buildroot will save our configuration in the path set by BR2_DEFCONFIG. So when we do a make savedefconfig that file will be updated.

BR2_DEFCONFIG="/mnt/500GB/buildroot_pi/buildroot_2025/configs/raspberrypi3_defconfig"

Our kernel configuration is based on

BR2_LINUX_KERNEL_USE_DEFCONFIG=y
BR2_LINUX_KERNEL_DEFCONFIG="bcm2709"

These reference a kernel configuration found in

./output/build/linux-headers-custom/arch/arm/configs/bcm2709_defconfig
./output/build/linux-custom/arch/arm/configs/bcm2709_defconfig

We can save a modified config with

make linux-update-defconfig

make linux-update-defconfig can be configured to save the linux configuration to a specified path by setting BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG. It simplifies the config file by removing default values. However, this only works with kernels starting from 2.6.33.

Flashing Images

The most straightforward way of flashing your image to the board is to use the pri-imager. On Ubuntu this can be installed with

sudo apt install rpi-imager

You can also flash the image using a script built around the dd command as shown below.

IMAGE=sdcard.img
SDCARD_LOCATION=/dev/sde
IMAGE_PATH=/mnt/500GB/buildroot_pi/buildroot_2025/output/images/
#rm -rf $IMAGE_PATH/*.img
echo "Writing image $IMAGE ..."
sudo dd if=$IMAGE_PATH/$IMAGE of=$SDCARD_LOCATION bs=4M status=progress
echo "Syncing changes ..."
sync

You can extend this to be more elaborate with error checking and warnings as shown in the next script:

#!/bin/bash

# Usage: sudo ./flash_pi_image.sh /path/to/SDCard.img /dev/sdX
# Example: sudo ./flash_pi_image.sh ./SDCard.img /dev/sde

set -e

IMAGE="$1"
DEVICE="$2"

# Validate arguments
if [ -z "$IMAGE" ](/johnosbb/Automation/wiki/|--z-"$DEVICE"-); then
  echo "Usage: sudo $0 /path/to/SDCard.img /dev/sdX"
  exit 1
fi

if [ ! -f "$IMAGE" ](/johnosbb/Automation/wiki/-!--f-"$IMAGE"-); then
  echo "Error: Image file '$IMAGE' does not exist."
  exit 1
fi

if [ ! -b "$DEVICE" ](/johnosbb/Automation/wiki/-!--b-"$DEVICE"-); then
  echo "Error: Device '$DEVICE' is not a valid block device."
  exit 1
fi

# Confirm with user
echo "You are about to write '$IMAGE' to '$DEVICE'"
echo "This will ERASE all data on $DEVICE!"
read -rp "Are you sure? (yes/NO): " confirm

if [ "$confirm" != "yes" ](/johnosbb/Automation/wiki/-"$confirm"-!=-"yes"-); then
  echo "Aborted."
  exit 1
fi

echo "Unmounting any mounted partitions on $DEVICE..."
for part in $(ls ${DEVICE}?* 2>/dev/null); do
  sudo umount "$part" 2>/dev/null || true
done

echo "Writing image..."
sudo dd if="$IMAGE" of="$DEVICE" bs=4M status=progress conv=fsync

echo "Syncing..."
sync

echo "Ejecting..."
sudo eject "$DEVICE"

echo "Flash complete. You can now remove the SD card."

Serial Port Connection

image

Kernel Debugging

The vmlinux file can be found in ./output/build/linux-custom/vmlinux.

References