Yocto: Add hello world kernel module

In this section, you are going to learn

How to create a simple kernel module 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 kernel module

  • Make sure the current directory is “yocto”

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

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

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

$ vi meta-mykernelmod/conf/layer.conf
BBPATH .= ":${LAYERDIR}"
BBFILES += "${LAYERDIR}/recipes-*/*/*.bb"

BBFILE_COLLECTIONS += "mykernelmod"
BBFILE_PATTERN_mykernelmod = "^${LAYERDIR}/"
BBFILE_PRIORITY_mykernelmod = "5"

LAYERVERSION = "1"
  • Create a directory recipe-mykernelmod

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

$ vi meta-mykernelmod/recipe-mykernelmod/helloworld.c
#include <linux/init.h>
#include <linux/module.h>

MODULE_LICENSE("GPL");
MODULE_AUTHOR("TEST");
MODULE_DESCRIPTION("A simple hello world kernel module");
MODULE_VERSION("0.1");

void module_function()
{
        printf("Hello from module function\n");
}

static int __init hello_init(void)
{
        printk(KERN_INFO "Hello, World module loaded\n");
        module_function();
        return 0;
}

static void __exit hello_exit(void)
{
        printk(KERN_INFO "Hello, World module unloaded\n");
}

module_init(hello_init);
module_exit(hello_exit);
  • Create recipe file helloworld.bb in the same directory.

$ vim meta-mykernelmod/recipe-mykernelmod/helloworld.bb
SUMMARY = "Hello world kernel module"
LICENSE = "GPL"
LIC_FILES_CHKSUM = file://${COMMON_LICENSE_DIR}/GPL-2.0;md5=801f80980d171dd6425610833a22dbe6"

PR = "r0"

SRC_URI = "file://helloworld.c"

do_compile() {
        oe_runmake
}

do_install() {
        install -d ${D}${base-libdir}/modules/${KERNEL_VERSION}/extra
        install -m 0644 helloworld.ko ${D}${base-libdir}/modules/${KERNEL_VERSION}/extra
}
SUMMARY = "Hello World Application"
LICENSE = "GPL"
LIC_FILES_CHKSUM = file://${COMMON_LICENSE_DIR}/GPL-2.0;md5=801f80980d171dd6425610833a22dbe6"
  • SUMMARY: Summary gives a basic definition about the kernel module.

  • LICENSE: License is used to specifie the license related information for the recipe. GPL indicates general public license.

  • LIC_FILES_CHKSUM: A checksum verification for the license file. It ensures that license file checksum matches the expected checksum

PR = "r0"
  • This keeps notes of the recipe version. Whenever the recipe file is modified the recipe version will be incremented.

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() {
        oe_runmake
}
  • do_compile() is used to define the rules to compile the source code.

  • oe_runmake : yocto’s build system will automatically generate the necessary build components based on the information provided in the recipe.

do_install() {
        install -d ${D}${base-libdir}/modules/${KERNEL_VERSION}/extra
        install -m 0644 helloworld.ko ${D}${base-libdir}/modules/${KERNEL_VERSION}/extra
}
  • do_install() defines the rules on how to install the generated binary from do_compile() to the final target image.

  • install -d ${D}${base-libdir}/modules/${KERNEL_VERSION}/extra : creates the destination directory in the target image.

  • install -m 0644 helloworld.ko ${D}${base-libdir}/modules/${KERNEL_VERSION}/extra : installs the helloworld.ko kernel module in the destination directory with the following permissions (read,write for owner and read-only permission for group and others)

In this section you will learn how to add kernel module layer and adding the kernel_module 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-mykernelmod \
  "
$ vim build/local.conf
IMAGE_INSTALL_append = "helloworld"

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

In .conf file kernel_module 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-mykernelmod
  • 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 kernel_module binary file

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

$HOME/yocto/build/tmp/hosttools/objdump -t helloworld.ko | grep -i module_function

0000000000000000 g     F .text  0000000000000017 module_function
  • Symbol “module_function” are present in kernel_module binary file

  • Hence we can confirm kernel_module is compiled successfully

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

What “objdump” command does ?

  • objdump -S : Display source code intermixed with disassembly

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

    $ $HOME/yocto/build/tmp/hosttools/objdump -S helloworld.ko | grep -i module_function
    
    0000000000000000 <module_function>:
     0:     e8 00 00 00 00          call   5 <module_function+0x5>
    10:     e8 00 00 00 00          call   15 <module_function+0x15>
    
  • Symbol “module_function” are present in kernel_module binary file

  • Hence we can confirm kernel_module is compiled 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 “module_function” is present or not in the “readelf”

$ $HOME/yocto/build/tmp/hosttools/readelf -s helloworld.ko | grep -i module_function

36: 0000000000000000    23 FUNC    GLOBAL DEFAULT    2 module_function
  • Symbol “module_function” are present in kernel_module binary file

  • Hence we can confirm kernel_module is compiled 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 “module_function” is present or not in the “nm”

$HOME/yocto/build/tmp/hosttools/nm -S helloworld.ko | grep -i module_function

0000000000000000 0000000000000017 T module_function
  • Symbol “module_function” are present in kernel_module binary file

  • Hence we can confirm kernel_module is compiled 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 “module_function” is present or not in the “nm”

$HOME/yocto/build/tmp/hosttools/nm -s helloworld.ko | grep -i module_function

0000000000000000 T module_function
  • Symbol “module_function” are present in kernel_module binary file

  • Hence we can confirm kernel_module is compiled successfully

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

  • file: Determine file tye

$ file helloworld.ko

helloworld.ko: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), not stripped

Why “file” command is used ?

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

$ size helloworld.ko

text       data     bss     dec     hex filename
647         896       0    1543     607 helloworld.ko

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.ko | grep -i Hello
Hello from module function
Hello, World module loaded
Hello, World module unloaded

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 16172804 Jan  5 17:01 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