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 : Adding patches to custom application
Step 2 : Add configurations in .conf files
Step 5.2: Check the “objdump” output of the application binary file
Step 5.3: Check the “readelf” output of the application binary file
Step 5.4: Check the “nm” output of the application binary file
Step 5.5: Check the “file” command output of application binary file
Step 5.6: Check the “size” command output of application binary file
Step 5.7: Check the “strings” command output of application binary file
Step 6: Build full rdkb - Incremental
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
See the complete file below
#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""Repo launcher.
This is a standalone tool that people may copy to anywhere in their system.
It is used to get an initial repo client checkout, and after that it runs the
copy of repo in the checkout.
"""
from __future__ import print_function
# repo default configuration
#
import os
REPO_URL = os.environ.get('REPO_URL', None)
if not REPO_URL:
REPO_URL = 'https://gerrit.googlesource.com/git-repo'
REPO_REV = os.environ.get('REPO_REV')
if not REPO_REV:
REPO_REV = 'repo-1'
# Copyright (C) 2008 Google Inc.
#
# 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.
# increment this whenever we make important changes to this script
VERSION = (1, 27)
# increment this if the MAINTAINER_KEYS block is modified
KEYRING_VERSION = (1, 2)
# Each individual key entry is created by using:
# gpg --armor --export keyid
MAINTAINER_KEYS = """
Repo Maintainer <repo@android.kernel.org>
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1.4.2.2 (GNU/Linux)
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
=CMiZ
-----END PGP PUBLIC KEY BLOCK-----
Conley Owens <cco3@android.com>
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1.4.11 (GNU/Linux)
mQENBFHRvc8BCADFg45Xx/y6QDC+T7Y/gGc7vx0ww7qfOwIKlAZ9xG3qKunMxo+S
hPCnzEl3cq+6I1Ww/ndop/HB3N3toPXRCoN8Vs4/Hc7by+SnaLFnacrm+tV5/OgT
V37Lzt8lhay1Kl+YfpFwHYYpIEBLFV9knyfRXS/428W2qhdzYfvB15/AasRmwmor
py4NIzSs8UD/SPr1ihqNCdZM76+MQyN5HMYXW/ALZXUFG0pwluHFA7hrfPG74i8C
zMiP7qvMWIl/r/jtzHioH1dRKgbod+LZsrDJ8mBaqsZaDmNJMhss9g76XvfMyLra
9DI9/iFuBpGzeqBv0hwOGQspLRrEoyTeR6n1ABEBAAG0H0NvbmxleSBPd2VucyA8
Y2NvM0BhbmRyb2lkLmNvbT6JATgEEwECACIFAlHRvc8CGwMGCwkIBwMCBhUIAgkK
CwQWAgMBAh4BAheAAAoJEGe35EhpKzgsP6AIAJKJmNtn4l7hkYHKHFSo3egb6RjQ
zEIP3MFTcu8HFX1kF1ZFbrp7xqurLaE53kEkKuAAvjJDAgI8mcZHP1JyplubqjQA
xvv84gK+OGP3Xk+QK1ZjUQSbjOpjEiSZpRhWcHci3dgOUH4blJfByHw25hlgHowd
a/2PrNKZVcJ92YienaxxGjcXEUcd0uYEG2+rwllQigFcnMFDhr9B71MfalRHjFKE
fmdoypqLrri61YBc59P88Rw2/WUpTQjgNubSqa3A2+CKdaRyaRw+2fdF4TdR0h8W
zbg+lbaPtJHsV+3mJC7fq26MiJDRJa5ZztpMn8su20gbLgi2ShBOaHAYDDi5AQ0E
UdG9zwEIAMoOBq+QLNozAhxOOl5GL3StTStGRgPRXINfmViTsihrqGCWBBUfXlUE
OytC0mYcrDUQev/8ToVoyqw+iGSwDkcSXkrEUCKFtHV/GECWtk1keyHgR10YKI1R
mquSXoubWGqPeG1PAI74XWaRx8UrL8uCXUtmD8Q5J7mDjKR5NpxaXrwlA0bKsf2E
Gp9tu1kKauuToZhWHMRMqYSOGikQJwWSFYKT1KdNcOXLQF6+bfoJ6sjVYdwfmNQL
Ixn8QVhoTDedcqClSWB17VDEFDFa7MmqXZz2qtM3X1R/MUMHqPtegQzBGNhRdnI2
V45+1Nnx/uuCxDbeI4RbHzujnxDiq70AEQEAAYkBHwQYAQIACQUCUdG9zwIbDAAK
CRBnt+RIaSs4LNVeB/0Y2pZ8I7gAAcEM0Xw8drr4omg2fUoK1J33ozlA/RxeA/lJ
I3KnyCDTpXuIeBKPGkdL8uMATC9Z8DnBBajRlftNDVZS3Hz4G09G9QpMojvJkFJV
By+01Flw/X+eeN8NpqSuLV4W+AjEO8at/VvgKr1AFvBRdZ7GkpI1o6DgPe7ZqX+1
dzQZt3e13W0rVBb/bUgx9iSLoeWP3aq/k+/GRGOR+S6F6BBSl0SQ2EF2+dIywb1x
JuinEP+AwLAUZ1Bsx9ISC0Agpk2VeHXPL3FGhroEmoMvBzO0kTFGyoeT7PR/BfKv
+H/g3HsL2LOB9uoIm8/5p2TTU5ttYCXMHhQZ81AY
=AUp4
-----END PGP PUBLIC KEY BLOCK-----
"""
GIT = 'git' # our git command
MIN_GIT_VERSION = (1, 7, 2) # minimum supported git version
repodir = '.repo' # name of repo's private directory
S_repo = 'repo' # special repo repository
S_manifests = 'manifests' # special manifest repository
REPO_MAIN = S_repo + '/main.py' # main script
MIN_PYTHON_VERSION = (2, 7) # minimum supported python version
GITC_CONFIG_FILE = '/gitc/.config'
GITC_FS_ROOT_DIR = '/gitc/manifest-rw/'
import collections
import errno
import optparse
import platform
import re
import shutil
import stat
import subprocess
import sys
if sys.version_info[0] == 3:
import urllib.request
import urllib.error
else:
import imp
import urllib2
urllib = imp.new_module('urllib')
urllib.request = urllib2
urllib.error = urllib2
# Python version check
ver = sys.version_info
if (ver[0], ver[1]) < MIN_PYTHON_VERSION:
print('error: Python version {} unsupported.\n'
'Please use Python {}.{} instead.'.format(
sys.version.split(' ')[0],
MIN_PYTHON_VERSION[0],
MIN_PYTHON_VERSION[1],
), file=sys.stderr)
sys.exit(1)
home_dot_repo = os.path.expanduser('~/.repoconfig')
gpg_dir = os.path.join(home_dot_repo, 'gnupg')
extra_args = []
init_optparse = optparse.OptionParser(usage="repo init -u url [options]")
# Logging
group = init_optparse.add_option_group('Logging options')
group.add_option('-q', '--quiet',
dest="quiet", action="store_true", default=False,
help="be quiet")
# Manifest
group = init_optparse.add_option_group('Manifest options')
group.add_option('-u', '--manifest-url',
dest='manifest_url',
help='manifest repository location', metavar='URL')
group.add_option('-b', '--manifest-branch',
dest='manifest_branch',
help='manifest branch or revision', metavar='REVISION')
group.add_option('-m', '--manifest-name',
dest='manifest_name',
help='initial manifest file', metavar='NAME.xml')
group.add_option('--current-branch',
dest='current_branch_only', action='store_true',
help='fetch only current manifest branch from server')
group.add_option('--mirror',
dest='mirror', action='store_true',
help='create a replica of the remote repositories '
'rather than a client working directory')
group.add_option('--reference',
dest='reference',
help='location of mirror directory', metavar='DIR')
group.add_option('--dissociate',
dest='dissociate', action='store_true',
help='dissociate from reference mirrors after clone')
group.add_option('--depth', type='int', default=None,
dest='depth',
help='create a shallow clone with given depth; see git clone')
group.add_option('--partial-clone', action='store_true',
dest='partial_clone',
help='perform partial clone (https://git-scm.com/'
'docs/gitrepository-layout#_code_partialclone_code)')
group.add_option('--clone-filter', action='store', default='blob:none',
dest='clone_filter',
help='filter for use with --partial-clone [default: %default]')
group.add_option('--archive',
dest='archive', action='store_true',
help='checkout an archive instead of a git repository for '
'each project. See git archive.')
group.add_option('--submodules',
dest='submodules', action='store_true',
help='sync any submodules associated with the manifest repo')
group.add_option('-g', '--groups',
dest='groups', default='default',
help='restrict manifest projects to ones with specified '
'group(s) [default|all|G1,G2,G3|G4,-G5,-G6]',
metavar='GROUP')
group.add_option('-p', '--platform',
dest='platform', default="auto",
help='restrict manifest projects to ones with a specified '
'platform group [auto|all|none|linux|darwin|...]',
metavar='PLATFORM')
group.add_option('--no-clone-bundle',
dest='no_clone_bundle', action='store_true',
help='disable use of /clone.bundle on HTTP/HTTPS')
group.add_option('--no-tags',
dest='no_tags', action='store_true',
help="don't fetch tags in the manifest")
# Tool
group = init_optparse.add_option_group('repo Version options')
group.add_option('--repo-url',
dest='repo_url',
help='repo repository location ($REPO_URL)', metavar='URL')
group.add_option('--repo-branch',
dest='repo_branch',
help='repo branch or revision ($REPO_REV)', metavar='REVISION')
group.add_option('--no-repo-verify',
dest='no_repo_verify', action='store_true',
help='do not verify repo source code')
# Other
group = init_optparse.add_option_group('Other options')
group.add_option('--config-name',
dest='config_name', action="store_true", default=False,
help='Always prompt for name/e-mail')
def _GitcInitOptions(init_optparse_arg):
init_optparse_arg.set_usage("repo gitc-init -u url -c client [options]")
g = init_optparse_arg.add_option_group('GITC options')
g.add_option('-f', '--manifest-file',
dest='manifest_file',
help='Optional manifest file to use for this GITC client.')
g.add_option('-c', '--gitc-client',
dest='gitc_client',
help='The name of the gitc_client instance to create or modify.')
_gitc_manifest_dir = None
def get_gitc_manifest_dir():
global _gitc_manifest_dir
if _gitc_manifest_dir is None:
_gitc_manifest_dir = ''
try:
with open(GITC_CONFIG_FILE, 'r') as gitc_config:
for line in gitc_config:
match = re.match('gitc_dir=(?P<gitc_manifest_dir>.*)', line)
if match:
_gitc_manifest_dir = match.group('gitc_manifest_dir')
except IOError:
pass
return _gitc_manifest_dir
def gitc_parse_clientdir(gitc_fs_path):
"""Parse a path in the GITC FS and return its client name.
@param gitc_fs_path: A subdirectory path within the GITC_FS_ROOT_DIR.
@returns: The GITC client name
"""
if gitc_fs_path == GITC_FS_ROOT_DIR:
return None
if not gitc_fs_path.startswith(GITC_FS_ROOT_DIR):
manifest_dir = get_gitc_manifest_dir()
if manifest_dir == '':
return None
if manifest_dir[-1] != '/':
manifest_dir += '/'
if gitc_fs_path == manifest_dir:
return None
if not gitc_fs_path.startswith(manifest_dir):
return None
return gitc_fs_path.split(manifest_dir)[1].split('/')[0]
return gitc_fs_path.split(GITC_FS_ROOT_DIR)[1].split('/')[0]
class CloneFailure(Exception):
"""Indicate the remote clone of repo itself failed.
"""
def _Init(args, gitc_init=False):
"""Installs repo by cloning it over the network.
"""
if gitc_init:
_GitcInitOptions(init_optparse)
opt, args = init_optparse.parse_args(args)
if args:
init_optparse.print_usage()
sys.exit(1)
url = opt.repo_url
if not url:
url = REPO_URL
extra_args.append('--repo-url=%s' % url)
branch = opt.repo_branch
if not branch:
branch = REPO_REV
extra_args.append('--repo-branch=%s' % branch)
if branch.startswith('refs/heads/'):
branch = branch[len('refs/heads/'):]
if branch.startswith('refs/'):
print("fatal: invalid branch name '%s'" % branch, file=sys.stderr)
raise CloneFailure()
try:
if gitc_init:
gitc_manifest_dir = get_gitc_manifest_dir()
if not gitc_manifest_dir:
print('fatal: GITC filesystem is not available. Exiting...',
file=sys.stderr)
sys.exit(1)
gitc_client = opt.gitc_client
if not gitc_client:
gitc_client = gitc_parse_clientdir(os.getcwd())
if not gitc_client:
print('fatal: GITC client (-c) is required.', file=sys.stderr)
sys.exit(1)
client_dir = os.path.join(gitc_manifest_dir, gitc_client)
if not os.path.exists(client_dir):
os.makedirs(client_dir)
os.chdir(client_dir)
if os.path.exists(repodir):
# This GITC Client has already initialized repo so continue.
return
os.mkdir(repodir)
except OSError as e:
if e.errno != errno.EEXIST:
print('fatal: cannot make %s directory: %s'
% (repodir, e.strerror), file=sys.stderr)
# Don't raise CloneFailure; that would delete the
# name. Instead exit immediately.
#
sys.exit(1)
_CheckGitVersion()
try:
if opt.no_repo_verify:
do_verify = False
else:
if NeedSetupGnuPG():
do_verify = SetupGnuPG(opt.quiet)
else:
do_verify = True
dst = os.path.abspath(os.path.join(repodir, S_repo))
_Clone(url, dst, opt.quiet, not opt.no_clone_bundle)
if do_verify:
rev = _Verify(dst, branch, opt.quiet)
else:
rev = 'refs/remotes/origin/%s^0' % branch
_Checkout(dst, branch, rev, opt.quiet)
if not os.path.isfile(os.path.join(dst, 'repo')):
print("warning: '%s' does not look like a git-repo repository, is "
"REPO_URL set correctly?" % url, file=sys.stderr)
except CloneFailure:
if opt.quiet:
print('fatal: repo init failed; run without --quiet to see why',
file=sys.stderr)
raise
# The git version info broken down into components for easy analysis.
# Similar to Python's sys.version_info.
GitVersion = collections.namedtuple(
'GitVersion', ('major', 'minor', 'micro', 'full'))
def ParseGitVersion(ver_str=None):
if ver_str is None:
# Load the version ourselves.
ver_str = _GetGitVersion()
if not ver_str.startswith('git version '):
return None
full_version = ver_str[len('git version '):].strip()
num_ver_str = full_version.split('-')[0]
to_tuple = []
for num_str in num_ver_str.split('.')[:3]:
if num_str.isdigit():
to_tuple.append(int(num_str))
else:
to_tuple.append(0)
to_tuple.append(full_version)
return GitVersion(*to_tuple)
def _GetGitVersion():
cmd = [GIT, '--version']
try:
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE)
except OSError as e:
print(file=sys.stderr)
print("fatal: '%s' is not available" % GIT, file=sys.stderr)
print('fatal: %s' % e, file=sys.stderr)
print(file=sys.stderr)
print('Please make sure %s is installed and in your path.' % GIT,
file=sys.stderr)
raise
ver_str = proc.stdout.read().strip()
proc.stdout.close()
proc.wait()
return ver_str.decode('utf-8')
def _CheckGitVersion():
try:
ver_act = ParseGitVersion()
except OSError:
raise CloneFailure()
if ver_act is None:
print('fatal: unable to detect git version', file=sys.stderr)
raise CloneFailure()
if ver_act < MIN_GIT_VERSION:
need = '.'.join(map(str, MIN_GIT_VERSION))
print('fatal: git %s or later required' % need, file=sys.stderr)
raise CloneFailure()
def NeedSetupGnuPG():
if not os.path.isdir(home_dot_repo):
return True
kv = os.path.join(home_dot_repo, 'keyring-version')
if not os.path.exists(kv):
return True
kv = open(kv).read()
if not kv:
return True
kv = tuple(map(int, kv.split('.')))
if kv < KEYRING_VERSION:
return True
return False
def SetupGnuPG(quiet):
try:
os.mkdir(home_dot_repo)
except OSError as e:
if e.errno != errno.EEXIST:
print('fatal: cannot make %s directory: %s'
% (home_dot_repo, e.strerror), file=sys.stderr)
sys.exit(1)
try:
os.mkdir(gpg_dir, stat.S_IRWXU)
except OSError as e:
if e.errno != errno.EEXIST:
print('fatal: cannot make %s directory: %s' % (gpg_dir, e.strerror),
file=sys.stderr)
sys.exit(1)
env = os.environ.copy()
try:
env['GNUPGHOME'] = gpg_dir
except UnicodeEncodeError:
env['GNUPGHOME'] = gpg_dir.encode()
cmd = ['gpg', '--import']
try:
proc = subprocess.Popen(cmd,
env=env,
stdin=subprocess.PIPE)
except OSError as e:
if not quiet:
print('warning: gpg (GnuPG) is not available.', file=sys.stderr)
print('warning: Installing it is strongly encouraged.', file=sys.stderr)
print(file=sys.stderr)
return False
proc.stdin.write(MAINTAINER_KEYS.encode('utf-8'))
proc.stdin.close()
if proc.wait() != 0:
print('fatal: registering repo maintainer keys failed', file=sys.stderr)
sys.exit(1)
print()
with open(os.path.join(home_dot_repo, 'keyring-version'), 'w') as fd:
fd.write('.'.join(map(str, KEYRING_VERSION)) + '\n')
return True
def _SetConfig(local, name, value):
"""Set a git configuration option to the specified value.
"""
cmd = [GIT, 'config', name, value]
if subprocess.Popen(cmd, cwd=local).wait() != 0:
raise CloneFailure()
def _InitHttp():
handlers = []
mgr = urllib.request.HTTPPasswordMgrWithDefaultRealm()
try:
import netrc
n = netrc.netrc()
for host in n.hosts:
p = n.hosts[host]
mgr.add_password(p[1], 'http://%s/' % host, p[0], p[2])
mgr.add_password(p[1], 'https://%s/' % host, p[0], p[2])
except:
pass
handlers.append(urllib.request.HTTPBasicAuthHandler(mgr))
handlers.append(urllib.request.HTTPDigestAuthHandler(mgr))
if 'http_proxy' in os.environ:
url = os.environ['http_proxy']
handlers.append(urllib.request.ProxyHandler({'http': url, 'https': url}))
if 'REPO_CURL_VERBOSE' in os.environ:
handlers.append(urllib.request.HTTPHandler(debuglevel=1))
handlers.append(urllib.request.HTTPSHandler(debuglevel=1))
urllib.request.install_opener(urllib.request.build_opener(*handlers))
def _Fetch(url, local, src, quiet):
if not quiet:
print('Get %s' % url, file=sys.stderr)
cmd = [GIT, 'fetch']
if quiet:
cmd.append('--quiet')
err = subprocess.PIPE
else:
err = None
cmd.append(src)
cmd.append('+refs/heads/*:refs/remotes/origin/*')
cmd.append('+refs/tags/*:refs/tags/*')
proc = subprocess.Popen(cmd, cwd=local, stderr=err)
if err:
proc.stderr.read()
proc.stderr.close()
if proc.wait() != 0:
raise CloneFailure()
def _DownloadBundle(url, local, quiet):
if not url.endswith('/'):
url += '/'
url += 'clone.bundle'
proc = subprocess.Popen(
[GIT, 'config', '--get-regexp', 'url.*.insteadof'],
cwd=local,
stdout=subprocess.PIPE)
for line in proc.stdout:
line = line.decode('utf-8')
m = re.compile(r'^url\.(.*)\.insteadof (.*)$').match(line)
if m:
new_url = m.group(1)
old_url = m.group(2)
if url.startswith(old_url):
url = new_url + url[len(old_url):]
break
proc.stdout.close()
proc.wait()
if not url.startswith('http:') and not url.startswith('https:'):
return False
dest = open(os.path.join(local, '.git', 'clone.bundle'), 'w+b')
try:
try:
r = urllib.request.urlopen(url)
except urllib.error.HTTPError as e:
if e.code in [401, 403, 404, 501]:
return False
print('fatal: Cannot get %s' % url, file=sys.stderr)
print('fatal: HTTP error %s' % e.code, file=sys.stderr)
raise CloneFailure()
except urllib.error.URLError as e:
print('fatal: Cannot get %s' % url, file=sys.stderr)
print('fatal: error %s' % e.reason, file=sys.stderr)
raise CloneFailure()
try:
if not quiet:
print('Get %s' % url, file=sys.stderr)
while True:
buf = r.read(8192)
if not buf:
return True
dest.write(buf)
finally:
r.close()
finally:
dest.close()
def _ImportBundle(local):
path = os.path.join(local, '.git', 'clone.bundle')
try:
_Fetch(local, local, path, True)
finally:
os.remove(path)
def _Clone(url, local, quiet, clone_bundle):
"""Clones a git repository to a new subdirectory of repodir
"""
try:
os.mkdir(local)
except OSError as e:
print('fatal: cannot make %s directory: %s' % (local, e.strerror),
file=sys.stderr)
raise CloneFailure()
cmd = [GIT, 'init', '--quiet']
try:
proc = subprocess.Popen(cmd, cwd=local)
except OSError as e:
print(file=sys.stderr)
print("fatal: '%s' is not available" % GIT, file=sys.stderr)
print('fatal: %s' % e, file=sys.stderr)
print(file=sys.stderr)
print('Please make sure %s is installed and in your path.' % GIT,
file=sys.stderr)
raise CloneFailure()
if proc.wait() != 0:
print('fatal: could not create %s' % local, file=sys.stderr)
raise CloneFailure()
_InitHttp()
_SetConfig(local, 'remote.origin.url', url)
_SetConfig(local,
'remote.origin.fetch',
'+refs/heads/*:refs/remotes/origin/*')
if clone_bundle and _DownloadBundle(url, local, quiet):
_ImportBundle(local)
_Fetch(url, local, 'origin', quiet)
def _Verify(cwd, branch, quiet):
"""Verify the branch has been signed by a tag.
"""
cmd = [GIT, 'describe', 'origin/%s' % branch]
proc = subprocess.Popen(cmd,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
cwd=cwd)
cur = proc.stdout.read().strip().decode('utf-8')
proc.stdout.close()
proc.stderr.read()
proc.stderr.close()
if proc.wait() != 0 or not cur:
print(file=sys.stderr)
print("fatal: branch '%s' has not been signed" % branch, file=sys.stderr)
raise CloneFailure()
m = re.compile(r'^(.*)-[0-9]{1,}-g[0-9a-f]{1,}$').match(cur)
if m:
cur = m.group(1)
if not quiet:
print(file=sys.stderr)
print("info: Ignoring branch '%s'; using tagged release '%s'"
% (branch, cur), file=sys.stderr)
print(file=sys.stderr)
env = os.environ.copy()
try:
env['GNUPGHOME'] = gpg_dir
except UnicodeEncodeError:
env['GNUPGHOME'] = gpg_dir.encode()
cmd = [GIT, 'tag', '-v', cur]
proc = subprocess.Popen(cmd,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
cwd=cwd,
env=env)
out = proc.stdout.read().decode('utf-8')
proc.stdout.close()
err = proc.stderr.read().decode('utf-8')
proc.stderr.close()
if proc.wait() != 0:
print(file=sys.stderr)
print(out, file=sys.stderr)
print(err, file=sys.stderr)
print(file=sys.stderr)
raise CloneFailure()
return '%s^0' % cur
def _Checkout(cwd, branch, rev, quiet):
"""Checkout an upstream branch into the repository and track it.
"""
cmd = [GIT, 'update-ref', 'refs/heads/default', rev]
if subprocess.Popen(cmd, cwd=cwd).wait() != 0:
raise CloneFailure()
_SetConfig(cwd, 'branch.default.remote', 'origin')
_SetConfig(cwd, 'branch.default.merge', 'refs/heads/%s' % branch)
cmd = [GIT, 'symbolic-ref', 'HEAD', 'refs/heads/default']
if subprocess.Popen(cmd, cwd=cwd).wait() != 0:
raise CloneFailure()
cmd = [GIT, 'read-tree', '--reset', '-u']
if not quiet:
cmd.append('-v')
cmd.append('HEAD')
if subprocess.Popen(cmd, cwd=cwd).wait() != 0:
raise CloneFailure()
def _FindRepo():
"""Look for a repo installation, starting at the current directory.
"""
curdir = os.getcwd()
repo = None
olddir = None
while curdir != '/' \
and curdir != olddir \
and not repo:
repo = os.path.join(curdir, repodir, REPO_MAIN)
if not os.path.isfile(repo):
repo = None
olddir = curdir
curdir = os.path.dirname(curdir)
return (repo, os.path.join(curdir, repodir))
class _Options(object):
help = False
def _ParseArguments(args):
cmd = None
opt = _Options()
arg = []
for i in range(len(args)):
a = args[i]
if a == '-h' or a == '--help':
opt.help = True
elif not a.startswith('-'):
cmd = a
arg = args[i + 1:]
break
return cmd, opt, arg
def _Usage():
gitc_usage = ""
if get_gitc_manifest_dir():
gitc_usage = " gitc-init Initialize a GITC Client.\n"
print(
"""usage: repo COMMAND [ARGS]
repo is not yet installed. Use "repo init" to install it here.
The most commonly used repo commands are:
init Install repo in the current working directory
""" + gitc_usage +
""" help Display detailed help on a command
For access to the full online help, install repo ("repo init").
""")
sys.exit(0)
def _Help(args):
if args:
if args[0] == 'init':
init_optparse.print_help()
sys.exit(0)
elif args[0] == 'gitc-init':
_GitcInitOptions(init_optparse)
init_optparse.print_help()
sys.exit(0)
else:
print("error: '%s' is not a bootstrap command.\n"
' For access to online help, install repo ("repo init").'
% args[0], file=sys.stderr)
else:
_Usage()
sys.exit(1)
def _NotInstalled():
print('error: repo is not installed. Use "repo init" to install it here.',
file=sys.stderr)
sys.exit(1)
def _NoCommands(cmd):
print("""error: command '%s' requires repo to be installed first.
Use "repo init" to install it here.""" % cmd, file=sys.stderr)
sys.exit(1)
def _RunSelf(wrapper_path):
my_dir = os.path.dirname(wrapper_path)
my_main = os.path.join(my_dir, 'main.py')
my_git = os.path.join(my_dir, '.git')
if os.path.isfile(my_main) and os.path.isdir(my_git):
for name in ['git_config.py',
'project.py',
'subcmds']:
if not os.path.exists(os.path.join(my_dir, name)):
return None, None
return my_main, my_git
return None, None
def _SetDefaultsTo(gitdir):
global REPO_URL
global REPO_REV
REPO_URL = gitdir
proc = subprocess.Popen([GIT,
'--git-dir=%s' % gitdir,
'symbolic-ref',
'HEAD'],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
REPO_REV = proc.stdout.read().strip().decode('utf-8')
proc.stdout.close()
proc.stderr.read()
proc.stderr.close()
if proc.wait() != 0:
print('fatal: %s has no current branch' % gitdir, file=sys.stderr)
sys.exit(1)
def main(orig_args):
cmd, opt, args = _ParseArguments(orig_args)
repo_main, rel_repo_dir = None, None
# Don't use the local repo copy, make sure to switch to the gitc client first.
if cmd != 'gitc-init':
repo_main, rel_repo_dir = _FindRepo()
wrapper_path = os.path.abspath(__file__)
my_main, my_git = _RunSelf(wrapper_path)
cwd = os.getcwd()
if get_gitc_manifest_dir() and cwd.startswith(get_gitc_manifest_dir()):
print('error: repo cannot be used in the GITC local manifest directory.'
'\nIf you want to work on this GITC client please rerun this '
'command from the corresponding client under /gitc/',
file=sys.stderr)
sys.exit(1)
if not repo_main:
if opt.help:
_Usage()
if cmd == 'help':
_Help(args)
if not cmd:
_NotInstalled()
if cmd == 'init' or cmd == 'gitc-init':
if my_git:
_SetDefaultsTo(my_git)
try:
_Init(args, gitc_init=(cmd == 'gitc-init'))
except CloneFailure:
path = os.path.join(repodir, S_repo)
print("fatal: cloning the git-repo repository failed, will remove "
"'%s' " % path, file=sys.stderr)
shutil.rmtree(path, ignore_errors=True)
sys.exit(1)
repo_main, rel_repo_dir = _FindRepo()
else:
_NoCommands(cmd)
if my_main:
repo_main = my_main
ver_str = '.'.join(map(str, VERSION))
me = [sys.executable, repo_main,
'--repo-dir=%s' % rel_repo_dir,
'--wrapper-version=%s' % ver_str,
'--wrapper-path=%s' % wrapper_path,
'--']
me.extend(orig_args)
me.extend(extra_args)
try:
if platform.system() == "Windows":
sys.exit(subprocess.call(me))
else:
os.execv(sys.executable, me)
except OSError as e:
print("fatal: unable to start %s" % repo_main, file=sys.stderr)
print("fatal: %s" % e, file=sys.stderr)
sys.exit(148)
if __name__ == '__main__':
main(sys.argv[1:])
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.confLAYERDEPENDS_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.bbappendRDEPENDS_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/See Output Below
$ ls -l lrwxrwxrwx 1 test test 10 Jan 4 12:59 '[' lrwxrwxrwx 1 test test 11 Jan 4 12:59 ar lrwxrwxrwx 1 test test 11 Jan 4 12:59 as lrwxrwxrwx 1 test test 12 Jan 4 12:59 awk lrwxrwxrwx 1 test test 17 Jan 4 12:59 basename lrwxrwxrwx 1 test test 13 Jan 4 12:59 bash lrwxrwxrwx 1 test test 14 Jan 4 12:59 bzip2 lrwxrwxrwx 1 test test 12 Jan 4 13:00 bzr lrwxrwxrwx 1 test test 12 Jan 4 12:59 cat lrwxrwxrwx 1 test test 14 Jan 4 12:59 chgrp lrwxrwxrwx 1 test test 14 Jan 4 12:59 chmod lrwxrwxrwx 1 test test 14 Jan 4 12:59 chown lrwxrwxrwx 1 test test 16 Jan 4 12:59 chrpath lrwxrwxrwx 1 test test 12 Jan 4 12:59 cmp lrwxrwxrwx 1 test test 13 Jan 4 12:59 comm lrwxrwxrwx 1 test test 11 Jan 4 12:59 cp lrwxrwxrwx 1 test test 13 Jan 4 12:59 cpio lrwxrwxrwx 1 test test 12 Jan 4 12:59 cpp lrwxrwxrwx 1 test test 12 Jan 4 12:59 cut lrwxrwxrwx 1 test test 13 Jan 4 12:59 date lrwxrwxrwx 1 test test 11 Jan 4 12:59 dd lrwxrwxrwx 1 test test 13 Jan 4 12:59 diff lrwxrwxrwx 1 test test 17 Jan 4 12:59 diffstat lrwxrwxrwx 1 test test 16 Jan 4 12:59 dirname lrwxrwxrwx 1 test test 11 Jan 4 12:59 du lrwxrwxrwx 1 test test 13 Jan 4 12:59 echo lrwxrwxrwx 1 test test 14 Jan 4 12:59 egrep lrwxrwxrwx 1 test test 12 Jan 4 12:59 env lrwxrwxrwx 1 test test 15 Jan 4 12:59 expand lrwxrwxrwx 1 test test 13 Jan 4 12:59 expr lrwxrwxrwx 1 test test 14 Jan 4 12:59 false lrwxrwxrwx 1 test test 14 Jan 4 12:59 fgrep lrwxrwxrwx 1 test test 13 Jan 4 12:59 file lrwxrwxrwx 1 test test 13 Jan 4 12:59 find lrwxrwxrwx 1 test test 14 Jan 4 12:59 flock lrwxrwxrwx 1 test test 12 Jan 4 12:59 g++ lrwxrwxrwx 1 test test 13 Jan 4 12:59 gawk lrwxrwxrwx 1 test test 12 Jan 4 12:59 gcc lrwxrwxrwx 1 test test 15 Jan 4 13:00 gcc-ar lrwxrwxrwx 1 test test 16 Jan 4 12:59 getconf lrwxrwxrwx 1 test test 15 Jan 4 12:59 getopt lrwxrwxrwx 1 test test 12 Jan 4 12:59 git lrwxrwxrwx 1 test test 12 Jan 4 13:00 gpg lrwxrwxrwx 1 test test 18 Jan 4 13:00 gpg-agent lrwxrwxrwx 1 test test 13 Jan 4 12:59 grep lrwxrwxrwx 1 test test 15 Jan 4 12:59 gunzip lrwxrwxrwx 1 test test 13 Jan 4 12:59 gzip lrwxrwxrwx 1 test test 13 Jan 4 12:59 head lrwxrwxrwx 1 test test 17 Jan 4 12:59 hostname lrwxrwxrwx 1 test test 14 Jan 4 12:59 iconv lrwxrwxrwx 1 test test 11 Jan 4 12:59 id lrwxrwxrwx 1 test test 16 Jan 4 12:59 install lrwxrwxrwx 1 test test 13 Jan 4 13:00 join lrwxrwxrwx 1 test test 11 Jan 4 12:59 ld lrwxrwxrwx 1 test test 15 Jan 4 13:00 ld.bfd lrwxrwxrwx 1 test test 12 Jan 4 12:59 ldd lrwxrwxrwx 1 test test 16 Jan 4 13:00 ld.gold lrwxrwxrwx 1 test test 11 Jan 4 12:59 ln lrwxrwxrwx 1 test test 11 Jan 4 12:59 ls lrwxrwxrwx 1 test test 13 Jan 4 13:00 lz4c lrwxrwxrwx 1 test test 13 Jan 4 12:59 make lrwxrwxrwx 1 test test 15 Jan 4 12:59 md5sum lrwxrwxrwx 1 test test 14 Jan 4 12:59 mkdir lrwxrwxrwx 1 test test 15 Jan 4 12:59 mkfifo lrwxrwxrwx 1 test test 14 Jan 4 12:59 mknod lrwxrwxrwx 1 test test 15 Jan 4 12:59 mktemp lrwxrwxrwx 1 test test 11 Jan 4 12:59 mv lrwxrwxrwx 1 test test 11 Jan 4 13:00 nc lrwxrwxrwx 1 test test 11 Jan 4 13:00 nl lrwxrwxrwx 1 test test 11 Jan 4 12:59 nm lrwxrwxrwx 1 test test 16 Jan 4 12:59 objcopy lrwxrwxrwx 1 test test 16 Jan 4 12:59 objdump lrwxrwxrwx 1 test test 11 Jan 4 12:59 od lrwxrwxrwx 1 test test 14 Jan 4 12:59 patch lrwxrwxrwx 1 test test 13 Jan 4 12:59 perl lrwxrwxrwx 1 test test 11 Jan 4 12:59 pr lrwxrwxrwx 1 test test 15 Jan 4 12:59 printf lrwxrwxrwx 1 test test 12 Jan 4 12:59 pwd lrwxrwxrwx 1 test test 16 Jan 4 12:59 python3 lrwxrwxrwx 1 test test 14 Jan 4 12:59 pzstd lrwxrwxrwx 1 test test 15 Jan 4 12:59 ranlib lrwxrwxrwx 1 test test 16 Jan 4 12:59 readelf lrwxrwxrwx 1 test test 17 Jan 4 12:59 readlink lrwxrwxrwx 1 test test 17 Jan 4 12:59 realpath lrwxrwxrwx 1 test test 11 Jan 4 12:59 rm lrwxrwxrwx 1 test test 14 Jan 4 12:59 rmdir lrwxrwxrwx 1 test test 15 Jan 4 12:59 rpcgen lrwxrwxrwx 1 test test 12 Jan 4 13:00 scp lrwxrwxrwx 1 test test 12 Jan 4 12:59 sed lrwxrwxrwx 1 test test 12 Jan 4 12:59 seq lrwxrwxrwx 1 test test 13 Jan 4 13:00 sftp lrwxrwxrwx 1 test test 11 Jan 4 12:59 sh lrwxrwxrwx 1 test test 16 Jan 4 12:59 sha1sum lrwxrwxrwx 1 test test 18 Jan 4 12:59 sha224sum lrwxrwxrwx 1 test test 18 Jan 4 12:59 sha256sum lrwxrwxrwx 1 test test 18 Jan 4 12:59 sha384sum lrwxrwxrwx 1 test test 18 Jan 4 12:59 sha512sum lrwxrwxrwx 1 test test 13 Jan 4 13:00 size lrwxrwxrwx 1 test test 14 Jan 4 12:59 sleep lrwxrwxrwx 1 test test 14 Jan 4 13:00 socat lrwxrwxrwx 1 test test 13 Jan 4 12:59 sort lrwxrwxrwx 1 test test 14 Jan 4 12:59 split lrwxrwxrwx 1 test test 12 Jan 4 13:00 ssh lrwxrwxrwx 1 test test 13 Jan 4 12:59 stat lrwxrwxrwx 1 test test 16 Jan 4 12:59 strings lrwxrwxrwx 1 test test 14 Jan 4 12:59 strip lrwxrwxrwx 1 test test 13 Jan 4 13:00 sudo lrwxrwxrwx 1 test test 13 Jan 4 12:59 tail lrwxrwxrwx 1 test test 12 Jan 4 12:59 tar lrwxrwxrwx 1 test test 12 Jan 4 12:59 tee lrwxrwxrwx 1 test test 13 Jan 4 12:59 test lrwxrwxrwx 1 test test 14 Jan 4 12:59 touch lrwxrwxrwx 1 test test 11 Jan 4 12:59 tr lrwxrwxrwx 1 test test 13 Jan 4 12:59 true lrwxrwxrwx 1 test test 14 Jan 4 12:59 uname lrwxrwxrwx 1 test test 13 Jan 4 12:59 uniq lrwxrwxrwx 1 test test 11 Jan 4 12:59 wc lrwxrwxrwx 1 test test 13 Jan 4 12:59 wget lrwxrwxrwx 1 test test 14 Jan 4 12:59 which lrwxrwxrwx 1 test test 14 Jan 4 12:59 xargs lrwxrwxrwx 1 test test 12 Jan 4 13:00 yes lrwxrwxrwx 1 test test 13 Jan 4 13:00 zcat lrwxrwxrwx 1 test test 13 Jan 4 12:59 zstd
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 ?
See Answer
$ cd build/tmp/work/raspberrypi4-poky-linux-gnueabi/sampleapp/1.0-r0/image/usr/bin/ $ ls -l -rwxrwxr-x 1 test test 16120 Jan 10 18:37 sampleapp
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 ?
See Answer
-t: Displays the symbols of application binary file
What “objdump” command does ?
See Answer
objdump: Display information from object files
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 ?
See Answer
-S : Display source code intermixed with disassembly
What is the purpose of “objdump” command ?
See Answer
The main purpose of the objdump tool is to debug and understand the executable file
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 ?
See Answer
-s: Display the symbol table
What “readelf” command does ?
See Answer
readelf: Display information about ELF files
What is the purpose of “readelf” command ?
See Answer
The main purpose of the readelf tool is to display the headers of an ELF (Executable and Linkable Format) files
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 ?
See Answer
-S: Print both value and size of defined symbols for the “bsd” output style
What “nm” command does ?
See Answer
nm is used to dump the symbol table and their attributes from a binary executable file.
What is the purpose of “nm” command ?
See Answer
The main purpose of the nm tool is to display information about symbols in the specified File, which can be an object file, an executable file, or an object-file library.
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 ?
See Answer
-s: When listing symbols from archive members, include the index: a mapping of which modules contain definitions for which names.
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 strippedWhy “file” command is used ?
See Answer
file command is used to determine the file type.
size: List section sizes and total size of binary files
$ size sampleapp text data bss dec hex filename 1812 616 8 2436 984 sampleappWhat “size” command does ?
See Answer
size command will display the output that will give you information on the size command in 5 values like data, text, dec, bss, and hex
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 ?
See Answer
strings command is used to return the string characters into files.
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
Other topics of linux rdkb rpi
Current Module
Next Module
Other Modules