Setting up Gentoo Linux on an MNT Reform Laptop

Introduction

This post is about my installation of Gentoo Linux on an MNT Reform laptop. So, first things first, what are those two things?

MNT Reform

The MNT Reform is an open hardware laptop by MNT Research. It is modular, and the case, mainboard, screen, keyboard, batteries, and, most important, the SoM can be swapped individually. For all of those parts the schematics are available for free on the MNT Research website. MNT also makes it a goal to support SoMs that can be used with little to no proprietary firmware, and that ideally are open hardware themselves. At the time of writing there are 5 different SoMs available for the Reform laptop, four of which are AArch64 based, while the fifth is an FPGA development board. An outstanding feature of the MNT Reform is its keyboard, which has mechanical keys with a rather large key drop, compared to most laptop keyboards. The rather large case also allows for a trackball as an alternative pointing device. Other things that make the MNT Reform stand out compared to most laptops are the case design, with a clear backplate to look inside, the broad range of accepted charging voltages, and that it uses standardized LiFePO4 batteries.

Gentoo Linux

Gentoo Linux is a source based Linux distribution. This means that users can easily change compile time options for to-be-installed packages, and therefore customize the system way more freely than on binary-only distributions. Gentoo's main selling point is this customizability, that also extends to other areas, like the free choice of init-daemon, system logger,... Gentoo Linux is rolling release, what means that there are no fixed release cycles, and packages are updated individually. Despite this, Gentoo is a very stable distribution. Unless the user explicitly chooses to install unstable package versions, the distribution will only ship well tested and known-to-be-compatible updates.

Motivation for installing Gentoo on the Reform

The official operating system image for the MNT Reform is Debian Linux. Which Debian versions are available depends on the used SoM, and pre-built images are only available for Debian Unstable. Debian Unstable is definitely not an option for me (due to its inherently unstable and buggy nature). MNT Research would offer a script to build Debian Stable for the Reform with my SoM, the Banana Pi CM4, but while Debian Stable is a Linux distribution I enjoy very much and also what I would recommend for new and experienced Linux users alike, I have been using Gentoo on all my other computers for years and honestly don't want to switch away from it any more. Also, because of Gentoo's source-based nature, I was quite optimistic about getting it to run on an MNT Reform. Together with the MNT Reform's modularity, I am expecting this Gentoo installation to last for years to come, maybe even decades, without the need to reinstall the system.

SoM choice

When I ordered my laptop, there were three SoMs available. The i.MX8MQ, the LS1028A, and the CM4 adapter module bundled with a Banana Pi CM4. Each of those modules has its own advantages and disadvantages, with details listed on MNT's Hardware Modularity page. I was unsure which one to choose, because I wanted both, relatively modern OpenGL features and a lot of memory. The LS1028A module has lots of memory and is fully open hardware, but the etnaviv graphics driver lacks features, compared to panfrost, as can be seen on Mesamatrix. On the other hand, the Banana Pi CM4 has only 4 GiB of memory, what is a bit little for Gentoo Linux, given that it is a source based distribution and that some programming languages like Rust or C++ tend to use a lot of memory during compilation. After some back-and-forth I went with the Banana Pi CM4. My netbook, which is also running Gentoo, also only has 4 GiB of memory, and while compiling some packages indeed becomes bottlenecked by memory, that is only an occasional annoyance.

Meanwhile MNT released a new SoM adapter, in this case for the Rockchip RK3588 processor. This would offer 16 or 32 GiB of memory, and both, fast graphics and main processor. However, I am not sure if I should buy this right away, given its rather high price tag, and the fact that the graphics drivers for it have only been merged to mainline Linux very recently. Another reason why I am hesitant to switch is that configuring the kernel for a new SoM takes quite some time - more on that later.

Assembly

MNT Research offers to buy the Reform laptop as a DIY kits, and what kind of self-proclaimed nerd would I be if I hadn't assembled my own laptop?

The laptop arrived in a neat box, with the various components packed individually.
Picture of the box the laptop came in
Picture of the parts of the MNT Reform laptop

