Installing PureOS in the Purism Librem 5 and Mobian in the PinePhone

The software in my Librem 5 USA and PinePhone were out-of-date, and I decided to simply do a new install of PureOS and Mobian, respectively, in the two phones. In both cases, I found the instructions to do the installation confusing, so I decided to document how I did it, in case other people have the same problem. I also find it interesting to compare the difficulty of installing the two phones.

Installing PureOS on the Librem 5

On my PC, I use PluriOS, which is a Linux distro based on Ubuntu 20.04 LTS created by my friend Jared López of OpenIT. I have been helping Jared add the Aymara language to PluriOS. I tried following the instructions from Purism for installing PureOS in the Librem 5, but I had to alter them for PluriOS.

First the uuu (Universal Update Utility) needs to be installed to update devices based on the NXP i.MX 8M processor. uuu is available in the standard repositories for Debian 11 (bullseye) and later and Ubuntu 22.04 LTS (jammy) and later, so it can be installed in the standard way if using one of these distros:

sudo apt update
sudo apt install uuu

However, earlier versions of these distros need to install uuu using Snap:

sudo apt update
sudo apt install snapd
sudo snap install universal-update-utility
sudo snap connect universal-update-utility:removable-media

Then, download the librem5-flash-image script which is used to download and install the OS in the Librem 5:

sudo apt install git
cd ~
git clone https://source.puri.sm/Librem5/librem5-flash-image.git

Also install the Python libraries used in the script:

sudo apt install python3-jenkins python3-tqdm

Then, change to the librem5-flash-image directory and execute the script’s help to see the options:

cd librem5-flash-image
./scripts/librem5-flash-image -h

There are many options available:

usage: librem5-flash-image [-h] [--dir DIR] [--dist DIST] [--skip-cleanup] [--skip-flash] [--download-attempts DOWNLOAD_ATTEMPTS] [--skip-download] [--variant {plain,luks}]
[--board {devkit,librem5r2,librem5r3,librem5r4}] [--stable] [--debug] [--image-job IMAGE_JOB] [--uboot-job UBOOT_JOB] [--udev]

Flash a Librem 5 or Librem 5 Devkit.

optional arguments:
  -h, --help            show this help message and exit
  --dir DIR             Download files to dir (instead of a temporary 
                        directory)
  --dist DIST           Download an image for this distribution, default
                        is 'byzantium'
  --skip-cleanup        Skip temporary directory cleanup
  --skip-flash          Do all the preparations but don't flash
  --download-attempts DOWNLOAD_ATTEMPTS
                        Maximum number of attempts to resume image 
                        download. 0: unlimited, default is 10
  --skip-download       Use a local image and uboot instead of 
                        downloading
  --variant {plain,luks}
                        Image variant to download ( plain, luks ),
                        default is 'luks'
  --board {devkit,librem5r2,librem5r3,librem5r4}
                        Type of the board to download ( devkit, 
                        librem5r2, librem5r3, librem5r4 ) default is 
                        'auto'
  --stable              Whether to grab the latest stable image, 
                        otherwise the dev snapshot is fetched

Testing and debugging options:
  --debug               Enable debug output
  --image-job IMAGE_JOB
                        Jenkins job to download the image from
  --uboot-job UBOOT_JOB
                        Jenkins job to download the uboot from

Initial setup options:
  --udev                Setup udev rules to flash without root 
                        permissions

By default, the librem5-flash-image script will download a 4.5GB image for the Librem 5 every time it runs and then automatically delete that image when the script ends, which is extremely annoying if the flashing of the phone fails, because you will have to download the whole image again. Use the --skip-cleanup option so the script doesn’t automatically delete the downloaded files and the --dir DIRECTORY option to specify the directory where the downloaded files will be stored.

Another annoying aspect of the script is that it limits the number download interruptions to 10 times by default, which I exceeded every time because I have an unreliable internet connection. Use the --download-attempts 0 option to allow an unlimited number of download interruptions. I also don’t care for the fact that disk encryption is enabled by default, since that option can make it very hard to recover my files in an emergency, so I added the --variant plain option to not use disk encryption.

Here is the output when I ran the script:

$ ./scripts/librem5-flash-image --dir img --skip-cleanup --download-attempts 0 --variant plain
2023-08-07 13:07:11,255 INFO Looking for librem5r4 plain byzantium image
2023-08-07 13:07:17,753 INFO Found disk image Build 14846 'plain librem5r4 byzantium image' from Sun Aug  6 19:24:53 2023
2023-08-07 13:07:20,977 INFO Found uboot Build 85 from Thu Aug 25 09:22:41 2022
2023-08-07 13:07:20,977 INFO Downloading to img
2023-08-07 13:07:21,852 INFO Downloading image from https://arm01.puri.sm/job/Images/job/Image%20Build/14846/artifact/librem5r4.img.xz
Download:   7%|██████████▎                                                                                                                                     | 62316544/869716404 [01:42<34:19, 391955.52it/s]2023-08-07 13:09:05,108 INFO Connection error, retrying                                                                                                     | 141591456/4500000256 [01:40<30:59, 2344407.93it/s]
Download:  24%|██████████████████████████████████▊                                                                                                            | 212054605/869716404 [05:18<15:28, 708344.53it/s]2023-08-07 13:12:41,992 INFO Connection error, retrying                                                                                                    | 1128868244/4500000256 [05:18<12:58, 4331382.30it/s]
                                                                                                                                                                                                               2023-08-07 13:25:41,647 INFO Calculating sha256sum of img/librem5r4.img                                                                                                                                          
