Tesla_OS_On_QEMU: Tooling to Unpack, Patch, and Boot Tesla Infotainment Firmware in QEMU
Summary
Why it matters
- Published
- Collected
📦 Full-Text Content Snapshot
R2 Archive · Full Article Preserved中文说明见 README.zh-CN.md。
Tooling to unpack a Tesla infotainment ECU ("ICE") firmware/eMMC dump, optionally patch its root filesystem for research, and boot it under QEMU for offline analysis — built from a full reverse-engineering pass over a real Model 3 Intel Elkhart Lake ("ICE-MRB") firmware image.
Repository: https://github.com/cn0xroot/Tesla_OS_On_QEMU
This repository ships tooling and documentation only. No firmware image, extracted filesystem, key material, packet capture, or log file is included or downloaded by anything here — see What's not in this repo below. You must supply your own firmware dump.
What this is
Tesla's Intel-based infotainment ECU stores its root filesystem as a squashfs image protected by dm-verity, spread across GPT partitions using a private dm-linear layout that the stock verity-init reconstructs at boot time. Getting a working, inspectable copy of that filesystem — and being able to boot it in an emulator instead of on real hardware — takes several non-obvious steps (documented in full, including the debugging dead-ends, in docs/firmware_unpacking_reproduction.md if you keep a local copy of that analysis).
scripts/tesla_fw.py is a single CLI that wraps the whole pipeline:
| Stage | What it does |
| unpack | Partition table → extract kernel from the iasImage container → reconstruct the dm-linear-spliced rootfs → unsquashfs it |
| patch | Build a minimal dm-verity-bypass init + initrd, and repack an edited rootfs directory back into squashfs |
| run | Boot the (optionally patched) firmware in QEMU — headless, interactive GUI, GDB-attached, or a full accelerated graphics stack |
| ssh / focus / capture | Day-to-day helpers for a running QEMU guest: SSH in, fix host input focus, capture traffic |
Requirements
- Linux host, Python 3.8+
qemu-system-x86_64,qemu-img(with KVM available for reasonable boot speed)
squashfs-tools(unsquashfs,mksquashfs)
gcc(to statically build the bypassinit),cpio,gzip
fdisk/sfdisk(partition inspection/extraction)
openssh-client(for thessh/capturehelpers)
Quickstart
git clone https://github.com/cn0xroot/Tesla_OS_On_QEMU
cd Tesla_OS_On_QEMU
# 1. Unpack a firmware dump you already have (not provided by this repo)
python3 scripts/tesla_fw.py unpack /path/to/tesla_ROM1_*.bin ./extracted both \
--ias-image ./extracted/boot/bank_a.iasImage --bzimage-len 0x832fa0 \
--make-overlay
# 2. (optional) Modify extracted/rootfs_reconstructed/squashfs-root-a/...,
# then repack it and build a verity-bypass boot path:
python3 scripts/tesla_fw.py patch repack \
extracted/rootfs_reconstructed/squashfs-root-a rootfs_edited.squashfs
python3 scripts/tesla_fw.py patch build-init ./patched_boot
# 3. Boot it
python3 scripts/tesla_fw.py run --mode headless --image /path/to/tesla_ROM1_*.bin --duration 180
python3 scripts/tesla_fw.py run --mode ui --rootfs rootfs_edited.squashfs
# 4. While it's running
python3 scripts/tesla_fw.py ssh
python3 scripts/tesla_fw.py capture eth0 30Every subcommand has its own --help with the full option list.
unpack in detail
`tesla_fw.py unpack <image.bin> <outdir> [a|b|both]
--ias-image PATH boot-partition bankX.iasImage (also extracts the kernel)
--bzimage-len HEX exact bzImage length read from the device's own bootlog.0
--skip-unsquashfs stop after reconstructing the raw image
--make-overlay also create a QEMU qcow2 copy-on-write overlay
--p2-off/--p3-off/--seg1-len/--p4-off/--p4-end-incl
override the GPT offsets if your image's
partition table differs from the default
`The reconstruction step matters: on this firmware family, a single GPT partition is too small to hold the full squashfs + dm-verity metadata. The real root device is a dm-linear splice of that partition plus a 1GiB slice borrowed from the tail of the LVM data partition — the exact offsets are derived from the vendor's own verity-init binary. Getting a truncation/rounding detail in that formula wrong produces a rootfs that looks corrupt (squashfs table pointers point past EOF) when it's really just misaligned by a few thousand bytes; tesla_fw.py unpack reproduces the corrected formula.
patch in detail
`tesla_fw.py patch build-init <outdir> # compiles scripts/custom_init.c,
# packs it as a 1-file initrd
tesla_fw.py patch repack <rootfs_dir> <out.squashfs> [--comp lz4] [--block-size 131072]
tesla_fw.py patch legacy-tables <squashfs> # deprecated/archival only, see --help
`The stock rootfs is dm-verity protected: touch a single byte and the vendor's verity-init will refuse to mount it. patch build-init compiles a small replacement PID 1 (scripts/custom_init.c) that mirrors the vendor init's mount/switch-root sequence but skips the RSA signature check, so any structurally valid squashfs — edited or not — can boot. This does not, and cannot, make edited content pass Tesla's real signature verification; it's for offline emulator research only.
run in detail
`tesla_fw.py run --mode headless --image IMG --duration 180 [--gui]
tesla_fw.py run --mode ui --rootfs squashfs [--kernel ...] [--initrd ...]
tesla_fw.py run --mode gdb --rootfs squashfs
tesla_fw.py run --mode glamor
`--mode selects between the four QEMU launch profiles already present under scripts/ (run_qemu.sh, run_qemu_ui.sh, run_qemu_gdb.sh, run_v62_glamor.sh) — a fixed-duration headless boot, a long-running interactive GUI session, a session with kernel- and userspace-GDB stubs attached, and a full accelerated 2D graphics stack respectively. See each script's header comment for the details of what it configures.
Device / feature status in QEMU
What actually works once you're booted, and what still doesn't:
| Subsystem | Status | Fix | Reproducible from this repo? |
| Touch input | Working | Replaced touch-proxy (wrong coordinate space) with x11-input-proxy, which injects clicks via X11 XTest directly in screen coordinates (v63) | Partially — scripts/x11-input-proxy.c is tracked; the rootfs-side wiring that runs it isn't |
| Browser — Apple Music web view (chromium-app) | Working (renders, stable) | Forced software rendering (--disable-gpu --disable-gpu-compositing) plus sandbox netns/bind-mount fixes; the streaming backend itself is unreachable from an emulator, which isn't a guest bug | No — baked into the rootfs only |
| Browser — built-in in-car Browser | Partially working | Panel opens after a boot-race workaround, but page content renders as a black screen: no GPU acceleration and no swiftshader software-GL fallback compiled in — an open, unresolved hard limit | No — open issue |
| Audio / sound card | Working (host playback) | The OEM kernel ships no PCI/USB sound driver at all; a custom AC97 kernel module plus QEMU -audiodev pa,... streams guest audio out to the host's PulseAudio/PipeWire. A prior crash loop was fixed separately by pre-creating /var/lib/alsa and /var/lib/audiod | Partially — the QEMU-side -audiodev wiring is in run_qemu_ui.sh/run_v62_glamor.sh; the kernel module and rootfs directory fix aren't |
| Network (app connectivity + stable SSH, simultaneously) | Working | v68's dual-NIC design: eth0 stays under connman's static IP for app connectivity, eth1 gets its own static IP outside connman's reach for SSH, so neither interferes with the other. A separate earlier fix stops connman from picking a factory-only config that drops the whole connection | Yes — tesla_fw.py patch network-fix (see below) |
| UI rendering (2D) | Working | Pure 2D scanout (-device virtio-vga, gl=on left off) — the real Tesla UI fully renders and keeps running (Factory Net label, map grid, loading cards, bottom taskbar all visible and animating) | No — QEMU display flags only, no rootfs change needed |
| 3D hardware acceleration | Not available on this host | Tried virtio-vga-gl + gl=on (virgl) to fix both the sluggish 2D refresh rate and the mame black screen below — QEMU segfaults inside libGLX_nvidia.so around the 35s mark when the guest starts creating a GL context; forcing Mesa software GLX avoids that crash but QEMU still silently dies at the same point. Permanently disabled; kept as an experimental GL=on switch in run_qemu_ui.sh only | N/A — host GPU/driver limitation, not something this repo's tooling can fix |
| Maps / navigation | Working | Needed a kernel rebuild (CONFIG_NETFILTER_XT_TARGET_REDIRECT, CONFIG_NF_NAT_REDIRECT) so a transparent SOCKS proxy can REDIRECT the map/streaming traffic that ignores http_proxy, plus raising CONFIG_NR_CPUS from 4 to 8. This is what "mapfix" in the STABLE rootfs filename refers to. Confirmed with real Google map tiles and a live supercharger list | No — baked into the custom bzImage_redirect_smp8 kernel build, not a rootfs file |
| Built-in games | Mixed | Native Toybox mini-games (Light Show, Sketchpad, etc.) work — they're rendered by QtCar itself, no separate GL process needed. The Arcade app opens, but its downloadable titles (Beach Buggy Racing 2, etc.) can't install — Tesla's CDN backend is unreachable from an emulator, an environment limit rather than a bug. Classic mame titles (Missile Command, Asteroids, ...) don't render at all: no GPU, no software SDL renderer compiled in, and Mesa's software EGL-on-X11 path doesn't work in this build — the same hard limit as 3D acceleration above | Partially — the audio-gate workaround (a synthetic gameaudio-ready runit service) is a rootfs change, not reproducible from this repo yet; the mame/Arcade limitations aren't fixable from software at all |
A few things worth being explicit about:
- Touch, Chromium, audio, maps, and the games audio-gate workaround are "working" only in the pre-built
..._STABLE.squashfsimages referenced byrun_qemu_ui.sh/run_v62_glamor.shby default — those images aren't distributed with this repo (see What's not in this repo), so a rootfs you build yourself from scratch viaunpack+patch repackwon't have those fixes unless you reconstruct them yourself. The graphics/audio/touch/maps fixes involve binary patches, a rebuilt kernel, and a custom kernel module that aren't reproduced as standalone tooling here yet.
- The network fix is the one exception: it's fully reproducible from this repo. Run it against an already-booted guest (one started with
run --mode uior--mode glamor, which already carry the second NIC):
python3 scripts/tesla_fw.py patch network-fixThis applies the exact connmanctl sequence documented in Part 2 to configure eth0, and a standard-tooling equivalent (not the original file, which wasn't preserved) to bring up a static IP on eth1. It only affects the currently running guest — it edits runtime network state, not /etc/runit/1 itself, so it doesn't survive a reboot. See the script's own header comment (scripts/apply_network_fix.sh) for the full detail on what's verified-exact versus reconstructed.
Further reading
The full research write-up — methodology, dead ends, and the findings this toolchain distills — is published in two parts on the author's blog:
— GPT partition analysis, reverse-engineering the iasImage container from the device's own bootlog.0, disassembling verity-init to recover the exact dm-linear splice formula, and the ±2MB exhaustive search that traced a "corrupted" rootfs down to one missed (p4_bytes >> 12) << 3 truncation.
— the boot-chain fixes (kernel module version pinning, RCU stall tuning, a LUKS/quota reformat-on-every-boot loop), the graphics stack port (DRM driver selection, Mesa ABI mismatches, the virtio-gpu-gl → virtio-vga fallback), the touch-input protocol translation, and two security findings worth flagging on their own: sshd_config's dev/production split gated by is-fused(), and a missing clock_gettime entry in QtCarDvServer.kafel's seccomp allowlist that only surfaces because this build's glibc skips the VDSO fast path.
What's not in this repo
.gitignore is a strict allowlist: everything is ignored by default, and only the tool sources (scripts/*.py, *.sh, *.c, *.patch) and this README are tracked. In particular, none of the following are ever committed:
- The firmware dump itself, or anything derived from it (extracted
partitions, reconstructed rootfs images, .squashfs/.qcow2 files)
- SSH keys (
scripts/ssh_key/)
- Packet captures, serial console logs, screenshots of the booted UI
- Any file under
extracted/,build/,docs/, or similar working
directories your own local checkout may accumulate
If you fork this for your own research, keep that boundary: the tooling is safe to share, the artifacts it produces from a real device usually are not.
Scope and ethics
This project exists to make Tesla's own infotainment firmware inspectable and bootable offline, in an emulator, for security research and defensive analysis — not to defeat vehicle security controls on a live, in-service car. The dm-verity bypass in patch build-init only helps you boot a modified image inside QEMU; it has no effect on, and provides no path to, a real vehicle's own verity/TPM chain. Use this against firmware you're authorized to analyze (your own hardware, or under a disclosed research/bug-bounty engagement), and follow responsible disclosure for anything you find.
Acknowledgments
Thanks to @vessial (GitHub) for guidance on the firmware unpacking approach — the dm-linear reconstruction work in unpack benefited directly from that input (credited in Part 2 of the write-up above).
The accelerated graphics stack used by run --mode glamor (scripts/run_v62_glamor.sh) ports the Ubuntu Xorg + modesetting + glamor (llvmpipe) approach pioneered by denysvitali/tesla-qemu onto this project's real Tesla 4.14 rootfs, including its vblank-wait DRM patch. scripts/touch-proxy.c is likewise based on that project's tools/touch-proxy.c. Credit to @denysvitali for the original QEMU-graphics groundwork this builds on.
Tesla's own public source releases were essential reference material for identifying and cross-checking the platform this firmware targets:
- teslamotors/linux — the vendor
kernel source, used to cross-reference the extracted bzImage (version, Tesla Model3 hardware core support string, driver selection) against a known-authentic build.
Tesla's coreboot sources, relevant to the early Intel Elkhart Lake boot chain that hands off into the iasImage/verity-init sequence this project's unpack/patch tooling targets.
confirmed the ice-mrb ("In-Car Entertainment") platform naming and general userspace layout (runit, connman, package set) match this firmware, and gave a version baseline to diff the extracted rootfs against.
License
This project is licensed under the GNU General Public License v3.0 — see LICENSE for the full text.
One exception: scripts/touch-proxy.c is a derivative of denysvitali/tesla-qemu's tools/touch-proxy.c, and that upstream project does not declare a license of its own. That single file is therefore not covered by this repository's GPL-3.0 grant — see the note at the top of the file. Everything else in this repository (including scripts/tesla_fw.py, scripts/custom_init.c, and this documentation) is original work licensed under GPL-3.0.
📦 Full-Text Markdown Snapshot archived by Phying News · Original source: github.com
---
id: 9244
canonical_url: "https://phying.com/item/9244"
source_url: "https://github.com/cn0xroot/Tesla_OS_On_QEMU"
source_domain: "github.com"
title: "Tesla_OS_On_QEMU: Tooling to Unpack, Patch, and Boot Tesla Infotainment Firmware in QEMU"
type: "tool"
severity: "unknown"
cve: null
published_at: "2026-09-22T04:34:21Z"
lang: "en"
---
# Tesla_OS_On_QEMU
中文说明见 [README.zh-CN.md](/cn0xroot/Tesla_OS_On_QEMU/blob/main/README.zh-CN.md)。
Tooling to unpack a Tesla infotainment ECU ("ICE") firmware/eMMC dump,
optionally patch its root filesystem for research, and boot it under QEMU
for offline analysis — built from a full reverse-engineering pass over a
real Model 3 Intel Elkhart Lake ("ICE-MRB") firmware image.
Repository: [https://github.com/cn0xroot/Tesla_OS_On_QEMU](https://github.com/cn0xroot/Tesla_OS_On_QEMU)
> **This repository ships tooling and documentation only.** No firmware
> image, extracted filesystem, key material, packet capture, or log file
> is included or downloaded by anything here — see [What's *not* in this
> repo](#whats-not-in-this-repo) below. You must supply your own firmware
> dump.
## What this is
Tesla's Intel-based infotainment ECU stores its root filesystem as a
squashfs image protected by dm-verity, spread across GPT partitions using
a private `dm-linear` layout that the stock `verity-init` reconstructs at
boot time. Getting a working, inspectable copy of that filesystem — and
being able to boot it in an emulator instead of on real hardware — takes
several non-obvious steps (documented in full, including the debugging
dead-ends, in `docs/firmware_unpacking_reproduction.md` if you keep a
local copy of that analysis).
`scripts/tesla_fw.py` is a single CLI that wraps the whole pipeline:
| Stage | What it does |
| `unpack` | Partition table → extract kernel from the `iasImage` container → reconstruct the `dm-linear`-spliced rootfs → `unsquashfs` it |
| `patch` | Build a minimal dm-verity-bypass `init` + initrd, and repack an edited rootfs directory back into squashfs |
| `run` | Boot the (optionally patched) firmware in QEMU — headless, interactive GUI, GDB-attached, or a full accelerated graphics stack |
| `ssh` / `focus` / `capture` | Day-to-day helpers for a running QEMU guest: SSH in, fix host input focus, capture traffic |
## Requirements
- Linux host, Python 3.8+
- `qemu-system-x86_64`, `qemu-img` (with KVM available for reasonable boot speed)
- `squashfs-tools` (`unsquashfs`, `mksquashfs`)
- `gcc` (to statically build the bypass `init`), `cpio`, `gzip`
- `fdisk`/`sfdisk` (partition inspection/extraction)
- `openssh-client` (for the `ssh`/`capture` helpers)
## Quickstart
```
git clone https://github.com/cn0xroot/Tesla_OS_On_QEMU
cd Tesla_OS_On_QEMU
# 1. Unpack a firmware dump you already have (not provided by this repo)
python3 scripts/tesla_fw.py unpack /path/to/tesla_ROM1_*.bin ./extracted both \
--ias-image ./extracted/boot/bank_a.iasImage --bzimage-len 0x832fa0 \
--make-overlay
# 2. (optional) Modify extracted/rootfs_reconstructed/squashfs-root-a/...,
# then repack it and build a verity-bypass boot path:
python3 scripts/tesla_fw.py patch repack \
extracted/rootfs_reconstructed/squashfs-root-a rootfs_edited.squashfs
python3 scripts/tesla_fw.py patch build-init ./patched_boot
# 3. Boot it
python3 scripts/tesla_fw.py run --mode headless --image /path/to/tesla_ROM1_*.bin --duration 180
python3 scripts/tesla_fw.py run --mode ui --rootfs rootfs_edited.squashfs
# 4. While it's running
python3 scripts/tesla_fw.py ssh
python3 scripts/tesla_fw.py capture eth0 30
```
Every subcommand has its own `--help` with the full option list.
### `unpack` in detail
```
`tesla_fw.py unpack <image.bin> <outdir> [a|b|both]
--ias-image PATH boot-partition bankX.iasImage (also extracts the kernel)
--bzimage-len HEX exact bzImage length read from the device's own bootlog.0
--skip-unsquashfs stop after reconstructing the raw image
--make-overlay also create a QEMU qcow2 copy-on-write overlay
--p2-off/--p3-off/--seg1-len/--p4-off/--p4-end-incl
override the GPT offsets if your image's
partition table differs from the default
`
```
The reconstruction step matters: on this firmware family, a single GPT
partition is *too small* to hold the full squashfs + dm-verity metadata.
The real root device is a `dm-linear` splice of that partition plus a
1GiB slice borrowed from the tail of the LVM data partition — the exact
offsets are derived from the vendor's own `verity-init` binary. Getting a
truncation/rounding detail in that formula wrong produces a rootfs that
*looks* corrupt (squashfs table pointers point past EOF) when it's really
just misaligned by a few thousand bytes; `tesla_fw.py unpack` reproduces
the corrected formula.
### `patch` in detail
```
`tesla_fw.py patch build-init <outdir> # compiles scripts/custom_init.c,
# packs it as a 1-file initrd
tesla_fw.py patch repack <rootfs_dir> <out.squashfs> [--comp lz4] [--block-size 131072]
tesla_fw.py patch legacy-tables <squashfs> # deprecated/archival only, see --help
`
```
The stock rootfs is dm-verity protected: touch a single byte and the
vendor's `verity-init` will refuse to mount it. `patch build-init`
compiles a small replacement PID 1 (`scripts/custom_init.c`) that mirrors
the vendor init's mount/switch-root sequence but skips the RSA signature
check, so any *structurally valid* squashfs — edited or not — can boot.
This does not, and cannot, make edited content pass Tesla's real
signature verification; it's for offline emulator research only.
### `run` in detail
```
`tesla_fw.py run --mode headless --image IMG --duration 180 [--gui]
tesla_fw.py run --mode ui --rootfs squashfs [--kernel ...] [--initrd ...]
tesla_fw.py run --mode gdb --rootfs squashfs
tesla_fw.py run --mode glamor
`
```
`--mode` selects between the four QEMU launch profiles already present
under `scripts/` (`run_qemu.sh`, `run_qemu_ui.sh`, `run_qemu_gdb.sh`,
`run_v62_glamor.sh`) — a fixed-duration headless boot, a long-running
interactive GUI session, a session with kernel- and userspace-GDB stubs
attached, and a full accelerated 2D graphics stack respectively. See each
script's header comment for the details of what it configures.
## Device / feature status in QEMU
What actually works once you're booted, and what still doesn't:
| Subsystem | Status | Fix | Reproducible from this repo? |
| Touch input | Working | Replaced `touch-proxy` (wrong coordinate space) with `x11-input-proxy`, which injects clicks via X11 XTest directly in screen coordinates (v63) | Partially — `scripts/x11-input-proxy.c` is tracked; the rootfs-side wiring that runs it isn't |
| Browser — Apple Music web view (`chromium-app`) | Working (renders, stable) | Forced software rendering (`--disable-gpu --disable-gpu-compositing`) plus sandbox netns/bind-mount fixes; the streaming backend itself is unreachable from an emulator, which isn't a guest bug | No — baked into the rootfs only |
| Browser — built-in in-car Browser | Partially working | Panel opens after a boot-race workaround, but page content renders as a black screen: no GPU acceleration and no swiftshader software-GL fallback compiled in — an open, unresolved hard limit | No — open issue |
| Audio / sound card | Working (host playback) | The OEM kernel ships no PCI/USB sound driver at all; a custom AC97 kernel module plus QEMU `-audiodev pa,...` streams guest audio out to the host's PulseAudio/PipeWire. A prior crash loop was fixed separately by pre-creating `/var/lib/alsa` and `/var/lib/audiod` | Partially — the QEMU-side `-audiodev` wiring is in `run_qemu_ui.sh`/`run_v62_glamor.sh`; the kernel module and rootfs directory fix aren't |
| Network (app connectivity + stable SSH, simultaneously) | Working | v68's dual-NIC design: `eth0` stays under `connman`'s static IP for app connectivity, `eth1` gets its own static IP outside connman's reach for SSH, so neither interferes with the other. A separate earlier fix stops `connman` from picking a factory-only config that drops the whole connection | **Yes** — `tesla_fw.py patch network-fix` (see below) |
| UI rendering (2D) | Working | Pure 2D scanout (`-device virtio-vga`, `gl=on` left off) — the real Tesla UI fully renders and keeps running (Factory Net label, map grid, loading cards, bottom taskbar all visible and animating) | No — QEMU display flags only, no rootfs change needed |
| 3D hardware acceleration | Not available on this host | Tried `virtio-vga-gl` + `gl=on` (virgl) to fix both the sluggish 2D refresh rate and the mame black screen below — QEMU segfaults inside `libGLX_nvidia.so` around the 35s mark when the guest starts creating a GL context; forcing Mesa software GLX avoids that crash but QEMU still silently dies at the same point. Permanently disabled; kept as an experimental `GL=on` switch in `run_qemu_ui.sh` only | N/A — host GPU/driver limitation, not something this repo's tooling can fix |
| Maps / navigation | Working | Needed a kernel rebuild (`CONFIG_NETFILTER_XT_TARGET_REDIRECT`, `CONFIG_NF_NAT_REDIRECT`) so a transparent SOCKS proxy can `REDIRECT` the map/streaming traffic that ignores `http_proxy`, plus raising `CONFIG_NR_CPUS` from 4 to 8. This is what "mapfix" in the STABLE rootfs filename refers to. Confirmed with real Google map tiles and a live supercharger list | No — baked into the custom `bzImage_redirect_smp8` kernel build, not a rootfs file |
| Built-in games | Mixed | Native Toybox mini-games (Light Show, Sketchpad, etc.) work — they're rendered by QtCar itself, no separate GL process needed. The Arcade app opens, but its downloadable titles (Beach Buggy Racing 2, etc.) can't install — Tesla's CDN backend is unreachable from an emulator, an environment limit rather than a bug. Classic mame titles (Missile Command, Asteroids, ...) don't render at all: no GPU, no software SDL renderer compiled in, and Mesa's software EGL-on-X11 path doesn't work in this build — the same hard limit as 3D acceleration above | Partially — the audio-gate workaround (a synthetic `gameaudio-ready` runit service) is a rootfs change, not reproducible from this repo yet; the mame/Arcade limitations aren't fixable from software at all |
A few things worth being explicit about:
- Touch, Chromium, audio, maps, and the games audio-gate workaround are "working" only in the pre-built `..._STABLE.squashfs` images referenced by `run_qemu_ui.sh`/`run_v62_glamor.sh` by default — those images aren't distributed with this repo (see [What's *not* in this repo](#whats-not-in-this-repo)), so a rootfs you build yourself from scratch via `unpack` + `patch repack` won't have those fixes unless you reconstruct them yourself. The graphics/audio/touch/maps fixes involve binary patches, a rebuilt kernel, and a custom kernel module that aren't reproduced as standalone tooling here yet.
- The network fix is the one exception: it's fully reproducible from this repo. Run it against an already-booted guest (one started with `run --mode ui` or `--mode glamor`, which already carry the second NIC):
```
python3 scripts/tesla_fw.py patch network-fix
```
This applies the exact `connmanctl` sequence documented in [Part 2](https://cn0xroot.wordpress.com/2026/09/20/root_tesla_os_on_qemu_part_2_debugging_fixing/) to configure `eth0`, and a standard-tooling equivalent (not the original file, which wasn't preserved) to bring up a static IP on `eth1`. It only affects the currently running guest — it edits runtime network state, not `/etc/runit/1` itself, so it doesn't survive a reboot. See the script's own header comment (`scripts/apply_network_fix.sh`) for the full detail on what's verified-exact versus reconstructed.
## Further reading
The full research write-up — methodology, dead ends, and the findings
this toolchain distills — is published in two parts on the author's
blog:
- [Part 1: Unpacking](https://cn0xroot.wordpress.com/2026/09/19/root-tesla-os-on-qemu-part-1-unpacking/)
— GPT partition analysis, reverse-engineering the `iasImage` container
from the device's own `bootlog.0`, disassembling `verity-init` to
recover the exact `dm-linear` splice formula, and the ±2MB exhaustive
search that traced a "corrupted" rootfs down to one missed
`(p4_bytes >> 12) << 3` truncation.
- [Part 2: Debugging + fixing](https://cn0xroot.wordpress.com/2026/09/20/root_tesla_os_on_qemu_part_2_debugging_fixing/)
— the boot-chain fixes (kernel module version pinning, RCU stall
tuning, a LUKS/quota reformat-on-every-boot loop), the graphics stack
port (DRM driver selection, Mesa ABI mismatches, the
`virtio-gpu-gl` → `virtio-vga` fallback), the touch-input protocol
translation, and two security findings worth flagging on their own:
`sshd_config`'s dev/production split gated by `is-fused()`, and a
missing `clock_gettime` entry in `QtCarDvServer.kafel`'s seccomp
allowlist that only surfaces because this build's glibc skips the
VDSO fast path.
## What's *not* in this repo
`.gitignore` is a strict allowlist: everything is ignored by default, and
only the tool sources (`scripts/*.py`, `*.sh`, `*.c`, `*.patch`) and this
README are tracked. In particular, **none of the following are ever
committed**:
- The firmware dump itself, or anything derived from it (extracted
partitions, reconstructed rootfs images, `.squashfs`/`.qcow2` files)
- SSH keys (`scripts/ssh_key/`)
- Packet captures, serial console logs, screenshots of the booted UI
- Any file under `extracted/`, `build/`, `docs/`, or similar working
directories your own local checkout may accumulate
If you fork this for your own research, keep that boundary: the tooling
is safe to share, the artifacts it produces from a real device usually
are not.
## Scope and ethics
This project exists to make Tesla's own infotainment firmware inspectable
and bootable *offline*, in an emulator, for security research and
defensive analysis — not to defeat vehicle security controls on a live,
in-service car. The dm-verity bypass in `patch build-init` only helps you
boot a modified image *inside QEMU*; it has no effect on, and provides no
path to, a real vehicle's own verity/TPM chain. Use this against firmware
you're authorized to analyze (your own hardware, or under a disclosed
research/bug-bounty engagement), and follow responsible disclosure for
anything you find.
## Acknowledgments
Thanks to [@vessial](https://x.com/vessial) ([GitHub](https://github.com/vessial)) for guidance on the firmware
unpacking approach — the `dm-linear` reconstruction work in `unpack`
benefited directly from that input (credited in [Part 2](https://cn0xroot.wordpress.com/2026/09/20/root_tesla_os_on_qemu_part_2_debugging_fixing/)
of the write-up above).
The accelerated graphics stack used by `run --mode glamor`
(`scripts/run_v62_glamor.sh`) ports the Ubuntu Xorg + `modesetting` +
glamor (llvmpipe) approach pioneered by
[denysvitali/tesla-qemu](https://github.com/denysvitali/tesla-qemu) onto
this project's real Tesla 4.14 rootfs, including its vblank-wait DRM
patch. `scripts/touch-proxy.c` is likewise based on that project's
`tools/touch-proxy.c`. Credit to [@denysvitali](https://github.com/denysvitali)
for the original QEMU-graphics groundwork this builds on.
Tesla's own public source releases were essential reference material for
identifying and cross-checking the platform this firmware targets:
- [teslamotors/linux](https://github.com/teslamotors/linux) — the vendor
kernel source, used to cross-reference the extracted `bzImage`
(version, `Tesla Model3 hardware core support` string, driver
selection) against a known-authentic build.
- [teslamotors/coreboot](https://github.com/teslamotors/coreboot) —
Tesla's coreboot sources, relevant to the early Intel Elkhart Lake
boot chain that hands off into the `iasImage`/`verity-init` sequence
this project's `unpack`/`patch` tooling targets.
- [teslamotors/buildroot](https://github.com/teslamotors/buildroot) —
confirmed the `ice-mrb` ("In-Car Entertainment") platform naming and
general userspace layout (`runit`, `connman`, package set) match this
firmware, and gave a version baseline to diff the extracted rootfs
against.
## License
This project is licensed under the **GNU General Public License v3.0** —
see [`LICENSE`](/cn0xroot/Tesla_OS_On_QEMU/blob/main/LICENSE) for the full text.
One exception: `scripts/touch-proxy.c` is a derivative of
[denysvitali/tesla-qemu](https://github.com/denysvitali/tesla-qemu)'s
`tools/touch-proxy.c`, and that upstream project does not declare a
license of its own. That single file is therefore *not* covered by this
repository's GPL-3.0 grant — see the note at the top of the file.
Everything else in this repository (including `scripts/tesla_fw.py`,
`scripts/custom_init.c`, and this documentation) is original work
licensed under GPL-3.0.
---
> 📦 **Full-Text Markdown Snapshot** archived by [Phying News](https://phying.com/item/9244) · Original source: [github.com](https://github.com/cn0xroot/Tesla_OS_On_QEMU)