Using FreeBSD® on a Raspberry Pi™

Why use FreeBSD

A big question in anyone's mind, at this point, might be "Why should I use FreeBSD on my Raspberry Pi board?" Well, to answer that question, I'll need to go into a bit of technical depth

To begin with, there are many different operating systems available for the Raspberry Pi, the most popular of which appears to be a version of Debian Linux known as 'Raspbian'. It currently tracks the latest production version of Debian, which (unfortunately) includes systemd, and a version of 'bluez' (bluetooth tools) that has problems with legacy USB bluetooth devices, as well as (potential) encumberances of the GPL.

But for most Raspbian users, you probably won't even notice those things.

For people who are interested in making devices based on the Raspbery Pi, by either embedding a Raspberry Pi (as I have done HERE), or by using the same ARM device that the Raspbery Pi uses [in a compatible manner], some of the concerns I have with Raspbian may be enough to choose an alternative operating system. And a very good choice for THAT would be FreeBSD.

FreeBSD is designed for 'build from source', and so the 'ports' collection helps to make this easy. More information on this aspect can be found in the FreeBSD handbook and other resources. What is worth pointing out is that FreeBSD makes a LOT of development work easier, and if you develop software specifically for the Raspberry Pi, you may grow to appreciate how much easier that can be.

Additionally, GPIO manipulation in FreeBSD uses an ioctl interface rather than proc variables. The Linux implementation appears to be tailored for use by scripts and interpretive languages (like Python). The FreeBSD implentation does include a command line utility ('gpioctl'), but it's the ioctl interface that would make a C language application more practical.

In Linux, you can directly access memory (via '/dev/mem') and map it into your address space (via 'mmap') and then directly manipulate the GPIO registers yourself (see THIS EXAMPLE). But (unfortunately) it generally requires a 'root' user to access '/dev/mem' (changing permissions on /dev/mem to allow non-root access is NOT a very good idea at ALL). Apparently, you can also use this method in FreeBSD (I have not tried it yet, but the /dev/mem device exists). However, in FreeBSD, you can change the permissions on the GPIO pin device /dev/gpioc0 automatically, with a configuration file, so that the 'gpio' group has read/write access to it. This way you can allow specific users to directly access the GPIO pins without having to 'be root', using a very fast (ioctl) interface.

Additionally FreeBSD supports I2C using the 'iic' device (via ioctl) as well as the 'i2c' utility for command line access. However, it does not (yet) appear to have an SPI driver. I guess I'll have to write one...

Raspberry Pi, FreeBSD, and the 'gpioshutdown' module

One of the glitches that I've found, with respect to using FreeBSD on the Raspberry Pi, is the manner in which FreeBSD handles GPIO pins on shutdown. In Linux, the GPIO pins are reset such that it is possible to detect the shutdown condition with appropriate hardware (like the The ATXRaspi), which would let you do a 'safe poweroff' on the Raspberry Pi, and avoid possible file system corruption. This is ESPECIALLY important for a headless system, because you won't be able to see the console output.

To correct for this, I created a loadable kernel module 'gpioshutdown', which is tentatively to be added to the 'ports collection' as 'misc/raspberrypi-gpioshutdown' (more on this, later).

