RDKB: Adding Patch to Hello world application

In this section, you are going to learn

How to create a patches to application in rdkb ?

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

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

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

Topics in this section,

  • Step 1: Install all the required packages

     $ sudo apt-get install gawk wget git-core diffstat unzip texinfo gcc-multilib \
       build-essential chrpath socat cpio python python3 python3-pip python3-pexpect \
       xz-utils debianutils iputils-ping python3-git python3-jinja2 libegl1-mesa libsdl1.2-dev \
       pylint3 xterm bmap-tools
    
    $ sudo apt-get install git cmake autoconf texinfo openjdk-8-jdk openjdk-8-jre \
       m4 libtool libtool-bin curl pkg-config lib32z1 doxygen
    
  • Step 2: Setup the repository

    $ mkdir ~/bin
    $ PATH=~/bin:$PATH
    
  • Step 3: Download the repo tool and ensure that it works

    $ curl http://commondatastorage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
    $ chmod a+x ~/bin/repo
    
  • Step 4: Edit the netrc file and add the following contents

    $ vi ~/.netrc
    
    machine code.rdkcentral.com
    login <YOUR_USERNAME>
    password <YOUR_PASSWORD>
    
  • NOTE: In order to repo the rdk source code, accounts need to be created in rdkcentral.com and that ssh key needs to be added.

  • Step 5: Create a repo file and replace it in ~/bin/repo

    $ vi repo
    $ cp -avrf bin ~/bin/repo
    
  • Step 6: Create the workspace directory

$ mkdir rdkb_build
$ cd rdbk_build
  • Step 7: Build steps for base rdkb image.

    • Initiate and sync the repository.

    $ repo init -u https://code.rdkcentral.com/r/manifests -b dunfell -m rdkb-extsrc.xml
    $ repo sync -j nproc --no-clone-bundle
    
    • Add the machine information using the following command

    $ MACHINE=raspberrypi4-64-rdk-broadband source meta-cmf-raspberrypi/setup-environment
    
    • Run bitbake to build the rdkb image.

    $ bitbake rdk-generic-broadband-image
    
    • Once build is done the image will be generated in tmp/deploy/raspberrypi4-64/images/

  • Step 8: Flash the image

    • Extract the .wic image using the bzip2 command.

    $ bzip2 -d rdk-generic-broadband-image-raspberrypi4-64-rdk-broadband.wic.bz2
    
    • Flash the image into sd card using this command

    $ sudo -E bmaptool copy --nobmap rdk-generic-broadband-image-raspberrypi4-64-rdk-broadband.wic /dev/sdb
    

In this section you will learn how to add custom application

$ mkdir meta-rdk-sampleapp
  • Create the below mentioned directories and files inside meta-rdk-sampleapp

$ mkdir conf
$ mkdir licenses
$ mkdir recipes-new
$ touch LICENSES.TXT
$ vi meta-rdk-sample/conf/layer.conf
##########################################################################
# ============================================================================
# RDK MANAGEMENT, LLC CONFIDENTIAL AND PROPRIETARY
# ============================================================================
# This file (and its contents) are the intellectual property of RDK Management, LLC.
# It may not be used, copied, distributed or otherwise disclosed in whole or in
# part without the express written permission of RDK Management, LLC.
# ============================================================================
# Copyright (c) 2018 RDK Management, LLC. All rights reserved.
# ============================================================================
##########################################################################
BBPATH .= ":${LAYERDIR}"
BBFILES += "\
            ${LAYERDIR}/recipes-*/*/*.bb \
            ${LAYERDIR}/recipes-*/*/*.bbappend \
           "

BBFILE_COLLECTIONS += "rdk-sampleapp"
BBFILE_PATTERN_rdk-sampleapp := "^${LAYERDIR}/"
#BBFILE_PRIORITY_rdk-sampleapp = "24"

# do not error out on bbappends for missing recipes (mysql5)
#BB_DANGLINGAPPENDS_WARNONLY = "true"

# Additional license directories.
LICENSE_PATH += "${LAYERDIR}/licenses"

GCCVERSION_daisy ?= "4.9%"
  • Mention the license file as Apache2.0 License which is the default license for this application.

All metadata files (including, but not limited to bb, bbappend,
bbclass, inc and conf files) are MIT licensed unless otherwise stated.
Source code included in tree for individual recipes is under the
LICENSE stated in the associated recipe (.bb file) unless otherwise
stated. All other files to have license as explicitly stated or default
to RDK Management licensed.

