Search icon
Arrow left icon
All Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletters
Free Learning
Arrow right icon
Instant Optimizing Embedded Systems Using BusyBox

You're reading from  Instant Optimizing Embedded Systems Using BusyBox

Product type Book
Published in Nov 2013
Publisher Packt
ISBN-13 9781783289851
Pages 72 pages
Edition 1st Edition
Languages

Adding new applets to a BusyBox-based embedded system (Intermediate)


If BusyBox built-in applets are not enough for our embedded requirement, new tools should be added.

This recipe shows three methods to integrate new utilities to a BusyBox-based embedded system.

Getting ready

In order to extend a fork of BusyBox by adding functionality from an existing utility, just compile and install the new utility as a separate binary, which will be explained later. But to distribute one binary exactly to our embedded system and get a smaller-sized system, integrating new applets into BusyBox is a direct method.

To do so, use the small sstrip program as an example. sstrip is a small utility that removes the contents at the end of an ELF file that are not part of the program's memory image. ELF (http://en.wikipedia.org/wiki/Executable_and_Linkable_Format) is the common standard file format for Linux executables.

Download it with SVN or download it from this link: https://dev.openwrt.org/browser/trunk/tools/sstrip/src/sstrip.c. In our example, use svn to check it out.

$ cd ~/tools/
$ svn co svn://dev.openwrt.org/openwrt/trunk/tools/sstrip

How to do it...

To add the sstrip program into BusyBox, follow these steps:

  1. Add the original tool to the BusyBox source code:

    The new applet should be added to a suitable directory of BusyBox. In our example, sstrip is a misc utility so we add it to miscutils/.

    $ cd ~/tools/busybox/
    $ cp ../sstrip/src/sstrip.c miscutils/sstrip.c
    
  2. Provide an applet-specific main entry, sstrip_main():

    The entry of a new applet should be named applet_main(). For sstrip, it should be sstrip_main().

    $ sed -i -e "s/int main/int sstrip_main/g" miscutils/sstrip.c
    
  3. Add usage information:

    Add the trivial and full usage macros into miscutils/sstrip.c.

    //usage:# define sstrip_trivial_usage
    //usage:# "sstrip FILE..."
    //usage:# define sstrip_full_usage "\n\n"
    //usage:# "sstrip discards all nonessential bytes from an executable.\n\n"
    //usage:# "Version 2.0-X Copyright (C) 2000,2001 Brian Raiter.\n"
    //usage:# "Cross-devel hacks Copyright (C) 2004 Manuel Novoa III.\n"
    //usage:# "This program is free software, licensed under the GNU\n"
    //usage:# "General Public License. There is absolutely no warranty.\n"

    By default, the trivial usage is added to minimize the size of the compiled binary, but if you want verbose output with full usage information, the CONFIG_FEATURE_VERBOSE_USAGE option should be enabled.

  4. Add configuration support:

    We add the configuration description at the end of miscutils/Config.src.

    config SSTRIP
       bool "sstrip"
       default n
       help
       sstrip is a small utility that removes the
       contents at the end of an ELF file that
       are not part of the program's memory image.

    This allows users to enable or disable the sstrip applet via the configuration utility.

  5. Add compiling support:

    Add compiling support at the end of miscutils/Kbuild.src.

    lib-$(CONFIG_SSTRIP)      += sstrip.o

    This builds the sstrip binary in the last BusyBox binary when the CONFIG_SSTRIP configure option is enabled.


  6. Add macros declaration about main entry, usage information, links, and the installation directory:

    Add the following line to include/applets.src.h to add the necessary macros.

    IF_SSTRIP(APPLET(sstrip, BB_DIR_USR_SBIN, BB_SUID_DROP))

    It lets BusyBox install sstrip to /usr/bin at the compiling stage with make install, and also exports the macros about the main entry, usage information, and links.

  7. Use common header files:

    Later, replace all of its header files except <elf.h> with libbb.h.

  8. Configure and compile it:

    To build sstrip in the BusyBox binary, enable it with make menuconfig:

       Miscellaneous Utilities  --->
          [*] sstrip
    

    The docs/new-applet-HOWTO.txt file provides more information about how to add a new applet, but part of it is out of date. Real examples may be better references; for example, miscutils/chrt.c.

