Mainlining Guide

Introduction
The kernel fork used in Android is different from the kernel at. The former is downstream kernel (aka. baseline kernel) and the latter is upstream kernel. Carrying around forks of the kernel is not sustainable as it becomes impossible to provide security patches after a short time. The only way to truly fix this for a device is mainlining it. Making a device boot with the upstream kernel is colloquially referred to as mainlining.

When it comes to postmarketOS, we want to get as many devices working with one shared kernel package (based on upstream).

This guide will walk you through mainlining your device. For the devices where this will work, you should be fine with basic shell knowledge, and you will be rewarded with learning a lot of new stuff and possibly booting the mainline kernel on your device!

Getting Help
Read Mainlining_FAQ first to check if there provides some tips for your progress. The mainlining process varies greatly for each device, which means we can't just write down straight forward instructions here. But luckily there are skilled people who have a bigger picture of a specific SoC and they know how to help you out efficiently. Head over to your device's wiki page (as linked in the device overview) and look at the chipset the device has (infobox on the top right). You can also check out Mainlining

Make sure that your SoC is listed in Mainlining. If it isn't, ask someone on #postmarketOS-mainline if it's supported in mainline Linux.

postmarketOS port
This guide assumes that postmarketOS was already ported with a downstream kernel to your device, and that you can enter a shell after it booted via USB (SSH or telnet). Downstream kernels are the ones from the vendor, that ship with the device, and all derivatives from that (e.g. your typical Android / LineageOS ROM). You can check if it was ported already on the devices page, and start a new port if necessary.

Serial cable
It is recommended to have a working serial cable for your device. In case you can not make one, it might be possible to use a workaround for retrieving log messages but that isn't straight forward. You can also use a framebuffer console to see logs appearing on your screen, which you will have to enable in your dts.

Kernel packaging
To make the kernel work with multiple devices, it no longer appends the  file to the kernel image. Instead, it puts all  files for the current architecture in. The  package appends the   file defined in the deviceinfo to the linux image in the boot partition.

Cooperative firmware
Some firmware, especially the bootloader, trustzone etc., don't play nice with the mainline Linux kernel. That is because it may require ugly hacks in the kernel, courtesy of being disgustingly broken. Those ugly hacks will not be accepted into mainline, because the proper solution would be to fix the firmware, regardless of the fact that the freedom to do that was taken away from you thanks to signature verification.

For example, a device shipping with 32bit kernel or even 64bit kernel with aforementioned ugly hacks, is likely to not support PSCI, the only mainline-approved way of CPU power management (including SMP) on aarch64. Considering this relies on trustzone cooperation, which is as far from being under your control as it possibly can, you're probably out of luck unless you a) implement said ugly hacks or b) manage to exploit your device and supply a proper trustzone.

Only if we campaign for the freedom to run our own software on the devices we own will we be able to replace the firmware with an open one, shall one emerge.

Device tree source
To make your device boot, you will need a device tree source file (which will get compiled to a   mentioned above). The guide would tell you about how to make a device tree from existing file provided by soc.

Preparation
''Before proceeding, make sure that you know that your device is supported by the mainline kernel. Otherwise use the source code of a vendor's fork of the kernel, which is known to work as described in the porting guide.''

pmbootstrap setup
If you have not done this already, please download and initialize. You can stay with the defaults. Just make sure to select the right device, and (to save you some time), select  as the user interface. Replace  with the path where you would like to store the source code.

Generate an initramfs with the debug-shell hook:

Kernel
Download a copy of. If your device's SoC has a git repository with active development, use that instead of :

If you have already checked out the regular linux repository, you can add the  branch as follows:

After running the commands of one of the two blocks above, add a new branch for your device:

envkernel.sh
Usually when compiling a kernel, you would install all dependencies and a cross compiler in your host system. To make it easier, we have the  script (for fish shell:  ). It sets up an Alpine Linux chroot with all the dependencies by using  internally, exports the environment variables to use the right cross compiler and creates an alias to. This means, whenever you type  after sourcing that script, it will actually run   in the chroot. Please try the script out once to make sure everything is working as expected:

envkernel.sh has grown to be quite powerful, read more about it at the compiling kernels with envkernel.sh wiki page.

Reminder
Please double check with the following checklist that you meet all the requirements before proceeding further. If you need any help with the above, just ask in the channel or on GitLab.


 * Serial cable (or suitable workaround)
 * Device ported to postmarketOS
 * Initramfs with debug-shell generated
 * envkernel.sh test run

Device Tree Source
The DTS file describes how the peripherals of the device are connected to the SoC. Here is a short description of the process you are guided through here.

Before start
If you are having trouble, ask in the channel. When it comes to DT, it's best to start with one that already works. Look under  in the kernel source code for relevant files (browse online) with your device's codename. You may want to use source code host services (GitLab, github, etc.) to search for your dts for your specific SoC.

The general file naming is. Examples:

When you don't have a result, try to find a  file with the same chipset as your device (e.g.  ). Try to create a new one for your device based on that by creating a patch for.

If there is not even a  file for the same chipset, you need to create one from scratch (no idea how to do that, good luck and please extend the wiki). If you have no idea but the faith, you may check the about DT at the page below to pick up some ideas.

Start with an existing file
Now we have got source DT  for our target device. Copy it and rename to your device name.

Example for copying an existing file:

Let's commit that directly, so it will be easy to see what you have changed later on by running  (adjust the description of the commit accordingly):

Adjust model and compatible
Open the DTS file in an editor and replace the  and   strings at the top of the file:

In the example, we replace  with   and the first string after compatible with   (we leave the second string in place, as this is the name of the SoC, which is the same).

And again, let's commit this change. It's recommended to commit after every change you make to the DTS files so you can revert easily to the last known working state if necessary:

! caveat: The right compatible values can be found in downstream dts. You may however find something unexpected.

In the following example (sm-a300fu), msm8916-mtp is used, which will result in the wrong dts being selected unless you copy  as well. Unfortunately, this board-id is shared between several Samsung phones, but considering they only bundle the one dtb a particular model uses, we can be grateful there even is a board-id. A solution has not been decided upon yet. (18. 3. 2019)

Finally, if you see regulators defined in your dts, remove them. They most likely won't work on your device, and can potentially damage your device/peripherals if set to the wrong values. An example would be: https://github.com/torvalds/linux/blob/master/arch/arm/boot/dts/qcom-msm8960-cdp.dts#L39-L273

Minimal booting version
The next steps are done to try an run a minimal mainline Linux kernel on your device. Almost nothing will work at this point, except for initializing RAM and serial output. We will work our way to enabling one feature after another throughout the process.

Adjust DTS Makefile
Open  in an editor and add one line for your new device tree. First find the right location by searching for the prefix in the file (e.g. all  lines are in the   section). Then insert the name of your  file there, but use   as extension and don't forget the backslash   at the end of the line. Save, check the diff (it should be similar to the one below) and commit your change:

Defconfig and compilation
Look at  to see what defconfig you should use. Generally, for Qualcomm devices  is used. If you are confused, ask on in the channel for what defconfig to use. Make a  file with the following:

there is also a defconfig in linux-postmarketos-qcom that used by postmarketOS, you can run  to inspect it. After you get the correct defconfig for your device:


 * 1) adjust the kernel config to add the drivers for the device if they are not enabled yet.
 * 2) Set as many drivers to build as external module as possible so the main vmlinuz filesize doesn't increase too much.
 * 3) Replace   with the kernel config you want to modify (see  ).

Verification of your DTS
Before you upload the kernel to the device, it's good practice to check, if the DTS file is valid.

You'll need to grep output of the command and look for warnings related to your device DTS file.

Init
We will now use pmbootstrap and your port in pmaports to our advantage in getting mainline running on your device. Obviously everyone's device is different, so your mileage may vary. It might also be helpful seeing an example of what to expect: https://gitlab.com/LogicalErzor/mainline-kernel-pmos-aports/-/commit/3f3401fc0c6c1c823c464869cd5e0edd72c6c07c

