Platform index / Digital mixing console

Yamaha DM7

Not one console CPU but a small cluster of identical i.MX8M Mini computers running one Linux rootfs in four roles — and the only platform here that ships its entire mixer parameter model as plain XML.

PartialIntroduced 2023DM series (codename "hagoromo")Linuxi.MX8M MiniNamed-component archiveXML parameter modelSHARCDanteMBDF presets

The load-bearing finding. app/Descriptor/mms_*.xml — 27 files, 1,701 collections, 2,693 parameters — declares every parameter's C type, array dimension, minimum, maximum, default and step, and every collection's packed datasize. That describes the console's binary state layout, not merely its parameter names, and it ships in a downloadable update. The audio itself is off-CPU on Yamaha SSP3 DSPs and a SHARC, exactly as the QL's was.

Verdict. The audio is off-CPU on Yamaha SSP3 DSPs and a SHARC, so this is no more a rehosting target than the SQ-5 or the HD96. What is different is everything above the DSP boundary: where the HD96 documents itself in Thrift and Protobuf, the DM7 hands over a typed, dimensioned, byte-sized schema of its entire mixer state as XML in a public update. This is a console to interoperate with, and almost all of that work can be done before touching one.

Method

Static analysis of the public firmware image DM7_firmware_V1.75.bin (release V1.75, main system R1.02): a walk of the container format, extraction of the Linux root filesystem and console application, a C++ RTTI type-name census of the stripped application binary, and disassembly of a small number of functions. No hardware was involved and no console was opened.

Artifacts examined

  • DM7_firmware_V1.75.bin — 174,392,092 bytes, 23 members, format #YAMAHA MBDFArchive
  • app_console.tar.xz V1.75 — the console application: three role binaries, 67 plugin .so, 27 XML descriptors
  • rootfs-DM7-2026-01-29-…tar.xz R1.02 — the arm64 Linux root filesystem
  • DOM 4.2.8.7 — a nested #YAMAHA MBDFArchive carrying its own kernel, initramfs, dom.dtb and three Xilinx bitstreams
  • installer/install_script R0.20 — the update procedure, in plain bash
  • DM7 Editor — 27 parameter descriptors and 303 .dm7p presets shipped with the free editor. No factory scenes: this is the one model in the family whose console-wide state file has not been read

No manufacturer firmware, binaries or documentation are redistributed here. Artifacts are referenced by name and version only. See the method and legal statement for the basis on which this analysis was performed and the boundaries it observes.

Hardware architecture