RDK Management License:
------------------------
This files (and contents) are the intellectual property of RDK Management, LLC.
It may not be used, copied, distributed or otherwise  disclosed in whole or in
part without the express written permission of RDK Management, LLC.
$ vi meta-rdk-sampleapp/recipes-new/sampleapp/files/sample/sample.c
/* sample.c: A program to show the time since the Epoch */

#include <stdio.h>

#if HAVE_CONFIG_H
#  include <config.h>
#endif /* HAVE_CONFIG_H */

#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#else
#include <time.h>
#endif

double get_sec_since_epoch()
{
   double sec;

   #ifdef HAVE_GETTIMEOFDAY
      struct timeval tv;

      gettimeofday(&tv, NULL);
      sec = tv.tv_sec;
      sec += tv.tv_usec / 1000000.0;
   #else
      sec = time(NULL);
   #endif

   return sec;
}

int main(int argc, char* argv[])
{
   printf("Hello Sample Program \t ");
   printf("%f\n", get_sec_since_epoch());
   return 0;
}
$ vi meta-rdk-sampleapp/recipes-new/sampleapp/files/sample/configure.ac
#                       -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.

AC_PREREQ([2.69])
AC_INIT(sampleapp, 1.0)
AM_INIT_AUTOMAKE([-Wall -Werror foreign])
#AM_INIT_AUTOMAKE(sample, main)
AC_CONFIG_SRCDIR([sampleapp.c])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_MACRO_DIR([m4])

# Checks for programs.
AC_PROG_CC
AC_PROG_INSTALL

# Checks for libraries.

# Checks for header files.

# Checks for typedefs, structures, and compiler characteristics.

# Checks for library functions.

AC_CONFIG_FILES([Makefile])
AC_OUTPUT
$ vi meta-rdk-sampleapp/recipes-new/sampleapp/sampleapp.bb
#
# If not stated otherwise in this file or this component's Licenses.txt file the
# following copyright and licenses apply:
#
# Copyright 2017 RDK Management
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
SUMMARY = "This recipe add a new sample component "
SECTION = "console/utils"
LICENSE = "Apache-2.0"
FILESEXTRAPATHS_prepend := "${THISDIR}:"
SRC_URI = "file://sampleapp.tgz"
S = "${WORKDIR}/sample"
LIC_FILES_CHKSUM = "file://LICENSE;md5=175792518e4ac015ab6696d16c4f607e"

DEPENDS_append = " ${@bb.utils.contains('DISTRO_FEATURES', 'systemd', 'systemd', '', d)}"

inherit autotools

do_install_append () {
    # Config files and scripts
    install -d ${D}${systemd_unitdir}/system
    install -D -m 0644 ${S}/scripts/sample.service ${D}${systemd_unitdir}/system/sample.service
}
SYSTEMD_SERVICE_${PN} += "sample.service"
FILES_${PN} += " \
      /usr/bin/* \
        ${systemd_unitdir}/system/sample.service \
"
SUMMARY = "Hello World Application"
SECTION = "console/utils"
LICENSE = "Apache-2.0"
  • Summary gives a basic definition about the application.

  • Section is used to specify the section in which the recipe should be placed in the Yocto build output.

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

FILESEXTRAPATHS_prepend := "${THISDIR}:"
SRC_URI = "file://sampleapp.tgz"
S = "${WORKDIR}/sample"
LIC_FILES_CHKSUM = "file://LICENSE;md5=175792518e4ac015ab6696d16c4f607e"
  • FILESEXTRAPATHS_prepend prepends the current directory to the file search paths.

  • 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.

  • S is source directory, derived from the WORKDIR and used during the build process.

  • LIC_FILES_CHKSUM is checksum of the recipe’s license file.

DEPENDS_append = " ${@bb.utils.contains('DISTRO_FEATURES', 'systemd', 'systemd', '', d)}"
  • Adds a dependency on systemd if the ‘systemd’ feature is enabled in the distribution.

inherit autotools
  • Inherits the autotools class, which is common for projects using the GNU Autotools build system.

do_install_append () {
        # Config files and scripts
        install -d ${D}${systemd_unitdir}/system
        install -D -m 0644 ${S}/scripts/sample.service ${D}${systemd_unitdir}/system/sample.service
}
  • Appends additional installation steps.

  • It creates a systemd unit directory, installs a sample systemd service file, and specifies the destination path.

SYSTEMD_SERVICE_${PN} += "sample.service"
FILES_${PN} += " \
        /usr/bin/* \
        ${systemd_unitdir}/system/sample.service \
"
  • SYSTEMD_SERVICE_${PN} specifies the systemd service associated with this package.

  • FILES_${PN} lists the files to be included in the final package, including binaries and the systemd service file.

  • Add service file to control the application.

