Embeddable Bastard Linux

This is not (thank god) another distro, but rather a method/how-to to make a supersmall linux install without going through the trouble of doing everything from scratch. The main idea is to use busybox, a kernel and copying everything else you need from your normal linux install. Personally I use FC5. (This is primarly a log for my own use)

Step 1 - kernel

Get your kernel and compile it. In the spirit of keeping things simple, turn OFF "Loadable module support". This will give you a big bloated static kernel, so you probably want to disable a lot of features you don't need; this is pretty boring, so once you have something working, backup your .config file for later kernel versions.

Hints for people haven't done this in a while (me):

    • SATA and USB storage devices are regarded as SCSI devices, so you need SCSI support
    • The kernel will probably panic when it tries to mount root if you boot from a USB device and doesn't have the parameter rootdelay=5 in your grub/syslinux config
    • Enabling the VESA framebuffer device will make the native framebuffer device fail
More details to come.. you should end up with a single bzImage file.

Step 2 - busybox

get and unpack busybox version of choice:
wget http://www.busybox.net/downloads/busybox-1.2.1.tar.bz
tar xfj busybox-1.2.1.tar.bz2
cd busybox-1.2.1
busybox comes with everything off by default, so turn everything on first, then turn stuff off:
make allyesconfig
make menuconfig
Busybox Settings  --->
   General Configuration  --->
     [ ] Support NSA Security Enhanced Linux
     (/bin/busybox) Path to BusyBox executable
   Build Options  --->                             
     [ ] Build shared libbusybox
     [ ] Compile all sources at once
   Debugging Options  --->
     [ ] Build BusyBox with extra Debugging symbols 
   Installation Options  --->
     [ ] Don't use /usr
Networking Utilities  --->
     [ ] Enable IPv6 support
     [ ] arping
     [ ] dnsd
     [ ] fakeidentd
     [ ] httpd
     [ ] inetd
     [ ] ipcalc
     [ ] nslookup
     [*] telnetd
     [ ]   Support call from inetd only
     [ ] traceroute
     udhcp Server/Client  --->
        [ ] udhcp Server (udhcpd)
        [ ]   Compile udhcp with noisy debugging messages

Shells  ---> 
   Choose your default shell (none)  --->
      (X) ash
make install
It will still be very small, about 1.6mb, and the make install simply copies busybox and creates a zillion symlinks in the _install directory.

Step 3 - set up and prepare the local copy

mkdir emame
cd emame/
mkdir eroot
cd eroot/
cp -a /dev .
mkdir proc
mkdir etc
mkdir tmp
mkdir etc/init.d
cp -a /usr/src/busybox-1.2.1/_install/* .

mkdir boot
cd boot
cp /usr/src/linux- mykernel
mkdir grub
cd grub/
cp /boot/grub/stage1 .
cp /boot/grub/stage2 .
cp /boot/grub/e2fs_stage1_5 .
you can try it out as root with
[root@localhost eroot]# /usr/sbin/chroot . bin/sh
/ $

Step 4 - Preparing your boot-media of choice, in this case an USB stick

!! be very careful and sure that you're doing this on the right drive !!
Use fdisk to delete whatever is on the target drive, and create a primary big enough to hold the kernel, a root filesystem and whatever you decide to put on it. Make it bootable with a. You should end up with something like:
Command (m for help): p

Disk /dev/sdc: 1031 MB, 1031798784 bytes
255 heads, 32 sectors/track, 246 cylinders
Units = cylinders of 8160 * 512 = 4177920 bytes

   Device Boot      Start         End      Blocks   Id  System
/dev/sdc1   *           1          18       73424   83  Linux
Create filesystem, and mount:
/sbin/mkfs.ext2 /dev/sdc1
mkdir eroot
mount /dev/sdc1 eroot/
copy the root structure to target:
cd /mnt/eroot
cp -a /usr/src/emame/eroot/* .
chown -R root:root *
Install grub:
grub> geometry (hd1) <- Check that hd1 really is the boot-target
drive 0x81: C/H/S = 15/255/63, The number of sectors = 256000, /dev/sdc
grub> root (hd1,0)
 Filesystem type is ext2fs, partition type 0x83
grub> setup (hd1)
 Checking if "/boot/grub/stage1" exists... no
 Checking if "/grub/stage1" exists... yes
 Checking if "/grub/stage2" exists... yes
 Checking if "/grub/e2fs_stage1_5" exists... yes
 Running "embed /grub/e2fs_stage1_5 (hd1)"...  15 sectors are embedded.
 Running "install /grub/stage1 (hd1) (hd1)1+15 p (hd1,0)/grub/stage2 /grub/grub.conf"... succeeded
grub> quit
make a small grub.conf in cd /mnt/eroot/boot/grub/
    root (hd0,0)
    kernel /boot/mykernel rootdelay=6
umount, and try it, if everything goes well, you should have a single-user system up.

Copying and setting up shared-libraries

While busybox is great, and a few other programs are relatively easy to get going under a minimalistic setup, some certainly are not. And compiling static versions of them without shared libraries is a lot of work and/or uncharted territory as most programs under linux are built on systems with shared libraries. So we're not even going to try, but just copy the libraries we need instead.

Figuring out library dependencies for a given binary is pretty easy, just ldd it.
[perole@localhost sdlmame0109u4]$ ldd tinypm
        linux-gate.so.1 =>  (0x00270000)
        libexpat.so.0 => /lib/libexpat.so.0 (0x0065d000)
        libz.so.1 => /usr/lib/libz.so.1 (0x0054b000)
        libSDL-1.2.so.0 => /usr/local/lib/libSDL-1.2.so.0 (0x00777000)
        libpthread.so.0 => /lib/libpthread.so.0 (0x00535000)
        libGL.so.1 => /usr/lib/libGL.so.1 (0x00cc2000)
        libc.so.6 => /lib/libc.so.6 (0x0028e000)
        libm.so.6 => /lib/libm.so.6 (0x003c9000)
        libdl.so.2 => /lib/libdl.so.2 (0x003c3000)
        /lib/ld-linux.so.2 (0x00271000)
        libX11.so.6 => /usr/lib/libX11.so.6 (0x003f0000)
        libXext.so.6 => /usr/lib/libXext.so.6 (0x004fc000)
        libXxf86vm.so.1 => /usr/lib/libXxf86vm.so.1 (0x00c35000)
        libdrm.so.2 => /usr/lib/libdrm.so.2 (0x00c3c000)
        libXau.so.6 => /usr/lib/libXau.so.6 (0x004f7000)
        libXdmcp.so.6 => /usr/lib/libXdmcp.so.6 (0x004ef000)
In the spirit of keeping it simple, we just use /lib - all this is done in the directory that is the local copy of root.
mkdir lib
cd usr/
ln -s ../lib/ lib
cd ../lib
cp -P /lib/libexpat.so.0* .
With -P and *, we get both the library and the symlink to the binary.