Title Emulating the baseband

Subtitle About eight months to find a way to make a voice call with osmocom-bb layer1 and a homemade C54x DSP emulation on a virtual 2G network.

Abstract A real GSM phone’s baseband DSP ROM now runs, unmodified, on an ordinary PC, and you can stop it at an instruction and see what it is doing. The DSP is the least observable part of a phone: a vendor processor running a mask ROM nobody outside the manufacturer could inspect. Instead of replacing it, this project emulates the TI TMS320C54x closely enough to run the original ROM, next to a QEMU Calypso machine running OsmocomBB’s real layer 1. The result is an end-to-end GSM call — attach, SMS, USSD, voice, A5 — with nothing on air, the ROM doing the downlink and part of the uplink. But the call is not the point: the DSP can now be single-stepped. Since April 2010 a FIXME in OsmocomBB has asked where a magic 23 came from. The ROM answers it.

Description A Calypso-type baseband has two processors. The ARM runs the protocol stack, and OsmocomBB has made that side free software since 2010. The DSP runs the physical layer — demodulation, channel coding, A5 — from a mask ROM that was never documented outside the vendor and that OsmocomBB drives through a shared-memory API without knowing what happens behind it. For fifteen years, “the DSP does it” was where the free stack stopped. This project removes that wall by emulating the DSP rather than replacing it.

What runs. A QEMU fork with a TI Calypso machine (ARM946, TPU, RIF, DMA, shared API RAM) loads OsmocomBB’s layer1.highram as the real chip would. A native emulator for the TMS320C54x executes the DSP mask ROM, frame-locked with QEMU over the same API RAM a real phone uses. The ROM dump is not redistributed: the one used is identical, word for word, to the public FreeCalypso dump. A bridge carries bursts to osmo-bts-trx, and an Osmocom core network (BSC, MSC, HLR, SIP) completes the call. An end-to-end test bench runs the whole chain — boot, attach, SMS in both directions, USSD, a voice call, a 1 kHz tone recovered through the vocoder — and the 4 October run reports 33 layer-1 functions handled by the chain, 1 degraded (downlink TCH/F quality flag), 1 not handled (frequency hopping, out of scope), with the DSP ROM doing FCCH detection, SCH decoding, all downlink channel decoding, speech decoding and A5. Uplink SDCCH is ROM-coded as well; RACH, FACCH/SACCH on TCH, uplink speech and uplink A5 are still encoded host-side in the full system, and that is the current work. The emulated DSP processes a 4.62 ms TDMA frame in 4.61 ms on a laptop.

