PCEngines APU2, From Box to Boot

A big thanks to PCEngines and documentation created by Piotr Król. Without that this would not have been possible. I've tried to note when I was using directions produced by someone else.

PCEngines provides hardware solutions that are perfect for routers and firewalls that service a small number of machines. This article will cover all of the pieces/parts/tools you need as well as how to compile and update the firmware.

What to Buy


They have a couple of choices here, but you need:

  • board
  • enclosure
  • A/C adapter
  • storage

I purchased the following directly from their site:

Shipping to the US was about $30, so total I paid about $185 and it took three days to arrive from the day I paid.

I followed up with a second order specifically for the flash recovery board. It's a nice safety net to have if you plan on flashing the firmware. Shipping for the followup order was $5 and took about a week to arrive.


You can find pre-made BIOS images on their BIOS Update page. Optionally, you can downloads and compile their firmware yourself. That process will be covered in detail below.

The TinyCore Linux installer will be used to flash new firmware on to the board, and can be downloaded from PCEngines.

If you're working from Windows then PuTTY will be a crucial tool to have.

Lastly, you'll need a Linux machine to do certain parts of the firmware building process. You can load CentOS 7 into a VirtualBox VM for free.


To put everything together you'll need the following tools.

  • phillips head screwdriver
  • 3/16" hex nut driver
  • alcohol pads (optional)
  • tweezers/x-acto knife (optional)

The alcohol pads are nice to have for cleaning surfaces which will have adhesives applied, but aren't completely necessary. As well, tweezers or an x-acto knife will help in peeling the backings from the thermal pads.

Extra Parts

Finally, you'll need a few other items to make sure you can connect to your APU2 and transfer files to it.

  • ethernet cable
  • null modem cable
  • USB to serial adapter
  • flash drive or SD card

Make sure you get a null modem cable, not just a regular serial cable. I don't have serial ports on my desktop so the USB to serial adapter was necessary for my particular hardware. The flash drive/SD card will be used to host a bootable TinyCore Linux installation.


When you receive your hardware, follow the guide here to assemble the board and enclosure with the heatsink in between. For any areas that have adhesive or a thermal pad applied to them, I recommend first cleaning the area with the alcohol pads.

Install and Configure PuTTY

If you haven't already, install PuTTY and then determine which COM port your null modem cable is connected to. On Windows, you can use the device manager (WIN + r, type "devmgmt.msc", hit enter) to figure this out. Look under the "Ports (COM and LPT)" section. You should see a listing here, my particular setup used COM6.

In the PuTTY connection configuration set the host name to your COM port (in my case I typed in COM6), choose the "Serial" connection type, and set the speed to 115200. In the Connection -> Serial menu, ensure that you have the following settings:

  • Data bits: 8
  • Stop bits: 1
  • Parity: None
  • Flow Control: XON/XOFF

Go back to the "Session" menu, type a name in the "Saved Sessions" box and click on "Save".

First boot

First, let's test your serial (null modem) cable to be sure it won't cause any issues. The PCEngines site says you can bridge pins 2 and 3 on the end you would plug in to the APU2 and any characters entered on the console will be echo'd back. You can use a staple, paper clip, or small length of wire to form the bridge.

Now plug the serial cable into the APU2 and open the PuTTY session we previously setup. Once this is done, connect the power and watch the terminal. You should see some scrolling output and eventually a boot menu. At this point I did nothing and the box automatically booted into memtest which I let run for a few hours while I figured out how to build the firmware.

Create the Firmware Builder Build Environment

We're gonna do this from scratch as much as possible. First, we need an environment that will allow us to build a Linux environment that will allow us to download coreboot for the APU2, compile it, and flash it to the device.

The first layer environment can be any operating system on which Docker will run. They support almost everything so this shouldn't be an issue. Go ahead and install Docker on your platform. My base environment was CentOS 7, so the following commands are assuming that environment. The second layer environment is a Docker container running Ubuntu which we will use to gather and create all the tools necessary for building the firmware.

Retrieve the Base Docker Image

