Yocto: Add Patches to an Application

In this section, you are going to learn

How to add patches to a simple application in yocto ?

How to generate full yocto image for RPI-4B ?

How to flash full yocto image for RPI-4B ?

How to run minicom and work remotely with RPI-4B ?

  • Step 1: Install all the required packages

    $ sudo apt-get install gawk wget git diffstat unzip texinfo gcc-multilib build-essential chrpath cpio python3 python3-pip python3-pexpect xz-utils debianutils iputils-ping
    
  • Step 2: Clone the yocto source directory

    • To clone poky directory

    $ mkdir sources
    $ cd sources
    $ git clone -b langdale git://git.yoctoproject.org/poky.git
    
    • To clone openembedded core layer

    $ git clone -b langdale git://git.openembedded.org/meta-openembedded
    
    • To clone meta-raspberrypi layer

    $ git clone -b langdale git://git.yoctoproject.org/meta-raspberrypi
    
  • Step 3: Initialize the build environment

    $ cd ..
    $ . sources/poky/oe-init-build-env
    
  • Step 4: Edit the local.conf and bblayers.conf file

    • Add the following configurations in conf/local.conf

    MACHINE ??= "raspberrypi4"
    
    • Add the following yocto layers in conf/bblayers.conf

    BBLAYERS ?= " \
      /home/test/yocto/sources/poky/meta \
      /home/test/yocto/sources/poky/meta-poky \
      /home/test/yocto/sources/poky/meta-yocto-bsp \
      /home/test/yocto/sources/meta-openembedded/meta-oe \
      /home/test/yocto/sources/meta-openembedded/meta-python \
      /home/test/yocto/sources/meta-raspberrypi \
      "
    
  • Step 5: Set locale settings as “en_US.UTF-8”

    export LC_ALL="en_US.UTF-8"
    export LC_CTYPE="en_US.UTF-8"
    sudo dpkg-reconfigure locales
    
    • Select en_US.UTF-8 and apply the changes.

  • Step 5: Build the image

    $ bitbake core-image-base
    
  • Step 6: Once build is completed the image will be in present in the following directory.

    $ pwd
    /home/test/yocto/build/tmp/deploy/images/raspberrypi4/
    
  • Step 7: Extract the base image file using bzip2 command to generate the .wic file.

    $ bzip2 -d -f core-image-base-raspberrypi4.wic.bz2
    
  • Step 8: Flash the image file core-image-base-raspberrypi4.wic to SD card using Elena Batcher tool.

  • Step 9: Run minicom to open the RPI-4B console.

    $ sudo minicom -D /dev/ttyUSB0
    

In this section you will learn how to add custom application

  • Make sure the current directory is “yocto”

$ pwd
/home/test/yocto
  • Create the new meta-layer directory for the custom application

$ mkdir meta-custom
  • Create a new directory called “conf” inside the meta-custom directory

$ mkdir meta-custom/conf
  • Create the layer.conf file and add the following configurations.

$ vi meta-custom/conf/layer.conf
LAYERVERSION = "1"

BBPATH .= ":${LAYERDIR}"

BBFILES += "${LAYERDIR}/recipes-*/*/*.bb \
            ${LAYERDIR}/recipes-*/*/*.bbappend"


BBFILE_COLLECTIONS += "meta-custom"
BBFILE_PATTER_meta-custom = "^${LAYERDIR}/"
BBFILE_PRIORITY_meta-custom = "6"
  • Create a directory recipes-custom

$ mkdir meta-custom/recipes-custom
  • Create helloworld.c inside recipes-custom and add the necessary instructions.

$ vi meta-custom/recipes-custom/helloworld.c
#include <stdio.h>

void app_fun()
{
        printf("Inside app_fun()\n");
}

int main(void)
{
        printf("Hello,World\n");
        app_fun();

        return 0;
}
  • Create recipe file helloworld.bb in the same directory.

$ vim meta-custom/recipes-custom/helloworld.bb
SUMMARY = "Hello World Application"
LICENSE = "CLOSED"

SRC_URI = "file://helloworld.c"

do_compile() {
        ${CC} ${CFLAGS} ${LDFLAGS} -o helloworld helloworld.c
}

