9 min read

(For more resources related to this topic, see here.)

BusyBox Compiling

BusyBox, the Swiss Army Knife of Embedded Linux, it can be compiled into a single binary for different architectures.

Before compiling software, we must get a compiler and the corresponding libraries, a build host and a target platform, the build host is the one running the compiler, the target platform is the one running the target binary. Herein, the desktop development system is a 64 bit X86 Ubuntu systems, it will be used as our build host, and an ARM Android system will be used as our target platform.

To compile BusyBox on X86-64 Ubuntu system for ARM, we need a cross compiler.

The gcc-arm-linux-gnueabi cross compiler can be installed directly on Ubuntu:

$ sudo apt-get install gcc-arm-linux-gnueabi

On the other Linux distributions, Google’s official NDK is a good choice if want to share Android’s Bionic C library, but since Bionic C library lacks lots of POSIX C header files, if want to get most of BusyBox applets building, the prebuilt version of Linaro GCC with Glibc is preferable, we can download it from http://www.linaro.org/downloads/, for example:

http://releases.linaro.org/13.04/components/toolchain/binaries/gcc-linaro-aarch64-none-elf-4.7-2013.04-20130415_linux.tar.bz2.

Before compiling, to simplify the configuration, enable the largest generic configuration with make defconfig and configure cross compiler: arm-linux-gnueabi-gcc with: make menuconfig.

$ make defconfig $ make menuconfig Busybox Settings ---> Build Options ---> (arm-linux-gnueabi-) Cross Compiler prefix

After configuration, we can simply compile it with:

$ make

Then, a BusyBox binary will be compiled for ARM:

$ file busybox busybox: ELF 32-bit LSB executable, ARM, version 1
(SYSV), dynamically linked (uses shared libs), stripped

To list the shared libraries required by BusyBox binary for ARM, a command arm-linux-gnueabi-readelf should be used:

$ arm-linux-gnueabi-readelf -d ./busybox grep "Shared library:" | cut -d'[' -f2 | tr -d ']'| libm.so.6 libc.so.6 ld-linux.so.3

To get the full path, we can get the library search path at first:

$ arm-linux-gnueabi-ld --verbose grep SEARCH | tr ';' 'n' | cut -d'"' -f2 | tr -d '"'| /lib/arm-linux-gnueabi /usr/lib/arm-linux-gnueabi /usr/arm-linux-gnueabi/lib

Then, we can find out that /usr/arm-linux-gnueabi/lib is the real search path in our platform and we can get the full path of the libraries as below:

$ ls /usr/arm-linux-gnueabi/lib/{libm.so.6,libc.so.6,ld-linux.so.3} /usr/arm-linux-gnueabi/lib/ld-linux.so.3 /usr/arm-linux-gnueabi/lib/libc.so.6
/usr/arm-linux-gnueabi/lib/libm.so.6

By default, the binary is dynamically linked, to enable static linking, configure BusyBox as following:

Busybox Settings ---> Build Options ---> [*] Build BusyBox as a static binary (no shared libs)

If using a new Glibc to compile BusyBox with static linking, to avoid such error:

inetd.c:(.text.prepare_socket_fd+0x7e): undefined reference to `bindresvport'

We need to disable CONFIG_FEATURE_INETD_RPC:

Networking Utilities ---> [*] inetd [ ] Support RPC services

Then, recompile it with make.

BusyBox Installation

This section shows how to install the above compiled BusyBox binaries on an ARM Android system.

The installation of BusyBox means to create soft links for all of its built-in applets, use wc applet as an example:

$ ln -s busybox wc $ echo "Hello, Busybox." ./wc -w| 2

BusyBox can be installed at the earlier compiling stage or at run-time.

To build a minimal embedded file system with BusyBox, we’d better install it at the compiling stage with ‘make install‘ for it helps to create the basic directory architecture of a standard Linux root file system and create soft links to BusyBox under the corresponding directories. With this installation method, we need to configure the target installation directory as following, use ~/busybox-ramdisk/ directory as an example:

Busybox Settings ---> Installation Options ("make install" behavior) ---> (~/busybox-ramdisk/) BusyBox installation prefix

After installation, we may get such a list of the file and directories:

$ ls ~/busybox-ramdisk/ bin linuxrc sbin usr

But to install it on an existing ARM Android system, it may be easier to install BusyBox at run-time with its –install option.

With –install, by default, hard links will be created, to create soft links (symbolic links), -s option should be appended. If want to create links across different file systems (E.g. in Android system, to install BusyBox to /system/bin but BusyBox itself is put in the /data directory), -s must be used.

To use the -s option, BusyBox should be configured as below:

Busybox Settings ---> General Configuration ---> [*] Support --install [-s] to install applet links at runtime

Now, let’s introduce how to install the above compiled BusyBox binaries to an existing ARM Android system.

To do so, the Android system must be rooted to make sure the /data and / directories are writable. We will not show how to root an Android device, please get help from your product maker. Or if no real rooted Android device available, the Android emulator (emulator) provided by ADT (Android Development Toolkit, http://developer.android.com/sdk/index.html) can be used to start a rooted Android system on a virtual ARM Android device. To create a virtual ARM Android device and to use the Android emulator, please read the online documents provided by Google on http://developer.android.com/tools/help/android.html and http://developer.android.com/tools/help/emulator.html.

Now, let’s assume a rooted Android system is already running there with the USB debugging option enabled for Android Debug Bridge (adb, http://developer.android.com/tools/help/adb.html) support, for example, to check if such a device is started, we can run:

$ adb devices List of devices attached emulator-5554 device

As we can see, a virtual Android device running on Android emulator: emulator-5554 is there.

Now, we are able to show how to install the BusyBox binaries on the existing Android system. Since the dynamically linked and statically linked BusyBox binaries are different, we will introduce how to install them respectively.

  • Install the statically linked Busybox binary

    To install the statically installed Busybox binary, we only need to upload the BusyBox binary itself:

    $ adb push busybox /data/

    Afterwards, install it with the –install option, for example, install it to the /bin directory of the Andriod system:

    $ adb shell root@android:/ # mount -o remount,rw / root@android:/ # mkdir /bin/ root@android:/ # /data/busybox --install -s /bin

    To be able to create the /bin directory for installation, the / directory is remounted to be writable. After installation, soft links are created under /bin for all of the built-in applets.

    If the -s option is not used, it will fail to create the hard links across the /bin and /data directories, that’s why we must use -s option, the failure log looks like:

    busybox: /bin/[: Invalid cross-device link busybox: /bin/[[: Invalid cross-device link busybox: /bin/acpid: Invalid cross-device link busybox: /bin/add-shell: Invalid cross-device link (...truncated...)

    To execute the just installed applets, use md5sum as an example:

    $ /bin/md5sum /bin/ls 19994347b06d5ef7dbcbce0932960395 /bin/ls

    To run the applets without the full path, the /bin directory should be appended to the PATH variable:

    $ export PATH=$PATH:/bin

    Then, all of the BusyBox applets can be executed directly, that means we have installed Busybox successfully.

    To make the settings permanently, the above commands can be added to a script and such a script can be run as an Android service.

  • Install the statically linked Busybox binary

    To install the statically installed Busybox binary, we only need to upload the BusyBox binary itself:

    $ adb push busybox /data/

    Afterwards, install it with the –install option, for example, install it to the /bin directory of the Andriod system:

    $ adb shell root@android:/ # mount -o remount,rw / root@android:/ # mkdir /bin/ root@android:/ # /data/busybox --install -s /bin

    To be able to create the /bin directory for installation, the / directory is remounted to be writable. After installation, soft links are created under /bin for all of the built-in applets.

    If the -s option is not used, it will fail to create the hard links across the /bin and /data directories, that’s why we must use -s option, the failure log looks like:

    busybox: /bin/[: Invalid cross-device link busybox: /bin/[[: Invalid cross-device link busybox: /bin/acpid: Invalid cross-device link busybox: /bin/add-shell: Invalid cross-device link (...truncated...)

    To execute the just installed applets, use md5sum as an example:

    $ /bin/md5sum /bin/ls 19994347b06d5ef7dbcbce0932960395 /bin/ls

    To run the applets without the full path, the /bin directory should be appended to the PATH variable:

    $ export PATH=$PATH:/bin

    Then, all of the BusyBox applets can be executed directly, that means we have installed Busybox successfully.

    To make the settings permanently, the above commands can be added to a script and such a script can be run as an Android service.

  • Install the dynamically linked BusyBox binary

    For a dynamically linked BusyBox, to install it, besides the installation of the BusyBox binary itself, the required dynamic linker/loader (ld-linux.so) and the dependent shared libraries (libc.so and libm.so) should be installed too. For the basic installation procedure are the same as the one for statically linked BusyBox, herein, we only introduce how to install the required ld-linux.so.3, libc.so.6 and libm.so.6.

    Without the above dynamic linker/loader and libraries, we may get such error while running the dynamically linked BusyBox:

    $ /data/busybox --install -s /bin /system/bin/sh: /data/busybox: No such file or directory

    Before installation, create another /lib directory on target Android system and then upload the above files to it:

    $ adb shell mkdir /lib $ adb push /usr/arm-linux-gnueabi/lib/ld-linux.so.3 /lib/ $ adb push /usr/arm-linux-gnueabi/lib/libc.so.6 /lib/ $ adb push /usr/arm-linux-gnueabi/lib/libm.so.6 /lib/

    With the above installation, the dynamically linked BusyBox binary should also be able to run and we are able to install and execute its applets as before:

    $ /data/busybox --install -s /bin

    As we can see, the installation of the dynamically linked BusyBox binary requires extra installation of the dependent linker/loader and libraries.

For real embedded system development, if only the BusyBox binary itself uses the shared libraries, the static linking should be used instead at compiling to avoid the extra installation and the time-cost run-time linking, otherwise, if many binaries share the same libraries, to reduce the total size cost for the size critical embedded systems, dynamic linking may be preferable.

Summary

In this article we learned about BusyBox compiling and its installation. BusyBox is a free GPL-licensed toolbox aimed at the embedded world. It is a collection of the tiny versions of many common Unix utilities.

Resources for Article :


Further resources on this subject:


LEAVE A REPLY

Please enter your comment!
Please enter your name here