What you can do with it. In effect, a root shell on each of the two processors of a baseband. The ARM firmware runs under gdb through QEMU’s gdbstub. The DSP has its own shell: stop it, dump the shared API RAM with every field of the ARM–DSP interface named and decoded, step it through the ROM. Put a breakpoint at the SB correlator, watch the 50-lag energy table fill, see which lag the ROM keeps and why. Two results from doing exactly that. OsmocomBB’s prim_fbsb.c has carried /* FIXME: where did this magic 23 come from? */ since April 2010. The ROM hard-codes a 191-sample SB window (stm #191,ar3), and 23 is the only margin for which layer 1’s window formula reproduces it: 148 + 2×23 − 3 = 191. The full chain (−23, +75 qbits, 16-qbit target) was then checked against logs from real Calypso phones found in the mailing-list archives: they land on the predicted values. A double subtraction nobody had noticed, present since a May 2010 refactoring, fell out on the way. Second result: the ROM’s burst emitter writes the complete access burst into the ABB script — training sequence, tails, I/Q inversion, A5 — bit-exact against libosmocoding. It took two missing instructions in my core (CMPR, LD src,ASM) to let it.

Honest state. The emulated core passes 150 of TI’s 230 worked instruction examples; 58 fail and 22 do not assemble yet. Every “the ROM does X” is conditional on that, and the talk says so. Most of the emulator’s code was written with an AI assistant; what decides whether it is right is none of that: the unmodified TI ROM, the unmodified OsmocomBB stack, a shadow mode comparing ROM and host encoders bit by bit, and the end-to-end bench.

Why it matters. 2G is still carried in tunnels, mines, railways (GSM-R) and in most of the world’s fallback paths. Its baseband has been a black box for twenty-five years. With this setup, anyone can watch one run, without hardware, without a licence, and check every claim against a public ROM dump and public source. The lab ships as a bootable ISO and Docker images, with srsRAN (4G over ZeroMQ, CSFB to the 2G core) and a multi-operator SS7 setup alongside.

What the audience sees. Live: the bench from boot to a voice call (about four minutes), with three consoles on screen — the DSP shell, gdb on layer 1, the phone’s VTY:

P:9002 D> d@ d_task_d 20
    W0    [0800]=000d  d_task_d           task 13 = TCHT
    W0    [0801]=0000  d_burst_d

P:9002 D> d@ 0862 20
    API   [0862]=3c92
    API   [0863]=3f92
    API   [0864]=3c92
Reading symbols from /opt/GSM/firmware/board/compal_e88/layer1.highram.elf...
The target architecture is set to "armv5te".
Remote debugging using 127.0.0.1:1234
l1a_l23_handler () at layer1/l23_api.c:650
650     msg = msgb_dequeue(&l23_rx_queue);
Continuing.
[cmd.gdb] osmocom panel loaded: help_osmo
% (MS 1)
% Call is answered

Then the inspection tools: the DSP paused at a frame boundary with its registers and the decoded ARM–DSP mailbox on screen, and gdb writing a string into the ARM’s RAM that the firmware prints on its own console. Slides only for the architecture and the two results.

What you will know on leaving. How a 2G baseband DSP is actually driven, what its ROM does at the instruction level for sync and channel decoding, how to build an emulator good enough to find bugs in your own emulator by reading the vendor’s code, and where the remaining walls are.

Notes to reviewers (not published) Everything claimed is reproducible from public material: the four repositories (osmo-operator, qosmo, c54x_exe, grgsm_exe, all under github.com/bbaranoff), the FreeCalypso ROM dump (ftp://ftp.freecalypso.org/pub/GSM/Calypso/dsp-rom-3606-dump.txt, not redistributed; the PROM0 used is identical to it word for word), and a binutils tic54x disassembler. Each sentence of the project pages is backed by a dated claims file (c54x_exe/docs/CLAIMS-2026-10-04.md) marking it VERIFIED / CORRECTED / OPEN with file and line. A one-line installer for the whole lab is at pl4y.store. Honest state: uplink is mixed (SDCCH in ROM, the rest host-side); the C54x core fails 58 of 230 of TI’s worked examples; downlink SACCH/8 often fails its FIRE check; two of the DSP unit tests in dsp_tester (nb, fb0/fb1) fail, while the end-to-end bench itself passes 25/25. Demo risk: everything runs on one laptop, no network needed; a recorded run is available as fallback (the linked video). I can do 40 or 60 minutes; 40 + Q&A is the natural length (one demo, two results). First talk at a Congress. English with a French accent; slides and all repositories in English.

Biography I’m an independent telecom engineer in Perpignan, France, about ten years in GSM and radio. Over the past eight months I built, alone, a software lab that runs the TI C54x DSP mask ROM of a Calypso baseband next to OsmocomBB’s layer 1 under QEMU, and used it to answer — I think — a fifteen-year-old FIXME in the OsmocomBB source. I’ve taught computer science and networking at university and spent a stint in a radio-security company. My code is on GitHub as bbaranoff; this is my first Congress talk.

Links - https://github.com/bbaranoff/c54x_exe - https://github.com/bbaranoff/osmo-operator - https://github.com/bbaranoff/qosmo - https://github.com/bbaranoff/grgsm_exe - Proof: https://github.com/bbaranoff/c54x_exe/blob/main/proof_toa_23.md - Video: https://www.youtube.com/watch?v=-UY50ZZ_mLc

Form Track: Hardware. Length: 40 min + Q&A.