do_install() {
        install -d ${D}${bindir}
        install -m 0755 helloworld ${D}${bindir}
}
SUMMARY = "Hello World Application"
LICENSE = "CLOSED"
  • Summary gives a basic definition about the application.

  • License is used to specifie the license related information for the recipe.

SRC_URI = "file://helloworld.c"
  • SRC_URI is used to indicate the uri for the recipe source files.

  • file://” denote that the source code is present in the same directory where the recipe file is.

do_compile() {
        ${CC} ${CFLAGS} ${LDFLAGS} -o helloworld helloworld.c
}
  • do_compile() is used to define the rules to compile the source code.

  • CC, CFLAGS and LDFLAGS are set by Yocto to appropriate cross-compilation tools and flags.

  • Here the source code helloworld.c is compiled and the binary file helloworld is generated.

do_install() {
        install -d ${D}${bindir}
        install -m 0755 helloworld ${D}${bindir}
}
  • do_install() defines the rules on how to install the generated binary from do_compile() to the final target image.

  • install -d ${D}${bindir} : creates the destination directory in the target image where the binary will be installed.

  • install -m 0755 helloworld ${D}${bindir} : installs the helloworld binary in the destination directory with the following permissions (read,write and execute for owner and read,execute permission for group and others)

  • Copy the application soure folder to another folder.

