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

Playing BusyBox on a virtual Android device (Intermediate)


This recipe uses a virtual Android device as the target platform that we just created to show the usage of BusyBox applets on an embedded platform. It will replace the Android toolbox mksh shell-based console with the more powerful BusyBox ash shell-based console. It starts a remote shell and a web service on it with BusyBox telnetd and httpd respectively.

The console based on BusyBox ash gives a more powerful shell environment. Not only can the applets be run on this console, but new shell scripts can also be written in such a shell environment.

The remote shell is useful for remote development and maintenance, and the web service is helpful for system monitoring. Both of them have common use cases in an embedded system.

Getting ready

At this stage, we aren't constructing a full bootable filesystem from scratch, but only using the BusyBox applets. So, for simplicity and ease of testing, we will install our compiled BusyBox binary and scripts into an existing Android ramdisk image.

At first, get a copy of the existing ramdisk.img; its path can be found at ~/.android/avd/busybox-avd.avd/hardware-qemu.ini; for example, adt-bundle-linux-x86_64/sdk/system-images/android-17/armeabi-v7a/ramdisk.img.

How to do it...

Three examples will be shown in this section to demonstrate the usage of the BusyBox applets on a virtual Android device.

  1. Replace the console based on Android mksh with the BusyBox ash console.

    Since the Android toolbox mksh shell is too lightweight, and the Android toolbox (the BusyBox-like toolset software) itself only provides a few of the applets, here it only shows us how to replace it with BusyBox ash. Start ash as the default console, and eventually build a more powerful shell environment.

    At first, decompress the original ramdisk image with the following steps:

    $ mv ramdisk.img ramdisk.img.gz
    $ gunzip ramdisk.img.gz
    $ mkdir ramdisk/ && cd ramdisk/
    $ cpio -i -F ../ramdisk.img
    

    Second, get a prebuilt BusyBox binary, busybox-armv7l, and put it into ramdisk/.

    $ wget http://busybox.net/downloads/binaries/latest/busybox-armv7l
    $ cp busybox-armv7l ramdisk/
    

    Third, to install BusyBox at runtime, let's prepare a script and name it busybox-console.sh, and add it into ramdisk/.

    #!/system/bin/sh
    # busybox-console.sh -- Install busybox to /bin and start /bin/ash
    
    # remount root file system for read and write
    mount -o remount,rw /
    mkdir /bin
    chmod 0777 /bin/
    chmod 0777 /busybox-armv7l
    /busybox-armv7l --install -s /bin
    
    export SHELL=/bin/ash
    /bin/ash
    

    It remounts the root filesystem to be readable and writable and allows us to install BusyBox with ––install to /bin at runtime; lastly, it starts /bin/ash.

    $ cp busybox-console.sh ramdisk/
    

    Then start a service in init.rc to launch the previous script. Add a chmod command to make sure the previous script is executable.

    $ cd ramdisk/
    $ sed -i '/loglevel/a \\n    chmod 0777 /busybox-console.sh' init.rc
    

    Let the BusyBox applets be executed directly without the full path.

    Append the installation directory of the BusyBox applet, /bin, to the default PATH environment.

    $ sed -i -e "s#export PATH #export PATH /bin:#g" init.rc
    

    Replace the original console service with our console service that is based on ash.

    $ sed -i -e "s#service console.*#service console /bin/busybox.sh#g" init.rc
    

    Now back up the old ramdisk and recompress a new one.

    $ mv ramdisk.img ramdisk-backup.img
    $ cd ramdisk/
    $ find . | cpio -H newc -o | gzip -9 > ../ramdisk.img
    

    Lastly, run the emulator to start with our new ramdisk and with the BusyBox ash console.

    $ emulator @busybox-emulator -ramdisk ./ramdisk.img -shell -show-kernel
    / # echo $SHELL
    /bin/ash
    / # ls /bin
    [                  fold               mke2fs             setsid
    (truncated to fit in the text)
    / # which ls
    /bin/ls
    

    This code only lists a part of the applets installed. As we can see, the shell becomes /bin/ash. The applets are installed under /bin and the ls command is not the one provided by Android toolbox (/system/bin/ls) but the one (/bin/ls) installed by BusyBox. This indicates that we have successfully changed the console service to our own.

    The writing of new shell scripts under this shell environment based on ash will be introduced in the Enhancing system stability of an embedded (Android) system recipe.

  2. Start a remote shell with BusyBox telnetd:

    A real embedded system may have no serial port and adb and no local cable connected, but a network connection with Wi-Fi or 3G; accessing such systems may need a remote shell. As a lot of remote shells exist, such as SSH and Telnet, and since BusyBox doesn't provide an SSH daemon but telnetd, we use telnetd as an example here.

    Firstly, start the service on an emulator from a virtual serial port.

    / # echo "Hello, telnetd" > /data/telnetd.issue
    / # telnetd -f /data/telnetd.issue -p 3333
    / # ps | grep telnetd | grep -v grep
      731 0     0:00 telnetd -f /data/telnetd.issue -p 3333
    

    Second, build an emulated network connection. Android emulator does not provide a standalone full emulated network stack but a port-redirection-based network stack. In order to use the network service, the adb forward command should be used to enable the port redirection feature.

    Say you want to access the telnetd service seen previously. The remote tcp:3333

    of the emulator must be redirected to a port of our desktop development system (for example, tcp:3333) by running the following command:

    $ adb forward tcp:3333 tcp:3333
    

    Third, log in to the telnet service and issue the following command on the development system:

    $ telnet localhost 3333
    Hello, telnetd
    localhost login:
    

    It means it really logs in and gets a prompt, Hello, telnetd. However, without a user account and the password, we cannot log in. To avoid setting up a username and password, we can simply let telnetd spawn /bin/ash rather than /bin/login, then no login progress will be required. Let's start telnetd on the emulator as follows:

    / # telnetd -p 3333 -f /data/telnetd.issue -l /bin/ash
    

    Log in to the shell directly and experiment with our Android device remotely.

  3. Start a web server with httpd:

    Firstly, start httpd at /data/www, and create a simple HTML page on the target platform from a virtual serial port as follows:

    / # mkdir /data/www
    / # httpd -h /data/www -p 8080
    / # cat > /data/www/index.html
    <!doctype html><html><head><title>BusyBox</title></head><body><h1>Hello, Busybox Http Server Works.</h1></body></html>
    

    Second, just like telnetd, make a port redirection from the emulator to the development system.

    # adb forward tcp:8080 tcp:8080
    

    Lastly, let's access the httpd service with any modern web browser on our development system. Here we use the Chromium browser as an example:

How it works...

BusyBox applets cover the standard coreutils, console tools, e2fsprogs, procps, SELinux, editors, modutils, debianutils, login-utils, networking, sysklogd, util-linux, findutils, mailutils, printutils, and even a tiny shell interpreter. This recipe shows how to install some of them at runtime on an existing Android system and demonstrates the working of these three applets: ash, telnetd, and httpd.

To add more function for an embedded system, the other applets may also need to be configured via the configuration utility and used based on their full usage information with the --help command.

There's more...

In order to start the previously mentioned service during boot, we can add httpd and telnetd in the previous /busybox-console.sh script.

# Start httpd service
httpd -h /data/www -p 8080
# Start telnetd service
telnetd -f /data/telnetd.issue -p 3333 -l /bin/ash

To access them, we must also forward the remote ports to the development system as follows:

$ adb forward tcp:3333 tcp:3333
$ adb forward tcp:8080 tcp:8080
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}