FreeBSD on a Raspberry Pi 4 with 4GB of RAM

This is the story of how I managed to get FreeBSD running on a Raspberry Pi 4 with 4GB of RAM, though I think the setup story is pretty similar for those with 2GB and 8GB.1

I also managed to get Rust built from source, (kind of) which is nice because the default Rust installer doesn’t seem to work for FreeBSD running on a Raspberry Pi.

If there’s anything awry with these steps, please contact me so I can fix it.

Installing FreeBSD

First, get yourself a Raspberry Pi 4 and an SD card. (I don’t know how to boot from a hard disk; if anyone figures that out, please let me know.) Next, download the FreeBSD image from the 13.0 snapshot repository. I used what was the most recent version as of 2020-12-23 (FreeBSD-13.0-CURRENT-arm64-aarch64-RPI3-20201210-7578a4862f0.img.xz).

FreeBSD doesn’t make Pi 4-specific snapshots, so you just have to use the RPI 3 version.

Unpack the zip file, and flash that to your SD card:

xz -d FreeBSD-13.0-CURRENT-arm64-aarch64-RPI3-20201210-7578a4862f0.img.xz

sudo dd bs=1m if=FreeBSD-13.0-CURRENT-arm64-aarch64-RPI3-20201210-7578a4862f0.img of=/dev/DISK_NUMBER conv=sync

Plug that into your Pi, and make sure it boots up.

Get FreeBSD to recognize all the RAM available

You can check how much RAM the OS thinks it has like this:

sysctl hw.physmem

After upgrading the boot system, I got 4124610560 (4GB). Prior to this, this returned a much lower number (though I can’t remember what it was).

First, on your FreeBSD pi, you’ll want to install the following packages:

sudo pkg install sysutils/rpi-firmware
sudo pkg install u-boot-rpi4

(Not sure how necessary that first one is, actually. Didn’t seem to hurt things though.)

After you’re done installing the u-boot-rpi4 package, you will want to copy a file from your FreeBSD machine to something you can use to modify the SD card. (In my case, I used the same machine as the one I used to flash the SD card in the first place.)

me@non-freebsd:~ $ rsync -aivz root@generic:/usr/local/share/u-boot/u-boot-rpi4/u-boot.bin .

(NOTE: If you want to use rsync, you’ll have to install rsync on your FreeBSD machine with pkg install rsync)

Shut down your Raspberry Pi, pull out the SD card, and mount it onto that machine you just copied the u-boot.bin file to. Open up the MSDOSBOOT image, and find the u-boot.bin file in the root of the image. Delete it, and move the one you copied from your pi into its place. Eject the SD card, and replace it into your Pi. Boot it up!

You can check to make sure that your Raspberry Pi now enjoys the full amount of RAM available on your machine:

$ sysctl hw.physmem
hw.physmem: 4124610560

Installing Rust

I love Rust. Unfortunately, FreeBSD running on an ARM system (like a Raspberry Pi) is in Tier 3 support, so I had to do some work to get it built myself.

Prerequisites

You will need to have all 4GB of RAM available. I tried this before getting the 4GB thing working, and builds kept failing.

Building everything from source takes forever, so go ahead and install the following with pkg:

  • perl (I think you need to specify a version with this one; just get the latest version)
  • python
  • llvm
  • git
  • cmake
  • libgit2
  • ninja
  • pkgconf

Ports Tree

You’ll want to get the ports tree on your machine so you can build Rust. Make sure you set your clock so it’s the right time, then you can install the port tree:

portsnap fetch
portsnap extract

That last command will take a while to run.

Start Building

Rust takes a very long time to build and consumes a lot of CPU. My build has been running all day and it hasn’t finished yet. You’ll want to throttle up your fan on your Raspberry Pi if you’ve got one; thermal throttling can kick in pretty quickly when all four cores are going at 100%.

This should get the build started:

cd /usr/ports/lang/rust
make

That should run for a few hours at least. Like, on the order of 18 hours or so. (Download speeds are not the bottleneck, at least not for me!)

And, for me, unfortunately, the build died near the end with this error:

       Fresh walkdir v2.3.1
       Fresh cmake v0.1.44
Traceback (most recent call last):=====>                               ] 35/76: serde_json(build), cmake, walkdir, ryu(build)
  File "x.py", line 11, in <module>
    bootstrap.main()
  File "/usr/ports/lang/rust/work/rustc-1.48.0-src/src/bootstrap/bootstrap.py", line 1066, in main
    bootstrap(help_triggered)
  File "/usr/ports/lang/rust/work/rustc-1.48.0-src/src/bootstrap/bootstrap.py", line 1039, in bootstrap
    build.build_bootstrap()
  File "/usr/ports/lang/rust/work/rustc-1.48.0-src/src/bootstrap/bootstrap.py", line 824, in build_bootstrap
    run(args, env=env, verbose=self.verbose)
  File "/usr/ports/lang/rust/work/rustc-1.48.0-src/src/bootstrap/bootstrap.py", line 153, in run
    raise RuntimeError(err)
RuntimeError: failed to run: /usr/ports/lang/rust/work/bootstrap/bin/cargo build --manifest-path /usr/ports/lang/rust/work/rustc-1.48.0-src/src/bootstrap/Cargo.toml --verbose --frozen
*** Error code 1

Stop.
make[1]: stopped in /usr/ports/lang/rust
*** Error code 1

Stop.
make: stopped in /usr/ports/lang/rust

However, I did notice that there was a rustc binary hanging out in /usr/ports/lang/rust/work/bootstrap/bin/rustc, along with binaries for cargo, rustdoc et. al. I think something in the standard lib (maybe serde) failed to build for some reason, but I tried compiling a little “Hello, World!” program, and that worked just fine. I don’t know how well other things will work.

If anyone manages to get everything working please tell me how you did it and I will update this post for the benefit of anyone coming after. :)

UPDATE 2020-12-28

I managed to compile a little rust program I made, and this includes serde. I’m not sure how well the filesystem watcher works; I’ll try that out some time and see how it goes. I just had to add /usr/ports/lang/rust/work/bootstrap/bin to my path, and I was able to run cargo build and then cargo run with no problems.


  1. See this thread for some help on 8GB Raspberry Pis ↩︎