NetBSD on 8M CF + 8M RAM

Last update: Fri Sep 16 01:23:10 2005.

NetBSD on <8M disk , 8M RAM

Why ?

Well, from the beginning: I own an old laptop (Acer 313t), very small, pentium 1 mmx (266) and 32 RAM. I have a pccard network card (realtek 8139) on it and one USB port. The display is very small but great quality. Mini keyboard, AC97 sound card, serial and parallel port, etc... It's a very cute computer for many uses, now it's a bit old so I don't use it too much.

Once, the hard drive died. The laptop was turned into a pretty useless piece of electronics, too bad. After removing the drive, I enjoyed one thing : the absolute silence ! That gave me an idea, I always wanted such a hardware to play, especially to use as a powerful mp3 player. So was time to transform it into a nice experience for playing mp3, and maybe more...

Without hard drive ?

That was the point. I found on ebay (but you can find it elsewhere) a mini-ide to CompactFlash adapter. I have 2 CF cards, I don't use the smallest one anymore (8M), I decided to recycle it into a silent full-featured micro hard-drive :)

Why NetBSD ?

I had some experiences putting Linux systems on reduced size disks (my first project was mininux), but Linux isn't exciting anymore (just my taste, I don't want to discuss it here). My actual love is NetBSD, a very clean system (design as well as code), very flexible, with lot of fun(tm) included. Added to this, the community is very open and sympathetic. I always used it as standard OS on my desktop computer, was time to do further work with it :)

How ?

Hehe, I suppose many people jumped to this part directly :) To do short, here is the constraints: 32M RAM, 8M Compact Flash, Network card, no OS on the box yet. Unfortunately, at the time being, my NetBSD computer wasn't available, since NetBSD can be compiled/run everywhere, that wasn't a big problem. The tools I used:

Prepare a kernel

Here is the configuration I used, It's adapted to the embedded system (sound card, network, etc...), please, review it before using. Some important notes:

Memory is precious, my system is only 32M RAM, at first I did a system that was loaded entirely in memory, too bad... I have many programs to run, some of them are greedy, I don't want to waste bytes uselessly. In the final system, I can run everything + run python interpreter with 8M ram only (not 8M _used_, 8M _total_).

The kernel I did isn't minimal, I added some bloat to run some programs that required it, but maybe you won't need it (ktrace is an example). Two important options are the support for ffs, vnd and VND_COMPRESSION.

Just compile it as usual. If you want your kernel to be smaller, strip it. If you want it even smaller, strip it with "-R .indent -R .comment" options. Then, gzip --best <name of kernel>

B You are done with the kernel part, that's was the easy piece of the cake.

Prepare the root filesystem

Now hings are becoming interesting, you will learn things with this part (at least, I did). I'm not going to give you a base filesystem, that would be too easy and won't require you to learn and try. I'll just give you some clues about problems you may encounter.

  1. don't forget to include /libexec/ld.elf_so
  2. don't forget to ln -s /libexec/ to /usr/libexec (I spend some hours tracking this problem!)
  3. init will run /etc/rc, can be any executable file.
  4. the /boot file is mandatory, rtfm about that
  5. it's convenient (but not necessary) to put your kernel in /netbsd
  6. don't forget libraries, use ldd to find the needed ones
  7. recompile your programs changing flags, strip it, edit text files, etc... to gain some space

    Now it's just a matter of time, do a directory in your netbsd filesystem with everything you want in the minimal system. You can play with it using chroot(8). I result in a system of 11M with mplayer, python, mpc, mpd, bozohttpd, some python soft to control my modem and a pair of cgi.

    This is too big :) Now comes the trick, the /usr filesystem will be mounted via compressed vnd, on my system, usr is 8.2M, and is compressed ~50%. Don't forget to mount /usr at startup...

    Here is the bare minimum taken from my /etc/rc file:

      #!/bin/sh
      export PATH=/sbin:/bin:/usr/bin:/usr/sbin:/usr/pkg/bin:/usr/pkg/sbin
      export PYTHONHOME=/usr/pkg/
      export PYTHONPATH=/usr/pkg/lib/python2.4
      echo -n "configuring"
      echo -n " mount"
      mount_mfs -s 2m tmp /tmp
      vnconfig -z vnd0 /usr.zimg
      mount -A
      mount_mfs -s 512k root /root
      echo -n " network"
      ifconfig lo0 127.0.0.1 netmask 255.0.0.0
      ifconfig rtk0 192.168.1.41 >/dev/null 2>&1
      route add default 192.168.1.1 >/dev/null 2>&1
      export TERM=vt220
      export HOME=/root
      echo "."
      cd
      ksh
      halt -p
    

    And the associated fstab:

      /dev/wd0a       /       ffs     ro      1       1
      /dev/vnd0a      /usr    ffs     ro      1       1
    

    I kept the python variables in case you need it too, if you don't put those variables, python won't find the modules. As you can see, I use a trick here to gain space: /usr is compressed. You'll need a kernel supporting VND_COMPRESSION (>= NetBSD 3 is OK). I configure the network card statically, dhclient is ok but you'll need some more files (in my system, I can use both).

    Everything is mounted read-only (ro) because my system can be unplugged at any moment, plus I use a compact flash and I heard it have relatively limited writes.

    Now the technical part, I give you the script I did but don't run it without understanding it ! I'm not responsible of your acts.

      #!/bin/sh
      FFS_VERSION=1
      RD=mp3box # root directory
      WD=work   # work directory
      FFS_OPTS=minfree=2,version=${FFS_VERSION}
      #BLOCK_SIZE=$((1024*64))
      ################################################################################
      
      BD=${WD}/boot
      OD=${WD}/out
      rm -fr ${WD}/*
      mkdir -p ${BD}
      cp -Rp ${RD}/* ${BD}
      mv ${BD}/usr ${WD}
      mkdir ${BD}/usr
      ln -s /libexec ${BD}/usr
      makefs -o ${FFS_OPTS} ${WD}/usr.img ${WD}/usr || exit
      vndcompress ${WD}/usr.img ${WD}/usr.zimg ${BLOCK_SIZE} || exit
      mv ${WD}/usr.zimg ${BD}
      makefs -o ${FFS_OPTS} ${WD}/boot.img ${BD} || exit
      installboot ${WD}/boot.img /usr/mdec/bootxx_ffsv${FFS_VERSION}
      dd if=${WD}/boot.img of=/dev/wd1d bs=512k || exit
      echo "DONE"
    

    This script automatically compresses the /usr directory and makes everything happy for booting. The minfree option is to avoid a problem I had to face of, but you may not have any need for it.

    To help you even more, here is a list of all the files.

Final word

One small advice I can give you: use qemu to test your fresh image. It will avoid you to modify/make/burn/fire up everything when your system don't boot because you forgot to copy some library or binary or everything else. I just give you a clue about the title, you are thinking I'm a lier since the box is 32M RAM and 8M Disk. I just use <6M on the disk and I it started running qemu with "-m 6", and with "-m 8" I could run python programs relatively comfortably.

In fact, those experiments with NetBSD were very fun, I find the whole system very clean, I already did similar things with linux some years ago and I think it's a lot more tricky. The netbsd kernel can be very small, it could be even small if it was supported by the UPX project.

If you are curious, you can take a look at the beast, don't be afraid.

I hope this document will give you information you needed to achieve your projects, you can send me feedback about success stories, I'm curious :) (to write to me: user = fab and host = gnux.info)