2023-08-07 13:25:56,090 INFO Downloading uboot from https://arm01.puri.sm/job/u-boot_builds/job/uboot_librem5_build/85/artifact/output/uboot-librem5/u-boot-librem5.imx                                                                                                                                                                                                                                                

After the script finishes the downloading the correct image, then it provides instructions to flash the Librem 5. It should work just by turning off the Librem 5 and then connecting the Librem 5 to your computer with a USB-A to USB-C cable. (I tried using the USB-C to USB-C cable that comes with the Librem 5 and it didn’t work for me.) Then, press the Librem 5’s Power button, while continuing to hold down on the Volume Up button.

The new image should be transferred to the Librem 5, but it never has worked for me without following the more advanced instructions below:

             Enter the flashing mode by holding volume-up button while turning the phone on.

            If it's not detected, follow these steps:
            - Ensure that the phone is powered off
            - Turn all Hardware-Kill-Switches off
            - Unplug the USB cable if connected
            - Remove battery
            - Hold volume-up button
            - Insert the USB-C cable (red light blinks, no green light)
            - Reinsert the battery (red and green lights constantly on, the script will continue)
            - Release volume-up button

Searching...
uuu (Universal Update Utility) for nxp imx chips -- libuuu_1.5.21-0-g1f42172

Success 1    Failure 0                                                                                                                                                                                         
                                                                                                                                                                                                                
                                                                                                                                                                                                                
1:2      4/ 4 [Done                                  ] FB: Done                                                                                                                                                 


Flashing complete. You can now turn the device off.

You have to wait for several minutes as the new image is flashed to the Librem 5 until the message “Flashing complete. You can now turn the device off." appears on the computer screen. Then hold down on the Power button to turn off the Librem 5, disconnect it from the USB cable and then hold down on the Power button again to turn it back on.

A wizard in the Librem 5 will guide you through several steps to configure the system language, WiFi connection, and provide an option to use NextCloud to get your account info that you have saved from another device.

If flashing the phone fails, then you can use the --skip-download option to flash the phone again without having to download the 4.5GB image a second time, but you need to use the --dir option to specify the directory where the image and u-boot files are located. For example:

./scripts/librem5-flash-image --skip-download --dir img --skip-cleanup --variant plain

If you didn’t specify a download directory with the --dir option where the PureOS image and uboot files are stored, then the script will create a directory named librem5-flash-image/tmp_librem5-flash-image_xxxxxxxx, where xxxxxxxx is randomly generated numbers and letters. You can use that directory when running the script a second time. For example:

./scripts/librem5-flash-image --skip-download --dir tmp_librem5-flash-image_1lmfdznt --skip-cleanup --variant plain

After successfully flashing the Librem 5, the downloaded files can be deleted:

rm -r tmp_librem5-flash-image_1lmfdznt

Installing Mobian on the PinePhone

The installation of Mobian on the PinePhone has changed significantly since the last time I tried it, because Mobian has switched to Tow-Boot, which makes it much easier to boot using U-Boot. After examining the options that Tow-Boot provides, I hardily support the change, but I did find Tow-Boot confusing the first time I tried to install it, so I will provide instructions to help others.

I found Mobian’s instructions and Tow-Boot’s instructions for the PinePhone to be confusing, because I couldn’t find the right file that I needed. To get the right file, go to Tow-Boot’s Releases page and click on the Assets link for a recent release to expand the list of files for all the supported devices. Download a file which will be labelled as pine64-pinephoneA64-YYYY.MM-RRR.tar.xz, where YYYY is the year, MM is the month and RRR is the release number.

Then decompress it and use the mmcboot.installer.img file inside the archive if installing Tow-Boot in PinePhone’s eMMC Flash memory or use the shared.disk-image.img file if wanting to boot the PinePhone from a microSD card. Given the performance benefits of running the PinePhone from the eMMC, I recommend using mmcboot.installer.img .

Tow-Boot didn’t include a mmcboot.installer.img file for the PinePhone in its 2022.07-006 release, but I found the file in the 2021.10-005 release.

Then, plug in or attach a microSD card to your PC and use the lsblk or sudo sfdisk -l command to find out which device file the microSD card is using on the PC. In my case, it was mounted from /dev/sdb, but it may vary on your PC. For example:

$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
loop0 7:0 0 53,3M 1 loop /snap/snapd/19457
loop1 7:1 0 55,7M 1 loop /snap/core18/2785
loop2 7:2 0 300K 1 loop /snap/universal-update-utility/500
sda 8:0 1 59,5G 0 disk
├─sda1 8:1 1 4M 0 part
└─sda2 8:2 1 22M 0 part /media/amos/57f8f4bc-abf4-655f-bf67-946fc0f9f25b