By loading this kernel module, the IO pins are reset to their 'default' (input) state right at the point where it is safe to power off the device. If, for example, you set a pin to an output with a '1' value, and then drove an LED (through a 220 ohm resistor) with that pin, the pin would light up when the system startup completes. If you then checked another pin for a shutdown (let's say it has a pushbutton on it), you could issue the command 'poweroff' (as root) upon detection of the pushbutton, and do a proper shutdown sequence. Once the system has completed shutting down, the LED would turn off, indicating that it's safe to turn off the power.

Alternately you could have a hardware device (like the ATXRaspi) do some of this work for you. The shutdown would be indicated by the output GPIO pin becoming a 'high impedence' input pin (similar to the LED trick that I just mentioned), at which point it would be safe to power off the Raspberry Pi.

Worthy of mention, this already works under Linux. The kernel module makes it work under FreeBSD, too.

Installing FreeBSD on a Raspberry Pi

Obtaining an SD card image

You must first obtain a bootable SD card image from the web site. Currently, you can download the latest FreeBSD 11.1 Raspberry Pi images HERE.

For the RPi Model 1B, you'll probably want FreeBSD-11.1-RELEASE-arm-armv6-RPI-B.img.xz.
For the RPi Model 2, you'll probably want FreeBSD-11.1-RELEASE-arm-armv6-RPI2.img.xz.
For the RPi Model 3, there is no production release available (yet). However, there is an incomplete 'bleeding edge' release available HERE. (look for a link that begins with "FreeBSD-12.0-CURRENT-arm64-aarch64-RPI3" or similar, as these links change frequently and you'll nearly always want the latest one).

NOTE: It's important to point out that as newer releases become available, they will be linked to from the main FreeBSD web site, at So if this web page is several years old, please keep in mind that these links are for the newest images at the time I wrote it.

Once you obtain the compressed disk image (compressed using 'xz'), you need to extract this into a binary image. Use the 'xz' utility (in Linux or FreeBSD) as follows:

    xz --decompress ImageFileName.img.xz
where 'ImageFileName.img.xz' is the name of the image you downloaded. This will get you the raw image file, named similarly to 'ImageFileName.img'.

Transfer the image to an SD card

Next, you'll need to insert an SD card that is at least 4G (preferably 8G or larger) into an appropriate slot [and then plug in the USB cable, if you are using an external USB device] on your Linux or FreeBSD computer, but do NOT allow it to be 'auto mounted' (you might have to forcibly unmount it if your GUI is aggressive and persistent at "helping" you in this way).

Then, once the SD card shows up in the '/dev/' tree, you'll need to overwrite the primary partition on the SD card with the contents of the '.img' file you extracted earlier. On a FreeBSD system, it will probably have a device name similar to '/dev/da0'. If the SD card has a file system on it, there may be other entries like '/dev/da0s1'. The entry you want to overwrite is the 'root' device, '/dev/da0'. On Linux the device naming is similar. If you're not sure which device to use, try unplugging the SD card, and plugging it back in again, and see which device names disappear and then re-appear when you do this.

Assuming that you're running FreeBSD and the SD card is '/dev/da0', use the following command to write the image:

    dd if=ImageFileName.img of=/dev/da0 bs=1M conv=noerror,sync
The 'conv=noerror,sync' parameter fills out the remainder of the image with padded zeros, necessary when you specify a non-default block size. And the block size of 1M actually speeds the process up quite a bit (there is a similar command example near the end of the man page).

Initial boot on a Raspberry Pi

Next, you'll want to boot up this image on an actual Raspberry Pi. You should connect a monitor and keyboard to the Raspberry Pi in order to monitor the process (and maybe control it). On initial boot, the FreeBSD startup script will automatically extend the image to fill the SD card completely, so you'll have the most possible disk space available. This is actually necessary prior to you making any modifications.

The first thing you'll need to do is log in via the console. I suggest logging in as 'freebsd' with the password 'freebsd' (this is documented in the FreeBSD/ARM Raspberry Pi wiki, and if for some reason the user/password changes, use the user/password specified there, instead). Then, you should change the password to something of your choice. You should never leave the default password as-is, for security reasons.

Next, you should immediately 'su' to root and change the root password. Don't leave it as 'root'. Again, this is for security reasons. I also recommend that you add a new login for the user name you prefer to log in as, using the 'adduser' command. Just fill in the prompts and accept the defaults (they'll be fine, for now). You can always modify them later, as needed.

FreeBSD 'pkg' utility and kernel/world source

FreeBSD has a package system that uses the 'pkg' utility. You'll want to install that. Type 'pkg' and follow the instructions you're given to get it up and running.

At this time it's a good idea to consider which packages you are going to want to install. If you prefer 'bash' as your login shell, you can install it via the command 'pkg install bash'. Other things, like Perl, Python, and a GUI, can be installed as packages. More information on this can be found in the FreeBSD Handbook.

If you will be building any kernel modules from source, including the 'raspberrypi-gpioshutdown' port (see below), you'll need to install the kernel source yourself. This is a VERY large tree (around 1.5G), and as such, you may want to host it on a different computer, via an NFS share, and mount it to /usr/src (rather than hosting the kernel/world source there). Keep in mind that the kernel source MUST match the actual kernel for this to work properly, so you might have to update the kernel on the Raspberry Pi's image as well. I'll cover this later.

You'll need to choose a directory for the kernel+world source. FreeBSD will expect it to be in the '/usr/src' directory on the Raspberry Pi. You can mount an external NFS share at this point, or else load the source tree directly onto the SD card at this point. Either way works. And if the source files are on an external computer, you can obtain the source directly on that computer first, and then mount it via NFS on the Raspberry Pi at your convenience (this is the method I prefer).

The FreeBSD kernel+world source is available via subversion. This is covered in the FreeBSD Handbook Chapter 23, including instructions on building the 'world' and 'kernel' trees. You'll need 'world' to build the kernel, so you basically have to get the entire tree.

On the Raspberry Pi, you can install the subversion client with the following command:

    pkg install subversion
With subversion installed, change the working directory to the location where you'll be keeping the source files (it should be a clean directory), and enter a command similar to the following:
    svn checkout
In this case, it will get the source for '11.1-RELEASE', which should match the SD card images I referenced earlier. Keep in mind that over time, you'll probably want to use a version newer than '11.1'. I used that version here only as an example. Also, additional information (and any corrections) will be available in the FreeBSD handbook.

NOTE: If you have a somewhat slow (pathetic DSL let's say) connection, or a connection that gets interrupted for some reason (storms, cable guy screwup, whatever) and the svn command fails, you can repeat the same command and subversion should figure out that it was interrupted and pick up where it left off.

Customizing the FreeBSD installation

It's very likely that you'll want to change how the operating system starts up, the things that are running by default, and so forth. The manual page for the 'rc' system ('man rc') explains all of this, but I'll cover some of the basics here, for convenience.

FreeBSD has a file '/etc/rc.conf' that assigns various pre-defined environment variables for the 'rc' system, that determines how the system boots up. It can configure network connections, load device drivers, start daemon programs, and do 'one time during startup' kinds of processing. Script files contained in '/etc/rc.d' and '/usr/local/etc/rc.d' define what the 'services' are, very similar to the 'System V' style startup used by pre-systemd versions of Linux.
Details on the contents of 'rc.conf' can be found in its 'man' page ('man rc.conf').

Most of the configuration can be done using the '/etc/rc.conf' file, with occasional startup scripts in '/usr/local/etc/rc.d' for customized operations (let's say, flipping a GPIO output bit to indicate that the Raspberry Pi has started up). There is also legacy support for 'rc.local', in case you want to go THAT route.

If you want to load a specific kernel module, for example, you could add the following line to '/etc/rc.conf':

This would load the 'gpioshutdown' kernel module on startup (for more information on using this, see the section below on the 'misc/raspberrypi-gpioshutdown' port). If you want to load more than one module, just separate the module names with white space.
(If you want to know what script handles this, see '/etc/rc.d/kld')

Setting up the Raspberry Pi for serial console boot

By default, the Raspberry Pi image for FreeBSD will boot using the video console and use the attached keyboard (via USB). However, on a 'headless' system, you will often want an alternate means of doing a controlled bootup, such as for maintenance or recovery.

To configure the Raspberry Pi to use serial port 0 ( /dev/ttyu0 and /dev/cuau0 ) :

  1. edit (or create) the '/boot/loader.rc.local' file, and add the following:
            set boot_multicons="YES"
            set boot_serial="YES"
            set comconsole_speed="115200"
            set console="comconsole,vidconsole"
    This will configure the serial console on pin 8 (TX) and pin 10 (RX) for 115k baud, 8 bits, no parity. To use a different speed, alter the line for 'comconsole_speed'.

  2. To get the 'beastie' boot menu, add the following at the end of the '/boot/loader.rc.local' file:
            include /boot/beastie.4th

Building and installing the 'gpioshutdown' kernel module from source

Before you can build and install the 'gpioshutdown' kernel module from source, you'll need to install the ports collection onto the Raspberry Pi, as well as having the kernel source available. As with the kernel source, the ports collection is relatively large (about 800Mb), but in this case, it should be installed locally on the Raspberry Pi's SD card. For more information on obtaining the ports collection, see The FreeBSD Handbook Chapter 4.5.

In summary, you'll be using the 'portsnap' utility to obtain the ports collection. It's a time-consuming process, especially on a slower CPU like the one on the Raspberry Pi. I recommend letting it run overnight.
A summary of the commands you'll need to run:

    portsnap fetch
    portsnap extract
I suggest reading the FreeBSD Handbook chapter first, so that you have a good idea of what's involved.

Currently the port for the 'gpioshutdown' module is not (yet) available in the FreeBSD ports collection. Eventually it will be, and should also be installable as a package. However, I am making it available here, and the instructions reflect installing the kernel module by building it from source, using a customized 'port' contained in a user directory.

If you plan on creating your own ports, or need to extract this one into a user directory, you should create a directory called 'ports' in the home directory of an appropriate user on the Raspberry Pi. In this example, it's the 'rpi' user.

First, log in as "that user" (in this case, 'rpi') and create a directory '~/ports'. Next, change the working directory to '~/ports' and create a directory 'misc'. Then, change the working directory to '~/ports/misc' and download the 'shar' file with the following command:

Next, extract the port by running the 'shar' archive as a shell script:
    sh <raspberrypi-gpioshutdown.shar
Once you've extracted the port files, you can delete the 'shar' file.

Now, change the working directory to the port directory, 'raspberrypi-gpioshutdown'. Then, use 'su' to switch to the root user. You will need to build and install the port as root, by running the command:

    make install
Even though you're not in the '/usr/ports' directory, you can still compile it as a port. The kernel module will be correctly installed into '/boot/modules' and will be version checked on load. Keep in mind that if you update the kernel, you'll also need to update the kernel module (basically re-build and re-install it with the correct kernel source).

The port installs an 'rc.d' script file 'gpioshutdown' in '/usr/local/etc/rc.d'. This script automatically assigns the LED pin 'pwr' (on an RPi model 2) or 'ok' (on an RPi model 1) as a shutdown indicator, using the correct LED polarity for each of those devices (later RPi models may not have this capability, which is why it's optional).
To use the built-in 'gpioshutdown' script, add the following line to rc.conf:

To start the script, you can reboot the Raspberry Pi or use the following command:
    service gpioshutdown start
You should now see the LED turn on (Raspberry Pi model 1B and model 2) indicating that the script is running. To test it, enter the 'poweroff' command (as root). You should see the LED turn off after about 30 seconds, indicating that it's safe to turn off the Raspberry Pi.

If you have a serial console enabled, or a monitor connected, you should see the following text appear:

    The operating system has halted.
    Please press any key to reboot.
The LED that was previously on (before) should turn off just before this text prints on the console. You can verify this by watching the shutdown sequence and observing the text and the LED state.

External Links:

Back to S.F.T. Inc. home page

Raspberry Pi™ is a trademark of the Raspberry Pi Foundation.
FreeBSD® is a registered trademark of the FreeBSD Foundation.

©2018 by Bob Frazier and Stewart~Frazier Tools, Inc. - all rights reserved
last updated: 3/19/2018

Community projects are generally good, but socialism, in all of its forms, is always evil.