Introduction
Goals
This is a proof of concept guide on using Debian with the PinePhone. Our goals are:
- Data Encryption
- Full Calling and Messaging Functionality
- Use of Android Applications
- Stay Close to Trusted Upstreams
Gotchas
There are nonetheless some gotchas with this guide:
- Rather than using the Debian Kernel, we use megi1’s patched kernel
- Speakers do not work outside of calling though bluetooth or the headphone jack should still work
- No cellular data (yet?) though calling/messaging/ethernet/WiFi is unaffected
Requirements
To follow this guide as written you need the following items:
- PinePhone
- Linux Computer
- USB-C to USB-A Cable
- SD Card
High Level Design Description
To do this we use a largely typical boot process. Tow-Boot will load the unencrypted kernel and custom initramfs with embedded wayland session, which then subsequently accepts the password from the user and opens the encrypted Btrfs root filesystem. Finally we switch-root and load Phosh, (though Plasma Mobile is available from external repos) and waydroid for android applications.
We choose Debian for this becuase:
- It is stable (though we are using Testing) and well supported
- It packages phosh in it’s repositories
- It has a convient bootstrapping tool called
debootstrap
Our filesystem will look like the following on 16/32GB devices:
eMMC
- 512M/1G Boot with Kernel, Initramfs and U-Boot:
/boot/efi
- Luks
- Btrfs:
/
- Swap 2G/4G
- Btrfs:
- 512M/1G Boot with Kernel, Initramfs and U-Boot:
SD Card
- Luks
- Btrfs:
/home
- Btrfs:
- Luks
Note that we could also have kept the rootfs unencrypted and encrypted only /home
. This would not require including a GUI in the Initramfs. As the design is described above, we will need to insert an on-screen keyboard application into the initramfs to receive the password from the touchscreen.
Booting
Tow Boot
First we install Tow-Boot. We use Tow-Boot becase it has a simple extlinux.conf
or UEFI interface and it can present the PinePhone’s storage as a USB mass storage device for manipulator from the Computer.
This is easily done as described here. Download the correct archive from their github releases. I use pine64-pinephoneA64-2021.10-004.tar.xz
. Insert your SD Card (I assume this is /dev/mmcblk0
)into your reader and do something similar to:
|
|
Next insert the SD Card into your pinephone and switch it on. As given in the instruction:
When starting up with Tow-Boot, which the installer image use, the phone will vibrate slightly and the LED will turn red. After a short moment, the LED should turn yellow. A few moments later the display will turn on with a blue colour, or will directly boot to the installer GUI. In the installer GUI, select “Install Tow-Boot to eMMC Boot”. It is not necessary to erase the storage before installing. Erasing the storage can be used to uninstall Tow-Boot (or any other platform firmware installed to the eMMC Boot partition). Once installed, remove the installation media, and verify Tow-Boot starts from power-on.
Once this is done, after removing the SD Card, switch it off and follow the instructions to start the phone in USB Mass Storage mode:
The phone can be started in USB Mass Storage mode by holding the volume up button at startup before and during the second vibration. The LED will turn blue if done successfully. In this mode, the phone will work like a USB drive when connected to a host computer.
Finally, attach it to your computer via USB.
Formatting
Identify the disk path of your PinePhone that is now connected via USB as a Mass Storage Device. We will assume that this is /dev/sdz
. Additionally, insert the SD Card into your reader. We will assume that this is /dev/mmcblk0
. We then format the drives with commands similar to the following. This will wipe your drives:
First we wipe the SD Card to remove the tow boot installer:
|
|
Next we create the partition table for the eMMC and wipe the new partition:
|
|
Then we encrypt the data partitons with Luks.
|
|
Note that we should be conservative with the above iter time. A high iter-time will result in a drastically higher unlock time on the PinePhone. Then open the encrypted filesystems.
|
|
Format the encrypted root:
|
|
Finally format the partitions:
|
|
Now close the encrypted filesystems:
|
|
Kernel
The mainline Linux Kernel does not currently have the drivers necessary to reliably manage the USB-C port on the PinePhone or to manage the Realtek RTL8723CS WiFi antenna on the PinePhone. The PinePhone Pro may fair better however. We will use megi1’s kernel here. More info is available on https://xnux.eu/.
Bootstrap
This section is a little tedious; we will use Qemu’s Arm64 emulation to complete the remainder of the install. If you have an Arm64 device, it is a good idea to do this natively or with KVM.
First acquire qemu-system-aarch64
using your package manager and fetch an OpenSuse Tumbleweed ISO like wget https://download.opensuse.org/ports/aarch64/tumbleweed/iso/openSUSE-Tumbleweed-KDE-Live-aarch64-Current.iso
. We use a Tumbleweed iso because it comes with a serial console enabled and OpenSuSE packages debootstrap. Then start up qemu, passing through the pinephones drives like so:
|
|
Note that /usr/share/qemu/edk2-aarch64-code.fd
is the path to arm64 UEFI firmware and may be located differently on your system. Alternatively you can use libvirt and the virt-manager GUI.
Now, wait for the VM to start up. Eventually you will see a login prompt. Login with the username “linux” and an empty password. Note that I like to use -o compress-force=zstd
. You may use lzo
, zlib
instead of zstd
or compress
instead of compress-force
or remove the argument altogether. We then mount the drives as follows:
|
|
We are now ready to begin bootstrapping. While we could have partially done this on the host with debootstrap --foreign
. There seemed to be some bugs with a circular dependancy so I opted to do the it completely in the VM. We the call debootstrap
and wait:
|
|
We then note the UUID of /dev/vdc1
:
|
|
Then create an fstab
at /mnt/os/etc/fstab
like:
|
|
We the chroot into the new install:
|
|
We the configure the PinePhone’s system:
|
|
If you get a statoverride
error, run the command below and repeat the steps above:
|
|
Then edit /etc/apt/sources.list
and edit it so that it looks like:
|
|
Then install packages on the new system:
|
|
Note that at this point, it is good practice to create a new user and configue sudo. This is not detailed in this guide but you may wish to do this. Finally fetch and install the kernel:
|
|
Initramfs
We will use an Alpine Linux install as the initramfs which ends up at around 100M. We do this because we would like to embed an on-screen-keyboard in the initramfs for the passwords of the encrypted filesystems. Dracut/Plymouth does not currently have this feature. This is easier than creating a new Dracut module doing the same as the package manger ensures that everything required is included in initramfs while otherwise, we would need to identify many of these files ourselves.
First note the UUIDs of the SD Card (/dev/vdb
) and encrypted emmc partition (/dev/vdc2
):
|
|
Fetch the Alpine package manager and use it to bootstrap the system:
|
|
Note that vi
is available inside the chroot. Put the follwing script at /init
(in the chroot):
|
|
We use s6 to manage services. This makes it easy to control the lifsespan of our wayland components and especially, terminate the processes when init
is done and ready to switch_root
.
We then create an s6 scan directory:
|
|
Put the following script at /service/sway/run
:
|
|
Put the following script at /service/kbd/run
:
|
|
Put the following script at /service/foot1/run
replacing <UUID of emmc>
with the value you wrote down previously:
|
|
Put the following script at /service/foot2/run
replacing <UUID of SD Card>
with the value you wrote down previously:
|
|
Finally mark the scripts as executable and set foot1
and foot2
to initally down:
|
|
Then we exit the chroot and build the initramfs:
|
|
Omit the --best
to speed it up.
Finishing Up With Boot Procedure
Finally, the pinephone is (almost) bootable and we can put on the finishing touches:
|
|
The audio and modem on the PinePhone require interventaion to enable/setup. We use the scripts below to do this:
Put the following script at /usr/bin/setup_pp.sh
:
|
|
We use audio-pp.c from https://xnux.eu/devices/feature/audio-pp.html to set up audio:
|
|
Create a systemd service to run the above script. Put it at /etc/systemd/system/setup_pp.service
:
|
|
Mark the script as executable and enable the service:
|
|
Finally we use a extlinux.conf
for the bootloader. This is simply the easiest way to do this. Put the following config at /boot/efi/extlinux/extlinux.conf
|
|
Boot The Pinepone
Finally, the PinePhone should be bootable. It is reccomended to set up SSH or enable serial by appending console=ttyS0,115200
to the kernel command line above. Now poweroff the VM, sync
on the VM host, unplug the PinePhone and boot it up. If everything works, great! If not, append rd.break
to the above kernel command line. The initramfs will drop to a shell after which you can use some sort of USB-C keyboard/adapter or the PinePhone serial cable to check for errors and boot the pinephone manually (using essentially the commands in /init
after cryptsetup
from foot1
and foot2
). The initramfs almost certainly contains all the tools needed for this.
Waydroid
Install
Now we install waydroid. Unfortunately, python3-gbinder
is not yet packaged for the current Debian Testing; we must build this from source. We will use install_waydroid.sh
from this gist to do this. Install libgl1-mesa-glx
and run the script:
|
|
Put the following at /etc/gbinder.conf
:
|
|
There are a few bugs relating to WayDroid’s networking that we will need to work around:
|
|
Finally start waydroid:
|
|
Omit the -s GAPPS
above to install an Android Image without Google serices. Now, start up phosh and select waydroid in the app drawer. It should get you to an Android session without networking. To enable networking note down the ipv4 address of the interface below:
|
|
Then set it as the default route in the WayDroid session:
|
|
Now the container has networking though, unfortunately, this needs to be done each restart though only after manually starting the waydroid session. See this issue for info.
F-Droid (Optional)
Now we set up app repositories. Setting up F-Droid is simple:
|
|
Google Play (Optional)
Google Play is more complicated. This requires the GAPPS image. Firstly we (at time of writing) need to update the Android System WebView in the image. Download the APK from here and transfer it to the PinePhone (scp
?). On the PinePhone, in the Android session, go to settings (not Phosh settings), About Phone, then tap Build Number several times till developer settings get enabled. Note down the ipv4 adress of the PinePhone in the same section. Then search for, and enable ‘ADB over network’. Finally use adb
to install the downloaded apk:
|
|
Next retreive the android_id
of the device and submit it to google:
|
|
Copy the android ID and submit it at https://www.google.com/android/uncertified/. Finally wait 20 minutes or so; after which you should be able to login to the Play Store an install apps like a typical android device.
Final Thoughts
In the end, we have a functional mobile device as we wanted. Linux alone provides basic calling and messaging functionality sufficient for use as a phone while WayDroid additionally provides a way to run Android apps seamlessy on top of a Debian Userspace and Linux Kernel allowing use of Android Apps (e.g. WhatsApp, FaceBook) on top of a trused Debian Kernel with auditable Encryption (Luks), Tunnelling (OpenVPN/Wireguard), Inspection (TOMOYO/Apparmor) and much more in a standard mobile form factor. My testing also showed very respectable performance on 2d Android Apps (e.g Messaging apps, eReaders) though video playback was poor.
The final device is indeed a proof of concept of a mobile device constructed from upstream Debian however, it lacks the likes of the polish that might be found on distributions dedicated to mobile use like Mobian or PostmarketOS.