Vendor kernel specific package

From postmarketOS
Jump to: navigation, search

Unless a device has been mainlined, we need to package the vendor kernel (also called "downstream kernel"). This is the reference for the APKBUILD files of vendor kernels.

Generate a template

Usually you would generate both a new device specific package and a new vendor kernel package by running pmbootstrap init and typing in a new device name. In case you should only have a device package, but not a kernel package, you can regenerate the latter with pmbootstrap aportgen linux-changeme-changeme (you guessed it, changeme needs to be adjusted).

The template gets improved every now and then to make porting easier, so don't be surprised when you are looking at older ports and their APKBUILDs look a bit more complicated than what gets generated from the latest pmbootstrap version. Essentially they are doing the same thing.

Modernize your aport

To recreate your vendor kernel aport on top of the latest (and therefore most readable) template, do the following steps:

$ mv aports/device/linux-wiki-example aports/device/linux-wiki-example-old
$ pmbootstrap aportgen linux-wiki-example
(now adjust the new aport to use the sources and patches from the "-old" folder)
$ pmbootstrap checksum linux-wiki-example
$ pmbootstrap build --force linux-wiki-example
(now test it on your device and make sure it boots, e.g. with 'pmbootstrap zap', 'pmbootstrap install', 'pmbootstrap flasher boot')
$ rm -r aports/device/linux-wiki-example-old
$ pmbootstrap pkgrel_bump linux-wiki-example
$ git add -A
$ git commit -m "device/linux-wiki-example: modernize aport"

downstreamkernel_prepare

Newly generated vendorkernel packages use the downstreamkernel_prepare function. That way we can share code between the APKBUILDs, so it is less redundant. To see what the function does, read the source over here.

GCC version

The kernel gets compiled with GCC. Alpine Linux has been shipping version GCC 6 for a long time, but changed the default GCC version to GCC 8 in September 2018. It was discovered that at least one vendor kernel does not boot when compiled with GCC 8 (pmaports#103), so we ended up packaging GCC 6 side by side with GCC 8. All existing 3.x vendor kernels that were packaged have been adjusted to use GCC 6 at this point in time, just to make sure we don't introduce any breakage there. The default for new packages is using the current GCC version that is packaged in Alpine (at time of writing: GCC 8).

Use GCC 6

If your new kernel port does not boot at all, please try to compile it with GCC 6 and see if it works then.

Replace these lines:

# Compiler: latest GCC from Alpine
HOSTCC="${CC:-gcc}"
HOSTCC="${HOSTCC#${CROSS_COMPILE}}"

with the following ones:

# Compiler: GCC 6 (doesn't boot when compiled with newer versions)
if [ "${CC:0:5}" != "gcc6-" ]; then
	CC="gcc6-$CC"
	HOSTCC="gcc6-gcc"
	CROSS_COMPILE="gcc6-$CROSS_COMPILE"
fi

Then add gcc6 to the kernel's makedepends line.

Technical detail: the if... guard around setting the variables is necessary, because the CC and CROSS_COMPILE variables extend themselves. abuild will parse the APKBUILD a second time while running the package() step (inside fakeroot). So without the if statement, we will end up with CC="gcc6-gcc6-gcc" instead of CC="gcc6-gcc" which gets problematic if you are calling make to install kernel modules in the package section (as done in linux-asus-tf101 for example). Interestingly, only CC and CROSS_COMPILE gets passed through, hence we can't simply check the HOSTCC variable.

Use the newest GCC from Alpine

Let's say you are using a device that has already been packaged, and you want to figure out if it also boots when compiled with a newer compiler.

Replace these lines:

# Compiler: this kernel was only tested with GCC6. Feel free to make a merge
# request if you find out that it is booting working with newer GCCs as
# well. See <https://postmarketos.org/vendorkernel> for instructions.
if [ "${CC:0:5}" != "gcc6-" ]; then
	CC="gcc6-$CC"
	HOSTCC="gcc6-gcc"
	CROSS_COMPILE="gcc6-$CROSS_COMPILE"
fi

with the following ones:

# Compiler: latest GCC from Alpine
HOSTCC="${CC:-gcc}"
HOSTCC="${HOSTCC#${CROSS_COMPILE}}"

Then remove the gcc6 package from the makedepends line.

Afterwards, remove the compiler-gcc6.h file from the aport folder, and from the source line. Instead you will probably need other patches as linked here. First try compiling without patches, then add one patch at a time to fix a specific problem. As usually, with pmbootstrap checksum, you can regenerate the checksums at the bottom of the file, this needs to be done whenever you change source.

When you made it boot successfully, please increase the pkgrel and make a merge request.

heimdall-isorec

If you have a device that only boots with heimdall-isorec, you will need to adjust your linux APKBUILD as follows:

  • add busybox-static-armhf to makedepends
  • copy the "init" file from linux-samsung-i9100 and customize the partition
  • add "init" to source= in the APKBUILD
  • adjust your prepare() like it's done in linux-samsung-i9100 and adjust the paths in there

You can search for more examples of heimdall-isorec deviecs with grep:

$ grep -r 'deviceinfo_flash_method="heimdall-isorec"' aports
aports/device/device-samsung-i9070/deviceinfo:deviceinfo_flash_method="heimdall-isorec"
aports/device/device-samsung-i9100/deviceinfo:deviceinfo_flash_method="heimdall-isorec"

See also