How to create a very small Linux system using Buildroot


Have you ever tried to install a modern Linux distro onto a small capacity (usually 32 megs or even less) usb drive or compact flash card?

Even with a minimal install, such a distribution will not fit! Major Linux distros like Debian/Slackware/Arch/etc need a bare minimum of 300-400 megs of disk space.

The only minimal system I have been able to install so far on a 128Meg disk is NetBSD ( http://www.netbsd.org ).

But there is a way to achieve such a thing : we will be using Buildroot in order to generate a very small (embedded) Linux system (targeted at a standard intel x86  computer)

In this tutorial I have used a Ubuntu 10.04 system as my build machine.

Buildroot :

http://buildroot.uclibc.org/

Documentation :

http://buildroot.uclibc.org/buildroot.html

Prior to using it, you’ll have to install a development environment on your system (GCC compiler, Linux kernel headers, make tools etc). On Debian/Ubuntu, this is done by installing packages such as :

  • build-essentials

First of all, we need to download and setup Buildroot on our build machine.

As a standard user (not root) :

# cd
# wget http://buildroot.uclibc.org/downloads/buildroot-snapshot.tar.bz2
# tar xvjf buildroot*
# cd buildroot

Buildroot Configuration

# make menuconfig

Now you have to select some options :

My target architecture is an x86 system, optimized for Pentium (i686). But your mileage may vary :)

Target Architecture : i386
Target Architecture Variant : i686

Toolchain —>
[X] Enable large file

System Configuration —>
System hostname : choose your system name
System banner : anything you want
[X] Generic serial port config (can be useful)

Update 01-07-2012 :

Now you need to set

“Port to run a getty (login prompt) on” to tty1 instead of ttyS0, in order to get a login prompt when booting your generated system!

 

Package Selection for the target

We select here the software packages we want to be in our embedded system

[X] Show packages that are also provided by busybox
[X] Customize

In this example I chose the following :

- support for foreign keyboard layouts

Hardware handling –>
[X] kbd

- optional, but can be useful

[X] makedevs

- some lightweight networking apps : dropbear (SSH server) , thttpd (ultra small http server)

Networking applications —>
[X] dropbear

[X] thttpd

- I like the nano text editor too

Text editors and viewers —>

[X] nano

Target filesystem options —>
[X] initramfs for initial ramdisk of linux kernel

Uncheck the other options.

This way, our system files (rootfs) will be contained within the kernel file, and loaded into RAM by the kernel.

(note : cramfs does the same, but is older and limited to a 16Meg rootfs max.)

Bootloaders —>

Uncheck everything here. We will test our image using qemu so we don’t need a bootloader yet. If you want to put your embedded system on a bootable USB drive, you can use SYSLINUX/EXTLINUX to make it bootable (see here!).

Kernel —>
[X] Linux Kernel

Important :

in Defconfig name,  enter the value :  i386

it corresponds to the linux-2.6.37/arch/x86/configs/i386_defconfig file

(otherwise the build system will complain that it couldn’t find a kernel configuration file).

Now select Exit to end the Buildroot configuration, save the changes of course (These settings are stored in the .config file in the Buildroot directory).

It’s time to start compiling!

# make

The first compilation will take some time, as software packages for the toolchain and other components are downloaded, extracted and compiled on your build machine!

TIP :

If you need to configure the linux kernel for your special needs (you’ll likely have to) :
# make linux-menuconfig

Important especially : remember to include support for the EXT2 filesystem in your kernel, if you want to be able to mount EXT2 formatted devices (usb flash drive for example) from your embedded system!

If everything went well, the compilation is finished and your final system files (kernel and optional boot and rootfs files) will be found in the output/images sub-directory of your Buildroot.

In our example, we can see that the obtained kernel file : bzImage,  is very small (above 5 megs, with and LZMA compressed initramfs filesystem)!

TIP

To force the complete rebuild of your embedded system :
# rm -rf output/build
# make

Testing our embedded system

We can use the QEMU emulator on our build host to do so.

# apt-get install qemu

# qemu -kernel output/images/bzImage
The default root login (as generated by Buildroot) has no password. There also exists a standard user named “default” (no password too).

login: root
password: (none)

Now you can play with your lightweight (yet somewhat limited) sytem :

in order to start the network interface :

# ifconfig eth0

# udhcpc eth0

look at the busybox available commands :

# busybox

TIP

load a keymap :
# loadkeys fr

Ok, we have a new system, but some things have to be improved in order to make it more usable. We are going to apply changes to the root filesystem (rootfs) before it’s included in the kernel by Buildroot’s make process.

We’d like, amongst other things :
- that our preferred keymap be automatically loaded,
- the network to be automatically up and running,
etc

To do that, changes will be applied in the rootfs files contained in Buildroot’s output/target subdir.

For the keymap :

# cd output/target
# nano etc/init.d/S99keymap

——- file S99keymap —–
#!/bin/sh

loadkeys fr
——- file S99keymap —–

