Tag Archives: freebsd

PC Engines APU2C4

Installing FreeBSD on PC Engines APU2

PC Engines APU2C4

The PC Engines APU2C low-power network computer on my desk, with serial console, the first ethernet port and a USB stick connected.

PC Engines has been producing small, low-power systems with AMD CPUs for a long time. Among the great features for building your own router are built-in serial console and multiple quality Ethernet controllers. For a project I selected the apu2c4, a system with three gigabit Ethernet ports and 4 GB of RAM. Together with a small M2 SSD module, you have a decently powerful machine to run as a router. In fact, it has enough capacity to run some applications as well, or even small VMs if you’re so inclined!

Installing FreeBSD

Installing FreeBSD on the APUs is fairly straightforward; however, a small number of gotchas might trip you up. Here’s how I managed to complete the install, and update the APU firmware once I had FreeBSD installed.

  1. Download the FreeBSD memstick installer image. I used my closest FreeBSD mirror to download FreeBSD-11.2-RELEASE-amd64-memstick.img.
  2. Copy the image to a USB stick that is at least as large as the image; 1 GB should be sufficient. I had trouble when I did the copying on my Mac with the resulting stick not working properly; using a FreeBSD box did the trick for me.
  3. Before booting from the USB stick, mount the UFS partition on a FreeBSD machine. For 11.2, that’s da0s2a; for other releases, it might be different. You can use gpart list to identify the UFS partition to mount.
  4. Add the following lines to /mnt/boot/loader.conf to properly enable just the serial console, and give the USB subsystem enough time to attach the USB stick:
  5. vfs.mountroot.timeout="10"
    comconsole_speed="115200"
    console="comconsole"
  6. Unmount /mnt and move the stick to the APU.
  7. Connect a serial terminal to the APU console port; I usually use an USB dongle and a null modem cable or adapter, and my own simple serial console program or cu(1), using 115200 baud.
  8. Boot from the USB stick and install FreeBSD as you would on any other PC. Before you reboot:
  9. Make sure to add the console and comconsole_speed variables to /boot/loader.conf on the installed system on the APU as well. Unless you add them, you won’t be able to log in to the console.

If you forget to edit /boot/loader.conf, not all is lost: you can change the settings during boot. But because the loader detects both the serial console and a keyboard (although the APU has no support for a keyboard or built-in graphics), it is somewhat cumbersome, as the console output will be screwed up.

Updating the BIOS

The APUs use CoreBoot as their BIOS. PC Engines has ready to use CoreBoot images on their own GitHub page. You can update the BIOS using flashrom, a command line tool to program firmware devices across many devices and platforms.

To update the APU BIOS:

  1. Download the correct CoreBoot image for your model of APU from pcengines.github.io, directly to the APU. I picked apu2 v4.8.0.1, which was the newest at the time of this post.
  2. Extract the firmware file:
  3. $ fetch http://pcengines.ch/file/apu2_v4.8.0.1.rom.tar.gz
    apu2_v4.8.0.1.rom.tar.gz                      100% of  852 kB 4100 kBps 00m00s
    $ tar xf apu2_v4.8.0.1.rom.tar.gz 
    $ ls -l
    total 862
    -rw-r--r--  1 stb  wheel  8388608 Jun  8  2018 apu2_v4.8.0.1.rom
    -rw-r--r--  1 stb  wheel       52 Jun  8  2018 apu2_v4.8.0.1.rom.md5
    -rw-r--r--  1 stb  wheel   873087 Jun 26  2018 apu2_v4.8.0.1.rom.tar.gz
  4. Install the utility:
    $ sudo pkg install flashrom
    Updating FreeBSD repository catalogue...
    FreeBSD repository is up to date.
    All repositories are up to date.
    Checking integrity... done (0 conflicting)
    The following 1 package(s) will be affected (of 0 checked):
    
    New packages to be INSTALLED:
            flashrom: 1.0
    
    Number of packages to be installed: 1
    
    Proceed with this action? [y/N]: y
    [1/1] Installing flashrom-1.0...
    [1/1] Extracting flashrom-1.0: 100%
  5. Check that flashrom can talk to your motherboard OK:
  6. $ sudo flashrom -p internal
    flashrom v1.0 on FreeBSD 11.2-RELEASE (amd64)
    flashrom is free software, get the source code at https://flashrom.org
    
    Using clock_gettime for delay loops (clk_id: 4, resolution: 2ns).
    coreboot table found at 0xcfde9000.
    Found chipset "AMD FCH".
    Enabling flash write... OK.
    Found Winbond flash chip "W25Q64.V" (8192 kB, SPI) mapped at physical address 0x00000000ff800000.
    No operations were specified.
  7. Verify the version currently installed:
  8. $ sudo dmidecode -t bios
    # dmidecode 3.1
    Scanning /dev/mem for entry point.
    SMBIOS 2.7 present.
    
    Handle 0x0000, DMI type 0, 24 bytes
    BIOS Information
            Vendor: coreboot
            Version: v4.8.0.1
            Release Date: 20180608
            ROM Size: 8192 kB
            Characteristics:
                    PCI is supported
                    PC Card (PCMCIA) is supported
                    BIOS is upgradeable
                    Selectable boot is supported
                    ACPI is supported
                    Targeted content distribution is supported
            BIOS Revision: 4.0
            Firmware Revision: 0.0
  9. Program the new version to the flash chip:
  10. $ sudo flashrom -p internal -w apu2_v4.8.0.1.rom
  11. If flashrom complains about the image not matching the mainboard, you need to force the programming as suggested in this forum post.
  12. Reboot the APU to activate the new firmware.