$ vi meta-rdk-sampleapp/recipes-new/sampleapp/files/sample/scripts/sample.service
[Unit]
Description=Example sampleapp systemd service.
After=CcspPandMSsp.service
[Service]
Type=simple
ExecStart=/bin/sh -c val=syscfg get sampleapp_enabled; echo "$val"; if [ "$val" == 1 ]; then /usr/bin/sampleapp; fi
ExecStop=/bin/sh -c  echo "Sample service Stopped"
[Install]
WantedBy=multi-user.target
  • Create a patch file where changes of source files will be added.

$ touch meta-rdk-sampleapp/recipes-new/sampleapp/001-add-patches-to-sampleapp.patch
  • Add this file in the SRC_URI param of sampleapp.bb so that it is included during the build.

SRC_URI = "file://sample/sampleapp.c \
           file://files/001-add-patches-to-sampleapp.patch \
        "
  • Run this command to create patches for our patch file.

$ MACHINE=raspberrypi4-64-rdk-broadband source meta-cmf-raspberrypi/setup-environment
$ bitbake sampleapp -c devshell
  • Now a pop-up opens and run quilt for editing the sources and creating patches.

$ quilt top
001-add-patches-to-sampleapp.patch
$ quilt edit sampleapp.c
$ vi sampleapp.c
/* sample.c: A program to show the time since the Epoch */

#include <stdio.h>

#if HAVE_CONFIG_H
#  include <config.h>
#endif /* HAVE_CONFIG_H */

#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#else
#include <time.h>
#endif

double get_sec_since_epoch()
{
   double sec;

   #ifdef HAVE_GETTIMEOFDAY
      struct timeval tv;

      gettimeofday(&tv, NULL);
      sec = tv.tv_sec;
      sec += tv.tv_usec / 1000000.0;
   #else
      sec = time(NULL);
   #endif

   return sec;
}

void patch_function()
{
  printf("Added line via patch\n");
}


int main(int argc, char* argv[])
{
   printf("Hello Sample Program \t ");
   printf("%f\n", get_sec_since_epoch());
   patch_function();
   return 0;
}
  • Once the changes are done run quilt refresh to apply the changes to the patch file.

$ quilt refresh
  • Now the changes are successfully added to the patch file 001-add-patches-to-sampleapp.patch

Index: sample/sampleapp.c
===================================================================
--- sample.orig/sampleapp.c
+++ sample/sampleapp.c
 -29,9 +29,15 double get_sec_since_epoch()
        return sec;
 }

+void patch_function()
+{
+       printf("Added line via patch\n");
+}
+
int main(int argc, char* argv[])
{
        printf("Hello Sample Program \t ");
        printf("%f\n", get_sec_since_epoch());
+       patch_function();
        return 0;
 }

In this section you will learn how to add configurations for our sample application.

  • Add the following changes in the configurations file.

$ vi meta-cmf-raspberrypi/conf/layer.conf
LAYERDEPENDS_cmf-raspberrypi = " rdk-sampleapp"
$ vi meta-cmf-raspberrypi/setup-environment
# Add meta-rdk-sampleapp only if not already present for RDK-B

echo "${_RDK_FLAVOR}"

if [[ "${_RDK_FLAVOR}" = "rdkb" ]]

then

   if [ $(grep ^BBLAYERS conf/bblayers.conf | grep -c meta-rdk-sampleapp) -eq 0 -a -d  $TOP_DIR/meta-rdk-sampleapp ]

   then

        cat >> conf/bblayers.conf <<EOF

BBLAYERS =+ "\${RDKROOT}/meta-rdk-sampleapp"

EOF

   fi

fi
$ vi meta-cmf-raspberrypi/recipes-core/packagegroups/packagegroup-rdk-oss-broadband.bbappend
RDEPENDS_packagegroup-rdk-oss-broadband_append
        rtl88x2bu\
        ethtool\
        ntpstat\
        sampleapp\

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

  • Below line should be present in /meta-cmf-raspberrypi/conf/layer.conf file

LAYERDEPENDS_cmf-raspberrypi = " rdk-sampleapp"
  • Below line should be present in packagegroup-rdk-oss-broadband.bbappend

RDEPENDS_packagegroup-rdk-oss-broadband_append
                        rtl88x2bu\
                        ethtool\
                        ntpstat\
                        sampleapp\
$ cd build/tmp/hosttools/
  • make tar of the sample folder present in the files directry of our package so then during our package compilation the .bb file can get the source files from the tarfile

$ tar cvf sampleapp.tgz sample
  • build the rdk source files along with our sample application

$ bitbake -c clean sampleapp
$ bitbake sampleapp

In this section you will learn about post build checks

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

See that binary called sampleapp is present inside directory ?

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

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

