User:Dr41nU/PinePhone

From Gentoo Wiki
Jump to:navigation Jump to:search

I started installing Gentoo on my pine phone after booting the PostmarketOS with Sxmo from the multiboot image from Megi.

For this guide, let's assume we have:

  • / (root) on emmc of 16Go
  • /var of 32Go (Firefox needs almost 16Go of tmp space in order to compile, and, if you use flatpak, you will need a lot of space too) on sdcard
  • /var/tmp on zram
  • /tmp on zram
  • /home on the remaining space (on sdcard)

I choose to install the root filesystem on the emmc and to have /home and /var on sdcard. Indeed, I think it can be a good practice to create partition for /var of /tmp in the SDCARD because they are likely to have a lot of read/write cycle, particularly on Gentoo since Gentoo use tmp dirs in /var during compiling process. So you will preserve your EMMC memory.

Moreover, I will use zram (for ram, /var/tmp - to handle small packages -, and /tmp).

A the moment, I use bingch overlay to install kernel sources and Phosh. For sway for exemple, you can have a look on this git repo : https://github.com/Dejvino/pinephone-sway-poc I use p-boot for the boot process.

Finally, depending on your needs, I can suggest to install tar (the Sxmo version is limited), screen and btrfs-progs on the installation host system.

Here are my installation steps.

prepare disks

For this steps the amd64 handbook helps : Handbook:AMD64/Installation/Disks

root #fdisk /dev/mmcblk0

Create filsystem

root #mkfs.btrfs /dev/mmcblk0p3
root #mkfs.btrfs /dev/mmcblk0p4
root #mkfs.ext4 /dev/mmcblk2p3

Chrooting

Prepare Chroot

root #mkdir /mnt/gentoo
root #mount /dev/mmcblk2p3 /mnt/gentoo && cd /mnt/gentoo

Handbook:AMD64/Installation/Stage

root #tar xpvf stage3-*.tar.xz --xattrs-include='*.*' --numeric-owner
root #vi /mnt/gentoo/etc/portage/make.conf

Edit your make.conf file to take advantage of Gentoo's powerfull customizing

FILE /mnt/gentoo/etc/portage/make.confmake.conf file
[...]
# Example of flags that can be used for pinephone cpu. Be carefull, some of theses flag can cause the compilation process to fail
# COMMON_FLAGS="-Os -march=armv8-a -mtune=cortex-a53 -fomit-frame-pointer -mfloat-abi=hard -funsafe-math-optimizations -mneon-for-64bits -pipe"
# Theses later flags are safer
COMMON_FLAGS="-O2 -march=armv8-a -mtune=cortex-a53 -pipe"
# Theses flags are given by cpuid2cpuflags. Please note that neon flag is masked by profile (since it is 32 bit instruction set). So don't be upset if portage does not use it for compiling (firefox for example) 
CPU_FLAGS_ARM="edsp neon thumb vfp vfpv3 vfpv4 vfp-d32 aes sha1 sha2 crc32 v4 v5 v6 v7 v8 thumb2"
VIDEO_CARDS="lima"
# Here I disable jumbo-build, that is used for webkit-gtk, since it increase the memory needed for compiling
USE="wayland -jumbo-build"
# Don't forget to adapt the rest of the file as your needs

You can find more information on CFLAG here:

Now you have to configure ebuild repositories.

root #mkdir --parents /mnt/gentoo/etc/portage/repos.conf
root #cp /mnt/gentoo/usr/share/portage/config/repos.conf /mnt/gentoo/etc/portage/repos.conf/gentoo.conf
root #touch /mnt/gentoo/etc/portage/repos.conf/bingch.conf
root #vi /mnt/gentoo/etc/portage/repos.conf/bingch.conf
FILE /mnt/gentoo/etc/portage/repos.conf/bingch.confBingch repos
[bingch]
location = /var/db/repos/bingch
sync-type = git
sync-uri = https://gitlab.com/bingch/gentoo_overlay.git
auto-sync = yes
root #mkdir /mnt/var-btrfs
root #mount -t btrfs /dev/mmcblk0p3 /mnt/var-btrfs
root #mkdir /mnt/home-btrfs
root #mount -t btrfs /dev/mmcblk0p4 /mnt/home-btrfs
root #btrfs subvolume create /mnt/var-btrfs/gentoo-var

