FreeBSD on AR9331 Routers

Last Updated:
tags: routers freebsd embedded networking
categories: embedded

Some introduction

I haven't had a whole lot of time to update this blog this year unfortunately. That doesn't mean I haven't been working on lots of interesting stuff though, so I'll be making a push to keep this blog updated.

One of the most recent and interesting things I've been experimenting with is FreeBSD as an embedded OS. I've been playing around with AR9331 hardware, specifically the GL.Inet AR150, which is a single-band 802.11n travel router sporting OpenWRT out of the box. It's fully supported in OpenWRT (and LEDE) and has performed well in a few of my side projects, like TOR gateway routers and mesh networking experiments (but these are other blog posts…).

The AR150 is perfect for a project I'm working on, to build a ~0.5km wifi link on my rural property to get clear line of sight to the local NBN wireless tower (rural broadband) and beam it to somewhere I can use it. This is all off-grid so low power consumption is key, but I'll get another blog post about the solar system I'm building to run this whole setup once I've got it put together.

Needless to say there will be time series databases and monitoring hardware involved.

I thought it would be cool however if I could run FreeBSD on these. I'm a huge fan of the flexibility and great network performance of the various BSDs. I set about seeing what would be involved only to find that Adrian Chadd over at the FreeBSD project has already put together freebsd-wifi-build. Great! The AR150 is extremely similar to the Carambola2, so I was able to build and boot a Carambola2 image, which suites my needs.

The steps to get something like this going


You have to build a FreeBSD image. This build needs to be done under FreeBSD, it can't be done under Linux.

Install the prerequisites:

  • pkg install fakeroot gmake bison dialog4ports git wget subversion fakeroot lzma uboot-mkimage libtool

Create a directory to house the code, i.e. mkdir ~/ar9331 Change into that directory and check out the required trees. You can use a snapshot of the FreeBSD source if you'd prefer.

  • git clone

  • git clone

Change directory into the freebsd directory once the clones finish, and then run:

  • ../freebsd-wifi-build/build/bin/build carambola2 buildworld buildkernel installworld installkernel distribution

  • ../freebsd-wifi-build/build/bin/build carambola2 mfsroot

  • ../freebsd-wifi-build/build/bin/build carambola2 fsimage

This will place a combined user and kernel image in ../tftpboot. cd into ../tftpboot and get ready to install by plugging in your USB TTL UART cable, and an ethernet cable to a machine with a TFTP server installed. The serial pinout is marked clearly on the AR150 board, you may have to solder a pin header if your board is missing the pins, but mine were still marked. You'll need to connect RX, TX and GND. Don't connect VCC.


In order to flash FreeBSD, you have to get the AR150 into U-boot. I find the easiest way to do this is to hook up a 3.3v FTDI USB adaptor to the on-board UART so you can access the serial console on the board. Once you've got that hooked up, you can just reset the board, and press enter when you see the prompt to interrupt the boot.

Once in U-boot, you want to set the IP of unit, the server IP, and then save the configuration. You'll also need a TFTP server on your network, running at the server IP you set in the config.

At this point, make sure you set a static IP on the ethernet device of your PC running TFTP, and copy the firmware image (carambola2.flashinst.img) to the root of your TFTP server, naming it openwrt-gl-ar150.bin

The below should be the defaults, so if printenv shows the server IP as and the ipaddress of the unit as, you can skip this. If my PC running TFTP is at, do the following at the prompt:

  • setenv ipaddress=

  • setenv serveraddress=

  • saveenv

  • reset

Interrupt the bootloader again with enter when prompted if you needed to change the IP addresses. You'll want to the the below now to flash the new firmware.

  • run lf

This will detect the correct ethernet interface, ping, and load firmware.bin from the TFTP server there, flashing the result. Once done, the unit should restart, and FreeBSD should load up!

If you want make any changes to the configuration, you'll want to edit /etc/cfg/rc.conf. If you make any changes, make sure you run cfg_save. The filesystem on the image is read-only, and an overlayed configuration filesystem is used to load configuration from flash at boot. cfg_save makes sure your changes are copied to that configuration partition.

And example configuration can be something as simple as:

system_hostname="router" kernel_modules=""
network_interfaces="arge1 ath0 wlan0 bridge0"

netif_arge1_enable="YES" netif_arge1_type="ether"
netif_arge1_addrtype="none" netif_arge1_descr="default"

netif_ath0_enable="YES" netif_ath0_type="ath" netif_ath0_descr="main"

netif_wlan0_enable="YES" netif_wlan0_type="wifi"
netif_wlan0_wifi_mode="hostap" netif_wlan0_descr="default"
netif_wlan0_addrtype="none" netif_wlan0_name="wlan0"
netif_wlan0_wifi_parent="ath0" netif_wlan0_wifi_channel="4:ht/40"
netif_wlan0_wifi_hostap_ssid="Router" netif_wlan0_wifi_hostap_wpa_mode=3
netif_wlan0_wifi_hostap_wpa_passphrase="Passw0rd" #obviously, change this
netif_wlan0_wifi_hostap_wpa_pairwise="CCMP TKIP"

netif_bridge0_type="bridge" netif_bridge0_addrtype="static"
netif_bridge0_descr="default" netif_bridge0_name="bridge0"
netif_bridge0_members="wlan0 arge1"

The Wiki over on the freebsd-wifi-build repository has more configuration examples, and information on customising the image further to include additional software, but storage space is at a premium.

Thanks again to Adrian Chadd and everyone who has contributed to FreeBSD and the freebsd-wifi-build projects. Almost all of the configuration required to do this comes from the helpful documentation made available by those folks.

Enjoy your new FreeBSD travel router!