Customizing Guide

Note

There is no need at all to modify any existing files in the Yocto source directory to customize the BSP for your own hardware. Instead, you should create a separate layer for your customizations where you can augment or override the original recipes.

This guide provides step-by-step instructions for customizing your Ka-Ro Board Support Package (BSP). You will learn how to:

  • Create and set up a custom Yocto layer

  • Customize U-Boot (u-boot-karo recipe) including bootloader configuration, device trees, and environment

  • Customize the Linux kernel (linux-karo recipe) and device trees

  • Create custom images and extend them using WIC

  • Use devtool for efficient development workflows

For comprehensive information beyond this guide, refer to the official Yocto Project Documentation. The Yocto Development Manual and Board Support Package (BSP) Guide are particularly relevant for advanced customizations.

Hint

All commands listed below are examples and must be adapted to your specific use case.

Getting Started: Creating Your Custom Layer

Before making any customizations, create a dedicated layer for your changes. This keeps your modifications separate from the BSP source and makes updates easier.

Note

Create your own DISTRO configuration based on one of the provided DISTRO configurations from our BSP layer. Prefix your DISTRO name with a unique identifier (e.g., mycompany-mydistro) and name your layer directory accordingly (e.g., meta-mycompany).

Layer Structure:

Your custom layer directory should have the following structure:

${BSPDIR}/sources/meta-mycompany/
  ├── conf/
  │   └── layer.conf          # Layer configuration (required)
  ├── COPYING.MIT             # License file (recommended)
  ├── README                  # Layer description (recommended)
  └── recipes-.../            # Your custom recipes and modifications

Setting Up Your Layer:

  1. Create your layer directory structure

  2. Create a minimal conf/layer.conf file:

    1# We have a conf and classes directory, add to BBPATH
    2BBPATH .= ":${LAYERDIR}"
    3
    4# We have recipes-* directories, add to BBFILES
    5BBFILES += "${LAYERDIR}/recipes-*/*/*.bb ${LAYERDIR}/recipes-*/*/*.bbappend"
    6
    7BBFILE_COLLECTIONS += "mycompany"
    8BBFILE_PATTERN_my-layer = "^${LAYERDIR}/"
    9BBFILE_PRIORITY_my-layer = "10"
    
  3. Add your layer to conf/bblayers.conf:

    1BBLAYERS += " \
    2  ${BUILDDIR}/../sources/meta-mycompany \
    3"
    

For more details on layer creation, see the Yocto documentation on Creating Your Own Layer.

Customizing a Recipe

The devtool command provides a streamlined workflow for modifying recipes, their source code, and configuration. This is particularly useful during development and testing.

Basic devtool workflow:

  1. Modify a recipe to create a workspace:

    devtool modify <recipe>
    

    This extracts the recipe’s source and creates a workspace directory (default: ${BUILDDIR}/workspace/).

  2. Make your changes in the workspace (source code, configuration files, etc.)

  3. Build and Test your changes:

    devtool build <recipe>
    
  4. Apply changes to your layer:

    devtool update-recipe <recipe> <layer>
    

    This applies your workspace changes to the specified layer, creating the necessary patches and/or bbappend files.

  5. Close the workspace:

    devtool reset <recipe>
    

    This closes the workspace, discarding any uncommitted changes.

For more information, see the Yocto documentation on devtool.

Creating your own baseboard settings

It will most probably be desirable to add your own baseboard setting to the yocto environment. The following steps are necessary to achieve this (replace ‘mybaseboard’ in the subsequent statements with your own boardname):

  1. Register your baseboard by extending the KARO_BASEBOARDS variable in your machine configuration. Create a machine configuration file in your layer that requires our module’s configuration, for example:

    meta-mycompany/
    └── conf/
       └── machine/
            └── module-mycompany.conf
    

    with the following content:

    1require module.conf
    2
    3KARO_BASEBOARDS += "mybaseboard"
    4
    5KARO_DTB_OVERLAYS[mybaseboard] = " \
    6   ... \
    7"
    
  2. Select your baseboard by adding

    KARO_BASEBOARD = "mybaseboard"
    

    to your conf/local.conf

For more details on how to add your own baseboard setting, see Adding overlays for a custom baseboard.

Customizing U-Boot (u-boot-karo)

Our BSP uses the u-boot-karo recipe for U-Boot. You can customize various aspects including configuration, device tree blobs (DTBs), and the default environment.

Creating a U-Boot bbappend File:

To customize U-Boot, create a .bbappend file in your custom layer. The file should be placed in a directory structure that mirrors the original recipe location:

meta-mycompany/
└── recipes-bsp/
    └── u-boot/
        └── u-boot-karo_%.bbappend

The % wildcard allows the bbappend to match any version of the u-boot-karo recipe.

Basic bbappend Example:

1FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:

This allows you to override or add files that U-Boot uses.

Modifications:

U-Boot can be customized by using devtool to open a workspace where you can modify source code and configuration with automatic patch generation (see devtool workflow above).

Note

Configuration changes applied through devtool may require manual adjustments to match your machine’s specific configuration requirements.

The u-boot-karo recipe contains special tasks that allow you to change configuration, device tree files, and environment files directly without opening a devtool workspace. These customizations are organized in subdirectories under your recipe directory:

meta-mycompany/
└── recipes-bsp/
    └── u-boot/
        ├── u-boot-karo/
        │   ├── cfg/          # Configuration fragments
        |   ├── defconfigs/   # Defconfig files
        │   ├── dts/          # Device tree source files
        │   └── env/          # Environment files
        └── u-boot-karo_%.bbappend

To ensure your custom files are found, add the following to your bbappend file:

FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}/env:${THISDIR}/${PN}/cfg:${THISDIR}/${PN}/defconfigs:"

Note

The dts directory is intentionally omitted in FILESEXTRAPATHS because the U-Boot source expects device tree files in a specific location.

The following subchapters explain how to use these directories.

Customizing U-Boot Configuration

The u-boot-karo recipe supports changing configuration directly through bbappend files without modifying the source. Place your configuration files in the appropriate subdirectories:

  1. Adding a custom config fragments:

    Add configuration fragments to the cfg/ directory:

    meta-mycompany/
    └── recipes-bsp/
       └── u-boot/
          └── u-boot-karo/
                └── cfg/
                   └── some-feature.cfg
    

    The fragment file contains only the configuration options you want to add or change:

    1CONFIG_MY_FEATURE=y
    2CONFIG_ANOTHER_OPTION=n
    
  2. Add your feature in your bbappend file:

    UBOOT_FEATURES:append = " some-feature"
    

The fragment file is automatically picked up by the u-boot-karo recipe through the UBOOT_FEATURES variable.

Note

The U-Boot configuration can also be altered by adding a defconfig. For more insight and options, look into the u-boot-karo recipe in our layer and our BSP documentation.

Adding a Custom Device Tree Blob (DTB)

The u-boot-karo recipe supports adding custom device tree blobs directly through bbappend files without modifying the source. Device tree selection is controlled by the KARO_BASEBOARD variable. This requires you to register your own baseboard (see Register your baseboard above).

Note

Check the u-boot-karo recipe in our BSP layer for naming requirements and examples specific to your module.

  1. Create your device tree source file (e.g. mybaseboard.dts) in the dts/ directory of your layer:

    meta-mycompany/
    └── recipes-bsp/
        └── u-boot/
            └── u-boot-karo/
                └── dts/
                    └── mybaseboard.dts
    
  2. Add the file to your bbappend:

    SRC_URI += "file://dts/mybaseboard.dts;subdir=git/arch/arm"
    
  3. Select your baseboard by setting KARO_BASEBOARD to “mybaseboard”. The u-boot-karo recipe will automatically pick up and compile your device tree.

For more details on device trees, refer to the Yocto Device Tree Manual.

Customizing the U-Boot Default Environment

The u-boot-karo recipe supports customizing the default environment directly through bbappend files without modifying the sources. Environment file selection is controlled by the KARO_BASEBOARD variable. This requires you to register your own baseboard (see Register your baseboard above).

Note

Check the u-boot-karo recipe in our BSP layer for naming requirements and examples specific to your module.

  1. Create your environment file based on the default envrionment file of our module for your specific module and baseboard in the env/ directory:

    meta-mycompany/
    └── recipes-bsp/
        └── u-boot/
            └── u-boot-karo/
                └── env/
                    └── module-mybaseboard.env
    
  2. Select your baseboard by setting KARO_BASEBOARD to “mybaseboard”. The u-boot-karo recipe will automatically pick up and use your envrionment file.

For information on U-Boot environment syntax, see the U-Boot Environment documentation.

Customizing the Linux Kernel (linux-karo)

Our BSP uses the linux-karo recipe for the Linux kernel. You can customize it in various ways, from configuration changes to adding patches and custom device tree blobs.

Creating a Linux bbappend File:

To customize Linux, create a .bbappend file in your custom layer. The file should be placed in a directory structure that mirrors the original recipe location:

meta-mycompany/
└── recipes-kernel/
    └── linux/
        └── linux-karo_%.bbappend

The % wildcard allows the bbappend to match any version of the linux-karo recipe.

Basic bbappend Example:

1FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:

This allows you to override or add files that the recipe uses.

Modifications:

Linux can be customized by using devtool to open a workspace where you can modify source code and configuration with automatic patch generation (see devtool workflow above).

Note

Configuration changes applied through devtool may require manual adjustments to match your machine’s specific configuration requirements.

The linux-karo recipe contains special tasks that allow you to change configuration and device tree files directly without opening a devtool workspace. These customizations are organized in subdirectories under your recipe directory:

meta-mycompany/
└── recipes-kernel/
    └── linux/
        ├── linux-karo/
        │   ├── cfg/          # Configuration fragments
        |   ├── defconfigs/   # Defconfig files
        │   └── dts/          # Device tree source files
        └── linux-karo_%.bbappend

To ensure your custom files are found, add the following to your bbappend file:

FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}/cfg:${THISDIR}/${PN}/defconfigs:"

Note

The dts directory is intentionally omitted in FILESEXTRAPATHS because the Linux Kernel source expects device tree files in a specific location.

The following subchapters explain how to use these directories.

Customizing Linux Kernel Configuration

The linux-karo recipe supports changing configuration directly through bbappend files without modifying the source. Place your configuration files in the appropriate subdirectories:

  1. Adding a custom defconfig:

    meta-mycompany/
    └── recipes-kernel/
        └── linux/
            └── linux-karo/
                └── defconfigs/
                    └── my-custom-defconfig
    
  2. Select your custom defconfig file in your bbappend file:

    # Use your custom defconfig for your machine
    KBUILD_DEFCONFIG = "my-custom-defconfig"
    

The defconfig file is automatically picked up and used by the linux-karo recipe.

Note

The custom defconfig can also be augmented by config fragments from the BSP layer selectable via the KERNEL_FEATURES variable. For more insight and options, look into the linux-karo recipe in our layer and our BSP documentation.

Adding a Custom Device Tree Blobs (DTB)

The linux-karo recipe supports adding custom device trees directly through bbappend files without modifying the source. Device tree selection is controlled by the KARO_BASEBOARD variable. This requires you to register your own baseboard (see Register your baseboard above).

Note

Check the linux-karo recipe in our BSP layer for naming requirements and examples specific to your module.

  1. Create your device tree source file in the appropriate directory:

    meta-mycompany/
    └── recipes-kernel/
        └── linux/
            └── linux-karo/
                └── dts/
                    └── <vendor>/
                        └── <soc-family>-<machine>-mybaseboard.dts
    
  2. Add the file to your bbappend file:

    # Add the device tree source
    SRC_URI:append = " \
       file://dts/<vendor>/<soc-family>-<machine>-mybaseboard.dts;subdir=git/${KERNEL_OUTPUT_DIR} \
    "
    
  3. Select your baseboard by setting KARO_BASEBOARD to “mybaseboard”. The linux-karo recipe will automatically pick up and compile your device tree.

For more details on device trees, refer to the Yocto Device Tree Manual.

Creating Custom Images

Our BSP mainly provides two image recipes: karo-image-minimal and karo-image-weston. Each uses WIC as the only IMAGE_FSTYPE, producing partitioned disk images with boot, rootfs, and userfs (/usr/local) by default.

For more details on WIC, refer to the Yocto WIC Guide.

Basic Custom Image

To extend karo-image-minimal:

Create your own mycompany-image-minimal.bb in your layer (e.g. under recipes-mycompany/images/):

SUMMARY = "My custom image"
LICENSE = "MIT"

require recipes-karo/images/karo-image-minimal.bb

IMAGE_INSTALL:append = " python3-pip htop"

Build with bitbake mycompany-image-minimal.

Custom Partition Layout

Default WKS structure:

part /boot --source karo-rootfs --rootfs-dir=${IMAGE_ROOTFS}/boot \
    --ondisk mmcblk0 --fstype=ext4 --label boot --use-label \
    --fsoptions noauto --active --align 1024 --fixed-size ${BOOTFS_PARTITION_SIZE}k

part / --source karo-rootfs --ondisk mmcblk0 --fstype=ext4 \
    --label rootfs --use-label --align 1024 \
    --fixed-size ${ROOTFS_PARTITION_SIZE}k --exclude-path boot/ usr/local/

part /usr/local --source karo-rootfs --rootfs-dir=${IMAGE_ROOTFS}/usr/local \
    --ondisk mmcblk0 --fstype=ext4 --label userfs --use-label \
    --fsoptions noauto --align 1024 --fixed-size ${USERFS_PARTITION_SIZE}k

bootloader --ptable gpt

To add a partition (e.g., /config):

  1. Create your own WKS file based on our default WKS structure

  2. Add or remove partitions at your discretion

  3. Include/exclude paths from the main partition (rootfs) with --exclude-path

  4. Set WKS_FILE in your image recipe

Example WKS addition:

part /config --source karo-rootfs --rootfs-dir=${IMAGE_ROOTFS}/config \
    --ondisk mmcblk0 --fstype=ext4 --label config --use-label \
    --fsoptions noauto --align 1024 --fixed-size 262144k

Partition Export

Our image recipe exports partitions which use the karo-rootfs source via WIC_PARTITIONS_EXPORT (default: "boot rootfs userfs"). Set in your recipe or local.conf:

WIC_PARTITIONS_EXPORT = "boot rootfs userfs config"

Output per partition: <image>-<machine>.<partition>.ext4 and <image>-<machine>.<partition>.tar.bz2.