Booting real mainline Linux - Fedora 44 aarch64 with a full KDE Plasma desktop -
natively on the Samsung Galaxy Tab S6 Wi-Fi (SM-T860, codename gts6lwifi,
Qualcomm SM8150 / Snapdragon 855). Installed on the internal UFS. Not an Android
chroot, not a container, not postmarketOS-as-a-dependency - a hand-integrated
mainline kernel driving a real desktop userspace, with GPU acceleration, working
multitouch, working Wi-Fi, and a USB-networking lifeline.
This repository is the shareable, reproducible subset of that project: the boot method, the device tree and kernel work, per-subsystem bring-up guides, packaging and analysis tooling, and the full technical write-ups. Samsung's SM8150 tablets have no turn-key mainline path, and several of the walls here (the locked ABL boot handoff, a UFS clock that lies about being off, a display pipe you must not touch, a Wi-Fi carveout pointed at firmware-owned memory that hard-locked the whole SoC) cost real time - this exists so the next person doesn't repeat them.
Sister project: the Galaxy S20 Ultra (
z3s, Exynos 990) reached a full GPU-accelerated KDE Plasma desktop first. The methodology transfers (stock DT first, USB/serial lifeline, one subsystem per boot, hash before every flash, simpledrm + render-only GPU); the hardware does not - the S20 is Exynos with anlk3rd/uniLoader chain, this tablet is Qualcomm with a completely different boot story.
No Samsung/Qualcomm firmware, no partition dumps, no efs/sec_efs/IMEI/serial, no
stock images are in this repo. Every firmware blob the port needs is extracted from
your own device - see firmware/README.md. The .gitignore
is deliberately aggressive about this.
A daily-drivable desktop is up, and as of 2026-08-29 it is on the network over its own Wi-Fi. One subsystem remains open: the native display pipe (and with it panel brightness and DPMS), which needs kernel fixes newer than the 6.12 tree in use. S Pen has not been started. The project has three layers; layers 1 and 3 are done and layer 2 is a working mainline kernel with most of the SoC brought up.
| Layer | Goal | Status |
|---|---|---|
| 1. Boot handoff | Samsung ABL -> Project Aloha SM8150 UEFI -> systemd-boot | SOLVED |
| 2. Kernel | mainline SM8150 Image + gts6lwifi DTB, EFI-stub booted |
working (6.12) |
| 3. Userspace | Fedora 44 aarch64 + KDE Plasma on internal UFS | running |
| Subsystem | Status | Notes |
|---|---|---|
| Boot handoff (Aloha UEFI -> systemd-boot on cache ESP) | working | Volume-Down = fastboot; iterate by re-flashing the cache ESP |
| UFS internal storage | working | needed a BRANCH_HALT_SKIP fix on the UFS and USB branch clocks (Aloha TZ lies about halt status) |
| Display (KDE Plasma visible) | working | simpledrm on the untouched bootloader framebuffer @2560x1600; do not enable the DSI/DPU pipe |
| Multitouch | working | STM fts1ba90a (Samsung SEC-TS protocol), GPI-DMA on QUP2 |
| GPU acceleration | working | Adreno 640 render-only via msm/freedreno, Mesa kmsro pairs it with simpledrm; Samsung-signed zap shader |
| USB networking + SSH | working | RNDIS+ACM configfs gadget -> root SSH over USB (the dev lifeline) |
| Wi-Fi (WCN3990) | working | 802.11ac, 866.7 MBit/s link rate (VHT-MCS 9, 80 MHz, 2 streams), auto-connects at boot; fixed by relocating wlan_mem into HLOS-owned DDR - see docs/WIFI.md |
| Native display pipe (DPU/DSI) | in progress | dual-DSI ANA38401 panel; needs the >=6.16 bonded-cmd-mode DPU fixes (6.18 tree staged). Only hardware brightness and DPMS depend on it - software dimming and idle blanking both work today |
| Brightness | working | software dimming via KWin (Plasma 6), since the panel has no hardware backlight interface. Measured cost of the whole display on a dark desktop: ~0.1 W |
| Power button, shutdown, reboot | working | power key is the PMIC PON block, not a GPIO; power-off and reboot go through PMIC PS_HOLD because PSCI SYSTEM_OFF/SYSTEM_RESET both hang on this firmware - see docs/POWER.md |
| Fuel gauge + charge detection | working | the battery is not on the Qualcomm PMIC at all - Samsung fits an SM5705 charger + fuel gauge + MUIC on I2C. Driver written from scratch: real state of charge, voltage, OCV and current, so charging is detected properly |
| USB host - keyboard, SSD, hub | working | dual-role port with a runtime usb-role switch, VBUS sourced from the SM5705 boost. A 4 TB bus-powered SSD runs off it - at USB 2.0; SuperSpeed is still unsolved, see docs/USB_HOST.md |
| Suspend / resume / idle sleep | working | s2idle, resume in 1.5 s, touchscreen survives it, power button wakes. Fedora ships sleep.target/suspend.target masked, which makes logind report "Access denied"; and PowerDevil ignores its profile config entirely, so idle sleep is handled by tools/tabs6-idled.py - see docs/SLEEP.md |
| Charge control | working | 2000 mA in / 2000 mA to the battery, maintained because the registers reset when the cable moves. Applies at boot - it used to start two minutes late, so the tablet charged at 500 mA through the busiest part of every boot - see docs/BATTERY.md |
| Screenshots | working | power + volume-down chord, and a button in the system tray; both copy to the clipboard and save to ~/Pictures/Screenshots - see docs/DESKTOP.md |
| Surviving distro upgrades | working | RPM silently reverts the lock-screen and keyboard customisations (package-owned, not %config, no .rpmsave). tabs6-desktop-patches.service re-applies them every boot |
| Bluetooth (WCN3990 UART) | working | hci_qca on a UART mainline never declared (0xc8c000 is only i2c13/spi13 upstream). Firmware and the BD address both come off the device itself - see docs/BLUETOOTH.md |
| Audio | works | speakers, via the ADSP + APR + Secondary TDM to four Cirrus CS35L41 amps, with an ALSA UCM profile so the desktop gets a real sink. Headphone jack not started - see docs/AUDIO.md |
| Hardware buttons | working | power and volume down are PMIC PON inputs; volume up is pm8150L gpio12, not the Surface Duo's pm8150_gpios 6 that was inherited and emitted nothing at all - see docs/DESKTOP.md |
| Boot time | ~38 s cold power-on to desktop | 23.9 s of that is controllable (was 56.6 s); the rest is Samsung's bootloader, which varies 8-23 s boot to boot. See the boot section of docs/DEVLOG.md |
| Microphones | working | Cirrus CS48L33 on SPI over Quinary MI2S, exposed to the desktop as a PipeWire source declared directly (a UCM capture device would take the card down). First capture after PipeWire starts can come back empty - see docs/AUDIO.md |
| Sensors + auto-rotate | working | LSM6DSO accelerometer behind the SLPI sensor DSP: PAS boot, hexagonrpcd serving the registry over FastRPC, libssc + iio-sensor-proxy 3.9, and a small session daemon because KWin will not auto-rotate a simpledrm output - see docs/SENSORS.md |
| Rollback + power logging | working | LAST KNOWN GOOD boot entry with tools/tabs6-kernel snapshot/rollback, fuel gauge logged to the journal every 5 min and around suspend - see docs/DAILY_DRIVER.md |
| S Pen | not done | see docs/PORT.md |
Read docs/PORT.md for the full hardware map and
docs/DEVLOG.md for the chronological story (what was tried, what
failed, what hurt, what we learned).
Every wall on this device fell to the same discipline, taken from the S20 port:
- Never touch the bootloader display pipe. simpledrm rides the framebuffer the bootloader already set up; the desktop is GPU-accelerated by a render-only GPU node (Adreno) paired to simpledrm via Mesa's kmsro. Enabling the real DSI/DPU pipe corrupted scan-out every time until a >=6.16 kernel.
- Keep a lifeline. First a fastboot/cache-ESP flash loop, then a root serial console over USB ACM, then root SSH over USB RNDIS. Every risky change is made over the lifeline, not by typing on the tablet.
- One subsystem per boot, verify the artifact. Build the
.dtb/module, grep the built artifact for the change before shipping it,md5sumbefore every flash, and bring up exactly one thing at a time. - Read the device's own extracted device tree first. The answers (panel timings, touch protocol, Wi-Fi supplies, firmware paths) were in Samsung's own downstream DT, not upstream docs.
- Check who owns a reserved-memory region before asking TrustZone to grant a
device permissions on it. Addresses inherited from an SoC
.dtsican land inside a vendor carveout that belongs to the firmware loader rather than to HLOS, and HLOS cannot give away memory it does not own. Theqcom_scm_assign_mem()call then returns-22, and the tempting workaround - skipping the assignment - leaves the peripheral running against memory it has no rights to. The eventual failure looks nothing like a memory problem: here it was an instant, silent, log-less SoC fabric lockup on the first firmware write, which pointed suspicion at the wrong step for days. Both Wi-Fi andrmtfson this device hit the identical bug; the fix in each case was a single line of device tree.
Samsung's ABL will not directly execute a mainline Image, and Samsung SM8150 has no
lk2nd target. The working path is Project Aloha (mu_aloha_platforms /
DualBootKernelPatcher): an SM8150 edk2/Project-Mu UEFI firmware volume is injected
into the stock Samsung boot kernel, so ABL boots the stock container which
chain-loads UEFI -> its BDS scans FAT partitions for \EFI\BOOT\BOOTAA64.EFI ->
systemd-boot -> the mainline EFI-stub Image + gts6lwifi DTB. Earlier attempts fell
back to stock Android because the boot image was repacked with a packer that
destroyed the Samsung SEANDROIDENFORCE/AVB trailer ABL requires; the fix is
magiskboot repack (which preserves it) paired with a verification-disabled
vbmeta. See docs/BOOT_METHOD.md.
Model SM-T860 (Wi-Fi), codename gts6lwifi
SoC Qualcomm SM8150P v2 / Snapdragon 855
Stock firmware T860XXS5DWH1 (Android 12, One UI 4.1), kernel 4.14.190
Bootloader unlocked; Project Aloha SM8150 UEFI flashed to `boot` (sda20)
Storage 128 GB UFS; Fedora root on userdata (sda30, ext4)
Boot ESP cache (sda27, FAT32) - systemd-boot + Image + DTB
Display dual-DSI ANA38401 / AMSA05RB06 WQXGA, 2560x1600
Touch STM FTS1BA90A (Samsung SEC-TS), i2c on QUP2 SE17
GPU Adreno 640
Wi-Fi/BT Qualcomm WCN3990 (ath10k_snoc / SNOC)
docs/
DEVLOG.md The full chronological story.
PORT.md Hardware map and per-subsystem status.
BOOT_METHOD.md Project Aloha SM8150 handoff, reproducible build.
AVB_ANALYSIS.md Byte-level boot-image / AVB trailer analysis.
UFS.md The lying-halt-bit clock fix that unlocked internal storage.
DISPLAY.md simpledrm-on-bootloader-framebuffer strategy (and what NOT to do).
GPU.md Adreno 640 render-only + Mesa kmsro bring-up.
TOUCH.md fts1ba90a + GPI-DMA bring-up.
USB_NETWORKING.md The RNDIS+ACM lifeline (SSH + serial over USB).
WIFI.md WCN3990 bring-up: modem boot, ath10k QMI, and the wlan_mem fix.
DESKTOP.md Making it usable: on-screen keyboard with real modifier keys,
zram, touch text selection, Electron/Wayland, routing, the
hardware buttons and screenshot chord, a tray screenshot
button, and re-applying the patches RPM upgrades revert.
USB_HOST.md Host mode, VBUS from the SM5705, and why SuperSpeed
does not work yet.
BATTERY.md The SM5705 fuel gauge, why pm8150b is a closed door, and
how to measure power without fooling yourself.
POWER.md Power button, shutdown and reboot: why PSCI cannot be used
here, and why the console lies about it.
CPU.md Topology (4 efficiency + 3 performance + 1 prime), hardware
DVFS and EAS - the subsystem that needed no work, and why.
AUDIO.md Why audio does not work yet: the real (Cirrus) hardware, and
the exact TrustZone call that refuses the ADSP.
BLUETOOTH.md WCN3990 over UART: the undeclared UART personality, the
alias the driver needs, the firmware name it derives, and the
controller that has no address of its own.
SLEEP.md Suspend, wake and the clock: the masked sleep targets, the
touchscreen resume fix, why the RTC cannot be set, and why
idle sleep is not PowerDevil's job here.
kernel/
dts/ sm8150-samsung-gts6lwifi board device tree.
config/ The kernel .config used for the running build.
patches/ Out-of-tree fixes: PMIC PS_HOLD power-off/reboot and SMPL
disarm, SPMI denied-revid tolerance, ADC battery capacity and
status, dwc3 userspace role control, and the fts1ba90a resume
ready-wait removal.
drivers/ Driver sources written for this port: the SM5705 fuel gauge and
the fts1ba90a touchscreen.
tools/ Boot-image AVB/trailer analyzers and Odin tar packers, plus the
runtime daemons and helpers this port needs: tabs6-powerkeyd
(power button + screenshot chord), tabs6-idled (idle suspend,
because PowerDevil will not), tabs6-charge (charge current),
tabs6-screenshot / tabs6-screenshot-tray (a tray button),
tabs6-desktop-patches (re-apply what upgrades revert), usb-role.
rootfs/ Files that live outside the kernel: the maliit keyboard QML, the
patched Plasma lock screen, systemd units and the .desktop entry.
firmware/ How to extract SM8150/Samsung firmware from your OWN device. No blobs.
Only ever write the boot, vbmeta, and cache partitions (and the userdata
rootfs you choose). Never flash BL, XBL, ABL, TZ, modem, EFS, PIT, or repartition
- Samsung KG/Knox and a wrong firmware write can hard-brick. Keep a full stock Odin
restore on hand. Never publish
efs,sec_efs, or IMEI/serial data.
Kernel/DTS/driver work is derived from Linux and is GPL-2.0. Documentation is shared under the same repo license. Proprietary firmware is not included and is not covered.