(Astute readers will notice that the above output already shows version 4.8.0.1 being installed; I took that output after successfully upgrading.)

I tried to update the BIOS using the procedure suggested by PC Engines, using TinyCore, but I had trouble creating a TinyCore USB stick. Luckily I came across this BSD Foren post and realised that I could just use FreeBSD directly.

Getting sshd to start as early as possible

In FreeBSD, sshd by default gets started quite late in the boot process, about the same time a console will show the login prompt. There’s quite a few services that can make trouble and hang before that. Annoyingly, you can’t fix a stuck system via ssh, since it’s not started yet. But as it turns out, sshd can be started quite a bit earlier than FreeBSD does by default.

The rcorder keywords in /etc/rc.d/sshd normally look like this:

# PROVIDE: sshd
# REQUIRE: LOGIN cleanvar
# KEYWORD: shutdown

Change the rcorder keywords like so:

# PROVIDE: sshd
# REQUIRE: NETWORKING cleanvar
# BEFORE: mountcritremote
# KEYWORD: shutdown

 

Now sshd will be started right after the network has been configured.

Note that starting sshd before certain parts of the system are ready might give you temporary or permanent errors. For example, starting sshd before the user home directories are mounted might cause problems with logins. However, if your machine has all critical filesystems on local disks, making these changes should not pose any problems, and will allow you to log in while the rc scripts are still running, giving you the opportunity to fix any misbehaving services.

Running bash as root’s shell only when it’s not broken

I like bash, mostly for its interactive features over FreeBSD’s standard Bourne-compatible shell, ash.

Setting bash as the default shell for the root user however has a big downside: if you ever break bash or any of the libraries it depends on, you can’t log in as root anymore to fix it. I’ve tried quite a few ways to work around this, and I think I’ve finally figured out a good solution: leave the root shell as /bin/sh, and add this snippet at the end of /root/.profile:

[ -z "$BASH" ] && /usr/local/bin/bash -c 'true' && exec /usr/local/bin/bash

This will start bash, but only if the shell sourcing .profile isn’t bash, and bash can actually successfully be executed.

In FreeBSD 9, ash has apparently grown command name completion. Together with the editing functions (already available in FreeBSD 7), this might allow me to switch to ash as the default shell.

 

FreeBSD, CUPS and iPad printing

For the longest time, I couldn’t get CUPS configured on my FreeBSD server successfully. Between CUPS access rules, foomatic drivers and avahi announcements, I had terrible trouble making heads or tails of the nondescript error messages I was getting.

Spurned on by the arrival of an iPad, I finally sat down and worked through configuring CUPS and avahi. So I don’t have to go through all the fiddling again, here’s a recipe of what I did.

Getting started with IPv6

Getting started with IPv6 on FreeBSD with Hurricane Electric’s free Tunnelbroker service is really straightforward. Since I’m behind a residential ADSL connection, my IPv4 address changes every 24 hours, so whenever that happens, the Tunnelbroker needs to learn my new address. We’ve put up a quick how-to on the wiki on how to do that.

FreeBSD ppp(8): work around invalid remote address

When connecting via a Huawai E169 UTMS USB stick through O2 Germany’s network, the data stick or the network suggests a PPP IPCP remote address of 0.0.0.0. FreeBSD refuses to ifconfig the tun interface with this endpoint address.

Fortunately, ppp(8) offers a configuration parameter to influence the IP addresses negotiated with the peer (ifaddr), and suggesting a different address will make the configuration work.

If you get this log output from ppp, you need to configure address selection:

IPCP: deflink: RecvConfigAck(4) state = Req-Sent
IPCP:  IPADDR[6] 10.68.235.57
IPCP:  PRIDNS[6] 193.189.244.197
IPCP:  SECDNS[6] 193.189.244.205
IPCP: deflink: State change Req-Sent --> Ack-Rcvd
IPCP: deflink: RecvConfigReq(47) state = Ack-Rcvd
IPCP:   [EMPTY]
IPCP: deflink: SendConfigAck(47) state = Ack-Rcvd
IPCP:   [EMPTY]
IPCP: deflink: State change Ack-Rcvd --> Opened
IPCP: deflink: LayerUp.
IPCP: myaddr 10.68.235.57 hisaddr = 0.0.0.0
Warning: iface add: ioctl(SIOCAIFADDR, 10.68.235.57 -> 0.0.0.0): Destination address required
Error: ipcp_InterfaceUp: unable to set ip address

Here’s my complete ppp.conf, with the ifaddr line included:

u3g:
	set device /dev/cuaU0.0
	set speed 115200
	set ifaddr 10.0.0.1/0 10.0.0.2/0 255.255.255.0
	set authname internet
	set authkey  internet
	set log local phase ipcp
	set dial "ABORT BUSY TIMEOUT 2 \
		\"\" \
		AT OK-AT-OK \
		AT+CFUN=1 OK-AT-OK \
		AT+CMEE=2 OK-AT-OK \
		AT+CSQ OK \
		AT+CGDCONT=1,\\\"IP\\\",\\\"internet\\\" OK \
		AT+CGACT? OK-AT-OK \
		AT+CGATT? OK \
		AT+CGCLASS? OK \
		AT+COPS? OK \
		ATD*99***1# CONNECT"
	set crtscts on
	nat enable yes
	add default HISADDR
	disable dns

This applies to both 7-stable and 8-stable (with both the old and the new USB stacks). I’ve used u3g(4) on both occasions. The original ppp.conf for 3G modems is based off this one from Nick Hibma.

This is how it looks like when using ifaddr:

IPCP:  PRIDNS[6] 10.11.12.13
IPCP:  SECDNS[6] 10.11.12.14
IPCP:  PRINBNS[6] 10.11.12.13
IPCP: MS NBNS req 130 - NAK??
IPCP:  SECNBNS[6] 10.11.12.14
IPCP: MS NBNS req 132 - NAK??
IPCP: deflink: SendConfigReq(2) state = Req-Sent
IPCP:  IPADDR[6] 10.0.0.1
IPCP:  COMPPROTO[6] 16 VJ slots with slot compression
IPCP: deflink: RecvConfigReq(50) state = Req-Sent
IPCP:   [EMPTY]
IPCP: deflink: SendConfigNak(50) state = Req-Sent
IPCP:  IPADDR[6] 10.0.0.2
IPCP: deflink: RecvConfigRej(2) state = Req-Sent
IPCP:  COMPPROTO[6] 16 VJ slots with slot compression
IPCP: deflink: SendConfigReq(3) state = Req-Sent
IPCP:  IPADDR[6] 10.0.0.1
IPCP: deflink: RecvConfigNak(3) state = Req-Sent
IPCP:  IPADDR[6] 10.42.237.110
IPCP:  IPADDR[6] changing address: 10.0.0.1  --> 10.42.237.110
IPCP: deflink: SendConfigReq(4) state = Req-Sent
IPCP:  IPADDR[6] 10.42.237.110
IPCP: deflink: RecvConfigAck(4) state = Req-Sent
IPCP:  IPADDR[6] 10.42.237.110
IPCP: deflink: State change Req-Sent --> Ack-Rcvd
IPCP: deflink: RecvConfigReq(51) state = Ack-Rcvd
IPCP:   [EMPTY]
IPCP: deflink: SendConfigAck(51) state = Ack-Rcvd
IPCP:   [EMPTY]
IPCP: deflink: State change Ack-Rcvd --> Opened
IPCP: deflink: LayerUp.
IPCP: myaddr 10.42.237.110 hisaddr = 10.0.0.2
PPP ON freebsd-current>

Fonts are finally coming to the web

I have to admit that I didn’t follow developments too closely for the last couple of years, but I was rather surprised today to find that Safari 4, Firefox 3.5 and Internet Explorer 6 to 8 support downloadable TrueType fonts in a compatible and useful manner.

Slashdot post, linked Slate article, nice overview page.

A couple of things that are buried in the pages linked above, but which helped me to get up to speed:

<style>
@font-face {
    font-family: "testing";
    src: url("output.ttf") format("truetype");
}
</style>
<!--[if IE]>
    <style>
    @font-face {
        font-family: "testing";
        src: url("output.eot");
    }
    </style>
<![endif]-->
<div style="font-family: testing">
Hello, Multiple Browser World!
</div>

Now I just need to quickly build a WordPress and a MediaWiki template, and we’re all set 🙂