Emulating the baseband

40C3 · Hardware

Bastien Baranoff

2026-10-08

Emulating the baseband

40C3 · HARDWARE

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.

I just wanted to make a cfile with fake_trx… and ended up emulating a DSP.

Speaker note — Say the subtitle as written. The talk is about the lab and the DSP: how the call got made, and how it was verified. How the code was written gets one slide, later, and no more.

Section 1 · The descent

From a cfile to the DSP

Nohl’s demo, minus the airwaves

THE PLAN

  • Capture GSM traffic as IQ samples (cfile)
  • Decode it with gr-gsm
  • Go all the way down to the encryption
  • Legally: my own network, my own phone, my own samples, nothing on the air

cfile → Wall 1 → Wall 2 → Wall 3 → C54x → Call

bursts ≠ cfile

WALL #1

fake_trx speaks bursts. Nohl’s demo needs IQ samples. The layer I needed was exactly the one being skipped.

phone ⇄ fake_trx (TRXD bursts over UDP) ⇄ BTS

No modulation, no signal, nothing to record.

QEMU doesn’t know Calypso

WALL #2

  • No IQ without a real phone layer 1
  • Real layer 1 = OsmocomBB firmware running on a TI Calypso
  • QEMU: Calypso not implemented

So I made a machine…

THE FIX

  • Implemented a Calypso machine in QEMU
  • OsmocomBB layer 1 boots on it

…and it needed the help of other machines.

One phone, two chips, zero hardware

TWO MACHINES

The ARM

Calypso in QEMU, running OsmocomBB layer 1

The DSP

A 1990s C54x, emulated from scratch

The ARM is the real OsmocomBB firmware. The DSP runs the real TI ROM. Wrong emulation → no sync, no call.

Section 2 · The emulated phone

How it works

Layer 1 thinks it’s on a real phone

VIRT_CALYPSO

  1. QEMU calypso-high (ARM946) boots the OsmocomBB loader
  2. Layer 1 arrives over the emulated UART: pty → socat → osmocon -m c123xor
  3. Layer 1 wakes the DSP: polls DSP_DL_STATUS at 0xFFD00000
  4. Every 4.615 ms: IRQ 4 → tasks in API RAM → TPU → burst out on UDP 4729 (TRXD) → IRQ 15

osmocon → Layer 1 → DSP → BTS

I faked the DSP

WALL #3

  • DSP_DL_STATUS: BOOT → READY, version 0x3606… answered by QEMU, not a DSP
  • FCCH found, SCH decoded, BSIC… all invented
  • Layer 1 believed it. No signal processing ever happened.

The shortcut · first

Shunt the DSP with gr-gsm

The hard way · last

Emulate the real C54x

gr-gsm as the DSP

THE SHORTCUT

  • Layer 1 tasks → handed to gr-gsm instead of a DSP
  • gr-gsm does the GMSK modulation and demodulation
  • Real IQ samples at last → the cfile exists ✅

It worked. So… why not the real DSP? Half the work was already done.

Who does the signal processing?

THE MODES · ARM LAYER 1 IN QEMU, ALWAYS

OBTAINED

  • v1 · gr-gsm — gr-gsm does the DSP’s job. No TI code.
  • v2 · ROM — Real TI ROM on the emulated C54x: downlink, Viterbi, vocoding.
  • v3 · shadow — ROM and host encoder side by side: 98.1 % identical bits on 215 SDCCH uplink blocks.

SOUGHT

  • full ROM — Every layer 1 task through the ROM, uplink coding included.
  • native — Host code in the DSP’s exact slot: same API RAM, same formats. No TI code.
  • free DSP — A free C54x firmware on the same emulated core. Long shot.

Same layer 1. Different brain underneath. Now the brains check each other.

The real C54x

THE HARD WAY

  • A TMS320C54x emulator, native, outside QEMU
  • Running the real DSP code
  • Layer 1 talks to it through the API RAM, like on a real Calypso
  • Voice goes through the DSP chain

C54x (real TI ROM) ⇄ ARM layer 1 (API RAM) ⇄ Bridge ⇄ osmo-bts-trx

No more faking on the downlink. Uplink coding: the ROM is checked in shadow mode before it drives the BTS.

Section 3 · Verification

How it was verified, and the proof

The lab vs the OSI model

WHERE IT SITS

Layer On the radio link Who
7 Application Call, SMS, USSD mobile + Osmocom core
4 to 6 none on the radio link core only: SIGTRAN, IP
3 Network RR, MM, CC mobile ↔︎ BSC, MSC
2 Data link LAPDm mobile ↔︎ osmo-bts-trx
1 Physical TDMA, GMSK, A5, Viterbi ARM layer 1 + C54x, real TI ROM (downlink)
1 bis GSM IQ over Ethernet next step

Everything above layer 1 already existed. The phone-side layer 1 is the new part.

How it was verified

THE METHOD

  • The TI ROM (green oracle) — Code I did not write, for the real chip. It runs or it doesn’t.
  • Osmocom layer 1 (green oracle) — Does not believe a wrong DSP. No sync, no call.
  • Shadow mode (grey oracle) — ROM vs host encoder: 98.1 % identical bits on 215 SDCCH blocks.
  • End-to-end bench (grey oracle) — 23/23 scenarios. 1 kHz in, 1 kHz out.