How it works...

BusyBox is modular and highly configurable. As seen previously, a new applet can be easily integrated, except renaming the main entry. The configure, build, and header files are added or modified for configuration, compiling, and installation respectively.

Since the main() entry is used by the BusyBox binary itself, the other applets' entries should be renamed with their own names.

The change in miscutils/Config.src adds a configure symbol, CONFIG_SSTRIP, with respective help information.

The modification in miscutils/Kbuild.src allows sstrip to be compiled while the CONFIG_SSTRIP symbol is enabled.

The addition in include/applets.src.h declares the prototypes of the new applet, sstrip, and the respective usage, main entry, and links.

There's more...

Lightweight tools like sstrip can be simply integrated into the BusyBox package. But for getting more functional utilities for our embedded systems, such methods don't work. However, we do have two other methods.

  • Build standalone tools:

    One method is to compile the existing tools independently and then add them into a BusyBox-based embedded system.

    As an example, we add a more powerful shell interpreter, Bash 4.2, into a BusyBox-based embedded system, and then download and compile it for ARM.

    $ sudo apt-get install bison autoconf
    $ cd ~/tools
    $ git clone git://git.savannah.gnu.org/bash.git
    $ cd bash
    $ git checkout -b bash-4.2 f281b8f4f
    $ ./configure –host=arm-linux-gnueabi --enable-static-link \ --without-bash-malloc
    $ make
    

    Now the compiled Bash can be put into ramdisk.img and used instead of BusyBox ash. Note that Bash is really powerful for writing shell scripts, but does cost more storage. It should not be used for a size-critical embedded system but rather for testing.

  • Automated building systems:

    Another method is to use automated building system; such systems include Buildroot. Buildroot can automate the procedure we performed in the Building BusyBox-based embedded system (Intermediate) recipe. It facilitates the generation of a complete embedded Linux system. It not only includes a root filesystem and a kernel image, but also a cross-compilation toolchain and a bootloader image. The root filesystem integrates BusyBox and other powerful utilities, and even programming environments.

    To build ramdisk.img automatically with Buildroot, create a configuration file, android_emulator_ramdisk_defconfig, first:

    # architecture
    BR2_arm=y
    BR2_cortex_a8=y
    BR2_EXTRA_GCC_CONFIG_OPTIONS="--with-fpu=vfpv3 --with-float=hard"
    # BR2_SOFT_FLOAT is not set
    
    # system
    BR2_TARGET_GENERIC_HOSTNAME="android-emulator"
    
    # development files, required by develop tools
    BR2_DEPRECATED=y
    BR2_HAVE_DEVFILES=y
    
    # gcc
    BR2_PACKAGE_GCC_TARGET=y
    
    # package with cpio+gzip for init ramfs
    BR2_TARGET_ROOTFS_CPIO=y
    BR2_TARGET_ROOTFS_CPIO_GZIP=y
    # BR2_TARGET_ROOTFS_TAR is not set
    
    # bash shell
    BR2_PACKAGE_BUSYBOX_SHOW_OTHERS=y
    BR2_PACKAGE_BASH=y

    This configuration file allows us to build a BusyBox-based embedded system in the gzipped cpio archive with GCC and Bash support for the ARM target with Cortex A8 CPU.

    Now download, configure, and compile it as follows:

    $ cd ~/tools
    $ wget http://www.buildroot.org/downloads/buildroot-2013.05.tar.bz2
    $ tar jxf buildroot-2013.05.tar.bz2
    $ cp android_emulator_ramdisk_defconfig .config
    $ make oldconfig
    $ make
    

    The default major number of ttyS device is not the same as the Android ttyS device.

    $ adb shell cat /proc/devices | grep ttyS
    253 ttyS
    

    The default tty console is not ttyS0, but ttyS2. So, we need to fix them and repackage ramdisk.img.

    $ sed -i -e '/ttyS\t/s#4\t#253\t#g' system/device_table_dev.txt 
    $ sed -i -e "/ttyS0/ittyS2::respawn:/sbin/getty -L ttyS2 115200 vt100" output/target/etc/inittab
    $ make
    

    After compiling, a target ramdisk image, output/images/rootfs.cpio.gz, should be ready for the Android emulator.

    $ cp output/images/rootfs.cpio.gz ramdisk.img
    $ emulator @busybox-avd -ramdisk ./ramdisk.img \
    -show-kernel - shell -no-window
    ...
    Welcome to Buildroot
    android-emulator login:
    

    After booting, log in as a root user. We can use the native GCC compiler directly without any extra configuration. The -no-window option disables window output for this simple root filesystem, and it doesn't include window support.

    If you want to avoid some of the pitfalls of cross-compilation and want to build C applications directly on the Android device as an exercise, a native C programming environment can be built for Android system by creating another configuration file, android_emulator_defconfig.

    # architecture
    BR2_arm=y
    BR2_cortex_a8=y
    BR2_EXTRA_GCC_CONFIG_OPTIONS="--with-fpu=vfpv3 --with-float=hard"
    # BR2_SOFT_FLOAT is not set
    
    # system
    BR2_TARGET_GENERIC_HOSTNAME="android-emulator"
    
    # development files, required by develop tools
    BR2_DEPRECATED=y
    BR2_HAVE_DEVFILES=y
    
    # gcc
    BR2_PACKAGE_GCC_TARGET=y
    
    # don't compile busybox in
    BR2_INIT_NONE=y
    # BR2_PACKAGE_BUSYBOX is not set
    
    # don't tar of the rootfs
    # BR2_TARGET_ROOTFS_TAR is not set

    This configuration file tells us to compile the native compiler, GCC, for our ARM target device without BusyBox support and without packaging the target root filesystem.

    Now, configure and compile it as follows:

    $ cp android_emulator_defconfig .config
    $ make oldconfig
    $ make
    

    Then prepare a configuration, native-gcc.rc, for the setting of environment variables as follows:

    # Compile and Using uClibc library based native gcc compiler in Android system
    export GCC_VER=4.7.3
    export GCC_HOME=/data/gcc/
    export GCC_NAME=arm-buildroot-linux-uclibcgnueabi
    export GCC_LIB=$GCC_HOME/usr/lib/gcc/$GCC_NAME/$GCC_VER/
    export GCC_LIBEXEC=$GCC_HOME/usr/libexec/gcc/$GCC_NAME/$GCC_VER/
    export PATH=$GCC_HOME/bin:$GCC_HOME/sbin:$GCC_HOME/usr/bin:$GCC_HOME/usr/sbin:$PATH
    export PATH=$GCC_HOME/usr/lib/ldscripts/:$GCC_LIB:$GCC_LIBEXEC:$PATH
    export LD_LIBRARY_PATH=$GCC_HOME/usr/lib:$GCC_HOME/lib:$GCC_LIB:$GCC_LIBEXEC:$LD_LIBRARY_PATH
    export LIBRARY_PATH=$LD_LIBRARY_PATH
    export C_INCLUDE_PATH=$GCC_HOME/usr/include:$GCC_LIBEXEC/include/:$GCC_LIBEXEC/include-fixed
    
    [ ! -d /lib ] && mkdir /lib
    ln -sf $GCC_HOME/lib/ld-uClibc.so.0 /lib/ld-uClibc.so.0

    This file mainly configures the PATH, LD_LIBRARY_PATH, LIBRARY_PATH, and C_LINCLUDE_PATH environment variables to let GCC works as is.

    At last, let's push the target directory and configuration to the Android system, and use the native GCC to compile a simple program as follows:

    $ adb push output/target /data/gcc
    $ adb push native-gcc.rc /data/
    $ adb shell
    root@android:/ # source /data/native-gcc.rc
    root@android:/ # echo -e '#include <stdio.h>\nmain(void){ printf("Hello, Android\\n"); }' | gcc -xc -o t - && ./t
    Hello, Android
    

In reality, with Bash (the popular shell-scripting environment) and with C (the popular native programming environment), we're able to re-use lots of existing shell scripts, C software, or write new ones for our BusyBox-based embedded system to enhance its functionality to a very flexible extent.

arrow left Previous Chapter
You have been reading a chapter from
Instant Optimizing Embedded Systems Using BusyBox
Published in: Nov 2013 Publisher: Packt ISBN-13: 9781783289851
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $15.99/month. Cancel anytime}