Difference between revisions of "Porting to a new device"

From postmarketOS
Jump to navigation Jump to search
(Initial import from github wiki)
 
m (Vendor kernel specific package -> Downstream kernel specific package)
 
(175 intermediate revisions by 53 users not shown)
Line 1: Line 1:
If you have ''any'' questions, feel free to ask in the [https://github.com/postmarketOS/pmbootstrap/wiki/Matrix-and-IRC matrix/irc channel] or [https://github.com/postmarketOS/pmbootstrap/issues bug tracker]! This is a wiki, so please adjust everything that isn't detailed enough or would have helped you with porting.
+
== Introduction ==
  
Please write your porting progress to the [https://github.com/postmarketOS/pmbootstrap/wiki/Devices devices] page, even if you didn't get very far. This helps to determine what can be improved to make porting easier.
+
''This is a step by step guide made for you to be able to port postmaketOS to a new device.''
  
'''Please use a spare device for experimenting with postmarketOS! You won't be able to use typical phone features right now, such as making calls, writing SMS, using Wi-Fi, using Bluetooth. Although everything has been tested, there is no guarantee that you won't break your device.'''
+
{{note|Beginner speaks to beginners: Have a look at the summary to keep the whole process in mind!}}
  
=== Initialization ===
+
The main steps are:
  
* Clone the repository: <code>git clone https://github.com/postmarketOS/pmbootstrap</code>
+
* Set up postmarketOS development environment on your computer.
* Run <code>./pmbootstrap.py init</code> and configure for a new device
+
* Build a device-specific kernel and a device-specific system package for your device, or make use of a (close to) mainline kernel and a device-specific system package.
* Open a second terminal and run <code>./pmbootstrap.py log</code> to get detailed output from the following pmbootstrap commands
+
* Install the system and adapt it according to your device and usage.
  
=== Device-specific package ===
+
For help, simply connect to the main [[Matrix and IRC|Matrix/IRC]] channel and kindly drop your question. People are happy to answer your questions!
  
Create an appropriate <code>device-$vendor-$name</code> package in the <code>aports/device</code> folder:
+
Before you follow this guide, identify what SoC (System on a Chip) the device you want to port has. We have dedicated mainlining guides for the following SoCs:
  
<pre class="shell">cp -r aports/device/device-samsung-i9100 aports/device/device-vendor-name</pre>
+
* [[MSM8916 Mainlining|Snapdragon 410/412 MSM8916/Snapdragon 615/616 MSM8939]]
The important files are <code>APKBUILD</code> (''build recipe, [[apk is an Alpine Linux term|Glossary#apk]]'') and [[deviceinfo|deviceinfo reference]]. Please adjust them as necessary. Note that if your device uses '''fastboot''', you will need to add <code>mkbootimg</code> to the <code>depends=</code> list in the <code>APKBUILD</code>, and the following variables at the end of <code>deviceinfo</code> ([https://github.com/postmarketOS/pmbootstrap/wiki/How-to-find-device-specific-information#fastboot-bootimg-flash-offsets guide], [https://github.com/postmarketOS/pmbootstrap/blob/2670c3a031e7204cb638a6947ea4e867e66d033b/aports/device-lg-mako/deviceinfo#L18-L24 example]):
+
* [[MSM8996 Mainlining|Snapdragon 820/821 MSM8996]]
 +
* [[SDM845 Mainlining|Snapdragon 845 SDM845]]
  
<pre class="shell"># Fastboot related
+
Even if your SoC isn't listed here, it may have good mainline support. You can try to find yours in [[SoC Communities]] and ask for help in postmarketOS mainline on [[Matrix and IRC|Matrix/IRC]].
deviceinfo_generate_bootimg=&quot;true&quot;
 
deviceinfo_flash_offset_kernel=&quot;&quot;
 
deviceinfo_flash_offset_ramdisk=&quot;&quot;
 
deviceinfo_flash_offset_second=&quot;&quot;
 
deviceinfo_flash_offset_tags=&quot;&quot;
 
deviceinfo_flash_pagesize=&quot;&quot;</pre>
 
A post-install script can be created to append device-specific partitions to <code>/etc/fstab</code>. See [https://github.com/postmarketOS/pmbootstrap/blob/ed8fba54c31c3ccd1f1f59c7194fffecc63ca7c4/aports/device/device-nokia-rx51/device-nokia-rx51.post-install#L12 the post-install script] for <code>device-nokia-rx51</code> for an example.
 
  
Once the device package is configured, you will need to update checksums in the APKBUILD to match the new configuration files. You can do that by running:
+
If your device is supported by a (close to) mainline Linux kernel, it is preferable to port it using that kernel. You will be able to achieve greater hardware support (GPU, modem, and so on) while also having more up-to-date software. In some cases, it can even be easier. However, if your device isn't well-supported by any (close to) mainline kernel, keep reading this guide.
  
<pre class="shell">./pmbootstrap.py checksum device-$vendor-$name</pre>
+
== Preparation ==
Now, you can build your device package with:
+
{{note|Please use a spare device for experimenting with postmarketOS! You won't be able to use typical phone features right now, such as making calls, sending text messages, or using Bluetooth. Although everything has been tested, there is no guarantee that you won't break your device.}}
  
<pre class="shell">./pmbootstrap.py build device-$vendor-$name</pre>
+
* Search the [[Devices]] page for your device to avoid duplicate work. Also search the wiki for your device, and check for links to existing branches. If your target device has an x86-64 CPU, you may be able to use the [[generic x64 UEFI device]] port.
=== Kernel package ===
+
* Join [[Matrix and IRC|Matrix/IRC]] to get help when you're stuck.
  
While the goal is to use a mainline kernel for all devices in the long run, this certainly can not be done in one step when porting to a new device. Create a new package for the kernel by copying the kernel package of the most similar device with an existing port. For example:
+
== Requirements ==
 +
<span id="Host_PC"></span><!-- Preserver anchor for old inbound links -->
 +
=== Development environment ===
 +
To set up a development environment, you will need a GNU/Linux system capable of making builds and running pmbootstrap, our development and installation tool. If you don't have a Linux-based OS installed, you may want to [http://www.brianlinkletter.com/installing-debian-linux-in-a-virtualbox-virtual-machine/ set up a virtual machine with VirtualBox] first.
  
<pre class="shell">cp -r aports/device/linux-lg-mako aports/device/linux-vendor-name</pre>
+
Your GNU/Linux system must have:
Now edit the <code>APKBUILD</code>. Replace the kernel source with a kernel suitable for your device. For Android devices we usually use the [https://github.com/postmarketOS/pmbootstrap/wiki/How-to-find-device-specific-information#lineageos-kernel-source-repository kernels from LineageOS]. Copy the right [https://github.com/postmarketOS/pmbootstrap/wiki/How-to-find-device-specific-information#kernel-defconfig-default-config defconfig] from your kernel's source folder into your new <code>linux-...</code> folder and adjust its file name. Please adjust the comments in the <code>APKBUILD</code> file about which defconfig you have used, and which modifications you have made. Please also adjust the <code>pkgver</code>/<code>pkgrel</code> to match the [https://stackoverflow.com/a/12151781 kernel version].
+
* A few gigabytes of free space
 +
* Linux kernel 3.17 or newer (since earlier Linux kernels do not support the <code>getrandom</code> syscall).
  
Next, generate the checksum for the kernel package files using:
+
=== Knowledge ===
 +
It is recommended that you at least somewhat know how to use Linux distributions and how to build software as the porting process is a bit harder than just running a few commands.
  
<pre class="shell">./pmbootstrap.py checksum linux-$vendor-$name</pre>
+
=== Target Device ===
Now, before building the kernel itself, it is required to run the kernel's [https://en.wikipedia.org/wiki/Menuconfig menuconfig] with:
+
If your target device has an ARM processor, it must have a [[wikipedia:Floating-point unit|floating-point unit]] (FPU). If the device has at least an ARMv7 CPU, it should have an FPU; however, only some ARMv6 CPUs have one.
  
<pre class="shell">./pmbootstrap.py menuconfig linux-$vendor-$name</pre>
+
Most smartphones have an FPU. Of the first 80+ ports that we started, only two phones lacked an FPU: the [[HTC Wildfire (htc-buzz)|HTC Wildfire]] from 2010 ({{issue|1203}}) and the [[Vodafone 858 Smart (huawei-u8160)|Vodafone 858 Smart]] from 2011 ({{issue|1592}})). Both phones use the MSM7225, an ARMv6 SoC. If your phone was made before 2012, [https://unix.stackexchange.com/a/185070 make sure it has an FPU].
The first time, you run the menuconfig command, you will get prompted about new config options, that the default config does not address (in Android's build process, these options get ignored, but in pmOS they must be specified). Please accept the defaults it presents. After that, you will be shown a menu, in which the <code>DEVTMPFS</code> kconfig flag should be enabled, to get udev working, which is needed for touchscreen support in Weston. It should be located under <code>Device Drivers ---&gt; Generic Driver Options</code>. NOTE: Do NOT set <code>DEVTMPFS</code> to automount.
 
  
Once you have configured the kernel, build it (the arch specification is necessary here, because we're really compiling code - the device package just contains text/scripts and no native code, therefore it is architecture independent):
+
== Initialization ==
 +
[[Installing pmbootstrap|Install pmbootstrap]], our lightweight postmarketOS development and installation tool. Then run the following:
  
<pre class="shell">./pmbootstrap.py build linux-$vendor-$name --arch=armhf</pre>
+
<syntaxhighlight lang="shell-session">
''NOTE'': The <code>linux-lg-mako</code> package has a patch called <code>gpu-msm-fix-gcc5-compile.patch</code>, to fix compiler errors with GCC6. If your kernel doesn't need that specific patch (if it does not apply correctly, as in [https://github.com/postmarketOS/pmbootstrap/issues/14#issuecomment-305083767 this] report), just remove the file, and remove it from the <code>source=</code> line in the <code>APKBUILD</code>.
+
$ pmbootstrap init
 +
Location of the 'work' path. Multiple chroots (native, device arch, device rootfs) will be created in there.
 +
Work path [/home/user/.local/var/pmbootstrap]:
 +
</syntaxhighlight>
  
If your manufacturer has not released the source code of your kernel and you don't want to give up on porting your device, you can try the [https://github.com/postmarketOS/pmbootstrap/wiki/Using-prebuilt-kernels prebuilt kernels] approach.
+
Type in the code name of your device to start a new port, and answer each prompt. For help, see [[how to find device-specific information]].
  
==== Appended device trees ====
+
<pre>
 +
Target device (either an existing one, or a new one for porting).
 +
Available (60): asus-flo, asus-grouper, fairphone-fp2, ...
 +
Device [samsung-i9100]: wiki-example
 +
You are about to do a new device port for 'wiki-example'.
 +
Continue? (y/n) [y]:
 +
Device architecture (armhf/armv7/aarch64/x86_64/x86) [armhf]: armv7
 +
Who produced the device (e.g. LG)?
 +
Manufacturer: Samsung
 +
What is the official name (e.g. Google Nexus 5)?
 +
Name: Wiki Example
 +
Does the device have a hardware keyboard? (y/n) [n]:
 +
Does the device have a sdcard or other external storage medium? (y/n) [n]:
 +
</pre>
  
Some devices need an appended device tree to boot. In LineageOS kernels this will mean that beside the generated <code>zImage</code> there is also a <code>zImage-dtb</code> file. To use this you have to enable in your kernel appending the <code>dtb</code> as in [https://github.com/postmarketOS/pmbootstrap/blob/51af907534a1518c22f78c006ae880d495ec3985/aports/linux-lg-hammerhead/config-lg-hammerhead.armhf#L674 lg-hammerhead] and change the package step in the build script to use the <code>dtb</code> file:
+
=== Flash method ===
 +
It depends on the flashing protocol that comes with the device. For most Android devices, this is <code>fastboot</code>, some Samsung models need <code>heimdall</code> (which is compatible to "Odin") and Maemo/MeeGo-based Nokia phones work with <code>0xffff</code>. If you don't know which one it is, try to enter the bootloader on your device and check whether it says "Fastboot mode" or "Odin mode". Most of the time that can be done by pressing the <code>Volume Down</code> key when it is just booting. In case you can't figure that one out, try to search the internet - there might even be videos on YouTube on how to do that if you're lucky.
  
<pre class="shell"># Change zImage to zImage-dtb on this command:   
+
For more information see the wiki page about [[Deviceinfo flash methods]].
install -Dm644 &quot;$srcdir/build/arch/arm/boot/zImage-dtb&quot; \
 
              &quot;$pkgdir/boot/vmlinuz-$_flavor&quot;</pre>
 
In Android kernels, you usually enable <code>BUILD_ARM_APPENDED_DTB_IMAGE</code> and get an image with <code>dtb</code> appended and the filename will be <code>zImage-dtb</code>.
 
  
In the mainline kernel instead, you enable [https://github.com/postmarketOS/pmbootstrap/blob/51af907534a1518c22f78c006ae880d495ec3985/aports/linux-nokia-rx51/config-nokia-rx51.armhf#L555 <code>ARM_APPENDED_DTB</code>] (without trialing **_IMAGE**) and will get a bunch of <code>.dtb</code> files for the boards that are selected in the kernel config. In this case you need to manually append the correct <code>.dtb</code> file to the compiled kernel image <code>zImage</code>. An example of this is in the kernel package for the [https://github.com/postmarketOS/pmbootstrap/blob/51af907534a1518c22f78c006ae880d495ec3985/aports/linux-nokia-rx51/APKBUILD#L94-L96 nokia n900]:
+
<pre>
 +
Which flash method does the device support?
 +
Flash method (fastboot/heimdall/0xffff) [fastboot]:
 +
</pre>
  
<pre class="shell">cd &quot;$srcdir/build/arch/arm/boot&quot;
+
Depending on your selection, <code>pmbootstrap</code> may ask you to analyze a <code>boot.img</code> file to get offset values required for the flash method. Get the right one for your device from [https://twrp.me/Devices/ TWRP] (<code>twrp-*.img</code>), [https://download.lineageos.org/ LineageOS] (<code>boot.img</code> inside the zip archive) or by [[Using prebuilt kernels#Extracting boot.img from an Android device|extracting it from within a running Android]]. If you can't find any, you can skip this step for now by just pressing the return key.
cat zImage dts/omap3-n900.dtb &gt; zImage-dtb</pre>
 
''If you are unsure, whether your device has an appended dtb file, use [https://github.com/PabloCastellano/extract-dtb extract-dtb] on an existing kernel image (e.g. from LineageOS). <code>extract-dtb</code> is packaged for postmarketOS, you can build it with <code>pmbootstrap build extract-dtb</code>.''
 
  
=== Installation ===
+
<pre>
 +
You can analyze a known working boot.img file to automatically fill out the flasher information for your deviceinfo file. Either specify the path to an image or press return to skip this step (you can do it later with 'pmbootstrap bootimg_analyze').
 +
Path: /home/user/Downloads/twrp-3.2.0-0-mako.img
 +
NOTE: You will be prompted for your sudo password, so we can set up a chroot to extract and analyze your boot.img file
 +
(native) install alpine-base
 +
(native) install file unpackbootimg
 +
</pre>
  
If you want to install to the system partition of an image file, run the following:
+
=== Interfaces ===
 +
{{note|Don't choose Plasma Mobile, Phosh, Sway if you use downstream kernel for porting.}}
 +
We recommend that you start with <code>weston</code> first, because that has been around the longest in postmarketOS and while it is not really suitable for a phone, it works as a stable demo interface for making the graphics output work in the first place. After that one works, feel free to try out another interface (but expect that it will not necessarily work out of the box).
 +
{{note|Weston is known to be broken on older kernels {{issue|579|pmaports}}, if your device is using a kernel older then 4.3, you might be better of with xfce4 instead.}}
 +
<pre>
 +
Username [user]:
 +
Available user interfaces (5):
 +
* none: No graphical environment
 +
* hildon: (X11) Lightweight GTK+2 UI (optimized for single-touch touchscreens)
 +
* luna: (Wayland) webOS UI, ported from the LuneOS project (Not working yet)
 +
* plasma-mobile: (Wayland) Mobile variant of KDE Plasma, optimized for touchscreen
 +
* weston: (Wayland) Reference compositor (demo, not a phone interface)
 +
* xfce4: (X11) Lightweight GTK+2 desktop (stylus recommended)
 +
User interface [weston]:
 +
Build options: Parallel jobs: 3, ccache per arch: 5G
 +
Change them? (y/n) [n]:
 +
Additional packages that will be installed to rootfs. Specify them in a comma separated list (e.g.: vim,file) or "none"
 +
Extra packages [none]:
 +
Your host timezone: Europe/London
 +
Use this timezone instead of GMT? (y/n) [y]:
 +
WARNING: The applications in the chroots do not get updated automatically.
 +
Run 'pmbootstrap zap' to delete all chroots once a day before working with pmbootstrap!
 +
It only takes a few seconds, and all packages are cached.
 +
Done!
 +
</pre>
  
<pre class="shell">./pmbootstrap.py install</pre>
+
=== Logging ===
If you want to install to a SD card, insert it and run the following. Replace mmcblk0 with the actual device name (<code>lsblk</code> is handy to find out the correct device name).
+
Open a second terminal and run the following command to see detailed logging (such as compiler output). Whenever reporting that something does not work, please attach the detailed log output from this window.
  
<pre class="shell">./pmbootstrap.py install --sdcard=/dev/mmcblk0</pre>
+
<syntaxhighlight lang="shell-session">
=== Flashing ===
+
$ pmbootstrap log
 +
</syntaxhighlight>
  
Before you can run any flash command, you must put your device in the flashing mode. It is usually done holding Volume Down &amp; Power simultaneously when the device is switched off but it may vary depending on the device. For more information see the specific page for your device in the [https://wiki.lineageos.org/devices LineageOS Wiki].
+
== Kernel package ==
 +
While the goal is to use a [[The Mainline Kernel|mainline kernel]] for all devices in the long run, this can usually not be done in one step when porting to a new device. What we do in the meantime is shipping a Linux kernel fork, that is known to work with this device (e.g. from Android).
 +
{{note|If your device does not have a known working Linux kernel fork around (e.g. because it is iPhone or [[Windows Phone]]) this guide won't work straightforward. Have a look at how similar [[Non-android devices|devices]] to yours got ported, [[Building generic kernels|build a generic kernel]] or ask in the [[Matrix and IRC|chat]] for help.}}
 +
The steps below are the straight forward changes you need to compile your kernel. For details see the [[downstream kernel specific package]] article.
 +
 
 +
=== APKBUILD file ===
 +
{{note|<code>APKBUILD</code> has [[Glossary#apk|nothing to do]] with Android's app format!}}
 +
<code>APKBUILD</code> file is a script used to build a package. There are two APKBUILDs you have to edit: for device and linux packages related to your port. The APKBUILDs located at packages' folders. 
 +
 
 +
Where to find device-related packages folders?
 +
 
 +
In case you cloned pmbootstrap from git:
 +
<pre>
 +
$workdir/aports/device/testing/device-wiki-example/APKBUILD
 +
$workdir/aports/device/testing/linux-wiki-example/APKBUILD
 +
</pre>
 +
 
 +
In case you have ''not'' cloned pmbootstrap from git:
 +
<pre>
 +
$workdir/cache_git/pmaports/device/testing/device-wiki-example/APKBUILD
 +
$workdir/cache_git/pmaports/device/testing/linux-wiki-example/APKBUILD
 +
</pre>
 +
 
 +
''Where $workdir is the path you provided at the first step of <code>pmbootstrap init</code> process and "wiki-example" by the brand and codename you provided there.''
 +
 
 +
<!--
 +
Maintainer line can be deleted if you don't plan to maintain your port, otherwise replace
 +
<pre>
 +
# Maintainer: Firstname Lastname <email> (CHANGEME!)
 +
</pre>
 +
with something similar to
 +
<pre>
 +
# Maintainer: Oliver Smith <ollieparanoid@postmarketos.org>
 +
</pre>
 +
but related to your information. You may use nickname instead of the real name if you want, but you have to submit your real e-mail address.
 +
-->
 +
 
 +
=== Source code ===
 +
[[How to find device-specific information#LineageOS kernel source repository|Find the source code]] of the known working kernel fork. Try to find a widely used kernel if possible, for example from LineageOS. The kernel version is also important, as of writing (April 2020), the lowest kernel version number we have packaged is 3.0.x. It might be possible to get even older kernels running (with [[Downstream kernel specific package#GCC version|old GCC versions]]), but even if you get them to boot, you will likely run into problems down the road.
 +
 
 +
Once you have your kernel, adjust the <code># Source</code> section in the <code>linux-wiki-example/APKBUILD</code> file. For LineageOS kernels, you will only need to change <code>_repository</code> and <code>_commit</code> variables. Usually it makes sense to use a commit from the most recently updated branch. For example, if the kernel repo is at <code>https://github.com/LineageOS/android_kernel_motorola_ghost.git</code>, you would use <code>_repository="android_kernel_motorola_ghost"</code> and <code>_commit="c4914db2f65ef63548b0af5d7b37d131581c9c62"</code> (find the commit by clicking on c4914db2 next to "Latest commit" at the top right corner of the directories box).
 +
 
 +
If your kernel is not in a LineageOS repository but somewhere else, you also have to change the URL in <code>source</code> accordingly, e.g. to
 +
<code><nowiki>https://github.com/jmrohwer/$_repository/archive/$_commit.tar.gz</nowiki></code> if the kernel is in <code>https://github.com/jmrohwer/TF101-GNU-kernel</code>. You still need to set <code>_repository</code> and <code>_commit</code> as described above.
 +
 
 +
If your kernel is only available as archive (zip, tarball, etc.), you can unpack it and use <code>pmbootstrap build linux-wiki-example --src=/path/to/extracted/kernel/source</code> for now. Later on, when it's time to upstream your work into the official postmarketOS repositories so everybody can use it, [[How to properly backup downstream kernels#Backup|talk to us]] so we can publish the kernel in a good place.
 +
 
 +
'''Do not fork the kernel and add patches there.''' There are already enough Linux kernel forks out there, and it's next to impossible to understand which kernel repository has which patches applied. Let's not make the situation worse with creating another fork with random patches on top just to make it compile with postmarketOS. Instead, point to the kernel you found. All postmarketOS specific patches should be applied as patch files in the same directory as the APKBUILD. How this is done exactly is described further below in the porting guide. When doing it like that, we avoid downloading the huge kernel sources every time a new patch is applied (remember that not everybody in the world has fast Internet connections), and it makes it much more transparent as the actual patches show up in code reviews.
 +
 
 +
Consider the reliability of the kernel source. If there is any chance that the source might disappear, a backup must be taken and used instead of the original source. See [[How to properly backup downstream kernels]] for instructions.
 +
 
 +
<syntaxhighlight lang="bash">
 +
_flavor="wiki-example" # be sure it's in form of <vendor-codename>, e.g. motorola-ghost
 +
 
 +
# Source
 +
_repository="(CHANGEME!)" # e.g. android_kernel_motorola_ghost
 +
_commit="ffffffffffffffffffffffffffffffffffffffff" # e.g. c4914db2f65ef63548b0af5d7b37d131581c9c62
 +
_config="config-$_flavor.$arch"
 +
source="
 +
    $pkgname-$_commit.tar.gz::https://github.com/LineageOS/$_repository/archive/$_commit.tar.gz
 +
    $_config
 +
    gcc7-give-up-on-ilog2-const-optimizations.patch
 +
    gcc8-fix-put-user.patch
 +
"
 +
builddir="$srcdir/$_repository-$_commit"
 +
</syntaxhighlight>
 +
 
 +
=== Kernel version ===
 +
In the repository with the kernel source code, you will find a <code>Makefile</code>. Open this file and adjust the <code>pkgver</code> in the kernel <code>APKBUILD</code> to the information from the <code>VERSION</code>, <code>PATCHLEVEL</code> and <code>SUBLEVEL</code> variables (e.g. [https://github.com/LineageOS/lge-kernel-mako/blob/c76e1bc83219088b2ff1b2b5709a88ebda5e54e4/Makefile#L1-L3 3.4.0]).
 +
 
 +
=== Defconfig ===
 +
Next you will need to [[How to find device-specific information#Kernel defconfig (default config)|find the kernel configuration]] that is used to compile that kernel source for your device. Download it and save it as <code>aports/device/testing/linux-wiki-example/config-wiki-example.armhf</code> (replace <code>wiki-example</code> and <code>armhf</code>).
 +
 
 +
<syntaxhighlight lang="shell-session">
 +
$ wget https://github.com/LineageOS/lge-kernel-mako/raw/cm-14.1/arch/arm/configs/lineageos_mako_defconfig
 +
$ mv lineageos_mako_defconfig aports/device/testing/linux-wiki-example/config-wiki-example.armhf
 +
</syntaxhighlight>
 +
 
 +
If your device is 64bit (aarch64) replace <code>.armhf</code> with <code>.aarch64</code>
 +
 
 +
=== Download sources and update checksums ===
 +
Use the checksum command. It will not only generate the checksums of all source files, but also download them in case they have not been downloaded yet. If this command fails, most likely the download URL is invalid and needs to be adjusted in the <code>APKBUILD</code> again. Another cause could be, that the defconfig could not be found (e.g. because it was saved with a wrong file name). The actual download URL (with all variables replaced) and the download progress are visible in the log window.
 +
 
 +
<syntaxhighlight lang="shell-session">
 +
$ pmbootstrap checksum linux-wiki-example
 +
</syntaxhighlight>
 +
 
 +
=== Kernel configuration ===
 +
{{note|If <code>pmbootstrap</code> throws an error here, you need to [[#Remove failed patches|remove the example patch]]!}}
 +
The magic command, which lets you change the kernel configuration is <code>pmbootstrap kconfig edit</code>. Don't try to manually change the defconfig file, because only by running menuconfig, the dependencies will get resolved properly. <code>menuconfig</code> always runs on the kernel with all patches applied, so we'll run it once to see if we need to remove patch files first.
 +
 
 +
If there are no errors, you can exit menuconfig with ESC-ESC and move on to making kconfig check happy.
 +
 
 +
==== Remove failed patches ====
 +
You will find some example patches already in the generated kernel package. When a patch does not apply correctly, you will get something like the following in the log window (scroll up, the error is above the <code>^^^</code> line).
 +
 
 +
<syntaxhighlight lang="shell-session">
 +
$ pmbootstrap kconfig edit
 +
</syntaxhighlight>
 +
<pre>
 +
>>> linux-wiki-example: Unpacking /var/cache/distfiles/linux-wiki-example-ffff.tar.gz...
 +
>>> linux-wiki-example: 01_msm-fix-perf_trace_counters.patch
 +
patching file arch/arm/mach-msm/perf_trace_counters.h
 +
Hunk #1 succeeded at 158 (offset 37 lines).
 +
>>> linux-wiki-example: 02_this_patch_fails.patch
 +
patching file arch/arm/mach-msm/perf_trace_counters.h
 +
Hunk #1 FAILED at 121.
 +
1 out of 1 hunk FAILED -- saving rejects to file arch/arm/mach-msm/perf_trace_counters.h.rej
 +
>>> ERROR: linux-wiki-example: all failed
 +
</pre>
 +
 
 +
When this happens, remove the failing patch from the <code>source=</code> variable in the <code>APKBUILD</code>, and delete the patch file from the same folder. Finally, correct the checksums and try kconfig edit again.
 +
 
 +
<syntaxhighlight lang="shell-session">
 +
$ nano aports/device/testing/linux-wiki-example/APKBUILD # remove from source
 +
$ rm aports/device/testing/linux-wiki-example/02_this_patch_fails.patch
 +
$ pmbootstrap checksum linux-wiki-example
 +
$ pmbootstrap kconfig edit
 +
</syntaxhighlight>
 +
 
 +
==== Make kconfig check happy ====
 +
{{note|Consider using <code>kconfig edit -x</code> to get a GUI instead of the terminal interface. Details: <code>pmbootstrap kconfig edit -h</code>}}
 +
Check what you need to adjust in the kernel config before it can be used with postmarketOS. Keep [[Kernel_configuration|changing the options]], until everything passes.
 +
 
 +
<syntaxhighlight lang="shell-session">
 +
$ pmbootstrap kconfig check
 +
$ pmbootstrap kconfig edit
 +
$ pmbootstrap kconfig check
 +
</syntaxhighlight>
 +
 
 +
=== Kernel compilation ===
 +
Next up is the kernel compilation, which will fail a few times before you get it working. Run it once to see where it fails.
 +
 
 +
<syntaxhighlight lang="shell-session">
 +
$ pmbootstrap build linux-wiki-example
 +
</syntaxhighlight>
 +
 
 +
We most likely use a more modern version of GCC compared to what your device kernel was intended to be compiled with (which is good, we don't want outdated software). However, this means that you will probably need to patch your kernel before it compiles successfully. Don't be scared, we'll talk you through it. But in the unlikely case that everything runs through smoothly, continue reading [[#Device specific package|here]].
 +
 
 +
=== Find the error message ===
 +
{{note|Tip: you can use <code>pmbootstrap log</code> to check the log quickly.}}
 +
To find the error message, you should open a log file in your favorite text editor, like
 +
<syntaxhighlight lang="shell-session">
 +
$ nano $(pmbootstrap config work)/log.txt
 +
</syntaxhighlight>
 +
and use search to find error messages for the last build run (they contain <code>error:</code> or <code>Error</code> word).
 +
 
 +
Examples of errors:
 +
<pre>
 +
In file included from arch/arm/mach-msm/perf_trace_counters.h:127:0,
 +
                from arch/arm/mach-msm/perf_trace_counters.c:14:
 +
include/trace/define_trace.h:79:43: fatal error: ./perf_trace_counters.h: No such file or directory
 +
</pre>
 +
 
 +
<pre>
 +
drivers/built-in.o: In function `.LANCHOR1':
 +
msm_iommu_sec.c:(.data+0x9298): undefined reference to `kgsl_iommu_sync_lock'
 +
msm_iommu_sec.c:(.data+0x929c): undefined reference to `kgsl_iommu_sync_unlock'
 +
Makefile:877: recipe for target '.tmp_vmlinux1' failed
 +
make: *** [.tmp_vmlinux1] Error 1
 +
</pre>
 +
 
 +
It is possible to clear the log file right before compilation when you press {{button|ctrl}} + {{button|c}} in the log window and use <code>log -c</code>:
 +
 
 +
<syntaxhighlight lang="shell-session">
 +
(old log output here)
 +
^C
 +
$ pmbootstrap log -c
 +
</syntaxhighlight>
 +
 
 +
Another trick to find the error message real quick is to open <code>log.txt</code> with <code>less</code> and use the follow mode (press {{button|F}} while in <code>less</code> or open less with the <code>+F</code> option: <code>less +F log.txt</code>). This causes <code>less</code> to behave like <code>tail -f</code>. When an error occurs, you can exit the follow mode by pressing {{button|ctrl}} + {{button|c}} and use {{button|?}} to reverse search the output (for example: <code>?error</code>). Press {{button|F}} to re-enable follow mode.
 +
 
 +
=== Get a patch ===
 +
==== From postmarketOS aports ====
 +
It is highly likely that we already ran into the same issue with another kernel. Take (parts of) the offending file name and search for it inside <code>aports/device</code>.
 +
 
 +
<syntaxhighlight lang="shell-session">
 +
$ grep -r 'perf_trace_counters\.c' aports/device/
 +
aports/device/testing/linux-lg-mako/01_msm-fix-perf_trace_counters.patch:In-tree compilation for arch/arm/mach-msm/perf_trace_counters.c was
 +
aports/device/testing/linux-lg-mako/01_msm-fix-perf_trace_counters.patch:                    from arch/arm/mach-msm/perf_trace_counters.c:14
 +
$ grep -r 'msm_iommu_sec' aports/device/
 +
aports/device/testing/linux-lg-mako/02_gpu-msm-fix-gcc5-compile.patch:msm_iommu_sec.c:(.data+0x9298): undefined reference to `kgsl_iommu_sync_lock'
 +
aports/device/testing/linux-lg-mako/02_gpu-msm-fix-gcc5-compile.patch:msm_iommu_sec.c:(.data+0x929c): undefined reference to `kgsl_iommu_sync_unlock'
 +
</syntaxhighlight>
 +
 
 +
When there is a result, copy the patch file you found to your new kernel package, add it to the <code>source</code> variable in the <code>APKBUILD</code> and try building again.
 +
 
 +
<syntaxhighlight lang="shell-session">
 +
$ cp aports/device/testing/linux-lg-mako/01_msm-fix-perf_trace_counters.patch aports/device/testing/linux-wiki-example/
 +
$ nano aports/device/testing/linux-wiki-example/APKBUILD # add it to source
 +
$ pmbootstrap checksum linux-wiki-example
 +
$ pmbootstrap build linux-wiki-example
 +
</syntaxhighlight>
 +
 
 +
==== From elsewhere ====
 +
Fire up your favorite search engine and look at all results for the error message and variations of it. The <code>""</code> feature of most search engines is useful, so it searches for an exact string and not single words. Example queries for the error messages above:
 +
* <code>include/trace/define_trace.h: fatal error: ./perf_trace_counters.h: "No such file or directory"</code>
 +
* <code>linux "./perf_trace_counters.h: No such file or directory"</code>
 +
* <code>android "undefined reference to `kgsl_iommu_sync_unlock'"</code>
 +
 
 +
In most cases, this will yield a patch that you can apply to your kernel. Save what you have found as a patch file right next to the <code>APKBUILD</code> of your new kernel package. Mailing list posts are usually in the format of a patch file and can be used directly, while commits or pull requests (PRs) on GitHub can be downloaded as patch when you append <code>.patch</code> to the URL (e.g. [https://github.com/ShinySide/HispAsian_Lollipop_G6/commit/b7756b6fc4bb728722b14d2dfdbaf1dc843812e9 commit], [https://github.com/ShinySide/HispAsian_Lollipop_G6/commit/b7756b6fc4bb728722b14d2dfdbaf1dc843812e9.patch patch]).
 +
 
 +
If what you found on the web can't be used as patch file directly (e.g. sometimes the files are in other folders), but you understood how you would need to patch the source (from the search results or simply because you already knew), please follow [[How to create a patch when packaging software|this guide]].
 +
 
 +
Patch files can contain arbitrary text before the first line with <code>---</code> in the file. Please use this space to link to the source where you found a patch (in case it is from the Internet) and to paste the error message, that your patch fixes (so it is easier to find for other people).
 +
 
 +
After creating the patch file and adding the source URL and error message, put the file name into <code>source</code> in your <code>APKBUILD</code> and give it another shot.
 +
 
 +
<syntaxhighlight lang="shell-session">
 +
$ nano aports/device/testing/linux-wiki-example/03_description-here.patch
 +
$ nano aports/device/testing/linux-wiki-example/APKBUILD
 +
$ pmbootstrap checksum linux-wiki-example
 +
$ pmbootstrap build linux-wiki-example
 +
</syntaxhighlight>
 +
 
 +
We can't promise anything, but you shouldn't need to do this more than 2 times or so before the kernel build finally goes through.
 +
 
 +
=== Changing compiler ===
 +
==== Using GCC6 ====
 +
If you can't make your kernel compile or boot with the latest GCC from Alpine, you can also try to [[Vendor kernel specific package#Use GCC 6|use GCC6 instead]].
 +
 
 +
==== Using GCC4 ====
 +
As GCC4 was recently introduced in postmarketOS repos, you can follow the procedure for GCC6 above and replace all gcc6 occurrences with gcc4 and add <nowiki>gcc4 (armv7/armhf/...)-gcc4</nowiki> to your list of dependencies.
 +
 
 +
==== Using Clang ====
 +
To use Clang as compiler you have to do the following in kernel package's APKBUILD:
 +
 
 +
* Add <code>clang</code> to <code>makedepends</code>
 +
* Add these lines:
 +
<syntaxhighlight lang="bash">
 +
CC="clang"
 +
HOSTCC="clang"
 +
</syntaxhighlight>
 +
 
 +
=== Device specific package ===
 +
Open the <code>deviceinfo</code> file in an editor (replace <code>wiki-example</code>).
 +
 
 +
<syntaxhighlight lang="shell-session">
 +
$ nano aports/device/testing/device-wiki-example/deviceinfo
 +
</syntaxhighlight>
 +
 
 +
Now adjust:
 +
 
 +
* <code>deviceinfo_screen_width</code>
 +
* <code>deviceinfo_screen_height</code>
 +
 
 +
If your device uses UFS storage, you may need to configure the rootfs image sector size. It defaults to 512b, but some devices use 4096b.
 +
In TWRP, check your sector size through the terminal:
 +
 
 +
<syntaxhighlight lang="shell-session">
 +
$ fdisk -l /dev/block/sd* | grep -i "sector size"
 +
</syntaxhighlight>
 +
 
 +
If the sector sizes are 4096 bytes, add the following line to the <code>deviceinfo</code> file:
 +
 
 +
<code>deviceinfo_rootfs_image_sector_size="4096"</code>
 +
 
 +
You can read more about sector sizes on [https://gitlab.com/postmarketOS/pmbootstrap/-/merge_requests/1725 this pull request thread.]
 +
 
 +
In case you were asked for <code>boot.img</code> analyzing, and skipped that section during [[#Flash method|init]]: You can run <code>pmbootstrap bootimg_analyze path/to/boot.img</code> to get the right values for the <code>deviceinfo_flash_offset_</code> lines now. Filling out manually also works, but that is error-prone and therefore not recommended.
 +
 
 +
See [[deviceinfo reference]] for a listing of all available variables and their meanings. The [[device specific package]] article explains advanced customization of the <code>APKBUILD</code>.
 +
 
 +
Create checksums and build the device package once to make sure it doesn't contain errors at this point (we didn't do that earlier, because <code>pmbootstrap</code> would have complained about the invalid <code>pkgver</code> of the kernel package):
 +
<syntaxhighlight lang="shell-session">
 +
$ pmbootstrap checksum device-wiki-example
 +
$ pmbootstrap build device-wiki-example
 +
</syntaxhighlight>
 +
 
 +
{{note|If you are getting a <code>dtb files not found</code> error, that may be because you used the model number of the device instead of the code name, see issue [https://gitlab.com/postmarketOS/pmaports/-/issues/35 #35]. To fix the problem, look at renaming the port, or simply create a new port with the correct name.}}
 +
 
 +
== We are happy to help you! ==
 +
If you get stuck, we are happy to help you [[Matrix and IRC|in the chat]] and in the [https://gitlab.com/postmarketOS/pmaports/issues issues tracker]. When asking for help, always include the APKBUILD you have written, and any custom patches you have applied, as well as the error message you have gotten from <code>pmbootstrap log</code>.
 +
 
 +
== Documentation ==
 +
This is a wiki, so please adjust everything that isn't detailed enough or would have helped you with porting.
 +
 
 +
If you have made some progress with a new port, please [[Help:Device Page|create a Device page]] to document your findings. Even if you didn't get very far and the kernel does not compile, this will help others to continue your work. To create a device page, you will need to [https://wiki.postmarketos.org/index.php?title=Special:CreateAccount&returnto=Porting+to+a+new+device register an account] on this wiki. (You do not need to provide an e-mail address.)
 +
 
 +
== Installation ==
 +
{{note|If you get a "no space left on device" error, please report in {{issue|928}}.}}
 +
 
 +
To install to the system partition of an image file, run the following:
 +
 
 +
<syntaxhighlight lang="shell-session">
 +
$ pmbootstrap install
 +
</syntaxhighlight>
 +
 
 +
If you want to install to a SD card, insert it '''into your PC''' and run the following. Replace mmcblk0 with the actual device name (<code>lsblk</code> is handy to find out the correct device name). You don't need to format or partition it beforehand, <code>pmbootstrap</code> will take care of that.
 +
 
 +
<syntaxhighlight lang="shell-session">
 +
$ pmbootstrap install --sdcard=/dev/mmcblk0
 +
</syntaxhighlight>
 +
 
 +
== Flashing ==
 +
Before you can run any flash command, you must put your device in the flashing/bootloader mode. It is usually done holding Volume Down &amp; Power simultaneously when the device is switched off but it may vary depending on the device. For more information see the specific page for your device in the [https://wiki.lineageos.org/devices LineageOS Wiki].
  
 
If you want to install to the system partition, run the following (not for the SD card installation!):
 
If you want to install to the system partition, run the following (not for the SD card installation!):
  
<pre class="shell">./pmbootstrap.py flasher flash_system</pre>
+
<syntaxhighlight lang="shell-session">
If the system partition for your device is less than 850MB, you should find the size and change the value of <code>install_size_system</code> in the file <code>pmb/config/__init__.py</code>
+
$ pmbootstrap flasher flash_rootfs
 +
</syntaxhighlight>
  
If you have a device, that works with fastboot, you can boot the kernel now without flashing it:
+
In case your system partition is too small for the generated image (e.g. because you chose Plasma Mobile as UI), it is possible to flash to another partition as well. Just be sure to erase any previous installations of postmarketOS in other partitions, because the init script will start with the first one that it encounters. (To delete a previous version either use <code>dd</code> or simply install the known working OS, e.g. Android, on it). Using multiple partitions with LVM is planned ({{issue|60}}).
 +
<syntaxhighlight lang="shell-session">
 +
$ pmbootstrap flasher flash_rootfs --partition userdata
 +
</syntaxhighlight>
 +
 
 +
If you have a device that works with fastboot, you can boot the kernel now without flashing it:
 +
 
 +
<syntaxhighlight lang="shell-session">
 +
$ pmbootstrap flasher boot
 +
</syntaxhighlight>
  
<pre class="shell">./pmbootstrap.py flasher boot</pre>
 
 
Otherwise, you will need to flash the kernel to the device boot partition:
 
Otherwise, you will need to flash the kernel to the device boot partition:
  
<pre class="shell">./pmbootstrap.py flasher flash_kernel</pre>
+
<syntaxhighlight lang="shell-session">
=== Alternative to flashing: export ===
+
$ pmbootstrap flasher flash_kernel
 +
</syntaxhighlight>
  
 +
== Alternatives to regular flashing ==
 
If the flashing method does not work, it is also possible to export all generated image files to a specific directory (with symlinks), so you can flash it manually with your host Linux system (or even on Windows with proprietary flashers such as Odin, if this is the only way it works for you):
 
If the flashing method does not work, it is also possible to export all generated image files to a specific directory (with symlinks), so you can flash it manually with your host Linux system (or even on Windows with proprietary flashers such as Odin, if this is the only way it works for you):
  
<pre class="shell">./pmbootstrap flasher export</pre>
+
<syntaxhighlight lang="shell-session">
=== After flashing ===
+
$ pmbootstrap export
 +
$ pmbootstrap export --odin
 +
</syntaxhighlight>
 +
 
 +
For Android based devices, you can do a [[Installation from recovery mode|recovery zip installation]].
 +
 
 +
When all else fails, you might have success with installing via [https://gitlab.com/postmarketOS/pmbootstrap/issues/456 netcat] or booting via [https://gitlab.com/postmarketOS/pmbootstrap/merge_requests/547 NFS].
 +
 
 +
== USB Network ==
 +
If you are lucky, your screen may give some clues that you are booted into pmOS. If not, do not get discouraged, the graphics on your device may not yet be setup correctly. The next steps are to see if you can connect to the device through [[USB Network|SSH over USB]] (or if that fails, via telnet). See the [[Boot process]] and [[Inspecting the initramfs]] pages for more details.
 +
 
 +
It is quite easy to give your phone [[USB Internet|Internet access via USB]] when your PC is connected to the Internet.
 +
 
 +
In case it looks like your device did not even boot, have a look at [[Troubleshooting:boot]].
 +
 
 +
== Upstreaming ==
 +
As soon as USB networking is functional, or you have another indication that booting the device works successfully, it is time to upstream your work into the official [https://gitlab.com/postmarketOS/pmaports/ pmaports] repository. This way other people can benefit from your work, and build upon it.
 +
 
 +
See the [[git workflow]] article for detailed instructions.
 +
 
 +
== Display ==
 +
To make the display work in the first place, read [[Troubleshooting:display]] and [[Tuning sysfs]].
 +
 
 +
After you have it working, please take some [[Making good photos|nice photos]] and add them to your device's wiki page. If you have a Reddit account, consider posting them in [https://www.reddit.com/r/postmarketOS/ /r/postmarketOS] as well.
 +
 
 +
== Touchscreen==
 +
To get it working, visit [[Screen Calibration#Touch screen|the screen calibration page]]. If you're having trouble, visit [[Troubleshooting:touchscreen|touchscreen troubleshooting]].
 +
 
 +
== Changing your installation ==
 +
=== Install packages over SSH ===
 +
Get Internet access via [[USB Internet|USB]] (easier) or [[Wifi]], then use the package manager to install new packages:
 +
<syntaxhighlight lang="shell-session">
 +
$ apk add hello-world
 +
</syntaxhighlight>
 +
 
 +
You can also [[Installing packages on a running phone|host packages you have built yourself]] from your PC. Just make sure to increase the package version when you build your own version of a package that already exists. Otherwise the package manager can not know that your package is the newest one and should be installed. Check the output of <code>apk</code> to see whether it is really installing the package or not.
 +
 
 +
=== Building a new system image ===
 +
Whenever you rebuild a package (or pick a new one to be installed by default in <code>pmbootstrap init</code>), you need to make sure that the package is actually installed in the chroot from which the system image gets generated. Achieve that by running <code>pmbootstrap install</code> again, it should update all outdated packages. Pay attention to the output of <code>pmbootstrap log</code> to see if it actually has been updated.
 +
If something did not work as expected, you can always <code>pmbootstrap zap</code> your chroots to start over with a clean installation.
 +
 
 +
=== Kernel ===
 +
A simple way to recompile your kernel (e.g. because you want to change your kernel config) and flash it to your device is running the following commands:
 +
<syntaxhighlight lang="shell-session">
 +
$ pmbootstrap build --force linux-wiki-example
 +
$ pmbootstrap install
 +
$ pmbootstrap flasher flash_kernel
 +
</syntaxhighlight>
 +
 
 +
The last flash_kernel step is only needed if your device has the kernel stored on an extra boot partition.
 +
Android/fastboot compatible devices have such a partition, and Maemo/MeeGo Nokia devices ([[Nokia N900 (nokia-n900)|N900]], etc.) typically don't use it. If your device does ''not'' have a boot partition, update your system partition or SD card.
  
If you are lucky, your screen may give some clues that you are booted into pmOS. If not, do not get discouraged, the graphics on your device may not yet be setup correctly. The next steps are to see if you can connect to the device through telnet over USB. See the [[Inspecting the initramfs]] page for more details.
+
After you've gotten more familiar with postmarketOS, you could try out the <code>postmarketos-update-kernel</code> as well. It allows you to flash a new kernel to the device's <code>boot</code> partition ([[Partition-layout#Android internal storage|not to be confused]] with postmarketOS' own boot subpartition <code>systemp1</code>).
  
Also check [[Tuning sysfs]].
+
== Full disk encryption: osk-sdl support ==
 +
{{note|Our charging application <code>charging-sdl</code> uses the same software stack as <code>osk-sdl</code>, so following the instructions should make both components work.}}
 +
If the display and the touchscreen interface are working, then it's time to add support for <code>osk-sdl</code> so that you are able to use full disk encryption on the root filesystem. Instructions for adding support can be found here: [[Osk-sdl#Porting to New Devices|Porting osk-sdl to New Devices]]
  
Don't forget to create a specific wiki page for your device, and add it to the [[devices]] page. If you noticed anything that was unclear or discovered something useful, please help to improve the wiki!
+
== Advanced topics ==
 +
{{note|Out of ideas what to do next with postmarketOS? Check out the [https://postmarketos.org/blog/2018/06/09/one-year/#get-involved get involved] section from the last big blog post!}}
 +
* [[:Category:Interface|Interfaces]]
 +
* [[WiFi]]
 +
* [[Bluetooth]]
 +
* [[Audio]]
 +
* [[Modem]]
 +
* [[Sensors]]
 +
* [[Mainline kernel]]
 +
* [[Existing Alpine installation]]
 +
* [[Hybris]]
  
<blockquote>Feel free to ask / help on [[Matrix-and-IRC|IRC or Matrix group]]
+
[[Category:Guide]]
</blockquote
 

Latest revision as of 07:03, 10 May 2022

Introduction

This is a step by step guide made for you to be able to port postmaketOS to a new device.

Note Beginner speaks to beginners: Have a look at the summary to keep the whole process in mind!

The main steps are:

  • Set up postmarketOS development environment on your computer.
  • Build a device-specific kernel and a device-specific system package for your device, or make use of a (close to) mainline kernel and a device-specific system package.
  • Install the system and adapt it according to your device and usage.

For help, simply connect to the main Matrix/IRC channel and kindly drop your question. People are happy to answer your questions!

Before you follow this guide, identify what SoC (System on a Chip) the device you want to port has. We have dedicated mainlining guides for the following SoCs:

Even if your SoC isn't listed here, it may have good mainline support. You can try to find yours in SoC Communities and ask for help in postmarketOS mainline on Matrix/IRC.

If your device is supported by a (close to) mainline Linux kernel, it is preferable to port it using that kernel. You will be able to achieve greater hardware support (GPU, modem, and so on) while also having more up-to-date software. In some cases, it can even be easier. However, if your device isn't well-supported by any (close to) mainline kernel, keep reading this guide.

Preparation

Note Please use a spare device for experimenting with postmarketOS! You won't be able to use typical phone features right now, such as making calls, sending text messages, or using Bluetooth. Although everything has been tested, there is no guarantee that you won't break your device.
  • Search the Devices page for your device to avoid duplicate work. Also search the wiki for your device, and check for links to existing branches. If your target device has an x86-64 CPU, you may be able to use the generic x64 UEFI device port.
  • Join Matrix/IRC to get help when you're stuck.

Requirements

Development environment

To set up a development environment, you will need a GNU/Linux system capable of making builds and running pmbootstrap, our development and installation tool. If you don't have a Linux-based OS installed, you may want to set up a virtual machine with VirtualBox first.

Your GNU/Linux system must have:

  • A few gigabytes of free space
  • Linux kernel 3.17 or newer (since earlier Linux kernels do not support the getrandom syscall).

Knowledge

It is recommended that you at least somewhat know how to use Linux distributions and how to build software as the porting process is a bit harder than just running a few commands.

Target Device

If your target device has an ARM processor, it must have a floating-point unit (FPU). If the device has at least an ARMv7 CPU, it should have an FPU; however, only some ARMv6 CPUs have one.

Most smartphones have an FPU. Of the first 80+ ports that we started, only two phones lacked an FPU: the HTC Wildfire from 2010 (#1203) and the Vodafone 858 Smart from 2011 (#1592)). Both phones use the MSM7225, an ARMv6 SoC. If your phone was made before 2012, make sure it has an FPU.

Initialization

Install pmbootstrap, our lightweight postmarketOS development and installation tool. Then run the following:

$ pmbootstrap init
Location of the 'work' path. Multiple chroots (native, device arch, device rootfs) will be created in there.
Work path [/home/user/.local/var/pmbootstrap]:

Type in the code name of your device to start a new port, and answer each prompt. For help, see how to find device-specific information.

Target device (either an existing one, or a new one for porting).
Available (60): asus-flo, asus-grouper, fairphone-fp2, ...
Device [samsung-i9100]: wiki-example
You are about to do a new device port for 'wiki-example'.
Continue? (y/n) [y]:
Device architecture (armhf/armv7/aarch64/x86_64/x86) [armhf]: armv7
Who produced the device (e.g. LG)?
Manufacturer: Samsung
What is the official name (e.g. Google Nexus 5)?
Name: Wiki Example
Does the device have a hardware keyboard? (y/n) [n]:
Does the device have a sdcard or other external storage medium? (y/n) [n]:

Flash method

It depends on the flashing protocol that comes with the device. For most Android devices, this is fastboot, some Samsung models need heimdall (which is compatible to "Odin") and Maemo/MeeGo-based Nokia phones work with 0xffff. If you don't know which one it is, try to enter the bootloader on your device and check whether it says "Fastboot mode" or "Odin mode". Most of the time that can be done by pressing the Volume Down key when it is just booting. In case you can't figure that one out, try to search the internet - there might even be videos on YouTube on how to do that if you're lucky.

For more information see the wiki page about Deviceinfo flash methods.

Which flash method does the device support?
Flash method (fastboot/heimdall/0xffff) [fastboot]:

Depending on your selection, pmbootstrap may ask you to analyze a boot.img file to get offset values required for the flash method. Get the right one for your device from TWRP (twrp-*.img), LineageOS (boot.img inside the zip archive) or by extracting it from within a running Android. If you can't find any, you can skip this step for now by just pressing the return key.

You can analyze a known working boot.img file to automatically fill out the flasher information for your deviceinfo file. Either specify the path to an image or press return to skip this step (you can do it later with 'pmbootstrap bootimg_analyze').
Path: /home/user/Downloads/twrp-3.2.0-0-mako.img
NOTE: You will be prompted for your sudo password, so we can set up a chroot to extract and analyze your boot.img file
(native) install alpine-base
(native) install file unpackbootimg

Interfaces

Note Don't choose Plasma Mobile, Phosh, Sway if you use downstream kernel for porting.

We recommend that you start with weston first, because that has been around the longest in postmarketOS and while it is not really suitable for a phone, it works as a stable demo interface for making the graphics output work in the first place. After that one works, feel free to try out another interface (but expect that it will not necessarily work out of the box).

Note Weston is known to be broken on older kernels pmaports#579, if your device is using a kernel older then 4.3, you might be better of with xfce4 instead.
Username [user]:
Available user interfaces (5):
* none: No graphical environment
* hildon: (X11) Lightweight GTK+2 UI (optimized for single-touch touchscreens)
* luna: (Wayland) webOS UI, ported from the LuneOS project (Not working yet)
* plasma-mobile: (Wayland) Mobile variant of KDE Plasma, optimized for touchscreen
* weston: (Wayland) Reference compositor (demo, not a phone interface)
* xfce4: (X11) Lightweight GTK+2 desktop (stylus recommended)
User interface [weston]:
Build options: Parallel jobs: 3, ccache per arch: 5G
Change them? (y/n) [n]:
Additional packages that will be installed to rootfs. Specify them in a comma separated list (e.g.: vim,file) or "none"
Extra packages [none]:
Your host timezone: Europe/London
Use this timezone instead of GMT? (y/n) [y]:
WARNING: The applications in the chroots do not get updated automatically.
Run 'pmbootstrap zap' to delete all chroots once a day before working with pmbootstrap!
It only takes a few seconds, and all packages are cached.
Done!

Logging

Open a second terminal and run the following command to see detailed logging (such as compiler output). Whenever reporting that something does not work, please attach the detailed log output from this window.

$ pmbootstrap log

Kernel package

While the goal is to use a mainline kernel for all devices in the long run, this can usually not be done in one step when porting to a new device. What we do in the meantime is shipping a Linux kernel fork, that is known to work with this device (e.g. from Android).

Note If your device does not have a known working Linux kernel fork around (e.g. because it is iPhone or Windows Phone) this guide won't work straightforward. Have a look at how similar devices to yours got ported, build a generic kernel or ask in the chat for help.

The steps below are the straight forward changes you need to compile your kernel. For details see the downstream kernel specific package article.

APKBUILD file

Note APKBUILD has nothing to do with Android's app format!

APKBUILD file is a script used to build a package. There are two APKBUILDs you have to edit: for device and linux packages related to your port. The APKBUILDs located at packages' folders.

Where to find device-related packages folders?

In case you cloned pmbootstrap from git:

$workdir/aports/device/testing/device-wiki-example/APKBUILD
$workdir/aports/device/testing/linux-wiki-example/APKBUILD

In case you have not cloned pmbootstrap from git:

$workdir/cache_git/pmaports/device/testing/device-wiki-example/APKBUILD
$workdir/cache_git/pmaports/device/testing/linux-wiki-example/APKBUILD

Where $workdir is the path you provided at the first step of pmbootstrap init process and "wiki-example" by the brand and codename you provided there.


Source code

Find the source code of the known working kernel fork. Try to find a widely used kernel if possible, for example from LineageOS. The kernel version is also important, as of writing (April 2020), the lowest kernel version number we have packaged is 3.0.x. It might be possible to get even older kernels running (with old GCC versions), but even if you get them to boot, you will likely run into problems down the road.

Once you have your kernel, adjust the # Source section in the linux-wiki-example/APKBUILD file. For LineageOS kernels, you will only need to change _repository and _commit variables. Usually it makes sense to use a commit from the most recently updated branch. For example, if the kernel repo is at https://github.com/LineageOS/android_kernel_motorola_ghost.git, you would use _repository="android_kernel_motorola_ghost" and _commit="c4914db2f65ef63548b0af5d7b37d131581c9c62" (find the commit by clicking on c4914db2 next to "Latest commit" at the top right corner of the directories box).

If your kernel is not in a LineageOS repository but somewhere else, you also have to change the URL in source accordingly, e.g. to https://github.com/jmrohwer/$_repository/archive/$_commit.tar.gz if the kernel is in https://github.com/jmrohwer/TF101-GNU-kernel. You still need to set _repository and _commit as described above.

If your kernel is only available as archive (zip, tarball, etc.), you can unpack it and use pmbootstrap build linux-wiki-example --src=/path/to/extracted/kernel/source for now. Later on, when it's time to upstream your work into the official postmarketOS repositories so everybody can use it, talk to us so we can publish the kernel in a good place.

Do not fork the kernel and add patches there. There are already enough Linux kernel forks out there, and it's next to impossible to understand which kernel repository has which patches applied. Let's not make the situation worse with creating another fork with random patches on top just to make it compile with postmarketOS. Instead, point to the kernel you found. All postmarketOS specific patches should be applied as patch files in the same directory as the APKBUILD. How this is done exactly is described further below in the porting guide. When doing it like that, we avoid downloading the huge kernel sources every time a new patch is applied (remember that not everybody in the world has fast Internet connections), and it makes it much more transparent as the actual patches show up in code reviews.

Consider the reliability of the kernel source. If there is any chance that the source might disappear, a backup must be taken and used instead of the original source. See How to properly backup downstream kernels for instructions.

_flavor="wiki-example" # be sure it's in form of <vendor-codename>, e.g. motorola-ghost

# Source
_repository="(CHANGEME!)" # e.g. android_kernel_motorola_ghost
_commit="ffffffffffffffffffffffffffffffffffffffff" # e.g. c4914db2f65ef63548b0af5d7b37d131581c9c62
_config="config-$_flavor.$arch"
source="
    $pkgname-$_commit.tar.gz::https://github.com/LineageOS/$_repository/archive/$_commit.tar.gz
    $_config
    gcc7-give-up-on-ilog2-const-optimizations.patch
    gcc8-fix-put-user.patch
"
builddir="$srcdir/$_repository-$_commit"

Kernel version

In the repository with the kernel source code, you will find a Makefile. Open this file and adjust the pkgver in the kernel APKBUILD to the information from the VERSION, PATCHLEVEL and SUBLEVEL variables (e.g. 3.4.0).

Defconfig

Next you will need to find the kernel configuration that is used to compile that kernel source for your device. Download it and save it as aports/device/testing/linux-wiki-example/config-wiki-example.armhf (replace wiki-example and armhf).

$ wget https://github.com/LineageOS/lge-kernel-mako/raw/cm-14.1/arch/arm/configs/lineageos_mako_defconfig
$ mv lineageos_mako_defconfig aports/device/testing/linux-wiki-example/config-wiki-example.armhf

If your device is 64bit (aarch64) replace .armhf with .aarch64

Download sources and update checksums

Use the checksum command. It will not only generate the checksums of all source files, but also download them in case they have not been downloaded yet. If this command fails, most likely the download URL is invalid and needs to be adjusted in the APKBUILD again. Another cause could be, that the defconfig could not be found (e.g. because it was saved with a wrong file name). The actual download URL (with all variables replaced) and the download progress are visible in the log window.

$ pmbootstrap checksum linux-wiki-example

Kernel configuration

Note If pmbootstrap throws an error here, you need to remove the example patch!

The magic command, which lets you change the kernel configuration is pmbootstrap kconfig edit. Don't try to manually change the defconfig file, because only by running menuconfig, the dependencies will get resolved properly. menuconfig always runs on the kernel with all patches applied, so we'll run it once to see if we need to remove patch files first.

If there are no errors, you can exit menuconfig with ESC-ESC and move on to making kconfig check happy.

Remove failed patches

You will find some example patches already in the generated kernel package. When a patch does not apply correctly, you will get something like the following in the log window (scroll up, the error is above the ^^^ line).

$ pmbootstrap kconfig edit
>>> linux-wiki-example: Unpacking /var/cache/distfiles/linux-wiki-example-ffff.tar.gz...
>>> linux-wiki-example: 01_msm-fix-perf_trace_counters.patch
patching file arch/arm/mach-msm/perf_trace_counters.h
Hunk #1 succeeded at 158 (offset 37 lines).
>>> linux-wiki-example: 02_this_patch_fails.patch
patching file arch/arm/mach-msm/perf_trace_counters.h
Hunk #1 FAILED at 121.
1 out of 1 hunk FAILED -- saving rejects to file arch/arm/mach-msm/perf_trace_counters.h.rej
>>> ERROR: linux-wiki-example: all failed

When this happens, remove the failing patch from the source= variable in the APKBUILD, and delete the patch file from the same folder. Finally, correct the checksums and try kconfig edit again.

$ nano aports/device/testing/linux-wiki-example/APKBUILD # remove from source
$ rm aports/device/testing/linux-wiki-example/02_this_patch_fails.patch
$ pmbootstrap checksum linux-wiki-example
$ pmbootstrap kconfig edit

Make kconfig check happy

Note Consider using kconfig edit -x to get a GUI instead of the terminal interface. Details: pmbootstrap kconfig edit -h

Check what you need to adjust in the kernel config before it can be used with postmarketOS. Keep changing the options, until everything passes.

$ pmbootstrap kconfig check
$ pmbootstrap kconfig edit
$ pmbootstrap kconfig check

Kernel compilation

Next up is the kernel compilation, which will fail a few times before you get it working. Run it once to see where it fails.

$ pmbootstrap build linux-wiki-example

We most likely use a more modern version of GCC compared to what your device kernel was intended to be compiled with (which is good, we don't want outdated software). However, this means that you will probably need to patch your kernel before it compiles successfully. Don't be scared, we'll talk you through it. But in the unlikely case that everything runs through smoothly, continue reading here.

Find the error message

Note Tip: you can use pmbootstrap log to check the log quickly.

To find the error message, you should open a log file in your favorite text editor, like

$ nano $(pmbootstrap config work)/log.txt

and use search to find error messages for the last build run (they contain error: or Error word).

Examples of errors:

In file included from arch/arm/mach-msm/perf_trace_counters.h:127:0,
                 from arch/arm/mach-msm/perf_trace_counters.c:14:
include/trace/define_trace.h:79:43: fatal error: ./perf_trace_counters.h: No such file or directory
drivers/built-in.o: In function `.LANCHOR1':
msm_iommu_sec.c:(.data+0x9298): undefined reference to `kgsl_iommu_sync_lock'
msm_iommu_sec.c:(.data+0x929c): undefined reference to `kgsl_iommu_sync_unlock'
Makefile:877: recipe for target '.tmp_vmlinux1' failed
make: *** [.tmp_vmlinux1] Error 1

It is possible to clear the log file right before compilation when you press ctrl + c in the log window and use log -c:

(old log output here)
^C
$ pmbootstrap log -c

Another trick to find the error message real quick is to open log.txt with less and use the follow mode (press F while in less or open less with the +F option: less +F log.txt). This causes less to behave like tail -f. When an error occurs, you can exit the follow mode by pressing ctrl + c and use ? to reverse search the output (for example: ?error). Press F to re-enable follow mode.

Get a patch

From postmarketOS aports

It is highly likely that we already ran into the same issue with another kernel. Take (parts of) the offending file name and search for it inside aports/device.

$ grep -r 'perf_trace_counters\.c' aports/device/
aports/device/testing/linux-lg-mako/01_msm-fix-perf_trace_counters.patch:In-tree compilation for arch/arm/mach-msm/perf_trace_counters.c was
aports/device/testing/linux-lg-mako/01_msm-fix-perf_trace_counters.patch:                     from arch/arm/mach-msm/perf_trace_counters.c:14
$ grep -r 'msm_iommu_sec' aports/device/
aports/device/testing/linux-lg-mako/02_gpu-msm-fix-gcc5-compile.patch:msm_iommu_sec.c:(.data+0x9298): undefined reference to `kgsl_iommu_sync_lock'
aports/device/testing/linux-lg-mako/02_gpu-msm-fix-gcc5-compile.patch:msm_iommu_sec.c:(.data+0x929c): undefined reference to `kgsl_iommu_sync_unlock'

When there is a result, copy the patch file you found to your new kernel package, add it to the source variable in the APKBUILD and try building again.

$ cp aports/device/testing/linux-lg-mako/01_msm-fix-perf_trace_counters.patch aports/device/testing/linux-wiki-example/
$ nano aports/device/testing/linux-wiki-example/APKBUILD # add it to source
$ pmbootstrap checksum linux-wiki-example
$ pmbootstrap build linux-wiki-example

From elsewhere

Fire up your favorite search engine and look at all results for the error message and variations of it. The "" feature of most search engines is useful, so it searches for an exact string and not single words. Example queries for the error messages above:

  • include/trace/define_trace.h: fatal error: ./perf_trace_counters.h: "No such file or directory"
  • linux "./perf_trace_counters.h: No such file or directory"
  • android "undefined reference to `kgsl_iommu_sync_unlock'"

In most cases, this will yield a patch that you can apply to your kernel. Save what you have found as a patch file right next to the APKBUILD of your new kernel package. Mailing list posts are usually in the format of a patch file and can be used directly, while commits or pull requests (PRs) on GitHub can be downloaded as patch when you append .patch to the URL (e.g. commit, patch).

If what you found on the web can't be used as patch file directly (e.g. sometimes the files are in other folders), but you understood how you would need to patch the source (from the search results or simply because you already knew), please follow this guide.

Patch files can contain arbitrary text before the first line with --- in the file. Please use this space to link to the source where you found a patch (in case it is from the Internet) and to paste the error message, that your patch fixes (so it is easier to find for other people).

After creating the patch file and adding the source URL and error message, put the file name into source in your APKBUILD and give it another shot.

$ nano aports/device/testing/linux-wiki-example/03_description-here.patch
$ nano aports/device/testing/linux-wiki-example/APKBUILD
$ pmbootstrap checksum linux-wiki-example
$ pmbootstrap build linux-wiki-example

We can't promise anything, but you shouldn't need to do this more than 2 times or so before the kernel build finally goes through.

Changing compiler

Using GCC6

If you can't make your kernel compile or boot with the latest GCC from Alpine, you can also try to use GCC6 instead.

Using GCC4

As GCC4 was recently introduced in postmarketOS repos, you can follow the procedure for GCC6 above and replace all gcc6 occurrences with gcc4 and add gcc4 (armv7/armhf/...)-gcc4 to your list of dependencies.

Using Clang

To use Clang as compiler you have to do the following in kernel package's APKBUILD:

  • Add clang to makedepends
  • Add these lines:
CC="clang"
HOSTCC="clang"

Device specific package

Open the deviceinfo file in an editor (replace wiki-example).

$ nano aports/device/testing/device-wiki-example/deviceinfo

Now adjust:

  • deviceinfo_screen_width
  • deviceinfo_screen_height

If your device uses UFS storage, you may need to configure the rootfs image sector size. It defaults to 512b, but some devices use 4096b. In TWRP, check your sector size through the terminal:

$ fdisk -l /dev/block/sd* | grep -i "sector size"

If the sector sizes are 4096 bytes, add the following line to the deviceinfo file:

deviceinfo_rootfs_image_sector_size="4096"

You can read more about sector sizes on this pull request thread.

In case you were asked for boot.img analyzing, and skipped that section during init: You can run pmbootstrap bootimg_analyze path/to/boot.img to get the right values for the deviceinfo_flash_offset_ lines now. Filling out manually also works, but that is error-prone and therefore not recommended.

See deviceinfo reference for a listing of all available variables and their meanings. The device specific package article explains advanced customization of the APKBUILD.

Create checksums and build the device package once to make sure it doesn't contain errors at this point (we didn't do that earlier, because pmbootstrap would have complained about the invalid pkgver of the kernel package):

$ pmbootstrap checksum device-wiki-example
$ pmbootstrap build device-wiki-example
Note If you are getting a dtb files not found error, that may be because you used the model number of the device instead of the code name, see issue #35. To fix the problem, look at renaming the port, or simply create a new port with the correct name.

We are happy to help you!

If you get stuck, we are happy to help you in the chat and in the issues tracker. When asking for help, always include the APKBUILD you have written, and any custom patches you have applied, as well as the error message you have gotten from pmbootstrap log.

Documentation

This is a wiki, so please adjust everything that isn't detailed enough or would have helped you with porting.

If you have made some progress with a new port, please create a Device page to document your findings. Even if you didn't get very far and the kernel does not compile, this will help others to continue your work. To create a device page, you will need to register an account on this wiki. (You do not need to provide an e-mail address.)

Installation

Note If you get a "no space left on device" error, please report in #928.

To install to the system partition of an image file, run the following:

$ pmbootstrap install

If you want to install to a SD card, insert it into your PC and run the following. Replace mmcblk0 with the actual device name (lsblk is handy to find out the correct device name). You don't need to format or partition it beforehand, pmbootstrap will take care of that.

$ pmbootstrap install --sdcard=/dev/mmcblk0

Flashing

Before you can run any flash command, you must put your device in the flashing/bootloader mode. It is usually done holding Volume Down & Power simultaneously when the device is switched off but it may vary depending on the device. For more information see the specific page for your device in the LineageOS Wiki.

If you want to install to the system partition, run the following (not for the SD card installation!):

$ pmbootstrap flasher flash_rootfs

In case your system partition is too small for the generated image (e.g. because you chose Plasma Mobile as UI), it is possible to flash to another partition as well. Just be sure to erase any previous installations of postmarketOS in other partitions, because the init script will start with the first one that it encounters. (To delete a previous version either use dd or simply install the known working OS, e.g. Android, on it). Using multiple partitions with LVM is planned (#60).

$ pmbootstrap flasher flash_rootfs --partition userdata

If you have a device that works with fastboot, you can boot the kernel now without flashing it:

$ pmbootstrap flasher boot

Otherwise, you will need to flash the kernel to the device boot partition:

$ pmbootstrap flasher flash_kernel

Alternatives to regular flashing

If the flashing method does not work, it is also possible to export all generated image files to a specific directory (with symlinks), so you can flash it manually with your host Linux system (or even on Windows with proprietary flashers such as Odin, if this is the only way it works for you):

$ pmbootstrap export
$ pmbootstrap export --odin

For Android based devices, you can do a recovery zip installation.

When all else fails, you might have success with installing via netcat or booting via NFS.

USB Network

If you are lucky, your screen may give some clues that you are booted into pmOS. If not, do not get discouraged, the graphics on your device may not yet be setup correctly. The next steps are to see if you can connect to the device through SSH over USB (or if that fails, via telnet). See the Boot process and Inspecting the initramfs pages for more details.

It is quite easy to give your phone Internet access via USB when your PC is connected to the Internet.

In case it looks like your device did not even boot, have a look at Troubleshooting:boot.

Upstreaming

As soon as USB networking is functional, or you have another indication that booting the device works successfully, it is time to upstream your work into the official pmaports repository. This way other people can benefit from your work, and build upon it.

See the git workflow article for detailed instructions.

Display

To make the display work in the first place, read Troubleshooting:display and Tuning sysfs.

After you have it working, please take some nice photos and add them to your device's wiki page. If you have a Reddit account, consider posting them in /r/postmarketOS as well.

Touchscreen

To get it working, visit the screen calibration page. If you're having trouble, visit touchscreen troubleshooting.

Changing your installation

Install packages over SSH

Get Internet access via USB (easier) or Wifi, then use the package manager to install new packages:

$ apk add hello-world

You can also host packages you have built yourself from your PC. Just make sure to increase the package version when you build your own version of a package that already exists. Otherwise the package manager can not know that your package is the newest one and should be installed. Check the output of apk to see whether it is really installing the package or not.

Building a new system image

Whenever you rebuild a package (or pick a new one to be installed by default in pmbootstrap init), you need to make sure that the package is actually installed in the chroot from which the system image gets generated. Achieve that by running pmbootstrap install again, it should update all outdated packages. Pay attention to the output of pmbootstrap log to see if it actually has been updated. If something did not work as expected, you can always pmbootstrap zap your chroots to start over with a clean installation.

Kernel

A simple way to recompile your kernel (e.g. because you want to change your kernel config) and flash it to your device is running the following commands:

$ pmbootstrap build --force linux-wiki-example
$ pmbootstrap install
$ pmbootstrap flasher flash_kernel

The last flash_kernel step is only needed if your device has the kernel stored on an extra boot partition. Android/fastboot compatible devices have such a partition, and Maemo/MeeGo Nokia devices (N900, etc.) typically don't use it. If your device does not have a boot partition, update your system partition or SD card.

After you've gotten more familiar with postmarketOS, you could try out the postmarketos-update-kernel as well. It allows you to flash a new kernel to the device's boot partition (not to be confused with postmarketOS' own boot subpartition systemp1).

Full disk encryption: osk-sdl support

Note Our charging application charging-sdl uses the same software stack as osk-sdl, so following the instructions should make both components work.

If the display and the touchscreen interface are working, then it's time to add support for osk-sdl so that you are able to use full disk encryption on the root filesystem. Instructions for adding support can be found here: Porting osk-sdl to New Devices

Advanced topics

Note Out of ideas what to do next with postmarketOS? Check out the get involved section from the last big blog post!