QEMU Calypso — emulating a GSM baseband
No C123 on your desk? Boot the baseband in software. Same firmware, same osmocom stack, no RF licence — the whole 2G phone side, reproducible on a laptop.
The Motorola C1xx phones (C118/C123/C121) run a TI Calypso baseband: an ARM7TDMI driving a C54x DSP over shared memory. OsmocomBB normally replaces that firmware on real hardware. This workflow runs the same firmware inside a QEMU fork (bbaranoff/qemu) that emulates the Calypso SoC — so you can bring up a 2G phone, camp on a cell, do a Location Update, send SMS and place a voice call, all in software.
The full bundle (sources, headers, DSP internals, scripts) is served on pl4y.store/calypso/, and the live test snapshot on pl4y.store/tests/.
Why emulate instead of flashing a phone?
No hardware hunt. Calypso handsets are eBay-only and dying. QEMU never wears out.
Reproducible. A crash is a rerun, not a resolder. Every burst is inspectable.
Debuggable. GDB on the ARM, memory watches on the ARM↔DSP mailbox — things you simply cannot do on a sealed baseband.
Safe & legal. The radio is a shunt to
gr-gsm, not an antenna. Nothing is emitted.
The pieces
+-------------------------------------------------------------+
| QEMU (bbaranoff/qemu) — emulated TI Calypso SoC |
| |
| ARM7TDMI <--- shared-memory mailbox ---> C54x DSP |
| (osmocom-bb firmware, unmodified) (L1 / framing) |
+----------------------------|--------------------------------+
| L1CTL over a virtual link
v
+-------------------------------------------------------------+
| osmocom network-in-the-box (osmo_egprs) |
| osmo-bts -- osmo-bsc -- osmo-msc -- osmo-hlr |
+----------------------------|--------------------------------+
| IQ / burst shunt
v
gr-gsm (no real RF)
ARM side runs the unmodified osmocom-bb firmware — the same Layer-1 control it would run on a real C123.
DSP side does the GSM framing/correlation. It is not fully reversed yet, so the heavy signal path is a shunt through
gr-gsmrather than a bit-exact C54x emulation. Voice and SMS work; the DSP is a work in progress.osmo_egprs is the operator side: a full multi-PLMN core in containers, shipped as a bootable ISO. See pl4y.store/osmo_egprs/.
Workflow — from zero to a call
1. Get the platform.
Grab the osmo_egprs ISO (bootable, network-in-the-box) or clone the repos:
git clone https://github.com/bbaranoff/osmo_egprs
git clone https://github.com/bbaranoff/qemu # the Calypso-aware fork
2. Build the QEMU fork. It emulates the Calypso SoC target; build it like any QEMU, then boot the firmware:
cd qemu && ./configure --target-list=arm-softmmu && make -j$(nproc)
3. Bring up the network side. Start the osmocom stack (osmo-bts / bsc / msc / hlr). On the ISO this is one launcher; from source it’s the standard osmo-* services wired to the same GSMTAP loopback.
4. Boot the baseband in QEMU. Launch the emulated Calypso with the osmocom-bb firmware. The ARM comes up, hands Layer-1 to the DSP shunt, and the phone starts scanning.
5. Camp on the cell.
Watch the L1 sync: FCCH → SCH → BCCH. When the SI reach Layer 3 (the gsm322
state machine), the phone camps. This is the first milestone — no camp, no service.
6. Location Update + TMSI.
The phone sends RACH → gets an IMM ASSIGN → does a SABM on SDCCH → the network
answers LU ACCEPT and hands a TMSI. You’re now attached.
7. SMS and voice.
MT/MO SMS works in A5/0 and A5/1.
Voice (TCH/F) works through the shunt path — established call, real audio.
8. Inspect and verify. Every step is observable: GDB on the ARM, GSMTAP in Wireshark, and the automated pytest suite whose latest run is published at /tests/ — pipeline coloured by pass ratio, so you see exactly where the chain breaks.
Known limits (be honest)
The DSP is not fully reversed — the signal path is a
gr-gsmshunt, not a cycle-accurate C54x. It’s a POC for voice, not a spec-complete baseband.The interpreter-based C54x path is slow; native front-end acceleration is ongoing.
A5/1 works; authentication is the current lock for the full A5/1-over-the-air story.
Where to dig
/calypso/ — the full source bundle (ARM↔DSP glue, DSP internals, scripts).
/osmo_egprs/ — the operator-side platform (Docker, configs, network).
/tests/ — the live test snapshot (what passes, what breaks, right now).
github.com/bbaranoff/qemu — the Calypso-aware fork.
See also: OsmocomBB for the real-hardware path, and A5/1 for the cipher.