9front on the Raspberry Pi

About a year ago, I bought myself a Raspberry Pi for running RISC OS on. Since RISC OS is a very light-weight operating system, and can only (at the moment) take advantage of a single 32-bit ARM processor, I decided to go for a first-generation Raspberry Pi model B (more specifically, the more common "revision 2" with 512 MiB of RAM), henceforth known as "the raspi".

Somewhat recently, the Plan 9 Desktop Guide was posted on lobste.rs and gave me the itch to try 9front out again. Looking at the release page, I noticed

The pi.img file can be used for Raspberry Pi 1, 2, and 3.

Thinking it would be fun to see how well it ran on there, I decided to test it out on the raspi. It took me a couple days, and I had to figure out some platform details that weren't properly documented, but I got 9front set up like how I wanted it to. 9front on the raspi is actually quite nice of an experience.

A couple days ago, there was a new 9front release. I took it as an opportunity to try out gefs (spoiler: don't try this on a raspi) and actually document all the details of the 9front setup on the raspi.

Hardware

For the installation, I am booting the pi.img off of a 2 gig SD card in the raspi's internal SD card reader, and with a 4 gig SD card (the installation target) in a USB card reader.

Initial setup

9front defaults to the US QWERTY keyboard layout. As I am not usamerican, I fix this with

cat /sys/lib/kbmap/fi > /dev/kbmap

The raspi does not have a real-time clock, meaning that 9front boots up thinking it's 1970. I set up networking and get the time from NTP with

ip/ipconfig
aux/timesync -n

Finally, to stop the kernel messages from spewing all over the screen and messing up rio's display, I open a new window, set it to scroll automatically (middle click → scroll), and run

cat /dev/kprint

Installer

I am basing this setup on the simple setup in the FQA, noting only the changes relevant to the raspi.

configfs

With 4 gigs on the installation target, a traditional cwfs setup which statically splits the storage between an append-only "dump" partition containing daily filesystem snapshows and a modifiable "cache" partition, doesn't make sense. While the FQA does mention a no-dump configuration, the upstream rpi.img still uses hjfs. So, let's go with that.

partdisk

My installation target already had an MBR on there, so I first deleted the existing partitions using the d command. Starting from empty, I then created a partitioning setup similar to what the upstream rpi.img has:

a p1 0 100M # Create the raspi boot partition
t p1 fat32  # Set partition type to fat32 (they default to being plan9)
A p1        # Set the boot partition to be active
a p2 . $    # Use the rest of the disk space for the 9front install

prepdisk

The default subdivision suggested in the prepdisk step includes a 9fat partition, which is used for the boot process on the PC. On the raspi, we do not need it, so again starting from empty:

a nvram 2 3 # Single-sector nvram subpartition
a fs . $    # Use rest of the partition for the file system

The reason the nvram partition starts at sector 2, nor sector 0, is that sectors 0 and 1 are reserved.

Set up encryption

Normally, you'd now proceed to mountfs. I like to use an encrypted rootfs, however, which requires manual setup. So, I drop to an rc prompt with !rc and then run

disk/cryptsetup -f /dev/sdU14649.3/fs
disk/cryptsetup -i /dev/sdU14649.3/fs

where /dev/sdU14649.3 is the installation target.

mountfs

Instead of choosing /dev/sdU14649.3/fs here, I instead select /dev/fs/fs. That is a virtual block device created by disk/cryptsetup in the previous step.

confignet, mountdist, copydist, ndbsetup, tzsetup

Nothing special for these steps.

Exiting the installer

At this point the installer wizard and the FQA suggest you to do a bootsetup step. It is not relevant to the raspi, only PC, so I just close the rio window (right click → Delete).

FAT partition

While we created the "dos" (FAT) partition in the partdisk step, it has no filesystem. I create one with:

disk/format -d /dev/sdU14649.3/dos

I then mount both the pre-existing boot partition and our new one:

9fs pidos
9fs dos /dev/sdU14649.3/dos

and copy the contents over:

cp /n/pidos/* /n/dos/

(The names "pidos" and "dos" are arbitrary, other than that they are names the 9fs script recognizes as being FAT file system. You could also use e.g. "esp".)

Changing hostowner's username

First I mount the new file system:

mount -c /srv/hjfs.newfs /n/newfs

Then I can rename the home directory:

mv /n/newfs/usr/glenda /n/newfs/usr/nortti

and edit /n/newfs/adm/users, replacing "glenda" with "nortti".

Then finally, to make the file system re-read the users file:

echo users >> /srv/hjfs.newfs.cmd

Configuring the "plan9.ini"

You'll find a lot of mentions of changing settings in plan9.ini, which lives on the 9fat partition. The raspi does not have one – instead you set the settings in cmdline.txt on the raspi boot partition, all on the same line. I changed it to set my keyboard map and user, as well to change the default boot args to /dev/fs/fs, for more convenient bootup experience.

console=0 kbmap=fi bootargs=local!/dev/fs/fs user=nortti

Automatically synchronize with NTP on boot

By default the termrc calls aux/timesync with the arguments -rLa1000000. This makes it attempt to get the time from the local RTC, which we do not have. I change it to use NTP instead by putting the following in /n/newfs/rc/bin/termrc.local:

TIMESYNCARGS=(-n)

Do note that termrc.local must be executable.

Rebooting into the new system

At this point the configuration of the system is complete and you can run fshalt. Switching the installation target to be in the internal SD card slot, I can then reboot into my new 9front install. When the OS prompts for the file system location, I first drop to shell with !rc, and decrypt the disk with

disk/cryptsetup -i /dev/sdM0/fs

Returning back to the file system prompt, which should be autofilled with /dev/fs/fs, I can just hit enter and the system boots right up.