The package also included a rather brief assembly manual. I would have preferred a bit more verbose instructions, but the included ones were fine. The biggest issue with the manual is that it is written for the default SoM, the i.MX8MQ, and that one needs to also read a second manual, that's specific to the CM4 Adapter. Overall, the assembly is straightforward though. The biggest difference to the default SoM is that the CM4 adapter is not connected to the M.2 slot on the mainboard. Instead, the module's package includes an mPCIe to M.2 adapter, so one can use the board's mPCIe slot instead. This adapter is a bit fragile, to say the least, but it seems to get the job done.
Picture of the MNT Reform after mounting the mainboard, but before installing the keyboard or trackball
Picture of the MNT Reform after assembly, but without batteries or WLAN antenna

I did make two mistakes though. The first one was that I missed to install the WLAN antenna, and had to unscrew one screw of the mainboard again. The second, and much more annoying mistake was that I overtightened the distance holder for said antenna, and broke it. This mistake happened, because the distance holder's thread didn't perfectly match the thread of the Reform's case, and I used the wrong tool, pliers. I have not been able to remove the broken screw from the mainboard yet, however it also sits tight enough with just 3 screws holding it. The antenna on the other hand was much harder to mount now, as I couldn't screw its holder anywhere. Initially I tried to just glue the antenna onto the SD Card slot, but the signal was pretty bad, due to the slot's metal. As a temporary fix, I now mounted the antenna holder using Patafix.
Picture of the MNT Reform fully assembled, with the WLAN antenna a glued to the SD Card Slot

Baby Steps: The official MNT Reform system image

The MNT Reform came with an SD card that had the official system image preinstalled, so the first boot was as simple as inserting that card into the Reform's SD card slot, and switching on the system. The latter is a bit different to what one might be used to from other laptops, because the Reform does not have a power switch. Instead, the Reform's system processor, a very low power ARM chip, is always on, and accepting SPI commands from the Reform keyboard. The keyboard, in turn, has a built-in OLED display, that offers a menu to interact with the system controller. This menu can be brought up by pressing the circle key. To turn the laptop on proper, one has to pick the second menu entry, or press the hotkey 1. Apart from controlling the laptop's power, the keyboard menu also offers a battery charge display, which is pretty handy when working on the terminal, and control over the keyboard key backligh brightness. Also, because both, keyboard and system controller software are open source, one can customize the menu freely, if one is so inclined.

After switching the laptop on I was worried for a short moment, because the screen remains completely blank until Linux has initialized the KMS console. This takes extra long, because the u-boot configuration of the official system image gives the user 1 second of time to interrupt the boot process via serial console. However, as soon as the Linux kernel was ready to display output, the well known wall of text generated by both, the kernel and systemd, started scrolling through. In this case nearly slow enough to actually read it, due to the SD card's comparably slow read speed.

A couple of seconds later, the system greeted me with a login prompt, and the information needed to log in as root. This was when I actually realized that the official system image on my SD card was built using Debian Unstable. While I was planning to switch to Gentoo sooner or later, this was a very good argument to not even try to install this official image on the laptop's SSD, and to directly attempt a Gentoo installation. Later I checked on the MNT website, and there is tooling available to build a system image that is built from Debian Stable, but at that point I had already made up my mind to try to install Gentoo as soon as possible. However, I also wanted to keep the SD card with Debian Unstable in a usable state, so my first action after changing the root password and adding a non-root user was to update the installed packages... This failed spectacularly though, as I hadn't checked for free space, and only realized after the system had become unusable that, while the SD card had 32 GiB of total capacity, only 4 GiB of it had been used for the Debian root partition, and those were already basically full when I got the card... Due to this I got to re-flash the SD card on the first day already. I made sure to resize the root partition right after I flashed the system image, to make sure to not run into the same issue again.

This time installing updates for Debian worked as expected, but, also expected, there were severe warnings about known bugs in several packages... That was not a problem for me, as I was at this point basically treating Debian as a bootstrapping tool for the upcoming Gentoo installation, but if I were to keep using Debian, I would have switched from Unstable to Stable the latest at this point.

I was expecting to feel right at home with the official Reform image, as the recommended graphical environment is based on sway, which is preconfigured for the Reform. However, this configuration was also a reason why I didn't want to use the official Debian image for too long, because it differs significantly from what I had been used to from my desktop PC. However, for someone who hasn't used sway before, the Reform's config is probably pretty good. Also, I could of course just have copied over my desktop's sway config file, but again, at this point I was already going to switch away from Debian in favour of Gentoo.

