Jump to content

Samsung Exynos 7885/Mainlining

From postmarketOS Wiki

Prepare device package

Since linux-postmarketos- package doesn't exist for 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" to avoid errors related to ramdisk being too big.

Download kernel sources and additional tools

1. Clone close-to-mainline kernel source git repository

git clone https://gitlab.com/HenriDellal/linux-exynos7885.git linux

This repository has three branches:

- exynos7870/6.15-rc1 is a copy of exynos7870 mainline kernel fork at https://gitlab.com/exynos7870-mainline/linux

- exynos7885-base includes VDavid003's patches from https://github.com/VDavid003/linux/tree/linux-6.11-rc2-7885 rebased on top of master branch

- 6.15-rc1-a10 is a WIP tree for Galaxy A10 which includes some additional patches for 7885, so you may want to take a look at that branch too

2. Download downstream kernel source, e.g. https://github.com/ResurrectionRemix-Devices/android_kernel_samsung_exynos7885

3. Clone uniLoader

git clone https://github.com/ivoszbg/uniLoader.git

uniLoader porting

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

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.

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/

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

# --format mkbootimg to get example of mkbootimg command
unpack_bootimg --boot_img boot.img --out unpacked-boot-img --format=mkbootimg

Use extract-dtb to get separate Image and dtb files

Now, copy files from unpacked image to 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 ramdisk is already in 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


Example:

// 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 dts

&serial_2 {
	status = "okay";
};

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

Building kernel

In order to build, you need to follow envkernel guide at Compiling_kernels_with_envkernel.sh with following considerations:

  • To create kernel config, run
make defconfig exynos7870.config exynos7885.config
  • Using uniLoader makes 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 kernel build is ready, use linux-postmarketos-exynos7870 to package the kernel
pmbootstrap build --force --envkernel linux-postmarketos-exynos7870

Creating boot image

Build device package if you didn't build it yet, then run pmbootstrap export to get 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
cp /tmp/postmarketOS-export/initramfs uniLoader/blob/ramdisk
# cleaning old uniLoader binary
cd uniLoader
[ -f uniLoader ] && rm uniLoader
# next command can be skipped if already done during uniLoader testing
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- -j$(nproc) a105f_defconfig
# build uniLoader binary
make ARCH=aarch64 CROSS_COMPILE=aarch64-linux-gnu- -j$(nproc)

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