In general, you would need to create a new kernel package for your device. You can do following to create a new kernel package:
 * 1) copy a existing kernel package under , rename it to your device model, and place it under   folder mentioned above.
 * 2) create a new package with pmbootstrap. You would need to create a   package and a   if your device is not in pmaports.

After creating kernel package, specifying device to use the new kernel package (or existing mainline kernel package), use the command below to build the kernel:

Once you have set these basic parameters, it's time to see if it'll boot.

Building and Running
Run. This will fetch the kernel source, compile it, and package it for your device. should get the mainline kernel onto your device

Rebuilds
In order to rebuild, run. This will zap your compiled kernel, and now you can run.

Prepare for production
First, open both your  (referred to as "DEVICE") and   (referred to as "LINUX") directories. We will be working in them heavily.

Do the following in order:

package { mkdir -p "$pkgdir"/boot make zinstall modules_install dtbs_install \ ARCH="$_carch" \ INSTALL_MOD_STRIP=1 \ INSTALL_PATH="$pkgdir"/boot \ INSTALL_MOD_PATH="$pkgdir" \ INSTALL_DTBS_PATH="$pkgdir/usr/share/dtb"
 * Open DEVICE/APKBUILD and LINUX/APKBUILD and up the pkgrel version by 1. Save the file and run
 * Open LINUX/APKBUILD and change the following:
 * pkgver=5.16 # mainline kernel version that you are using
 * pkgdesc=... # include mainline in the string
 * change makedepends to the following: . If there are any errors during   then you will most likely be editing this
 * _repository="linux"
 * _commit=" "
 * in source="" change the following:
 * $pkgname-$_commit.tar.gz::https://github.com/torvalds/$_repository/archive/$_commit.tar.gz
 * remove all patches listed here. You used that for downstream, which isn't needed for mainline
 * replace  with
 * make package like the following:

install -D "$builddir"/include/config/kernel.release \ "$pkgdir/usr/share/kernel/$_flavor/kernel.release" }
 * Remove the huge GCC check (Don't need that for mainline)
 * Save the file and run
 * Look at DEVICE/deviceinfo and see if any of the variable listed in https://gitlab.com/postmarketOS/boot-deploy/-/blob/master/boot-deploy-functions.sh are needed for your device. For example, for the MSM8960 SoC device, it needs  and   as the bootloader doesn't support dtbs
 * Replace the config file in your LINUX folder with the .config file. Make sure it's the same name and run

= See also =

General

 * Mainlining FAQ various information collected from #postmarketOS
 * Guides in Qualcomm mainline porting
 * User:Alexeymin/Kernel_development_in_chroot_using_abuild
 * Troubleshooting:kernel
 * Submitting_Patches guide on submitting patches to Linux
 * #91: &quot;The Mainline Kernel&quot;

Misc

 * Linux Kernel Release Model (reasons why we should all be using mainlined kernels)
 * Submitting your first patch to the Linux kernel and responding to feedback
 * Replicant upstream kernel and upstream bootloader wiki
 * Linux Foundation youtube video ARM64 SoC Linux Support Check-List (what needs to be done to get an arm64 soc to work on mainline)

Other guides

 * A XDA thread about How to get an Android kernel up to date with Linux upstream
 * Getting started tips from zhuowei
 * Device Tree usage on elinux.org
 * Device Tree reference on elinux.org
 * Documentation of devicetree bindings on bootlin.com
 * opendata26 walking alibabzo through mainlining aries

Device specific

 * Google Galaxy Nexus (samsung-maguro): Mainlining progress (initial tricks with RAM and some sleep calls before the reboots in the code to figure out where it was failing will also be useful for other devices)
 * Google Pixel 3 XL (google-crosshatch): mainlining attempt: progress and questions (useful for newer SoCs, useful info about force-reboot code, stub dtbo partition)
 * Blog about mainline kernel support for the Motorola Droid 4
 * Debian on N900
 * Build Mainline for Xperia devices
 * Documenting devices with mainline Linux support A thread on maemo forums, provide a list of mainline device DTs

SoC-specific

 * Allwinner mainline effort
 * probably a list of which qualcomm socs are similar

Display

 * Freedreno wiki: Display driver porting
 * List of DTSI -> panel driver function translations