I just recently swapped out my old tower with an Intel Core i7 and 12GB of RAM for a Raspberry Pi 4, the 4GB model. This is a pretty drastic change, and I'm sacrificing a lot of computing power in the process. Of course, this is a pain for building OpenBSD ports, because they take forever, but other than that I'm loving it.
All I use my desktop machine for is writing these blog posts, doing some programming projects, and then occasionally doing homework. I used to run it as my home server, until I got a dedicated server. Suffice it to say that I don't really do any intensive computing with it anymore. I obviously run OpenBSD on it, and OpenBSD is very lightweight. However, this machine is starting to have problems. It is 10 years old this year, and though it performs just fine, it is very loud because the fans are failing, and it takes a very long time to boot up. This latter problem is probably more the fault of OpenBSD, though. Now, I could most likely just replace the fans, and get a faster SSD, but I would really love to have a computer that
The Raspberry Pi 4 seems like the perfect candidate for a computer that satisfies all of these requirements, especially because I already have one laying around. I figured it shouldn't be too hard to get OpenBSD running on it, since OpenBSD does have ARM support, and even lists a few Raspberry Pi models as supported. Unfortunately though, the install process is a bit more complex for this little ARM computer than it is for a normal x86 computer.
The first problem is that it does not have a UEFI implementation. Instead, it uses a tiny EEPROM that loads firmware and kernel images from a FAT32 partition on an SD card. You can program this EEPROM to also boot the same way from an external USB drive or—theoretically, at least—from the network 1. This probably works fine for the official Raspberry Pi OS, which is tailored specifically for this setup, but it doesn't work so great for operating systems that expect a little more of a standardized boot-up process. OpenBSD prefers to do things correctly, and that means expecting a boot ROM that will properly initialize the hardware to a known state.
OpenBSD's official solution to this problem is to ship U-Boot on their ARM images. Technically speaking, U-Boot does the job. It does indeed boot OpenBSD to the installer, and I'm able to complete an install. However, the screen is fuzzy and the performance is also not very good. I was never able to get U-Boot installed on the hard drive that I installed OpenBSD on either, which means that after the install, I couldn't boot it. The ramdisk kernel doesn't seem to have mkuboot(8) built into it, at least not as of OpenBSD 7.1. I tried copying the U-Boot files from the installation disk, but OpenBSD doesn't allocate a FAT partition big enough for all that. I quickly ran out of disk space and didn't feel like re-installing OpenBSD with a bigger FAT partition. I wanted to stick as closely as possible to the official install process and use the recommended disk partitioning.
Another problem I had was with full-disk encryption. Full-disk encryption is an absolute must for me on all of my computers—even my servers. I don't even consider installing OpenBSD without it. Unfortunately, U-Boot could not figure out how to boot a softraid(4) volume. So all of these problems left me searching for a better solution that would allow me to install OpenBSD just like I would on my desktop. If I could manage, I even wanted to network-boot the installer.
I then discovered a project on Github 2 that provides EDK2 3 builds for the Raspberry Pi 4. EDK2 is a development UEFI firmware that is conveniently BSD-licensed. This basically means that I can install a UEFI bootloader onto the Raspberry Pi, which allows me to theoretically just boot the OpenBSD installer disk with that instead of the built-in U-Boot hack.
I grabbed my own copy of the Raspberry Pi UEFI firmware and then installed it to a microSD card, pretty much like this:
Basically, I just created a FAT partition on the SD card, and copied the firmware files over. Then, I inserted the card into my Raspberry Pi, and re-flashed my EEPROM so that it only boots from the card without trying to boot from anything else. That's now supposed to be the UEFI's job. When I booted my Pi, I was delighted to see a full UEFI splash screen complete with the Raspberry Pi logo, and upon hitting ESC to get to the settings, I disabled the 3GB memory limit, and made sure the boot order was correct. When I rebooted, I was taken right to my connected USB drive, which proceeded to prompt me for my password for the softraid(4) volume.
Just for fun, I set up my DHCP server to serve the ARM EFI bootloader binary to my Raspberry Pi, and much to my surprise, I was able to do a network install using the UEFI firmware's PXE boot, just like on my x86 machine.
One thing I immediately noticed when I got through my final installation of OpenBSD on this machine, is that the graphics were so much better than when I was using U-Boot, and the sets downloaded and extracted faster. This is to say that I would highly recommend using the UEFI firmware instead of U-Boot if you're interested in installing OpenBSD on a Raspberry Pi. It's easy enough to configure, and prevents so many problems. It even boosts performance for some reason beyond me at the moment.
I could theoretically have the EEPROM boot directly to the USB drive, which could then have the UEFI firmware on it to boot OpenBSD. That wouldn't be too much more difficult to do, but again, that would require a non-standard OpenBSD partition scheme, and I didn't really want to deal with that. It seems more correct and proper to have the UEFI firmware on the microSD card, totally independent from the OpenBSD drive. One thing to note is that I did have to manually run installboot(8) to get OpenBSD's EFI bootloader installed. I think this should happen automatically on an unencrypted install, but something got lost in translation there when I set up the encryption. No big deal, though. Once I ran the proper command, everything worked great.
So now that I can boot to a functional system, I started messing around to see what worked and what didn't. It's always expected that something isn't going to work properly on these little obscure machines, so I was determined to figure out what it was. One thing I noticed during the install is that I was never prompted to enable xenodm(1), which usually indicates that the installer doesn't recognize your graphics setup. This concerned me at first, but when I booted to the completed install, the console graphics looked crispy, and I was able to log in as root and start xenodm. It started up without issues, and the screen resolution is the same as it was with my x86 machine. There was no lag either. It really felt just like my other computer.
I am getting some bwfm(4) firmware errors in the kernel log. Even though fw_update(8) reports that all the firmware is installed and up to date, it doesn't look like the Raspberry Pi's WiFi will work. That doesn't bother me though, because I have it connected to a switch on my desk with a little mini patch cable. I don't run WiFi on any of my machines if I don't absolutely have to.
Now it's time to install packages and get the system configured to my liking. Of course, nothing ever goes according to plan. I got Firefox and a few other essential packages installed from the official mirror, but when I got to installing LibreOffice, pkg_add(1) reported that the package could not be found. I checked out my mirror, and sure enough, there was no build of LibreOffice for arm64. I'm not a quitter though. I fetched the ports tree and would attempt to build it from source. I had to add arm64 as a supported architecture to editors/libreoffice/Makefile, because the ports build system complained that I was not building it on a supported architecture. But once I patched the Makefile, the build took off.
Of course there were a few hiccups along the way. While the build was under way, I tried to install a little fan to keep my Pi cool. In the process, I accidently shorted the GPIO pins and caused it to force shut down in the middle of my build. When I rebooted, the build started failing in weird ways, such as the linker segfaulting, so I had to clean out a bunch of packages and rebuild them. Finally, once that was taken care of, I ran out of space on my /usr partition halfway through. This is because I had neglected the step on the OpenBSD FAQ page that configured the different directories. So I added an /etc/mk.conf:
WRKOBJDIR=/usr/obj/ports DISTDIR=/home/distfiles PACKAGE_REPOSITORY=/home/packages
I'm assuming that the /usr/obj partition is specifically made for building ports, so I moved /usr/ports/pobj to /usr/obj/ports, which freed up a ton of space on /usr. I just moved the distribution archives and the package repository to my home partition for now because those took up the bulk of the space, and I didn't want them under /usr at all. After getting all that sorted out, I restarted the build for a third time.
I'm sure it would've finished just fine, and I would have had a working LibreOffice installation, but around the 10 hour mark, I saw that the Raspberry Pi was downloading the source code for GCC and was going to compile it from source. I let it go for maybe an hour more, but I eventually gave up on compiling LibreOffice from ports because it was just taking too long and building way too many dependencies. I CTRL+C-ed the process and turned off the Raspberry Pi. I wanted to do a clean install because by that point, there were a ton of packages installed. I connected a fresh hard drive, and installed OpenBSD on it from the network.
It looks like I'll have to live without LibreOffice for now, which is fine with me because I want to use mandoc(1) more, and, if I absolutely have to, TeX. I'm all about reducing my dependency on large, complicated software, and trying to build LibreOffice really showed me just how big and complicated it is. I will probably have to use it for a few more years for college, but then after that, I'd love to ditch it completely. In the meantime, I want to try converting all of my existing documents to plain text. Maybe I'll use pandoc for this.
Other than the fact that ports build extremely slowly, using a Raspberry Pi is surprisingly pleasant. Even with a little fan, it is so much quieter than my old desktop computer, and I feel a lot better about leaving it on all the time. It's also not too slow. Sure, it isn't as snappy as my old computer, but it isn't laggy or glitchy either. Everything seems to just work so far. I haven't tested the audio, and I'm certain that the WiFi won't work, but neither of those things are super important to me at the moment. When they do become important, I'll figure it out then!
My complete setup is really quite simple. On my desk is the Raspberry Pi 4 with one of those acrylic puzzle cases that has a fan in it. Connected is a wired keyboard and mouse, an ethernet cable, a display, and an external hard drive. The external hard drive is actually an NVME drive in a USB enclosure that has a massive heatsink and it's own little fan that comes on if the drive starts getting warm. So far, it seems to be performing rather well. I'm using the offical Raspberry Pi power supply, as well as the offical display cable.
I could never figure out how to have the EEPROM fetch anything over the network. It makes a DHCP request to the server, and the server responds with an address it can use, and the EEPROM will even pick up this address and display it on the screen, but it never acknowledges to the server that it obtained this address, and then it just hangs. Maybe this has something to do with OpenBSD's dhcpd(8) implementation, but it's more likely a bug in the EEPROM because my DHCP server works great for everything else, including the UEFI implementation I installed. ↩
© 2019-2023 Jordan Bancino.