Custom firmware on the Ubiquiti Ministation

We’re using a Ubiquiti Ministation as wifi-enabled SBC for a weather station project. There’s a lot to like, and a few things lacking. It has a single 802.11b/g interface, a single ethernet port, and a single console/serial port. Like? Most everything. Dislike? The single serial port, as we want to use it as a serial-to-network gateway, which means sacrificing the console. It also runs a custom Linux installation, which we can hack it to our devious needs.

Instructions for rebuilding the system are out there, but pretty brief. Here’s my experiences.

Ubiquiti provide the SDK as a tarball, as well as a MIPS toolchain as a i386 deb. That’s fine with me as I’m running Ubuntu, though sadly I’m running 64-bit, so I built up a small VirtualBox machine for development. Not optimal, but nothing wrong with it. It’s noted here that you could also build the MIPS compiler with buildroot. your mileage may vary.


  1. Download the SDK and toolchain from here, selecting the Ministation2 as the model. As of right now, the current firmware is v3.6.1.
  2. Install the toolchain on a i386 Debian/Ubuntu system.
  3. You’ll also need a few other packages. I got this list from here, so I can’t verify it’s correctness.

    $ sudo apt-get install sharutils fakeroot zlib1g-dev patch lzma flex bison

    If a package is missing, you’ll notice pretty quickly when the compile blows up.

  4. Unpack the SDK someplace convenient:

    $ mkdir ministation
    $ cd ministation
    $ tar -xjvf ~/SDK.UBNT.v3.6.1.4873.tar.bz2
    $ cd SDK.UBNT.v3.6.1.4873

First, let’s see how the SDK works out of the box. Note, I already have my ministation up, running, and configured properly. So what happens when I “upgrade” my ministation with a filesystem I’ve built myself.

First, build it:

$ make xs2

And go get a refreshing drink.

The resulting package will end up in a directory with a name like rootfs/XS2.ar2316.v3.6.1.unknown.110707.1210 which gives the Ubiquiti model (XS2), the chip (ar2316), version number (v3.6.1) and a date/timestamp (110707.1210). The unkown is where Ubiquiti puts a patch number (like 4873 in this case), not sure why that doesn’t make it through.

Conveniently, they also symlink in rootfs/XS2.ar2316.v3.6.1.latest which points to the latest build.

In that directory are a number of intermediate results, as well as a few .bin packages:

$ ls -al
total 38976
drwxr-xr-x 2 aaron aaron 4096 2011-07-14 16:17 .
drwxr-xr-x 14 aaron aaron 4096 2011-07-14 16:22 ..
-rw-r–r– 1 aaron aaron 678439 2011-07-14 16:17 bzImage
-rwxr-xr-x 1 aaron aaron 2605056 2011-07-14 16:17 squashfs.bin
-rwxr-xr-x 1 aaron aaron 493554 2011-07-14 16:17 vmlinux.lzma
-rwxr-xr-x 1 aaron aaron 25055859 2011-07-14 16:17 vmlinux.notstripped
-rw-r–r– 1 aaron aaron 3099018 2011-07-14 16:17 XS2.ar2316.v3.6.1.unknown.110714.1614-8M.bin
-rw-r–r– 1 aaron aaron 3099018 2011-07-14 16:17 XS2.ar2316.v3.6.1.unknown.110714.1614.bin
-rw-r–r– 1 aaron aaron 4858567 2011-07-14 16:17 XS2.ar2316.v3.6.1.unknown.110714.1614.debug_binaries.notstripped.tgz

Comparing XS2.ar2316.v3.6.1.unknown.110714.1614.bin to the “stock” Ubiquiti filesystem:

$ ls -l
total 9856
-rw-r–r– 1 amarburg amarburg 3244841 2011-07-19 10:50 MiniStation2-v3.6.1.build4866.bin

my version is a bit smaller. Hmm. Well, never mind.

Install the new version of the s/w through the the web interace. Luckily, the Ministation warns me I’m about to break things:

Well, let’s go. I monitored the process on the serial console (which is a separate topic).

Writing ‘FIS directory ‘ to /dev/mtd4(FIS directory ) … [[1300398.770000] Restarting system.
+Ethernet eth0: MAC address 00:15:6d:a4:14:ed
IP:, Gateway:
Default server:

RedBoot(tm) bootstrap and debug environment [ROMRAM]
Ubiquiti Networks certified release, version 0.9.00483.1103151313 – built 13:14:44, Mar 15 2011

Copyright (C) 2000, 2001, 2002, 2003, 2004 Red Hat, Inc.

Board: Ubiquiti Ubiquiti AR2315/6/7/8 based board (Ubiquiti PicoStation2 detected)

Arch: ar2316
RAM: 0x80000000-0x82000000, [0x80040b80-0x80fe1000] available
Flash: 0xbfc00000-0xbfff0000, in 64 blocks of 0x00010000 bytes each
== Executing boot script in 1.000 seconds – enter ^C to abort
RedBoot> cache off
RedBoot> fis load -d -e kernel
Trying LZMA decompression…
Image loaded from 0x80041000-0x801df23c
Entry point: 0x80196040, address range: 0x80042000-0x801bf000
RedBoot> go
[ 0.000000] CPU revision is: 00019064
[ 0.000000] Primary instruction cache 16kB, physically tagged, 4-way, linesize 16 bytes.
[ 0.000000] Primary data cache 16kB 4-way, linesize 16 bytes.
[ 0.000000] Linux version 2.4.27-ubnt0 (aaron@moa) (gcc version 3.3.3) #2 Tue Jul 19 10:55:22 NZST 2011

Much to my surprise, it worked. And, much to my surprise, my configuration has been maintained. Sweet.