nvme0n1 259:0 0 1,8T 0 disk
├─nvme0n1p1 259:1 0 200M 0 part /boot/efi
├─nvme0n1p2 259:2 0 1,5T 0 part /media/files
├─nvme0n1p3 259:3 0 20G 0 part [SWAP]
└─nvme0n1p4 259:4 0 146,5G 0 part /
$ sudo sfdisk -l

Disk /dev/sda: 59.49 GiB, 63864569856 bytes, 124735488 sectors
Disk model: SD/MMC
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: E0CA6E57-39B2-4482-9838-21E2785CD93D

Device Start End Sectors Size Type
/dev/sda1 16 8207 8192 4M unknown
/dev/sda2 10240 55295 45056 22M Linux filesystem

Then, use dd to copy the Tow-Boot image to the microSD card (changing /dev/sdX to the device file used by the microSD card on your PC):

sudo dd if=mmcboot.installer.img of=/dev/sdX bs=1M oflag=direct,sync status=progress

Then, download a recent Mobian release for the PinePhone and use gunzip to decompress it. For example:

wget https://images.mobian-project.org/pinephone/mobian-pinephone-phosh-12.0.img.gz
gunzip mobian-pinephone-phosh-12.0.img.gz 

Then turn off the PinePhone and take out the battery and put the microSD card containing Tow-Boot into the PinePhone, and put the battery back in. Then press the Power button to boot the PinePhone and show a blue Tow-Boot screen. Press the Install Tow-Boot to eMMC Boot button at the bottom of the screen to install Tow-Boot in the PinePhone’s Flash memory.

When done installing Two-Boot, turn off the PinePhone and take out the battery and remove the microSD card and put the battery back in. Then, connect the PinePhone to your computer with a USB cable. Boot up the PinePhone holding down on the Volume Up button while pressing the Power button to enter Tow-Boot’s “Jump Drive” mode.

Then, in your PC, use the lsblk or sudo sfdisk -l command to find the device file where the PinePhone’s eMMC is using. In my case, it is /dev/sdb, but it might be different on your PC. Then use dd to write the Mobian image to the PinePhone’s eMMC:

sudo umount /dev/sdX
sudo dd status=progress bs=1M conv=fsync if=mobian-pinephone-phosh-XX.X.img of=/dev/sdX 

Then, disconnect the USB cable and reboot the PinePhone and it should have Mobian installed in it.

Finally, delete the uncompressed Mobian image which is 6 GB in size to save space:

rm mobian-pinephone-phosh-XX.X.img 

Final Thoughts

When I first read about Tow-Boot several years ago, I dismissed it as another needless complication. However, after seeing it in action in the PinePhone, I now hope that Tow-Boot will become widely adopted, so Linux distributions for ARM devices no longer have to deal with creating customized U-Boot installations for each device. Mobian foresees a future where Tow-Boot will allow the distro to ship one universal image that works for all ARM devices, rather than having to create separate images for each ARM device. This change will make it much easier to port new distributions to ARM devices and eventually make it possible for one distro to support hundreds of devices if Tow-Boot becomes widely adopted.

If hardware ships with Tow-Boot preinstalled, just like x86 computers ship with BIOS/UEFI preinstalled, it will become much easier to install the operating system of our choice and give us some degree of booting standardization for ARM devices like we now have for x86 devices.

With ARM offering better energy efficiency, lower prices and far more product diversity than the traditional Intel/AMD duopoly, the switch to ARM devices promises to bring great benefits, but we will only achieve those benefits if it becomes easier for people to install the operating system of their choice to avoid the kind of control that many hardware makers are wont to impose on their users. I foresee Tow-Boot becoming an important element in making it just as easy to install new operating systems on ARM devices as the traditional x86 PC.

Another benefit of Tow-Boot is the fact that it can be booted into “Jump Drive” mode that mounts its Flash memory like any other USB storage device. Even if the operating system is hosed and the device can’t be booted, Tow-Boot makes it possible to easily access the files on the device for recovery or fixing a bad configuration. I don’t know how many times I have had trouble connecting my Android phone to other devices to transfer files. With Tow-Boot’s Jump Drive, it will be much easier to use the PinePhone as a portable storage device and to make system backups.

I would like to see Tow-Boot add an option for selecting the operating system so multi-booting ARM device is possible similar to GRUB, but even with out that option, Tow-Boot goes a long way to making it as easy to boot an ARM device as an x86 device. Unfortunately, the Librem 5 and its NXP i.MX 8M Quad processor is not yet supported by Tow-Boot.

Purism’s librem5-flash-image script handles the tricky parts of downloading and flashing new images on the Librem 5, which I appreciate, but Purism’s documentation doesn’t explain the options for using its script, so I had to read the Python code to discover how to use it. Adding better documentation for the librem5-flash-image script to the Purism web site would be helpful. However, I hope that Purism will consider switching the Librem 5 to use Tow-Boot in the long term.

Leave a comment