glibc based Minimal Root File Systems using tsrpm

This article describes how to use rpm based tools from Timesys to build a Busybox based minimal Root File System from RPMs available on LinuxLink. This article assumes you have knowledge of mounting an RFS over NFS, flash file systems, command line utilites and downloading RPMs from the LinuxLink Repository. You can reference the Target Configurator documentation for instructions on creating an RFS with TimeStorm. Tsrpm is Timesys' command line system configuration tool. It is included with each reference distribuition and is installed under /opt/timesys/bin/

When building an RFS for your target there are many options. Some developers will need many packages while others just want the basics. This article will focus on building the minimal RFS the developer needs to have a bootable target.

The determining factors in minimal RFS size are the C library (glibc or uClibc) that you choose and using Busybox to replace bash and coreutils.

uClibc is small C standard library intended for embedded Linux systems. Choosing uClibc over glibc can save over 10 megabytes on an uncompressed file system.

BusyBox is known as "The Swiss Army Knife of Embedded Linux". It is a single binary that replaces the most common GNU system utilities. Once your BusyBox RFS is built, look in it's /bin directory. You will see that utilities such as ps and ls are actually symbolic links the busybox binary. When you invoke busybox with a symlink it uses the name of the link as an input variable to determine which action to take. So executing the ls symlink is the same as executing 'busybox ls'.

Depending on how involved you want to get in customizing the RFS there are some things you can do to conserve storage space. Many of the packages for a minimal RFS simply configure things such as device nodes, init scripts and configuration files. If you aren't afraid of a little extra system configuration you can skip these extra packages, save over one megabyte and have more granular control over your operating system.

For a bare bones RFS you will need the following packages:

  • busybox
  • libgcc
  • A standard C Library (either uClibc or Glibc)

For a ready-to-go out-of-the-box RFS you will need the following additional packages:

  • filesystem
  • setup
  • timesys-init
  • timesys-init-busybox

So we have two C libraries and two minimal package lists (let's call them easy-minimal and very-minimal) for a total of four combinations of a Root File Systems.

The easy-minimal RFS

Let's begin with the easiest route to a bootable RFS. The easy-minimal configuration has the additional system configuration RPMs included. To create the RFS follow these steps:

  • Create an empty directory
  • Download your packages from the LinuxLink repository and place them in the new empty directory. Please remember to get them from the appropriate target subdirectory (either uClibc or glibc) depending on which Standard C library you are using. The required packages are:
    • either uClibc or glibc
    • busybox
    • libgcc
    • filesystem
    • setup
    • timesys-init
    • timesys-init-busybox
  • Issue the following command in the directory where you placed the RPMs.
    sudo tsrpm --target=<arch> --install *.rpm

That is it. After tsrpm runs you will have a bootable RFS in the <arch>/root directory under your current working directory. When issuing the tsrpm command the "target=" options tells tsrpm which subdirectory to create the RFS and the assocaited directories. Generally the processor architecture is used. For example: target=armv5l for a glibc based RFS or target=armv5l-uclibc for a uClibc based RFS.

The RFS created with the above command will boot on your target and execute /etc/rc.timesys from /etc/inittab on start up. The standard rc.timesys script will mount /proc, create device nodes and start Busybox's syslogd and telnetd. You can edit this script to execute anything on the filesystem that you want to happen on boot-up.

The standard inittab does not give the user an option to log on to the board directly (that is why telnetd is started). You can modify inittab to include the following line if you would like to log into the board from the console:
console::respawn:/sbin/getty -L console 115200 vt100

From this point you can copy the RFS to an NFS exported directory or use your favorite utility to create a disk image which you can flash on to your target. The glibc based RFS is 13MB while the uClibc based RFS is only 2.5MB. Running these RFSs through mkfs.jffs2 produces images of 6.3MB for glibc and 916k for uClibc. Your mileage may vary on the disk image size, but you can see that there is a substantial difference.

The very-minimal RFS

If you are not adverse to working on a command line and would like to get your RFS even smaller you can use tsrpm in conjuction with some common command line utilies to create a very-minimal RFS. This requires only three rpms from the repository. Configuring your RFS in this manner will take a little longer but you will have finer control over which processes are running and a greater knowledge of the running system in addition to the size advantages.

The steps to create the base RFS are:

  • Create an empty directory
  • Download your packages from the LinuxLink repository and place them in the new empty directory. Please remember to get them from the appropriate target subdirectory (either uClibc or glibc) depending on which Standard C library you are using. The required packages are:
    • either uClibc or glibc
    • busybox
    • libgcc
  • Issue the following command in the directory where you placed the RPMs.
    sudo tsrpm --target=<arch> --install *.rpm

As with the first example tsrpm creates the RFS in <arch>/root.

At this point the RFS is not yet bootable. You need to create the console and null device nodes so the kernel has places to output information to when it is booting. The steps are:

  • cd <arch>/root/dev
  • sudo mknod console c 5 1
  • sudo mknod null c 1 3

Now you have a bootable RFS. The uncompressed uClibc based RFS uses 1.6MB of disk space while the uncompressed glibc based RFS consumes a comparatively gigantic 12MB. Jffs2 disk image sizes are similarly mismatched at 745k for uClibc and 6.1MB for glibc. This very-minimal RFS won't do much upon boot. At this point the RFS has no user control, very few device nodes, no proc filesystem, no ip address and will boot straight to a /bin/sh prompt.

Two common modifications to a very-minimal RFS would be enabling user accounts/login and automatically executing scripts upon boot. These are accomplished by creating and configuring files under the RFS's /etc directory.

To enable multiple accounts and logins:

  • Create the following files on the RFS:
    /etc/inittab
    /etc/passwd
    /etc/group
  • Edit initab to include:
    console::respawn:/sbin/getty -L console 115200 vt100
  • Edit passwd to include:
    root::0:0:root:/:/bin/sh
  • Edit group to include:
    root::0:root

This will allow root to login with a blank password. You can use busybox's adduser, addgroup, passwd and group commands to manage your users on the target.

To enable automatic execution of a script named /etc/rc.timesys upon boot:

  • Edit inittab to include:
    ::sysinit:/etc/rc.timesys

You can then edit rc.timesys to mount /proc, create device nodes, configure networking (ifup scripts or udhcpd), start server daemons, initilize your application, etc. Anything you can do from a command line you can do automatically from this script.