Create subvolume '/mnt/var-btrfs/gentoo-var'

root #btrfs subvolume create /mnt/home-btrfs/gentoo-home

Create subvolume '/mnt/home-btrfs/gentoo-home'

root #mount -t btrfs -o subvol=gentoo-var /dev/mmcblk0p3 /mnt/gentoo/var
root #mount -t btrfs -o subvol=gentoo-home /dev/mmcblk0p4 /mnt/gentoo/home`
root #mount --types proc /proc /mnt/gentoo/proc
root #mount --rbind /sys /mnt/gentoo/sys
root #mount --make-rslave /mnt/gentoo/sys
root #mount --rbind /dev /mnt/gentoo/dev
root #mount --make-rslave /mnt/gentoo/dev
root #test -L /dev/shm && rm /dev/shm && mkdir /dev/shm
root #mount --types tmpfs --options nosuid,nodev,noexec shm /dev/shm
root #chmod 1777 /dev/shm

Chroot itself

root #cp --dereference /etc/resolv.conf /mnt/gentoo/etc/
root #chroot /mnt/gentoo /bin/bash
root #source /etc/profile
root #export PS1="(chroot) ${PS1}"


Further configuration

root #eselect profile list Available profile symlink targets:
 [1]   default/linux/arm64/17.0 (stable)
 [2]   default/linux/arm64/17.0/desktop (stable)
 [3]   default/linux/arm64/17.0/desktop/gnome (stable)
 [4]   default/linux/arm64/17.0/desktop/gnome/systemd (stable)
 [5]   default/linux/arm64/17.0/desktop/plasma (stable)
 [6]   default/linux/arm64/17.0/desktop/plasma/systemd (stable)
 [7]   default/linux/arm64/17.0/desktop/systemd (stable)
 [8]   default/linux/arm64/17.0/developer (stable)
 [9]   default/linux/arm64/17.0/systemd (stable) *
 [10]  default/linux/arm64/17.0/big-endian (exp)
 [11]  default/linux/arm64/17.0/musl (exp)
 [12]  default/linux/arm64/17.0/musl/hardened (exp)
root #eselect profile set 4

Without systemd

root #echo "Europe/Brussels" > /etc/timezone
root #nano -w /etc/locale.gen
root #eselect locale set 9

See Handbook:AMD64/Installation/System#Networking_information for the network configuration

With Systemd

Systemd

root #systemctl enable systemd-networkd.service

Created symlink /etc/systemd/system/dbus-org.freedesktop.network1.service → /lib/systemd/system/systemd-networkd.service. Created symlink /etc/systemd/system/multi-user.target.wants/systemd-networkd.service → /lib/systemd/system/systemd-networkd.service. Created symlink /etc/systemd/system/sockets.target.wants/systemd-networkd.socket → /lib/systemd/system/systemd-networkd.socket. Created symlink /etc/systemd/system/network-online.target.wants/systemd-networkd-wait-online.service → /lib/systemd/system/systemd-networkd-wait-online.service.

root #systemctl enable systemd-resolved.service

Created symlink /etc/systemd/system/dbus-org.freedesktop.resolve1.service → /lib/systemd/system/systemd-resolved.service. Created symlink /etc/systemd/system/multi-user.target.wants/systemd-resolved.service → /lib/systemd/system/systemd-resolved.service.

Prepare network for reboot on Gentoo
root #emerge --ask net-misc/dhcpcd
root #emerge --ask net-wireless/iw net-wireless/wpa_supplicant
root #emerge -avq ssh
root #systemctl enable sshd

