Building KZR OS: A Custom Embedded Linux Distro Using Yocto
Over the past few weeks, I’ve built KZR OS — a minimal embedded Linux distribution tailored for robotics and IoT systems. It’s based on the Yocto Project and includes support for ROS 2, CANbus, MQTT, a web interface, and Wi-Fi Access Point mode. This post outlines the process and structure behind building a custom embedded OS with Yocto, rather than diving deep into code or exact commands.
Why I Chose Yocto
Yocto allows complete control over what goes into your Linux image. It’s reproducible, layered, and designed for embedded systems. Unlike general-purpose Linux distros, Yocto gives you fine-grained customization at the image, package, and kernel level.
Step 1: Understanding Yocto’s Structure
A typical Yocto setup consists of:
- Poky: The core build system
- Board Support Package (BSP): Hardware-specific configuration
- Layers: Each layer contains metadata, recipes, and configurations
- Image recipe: Defines what gets installed into the final image
You start by cloning the core Yocto layers (poky
) and any necessary BSPs for your target board, such as meta-raspberrypi
for Raspberry Pi.
Step 2: Board Support Packages (BSPs)
A BSP in Yocto contains everything needed to support a specific hardware platform:
- Machine configurations
- Kernel configuration fragments
- Device tree overlays
- Bootloader setup (U-Boot, etc.)
For KZR OS, I used meta-raspberrypi
as a base BSP and modified machine files and device trees within a custom layer for specific hardware needs. Writing your own BSP is about defining your board’s identity in Yocto terms.
Step 3: Creating Your Own Layers
Custom layers keep your changes isolated. I created two:
meta-custom
: For hardware-specific overrides, kernel modules, and configurationsmeta-cookbook
: For custom image recipes, services, and packages
Each layer has its own conf/layer.conf
file and follows a standard directory structure (recipes-core, recipes-kernel, recipes-ros, etc.).
Step 4: Writing Recipes
Recipes are the core unit of build logic in Yocto. Each .bb
file describes how to fetch, build, and install a package.
To write a recipe:
- Define the source (Git, tarball, local)
- Provide dependencies and licensing
- Specify install steps
For example, a custom ROS node or a small Python app can be packaged by writing a recipe under recipes-ros
or recipes-apps
.
Appending or modifying existing recipes is also possible using .bbappend
files in your own layer.
Step 5: Building the Image
With your layers defined, you configure the build with:
bblayers.conf
: Enables layerslocal.conf
: Controls image features, init system, debug settings, etc.
You then create your own image recipe that defines what packages and features go into the final OS image. For KZR OS, I built a headless image that includes ROS 2, MQTT, CANbus tools, and web server support.
Once configured:
source oe-init-build-env
bitbake your-image-name