# chmod 755 etc/init.d/S99keymap

AN ALTERNATIVE WAY TO DO THIS WITH BUSYBOX! :

BusyBox has internal keymap manipulation commands
# dumpkmap >etc/french.kmap
# loadkmap </etc/french.kmap

See more at :  http://www.unixgarden.com/index.php/embarque/linux-embarque%C2%A0-busybox-%C2%AB%C2%A0in-a-nutshell%C2%A0%C2%BB

You can generate the .kmap file on your build host machine, then copy it to the rootfs
# apt-get install busybox
# sudo busybox dumpkmap >fr.kmap
# cp fr.kmap output/target/etc/

and then the  S99keymap file contains the following line instead :
loadkmap </etc/fr.kmap

For the network configuration, we modify the  etc/network/interfaces  file :

# nano etc/network/interfaces

——————————-
# Configure Loopback
auto lo
iface lo inet loopback

# automatically start eth0, with dhcp
auto eth0
iface eth0 inet dhcp
——————————-

While we are at it, we can modify the etc/TZ file, in order to have the correct timezone in our embedded system.

Hare the TZ value below corresponds to  Europe/Paris, see here for your preferred value : http://www.sonoracomm.com/support/20-voice-support/107-uclibc-tz

# echo "CET-1CEST-2,M3.5.0/02:00:00,M10.5.0/03:00:00" >etc/TZ

SECURITY enhancements :

- Change the root password :

There maybe other ways to do the trick, but I found this one to be working :

# apt-get install mkpasswd
# echo 'mynewpassword' | mkpasswd -s -m md5

then paste the obtained string : $1$2VnNG40d$3SSSNXs.FfPnzlx9CMHZE/   (you will obtain another value, this is just an example)
in the  output/target/etc/shadow file, like this :

——– -etc/shadow ———-
root:$1$2VnNG40d$3SSSNXs.FfPnzlx9CMHZE/:10933:0:99999:7:::

Let’s de-activate the “default” user login too :

modify the line :

default::10933:0:99999:7:::

into :

default:LK:10933:0:99999:7:::

(LK is for locked)

Other modifications (may be useful, some more testing needed!) :

To improve device hotplug support, add the two following lines

null::sysinit:/bin/echo /sbin/mdev >/proc/sys/kernel/hotplug
null::sysinit:/sbin/mdev -s

in the output/target/etc/inittab file. So that it looks :

——– etc/inittab ———

# Startup the system
null::sysinit:/bin/mount -t proc proc /proc
null::sysinit:/bin/mount -o remount,rw /
null::sysinit:/bin/mkdir -p /dev/pts
null::sysinit:/bin/echo /sbin/mdev >/proc/sys/kernel/hotplug
null::sysinit:/sbin/mdev -s
null::sysinit:/bin/mount -a
null::sysinit:/bin/hostname -F /etc/hostname

——– etc/inittab ———

Final generation of our embedded Linux system :

go back to the Buildroot directory, then

# make

TIP :

If you delete the whole output subir, your changes in the output/target rootfs will be lost (obviously!) so it may be more convenient to make your changes in the fs/skeleton subdir, so that they will be used when generating the target subdir.

There is still plenty of work to do in our embedded system, but you’ve got the process uncovered.

About these ads

