BusyBox is a collection of cut down versions of common UNIX utilities compiled into a single small executable. This makes BusyBox an ideal foundation for resource constrained systems.
Install the following prerequisites (assuming an Ubuntu 14.04 build machine):
apt-get install gcc-arm-linux-gnueabi apt-get install libncurses5-dev apt-get install gawk
BusyBox can be built either as a single static binary requiring no external libraries, or built requiring shared libraries such as GLIBC (default). This setting can be found under BusyBox Settings -> Build Options -> Build BusyBox as a static binary (no shared libs).
I generally choose to build BusyBox to require GLIBC as it is highly likely you will want to run additional applications that will require GLIBC sometime in the future.
wget https://busybox.net/downloads/busybox-1.32.1.tar.bz2 tar -xjf busybox-1.32.1.tar.bz2 cd busybox-1.32.1/ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- defconfig make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- menuconfig
At the menu, you can configure BusyBox options. Once configured, you can build BusyBox:
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- install CONFIG_PREFIX=/home/export/rootfs
GLIBC is the GNU C Library and includes common system calls required by executables running on your system.
Download, build and install GLIBC:
wget http://ftp.gnu.org/gnu/libc/glibc-2.33.tar.xz tar -xJf glibc-2.33.tar.xz mkdir glibc-build cd glibc-build/ ../glibc-2.33/configure arm-linux-gnueabi --build=i686-pc-linux-gnu CXX=arm-linux-gnueabi-g++ --prefix= --enable-add-ons make make install install_root=/home/export/rootfs
Some programs may require libgcc_s.so, otherwise you will receive an error:
error while loading shared libraries: libgcc_s.so.1: cannot open shared object file: No such file or directory
libgcc_s.so.1 can be copied over from your arm-linux-gnueabi installation:
cp /usr/lib/gcc-cross/arm-linux-gnueabi/4.7.3/libgcc_s.so.1 /home/export/rootfs/lib
Once BusyBox and GLIBC has been cross-compiled, you will want to create the remainder of the root file system. Start by creating the necessary directory structure:
mkdir proc sys dev etc/init.d usr/lib
Now we must mount the /proc & /sys filesystem and populate the /dev nodes. This can be done at runtime by creating a file called etc/init.d/rcS and adding:
#!bin/sh mount -t proc none /proc mount -t sysfs none /sys echo /sbin/mdev > /proc/sys/kernel/hotplug /sbin/mdev -s
and make executable:
chmod +x etc/init.d/rcS
You should now have a basic, yet quite functional, BusyBox root file system.
DropBear is a small SSH server and client and is useful to allow remote shell access to your system.
Download, build and install DropBear:
wget https://matt.ucc.asn.au/dropbear/releases/dropbear-2020.81.tar.bz2 tar -xjf dropbear-2020.81.tar.bz2 cd dropbear-2020.81 ./configure --host=arm-linux-gnueabi --prefix=/ --disable-zlib CC=arm-linux-gnueabi-gcc LD=arm-linux-gnueabi-ld make make install DESTDIR=/home/export/rootfs
DropBear requires RSA and DSS (Digital Signature Standard) encryption keys to be generated. I normally do this on the target, but you could generate the keys on the host if you have the dropbearkey executable installed.
To generate your keys:
mkdir /etc/dropbear dropbearkey -t dss -f /etc/dropbear/dropbear_dss_host_key dropbearkey -t rsa -f /etc/dropbear/dropbear_rsa_host_key
You will also require users and passwords to validate login credentials:
touch /etc/passwd touch /etc/group adduser root -u 0
Unless otherwise specified, root will be given a default home directory of /home/root. However as this doesn't exist, DropBear will close your connection immediately after successfully logging in. To address this, simply create a home directory for root:
mkdir /home /home/root
DropBear can now be started by running:
and you should be able to remotely login to your system using the root user.
If you get an error after logging in, "Server refused to allocate pty" check you have Device Drivers > Character devices > Legacy (BSD) PTY support enabled in your kernel. (Especially applicable to Beaglebone kernels)
Alternatively, make sure you have mounted the /dev/pts filesystem (after /dev has been mounted)
mkdir /dev/pts mount -t devpts none /dev/pts
ldconfig is used to configure dynamic linker run-time bindings. It creates symbolic links and a cache to the most recent shared libraries. As you build upon your root filesystem and add additional libraries, you may need to run ldconfig.
ldconfig will search for libraries in the trusted directory /lib. Additional search paths can be added to the ld.so.conf configuration file. ldconfig looks for a configuration file in /etc/ld.so.conf and generates a warning if this cannot be found. Suppress the warning and extend the search range to include /usr/lib by:
echo /usr/lib > etc/ld.so.conf
ldconfig will also generate a cache at /etc/ld.so.cache. If this file doesn't exist, it will be automatically generated.
Finally, to update the dynamic linker run-time bindings with verbose output, execute:
If you are using a root file system residing on flash memory, to improve longevity it may be desirable to either mount your rootfs as read only, or to move as many of the frequently written to files (for example /var) to a temporary volatile file system stored in RAM.
The following is an expanded etc/init.d/rcS file demonstrating this.
We mount /var and /dev as tmpfs. The device nodes are generated using mdev at boot and from hotplug, hence we move these to a temp file system otherwise they could not be generated on a read only root filesystem.
#!bin/sh mount -t proc none /proc mount -t sysfs none /sys mount -t tmpfs none /var mount -t tmpfs none /dev echo /sbin/mdev > /proc/sys/kernel/hotplug /sbin/mdev -s mkdir /var/log syslogd dropbear
syslogd writes system messages to /var/log/messages and is something you probably don't want constantly writing to flash. After mounting /var as a temp file system, we create the /var/log directory for systemd.