$HOME/rdkb/build/tmp/hosttools/objdump -t sampleapp | grep -i main

00000000000011d8 g     F .text  0000000000000060              main
  • Check if “get_sec_since_epoch” is present or not in the “objdump”

$HOME/rdkb/build/tmp/hosttools/objdump -t sampleapp | grep -i get_sec_since_epoch

0000000000001189 g     F .text  0000000000000035              get_sec_since_epoch
  • Check if “patch_function” is present or not in the “objdump”

$HOME/rdkb/build/tmp/hosttools/objdump -t sampleapp | grep -i patch_function

00000000000011be g     F .text  000000000000001a              patch_function
  • Symbols “main”,”get_sec_since_epoch” and “patch_function” are present in application binary file

  • Hence we can confirm application is compiled successfully with patches

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/rdkb/build/tmp/hosttools/objdump -S sampleapp | grep -i main
    
    10b8:   48 8d 3d 19 01 00 00    lea    11d8 <main>
    
  • Check if “get_sec_since_epoch” is present or not in the “objdump”

    $ $HOME/rdkb/build/tmp/hosttools/objdump -S sampleapp | grep -i get_sec_since_epoch
    
    0000000000001189 <get_sec_since_epoch>:
    1204:   e8 80 ff ff ff          call   1189 <get_sec_since_epoch>
    
  • Check if “patch_function” is present or not in the “objdump”

    $HOME/rdkb/build/tmp/hosttools/objdump -S sampleapp | grep -i patch_function
    
    00000000000011be <patch_function>:
    122c:   e8 8d ff ff ff          call   11be <patch_function>
    
  • Symbols “main”,”get_sec_since_epoch” and “patch_function” are present in application binary file

  • Hence we can confirm application is compiled successfully with patches

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/rdkb/build/tmp/hosttools/readelf -s sampleapp | grep -i main

35: 00000000000011d8    96 FUNC    GLOBAL DEFAULT   16 main
  • Check if “get_sec_since_epoch” is present or not in the “readelf”

$ $HOME/rdkb/build/tmp/hosttools/readelf -s sampleapp | grep -i get_sec_since_epoch

34: 0000000000001189    53 FUNC    GLOBAL DEFAULT   16 get_sec_since_epoch
  • Check if “patch_function” is present or not in the “readelf”

$HOME/rdkb/build/tmp/hosttools/readelf -s sampleapp | grep -i get_sec_since_epoch

29: 00000000000011be    26 FUNC    GLOBAL DEFAULT   16 patch_function
  • Symbols “main”,”get_sec_since_epoch” and “patch_function” are present in application binary file

  • Hence we can confirm application is compiled successfully with patches

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/rdkb/build/tmp/hosttools/nm -S sampleapp | grep -i main

00000000000011d8 0000000000000060 T main
  • Check if “get_sec_since_epoch” is present or not in the “nm”

$HOME/rdkb/build/tmp/hosttools/nm -S sampleapp | grep -i get_sec_since_epoch

0000000000001189 0000000000000035 T get_sec_since_epoch
  • Check if “patch_function” is present or not in the “nm”

$HOME/rdkb/build/tmp/hosttools/nm -S sampleapp | grep -i patch_function

00000000000011be 000000000000001a T patch_function
  • Symbols “main”,”get_sec_since_epoch” and “patch_function” are present in application binary file

  • Hence we can confirm application is compiled successfully with patches

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/rdkb/build/tmp/hosttools/nm -s sampleapp | grep -i main

00000000000011d8 T main
  • Check if “get_sec_since_epoch” is present or not in the “nm”

$HOME/rdkb/build/tmp/hosttools/nm -s sampleapp | grep -i get_sec_since_epoch

0000000000001189 T get_sec_since_epoch
  • Check if “patch_function” is present or not in the “nm”

$HOME/rdkb/build/tmp/hosttools/nm -s sampleapp | grep -i patch_function

00000000000011be T patch_function
  • Symbols “main” and “get_sec_since_epoch” are present in application binary file

  • Hence we can confirm application is compiled successfully

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

  • file: Determine file tye

$ file sampleapp

sampleapp: 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 sampleapp

text       data     bss     dec     hex filename
1812        616       8    2436     984 sampleapp

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 sampleapp | grep -i Hello
Hello Sample Program
  • Check if “patch_function” is present or not in “strings”

    $ strings sampleapp | grep -i patch Added line via patch

What “strings” command does ?

In this section you will learn how to build full rdkb

  • Make sure the current directory “build”

$ cd $HOME/rdkb/build
$ bitbake rdk-generic-broadband-image
  • 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 1704893 Jan  10 18:53 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