.. _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``.