
Boots a custom Linux kernel on rooted LG webOS TVs via kexec, with reverse-engineered SoC watchdog support, framebuffer payloads, and an initramfs kernel build flow.
Boot a custom Linux kernel on a rooted LG webOS TV via kexec — in RAM, no secure-boot bypass.
Status: work-in-progress. A custom kernel can be staged and reaches userspace, but it does not yet stay up as a usable OS.
LG 50UP81009LR (webOS 6.5, Realtek RTD2875, armv7l). Rooted via Homebrew Channel; stock signed kernel + webOS userspace are untouched.
kexec -l stages a (stock or from-source) kernel; /sys/kernel/kexec_loaded flips to 1.kexec -e replaces the running kernel (the TV resets back to stock after)./sbin/init ran real code.startup.sh — the signed bootloader / ATF / OP-TEE are never touched.The reset is the SoC watchdog (TC block). The stock kernel's micom_wdt_thread()
holds it off with three register pokes (drivers/rtk_kdriver/platform/tv006/intmicom.c):
TCWCR @ 0xFE062204 <- 0xA5 // unlock
TCWOV @ 0xFE062210 <- 0x0FFFFFFF // max overflow => huge timeout
TCWTR @ 0xFE062208 <- 0x01 // kick
Under kexec the driver's raw *(volatile*)0xFE062208 = 0x01 lands on an unmapped
VA and is a silent no-op, so the SoC watchdog fires (~10–21 s). micom-pet.c now
does the same pokes from userspace via /dev/mem (CONFIG_DEVMEM=y), which maps
correctly, plus a 0xB1 keepalive to /dev/sys-intmicom as defense-in-depth.
Status: micom-pet.c rewritten, compiles with the musl toolchain, and a 5 s
benign smoke test on the live TV confirmed it runs and writes its breadcrumb
(0x52455814 = "REX"+beat). The only remaining proof is a kexec -e boot that
stays up past ~21 s — that reboots the TV, so it is an attended test.
wlan module vermagic must match CONFIG_LOCALVERSION="" to load; not yet wired into the initramfs.boot ROM → ATF → signed LG kernel (~2 s) → startup.sh
→ kexec -l <our zImage + dtb + initramfs>
→ kexec -e
→ OUR kernel runs in RAM (no eMMC writes)
Pull power = stock. It cannot brick.
Most of this repo was put together by Rex — an AI coding-agent instance — helping a human operate on their own TV, in their own living room. The AI wrote the kexec PoC, the boot chain, the framebuffer canaries, and these RE writeups. But the claims in this README were only ever made after the human fired the TV, looked at the screen, and confirmed it. If a claim isn't backed by a real screen/photo/uptime check from the hardware, it's not here.
No TVs were bricked in the making of this repo. Some were temporarily confused (a kexec'd kernel with no watchdog pet resets your box after ~15 s), then power-cycled back to stock. /tmp is wiped by every reset, so the TV forgets everything we did — that's the whole point.
rexos/ — the custom OS: boot hook, kernel build, initramfs, RexBus stub.kexec-poc/ — the load-only proof-of-concept + framebuffer canary payloads.docs/ — reverse-engineering writeups (boot/security, SAM app loading, surface map, luna2 schema).These steps reproduce what we did, on the exact hardware. Nothing is faked.
192.168.2.103 by default below; edit if yours differs.KERNEL_SRC=/path/to/linux-4.4.3 (download the 03.53.45 K7LP GPL tarball from LG open-source), or symlink ~/lgtv-toolkit/kernel-src/kernel/linux-4.4.3.kexec (no TV needed, ~2 min)git clone https://github.com/ggfuchsi-oss/lg-webos-kexec
cd lg-webos-kexec/kexec-poc && ./build.sh
Expected: a static ARM kexec binary at kexec-arm (168K, file shows ELF 32-bit LSB ... ARM ... statically linked).
cd ../kexec-poc
./run-poc.sh 192.168.2.103 ~/.ssh/tv_key
Expected result:
staged before : 0
staged after load : 1 <- kernel accepted, DTB wired, segments allocated
staged after unload: 0 <- cleared, TV untouched
This stages the TV's own current kernel via kexec and then immediately unloads it. /sys/kernel/kexec_loaded flips to 1 then back to 0. No reboot, no kernel switch, nothing persists. Pull the plug = stock.
Only do this with the TV on and someone present:
cd ../rexos
make # builds rexos-kernel.zImage + rexos-initramfs.cpio.gz into out/
./boot/rexos-kexec --load-only # stage, do NOT fire (same safe state as step 2)
# then, when ready to actually jump:
./boot/rexos-kexec # kexec -e -> our kernel runs in RAM (TV will reset)
Known-honest caveats at step 3 (not bugs I'm hiding):
kexec -e, the new kernel reaches userspace but the TV resets after ~10–21 s because the micom/SOC watchdog isn't being petted. That's the current wall, not a crash bug. rexos/initramfs/micom-pet.c is the daemon meant to fix this (still wiring it in).kexec-poc/canary/). Real graphics needs the VCPU RPC path (not done).This repo contains source + docs + the TV-captured build inputs (kernel .config, wifi module + firmware, rootfs libs), but not the ~390 MB LG K7LP GPL kernel source tree itself — that is LG's to distribute, not ours to re-host.
| dependency | how you get it |
|---|---|
LG K7LP GPL linux-4.4.3 (RTD2875) | LG opensource site → 03.53.45 K7LP GPL tarball → kernel |
| musl armv7 cross-toolchain (~98 MB) | auto-fetched by kexec-poc/build.sh (self-contained) |
| A rooted TV (50UP81009LR) | needed the first time, only to capture .config — but that config is now committed at rexos/kernel/rexos-tv.config, so a clone builds offline |
make will fail with a clear KERNEL_SRC missing if the kernel tree isn't present — there's no silent half-build.
As far as we can tell, this is the first public kexec-based custom-kernel boot for an LG webOS TV. The primitives (kexec, rooted webOS, RTD2875) are all known individually; the application to this locked-down consumer TV appears to be new. We are not claiming a secure-boot bypass — we sidestep it.
GPL-2.0 (kernel work; LG's GPL kernel source is GPL). Our scripts are GPL-compatible. See CREDITS for upstream attribution.