These instructions pulled from here with slight modifications.

Create a directory for this new container and move into it:

mkdir apu2-docker

cd apu2-docker

Then we can pull down the Dockerfile provided by PCEngines:

wget https://raw.githubusercontent.com/pcengines/apu2-documentation/master/Dockerfile

Finally, build the docker image:

docker build -t pc-engines/apu2c .

Now you have the base environment image we need.

Download Packages

These instructions pulled from here with slight modifications.

Now we need to get a few different pieces of software which we'll compile later on.

git clone https://github.com/pcengines/coreboot.git

git clone https://github.com/pcengines/memtest86plus.git

git clone https://github.com/pcengines/ipxe.git

git clone https://github.com/pcengines/sortbootorder.git

Compile Toolchain

Next, we will start up the Docker image we just setup, providing paths to the repos we just downloaded, so that we can compile the toolchain we need to build the payloads and the firmware itself.

docker run -v ${PWD}/coreboot:/coreboot -v ${PWD}/memtest86plus:/memtest86plus -v ${PWD}/ipxe:/ipxe -v ${PWD}/sortbootorder:/coreboot/payloads/pcengines/sortbootorder -t -i pc-engines/apu2c

Once you have a command-line inside the Docker container, the toolchain can be built with the following commands (which I recommend running in a screen session if you're connected over SSH):

cd /coreboot

cp configs/pcengines.apu2.4.0.1.config .config

The next step will take a pretty long time since it has to download a few tarballs and build the entire toolchain. Get comfortable or find something else to do for a while.

make crossgcc-i386 CPUS=4


Compile a New Firmware Image

Now we have both a toolchain and the supporting environment necessary for building the firmware.

Build Payloads

Continuing instructions from here with slight modifications.

We'll use the toolchain to compile all of the payloads that we want to add to the image (e.g. ipxe, memtest). Continue executing these commands within the same Docker container.

IPXE Payload


wget https://raw.githubusercontent.com/pcengines/apu2-documentation/master/ipxe/general.h -O $IPXE_PATH/src/config/local/general.h

wget https://raw.githubusercontent.com/pcengines/apu2-documentation/master/ipxe/menu.ipxe -O $IPXE_PATH/src/menu.ipxe

cd $IPXE_PATH/src

make bin/8086157b.rom EMBED=./menu.ipxe

That step took about ten minutes. It's important to note that the name of the ROM corresponds to the vendor/device IDs for an Intel I210 NIC, the specific NICs found on the APU2C4 board. If you have a different board then it's possible you will need to name the ROM differently so that the correct drivers are built in to the firmware.

Sortbootorder Payload

Continue executing these commands within the Docker container.

cd /coreboot/payloads/libpayload

wget https://raw.githubusercontent.com/pcengines/apu2-documentation/master/xcompile/.xcompile-libpayload

make clean

make defconfig


make install

cd ../pcengines/sortbootorder



Continue executing these commands within the Docker container.

cd /memtest86plus


Place Compiled Payloads into the Coreboot Image

Continue executing these commands within the Docker container.

cd /coreboot

./build/cbfstool ./build/coreboot.rom add -f /ipxe/src/bin/8086157b.rom -n genroms/pxe.rom -t raw

./build/cbfstool ./build/coreboot.rom remove -n img/setup

./build/cbfstool ./build/coreboot.rom add-payload -f payloads/pcengines/sortbootorder/sortbootorder.elf -n img/setup -t payload

./build/cbfstool ./build/coreboot.rom remove -n img/memtest

./build/cbfstool ./build/coreboot.rom add-payload -f /memtest86plus/memtest -n img/memtest -t payload

Pull out the image

So now you've fully built the coreboot firmare image and it can be found at /coreboot/build/coreboot.rom. However, this ROM image is inside a Docker container and we need it outside of the Docker container so we can write it to the APU2.

We can do this from the host machine using the docker cp command, but it requires knowing the Docker container ID. If you look at your command-line within the container, the ID is on the prompt:


Where the ID for this container is 62dd0a6d50c4. Copy this down somewhere since we'll need it in just a second. Go ahead and exit the Docker container since we're done with it.


Now copy out the coreboot.rom image to your local directory (you should be placed back in the apu2-docker directory after exiting the container). Replace the ID text below with your container ID.

docker cp ID:/coreboot/build/coreboot.rom ./coreboot.rom

My command specifically was:

docker cp 62dd0a6d50c4:/coreboot/build/coreboot.rom ./coreboot.rom

Great, now we have a local copy of the firmware we wish to write to our APU2. We just need to get it in an environment capable of writing to the flash of our APU2. At this point I used WinSCP to copy the coreboot.rom file from this Linux system back to my main Windows machine so I can use it in the next step.

Write Firmware with TinyCoreLinux

We'll create a bootable TinyCore Linux flash drive (optionally SD card) and finally flash the APU2 with the ROM we just compiled.

Create TinyCore Linux Bootable Device

This step can utilize a USB flash drive or SD card, depending on what you have available. The APU2 can boot from either one. You can download the TinyCore Linux installer directory from PCEngines on this page.

Plug-in a flash drive/SD card you're OK with having wiped, run the TinyCore Linux installer, select the desired device, check the box to format the flash drive, and let it install TinyCore Linux for you.

On my first try, I didn't check the format option and got the following message during installation:

An error(1) occurred while executing syslinux. Your USB device won't be bootable...

This seems to be caused by an issue with the existing drive format. I reformatted it as NTFS, re-ran the installer and the error went away. However, using the format option within the tool is the way to go.

Now that your flash drive has TinyCore Linux, copy the coreboot.rom file to the flash drive before removing it. When TinyCore Linux boots up it will automount the drive in /media and we can directly pull the new ROM image from the flash drive itself (thanks for the tip on this PCEngines).

Boot TinyCore Linux on the APU2

First, reboot or power on your APU2 and watch the console. The very first messages will be about the current coreboot build and the BIOS version. Something like:

PCEngines apu2
coreboot build 20160307

SeaBIOS (version ?-20160307_153453-michael-desktop64)

Take note of this information so that we can verify that we've actually updated the flash image on the device.

Safely remove the boot device you just made, plug it in to your APU2, and power it up. Shortly after booting you should see a message:

PCengines Press F10 key now for boot menu:

Press F10 and select the appropriate boot device (flash drive or SD card). You'll be presented with a few boot options, choose "tinyCore". After 15-20 seconds you should see a nice ASCII art image saying "PC Engines" and get a command prompt.

I like copying the file to the home directory, even though it may not matter:

[+53.9 C][root@box:~]$ ls /media
TINYCORE          flash_drive_sdb
[+54.1 C][root@box:~]$ cp /media/TINYCORE/coreboot.rom .

Flash the New Firmware

Finally! Now that we have the new firmware image in an environment running on the APU2, we can actually flash it. Assuming your new firmware is in the home directory of the default logged in user, /root/coreboot.rom, you can flash it like so:

flashrom -w /root/coreboot.rom -p internal

This is the scary part and you'll just have to cross your fingers and wait...

Assuming it succeeded, power down TinyCore Linux and remove the TinyCore Linux flash drive.

Verifying flash... VERIFIED.
[+49.8 C][root@box:~]$ poweroff

The Moment of Truth

Power up your APU2 and let's see if we were successful. The first few prints should now be similar to:

PCEngines apu2

Google, Inc.
Serial Graphics Adapter 08/22/15
SGABIOS $Id: sgabios.S 8 2010-04-22 00:03:40Z nlaredo $ (wiv@coreboot-Virtual-Machine) Sat Aug 22 09:25:30 UTC 2015
Term: 80x24
IO4 0

SeaBIOS (version rel-1.9.0-139-gac6d3e2)

We no longer see the coreboot build 20160307 message, and the SeaBIOS version as changed. Success!


Now that your APU2 is up and running with the most up-to-date firmware you can proceed with installing an operating system of your choice. See the manual for specific notes about OS support.