Created symlink /etc/systemd/system/multi-user.target.wants/sshd.service → /lib/systemd/system/sshd.service.`

Create file /etc/systemd/network/50-dhcp.network :

FILE /etc/systemd/network/50-dhcp.networkNetwork configuration
[Match]
Name=en*
 
[Network]
DHCP=yes
root #systemctl enable systemd-networkd.service

Edit fstab

FILE /etc/fstabfstab
/dev/mmcblk2p3		/		ext4		noatime								0 1
/dev/mmcblk0p3		/var		btrfs		rw,noatime,ssd,space_cache,subvolid=256,subvol=/gentoo-var	0 0
/dev/mmcblk0p4		/home		btrfs		rw,noatime,ssd,space_cache,subvolid=256,subvol=/gentoo-home	0 0
tmpfs			/tmp		tmpfs           noatime,size=500M						0 0

Sync bingch repo

root #emaint -r bingch sync

Distcc setup

Since it can take a while to compile the entire system onboard, I should advice to use distcc.

The use of docker images makes it easy to configure on every systems.

As fas as I am concerned, I used the ksmanis Gentoo distcc image here: https://hub.docker.com/r/ksmanis/gentoo-distcc

Ksmanis provides a lot of different images that should suits your needs (for me: ksmanis/gentoo-distcc:arm64-tcp).

So once installed on every participating machines, you just have to follow theses simple steps:

  • configure distcc for participating hosts:

Distcc#Specifying_participating_hosts

root #/usr/bin/distcc-config --set-hosts "192.168.0.1 192.168.0.2 192.168.0.3"
  • adapt the make.conf file to indicates that the emerge process now have to use distcc

Distcc#Configure_portage

FILE /etc/portage/make.conf
[...]
MAKEOPTS="-j11 -l2"
FEATURES="distcc"

Please note that you should not use -march=native or -mtune=native in the CFLAGS or CXXFLAGS variables of make.conf when compiling with distcc.

If you are running your participating host inside your own network, I think there is no need to configure ssh connection or ever compression.

Compile and install kernel

https://github.com/umiddelb/armhf/wiki/How-To-compile-a-custom-Linux-kernel-for-your-ARM-device

root #emerge -avq pinephone-sources
root #eselect kernel list

Available kernel symlink targets:

 [1]   linux-5.10.2-pinephone *
root #cd /usr/src/linux
root #make pinephone_defconfig #See arch/arm64/configs/pinephone_defconfig
root #make -j23 -l4 CC=distcc CXX=distcc Image dtbs modules #you need several hours
root #cp ./arch/arm64/boot/Image /boot/vmlinuz-5.10.2-pinephone-arm64
root #cp ./arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone*.dtb /boot
root #make modules_install
root #make firmware_install
root #make headers_install INSTALL_HDR_PATH=/usr

Or if you have cross build environment installed on your amd64 host, you can cross compile the kernel on your amd64 host much quicker, on my i5 laptop it takes about 10 mins. I use wrapper like this

$ cat /usr/local/bin/xmake 
#!/bin/sh
exec make ARCH="arm64" CROSS_COMPILE="aarch64-unknown-linux-gnu-" INSTALL_MOD_PATH="${SYSROOT}" "$@"

Then run the xmake as you would use make for compiling the kernel for pinephone

$ ebuild /var/db/repos/bingch/sys-kernel/pinephone-sources/pinephone-sources-5.10.12.ebuild prepare
$ cd /path/to/portage_build_folder/portage/sys-kernel/pinephone-sources-5.10.12/work/linux-5.10.12/
$ cp arch/arm64/configs/pinephone_defconfig .config # or you can use the config files in sys-kernel/pinephone-sources/files/
$ xmake oldconfig; xmake menuconfig
$ xmake -j9 Image modules # adjust j number as needed
$ xmake DTC_FLAGS="-@" dtbs
$ mkdir /tmp/boot
$ xmake INSTALL_DTBS_PATH=/tmp/boot dtbs_install
$ xmake INSTALL_MOD_PATH=/tmp/boot modules_install
$ cp arch/arm64/boot/Image /tmp/boot
$ rsync -avP /tmp/boot pinephone_ip:/tmp # copy kernel files to pinephone

Then on pinephone move files /tmp/boot to /boot and /lib/modules folders and re-configure new kernel

Configure bootloader

Using p-boot

Follow the p-boot README to install p-boot binary and other files into pinephone's /boot folder.

$ ls -l /boot/
-rw-r--r-- 1 root root 15806472 Jan 31 10:42 Image-5.10.12
-rw-r--r-- 1 root root     1697 Jan 31 09:09 boot.conf
drwxr-xr-x 3 root root     3488 Jan 31 09:03 dtbs-5.10.12
drwxr-xr-x 2 root root     3488 Jan 15 20:51 files
-rwxr-xr-x 1 root root    61304 Sep 30 20:10 fw.bin
-rw------- 1 root root 23844428 Jan 31 10:45 initramfs-5.10.12.img
-rwxr-xr-x 1 root root   522128 Dec 31 17:30 p-boot-conf
-rwxr-xr-x 1 root root   509840 Dec 31 17:45 p-boot-select
-rwxr-xr-x 1 root root    66336 Dec 31 17:46 p-boot-start32
-rwxr-xr-x 1 root root      132 Dec 31 17:46 p-boot-start32.bin
-rw-r--r-- 1 root root    32768 Dec 31 17:19 p-boot.bin

You need the first partition of the boot media formatted as linux (83) partition, with enough space for kernel and other files, here's my SD card config

/dev/mmcblk0p1       62500   500000   437501 213.6M 83 Linux

Then write the p-boot.bin to boot media

$ sudo dd if=p-boot.bin of=/dev/mmcblk0 bs=1024 seek=8

Here's the boot config

$ cat /boot/boot.conf
device_id = pp3 (PP 1.2a)
no          = 0
  name      = 5.10.12 (EMMC)
  atf       = fw.bin
  dtb       = dtbs-5.10.12/allwinner/sun50i-a64-pinephone-1.2.dtb
  linux     = Image-5.10.12
  initramfs = initramfs-5.10.12.img
  bootargs  = console=tty1 console=ttyS0,115200 root=/dev/mmcblk2p4 rootfstype=f2fs rootflags=fastboot rw rootwait quiet
  splash    = files/xnux.argb

Command to write boot kernel and other files to boot partition

$ cd /boot
$ sudo ./p-boot-config . /dev/mmcblk0p1  

Boot into gentoo

Initial configuration for systemd

As a matter of fact, some steps can't be done on chrooted environment

root #hostnamectl set-hostname pinephone
root #localectl set-keymap fr # or whatever your keyboard is
root #timedatectl set-timezone Europe/Paris # or wathever your time-zone is
root #timedatectl
              Local time: mar. 2020-12-29 22:25:34 CET
          Universal time: mar. 2020-12-29 21:25:34 UTC
                RTC time: mar. 2020-12-29 21:25:34    
               Time zone: Europe/Paris (CET, +0100)   

System clock synchronized: no

             NTP service: inactive                    
         RTC in local TZ: no                          

At this point, I installed screen one again to gain confort for last steps

root #emerge -avq app-misc/screen

Enable zram

Zram

root #emerge -avq sys-block/zram-init
root #echo "zram" > /etc/modules-load.d/zram.conf
root #systemctl edit zram_swap

and modify startup command as follows:

FILE temporary file used for editing serviceservice override
[Service]
ExecStart=
ExecStart=/bin/sh -c "exec /sbin/zram-init -s4 -alz4 -d0 -Lzram_swap 1024"

This will reserve a 1Go swap space. Please note that -d0 is unnecessary since by default the zram-init script will use slot #0.

And the same for zram_tmp

root #systemctl edit zram_tmp

add

FILE temporary file used for editing serviceservice override
[Service]
ExecStart=
ExecStart=/sbin/zram-init -d1 -s4 -azstd -text4 -ostrictatime -m1777 -Ltmp_dir 124 /tmp

By this command you will mount a drive on /tmp of 124Mo in the ZRAM slot #1

root #systemctl edit zram_var_tmp

add

FILE temporary file used for editing serviceservice override
[Service]
ExecStart=
ExecStart=/sbin/zram-init -d2 -s4 -azstd -text4 -orelatime -m1777 -Lvar_tmp_dir 1024 /var/tmp

This command mount a drive on /var/tmp of 1Go in the ZRAM slot #2. Then mask tmp.mount as it is replaced by zram_tmp

root #systemctl mask tmp.mount

And finaly, enable the units

root #systemctl enable zram_swap zram_tmp zram_var_tmp

Created symlink /etc/systemd/system/swap.target.wants/zram_swap.service → /usr/lib/systemd/system/zram_swap.service. Created symlink /etc/systemd/system/local-fs-pre.target.wants/zram_tmp.service → /usr/lib/systemd/system/zram_tmp.service. Created symlink /etc/systemd/system/local-fs-pre.target.wants/zram_var_tmp.service → /usr/lib/systemd/system/zram_var_tmp.service.

Emerge stuff

At this time, compilation process can be very long. A usefull tip, if the compilation process is halted, is to continue by submitting

root #ebuild /path/to/package merge
root #ln -s /usr/bin/vapigen-0.48 /usr/bin/vapigen # seems to be requied by some packages
root #ln -s /usr/share/asciidoc /etc/asciidoc # seems to be requied by some packages
root #emerge pinephone phosh-meta --autounmask --autounmask-write -av
root #emerge -avquDN @world

Final configuration

Add various services

root #systemctl enable ModemManager
root #systemctl enable eg25-manager
root #systemctl enable bluetooth

Troubleshooting and tips

Keyboard not showing

Squeekboard should be running (even when it is not showing) and gnome should be configured to use screen keyboard.

Start Squeekboard at session startup:

FILE /etc/xdg/autostart/sm.puri.Squeekboard.desktopSqueekboard launch
[Desktop Entry]
Name=Squeekboard
GenericName=Squeekboard Virtual Keyboard
Comment=Virtual Keyboard
Exec=/usr/bin/squeekboard
Terminal=false
Type=Application
NoDisplay=true
Categories=GTK;Utility;

Enable screen keyboard (if necessary):

root #gsettings set org.gnome.desktop.a11y.applications screen-keyboard-enabled true

Authorization asked for calling

It can be related to PolicyKit rules.

In that case you just have to edit a new file (starting with 00 to take precedence of /etc/polkit-1/rules.d/01-org.freedesktop.ModemManager1.rules)

FILE /etc/polkit-1/rules.d/00-org.freedesktop.ModemManager1.rulesPolicyKit additionnal rule
// Let users in plugdev group modify ModemManager
polkit.addRule(function(action, subject) {
    if (/^org\.freedesktop\.ModemManager1\.(Device\.Control|Contacts|Messaging|Location|Voice)$/.test(action.id) &&
        subject.isInGroup("plugdev") && subject.active) {
        return "yes";
    }
});

Using other branch or version

Since many pinephone related ebuilds are relying on GIT, it is easy to change branch, version, commit and even source URL before merging an ebuild.

Here is a example:

root #EGIT_OVERRIDE_BRANCH_LIBREM5_CHATTY="wip/sadiq/mm-account" EGIT_OVERRIDE_COMMIT_LIBREM5_CHATTY="" EGIT_OVERRIDE_REPO_LIBREM5_CHATTY="https://source.puri.sm/kop316/chatty" emerge -a1 =net-im/chatty-0.2.0-r6

Each environment variable that you will need starts with EGIT_OVERRIDE_. Then, you have the object (BRANCH, REPO, COMMIT, etc.) and finaly a text generated from the original repo URL