⑨ lab ≡ who cares?!

Plan9/ThinkPad T420s

⑨ lab ≡ 9front running on T420s…

9front running on T420s

Finally, after a long time running 9front on virtual machines, it is time to get productive on real machines. ThinkPads are the best supported laptops in 9front because ThinkPads are what the developers use.

After some search the Lenovo ThinkPad T420s looked like a good candidate for my use case. There are still a few places that sell T420s, mine was purchased at refurbed.at, delivered swiftly, is as good as new, and has the following specifications:


At the time 9front release Mit Fruchtgeschmack was available. Simply follow the installation guide to get 9front up and running.

With a 1TB SSD drive the aim was to setup a cwfs64x file system with encrypted fsworm, fscache and other partitions. The documentation describing how to setup encrypted disk partitions is simple and worked out of the box.

The key thing to keep in mind after installation, when booting at the bootargs prompt, type !rc to drop to a shell, and activate the encrypted partitions with the following command:

 % disk/cryptsetup -i /dev/sdE0/fsworm /dev/sdE0/fscache /dev/sdE0/other
 Password: *********
 % exit

After entering the password chosen during disk encryption setup type exit to resume booting.

At the bootargs prompt, enter local!/dev/fs/fscache to continue booting from the encrypted partition.


The following section describes additional setup and configuration steps to simplify booting from an encrypted partition, enable wifi, and audio, starting with my plan9.ini.


 % 9fs 9fat
 % cat /n/9fat/plan9.ini
ether1=type=iwl essid=0xBADC0FFE

Boot from Encrypted Partitions

The setup of encrypted partitions is well documented and straight forward. Booting from them is a bit tedious though. Having to enter !rc at the bootargs prompt and typing:

 % disk/cryptsetup -i /dev/sdE0/^(fsworm fscache other)
 Password: *********
 % exit

…is not exactly swift. It would be nice if the boot procedure just prompted for the password required to decrypt the encrypted partition.

There are probably many ways to achieve this. I have settled on adding a variable cryptdev to plan9.ini and modify /sys/src/9/boot/bootrc to automatically activate a previously formatted AES-encrypted partition if that variable is set.

First, lets extend plan9.ini with a variable cryptdev, specifying the device (/dev/sdE0) containing encrypted cwfs partitions:

 % 9fs 9fat
 % echo 'cryptdev=/dev/sdE0' >> /n/9fat/plan9.ini

Next, extend /sys/src/9/boot/bootrc to activate AES-encrypted cwfs partitions on the device defined in cryptdev (diff highlighting the changes):

 % bind -ac /dist/plan9front /
 % cd /usr/src
 % hg diff .
