Jump to content

Samsung Exynos 7885/Mainlining

From postmarketOS Wiki

Prepare device package

Since a kernel package doesn't exist for the Exynos 7885 family yet, you need to add linux-postmarketos-exynos7870 in depends. It will be used for kernel packaging with envkernel, because the packaging procedure is similar.

It is recommended to set deviceinfo_create_initfs_extra="true" in: ~/.local/var/pmbootstrap/cache_git/pmaports/device/[downstream or testing]/device-name/deviceinfo to avoid errors related to ramdisk being too big.

When preparing the port for mainline, a new device info should be created, but for testing only kernel builds, it can be added to downstream.

This folder is created after launching pmbootstrap init.

Download kernel sources and additional tools

  1. Clone the close-to-mainline kernel source git repository:
    $ git clone https://gitlab.com/HenriDellal/linux-exynos7885.git linux
    
    This repository has three branches:
  1. Download the downstream kernel source;
  2. Clone uniLoader:
    $ git clone https://github.com/ivoszbg/uniLoader.git
    

uniLoader porting

See also: UniLoader

Example of porting can be seen in this commit: https://github.com/ivoszbg/uniLoader/commit/b92c92452bef0443077566ffab6580cf1e680fe3

It can be done in following steps:

  • Copy board file from any working 7885 device (e.g. board/samsung/board-jackpotlte.c) and modify codename and framebuffer values (you need to change width and height only)
  • Add device entry to board/Kconfig and change default values for following options (refer to the uniLoader page for how to get these values):
    • PAYLOAD_ENTRY - memory address where kernel is loaded;
    • RAMDISK_ENTRY - memory address where ramdisk is loaded, can be found in downstream as linux,initrd-start property (this can be also extracted from the device tree);
    • FRAMEBUFFER_BASE - 0x0ec000000 for all 7885 devices;
    • FRAMEBUFFER_WIDTH, FRAMEBUFFER_HEIGHT, FRAMEBUFFER_STRIDE - self-explanatory.

After that, add rule to build board file for your device in board/Makefile and create uniLoader defconfig in configs/

Testing if uniLoader works

This step is optional. The tools unpack_bootimg and mkbootimg are available here: https://github.com/LineageOS/android_system_tools_mkbootimg/tree/lineage-23.0

You can test if uniLoader works by repacking any working boot image with uniLoader.

To get an example of mkbootimg command, use --format mkbootimg
$ unpack_bootimg --boot_img boot.img --out unpacked-boot-img --format=mkbootimg

Use extract-dtb to get separate Image and dtb files, then copy the files from unpacked image to the uniLoader blobs folder:

$ cp unpacked-boot-img/Image uniLoader/blob/Image
$ cp unpacked-boot-img/dtb uniLoader/blob/dtb
$ cp unpacked-boot-img/ramdisk uniLoader/blob/ramdisk
Replace a105f_defconfig with yours in this command
$ make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- -j$(nproc) a105f_defconfig
$ make ARCH=aarch64 CROSS_COMPILE=aarch64-linux-gnu- -j$(nproc)
Create empty_ramdisk because the ramdisk is already in the uniLoader binary
$ touch empty_ramdisk
$ mkbootimg --header_version 1 --kernel uniLoader --ramdisk empty_ramdisk --pagesize 0x00000800 --base 0x00000000 --kernel_offset 0x10008000 --ramdisk_offset 0x11000000 --second_offset 0x10f00000 --tags_offset 0x10000100 --out boot.img

Writing minimal DTS

Note Before you start, it is recommended to switch to either exynos7885 or a10 branch and then create a new branch, commit your changes afterwards so your work is not lost and some changes can be reverted

In the folder: linux/arch/arm64/boot/dts/exynos/, create a new minimal dts file, like the one in the example below:

// SPDX-License-Identifier: GPL-2.0
/dts-v1/;
#include "exynos7885.dtsi"

/ {
	model = "Samsung Galaxy A10";
	compatible = "samsung,a10", "samsung,exynos7885";
	chassis-type = "handset";

	chosen {
		#address-cells = <2>;
		#size-cells = <1>;
		ranges;
        
        stdout-path = "fb0";
        
		fb0: framebuffer@ec000000 {
			compatible = "simple-framebuffer";
			reg = <0x0 0xec000000 (720 * 1520 * 4)>;
			width = <720>;
			height = <1520>;
			stride = <(720 * 4)>;
			format = "a8r8g8b8";
		};
	};

	reserved-memory {
		#address-cells = <2>;
		#size-cells = <1>;
		ranges;

		framebuffer_region@ec000000 {
			reg = <0x0 0xec000000 (720 * 1520 * 4)>;
			no-map;
		};
        
        abox_rmem: memory@e9400000 {
			reg = <0x0 0xe9400000 0x400000>;
		};
	};

	memory@80000000 {
	    device_type = "memory";
		reg = <0x0 0x80000000 0x3da00000>,
		      <0x0 0xc0000000 0x40000000>;
	};
};

&oscclk {
    clock-frequency = <26000000>;
};

Change model and compatible for your device, as well as framebuffer width and height. &oscclk and memory nodes need to be checked against downstream.

If you have UART, you can change stdout-path to serial by changing stdout-path to &serial_2 and enable serial_2 node by adding this node override to the dts:

&serial_2 {
	status = "okay";
};

Now you can add a rule in arch/arm64/boot/dts/exynos/Makefile to build the dts and start building the kernel.

Building kernel

To create the kernel config, run

$ make defconfig exynos7870.config exynos7885.config

Using uniLoader makes the cmdline set by mkbootimg useless, so if you want to e.g. disable splash, add this configuration to exynos7885.config fragment or already compiled .output/.config as CONFIG_CMDLINE option. After the kernel build is ready, package the kernel:

$ pmbootstrap build --force --envkernel linux-postmarketos-exynos7870

Creating boot image

To build uniLoader you need to have gcc-aarch64-linux-gnu installed (check your distro for the exact name).

Build the device package if you haven't built it yet, then run pmbootstrap export to get the initramfs.

Now, copy output files to uniLoader and create boot.img

$ cp linux/.output/arch/arm64/boot/Image uniLoader/blob/Image
$ cp linux/.output/arch/arm64/boot/dts/exynos/CHANGEME.dtb uniLoader/blob/dtb # dtb is a file, not a folder
$ cp /tmp/postmarketOS-export/initramfs uniLoader/blob/ramdisk
Clean the old uniLoader binary
$ cd uniLoader
$ [ -f uniLoader ] && rm uniLoader

For the next steps, make sure to deactivate envkernel:

The next command can be skipped if already done during uniLoader testing.
$ make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- -j$(nproc) a105f_defconfig
Build the uniLoader binary
$ make ARCH=aarch64 CROSS_COMPILE=aarch64-linux-gnu- -j$(nproc)

Replace a105f_defconfig with the defconfig you have created, if necessary.

Now, use mkbootimg to create boot.img (example is in the uniLoader section).