28 thoughts on “How to create a very small Linux system using Buildroot

  1. hi,

    I followed your procedure, but i am getting kernel panic when I emulate using qemu.

    please help me. what is your build environment?

    Cheers,
    Venkat

    • Hi

      I’m using a Debian 6.0 virtual machine (VirtualBox) for my buildroot environment.

      Try starting qemu with -m 256 (to emulate 256Megs of RAM). By default qemu uses 128Megs, which might not be nough for bigger kernels.

      If that doesn’t still work, please show a screen capture and your qemu line :)

  2. Hi,
    I followed your steps, but in the end the qemu hangs on “starting tftpd.”. After googling, it seems it didn’t start console on serial port, but I can’t figure out what is the next. The inittab looks have the right ttyS0:

    # Put a getty on the serial port
    ttyS0::respawn:/sbin/getty -L ttyS0 38400 vt100 # GENERIC_SERIAL

    Can you help?

    • Hi,

      Looks like that we need to use “tty1″ instead of “ttyS0″ !

      Then you’ll have a login prompt in your buildroot system.

      I’m updating this howto

      Thanks & have fun!

  3. It’s working perfectly. This will be my starting point and look forward to reducing the memory consumption. Do you have any suggestion or link?

    Thanks and have a great day!

    DJ

    • Good!

      What are your memory requirements?

      You could configure the kernel to remove unneeded drivers and features, but this won’t give a big gain in memory consumption.

      I found that a minimal buildroot generated system (no X) with initramfs embedded within the kernel needs at least 27M of RAM to boot, not less.

      If you have less RAM, you might try to generate a kernel with no embedded initramfs, but then you need to create a virtual hard disk with the root filesystem on it (when using qemu).

      • Thanks for reply.
        I try to get down to 10M. Generating a kernel without initramfs seems a good option. How to create virtual disk with qemu? Thanks again.

  4. In Buildroot > Filesystem Images menu :

    - uncheck initramfs
    - check ext2 root filesystem

    Then boot the system with :

    qemu -kernel bzImage -append “root=/dev/sda” -hda rootfs.ext2

    And remember to include support for ext2 fs in the kernel (not as module), otherwise the kernel won’t be able to mount the rootfs.

    Still can’t boot with less than 24Mb of RAM!

    This is because the kernel needs this to decompress itself. We could try with an uncompressed kernel (but so far I don’t know how to obtain it)

    Or you may try with an older 2.6.27.58 kernel, with it I could boot on a 16Mb system!

  5. hi

    how it is possible that you have eth0 device present in the system? I do it by virtualbox and there is only lo device and sit0, i do the same with qemu but there’s no eth0 at all … what should i do in order to setup networking? thx

    • Hi,

      Have you configured your kernel with the ethernet drivers? (include them all in doubt)

      Also, paste your dmesg to pastebin and give us the link here so we can see what’s happening :)

      • i’ve got it, i had to compile some additional network driver to the kernel (Intel(R) 82575/82576 PCI-Express Gigabit Ethernet support + Intel(R) 82576 Virtual Function Ethernet support) and switch network adapter in vmware setting like Intel PRO/1000 MT Desktop (82540EM) under network – adapter 1 – “advanced” settings

  6. I tried to preapre my own linux by buildroot but after changed of ttyS0 to ttyS1 I still cannot see login promt, it hangs after dropbear dsa key generated. I didn’t add thttpd. I have tried to change baudrate and ttyS to higher but after two days of compiling my kernel still hangs after dropbear

  7. Hi, I tried your tutorial, but buildroot fails at building host-m4 :
    make[1]: Entering directory `/home/antoine/buildroot-2012.11.1/output/build/host-m4-1.4.16′
    make[1]: warning: -jN forced in submake: disabling jobserver mode.
    make[1]: *** INTERNAL: readdir: Not a directory
    . Stop.
    make[1]: maint.mk: Field ‘stem’ not cached: maint.mk

    make[1]: Leaving directory `/home/antoine/buildroot-2012.11.1/output/build/host-m4-1.4.16′

    I tried to use google, but I could not figure out what was wrong…

  8. I said I followed your tutorial to the letter but the launch of the initramfs image with the launch qemu hangs a thttpd server initialization
    my config is as follows
    Lubuntu 12.04 X64
    Intel core I3
    6 giga ram
    please help me thank you

  9. Hi,

    How can I build a system with buildroot which will be remember changes which I made on harddrive? So it will remember changes which I made in rootfs.cpio filesystem, or it will remember that I’ve added some new software.

    Regards,
    Piotr

    • Hi, I haven’t experimented that kind of things yet… But look at Slitaz, or even Slax. They have different mechanisms to do what you are looking for :)

  10. after the configuration and when i excute the make command i get this error message :

    –2013-04-06 08:12:51– http://ftp.gnu.org/pub/gnu/gmp/gmp-5.0.2.tar.bz2
    Connecting to 192.168.110.80:8080… failed: Connection timed out.
    Retrying.

    –2013-04-06 08:13:13– (try: 2) http://ftp.gnu.org/pub/gnu/gmp/gmp-5.0.2.tar.bz2
    Connecting to 192.168.110.80:8080… failed: Connection timed out.
    Retrying.

    –2013-04-06 08:13:36– (try: 3) http://ftp.gnu.org/pub/gnu/gmp/gmp-5.0.2.tar.bz2
    Connecting to 192.168.110.80:8080… failed: Connection timed out.
    Giving up.

    –2013-04-06 08:13:57– http://sources.buildroot.net//gmp-5.0.2.tar.bz2
    Connecting to 192.168.110.80:8080… failed: Connection timed out.
    Retrying.

    –2013-04-06 08:14:19– (try: 2) http://sources.buildroot.net//gmp-5.0.2.tar.bz2
    Connecting to 192.168.110.80:8080… failed: Connection timed out.
    Retrying.

    –2013-04-06 08:14:42– (try: 3) http://sources.buildroot.net//gmp-5.0.2.tar.bz2
    Connecting to 192.168.110.80:8080… failed: Connection timed out.
    Giving up.

  11. when i excute:
    # qemu -kernel output/images/bzImage

    i get this message :

    pci_add_option_rom: failed to find romfile “pxe-rtl8139.bin”

  12. when i excute ifconfig eth0
    ifconfig eth0 error fetching interface information device not found

  13. Pingback: Minimal USB Linux Install

  14. Thnx for your tutorilal!

    I don’t see login page when I run
    #qemu-system-x86_64 -kernel output/images/bzImage -no-kvm -append “root = /dev/sda” -hda output/images/rootfs.ext2

    tty1 is set correctly.

    What’s wrong here?

    thnx!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s