Green oracles can prove me wrong without my help. Grey ones share my assumptions: they catch implementation bugs, not misunderstandings. Internal coherence is not correctness.

Full disclosure: most of the emulator code was written with an AI assistant. The oracles above are what makes that acceptable: none of them were.

Speaker note — Say the disclosure line once, plainly, and move on. The ROM, Osmocom, the shadow mode and the bench did not come from the assistant, and they are what decides whether the DSP is right.

Proof

23/23

automated end-to-end bench, DSP mode, 0 failures

  • Camp, attach, location update, ciphering through the emulated A5 coprocessor
  • SMS MO/MT, USSD, call, second phone
  • Voice: 1 kHz in → 1 kHz out, 100% energy in 950–1050 Hz
  • The real TI ROM does FCCH, SCH, BCCH, Viterbi, vocoding
  • Uplink coding by the ROM, shadow mode: 98.1 % bit-identical
  • Cfiles recorded both ways

Real-time margin: 4.3–4.6 ms of DSP work per 4.62 ms frame — github.com/bbaranoff/tests

Honest coverage

WHAT DOESN’T WORK (YET)

32 1 2 2
handled degraded not handled not observed
  • Speech frames flagged bad (B_BFI): open point #1
  • No frequency hopping
  • A5 confirmation on the BTS side: degraded

Full run report: rpubs.com/bbaranoff

A full GSM voice call

DEMO

A full GSM voice call

phone (QEMU + C54x) ⇄ bridge ⇄ osmo-bts-trx ⇄ Osmocom core

Nothing on the air.

The only one I know of, and I looked. If you know another, I want to see it.

Speaker note — The biggest claim of the talk: say it exactly as written, as a question to the room. Play the clean recording first; live is the bonus.

Three consoles, one phone call

LIVE · UNDER THE HOOD

DSP · Harvard shell (NDB, API RAM)

P:9002 D> d@ d_task_d 20
[0800]=000d d_task_d   task 13 = TCHT
[0802]=000d d_task_u   task 13 = TCHT
[0808]=3d23 d_fn       fn_report=35 fn_sid=61
[0809]=0011 d_ctrl_tch TCH_FS, TCH_F
[080c]=0409 a_a5fn[0]  T2=9 T3=32  (A5)
[080f]=fd44 d_afc      -700

ARM · gdb on layer 1 in QEMU

$ telnet 0 44444
Reading symbols from layer1.highram.elf...
Remote debugging using 127.0.0.1:1234
l1a_l23_handler () at layer1/l23_api.c:650
650  msg = msgb_dequeue(&l23_rx_queue);
(gdb) _

Mobile · OsmocomBB VTY

OsmocomBB(mobile)# call 1 600
% Call is proceeding
% Call is answered

Same instant, three views: the DSP’s task registers mid-TCH, the ARM firmware under gdb, the phone in a call. Nothing here is a mock-up.

Section 4 · What it is for

Research, teaching, networks

A real baseband, visible down to the signal

WHAT IT’S FOR · RESEARCH

  • Baseband security — Fuzz and trace the real DSP firmware, no phone, no RF
  • Bug replay — Replay IQ bit-exact into the real TI ROM
  • Labelled IQ datasets — Legal, fully known content and A5 keys
  • Nohl-style demos — Legally, on your own cfiles
  • SS7 research — On a virtual multi-operator network

A full mobile network per laptop

WHAT IT’S FOR · TEACHING AND TESTING

  • Teaching — From signal to call, no hardware, no licence
  • Technician training — Without touching a live network
  • Osmocom CI — Test every change down to layer 1
  • 2G sunset and CSFB — What devices do when 2G degrades or disappears
  • Channel emulation — Noise, fading, interference vs the real DSP

When 2G leaves the air

WHAT IT’S FOR · NETWORKS AND PRESERVATION

  • Virtual phones, real BTS — IQ → SDR → coax or fiber
  • Multi-cell networks — Handovers in a software air
  • GSM-R, tunnels, DAS — Validate without blocking a track
  • GSM-R → FRMCS — Test 2G and 4G/5G coexistence
  • Preservation — A living, replayable baseband after the networks are gone

Section 5 · Next

Next steps and how to try it

MS over any PHY

WHAT’S NEXT

  • Full ROM: uplink, RACH, FACCH, TCH through the real DSP code
  • Native mode: the DSP’s slot, no TI code
  • Export the IQ out of the machine: Ethernet, coax, fiber
  • Fix the open points: B_BFI, hopping
  • GSM-R features: group calls, priorities

MS (ARM + C54x) → IQ → Ethernet · Coax · Fiber

The phone doesn’t exist. Its signal does.

pl4y.store

TRY IT

pl4y.store

  • Bootable ISO
  • Docker images
  • All the code (GPLv3), test bench included
  • TI ROM not included: fetched from FreeCalypso

Thanks: Osmocom, fixeria, FreeCalypso, TI, Claude, and everyone who reverse-engineered the Calypso before me.