device-motorola-rtwo: initramfs debug shell, panel revive, power key

- deviceinfo / modules-initfs: boot through the U-Boot chainload, modules
  needed in the initramfs for the display, USB and the DSPs.
- initfs hooks: dropbear/telnet debug shell over USB networking.
- rtwo-panel-revive.service: blank/unblank the NT37705 if it comes up
  dead from the ABL handoff.
- logind-power-key.conf: ignore the power key (handled by the dashboard).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DnHwDU5yL8L6qgPEN5CV5m
This commit is contained in:
2026-09-26 20:02:56 -03:00
co-authored by Claude Opus 5.5
parent 8a87204d48
commit c028f63183
10 changed files with 497 additions and 12 deletions
@@ -0,0 +1 @@
/usr/sbin/dropbear
+94 -6
View File
@@ -2,13 +2,21 @@
maintainer="snlavaise <snlavaise@gmail.com>" maintainer="snlavaise <snlavaise@gmail.com>"
pkgname=device-motorola-rtwo pkgname=device-motorola-rtwo
pkgver=1 pkgver=1
pkgrel=15 pkgrel=36
pkgdesc="Motorola Moto Edge 40 Pro" pkgdesc="Motorola Moto Edge 40 Pro"
url="https://postmarketos.org" url="https://postmarketos.org"
arch="aarch64" arch="aarch64"
license="MIT" license="MIT"
depends=" depends="
android-tools android-tools
busybox-extras
dropbear
firmware-motorola-rtwo-adsp
firmware-motorola-rtwo-cdsp
firmware-motorola-rtwo-gpu
linux-firmware-ath12k
linux-firmware-qcom
linux-firmware-rtw88
linux-postmarketos-qcom-sm8550 linux-postmarketos-qcom-sm8550
postmarketos-base postmarketos-base
soc-qcom soc-qcom
@@ -17,13 +25,47 @@ makedepends="devicepkg-dev"
source=" source="
deviceinfo deviceinfo
modules-initfs modules-initfs
initfs-hook.sh
initfs-hook-cleanup.sh
30-dropbear.files
debug-telnetd.service
logind-power-key.conf
rtwo-panel-revive.sh
rtwo-panel-revive.service
" "
options="!archcheck !check" options="!archcheck !check"
# TODO (as hardware comes up): # TODO (as hardware comes up):
# - firmware-motorola-rtwo (WiFi/BT/modem/GPU blobs, generate from the # - WiFi (WCN7850/ath12k via pcie0): links up, enumerates fine, and the real
# stock image with 'pmbootstrap ...' or extract manually) # Motorola calibration (bdwlan.elf.rtwo.epa) is fully extracted and
# - firmware-qcom-adreno-* for the Adreno 740 (GPU / mesa-vulkan-freedreno) # verified byte-perfect -- but it ALWAYS fails at the QMI board-data
# transfer itself (qmi failed to load board data file:-110, ETIMEDOUT),
# confirmed a dead end after exhaustive investigation (re-verified
# 2026-09-22, no format/corruption issue found). Workaround: a generic
# Qualcomm board-id=44 blob as the LEGACY board.bin (not board-2.bin) at
# ath12k/WCN7850/hw2.0/board.bin gets wlan0 to appear, but hits a
# separate, deeper WMI/HTC credit-exhaustion bug in ath12k_mac_start()
# (PMF_QOS never gets a second tx credit) -- 7 hypotheses ruled out with
# evidence, cross-referenced against a real LKML thread with the exact
# same symptom on unrelated hardware. Looks like a genuine unfixed
# upstream kernel bug, not something fixable from this device's side.
# Draft bug report at ~/pmos/ath12k-bug-report-wmi-credit-exhaustion.md,
# not sent (needs explicit go-ahead before any public post).
# - USB WiFi dongle (RTL8723DU) as an alternative to onboard WCN7850:
# CONFIG_RTW88_8723DU=m already enabled, needs linux-firmware-rtw88
# (added below) for rtw88/rtw8723d_fw.bin. Requires &usb_1 in host mode
# (now the default, see the .dts) + a self/externally-powered USB-C hub.
# - Bluetooth (qcom,wcn7850-bt) not wired in the .dts yet, same PMU node.
# - firmware-motorola-rtwo: ADSP/CDSP (remoteproc, pmic-glink battmgr/UCSI
# run on the ADSP) and the GPU zap shader are pulled in as dependencies.
# -hexagonfs (FastRPC libs for hexagonrpcd, e.g. sensors) is left out
# until hexagonrpcd is actually set up. Modem blobs still TODO.
# - GPU (Adreno 740): WORKING 2026-09-25 (freedreno FD740, OpenGL 4.6/GLES).
# a740_sqe.fw + gmu_gen70200.bin come from linux-firmware-qcom; the zap
# shader MUST be Motorola's signed one (firmware-motorola-rtwo-gpu,
# qcom/sm8550/motorola/rtwo/a740_zap.mbn) -- the generic
# qcom/sm8550/a740_zap.mbn in linux-firmware-qcom is QRD-signed and is
# rejected on a retail device.
# - make-dynpart-mappings once super partitions are mapped # - make-dynpart-mappings once super partitions are mapped
# - soc-qcom-modem, qbootctl (A/B slot handling) once booting # - soc-qcom-modem, qbootctl (A/B slot handling) once booting
@@ -33,9 +75,55 @@ build() {
package() { package() {
devicepkg_package $startdir $pkgname devicepkg_package $startdir $pkgname
# devicepkg_package handles initfs-hook.sh natively (installs it to
# usr/share/mkinitfs/hooks/00-$pkgname.sh), but has no generic handler
# for extra ".files" manifests (unlike modules-initfs) -- install this
# one by hand, same mechanism postmarketos-mkinitfs-hook-debug-shell
# uses for telnetd's own 20-debug-shell.files.
install -Dm644 "$srcdir"/30-dropbear.files \
"$pkgdir"/usr/share/mkinitfs/files/30-dropbear.files
# Mata el dropbear del debug-shell antes de switch_root -- si no, sigue
# vivo pegado al puerto 22 y sshd.service de la rootfs real nunca puede
# bindear (ver comentario grande en el propio initfs-hook-cleanup.sh).
install -Dm755 "$srcdir"/initfs-hook-cleanup.sh \
-t "$pkgdir"/usr/share/mkinitfs/hooks-cleanup/
# Debug telnet shell de la rootfs REAL (no del initramfs -- ver el
# comentario grande en el propio .service). Se habilita a mano con el
# symlink porque esto no es un paquete "de verdad" con postinstall,
# es un hack de bring-up.
install -Dm644 "$srcdir"/debug-telnetd.service \
"$pkgdir"/usr/lib/systemd/system/debug-telnetd.service
install -d "$pkgdir"/usr/lib/systemd/system/sysinit.target.wants
ln -s ../debug-telnetd.service \
"$pkgdir"/usr/lib/systemd/system/sysinit.target.wants/debug-telnetd.service
# Boton de encendido: ignorar la pulsacion corta (ver el .conf).
install -Dm644 "$srcdir"/logind-power-key.conf \
"$pkgdir"/usr/lib/systemd/logind.conf.d/50-rtwo-power-key.conf
# Panel negro en frio: blank/unblank desde el rootfs si el panel salio
# muerto (el initfs-hook no alcanza cuando msm engancha el display
# despues del switch_root). Ver rtwo-panel-revive.sh.
install -Dm755 "$srcdir"/rtwo-panel-revive.sh \
"$pkgdir"/usr/libexec/rtwo-panel-revive
install -Dm644 "$srcdir"/rtwo-panel-revive.service \
"$pkgdir"/usr/lib/systemd/system/rtwo-panel-revive.service
install -d "$pkgdir"/usr/lib/systemd/system/multi-user.target.wants
ln -s ../rtwo-panel-revive.service \
"$pkgdir"/usr/lib/systemd/system/multi-user.target.wants/rtwo-panel-revive.service
} }
sha512sums=" sha512sums="
2a152f5a33e503f255fb3e0201f204e2066a95a763d1bf517f99f61821c2db66da6f1e0132ce24cdf420502f7831aad4a9e25b2c6d020403b3974ef63b2fb399 deviceinfo bc4d018a852d900fd9932bf881e81b1eae49f416dbafe212a4fa6e26c05f812cef64ca19b8adb69225331468ac1535d568f547e2e9f4ea296ed37a8c6340e4ad deviceinfo
44085ab61668201f3091046586a333f017bc0e11af7624d7bd5bfe13e98eed3943a2daa02922db48ce8cac8de3c08622ac2c32cf959daf96bd416f217863f62c modules-initfs 298e836000c92db16ee4fe3ce4899eb13e9099983ee0fabff1e98c494e8a1883cef327a3ddce5c1ef98e0043b804aae8506438630b3bb144f92ded89c129668b modules-initfs
eccadc2bf5713ff9df16234c0d9daf1364bdcd88fb9709df012035719e2d5e44d658ccaf87a9bb1a76d433861c37162cdfef999fbe1093d6d0d32eb849dbdfe8 initfs-hook.sh
cb8ea3e0da0219fdf77f6def6d7a77157a4ef152cc434e3d282457647784b05e7152cf1028d00a5534ae721a38d3c24047edd1dfbaa6fd34290c3823d4cf54c0 initfs-hook-cleanup.sh
07ceb61f64d99fdbc815795beae9014dc22177d5622d015db79849faed5c14225b280d83dbac174957089344d2e857595b046683cee033d4acd76fdbf7114eab 30-dropbear.files
3511918144a3130d9ac64df78cfd9a02e3ed5ee11f45f0b3b872f2e42504434b3c3197b47797fad2510ff1e7ae7822813a8710eb4830f324b5cb101742fde062 debug-telnetd.service
bab2fbd6078d9ac342708a1e85b7f5d5cff5e1105b5bd633517bf27f9a61499b9903c9aa17d0142c82f8cd874cd9ac03d1ddb33b8c66e40094a7271dd54c0502 logind-power-key.conf
59db456c9ba57352aa8bff0e8ca73bd5b1c5c7f6f9c57e382e5bdd68791c9324d705210e77aa4e945e3869ab11dc1066e1a290c3750a27772c89f83731d28609 rtwo-panel-revive.sh
8e374a7304f8648d33d9087149e53efc5b09ffe1f7bc07b8b10521b7b1163e4787b56ecf3d2871629b1cfcc0037c1c15d084b514412e5e0a90ff66fd8e83b088 rtwo-panel-revive.service
" "
@@ -0,0 +1,21 @@
[Unit]
# Bring-up diagnostic (2026-09-18): shell sin ninguna dependencia de
# cripto/entropia, para no quedar a ciegas si sshdgenkeys.service (ssh-keygen
# -A, bloqueado en getrandom() si el CRNG nunca termina de inicializar) o
# cualquier otra cosa de multi-user.target se cuelga antes de que sshd
# arranque. DefaultDependencies=no + WantedBy=sysinit.target: arranca lo mas
# temprano posible, en paralelo con todo lo demas, sin esperar a basic.target
# ni a nada que dependa de el. Misma IP/puerto que el debug-shell del
# initramfs (pmos.debug-shell), a proposito, para no tener que recordar dos
# direcciones distintas.
Description=Debug telnet shell (bring-up, sin dependencias de cripto)
DefaultDependencies=no
[Service]
Type=simple
ExecStart=/usr/sbin/telnetd -b 172.16.42.1:23 -F -l /bin/sh
Restart=always
RestartSec=1
[Install]
WantedBy=sysinit.target
+202 -6
View File
@@ -19,8 +19,20 @@ deviceinfo_screen_height="2400"
deviceinfo_getty="ttyMSM0;115200" deviceinfo_getty="ttyMSM0;115200"
deviceinfo_no_framebuffer="true" deviceinfo_no_framebuffer="true"
# Small base initramfs (fits init_boot) + a separate initramfs-extra. # UN SOLO initramfs, sin initramfs-extra. Es lo que hace que
deviceinfo_create_initfs_extra="true" # 'pmos.debug-shell' sirva de algo: init_2nd.sh (y con el, la rama
# if [ "$debug_shell" = "y" ]; then debug_shell; fi
# ) vive en el paquete de ficheros -extra, o sea DENTRO del rootfs, que en
# este equipo no podemos flashear. Con extra separado, jump_init_2nd() del
# stage 1 es un no-op, la bandera de la cmdline no la lee nadie y el unico
# camino a la shell de depuracion es agotar los 30 s de wait_boot_partition
# -> fail_halt_boot. Fusionandolo, init.sh salta a init_2nd.sh de inmediato,
# que hace setup_udev + setup_usb_network + start_unudhcpd y ENTONCES entra
# en debug_shell: telnet en 172.16.42.1:23 y getty en /dev/ttyGS0 en cuanto
# el USB enumera, sin depender de ninguna particion.
# El coste (initramfs de 3 MiB -> ~15 MiB) ya no importa: con cabecera v2 el
# ramdisk va DENTRO de boot.img, no en init_boot, y boot_a admite 96 MiB.
deviceinfo_create_initfs_extra="false"
# The stock LineageOS boot chain packs both Android-v4 ramdisks with LZ4 # The stock LineageOS boot chain packs both Android-v4 ramdisks with LZ4
# legacy. When the bootloader concatenates our vendor_ramdisk with the # legacy. When the bootloader concatenates our vendor_ramdisk with the
# init_boot ramdisk, a gzip stream after an LZ4-legacy one makes the # init_boot ramdisk, a gzip stream after an LZ4-legacy one makes the
@@ -34,13 +46,197 @@ deviceinfo_initfs_compression="lz4:legacy"
# Lessons folded in from device-motorola-dubai (the closest working # Lessons folded in from device-motorola-dubai (the closest working
# Motorola mainline port) and the stock LineageOS images. # Motorola mainline port) and the stock LineageOS images.
deviceinfo_flash_method="fastboot" deviceinfo_flash_method="fastboot"
# Keep flashing dtbo, and keep it EMPTY. The ABL overlays whatever sits in
# the dtbo partition on top of the DTB it took from vendor_boot, and a stock
# overlay applied to a mainline DTB mangles it - the documented advice for
# mainline on Qualcomm is to erase the dtbo partition or program NULL to it.
# The dtbo.img pmbootstrap generates here is 24 MiB of zeroes (no DTBO magic,
# no entries), so flashing it IS that "program NULL" step: it wipes the
# LineageOS/stock table (32 entries) that a restore-to-stock puts back.
# Do not drop this line expecting the ABL to skip overlays - dropping it
# leaves the stock table in place.
deviceinfo_flash_fastboot_partition_dtbo="dtbo" deviceinfo_flash_fastboot_partition_dtbo="dtbo"
deviceinfo_flash_fastboot_partition_vbmeta="vbmeta" deviceinfo_flash_fastboot_partition_vbmeta="vbmeta"
# 'earlycon' is REQUIRED on Motorola - without it the ABL reboots the # CONSOLA REAL POR UART (2026-09-13, sin framebuffer en el .dts): console=
# phone immediately (see device-motorola-dubai/kernel-cmdline.conf). # apunta ahora a ttyMSM0 (uart7, GENI QUP0/SE7), no a tty0. Ya no hace falta
deviceinfo_kernel_cmdline="console=ttyMSM0,115200n8 earlycon" # el 'ignore_loglevel'+panic=5-como-sustituto-de-consola: si el UART vive,
# vemos todo en tiempo real.
#
# 'earlycon' AGREGADO DE NUEVO (2026-09-13, segunda pasada). Se habia sacado
# a proposito por el riesgo real y documentado de fragilidad en el handover
# clk/earlycon (serie LKML "clk: help OF platforms with their stdout
# (earlycon) clocks during early boot", aun en v6) combinado con la sospecha
# de que DisableHypUartUsageForLogging() (SMC que el ABL llama antes de
# saltar al kernel, ver rtwo-abl-vs-abl-de-referencia) deje el UART en un
# estado raro para un acceso CRUDO y tempranisimo. Pero: 'console=ttyMSM0'
# SOLO (sin earlycon) no muestra nada hasta que el driver real de
# qcom_geni_serial prueba, lo cual exige que GCC y el pinctrl ya hayan
# probado antes - y CADA cuelgue que vimos en este bring-up paso muchisimo
# antes de eso (reset en 1-2s, antes de fbcon). Si el problema sigue siendo
# pre-driver, sin earlycon no veriamos nada, igual que en todos los intentos
# anteriores con framebuffer. Sin argumento usa /chosen/stdout-path (serial0
# -> &uart7, qcom,geni-debug-uart tiene OF_EARLYCON_DECLARE).
#
# 'panic=5': con consola real ya no es indispensable, pero se deja: si
# panickea en vez de colgarse, lo vemos en pantalla Y el registro queda en
# pstore/ramoops para la proxima vez.
# 'pmos.debug-shell': shell de depuracion por USB (telnet 172.16.42.1) con
# dmesg y pstore montados, si se llega al stage 2 del initramfs.
# 'allow_mismatched_32bit_el0' AGREGADO (2026-09-14): AYN Thor (mismo SoC,
# SD8 Gen 2 = SM8550, arranca ABL-directo sin U-Boot igual que nosotros) lo
# lleva en su receta de cmdline. Sin el, en el peor caso el kernel solo
# restringe apps de 32 bits en runtime (no bloquea el arranque segun el
# codigo fuente) - pero es gratis agregarlo: solo relaja una verificacion,
# nunca puede empeorar nada.
# 'console=tty0 ignore_loglevel' AGREGADO (2026-09-17): consola visual sobre
# el framebuffer@b8000000 reagregado al .dts del kernel, ver ese archivo.
# 'console=ttyMSM0,115200n8' SACADO (2026-09-18): no hay UART real
# enganchado en este bring-up, la consola que se usa de verdad es la de
# framebuffer (tty0, ver foto). Se deja 'earlycon' (bare, sin argumento)
# porque igual sale por /chosen/stdout-path sin bloquear nada aunque nadie
# lo lea.
# 'printk.devkmsg=on' AGREGADO (2026-09-21): con systemd.log_target=kmsg
# (ver qcom-phone.env), TODO el log visible en la consola de framebuffer
# sale de que systemd escribe activamente a /dev/kmsg -- inicialmente se
# penso que el kernel (printk.devkmsg=ratelimit por default) era el que
# cortaba esas escrituras con un rate-limit agresivo, disparando "Too many
# messages being logged to kmsg, ignoring" a los ~2-3s de systemd. FALSO,
# confirmado en hardware: con SOLO este flag el freeze sigue exactamente
# igual, misma linea. Se deja de todos modos (no molesta), ver el flag de
# abajo para el fix real.
# 'systemd.log_ratelimit_kmsg=false' AGREGADO (2026-09-21, segundo
# intento): el rate-limit real es del propio systemd, no del kernel --
# write_to_kmsg() en systemd tiene su PROPIO limitador interno para
# escrituras a /dev/kmsg, totalmente independiente de printk.devkmsg.
# Documentado en systemd(1)/kernel-command-line(7) como
# $SYSTEMD_LOG_RATELIMIT_KMSG / systemd.log_ratelimit_kmsg= (boolean,
# default true). CONFIRMADO EN HARDWARE QUE ESTE FLAG TAMPOCO ALCANZA: el
# usuario reportó que después del freeze NO aparece ningún mensaje nuevo,
# ni siquiera los timeouts de WMI del kernel que se repiten cada ~13s
# (esos SÍ se siguen generando en el ring buffer real, confirmado por
# SSH). Descarta cualquier teoría de "se generan menos mensajes" -- el
# framebuffer literalmente deja de refrescarse, sin relación con volumen
# de logging.
# 'cpufreq.default_governor=performance' AGREGADO (2026-09-21, tercer
# intento, DIAGNÓSTICO): el .dts del kernel
# (sm8550-motorola-rtwo.dts líneas 721-754) ya documenta que dispcc
# habilitado por defecto glitchea disp_cc_mdss_mdp_clk_src (el reloj de
# píxeles del MDP que el ABL/U-Boot deja corriendo para seguir escaneando
# el framebuffer heredado), fix aplicado ahí ('&dispcc { status =
# "disabled"; }', confirmado vigente) -- pero el freeze persiste con ese
# fix puesto, así que algo MÁS sigue tocando ese mismo reloj heredado por
# una vía distinta. Hipótesis: GCC comparte una PLL padre con ese reloj de
# píxeles, y el escalado dinámico de cpufreq (que arranca justo cuando el
# boot termina y baja la carga -- la misma ventana donde aparece el
# freeze) la glitchea indirectamente. Este flag fija el governor a
# 'performance' para probar si evita el glitch. CONFIRMADO EN HARDWARE QUE
# TAMPOCO ALCANZA: freeze idéntico con el governor fijo -- descarta
# cpufreq DVFS.
#
# Con 4 hipótesis descartadas con evidencia real (rate limit kernel, rate
# limit systemd, cpufreq, y el mecanismo de dispcc vía otro controlador --
# dmesg | grep WARNING/clk_rcg2/update_config/genpd no muestra nada salvo
# "PM: genpd: Not disabling unused power domains", y el usuario confirmó
# que el freeze pasaba INCLUSO ANTES de que existieran los nodos de WiFi
# en el .dts, descartando PCIe/ath12k), toca dejar de adivinar QUÉ driver
# específico es y aislar CUÁNDO pasa.
# 'systemd.mask=systemd-udev-trigger.service' PROBADO (2026-09-21, cuarto
# intento): CONFIRMADO EN HARDWARE que con esto el freeze DESAPARECE
# (pantalla mostró "emergency mode" en vez de congelarse) -- prueba
# definitiva de que es un driver/módulo cargado durante el coldplug de
# udev, no un timeout de hardware. Pero bloquear el coldplug entero rompe
# el boot normal (cae a emergency mode sin red, probablemente porque el
# descubrimiento de particiones/interfaz USB de red también depende de
# udev). SACADO, reemplazado por el flag de abajo para bisectar sin
# romper el boot.
# 'module_blacklist=gpucc_sm8550,videocc_sm8550,camcc_sm8550' AGREGADO
# (2026-09-21, quinto intento) -- CONFIRMADO EN HARDWARE QUE ES EL FIX:
# con estos 3 bloqueados, boot completo normal (SSH/red ok) y la pantalla
# llega al login prompt sin congelarse. NO se aisló cuál de los tres en
# particular es el culpable real -- el bring-up actual no necesita
# GPU/video-codec/cámara, así que no vale la pena bisectar más por ahora.
# Si en el futuro hace falta reactivar alguno (ej. GPU para aceleración
# gráfica), sacarlo de esta lista de a uno y probar en hardware; si
# individualmente reproduce el freeze, deshabilitarlo a nivel .dts
# (status = "disabled", mismo patrón que dispcc) en vez de blacklistear
# el módulo. FIX VIGENTE.
# 'gpucc_sm8550' SACADO de la lista (2026-09-21) para empezar el
# bisect de a uno, siguiendo el plan de arriba -- es el primer candidato
# porque es el unico de los tres con un caso de uso real a corto plazo
# (aceleracion grafica). El .dts no tiene NINGUN nodo de GPU (no hay
# Adreno/zap-shader, se verifico: sm8550-motorola-rtwo.dts no menciona
# "adreno"/"gpu@" en ningun lado), asi que gpucc queda habilitado por
# defecto desde sm8550.dtsi (como dispcc, ver comentario de &dispcc mas
# abajo) sin ningun consumidor todavia. Si el freeze vuelve, la sospecha
# recae en gpucc_sm8550 y el fix pasa a &gpucc { status = "disabled"; }
# en el .dts en vez del blacklist. videocc_sm8550/camcc_sm8550 SIGUEN
# blacklisteados -- no bisectar los tres a la vez.
# 'videocc_sm8550' SACADO de la lista (2026-09-21, mismo dia, mas tarde):
# reset random confirmado en hardware CON gpucc_sm8550 ya reactivado (asi
# que gpucc queda descartado como causa unica del reset). Leyendo el
# fuente real de gdsc_init() (drivers/clk/qcom/gdsc.c) contra los GDSC de
# cada controlador: video_cc_mvs0_gdsc/mvs1_gdsc tienen la flag
# HW_CTRL_TRIGGER (control autonomo por hardware del colapso de energia),
# la MISMA clase de flag que mdss_gdsc/mdss_int2_gdsc de dispcc (HW_CTRL) --
# dispcc tambien cambio de habilitado a disabled en el mismo fix del
# freeze, asi que es sospechoso que comparta este patron con videocc.
# camcc_sm8550 NO tiene ningun GDSC con HW_CTRL/HW_CTRL_TRIGGER/VOTABLE
# (todos "planos", solo POLL_CFG_GDSCR|RETAIN_FF_ENABLE) -- por eso queda
# BLACKLISTEADO todavia, es el candidato menos sospechoso de los tres.
# CONFIRMADO EN HARDWARE 2026-09-22: el reset random no volvio a pasar con
# videocc_sm8550 reactivado (junto con cpuidle.off=1 y CONFIG_GUNYAH_WATCHDOG,
# ver comentarios de abajo) -- no se aislo cual de los tres exactamente era
# necesario, pero con los tres juntos el reset desaparecio. No bisectar mas
# a menos que vuelva a aparecer.
# NOTA: esta linea documenta la cmdline "canonica" del dispositivo, pero el
# flujo de arranque VIGENTE es el chainload de U-Boot (ver
# rtwo-uboot-chainload en las notas del proyecto), que ignora esto y usa en
# cambio pmos_bootargs de ~/pmos/uboot-chainload/qcom-phone.env (mantenida
# en sincronia a mano con esta linea).
# 'ath12k.debug_mask=0x66' QUITADO 2026-09-22 (sincronizado con deviceinfo):
# el WiFi ya funciona y ese mask inundaba dmesg con cada header HTC RX y cada
# mensaje WMI (bits 0x2|0x4|0x20|0x40, solo presentes con CONFIG_ATH12K_DEBUG=y).
# Si vuelve a hacer falta diagnostico, re-agregar exactamente asi: ath12k.debug_mask=0x66
deviceinfo_kernel_cmdline="earlycon console=tty0 quiet splash panic=5 allow_mismatched_32bit_el0 random.trust_cpu=on printk.devkmsg=on systemd.log_ratelimit_kmsg=false cpufreq.default_governor=performance cpuidle.off=1 module_blacklist=camcc_sm8550 msm.separate_gpu_kms=1 deferred_probe_timeout=30"
# 'cpuidle.off=1' AGREGADO (2026-09-21): prueba para aislar si el reset
# random (siempre dentro de los primeros 5 min, nunca mientras corre algo)
# es un cuelgue al entrar/resumir de un C-state profundo via PSCI
# CPU_SUSPEND -- no hay overrides de idle-states/cpuidle en este .dts,
# heredamos lo que trae sm8550.dtsi sin validar en este hardware. Con esto
# las CPU solo usan WFI simple, nunca los estados profundos.
# CONFIRMADO EN HARDWARE 2026-09-22: el reset random no volvio a aparecer
# con esto puesto (junto con videocc_sm8550 reactivado y
# CONFIG_GUNYAH_WATCHDOG=y, ver arriba) -- FIX VIGENTE, no sacar. No se
# aislo cual de los tres cambios era el necesario especificamente; si algun
# dia hace falta reactivar cpuidle (ej. por consumo de bateria), bisectar
# de a uno en vez de sacar los tres juntos.
# CONFIG_GUNYAH_WATCHDOG=y (drivers/watchdog/gunyah_wdt.c, protocolo SMC con
# techo de ~32s) tambien esta activo -- no encajaba bien con la
# variabilidad de 0-5min del reset visto originalmente, pero se dejo activo
# sin costo real (el driver apaga el watchdog al hacer probe() si nadie
# abre /dev/watchdog) y forma parte del combo que resolvio el reset.
# CABECERA v2, NO v4 - y esta es la razon de fondo:
# DTBImgCheckAndAppendDT() coge el DTB de sitios distintos segun la version.
# v3/v4: ImageBuffer = vendor_boot, DtbOffset = dentro de vendor_boot. Si el
# match de qcom,msm-id/board-id falla, el fallback de "single appended
# DTB" calcula ImageBuffer(=BOOT.IMG) + DtbOffset(=de vendor_boot), o
# sea apunta DENTRO DEL KERNEL -> fdt_check_header falla ->
# EFI_NOT_FOUND -> LoadImageAndAuth falla -> el ABL de Motorola hace
# "Rebooting to retry" -> bootloop de 7 y a fastboot.
# v2: ImageBuffer y DtbOffset son AMBOS del boot.img, asi que el fallback
# funciona y acepta nuestro DTB SIN comparar ningun ID.
# O sea: con v4 dependemos de acertar msm-id/board-id exactos; con v2 no
# dependemos de nada. device-motorola-dubai (mismo ABL de Motorola, puerto
# mainline que SI arranca) usa v2 por esto mismo.
deviceinfo_generate_bootimg="true" deviceinfo_generate_bootimg="true"
deviceinfo_header_version="4" deviceinfo_header_version="2"
deviceinfo_append_dtb="true"
deviceinfo_flash_offset_base="0x00000000"
deviceinfo_flash_offset_kernel="0x00008000"
deviceinfo_flash_offset_ramdisk="0x01000000"
deviceinfo_flash_offset_second="0x00000000"
deviceinfo_flash_offset_tags="0x00000100"
deviceinfo_flash_offset_dtb="0x01f00000"
deviceinfo_bootimg_qcdt="false" deviceinfo_bootimg_qcdt="false"
deviceinfo_flash_pagesize="4096" deviceinfo_flash_pagesize="4096"
# Stock uses base 0 (mkbootimg defaults to 0x10000000, dtb ends up outside # Stock uses base 0 (mkbootimg defaults to 0x10000000, dtb ends up outside
@@ -0,0 +1,15 @@
#!/bin/sh
# Corre en la etapa /hooks-cleanup de init_2nd.sh, justo antes de
# "Switching root" (el ultimo punto de control antes de pasarle el arbol
# de procesos al systemd de la rootfs real).
#
# El dropbear que arranca initfs-hook.sh para el debug-shell (-p 22, en
# background con '&') NO muere solo en switch_root -- los procesos
# existentes sobreviven el pivote de root, solo cambia el filesystem raiz
# para los que arrancan DESPUES. Confirmado en hardware 2026-09-19: quedaba
# vivo (PID bajo, ej. 235) pegado al puerto 22 para siempre, y
# sshd.service de la rootfs real nunca podia bindear ("Address in use",
# reintentaba 5 veces y se rendia con start-limit-hit) -- el sistema
# arrancaba perfecto por debajo (Multi-User System, Graphical Interface
# alcanzados en ~48s), pero SSH quedaba inutilizable siempre.
pkill dropbear 2>/dev/null || true
@@ -0,0 +1,70 @@
#!/bin/sh
# Arranca dropbear (SSH) en el debug-shell, ademas del telnetd que ya trae
# postmarketos-mkinitfs-hook-debug-shell. Ningun paquete oficial de
# postmarketOS declara dropbear para el initramfs (solo para el rootfs real,
# via postmarketos-base-downstream, que es otra cosa) -- se agrega aca a
# mano porque hace falta poder scriptear el debug-shell (heredocs, comandos
# no interactivos por SSH), cosa que telnet no permite bien.
#
# Corre via run_hooks() en init_2nd.sh, DESPUES de setup_usb_network +
# start_unudhcpd (la red ya esta arriba en este punto) y ANTES de
# debug_shell(). Ver init_functions.sh:run_hooks (invoca cada hook con
# 'sh "$hook"', no hace falta que sea ejecutable).
# Panel NT37705 (2026-09-25): el ABL deja el subsistema de display encendido
# (mdss_gdsc on) y el primer encendido de msm sobre ese estado no logra
# arrancar el panel (sin TE, lecturas DCS -61). Probado en hardware: ni un
# ciclo de alimentacion del panel ni uno del host DSI/PHY alcanzan; lo unico
# que lo arranca es apagar mdss_gdsc (reinicia todo el hardware de display),
# y eso pasa con un blank/unblank del framebuffer. Se hace aca, antes del
# debug-shell, para que la consola ya se vea. El estado de mdss_gdsc durante
# el blank queda en dmesg para confirmar que el dominio se apago.
if [ -e /sys/class/graphics/fb0/blank ]; then
mount -t debugfs none /sys/kernel/debug 2>/dev/null
echo 1 > /sys/class/graphics/fb0/blank
sleep 1
gdsc=$(grep '^mdss_gdsc ' /sys/kernel/debug/pm_genpd/pm_genpd_summary 2>/dev/null)
echo "rtwo-panel: mdss_gdsc durante blank: ${gdsc:-desconocido}" > /dev/kmsg
echo 0 > /sys/class/graphics/fb0/blank
fi
# Este initramfs no trae /etc/passwd ni /etc/shadow (confirmado: ni
# siquiera una entrada minima de root) -- sin esto dropbear no puede
# resolver el home de root para buscar authorized_keys, y 'passwd root'
# falla con "unknown uid 0". El shadow con el campo de clave vacio entre
# los primeros dos ':' permite login sin contrasena (para cuando -B mas
# abajo si esta soportado por este build de dropbear).
if [ ! -f /etc/passwd ]; then
cat > /etc/passwd <<'PASSWD'
root:x:0:0:root:/root:/bin/sh
PASSWD
fi
if [ ! -f /etc/group ]; then
cat > /etc/group <<'GROUP'
root:x:0:
GROUP
fi
if [ ! -f /etc/shadow ]; then
cat > /etc/shadow <<'SHADOW'
root::10933:0:99999:7:::
SHADOW
chmod 600 /etc/shadow
fi
mkdir -p /etc/dropbear
mkdir -p /root/.ssh
cat > /root/.ssh/authorized_keys <<'KEYS'
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPpCHmYjP+h7qod3HLcAU55A05c/ZDSkzKEXhU8OpJZG rtwo-debug-shell
KEYS
chmod 700 /root/.ssh
chmod 600 /root/.ssh/authorized_keys
# -R: genera las claves de host al vuelo (el initramfs es tmpfs, no
# persisten entre arranques, no tiene sentido guardarlas)
# -B: tambien permite login con clave en blanco, por si /etc/passwd trae
# root sin contrasena (mismo modelo de acceso que telnetd -l
# pmos_getty, que da shell sin ninguna autenticacion) -- si el build de
# dropbear no tiene compilado el soporte de blank-password esta opcion
# simplemente no hace nada, la clave publica de arriba sigue funcionando
# -E: loguea a stderr/consola, para poder ver por que no conecta si falla
/usr/sbin/dropbear -R -B -E -p 22 &
@@ -0,0 +1,6 @@
# rtwo (2026-09-25): el boton de encendido (pon_pwrkey, KEY_POWER) se usa para
# ocultar el dashboard de la consola y todavia no hay suspension probada en
# este equipo. Sin esto, systemd-logind apaga el telefono al tocarlo.
[Login]
HandlePowerKey=ignore
HandlePowerKeyLongPress=poweroff
@@ -7,6 +7,13 @@ spi-geni-qcom
goodix-berlin-core goodix-berlin-core
goodix-berlin-spi goodix-berlin-spi
# USB keyboard (via &usb_1 host mode + a hub). CONFIG_HID/CONFIG_USB_HID
# are built-in, but CONFIG_HID_GENERIC=m is not -- without it, usbcore
# enumerates the keyboard fine (visible in dmesg) but no input device is
# ever created, so no keypress does anything. 2026-09-22: keyboard showed
# as "connected" but keys didn't work, this was the missing piece.
hid-generic
# USB gadget path. dwc3 + dwc3-qcom are built-in; the eUSB2 PHY and its # USB gadget path. dwc3 + dwc3-qcom are built-in; the eUSB2 PHY and its
# PMIC repeater are modules and MUST be in the initramfs, otherwise # PMIC repeater are modules and MUST be in the initramfs, otherwise
# usb@a600000 sits on -EPROBE_DEFER forever and no UDC appears. # usb@a600000 sits on -EPROBE_DEFER forever and no UDC appears.
@@ -15,6 +22,16 @@ goodix-berlin-spi
phy-snps-eusb2 phy-snps-eusb2
phy-qcom-eusb2-repeater phy-qcom-eusb2-repeater
# Root filesystem lives on UFS (1d84000.ufshc) inside the dynamic 'super'
# partition. ufs-qcom and its QMP PHY are modules in this config, so without
# them here the initramfs never sees a root device and the kernel panics with
# "VFS: Unable to mount root fs on unknown-block(0,0)". qcom_ice is ufs-qcom's
# only modules.dep dependency; listed explicitly rather than relying on
# mkinitfs to pull it in.
ufs-qcom
qcom_ice
phy-qcom-qmp-ufs
# Panel / DRM are not wired up yet: # Panel / DRM are not wired up yet:
# panel driver for Novatek NT37705 (1080x2400 DSC cmd, reset TLMM133) # panel driver for Novatek NT37705 (1080x2400 DSC cmd, reset TLMM133)
# msm (once &mdss / &mdss_dsi0 are enabled in the .dts) # msm (once &mdss / &mdss_dsi0 are enabled in the .dts)
@@ -0,0 +1,13 @@
[Unit]
Description=Revive the NT37705 panel if it came up dead from the ABL handoff
# Antes de cualquier cliente DRM/fbcon interactivo: con un DRM master activo
# el blank de fbdev no hace nada (ver rtwo-panel-revive.sh).
Before=rtwo-dashboard.service getty@tty1.service display-manager.service
[Service]
Type=oneshot
ExecStart=/usr/libexec/rtwo-panel-revive
TimeoutStartSec=60
[Install]
WantedBy=multi-user.target
@@ -0,0 +1,58 @@
#!/bin/sh
# Panel NT37705: el ABL deja el subsistema de display encendido (mdss_gdsc on)
# y a veces el primer encendido de msm sobre ese estado no arranca el panel
# (lecturas DCS -61, pantalla negra). Lo unico que lo revive es apagar
# mdss_gdsc, cosa que pasa con un blank/unblank del framebuffer.
#
# El initfs-hook hace lo mismo, pero msm suele enganchar el display recien
# despues del switch_root (no hay fb0 en el initramfs), asi que aca se
# repite desde el rootfs. Solo actua si el panel esta muerto: con el panel
# vivo actual_brightness devuelve el valor; muerto, falla con ENODATA (la
# lectura DCS del driver da -61).
#
# Tiene que correr antes que cualquier cliente DRM (cage): con un DRM
# master activo el blank de fbdev no hace nada.
BL=/sys/class/backlight/ae94000.dsi.0
FB=/sys/class/graphics/fb0
log() {
echo "rtwo-panel: $*" > /dev/kmsg
}
panel_alive() {
cat "$BL/actual_brightness" > /dev/null 2>&1
}
i=0
while [ ! -e "$BL/actual_brightness" ] || [ ! -e "$FB/blank" ]; do
i=$((i + 1))
if [ "$i" -gt 60 ]; then
log "sin backlight/fb0 tras 30 s, nada que hacer"
exit 0
fi
sleep 0.5
done
# Dar tiempo al primer prepare/enable del panel.
sleep 1
if panel_alive; then
log "panel vivo, sin cambios"
exit 0
fi
for try in 1 2 3; do
log "panel muerto, blank/unblank (intento $try)"
echo 1 > "$FB/blank"
sleep 1
echo 0 > "$FB/blank"
sleep 1
if panel_alive; then
log "panel revivido en el intento $try"
exit 0
fi
done
log "el panel sigue muerto tras 3 intentos"
exit 1