.. _yocto-customizing-guide:
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
-------------------------------------------
.. _create-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:
.. code-block:: text
${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:
.. code-block:: text
:linenos:
# We have a conf and classes directory, add to BBPATH
BBPATH .= ":${LAYERDIR}"
# We have recipes-* directories, add to BBFILES
BBFILES += "${LAYERDIR}/recipes-*/*/*.bb ${LAYERDIR}/recipes-*/*/*.bbappend"
BBFILE_COLLECTIONS += "mycompany"
BBFILE_PATTERN_my-layer = "^${LAYERDIR}/"
BBFILE_PRIORITY_my-layer = "10"
3. Add your layer to ``conf/bblayers.conf``:
.. code-block:: text
:linenos:
BBLAYERS += " \
${BUILDDIR}/../sources/meta-mycompany \
"
For more details on layer creation, see the Yocto documentation on
`Creating Your Own Layer `_.
.. _using-devtool:
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:**
.. prompt::
:prompts: $
devtool modify
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:**
.. prompt::
:prompts: $
devtool build
4. **Apply changes to your layer:**
.. prompt::
:prompts: $
devtool update-recipe
This applies your workspace changes to the specified layer, creating the necessary patches and/or bbappend files.
5. **Close the workspace:**
.. prompt::
:prompts: $
devtool reset
This closes the workspace, discarding any uncommitted changes.
For more information, see the Yocto documentation on
`devtool `_.
.. _register-baseboard:
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:
.. code-block:: text
meta-mycompany/
└── conf/
└── machine/
└── module-mycompany.conf
with the following content:
.. code-block:: text
:linenos:
require module.conf
KARO_BASEBOARDS += "mybaseboard"
KARO_DTB_OVERLAYS[mybaseboard] = " \
... \
"
2. **Select your baseboard** by adding
.. code-block:: text
KARO_BASEBOARD = "mybaseboard"
to your `conf/local.conf`
For more details on how to add your own baseboard setting, see :ref:`software-documentation/uboot/fdt-overlays: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:
.. code-block:: text
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:**
.. code-block:: text
:linenos:
FILESEXTRAPATHS: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 :ref:`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:
.. code-block:: text
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:
.. code-block:: text
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:
.. code-block:: text
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:
.. code-block:: text
:linenos:
CONFIG_MY_FEATURE=y
CONFIG_ANOTHER_OPTION=n
2. **Add your feature in your bbappend file:**
.. code-block:: text
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 :ref:`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:
.. code-block:: text
meta-mycompany/
└── recipes-bsp/
└── u-boot/
└── u-boot-karo/
└── dts/
└── mybaseboard.dts
2. **Add the file to your bbappend:**
.. code-block:: text
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 :ref:`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:
.. code-block:: text
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:
.. code-block:: text
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:**
.. code-block:: text
:linenos:
FILESEXTRAPATHS: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 :ref:`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:
.. code-block:: text
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:
.. code-block:: text
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:**
.. code-block:: text
meta-mycompany/
└── recipes-kernel/
└── linux/
└── linux-karo/
└── defconfigs/
└── my-custom-defconfig
2. **Select your custom defconfig file in your bbappend file:**
.. code-block:: text
# 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 :ref:`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:
.. code-block:: text
meta-mycompany/
└── recipes-kernel/
└── linux/
└── linux-karo/
└── dts/
└── /
└── --mybaseboard.dts
2. **Add the file to your bbappend file:**
.. code-block:: text
# Add the device tree source
SRC_URI:append = " \
file://dts//--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/):
.. code-block:: text
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:
.. code-block:: text
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:
.. code-block:: text
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``:
.. code-block:: text
WIC_PARTITIONS_EXPORT = "boot rootfs userfs config"
Output per partition: ``-..ext4`` and ``-..tar.bz2``.