Files
qunexus-firmware/README.md
T
nils 27c21396f8 QuNexus v2.2.1 firmware: reverse-engineered disassembly & pseudocode
Decompiled from stock QuNexus_Firmware_v2.2.1.bin (EFM8UB20F64G / 8051,
base 0x2400, 54279 bytes) with radare2 6.2.0.

- qunexus_v2.2.1.asm : full linear disassembly (37287 lines, byte-faithful)
- pseudocode_all.c   : r2 pdc pseudocode for all 1002 functions
- functions.txt     : function index (1002 functions)
- regen.sh + r2script.r2 : one-command reproduction (brew install radare2)

Verified: reconstructing the binary from the asm byte-columns reproduces the
original image byte-for-byte (30560 instructions + 195 data gaps).
2026-08-17 22:22:21 +02:00

77 lines
3.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# QuNexus firmware v2.2.1 — reverse-engineered source
Disassembly and pseudo-decompilation of the Keith McMillen / KESUMO QuNexus
application firmware (EFM8UB20F64G, an 8051-core MCU), produced with radare2.
This is a **nested git repository** (its own repo, living under the parent
`qunexus-qt6` project). It is self-contained: the stock input binary is
included so every artifact here can be regenerated with one command.
## Input
| File | What |
|---|---|
| `QuNexus_Firmware_v2.2.1.bin` | stock v2.2.1 application image, flat binary, base `0x2400`, 54 279 bytes, spans `0x2400`–`0xF806`. (The bootloader region `0x0000`–`0x23FF` is not in this image and is not decompiled here.) |
## Generated artifacts
| File | What | Lines |
|---|---|---|
| `qunexus_v2.2.1.asm` | **Full linear disassembly** of the whole image, absolute code-space addresses (`0x2400`+), with xrefs & comments. Nothing omitted. | 37 287 |
| `pseudocode_all.c` | r2 `pdc` C-like **pseudocode for all 1002 functions**. 668 complete; 334 end with `// chop` (r2's size limit on big functions — see those in the asm). | 38 396 |
| `functions.txt` | r2 function index: `address size nblocks name` — 1002 functions. | 1 002 |
## Reproduce
```
brew install radare2 # one-time
./regen.sh # rebuilds the three artifacts from the .bin
```
`regen.sh` runs `r2 -a 8051 -b 8 -m 0x2400 -i r2script.r2 QuNexus_Firmware_v2.2.1.bin`.
`r2script.r2` is the exact radare2 script used.
## Faithfulness — does it re-compile?
The disassembly is **byte-faithful**: reconstructing the binary from the asm's
byte columns (30 560 instructions + 195 small data gaps) reproduces the
original 54 279-byte image **byte-for-byte**. So the listing is a complete,
accurate representation — nothing lost or corrupted.
The r2 `.asm` file is **not** directly valid input to an 8051 assembler (it is
r2 display format: function borders, xref comments, `fcn.xxxx` labels, address
prefixes). To re-assemble into a flashable binary it must be converted to a
real assembler's syntax (e.g. `sdas8051` from SDCC, or Keil A51): strip r2
annotations, turn `ljmp`/`lcall` targets into labels, emit the 195 data gaps as
`.db`, and set `.org 0x2400`. With that conversion it re-assembles to the
identical binary. (Round-trip via SDCC is the natural next step if needed.)
## Known landmarks (verified in the output)
| Address | Meaning |
|---|---|
| `0x2400` | app reset vector (`ljmp 0xb691`) |
| `0xA57B` | USB-MIDI router: cable number → destination ring buffer |
| `0xDF05` | USB-MIDI event dispatcher |
| `0xDF28` | `LCALL 0xA57B` — the single call site the USB-1→CV patch retargets |
| `0x8126` | 23-byte `0xFF` padding region the patch's stub is written into |
| `0xE8E6` | `LJMP 0x0000` — the only bootloader-entry jump |
| `0xB48D` | SysEx command handler (bootloader-entry path) |
## Caveats
- r2's 8051 auto-analysis is decent but imperfect: data-in-code regions decode
as the matching instruction (a linear-sweep artifact). Use `ljmp`/`lcall`/
`acall` targets and `functions.txt` as the map of real code.
- `pdc` chops ~1/3 of functions (the big ones). The asm listing covers them
fully. For unchopped Ghidra-quality pseudocode, the `r2ghidra` plugin
(`r2pm install r2ghidra`, then `pdg @ func`) is the upgrade path.
## Provenance
Decompiled 2026-08-17 from the stock `QuNexus_Firmware_v2.2.1.bin` (the same
image shipped in the qunexus-qt6 editor's Qt resources as
`QuNexus_Firmware_v2.2.1-cs512.syx`). The reverse-engineering was done in
service of a USB-1→CV routing patch (see `../patch_usb1_to_cv.py` and
`../c2probe/`); this repo captures the reference disassembly of the unmodified
firmware.