An issue that I had with the official Debian image, and also later, once I had my Gentoo system running, was that the wireless connection would fail constantly if power saving was enabled. Luckily there is an easy workaround, but it was still quite annoying that the official system image has such issues. On the bright side, because the official image has the problem, I was able to find help for it easily, and already knew about the workaround when I got to set up wireless on my Gentoo install later.

Before trying to install an OS by myself, I thought it would be a good idea to learn more about the boot process, as that differs of course between the different SoMs, and the manual of the Reform only goes into details about the i.MX8MQ. The u-boot log output, as well as early printk output from the kernel, is routed to the system's serial console. Checking the u-boot settings, and the boot script of the official image, I quickly confirmed that this is also the case for the Banana Pi CM4. However, when I tried to connect a serial cable (3.3 V - luckily someone had already asked this in the forums, otherwise I might have tried a 5 V cable) to the S1 serial port on the mainboard, I did not get any output. I even dug out my oscilloscope to see if there is any signal, or if something was wrong with my serial cable...
Picture of the MNT Reform lying top-down, and an oscilloscope next to it.
The voltage on the pins was, however, completely wrong, and there was no signal whatsoever. To see what was going on, I installed KiCAD on my desktop, and opened up the MNT Reform Mainboard 2.5 schematics, together with the schematics for the CM4 adapter. This quickly resolved the question, because with the Banana Pi CM4, the S1 serial port is connected to the pins GPIOX_7 and GPIOX_6. The actual serial console is connected to the S2 serial port... Finding out about this was quite fun, to be honest, and for me that were the first baby steps in KiCAD. After connecting my serial cable to the correct port, the debug output from u-boot and early kernel logging worked like a charm. I also tried interrupting u-boot and giving it commands from my desktop, and after this worked, I felt confident enough to try messing with the Reform's boot process myself.

Initial Gentoo setup

At this point I started installing Gentoo Linux. Since Gentoo did not offer a dedicated ARM64 handbook when I was installing the system, I instead went with the AMD64 handbook, adapting the instructions whenever I felt that they don't apply. Luckily, apart from the early boot process, the differences were minor, and I was able to mostly follow the handbook by the word.

I partitioned the SSD that I had ordered along with the Reform, such that it contains 2 partitions: One for swap space (30 GiB - since the CM4 only has 4 GiB RAM, plenty of swap space is needed) and one that is formatted as btrfs (the rest of the space). The btrfs partition has been set up to contain several subvolumes, the most important being the home folder. I did not create a separate boot partition on the SSD. Instead, the boot partition is placed in the eMMC storage of the Compute Module, to be precise in the mmcblk1p1 partition. That way, u-boot has easy access to it during boot. Unlike the root partition, the boot partition is formatted as ext2. I followed the recommendation to use UUIDs that follow the DPS, but did not rely on this anywhere later. I did not yet install u-boot itself at this point, as the official recommendation by MNT Research is to boot the CM4 off an SD card. The reason for this is that, if anything goes wrong during u-boot installation, the system would not boot any more, and the only way to repair it would be to use a CM4 I/O board, which I did not own yet at that point.

Starting from the Debian Unstable system booted from SD Card, I mounted the newly created partitions and set up bind mounts according to the handbook, in order to be able to chroot into the new root filesystem. I also downloaded a Gentoo stage 3 tarball, namely the current-stage3-arm64-openrc one. After unpacking it, chrooting into the new file system already worked.

