20071016

Building bootable FreeBSD/i386 images

From time to time I hear people complain at how hard it is to build an image from the FreeBSD sources. This week, I'll explain how I built a bootable i386 image on a USB flash device and also make some observations about the results.

Recently, I needed to create a bootable i386 image. The easiest way was to build one on my amd64. Here's what I did. I setup my environment for the build (steps 1-3), built FreeBSD/i386 userland and kernel (steps 4 and 5), prepared the flash (steps 6-11), installed userland and the kernel (steps 12 and 13), added the extra files needed for boot (steps 14-18). The detailed commands follow:

  1. setenv MAKEOBJDIRPREFIX /blah
  2. setenv TARGET i386
  3. setenv TARGET_ARCH i386
  4. make buildworld
  5. make buildkernel KERNCONF=GENERIC
  6. fdisk -I da0
  7. fdisk -B da0
  8. bsdlabel -w da0s1 auto
  9. bsdlabel -B da0s1
  10. newfs /dev/da0s1a
  11. mount /dev/da0s1a /mnt
  12. make installworld DESTDIR=/mnt
  13. make installkernel DESTDIR=/mnt KERNCONF=GENERIC INSTALL_NODEBUG=t
  14. make distrib-dirs DESTDIR=/mnt
  15. make distribution DESTDIR=/mnt
  16. echo /dev/da0s1a / ufs rw 1 1 > /mnt/etc/fstab
  17. echo ifconfig_DEFAULT=DHCP > /mnt/etc/rc.conf
  18. echo hostname=demo >> /mnt/etc/rc.conf

I put all this on an SD card and inserted that into an usb adapater and booted the laptop with it. FreeBSD's base system isn't too big these days, only 205MB for a full system.

% df /mnt
Filesystem 1024-blocks Used Avail Capacity Mounted on
/dev/da0s1a 484822 205570 240468 46% /mnt

This can easily be trimmed, but with a 512MB SD card for $5 at Office Max, there's little point in trimming for the project I needed the flash for. I just needed something that I could boot to transition my FreeBSD/amd64 laptop to a FreeBSD/i386 laptop.

If one needed to reduce the amount of space used by an installation, then there's a number of options than can be used to reduce the footprint of the system. In my experience, it is best to build everything without these options, then use the WITHOUT_* options on the installworld step to keep the image size down. It is easy to cut FreeBSD's footprint in half with these options. In addition, the kernel is 28MB with all its modules, and this can easily be reduced below 5MB in most cases.

nanobsd can be used to automate this process, as can TinyBSD. I'll save for another column the techniques I have used in the past to reach 16MB.

16 comments:

Eric Anderson said...

Also, in many cases, removable devices can boot with a different device name than it did originally. For instance, it may come up as da0, or da1, or daX, sometimes even adX (think: virtual machines).
In these cases, I label my UFS file system while doing the newfs command with the -L option:

newfs -L "usbroot" /dev/...

or something similar. Then, instead of using /dev/daXXX in the /etc/fstab, I use:

/dev/ufs/usbroot ...

and I also make sure I add GEOM_LABEL into my kernel config (or load as a module). It's relatively small, and very useful.

Eric

Anonymous said...

There is a typo in the echo for fstab. The partition a is missing.

Anonymous said...

Funny thing is: you could skip the fdisk part and put a label on adX directly, which gives you adXa, adXb, adXc. I've been using that for some time now and works like a charm.

Who needs x86-style partition tables? ;-)

Warner Losh said...

I've had a number of PC BIOSes hate disks that didn't have a proper MBR on it. The 'dangerously dedicated' mode puts a fake MBR onto the disk. Sometimes this works, other times it doesn't. I've been involed in shipping embedded FreeBSD systems for the past 9 years, so maybe some of the paranoia that one needs in that environment is rubbing off on the instructions that I gave.

Warner Losh said...

Re typo in echo command: fixed! Thanks!

Anonymous said...

I would personally use vfs.mountfrom="ufs:ufs/usbroot" in loader.conf, as that would save you from having the kernel try to figure out the real disk to read /etc/fstab from using the BIOS-centric rootdev kernel environment variable.

I have noticed some situations where that can cause problems during kernel initialization.

marwooj said...

Hi,
Does you know what is difference between nanoBSD and TinyBSD?
I am looking for a method to build freeBSD
as flashboot described here http://www.nmedia.net/flashdist/flashdist-alternatives.html

Anonymous said...

all of this doesnt work if you're still on linux and want to boot from a usb into a live cd..

Anonymous said...

hi,

the blog is great. also can you provide info on how to create FreeBSD6.2 i386 image from a FreeBSD5.4 amd64.

thanks in advance.

ampledata said...

hey Warner,
first off, thanks for posting these instructions here.

i'm not sure what i'm doing wrong, but i've followed your instructions and whenever i boot off of my usb drive i get the following error:

"No /boot/loader"

any idea where i could be going wrong?

Anonymous said...

Hi Warner,
10x for the article. Would you be so kind to give me an advice how can I make a bootable usb stick with Free BSD on it but formatted like super floppy?

10x.

Anonymous said...

# make installworld DESTDIR=/mnt

fails with:
...
--------------------------------------------------------------
>>> Installing everything
--------------------------------------------------------------
cd /usr/src/myHEAD/src; make -f Makefile.inc1 install
===> share/info (install)
install -o root -g wheel -m 444 dir-tmpl /mnt/usr/share/info/dir
install:No such file or directory
*** Error code 1

of course 'install' exists in the normal file system:

# which install
/usr/bin/install

but it seems it is not to be seen during the 'make -f Makefile.inc1
install'... does this run somehow chrooted? and if so, what would be the correct procedure to install the system to /mnt?

Thx

Matthias

Anonymous said...

It would be nice if FreeBSD had something like NetBSD's build.sh script so versions and build host didn't matter that much.

Anonymous said...

I have tried your steps on a vmware freebsd 6.4 guest trying to convert the machine from i386 to AMD64. I followed the steps precisely,substituting the architectures of course, but when I try to boot the system from the second hard drive, its simply hangs, i get no error no nothing :(
Could you possibly try this in vmware ?

Anonymous said...

Hi Warner!

I find that this isn't the case anymore in 8.X, I'm always failing at rescue. Any thoughts?

Thanks!

cisco voice said...

The information you have provided is really very helpful. thanks...it help me