ItemFindingConfidence
Application processorNXP i.MX8M Mini (fsl-imx8mm), arm64 Cortex-A53 — from the device trees, /etc/os-release and /boot/imx-boot-eMMC_dm7_20231128.binVerified
System topologyFour board roles boot from one root filesystem, selected by device tree: main, bay, ctrl (the CTL-DM7 surface) and main-jig (a factory test rig). A DM7 is a cluster of identical i.MX computers, not one CPU with peripheralsVerified
Mixing DSP2 × Yamaha SSP3 at IC120 and IC123, plus a third for USB audio at IC136/IC124. The application's own factory-diagnostic strings print the board reference designators and BGA ball coordinatesVerified
Effects DSPAnalog Devices ADSP-21469 SHARC, over SPI, on the NAIO board — the symbol CspiNaio21469SharcController names transport, board and part in one string. More than one is present (SHARC#%d, kernel [dspNo])Verified
FPGAs and CPLDsPUBe and PY64-MD are Xilinx 7-series bitstreams; NAB is an Altera .rpd and NAB_L a Lattice ECP5 .bit at the same version V0.33c; HIC, HIC_L and FDC are JAM STAPL JTAG programming streams. Each identified from its own magic bytesVerified
Xilinx parts, by nameThe two 7-series members name their own devices in the bitstream's IDCODE configuration packet: PUBe is an XC7A35T (0x0362D093, 3,330 configured frames) and PY64-MD an XC7A100T (0x03631093, 7,464 frames). Both are Vivado-compressed — they carry multi-frame-write packets, which a frame reader that ignores MFWR will silently mis-expandVerified
Second-sourced siliconThe _L members are the same board in different fabric — NAB/NAB_L share V0.33c and HIC/HIC_L pair the same way, with the console programming whichever it finds. The contemporaneous Behringer X32 image carries the same Xilinx/Lattice pairing, so a second-source bitstream is itself a fingerprint of a 2021–2023 respinInferred
Dante subsystem (DOM)A second computer, not a chip: Xilinx Zynq-7000, dual Cortex-A9, 512 MB, Micron n25q512a QSPI boot flash, two Cadence GEM MACs for Dante primary/secondary, running its own Linux. From the decompiled dom.dtb, model = "YAMAHA DOM". The part is XC7Z020 in the clg484 package — its three bitstreams are stock .bit files, so they carry Vivado's own header naming the part 7z020clg484, the top-level design khaju_hc_top, the toolchain 2019.2 and a build date of 2025/07/18, the three SRC variants differing only by build minute. That is the same device as the SQ-5 mixes on, doing an entirely different jobVerified
Dante bridge fabricA custom Yamaha FPGA IP block in the DOM's programmable logic, compatible = "xlnx,akashi" at 0x60000000, with interrupts named ts/rx/tx/rxerr/smi and rx_act/meter/rx_ka/daif. Three shipped bitstream variants (noSRC, syncSRC, asyncSRC) select the sample-rate-conversion modeVerified
MicrocontrollersSeven ARM Cortex-M images — JK (AES I/O), P-U2S2, P-MD2, P-HR1, P-FDC2 (panel boards), PY-MIDI-GPI (slot card) and USB2HOST — each identified from its vector table. Two SRAM bases appear (0x2000_0000 and 0x1000_0000), so at least two MCU families are in use. USB2HOST is filed as DSP_V105.bin but is a 3.8 MB Cortex-M image, not DSP codeVerified
Ethernet switchMarvell 88E6352 managed switch, configured from userspace — the application names 88E6352 PORT#0, PORT#5 and PORT#6, so at least three ports are software-visibleVerified
Internal networkscontrol on 192.168.53.100/24, the three expansion bays on 240.0.10.x/24, and Dante as a MACVLAN parent with its own MAC carrying dante0 and dante1. The bay links use IANA-reserved 240.0.0.0/4 space, which is a good fingerprint for telling console plumbing from console I/O in a captureVerified

Software architecture

ItemFindingConfidence
Operating systemNXP i.MX Release Distro 4.19-warrior, image ID=ymh-cpum-wayland (Yamaha CPU-M, Wayland), Linux 4.19, systemd, Weston and Qt, plus about ten yamaha-*.service unitsVerified
Console applicationapp_console_{main,bay,ctrl}, arm64 ELF, stripped — unlike the DM3's, which ships with named functions. Retained build paths disclose the source tree: project codename hagoromo, internal framework Citrus, an OpenCV-linked AI core Trident, and a vendored shureacnVerified
Parameter model27 mms_*.xml descriptors: 1,701 collections, 2,693 parameters, 6,572,842 bytes of declared datasize. Every parameter carries a C type and array dimension; numerics carry minimum, maximum, default and step; collections carry arraysize and the packed byte size of one instanceVerified
Control protocolsThree. Yamaha SCP (232 recovered types, the complete command set with client and server sides), a Yamaha OSC dialect addressed /yosc: (30 server commands, 12 notifications), and a vendored Shure ACN SDT/DMP stack for wireless microphone control with a Yamaha-written discovery supplementVerified
SCP and YOSC are one modelYOSC is an OSC-shaped front end onto the SCP engine, not a second control model — every YOSC concept is a wrapper class over the SCP implementation of the same thing, and SCPMODE exists as a command in both. The competing reading, two independent engines, is unsupported: the type census contains no second parameter engineInferred
OSC address grammar/yosc:%s/%s/ts: — the ts: segment is a path into the parameter tree whose names line up with the descriptor collections, and subscribe is a distinct verb, so the protocol is subscribe/notify rather than poll-only. The two %s fields are unresolved; a device or session identifier and a target name is inference from shape onlyInferred
Service portsNot recovered, and possibly not constants. Only four bind call sites exist in 22 MB of .text because the application uses standalone Asio, and none yields a port; no port-shaped literal sits near any protocol symbol; the only mDNS service types in the binary are Audinate's. A YSDP class family — responder, listener and a per-host service list — is present, and its wire format is undeterminedUnknown
Plugin ABIThe same Perseus ABI as the QL. createPerseusPlugin_203 appears verbatim in both, the coefficient address format is unchanged in shape, and four Premium Rack plugins have byte-identical step/pmcoef/dmcoef profiles across the two consoles — the same algorithms across a decade and two CPU architecturesVerified
Console plugin linkage67 separate .so files under /yamaha/app/Plugins — 34 algorithms in GUI/DSP pairs — loaded at runtime, where the QL statically links its Premium Rack into the firmware image. All 34 DSP resource manifests were lifted statically from .rodata, with no host services involvedVerified
SHARC algorithm codeNot present anywhere in the image. Established by scanning all three application binaries, both Perseus libraries and every device member — 17 files, roughly 150 MB — for ADSP-214xx loader block chains, which finds none. There is also no NAIO firmware member in the update at allVerified
Mixing coefficient layerMix1000DSP (213 recovered types) is the SSP3-side layer and names the whole mixer signal path, with array dimensions readable from its template arguments — 32 in-ports, 16 and 4 out-ports, a 20-tap port delay, a 32 × 8 port filter. It sits on a generic DspFramework whose class names are shared with the DM3Verified
InstallerPlain bash. For each member it compares a version file against the installed copy, deletes and re-copies on mismatch, runs an optional per-member hook to flash the device, repeats the procedure for each mounted bay, and returns early on a control-surface CPU. About a third of the script is a recovery branch for one shipped root-filesystem bugVerified
Shared codebase with the DM3SystemSetting.ini is headed "DM3シリーズ本体用" — for the DM3 series. Its ApplicationType key enumerates firmware, fader_iqc, editor and emulator, so the same binary lineage runs off-console, and UseMMSExplorer names a built-in browser over the parameter tree that ships switched offVerified
The shipped parameter model predicts the file layoutThe XML above is not only a description of the running console — it is the decoder for what the console writes. The DM7's input-channel record is declared 1,785 bytes × 120, with a nine-byte input-patch field at offset 93 and the signal selector ahead of it: a different shape from the DM3 and TF pair, which put a patch field at offset 100 and differ from each other in its width. Same container across the family, different layout in every modelVerified
The one model whose declared size does not add upSumming each collection's size × array length in document order gives 1,784 against a declared 1,785, so there is a padding byte somewhere in the record and its position is not stated. The DM3 and TF sum exactly, so a decoder written and tested against those two would never discover the discrepancy — it would simply read every DM7 field after the padding one byte earlyVerified

Update path & security model

ItemFindingConfidence
Image signingNone. Neither the container nor installer/install_script carries or checks a signatureVerified
EncryptionNone — every one of the 23 member payloads is a zlib stream, and the two .tar.xz members are wrapped in zlib stored blocks so a reader can decompress unconditionallyVerified
Per-member integrityNone. There is no digest field per member and nothing to check a payload against; the only integrity-shaped field in the whole format is 20 bytes in the archive headerVerified
Archive header id20 bytes at offset 0x34. Not a SHA-1 of the image or of any obvious sub-range. Every nested archive carries its own and all four observed values begin 5601, which reads more like a version or type prefix than a pure digestUnknown
Update validationThe installer validates nothing beyond comparing a version file, so a member whose version string is unchanged is not reinstalled even if its contents differ. This is a statement about the container and the installer only — whether the bootloader or the running application validates an image was not establishedVerified
Plugin loadingThe effect-plugin host authenticates nothing. There is exactly one dlopen call site in the whole application binary; the function that reaches it contains no hash, signature, certificate or filesystem-permission check, and the selection of what to load is a filename pattern rather than a name whitelistVerified
Filesystem postureThe root filesystem is mounted read-only by a systemd hook; /yamaha is a separate writable partition, which is what the installer copies into and where the plugin directory lives. Whether any unprivileged or remote path can write there was not examinedVerified
Cryptography that is presentThe binary's OpenSSL surface is real but belongs to the TLS/Dante paths and to an AES-256-CBC console-settings encryption path. None of it sits on the update or plugin pathsInferred

These rows describe how a platform validates a firmware image, because that is a structural fact about its architecture. They are not a vulnerability disclosure and no exploit, bypass or circumvention technique is published here. Licensing and entitlement mechanisms are out of scope throughout — seescope boundaries.

What is programmable

  1. 1An offline client against the shipped parameter model

    The descriptors give types, ranges, array dimensions and packed sizes, so the state layout can be reconstructed and the datasize arithmetic self-checks without hardware. The SCP and /yosc: command vocabularies are already recovered, which leaves only the transport blank — and the transport is a discovery protocol to be captured, not a port constant to be guessed.

  2. 2The Perseus effect-plugin surface

    Plugins are separate loadable objects here rather than statically linked as on the QL, and the load path performs no authentication. What that reaches is the host-side coefficient computation, the parameter model and the GUI — not proven custom SHARC execution, because the SHARC algorithm code is not in the image and a plugin ships coefficients to a kernel that is already resident. extRAM is absent from all 34 manifests, so no shipping Yamaha plugin uses the SHARC's external SDRAM.

  3. 3The mini-YGDAI (PY) slot

    The same route the QL offers — custom processing in the audio path with no console modification — and the image confirms the slots carry their own Cortex-M firmware and, for PY64-MD, a Xilinx bitstream. The DM7's host-side slot interface was not examined, so this is the least investigated of the three.

Traps

Mistakes this analysis actually made, or came close to making. They are recorded because each one produces a plausible-looking wrong answer rather than an obvious failure.

  • The container's section alignment is 4 bytes, not 2. A 2-byte assumption walks the first three sections correctly and then desynchronises at the NAB member onto a plausible-looking wrong magic. Validate the walk by landing exactly on #END, never on the first few hops.
  • var_len is not the offset to the payload. It is the string-area length plus a constant 8, and the payload begins at the 4-byte-aligned end of the three NUL-terminated strings — a different number whenever those strings are not a multiple of 4. Parse the strings and align; do not do arithmetic on the field.
  • The payloads look like xz and are zlib. The two .tar.xz members carry the xz magic a few bytes in, behind a zlib header wrapping a deflate stored block, so treating payloads as xz appears to work on exactly those members and fails on every genuinely compressed one.
  • Regex-scanning for the #… section magics finds hits inside compressed payloads. The chain has to be walked from 0x48, not pattern-matched.
  • The port hunt's near-misses are worse than its failures. Walking back from the bind call sites yields plausible port-shaped immediates — 4096, 3072, 25600 — which are byte-swaps of the small integers 16, 12 and 100. Reading any of them as a port number would have produced a confident, wrong, publishable answer.

Open questions

  • The ports for SCP and /yosc: are not recovered and may not be constants. The real target is the YSDP wire format, and a single broadcast capture from a console would settle it far more cheaply than more disassembly.
  • Whether anything outside the container validates an update. The container does not and the installer does not; the bootloader and the running application were not examined.
  • Where the SHARC algorithm code lives. It is proven absent from the image, and residency on the NAIO board fits the absence of any NAIO update member — but that is not proven.
  • The coefficient block format the plugin side emits is documented nowhere in the image, and it is the real ceiling on the plugin route. So is whether a plugin configuration transfer can introduce new SHARC program code or only reconfigure resident kernels.
  • The 20-byte archive-header id and the kind field (8 versus 12) are both undecoded; kind correlates loosely with unpack-versus-flash but the installer member breaks the pattern.
  • The DSP wire format, the FPGA register maps and the bay synchronisation protocol are untouched.
  • No claim here has been checked against a DM7. One pass, one firmware image, no hardware.
  • Where the DM7's padding byte sits. The record sums one byte short of its declared size, and until that is located every field beyond it is suspect on this model alone.
  • What a DM7 scene looks like. The editor ships 303 presets and no scenes, so the console-wide state — the file a patch list would come from — has not been seen for this model, only for its smaller siblings.

Status of this entry. Substantial findings recorded, but whole subsystems remain unexamined. Nothing on this page has been verified against physical hardware — no unit of this platform has been opened, connected to or modified.

← Back to the platform index