diff -r d588a54f841a sys/src/9/boot/bootrc
--- a/sys/src/9/boot/bootrc	Mon May 17 13:46:44 2021 -0700
+++ b/sys/src/9/boot/bootrc	Sun May 23 00:53:48 2021 +0200
@@ -66,6 +66,14 @@
 fn main{
+	# disk encryption
+	if(! ~ $#cryptdev 0){
+		if(~ `{grep -c crypt /dev/fs/ctl} 0){
+		  disk/cryptsetup -i $cryptdev/^(fscache fsworm other)
+		}
+	}
 	while(~ $#mp 0){
 		if(~ $#nobootprompt 0){

After modifying /sys/src/9/boot/bootrc as described above, rebuild and install the kernel to activate the changes during boot:

 % cd /sys/src/9/pc64
 % mk install
 % 9fs 9fat
 % cp /amd64/9pc64 /n/9fat/
 % fshalt -r

With this setup a password prompt will automatically appear during boot if the variable cryptdev is defined, and the encrypted partition has not yet been activated.


Wifi Firmware

A binary firmware blob (i.e. iwn-6005) is required to enable Wifi.

Here is how to download and copy the firmware blob to /lib/firmware:

% ramfs ; cd /tmp
% hget -o iwn-firmware-5.11p1.tgz \
% tar xzf iwn-firmware-5.11p1.tgz
% cp firmware/iwn-6005 /lib/firmware

To make the firmware blob available at boot rebuild and install the kernel:

 % cd /sys/src/9/pc64
 % mk install
 % 9fs 9fat
 % cp /amd64/9pc64 /n/9fat/
 % fshalt -r

This ‘packs’ the firmware blob into the boot kernel image, enabling boot via wifi.

Wifi Configuration

There are many ways how Wifi interfaces can be configured. My use case for WiFi ethernet is as follows:

The following script initialises WiFi ethernet accordingly:

% cat $home/bin/rc/initwifi
#!/bin/rc -e
rfork e

fn Help{ echo `{basename $0}^' [essid]' }
fn Dump{ grep node '#'l1/ether1/ifstats }
fn Ask{
	echo -n $1
	essid=`{dd -bs 64 -count 1 >[2]/dev/null}
fn Wifi{
  ip/ipconfig ether /net/ether0 unbind
  bind -b '#'l1 /net
  aux/wpa -p2 -s $essid /net/ether1
  ip/ipconfig -6
  ip/ipconfig ra6 recvra 1 &
  ip/ipconfig ether /net/ether1 &
  secstore=`{grep sys /net/ndb | awk -F'=' '{print $2}'}
  cat /net/ndb

	case 0
		if(~ $#essid 0){
			echo Available wifi essids…
			Ask 'essid='
		if(! ~ $#essid 0){
	case 1
	case *

A good place to call this script is for the terminal case in lib/profile:

% cat $home/lib/profile
case terminal
	rio -i riostart

A prompt to select an essid from a list just before starting rio will be displayed. Hit enter to skip the selection or type in the desired essid. To avoid the prompt all together define essid in plan9.ini.

The following transcript of the bootprocess highlights at what stage the essid prompt appears:

% cat /dev/kmesg
/dev/sdE0: HP SSD S700 1TB
/dev/sdE0/9fat	 dos
/dev/sdM0: MMC Host Controller
bootargs is (tcp, tls, il, local!device)[local!/dev/fs/fscache] 
current fs is "main"
11 uids read, 6 groups used
63-bit cwfs as of Tue May 18 01:16:27 2021
	last boot Fri Jun  4 02:14:31 2021

init: starting /bin/rc
warning: scanning for unoffered vesa modes
secstore password: 
Available wifi essids…
node: 6c710d521720 1431 70          01 0xBADC0FFE
node: 6c710d521722 1431 70          01 0xBADGUEST
node: 6c710d521980 1431 110         01 0xBADC0FFE
node: 6c710d521982 1431 110         01 0xBADGUEST

ip= ipmask= ipgw=

Note that the script assumes a protected wifi network is being joined, requiring authentication and key exchange handled by aux/wpa (see man 8 wpa).


The following settings are used for the builtin screen:

term% 9fs 9fat
term% cat /n/9fat/plan9.ini

Using an external monitor such as the LG ULTRAWIDE at 3440x1440 via the DisplayPort is not working using vesa, use igfx instead.

⑨ lab ≡ External monitor connected to T420s

External monitor connected to T420s

To find out what resolutions are supported issue the following command:

term% @{rfork n; aux/realemu; aux/vga -m igfx -p}
edid name           LG ULTRAWIDE
edid product        23266
edid serial         112436
edid version        1.4
edid mfrdate        2015.1
edid size (cm)      80x34
edid gamma          2.20
edid vert (Hz)      56-61
edid horz (Hz)      30000-90000
edid pclkmax        320000000
edid flags           digital standby
edid 3440x1440@50Hz 
		shb=3488 ehb=3520 ht=3600
		vrs=1443 vre=1453 vt=1474
		hsync=+ vsync=- 
edid 3440x1440@60Hz 
		shb=3488 ehb=3520 ht=3600
		vrs=1443 vre=1453 vt=1481
		hsync=+ vsync=- 

The following command tries to use that resolution using igfx:

term% @{rfork n; aux/realemu; aux/vga -m igfx -l '3440x1440'}

NOTE: Before you issue the above command ensure you are in a terminal and you can type fshalt if anything goes wrong. Not all of my external screens work with igfx and once igfx falls over and the screen is black there is no recovery other than fshalt

#Plan9 #9front #ThinkPad