$ cp -rvf meta-custom/* meta-custom-modified/
  • Edit the files which needs to be modified.

$ vi meta-custom-modified/recipes-custom/helloworld.c
#include <stdio.h>

void patch_fun()
{
        printf("Patch function added\n");
}

void app_fun()
{
        printf("Inside app_fun()\n");
}

int main()
{
        printf("Hello,World\n");
        app_fun();
        patch_fun();
        return 0;
}
  • Generate a patch file using diff command.

$ diff -Naur meta-custom meta-custom-modified > adding-patch-to-application.patch
diff -Naur meta-custom/recipes-custom/helloworld.c meta-custom-modified/recipes-custom/helloworld.c
--- meta-custom/recipes-custom/helloworld.c     2024-01-06 11:19:18.826512585 +0530
+++ meta-custom-modified/recipes-custom/helloworld.c    2024-01-06 12:47:51.562803201 +0530
 -1,5 +1,10
 #include <stdio.h>

+void patch_fun()
+{
+       printf("Patch function added\n");
+}
+
 void app_fun()
 {
        printf("Inside app_fun()\n");
 -9,6 +14,6
 {
        printf("Hello,World\n");
        app_fun();
-
+       patch_fun();
        return 0;
 }
  • Place this patch file in appropriate location which is inside the recipes-custom folder.

$ mv adding-patch-to-application.patch meta-custom/recipes-custom/
  • Add the following instructions in helloworld.bb recipe file.

SRC_URI += "file:://adding-patch-to-application.patch"
SRC_URI[md5sum] = "f1f23cb1a8d3315aa21365b2c526416a"
SRC_URI[sha256sum] = "62b5f357d8a19c29b0586943febaa890a696103107fb0b8d40b0f5c3417ab625"

inherit quilt

QUILTCMDS = "push"
  • Include the patch file in SRC_URI parameter. Since it is in the same directory as the recipe file it is indicated using “file://”.

  • Add the md5sum and sha256sum of the patch. This can be obtained from the following commands.

$ md5sum adding-patch-to-application.patch
f1f23cb1a8d3315aa21365b2c526416a  adding-patch-to-application.patch
$ sha256sum adding-patch-to-application.patch
62b5f357d8a19c29b0586943febaa890a696103107fb0b8d40b0f5c3417ab625  adding-patch-to-application.patch
  • Add do_patch() section in the recipe file to apply the patch.

do_patch() {
        quilt push -a
        autoreconf -f -i
}
  • In this do_patch() sections the patch is applied using “quilt push -a” and “autoreconf” is used to remake only the files older than their sources.

  • Finally the updated recipe file will look like this.

    SUMMARY = "Hello World Application"
    LICENSE = "CLOSED"
    
    SRC_URI = "file://helloworld.c"
    SRC_URI += "file:://adding-patch-to-application.patch"
    SRC_URI[md5sum] = "f1f23cb1a8d3315aa21365b2c526416a"
    SRC_URI[sha256sum] = "62b5f357d8a19c29b0586943febaa890a696103107fb0b8d40b0f5c3417ab625"
    inherit quilt
    
    QUILTCMDS = "push"
    
    do_patch() {
            quilt push -a
            autoreconf -f -i
    }
    
    do_compile() {
            ${CC} ${CFLAGS} ${LDFLAGS} -o helloworld helloworld.c
    }
    
    do_install() {
            install -d ${D}${bindir}
            install -m 0755 helloworld ${D}${bindir}
    }
    

In this section you will learn how to add application layer and adding the application binary to final target image.

$ vim build/bblayers.conf
BBLAYERS ?= " \
  /home/test/yocto/sources/poky/meta \
  /home/test/yocto/sources/poky/meta-poky \
  /home/test/yocto/sources/poky/meta-yocto-bsp \
  /home/test/yocto/sources/meta-openembedded/meta-oe \
  /home/test/yocto/sources/meta-openembedded/meta-python \
  /home/test/yocto/sources/meta-raspberrypi \
  /home/test/yocto/sources/meta-custom \
  "
$ vim build/local.conf
IMAGE_INSTALL_append = "helloworld"

In this section you will learn how to do Pre-build checks

In .conf file application image and layer should be added.

  • Below line should be present in local.conf file

IMAGE_INSTALL_append = "helloworld"
  • Below line should be present in bblayers.conf file inside BBLAYERS parameter

/home/test/yocto/sources/meta-custom
  • Make sure the current directory “yocto”

    $ cd build/tmp/hosttools/
    
  • Make sure the current directory is ‘yocto’

$ cd build
$ bitbake helloworld

In this section you will learn about post build checks

  • Make sure the current directory is ‘yocto’

$ pwd
/home/test/yocto

$ cd build/tmp/work/raspberrypi4-poky-linux-gnueabi/helloworld/1.0-r0/image/usr/bin/

See that binary called helloworld is present inside directory ?

  • objdump -t : Displays the symbols of application binary file

  • Check if “main” is present or not in the “objdump”

$HOME/yocto/build/tmp/hosttools/objdump -t helloworld | grep -i main

0000000000001163 g     F .text  0000000000000037              main
  • Check if “app_fun” is present or not in the “objdump”

$HOME/yocto/build/tmp/hosttools/objdump -t helloworld | grep -i app_fun

0000000000001149 g     F .text  000000000000001a              app_fun
  • Symbols “main” and “app_fun” are present in application binary file

  • Hence we can confirm application is compiled successfully

  • Check if “patch_fun” is present or not in the “objdump”

$HOME/yocto/build/tmp/hosttools/objdump -t helloworld | grep -i patch_fun

0000000000001149 g     F .text  000000000000001a              patch_fun
  • Symbol “patch_fun” is present in application binary file.

  • Hence we can confirm patch is added to the application successfully.

What is “-t” option is used in “objdump” command ?

What “objdump” command does ?

  • objdump -S : Display source code intermixed with disassembly

  • Check if “main” is present or not in the “objdump”

$HOME/yocto/build/tmp/hosttools/objdump -S helloworld | grep -i main

1078:   48 8d 3d e4 00 00 00    lea    1163 <main>
  • Check if “app_fun” is present or not in the “objdump”

$HOME/yocto/build/tmp/hosttools/objdump -S helloworld | grep -i app_fun

0000000000001149 <app_fun>:
117f:   e8 c5 ff ff ff          call   1149 <app_fun>
  • Symbols “main” and “app_fun” are present in application binary file

  • Hence we can confirm application is compiled successfully

  • Check if “patch_fun” is present or not in the “objdump”

$HOME/yocto/build/tmp/hosttools/objdump -S helloworld | grep -i patch_fun

0000000000001149 <patch_fun>:
11a3:   e8 a1 ff ff ff          call   1149 <patch_fun>
  • Symbol “patch_fun” is present in the binary file which confirms that the patch is added successfully.

What is “-S” option is used in “objdump” command ?

What is the purpose of “objdump” command ?

  • readelf -s: Display the symbol table

  • Check if “main” is present or not in the “readelf”

$HOME/yocto/build/tmp/hosttools/readelf -s helloworld | grep -i main

32: 0000000000001163    40 FUNC    GLOBAL DEFAULT   16 main
  • Check if “app_fun” is present or not in the “readelf”

$ $HOME/yocto/build/tmp/hosttools/readelf -s helloworld | grep -i app_fun

18: 0000000000001149    26 FUNC    GLOBAL DEFAULT   16 app_fun
  • Symbols “main” and “app_fun” are present in application binary file

  • Hence we can confirm application is compiled successfully

  • Check if “patch_fun” is present in binary file or not

$HOME/yocto/build/tmp/hosttools/readelf -s helloworld | grep -i patch_fun

25: 0000000000001149    26 FUNC    GLOBAL DEFAULT   16 patch_fun
  • Symbol “patch_fun” is present in the binary file which confirms that the patch is applied successfully.

What is “-s” option is used in “readelf” command ?

What “readelf” command does ?

What is the purpose of “readelf” command ?

  • nm -S: Print both value and size of defined symbols for the “bsd” output style

  • Check if “main” is present or not in the “nm”

$HOME/yocto/build/tmp/hosttools/nm -S helloworld | grep -i main

0000000000001163 0000000000000028 T main
  • Check if “app_fun” is present or not in the “nm”

$HOME/yocto/build/tmp/hosttools/nm -S helloworld | grep -i app_fun

0000000000001149 000000000000001a T app_fun
  • Symbols “main” and “app_fun” are present in application binary file

  • Hence we can confirm application is compiled successfully

  • Check if “patch_fun” is present or not in the “nm”

$HOME/yocto/build/tmp/hosttools/nm -S helloworld | grep -i patch_fun

0000000000001149 000000000000001a T patch_fun
  • Symbol “patch_fun” is presnt in the application binary file which confirms the patch is applied successfully.

What is “-S” option is used in “nm” command ?

What “nm” command does ?

What is the purpose of “nm” command ?

  • nm -s: When listing symbols from archive members, include the index: a mapping of which modules contain definitions for which names.

  • Check if “main” is present or not in the “nm”

$HOME/yocto/build/tmp/hosttools/nm -s helloworld | grep -i main

0000000000001163 T main
  • Check if “app_fun” is present or not in the “nm”

$HOME/yocto/build/tmp/hosttools/nm -s helloworld | grep -i app_fun

0000000000001149 T app_fun
  • Symbols “main” and “app_fun” are present in application binary file

  • Hence we can confirm application is compiled successfully

  • Check whether “patch_fun” is present or not in “nm”

$HOME/yocto/build/tmp/hosttools/nm -s helloworld | grep -i patch_fun

0000000000001149 T patch_fun
  • Symbol “patch_fun” is present in the application binary file which confirms the patch is applied successfully.

What is “-s” option is used in “nm” command ?

  • file: Determine file tye

$ file helloworld

helloworld: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-musl-aarch64.so.1, for GNU/Linux3.7.0, not stripped

Why “file” command is used ?

  • size: List section sizes and total size of binary files

$ size helloworld

text       data     bss     dec     hex filename
1530        600       8    2138     85a helloworld

What “size” command does ?

  • strings - print the sequences of printable characters in files

  • As we can see string output are added in the program are confirmed.

$ strings helloworld | grep -i Hello
Hello,World
  • Now we will check whether the patches are applied to the binary file.

$strings helloworld | grep -i patch
Patch function added

What “strings” command does ?

In this section you will learn how to build full yocto

  • Make sure the current directory “build”

$ cd $HOME/yocto/build
$ bitbake core-image-base
  • It downloads, compiles and configures all the necessary packages required for the build.

  • Make sure the current directory “build”

  • To check package is successfully compiled, below is the path

$ cd tmp/deploy/images/raspberrypi4/
$ ls
-rw-r--r-- 1 test test 16136112 Jan  6 12:24 core-image-base-raspberrypi4.wic.bz2
  • As we can see image is present in the tmp/deploy/images/raspberrypi4 directory

  • Image file is core-image-base-raspberrypi4.wic.bz