Wednesday, October 26, 2005

Cross building FreeBSD

A Tale of OS Bootstrapping

What do you do when an AMD64 box comes by your way but you only have an 32-bit operating system to run on it? With FreeBSD, you can bootstrap your way into a 64 bit world. Here is what you do:
  1. Install FreeBSD in the usual way. When doing so, keep a spare disk partition for holding the new amd64 OS. In this example, we'll assume that this is partition 'd'. Mount this partition on some convenient mount point, say /1. The full FreeBSD system occupies about ~250MB these days; so make this partition a few GB in size. Don't forget to install the sources to the FreeBSD system of course, otherwise there won't be anything to cross-build.
  2. Change directory to the root of the source tree /usr/src and execute the following commands:
    # cd /usr/src
    # make world TARGET_ARCH=amd64 DESTDIR="/1"
    This step builds an amd64 userland and populates it into /1. Several interesting things happen as part of this step.
    • Since the host OS at this point is running in 32-bit mode it has to build a full cross-toolchain first: tools running on the i386 architecture but manipulating libraries and executables for the amd64 architecture.
    • It then needs to compile the whole source tree for the amd64 architecture using tools running on the i386.
    • Once compilation succeeds, the build process transfers the newly built binaries into the filesystem rooted at /1.
    Other options for TARGET_ARCH include powerpc, sparc64, alpha, ia64.
  3. The next step is to populate a default /etc. This is how you do this:
    # make distribution TARGET_ARCH=amd64 DESTDIR=/1
    This step populates /1/etc with the default set of startup scripts.
  4. Now we need an amd64 kernel to boot from:
    # make kernel KERNCONF=GENERIC TARGET_ARCH=amd64 DESTDIR="/1"
    This builds a kernel following the configuration specified in the configuration file named /usr/src/sys/amd64/conf/GENERIC and installs it under /1/boot/kernel.
  5. Copy over /etc/fstab to /1/etc/fstab and change the definition of the / (root) mount point to use partition 'd' (the default is to mount / on the 'a' partition).
  6. Copy over /etc/rc.conf to /1/etc/rc.conf, as this contains the machine's hostname, and IP addresses of its interfaces.
  7. Create a file boot.config in the 'a' disk partition containing the following text:
    0:ad(0,d)/boot/loader
    This command informs the first stage boot loader (see boot(8)) that we want to boot from partition 'd' instead of the usual partition 'a'. If you've booted from a SCSI disk, you may need to specify the boot device as da(0,d).
  8. Reboot. Viola! You boot into an AMD64 kernel running an AMD64 userland.