The next step was setting up the make.conf file. Back then I wasn't aware that gcc has optimization switches suitable for the big/little architecture of the CM4's CPU, so I just went with -march=native. However, relatively shortly after I learned a bit more about optimization flags on ARM64, and set CFLAGS="-O2 -pipe -mcpu=cortex-a73.cortex-a53+crc+crypto". For the default USE-flags in make.conf I did a wild combination of gut feeling and values that have been working well on my desktop. I did invest time to make sure no redundant flags were set though. Back then the 17.0 profiles for Gentoo were still the recommended ones though, so I should probably revisit the USE flags once more, since meanwhile the 23.0 profiles have been stabilized. Another setting that I made in make.conf was VIDEO_CARDS="panfrost", as that's the driver needed for the CM4's graphics unit. Outside of make.conf, I also set the CPU_FLAGS_ARM variable, which, for the CM4, is */* CPU_FLAGS_ARM: edsp neon thumb vfp vfpv3 vfpv4 vfp-d32 aes sha1 sha2 crc32 v4 v5 v6 v7 v8 thumb2.

Choosing a profile was the next challenge. I knew that I would not want to run Gnome or KDE, or any other fancy desktop environment, but the Gentoo handbook still recommended to use a desktop profile for most desktop/laptop use cases, so I chose default/linux/arm64/17.0/desktop. Meanwhile I have upgraded to default/linux/arm64/23.0/split-usr/desktop, by the way. After that it was time for the first world update, which went through marvelously.

Setting timezone, language and similar stuff followed the handbook step by step, there is no difference between ARM64 and AMD64 here.

Charging issues

While compiling the world update, I noticed that the Reform refuses to charge with the default power supply, if the system is under heavy load. While an easy workaround is to disable the display backlight for a moment while plugging the power supply, I was hoping for a more permanent solution. Sadly, at this point in time there is no real software fix though. The issue is likely coming from the high current that is drawn from the power supply right after charging starts. To counter that, a branch of the system controller firmware has been created that contains a slight delay between plugging the power cord, and the onset of charging. In order to install it, I had to set up a 32 bit ARM cross toolchain, but thanks to Gentoo's crossdev tool, that was a matter of minutes on my desktop. It still took me a while to get this compiled, because the toolchain installed by Gentoo defines _FORTIFY_SOURCE, and I didn't immediately see that this is not compatible with the system controller firmware. Flashing the firmware, on the other hand, was a breeze, as the system controller shows up as a regular USB drive when connected to the PC. That change did definitely improve the charging situation for me, but it did not resolve it completely, so sometimes I still need to use the trick of switching the backlight off... I also tried to use another power supply that I still had lying around, which has a nominal output power of 78 W at a voltage of 13 V, and while this power supply seems to be able to run through the initial power draw of the laptop, there is also a worrying amount of heat, both from the laptop's charging circuitry and from the power supply itself. So, for the moment I will likely stick to the stock charger, despite the problems.

Kernel

The next, very big challenge was configuring the kernel. While there is a user-supplied pre-packaged pre-built kernel available for Gentoo, I wanted to build it myself, based on the gentoo-sources package. The first step was preparing the patch-set from the MNT reform sources, and adding them in /etc/portage/patches/sys-kernel/gentoo-sources. Luckily the patch set applied to the kernel version offered in the Gentoo repositories flawlessly. However, the patches also modified the DTS file for the meson-g12b-bananapi-cm4-mnt-reform2, and I am pretty sure that modification is unintentional. So, I added another patch that overwrites that file again with the version from the same repo.

The kernel configuration was not that much fun though. Not only has the kernel meanwhile grown to a point where simply going over all options keeps one busy for several hours, but dealing with a hardware platform I had been utterly unfamiliar with before turned into a lot of trial and error. My strategy was to first go over all options once, and selecting those that I knew I needed or wanted, like drivers for USB devices, file systems, and so on. The second step was to read through the DTS files, and to select all modules that sounded similar to the names of the devices mentioned. The starting point for this was the file specific to the Reform laptop with a Banana Pi CM4. This became quite a chore, and I sometimes had to look into the kernel source code which module of several actually corresponded to a given device tree entry. A resource that came very, very handy here was the elixir graphical device tree browser. In case anyone wonders about the outcome, here is the kernel config I am currently using.

System packages

For the system packages needed for the first real Gentoo boot, I went a bit of a different route from my other systems. As mentioned when talking about the stage-3 tarball and the profile selection, this time I chose OpenRC as init system. This was mostly a gut-feeling decision, as I personally like the systemd init-daemon. However, I was planning for a minimal system on the Reform, and while the systemd init daemon itself is rather lightweight, I did not want to install too much of the other stuff from that rather large and inter-dependent project. Also, I have been using OpenRC on my netbook for several years, and have always been quite happy with it. This also meant, that instead of journald, I had to use another sys logger, and I went with sysklogd, as it has a reasonable default configuration. As cron daemoen I chose cronie, and for network configuration I went with networkmanager. Since I had had troubles with any other network time daemon solutions on my netbook, I directly went with NTPd here. It migth strike you that I used networkmanager on a system that is supposed to be lightweight, but after having used a manually maintained wpa_supplicant configuration on my netbook for several years, I really wanted to have a more convenient way to connect to wireless networks...
Sysklogd by the way is sometimes causing issues on shutdown. This happens rarely enough though, so I don't feel pressured to switch and instead I am hoping that a future update will resolve this problem.

Bootloader

After I was reasonably sure that I had selected all required kernel modules, and that I had installed everything the Gentoo handbook mentions as required for the first proper boot, I went ahead with the bootloader installation. This step was the first one that was really different from the description in the AMD64 Gentoo handbook.

I initially followed the recommendation to not install u-boot in the eMMC storage. The Banana Pi CM4 Boot Sequence does not require the u-boot binary and the boot script to be located on the same device. It works perfectly fine to have the boot script in eMMC, and the u-boot binary on an SD Card. To compile u-boot, I set up an ARM64 crossdev toolchain on my desktop, and followed the MNT Reform A311D boot readme to install it on the SD card. I also consulted the information on the u-boot website about the Banana Pi CM4, but everything important was already mentioned in the readme.

After cross-compiling and installing the u-boot binary to an SD card, I had to supply a boot script. The tooling to compile a .scr file from a text file is available in portage, and the Gentoo installation was at this point far enough, so I could simply install the dev-embedded/u-boot-tools package. Similarly, the device tree compiler dtc is available in the sys-apps/dtc package. For the boot script itself I decided to not use any pre-made templates, but rather write a very simple script by hand, that just hardcodes all paths. The kernel command line was taken from the official system image, and slightly modified to match my setup. For reference, here is my current boot script. After compiling the boot script and the meson-g12b-bananapi-cm4-mnt-reform2.dts file (as downloaded from the MNT Reform repos), I copied the compiled files to /boot/boot.scr and /boot/devicetree.dtb respectively. I had to manually copy the compiled kernel to /boot/vmlinuz once, but once this file existed, running make install in the kernel source tree updates it automatically, thanks to the installkernel tool (if set to not use systemd). After those three files were in place, I rebooted the system, with the u-boot SD Card inserted.

Surprisingly enough, the simple boot script and the initial kernel configuration worked well enough to boot the system on first try. Audio and wireless networking didn't work yet, but given that the whole kernel config was a shot in the dark, I still was very happy with this result.

Finding the missing drivers

The first problem I decided to solve was wireless. I spent quite some time comparing my kernel configuration with the one of the official image, and digging through sysfs to find out which devices were missing. This all did not really help me, but after going through the boot log output I figured that some device was set to deferred probe. Which one, though, was not obvious from the logs alone. Luckily, there is debug functionality for deferred probe issues available in the Linux kernel, and this helped me find out that the clock for the wireless chip was not available, which, according to the device tree, was a PWM "clock". I was pretty certain that I had enabled CONFIG_PWM_CLK in the kernel though, so I was utterly confused why it did not work... Until I found out that the correct kernel module is called CONFIG_COMMON_CLK_PWM, which I had not enabled.

With the CONFIG_COMMON_CLK_PWM module enabled, the wireless chip was now detected, but it was very unstable, crashing within minutes. I was again lucky, as the crash callstack did lead me directly to a bug report by none other than Lukas from MNT Research. I quickly added the fix for the WLAN crash to my list of kernel patches, rebuilt the kernel, and had wirless networking running stable. The reason that patch was needed for me on Gentoo, while it wasn't needed for the official Debian image was, that Gentoo back then still shipped Linux 6.6.13 as stable version, while the patch was included in 6.6.14 and newer. Meanwhile it's no longer needed on Gentoo, as currently 6.6.30 is stable.

At this point I went on a tangent, as I misread the output of wireless speed tests, and thought the official Debian image would offer much higher speeds than my Gentoo installation. I am a bit ashamed that nothing came of it, as it turned out in the end that I had simply mixed up bits and bytes...

At this point, all hardware was running, but I still did not have any audio yet. I played around in alsamixer a bit, and by trial and error I got audio output working by setting "FRDDR_A Sink 1 Sel" to "Out 1". With that out of the way, I proceeded by setting up a very minimal asoundrc file that enables dmix.

I still do not have audio input working, by the way. I am pretty sure that in order to proceed, I cannot just rely on trial and error, as the sound chip has way too many options. Instead, I am afraid, I will have to read the data sheet at some point... Anyhow, I don't need audio input urgently, as the headset connector only supports electrite microphones, and the actual line-in pins on the Reform mainboard are not connected to anything in my laptop - yet.

Reform-specific drivers

The MNT Reform needs an additional kernel module for battery level readout and poweroff functionality. This module is present twice in the git repositories for the Reform. At first I had installed the outdated version and was confused why the system wouldn't poweroff on shutdown. After digging a bit through the Kernel source, I was pretty sure that this module did not contain any poweroff code, so I asked the MNT community for help. There I was quickly referred to the current version of the LPC module. To little surprise, the difference between the two versions was the support for automatic power off...

In order to be able to easily update the module whenever I do a kernel update, I made my first baby steps when it comes to writing ebuild files. I had modified ebuilds before, but this was the first time I actually wrote one from scratch. I was pretty proud when I had the ebuild for the old version of the LPC module ready, just to delete most of it after I had learned about the newer version, which not only had power off support, but also integrated way better with Gentoo's ebuilds. I posted the ebuild in the MNT Community thread about the Gentoo kernel, and Niklaus Hofer was so nice and also added it to his Gentoo overlay for the Reform, which is also available via eselect repository under the name mnt-reform.

With the kernel module packaged as ebuild, it is now as simple as running emerge @module-rebuild after a kernel update to get poweroff functionality and battery readout. However, I still made the mistake once to forget about this, what led to the laptop remaining powered on after I thought I had shut it down. I did put it into the backpack I usually store it in, and only realized on the next day that something was amiss. I am really glad that I have the new, protected battery packs, otherwise the batteries might have been damaged, because they were as empty as can be when I started charging the laptop again. In addition, there had been enough heat buildup, that even though the Reform being very energy efficient, had caused the trackball mount to deform slightly, blocking the trackball's movement. I spent an evening repairing this damage using sandpaper... Long story short, I will probably at some point in the future automate the call to the module rebuild in some way, to prevent such problems.

Finalizing the setup

With the hardware being ready for use, I now continued setting up things to make the laptop usable. The first thing I did was to install sway, and to copy over the configuration from my desktop. I had to adjust a couple of things though. The biggest change I had to make was to disable HDMI output, as quite often windows would randomly end up on the second, not connected, screen. Setting output HDMI-A-1 disable in the sway config file did the trick. I also modified the volume control hotkeys in such a way that they now increase/decrease the volume by decibels: bindsym XF86AudioRaiseVolume exec amixer -c 0 sset Playback 2dB+.

I also wanted to set up shortcuts for controlling the display brightness. The respective setting in sysfs is simply /sys/class/backlight/backlight/brightness, but writing to this file requires root access. I first tried to write a bash script and set it to suid, but learned the hard way that suid root bash scripts do not work for security reasons. Instead I then wrote a very short Rust program, that takes one parameter (up or down) and increments or decrements the integer value in the brightness file. This program is now installed suid root, and my sway configuration has a hotkey set for it: bindsym XF86MonBrightnessUp exec brightness up (and the same for brightness down). Having this program around is also handy on the terminal, as one can increase brightness simply via brightness up.

For the status bar in sway I am using the same tool that I am using on my desktop, namely my work-in-progress swaystatus tool. While I had been waiting for the shipment of the Reform laptop I had already started working on an ALSA support plugin for it (at the time of writing on a separate branch), as I did not plan to install any sound server on the Reform. So, getting a working status bar was nearly as easy as checking out that branch of swaystatus, compiling it, and setting up a simple config file that uses the clock and alsa plugins. Nearly, because two things on the Reform differed from my desktop. First, the desktop always triggered a volume-changed callback immediately after subscribing, what does not happen on the laptop, and second, the unitless volume values do not scale linearly with the decibel volume values. Fixing those two problems was not much work though, and now I have working volume and time display in my status bar. I do not (yet) have a battery display plugin for swaystatus, because I do not need one. The Reform keyboard has a built-in OLED display, that can be set to show battery level.

One last annoying thing remained. The Reform does not have an ACPI power button, so that one needs to use a command like shutdown to switch the system off. To make this less tedious, I edited inittab to change the meaning of CTRL+ALT+DEL. Instead of rebooting, this key combination is now switching off my Reform laptop, and available to non-root users too.

While I had inittab open, I noticed something else that I had to change: The port name for the serial console was not yet set to the correct one for the CM4, so I changed it to s0:12345:respawn:/sbin/agetty -L 115200 ttyAML0 vt100. I have not tried this terminal yet though, this might be wrong.

Installing the bootloader in eMMC memory

After a couple of weeks the need to use an SD Card for booting became annoying. For this reason I decided to take the risk and flash u-boot to the embedded storage of the Banana Pi CM4. However, as a kind of insurance should anything go wrong, I also ordered a CM4 I/O board. The instructions for flashing u-boot to eMMC are on the u-boot website, but I still managed to mess this step up. Luckily not too badly, as all I mixed up was the target partition. I accidentally flashed the bootloader over the file system of the /boot partition, rendering the Gentoo install unbootable. However, booting the official system from SD Card still worked, and a simple fsck invocation later everything was running again.

The second attempt worked flawlessly, by the way, and I no longer need to use an SD card for booting. Booting off SD Cards works too, because u-boot first checks for the presence of a boot script on the SD Card, before checking internal storage.

Current status and plans for the future

I am still looking around for software that fits my demand for a relatively lightweight system. While I do have sway installed, I enjoy working directly on the terminal, and actually prefer it on the Refom. This is in parts because the graphical environment is not perfectly stable. For instance, sometimes the display does not come back from the DPMS-off state, and using Firefox has a very slight chance to freeze the system... For this reason I have installed mutt as mail client, and links as a terminal-based browser. to show images, I have fbida installed, which can also render PDF files via ghostscript. I have configured language server protocol support in vim, so I can use it relatively conveniently for Rust coding.

I do, however, also have VSCodium installed, due to the excellent Lean4 plugin for it. It is, probably, the least lightweight tool I am currently using on the Reform, but up to now there is little to complain about.

Maintaining the Gentoo installation on the Reform is quite convenient, though I did take a few shortcuts, like relying on rust-bin instead of building the Rust toolchain from source. Compiling bigger packages like Firefox from source easily exceeds the 4 GiB of memory that the Banana Pi CM4 offers, so having a big swap partition is more or less a must. I also made sure to not install webkit or anything based on it, as I do not really want to find out how long the compilation of that package on the reform might take... Luckily Gentoo offers binary packages for common USE flag combinations nowadays, so quite often it is possible to skip local compilation. I am aware that especially on ARM using generically optimized packages might waste a bit of performance, but the time saved while installing updates easily makes up for that drawback of the binary packages in my opinion.

For gaming, I did install a couple of open source games/engines, like OpenTTD and VCMI, but I also installed Box64, for which I made a heavily WIP ebuild too (which is so bad, I don't want to share it). I got quite a few games from my itch and GoG game collection to run, and I am expecting even more to work with upcoming Box64 versions. I did not bother with Box32 yet (it basically needs a 32-bit chroot), that's why my Steam game library remains inaccessible on the Reform for now. In addition, I found out that Ren'Py has ARM binaries, what makes it relatively easy to launch most Ren'Py games on the Reform natively.

Regarding the previously mentioned audio input issue, I am currently thinking about buying an external sound adapter, as the stereo line-in pins on the Reform mainboard are a bit hard to reach, as the WIFI antenna is blocking the access to them. It would of course be possible to connect them nevertheless, but that would still require either modding the Reform case to route the input to the outside, or keeping the laptop case open while using the Line In port. Just plugging a second audio-device via USB sounds way more convenient to be honest.

I really like the Reform laptop, and I can recommend it for anyone who is looking for an unusual computing device. The parts that matter, namely the screen, keyboard and trackball, are really good, and with the Banana Pi CM4 the system is also fast enough for everyting I have thrown at it as of yet. I think it's worth highlighting the keyboard once more. It is by very far the best I have seen in any laptop I have used up to now, and I like it so much, that I did order the standalone version of it for my work PC.

To finish this up, one last thing that might be relevant: This blog post was written on my Reform, using vim and the cobalt static-site-generator.


Previous: Writer and State Monad in Rust, based on higher Home