Choosing the Ubiquiti EdgeRouter X
As I will be moving soon I will be needing a new router for managing my home network. There are hundreds of routers availble at various prices in many stores but I knew I wanted something beefier than most consumer routers and preferably run my favourite router firmware on it: OpenWRT. With that in mind, I researched a handful of candidates and decided on the Ubiquiti EdgeRouter X. It's a small 5-port gigabit router with no wireless support but sports a dualcore Mediatek MIPS processor and has both 256MB of RAM and NAND Flash. The inreased RAM and Flash size compared to most consumer routers would come in very handy with OpenWRT as it would allow me to install plenty of extra software packages later on, and allow me to use the storage for saving any logs or other files. The lack of WiFi support didn't bother me, this router will be mounted near my front door where the cable modem will reside and I would like my WiFi AP to have a somewhat more central location in the house anyway.
So, I had chosen for this EdgeRouter X, but I knew there was one catch: barely any information on getting OpenWRT on it seemed to be available. The OpenWRT techdata page listed some of the router's details but little else, and the OpenWRT device page was almost completely barren. It did however feature a picture of the internal serial port, which came in handy later. The most promising resource appeared to be a topic on the OpenWRT forums which showed that at least two people had gotten OpenWRT running on it, and that gave me just enough hope to give it a try myself.
A first look at EdgeOS
The Ubiquiti EdgeRouter X comes with the EdgeOS firmware by default. Contrary to the stock firmware on many consumer routers, this firmware is actually regarded as pretty decent and provides many features. Before flashing OpenWRT on the router, I had a little look around EdgeOS first.
After logging in on the web UI, the user is presented with some general live graphs on the first page and a status for all five ethernet ports. From here on many settings can be configured on either the main page or any of the other pages. I did notice however that my browser asked me if this website was allowed to run Flash. Why a router needs Flash on its web interface is beyond me.
SSH is enabled by default and you can log in with the same user credentials
as for the web interface. Upon logging in, surprisingly enough I am greeted
with a real bash shell. The linux version appears to be 3.10.14, and the
presence of a /etc/debian_version
file (containing "7.8") hints to me that
the firmware is based on Debian. I wouldn't be surprised if it would be
possible to use the official Debian repositories to install additional packages
on this firmware.
As a last step before waving EdgeOS goodbye, I inspected /proc/mtd
and used
dd to make images of all the partitions, just in case. Here's the layout:
ubnt@ubnt:~$ cat /proc/mtd
dev: size erasesize name
mtd0: 00080000 00010000 "SPI_FLASH"
mtd1: 0ff80000 00020000 "ALL"
mtd2: 00080000 00020000 "Bootloader"
mtd3: 00060000 00020000 "Config"
mtd4: 00060000 00020000 "eeprom"
mtd5: 00300000 00020000 "Kernel"
mtd6: 00300000 00020000 "Kernel2"
mtd7: 0f7c0000 00020000 "RootFS"
I'm not entirely sure what the SPI_FLASH
is used for, but the firmware
resides on the NAND flash (recognisable by the different erasesize). The ALL
partition covers the same memory as all the following partitions toghether.
U-Boot and its configuration resides on mtd2 and mtd3 respectively. The
eeprom
partition probably contains some settings for the router hardware,
though I can't be too sure. After that two kernels are present, the second one
as a fallback in case of a bad upgrade or flash corruption. Finally, the last
and largest partition is used for the RW root filesystem (ubifs).
Compiling the OpenWRT images
The forum topic that I mentioned in the introduction of this article included a post that referred to a patch submitted in November 2015 introducing support for this specific device. This patch would've been too recent to have made it into a stable release of OpenWRT yet, so this meant I was going to be running the trunk version. The techdata page links to a nightly built trunk image specifically for this device, but this image is a sysupgrade image. When you are still running the stock firmware, this image won't do. The router needs to already be running OpenWRT if you want to use the sysupgrade image. For the purpose of getting the router on OpenWRT in the first place, so-called factory images are used. Looking through the nightly built trunk images, there was a noticable lack of this factory image however. Time to compile my own.
I set up a new OpenWRT buildroot environment as per the instructions:
git clone https://git.openwrt.org/openwrt.git
cd openwrt
./scripts/feeds update -a
./scripts/feeds install -a
make menuconfig
At this point, you will be asked how you want your Linux kernel and rootfs to
be configured. Initially, I chose Mediatek Ralink ARM
as the Target System
.
About 24 hours later, I realised that that had been a mistake as I couldn't
manage to get any images generated without a load of compilation errors.
Confusingly enough, when compiling for a Mediatek platform, for Target System
you should choose Ralink RT288x/RT3xxx
. This in turn enables you to choose
from various Mediatek subtargets, in the case of the Ubiquiti EdgeRouter X you
choose MT7621 based boards
. Having done that, there will be a Target Profile
specifically for this router. Now this feels a lot more reassuring than my
earlier option where I couldn't choose subtargets or a profile.
Having ran make -j3 V=s
(verbose compilation with 3 workers) I went into
bin/ramips
and found an image for my router! But, it's the same sysupgrade
image that was available online, I still don't have the factory image I was
looking for. Some thinking and exploration of the options in make menuconfig
later, I realised what I needed to do. The factory images are different from
the sysupgrade images in that they combine the kernel with a filesystem
toghether, this is also called initramfs
. Under Target Images
, select
ramdisk
and leave the compression on lzma as it is. When doing another
compilation run now, you end up with the factory images in addition to the
sysupgrade image.
Installing OpenWRT
Now I needed to find a way to actually get OpenWRT on the router. There are
likely multiple approaches to accomplishing this, but I went with what I
believed to be the path of least resistance. I spotted the router to have just
two small screws and decided to remove these. After this, the casing opens
right up without breaking any stickers and as such this shouldn't affect your
warranty. Low and behold, the pin headers for a serial connection are easily
spotted and better yet: they are already populated! I grabbed my Adafruit-style
USB to serial converter cable and hooked it up as per the pinout described on
the OpenWRT device page. I launched the screen
utility, set the baudrate to
57600, and I was awarded with a working serial connection. I have not come
across many devices where it was this easy to set serial up.
Powering on the router now it becomes apparent that it is using U-Boot as a bootloader for its Linux-based EdgeOS. The following output shows this, and also an interesting addition in the form of some custom pre-implemented boot procedures:
============================================
Ralink UBoot Version: 4.3.S.0
--------------------------------------------
ASIC MT7621A DualCore (MAC to MT7530 Mode)
DRAM_CONF_FROM: Auto-Detection
DRAM_TYPE: DDR3
DRAM bus: 16 bit
Xtal Mode=3 OCP Ratio=1/3
Flash component: NAND Flash
Date:Jan 27 2015 Time:17:52:09
============================================
icache: sets:256, ways:4, linesz:32 ,total:32768
dcache: sets:256, ways:4, linesz:32 ,total:32768
##### The CPU freq = 880 MHZ ####
estimate memory size =256 Mbytes
#Reset_MT7530
Please choose the operation:
1: Load system code to SDRAM via TFTP.
2: Load system code then write to Flash via TFTP.
3: Boot system code via Flash (default).
4: Entr boot command line interface.
7: Load Boot Loader code then write to Flash via Serial.
9: Load Boot Loader code then write to Flash via TFTP.
default: 3
Option 4 presents you with a classical U-Boot prompt and allows you to fiddle with the environment and run any supported commands. I was curious about option 1 though. This option claims to use TFTP to load an image from the network into RAM and then boot that image accordingly, a perfect approach to trying out an image without having to make any changes to the data present on the Flash memory.
I placed the generated initramfs image
(bin/ramips/openwrt-ramips-mt7621-ubnt-erx-initramfs-kernel.bin
) in the
directory that's hosted by the TFTP server on my LAN and connected the router's
eth0
port to this LAN. I then proceeded to powercycle the router so I could
try out the boot option of interest. My second attempt succeeded, pressing the
number 1
before U-Boot has printed out its choices helps significantly. Now
I was presented with a short wizard asking for the required connection and
image details:
You choosed 1
0
1: System Load Linux to SDRAM via TFTP.
Please Input new ones /or Ctrl-C to discard
Input device IP (172.16.3.212) ==:192.168.2.199
Input server IP (172.16.3.210) ==:192.168.2.104
Input Linux Kernel filename (vme50) ==:openwrt.bin
netboot_common, argc= 3
NetTxPacket = 0x8FFE55C0
KSEG1ADDR(NetTxPacket) = 0xAFFE55C0
NetLoop,call eth_halt !
NetLoop,call eth_init !
Trying Eth0 (10/100-M)
Waitting for RX_DMA_BUSY status Start... done
ETH_STATE_ACTIVE!!
TFTP from server 192.168.2.104; our IP address is 192.168.2.199
Filename 'openwrt.bin'.
TIMEOUT_COUNT=10,Load address: 0x80a00000
Loading: checksum bad
checksum bad
checksum bad
Got ARP REPLY, set server/gtwy eth addr (70:5a:b6:b4:24:a1)
Got it
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
##############
done
Bytes transferred = 2731102 (29ac5e hex)
NetBootFileXferSize= 0029ac5e
..Erasing NAND Flash...
ranand_erase: start:80000, len:20000
.Writing to NAND Flash...
done
Automatic boot of image at addr 0x80A00000 ...
## Booting image at 80a00000 ...
Image Name: MIPS OpenWrt Linux-4.4.6
Image Type: MIPS Linux Kernel Image (lzma compressed)
Data Size: 2731038 Bytes = 2.6 MB
Load Address: 80001000
Entry Point: 80001000
Verifying Checksum ... OK
Uncompressing Kernel Image ... OK
No initrd
## Transferring control to Linux (at address 80001000) ...
## Giving linux memsize in MB, 256
Starting kernel ...
Perfect, everything worked as intended and the OpenWRT factory image started to
boot! Before continuing to flash the sysupgrade image, I had a quick peek at
/proc/mtd
to find out what partition layout OpenWRT has decided on for itself.
This layout mostly matched the one used by EdgeOS, with some names being
different and the exclusion of the SPI Flash partition and the ALL
partition.
All in order, so I used wget
on the router to retrieve the sysupgrade image
that I hosted with python -m SimpleHTTPServer
and stored it in /tmp
.
Following this I ran the sysupgrade
tool:
root@OpenWrt:/tmp# sysupgrade -v /tmp/openwrt-ramips-mt7621-ubnt-erx-squashfs-sysupgrade.tar
Cannot save config while running from ramdisk.
killall: watchdog: no process killed
Watchdog handover: fd=3
- watchdog -
killall: telnetd: no process killed
Sending TERM to remaining processes ... dnsmasq ubusd logd netifd odhcpd ntpd
Sending KILL to remaining processes ...
1+0 records in
1+0 records out
Unlocking kernel2 ...
Writing from <stdin> to kernel2 ...
Volume ID 0, size 11 LEBs (1396736 bytes, 1.3 MiB), LEB size 126976 bytes (124.0 KiB), dynamic, name "rootfs", alignment 1
Set volume size to 244682752
Volume ID 1, size 1927 LEBs (244682752 bytes, 233.3 MiB), LEB size 126976 bytes (124.0 KiB), dynamic, name "rootfs_data", alignment 1
sysupgrade successful
[ 81.060000] reboot: Restarting system
Success! The router continued to boot the default option 3 and this time round OpenWRT booted from Flash. Contrary to the initramfs image, the UBIFS on the Flash got mounted too now and this gives you a nice and spacious RW root overlay. Mission accomplished! Now remains one important task, and that is to update the OpenWRT wiki with the information I have found during this little excercise.
Resources
OpenWRT techdata page
OpenWRT device page
OpenWRT forum topic