Platform index / Digital mixing console

Allen & Heath SQ-5

A 55 MB firmware image that contains none of the mixer. The audio path lives in FPGA fabric behind an undocumented AXI register map — and the fabric has now been opened far enough to read a pan-law table out of it.

DocumentedIntroduced 2018SQ seriesFPGA mixingZynq-7000Bare metalAMPNo signingNVRAM show imagesChecksummed

The load-bearing finding. The update package is 55 MB of ARM image and 2.5 MB of bitstream, and the 2.5 MB is the mixer. What looked like 40 MB of UI artwork also turned out to hold two more complete FPGA bitstreams, and the mixer's own fabric has given up the first data recovered from inside this console: a constant-power crossfade table, decoded twice by independent paths to the same bits.

Verdict. A poor rehosting target, but not for the usual reasons. There is no secure boot and no signing — yet none of the mixer is in the software you would replace. If it were ever pursued, the correct first move is JTAG, not the USB update path: dump the 64 MB QSPI intact before writing anything.

Method

Static analysis of a single vendor firmware update file, extended into the FPGA fabric itself. No hardware was inspected and nothing here was run on a console. The image was re-obtained in August 2026 and the container format re-verified against it, so every claim below is now re-derivable — an earlier version of this page recorded the image as lost. The fabric work goes bitstream → FASM → netlist → simulator, using Project X-Ray's bit-to-feature database and fasm2bels; the parts of that route which touch this console were run end to end, and the general route is described on the method page.

Artifacts examined

  • SQ-5UPG_1_6_3r6268.bin — three records, no compression, no encryption
  • SQuMixFPGA.bit — the 2.5 MB mixer bitstream, carved from the package: byte-swapped for the Zynq PCAP path and Vivado-compressed
  • Two Artix-7 bitstreams carved out of the region this page used to call artwork — the device-side images the console pushes to its remote I/O boxes
  • NVDATA.DAT and SCENE001.DAT written by SQ MixPad V1.6.0 running offline as an SQ-7 — two 128 KiB NVRAM images, and the controlled diffs taken across a single patch change

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
SoCXilinx Zynq-7000 XC7Z020 — proven from the bitstream's IDCODE configuration packet (30018001 → 03727093), not inferredVerified
CorroborationLinked Xilinx PS drivers: xemacps, xscugic, xdevcfg, xqspips, xiicps, xttcps, xuartps, plus lwIP 2.0.3 (xilinx_modified)Verified
FPGA countOne. xdevcfg with PCAP_FPGA_DONE_FAIL shows the bitstream loading into this same chip's PL over the PCAP bridge — there is no second FPGAVerified
DRAM≥1 GB — inferred from CPU1's 0x20100000 load address (513 MB in) against the Zynq-7000 PS ceiling of 1 GB. No memory-controller config was decodedInferred
Boot flashDual-parallel QSPI NOR, ~64 MB (InitQspi2Dual). Dual-parallel means two devices striped — a naive single-chip dump gets every other byteVerified
Surface MCUA fader/surface MCU flashed over SPI from the ARM (Expected Fader Version %u.%u, updating...)Verified
FX boardSeparate board with its own DSPs and SDRAM (FX board ID 0x%02X not recognised, FX[0] failed SDRAM test)Verified
Mixer bitstream — it is compressedSQuMixFPGA.bit uses Vivado bitstream compression: 6,021 configured frames written by FDRI, plus 4,024 frames filled by MFWR multi-frame writes. This matters more than it sounds, because the standard open-source frame reader parses MFWR into a named packet and then discards it — so a compressed bitstream does not error, it yields a frame set with frames missing or duplicated, and that corruption stays structured all the way through FASM into a netlist that still simulates. Expanding the compression correctly is the first gate on any fabric work hereVerified
Mixer fabric — frames placed5,935 mixer logic frames placed at absolute device addresses. Compressed bursts auto-increment through the device's own frame ordering rather than through consecutive addresses, so placement needs the part's geometry, not arithmetic. Two independent placement paths were run against each other and initially disagreed on 1 frame in 124 — the cause was the single MFWR immediately after a CMD=MFW, which has no address of its own because it primes the mode; applied as a frame write it overwrites one real frame silently. Verification also has to account for 2 pad frames after each block-type/half/row group, twelve in total on this partVerified
Mixer fabric — first data recovered from inside itExactly two initialised block-RAM halves are configured in the whole mixer design, and their contents decode to a crossfade / pan-law table pair: a symmetric sine-shaped bell rising 0→31→0 across 49 points, and its complement falling 61→32→61, the two summing to roughly a constant — which is what a constant-power pan law looks like — alongside higher-entropy coefficient lines. The validation is that the two halves decode bit-identically from different base addresses and word offsets: two independent paths through the geometry cannot agree by accident. This is the first data recovered from inside this console's fabric rather than from the software around itVerified
Remote-I/O bitstreams — hiding in the artworkThe ~40 MB region this page described as uncompressed artwork is not all artwork: it embeds two complete Artix-7 bitstreams, both plaintext, carved out and identified as XC7A15T (0x0362E093). They are the device-side images the console pushes down its SLink/gigaACE port to a remote I/O box, so they are the far end of the link, not fabric inside the console. They are two different designs and not one design compressed twice: one is uncompressed with no SPI-boot configuration, the other sets the boot-SPI registers and carries initialised memoryVerified
One of those images is shipped by three consolesThe smaller of the two is byte-identical — same SHA-256 over all 1,154,836 bytes of configuration data — to a bitstream embedded in the Qu-7 and Avantis update packages. Allen & Heath ship one common remote-I/O device image across three product lines a decade and two platform generations apart, which is a stronger statement of shared architecture than any string match on this siteVerified
Remote-I/O fabric — recovered and simulatedThat bitstream was taken all the way back to a netlist and elaborated in a simulator without error: 4,206 6-input LUTs, 3,625 flip-flops, 12 block RAMs, 3 clock managers. It went further than the mixer could because it is roughly twenty times smaller and has no processor system to model. The design partitions cleanly by clock domain into a 240 MHz audio datapath — 2,427 elements, heavy on shift-register primitives, almost no feedback — and a 180 MHz protocol engine which is 30% of the flip-flops but 103 of the design's 159 state machinesVerified
Remote-I/O fabric — the PHY, and why it matters hereThe link PHY is LVDS SelectIO with source-synchronous SERDES — 107 input serialisers, 29 output serialisers, 65 delay elements and zero gigabit transceivers. Corroborated independently by the clocking: all three clock managers run a 900 MHz internal frequency from three different input clocks (50, 36 and 28.125 MHz), and one produces a 180 MHz pair 90° apart, which is a source-synchronous capture clock and nothing else. This is load-bearing for the question of whether the console could speak the far end's protocol, because SelectIO is ordinary I/O that the console's own XC7Z020 has — its clg400 package has no gigabit transceivers at all, so a transceiver-based PHY would have ended the questionVerified
Remote-I/O fabric — where the audio crossesAll twelve block RAMs are simplex buffers, written on one port and read on the other, never both. Four are 16-bit × 2048 control buffers; eight are 24 bits wide, which is the console's sample width stated by the fabric rather than by a specification. Four of the twelve are asynchronous — written on one clock and read on another, in both directions across the 180/240 MHz boundary — and those four are the clock-domain-crossing FIFOs where link audio enters and leavesVerified

Software architecture

ItemFindingConfidence
Operating systemNone. Zero FreeRTOS, ThreadX or Linux strings — a bare-metal Xilinx standalone BSP with a custom message-block system and a custom GUIVerified
Core modelAMP across both Cortex-A9s, not SMP. CPU0: sending Start Msg to CPU1Verified
CPU0sQu_Host at 0x00100000 — mixer control, GUI, protocolsVerified
CPU1sQu_USB at 0x20100000 — SQ-Drive: USB host, FAT, WAV. Directory layout /AHSQ/USBRec, /AHSQ/Scenes, /AHSQ/Shows appears verbatimVerified
Container header0x70 (112) bytes, computed as next_offset − this_offset − payload_len and confirmed independently at both gaps. It is not read from any fieldVerified
Payload formatDespite .elf names the payloads are raw ARM32 images, each with a 16-byte preamble; byte 16 onward is the ARM exception vector tableVerified
Code fractionOnly ~10–16 MB of the 55 MB host image is code. From 16 MB on it compresses to 9–27%, i.e. uncompressed artwork and fontsVerified
What the console writes to diskNo container at all: flat, fixed-size binary NVRAM images, one per file, each exactly 128 KiB — NVDATA.DAT for global and setup state, SCENE001.DAT and its siblings for scenes. Both open with a similar 20-byte header differing in a single leading type tag, and a scene carries its name as text a few bytes in. This is a memory image written to disk rather than a document format, which is consistent with the bare-metal architecture aboveVerified
The input patch is global, not scene dataEstablished by controlled diff in MixPad offline: changing one input's socket moved five bytes, all of them in NVDATA.DAT, and the scene file did not change at all. So a patch list must be read from the global image, and recalling a scene does not repatch the console. The Avantis behaves the same way for the same reason, which makes it worth expecting across the manufacturer's rangeVerified
Channel state is a fixed-stride record arrayThe patch byte is not in a flat table — it sits inside a per-channel record at a 336-byte stride, as a 0-based socket index. The array runs to 122 records, well past the input channels and on into stereo inputs and mix objects at the same stride, with nothing in the file marking where one kind of object ends and the next beginsVerified
Names are not in the channel recordOf the 336 bytes in a record, 22 fall in the printable range and none of them is text, so the channel name lives in a separate table that a default show leaves empty. It has not been located, and MixPad appears not to expose channel naming at all — tried on the strip name button, the selected-channel name, press-and-hold, right-click and the strip-assign grid. That is an absence of evidence rather than a finding, and a show saved off a real console with named channels would settle itVerified

Update path & security model

ItemFindingConfidence
Image signingNone. No RSA, SHA or AES strings anywhere in either imageVerified
Update validationCRC only, and the variant was not identified — Error in firmware header, VerifyFlash Expected CRC to be 0x%lx, but calculated 0x%lxVerified
Bitstream encryptionNot encrypted. The CTL0 write is 0x00001501 with the DEC bit (bit 6) clear and no key-load sequence, so the bitstream is analysableVerified
RecoveryA/B image banks with Zynq multiboot. The update overwrites the inactive bank; the first-stage bootloader is not in the update file and is not protected by the A/B schemeVerified
EntitlementAn entitlement mechanism exists and was identified. Analysis stopped there — see the methodology pageVerified
The show image carries a four-byte checksumThe last four bytes of NVDATA.DAT change with every edit. Harmless for reading and a hard blocker for writing: a file assembled with a stale checksum may simply be refused, and there is no way to find out without a console. The Yamaha .CLF is in exactly the same position — two unrelated manufacturers, the same integrity check with no authenticity in it, and the same consequence for anyone hoping to write a show file rather than read oneVerified

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. 1Interoperability, not rehosting

    The SLink slot takes gigaACE, Dante and Waves cards, and Allen & Heath publish the SQ MIDI/TCP control protocol. Almost anything that motivated looking at the firmware in the first place is better served here, and none of it needs reverse engineering.

  2. 2The AXI register map — the one thing genuinely worth reversing

    Map the PS↔PL interface and the black box becomes documented hardware: you could drive the stock mixing engine from your own software, which is a far better position than replacing either half. It is also reachable non-destructively, with the stock bitstream loaded and nothing written to flash.

  3. 3The PL bitstream

    No longer "in principle" — the compression has been expanded, 5,935 frames placed, and the initialised memory decoded to a pan-law table. But the ceiling is real and it is specific: the open-source bitstream-to-netlist path does not support the DSP48 arithmetic primitive, which on a mixing engine is the part you actually want. You can recover the memories, the logic and the interface around the arithmetic, and not the arithmetic. That makes the bitstream a good route to the register map and a poor route to the algorithms, which is the reverse of what it looks like from outside.

  4. 4Linux on the PS

    Entirely feasible and almost pointless on its own — it gets you Linux wired to a black box you cannot command. Worth doing only as a means of probing the AXI map.

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.

  • A parser assuming a 0x24 or 0x40 container header parses record 0 plausibly and then lands mid-payload in 55 MB of ARM code and artwork.
  • The correct load mapping for the host image is VA = file offset + 0x103DD0, pinned empirically from the GUI string-pointer table — not the 0x100000 the container header implies.
  • GUI strings are reached through a master string-pointer table indexed by string ID, so they have no direct LDR-literal cross-reference. Only BSP and system strings are loaded directly.
  • Bitstream compression fails silently, not loudly. The standard frame reader decodes the multi-frame-write packet into a named object and then drops it. Feed it a compressed bitstream and you get no error and no warning — you get a frame set that is quietly wrong, and it stays plausible through every downstream stage. Check for those packets before trusting anything built on the frames.
  • Carved filenames are a guess, and these ones were wrong. The two remote-I/O bitstreams were carved and named for a part that the die measurement and the IDCODE then contradicted. A filename you invented during extraction is not evidence, and it will be quoted back at you three documents later.
  • "Twenty block RAMs in two columns" was an artefact of the decode, not a finding. An early pass matched initialised memory by shared column base address and reported ten times too many, because roughly ten tiles stack per column and differ only by word offset. Each tile's own word window has to be checked. The corrected answer is two.
  • Looking for a patch table by scanning for an ascending run of bytes. A default show is patched 1:1, so the values do run 00 01 02 03 … — but 336 bytes apart, not adjacent. The scan finds nothing, and the obvious conclusion from that — that the format has no patch table — is wrong. The same heuristic works on the Avantis and on the Yamaha .CLF, which is what makes it dangerous here.
  • Anchoring a record signature on a neighbouring byte. The byte after the patch field is a patched/unpatched flag, so requiring it silently dropped every unpatched channel — eight of forty on a default SQ-7 — and produced a patch list with fewer rows than the console and nothing to say any were missing.
  • Diffing before the app has written anything. MixPad flushes CurrentShow on logout, not on edit, so a diff taken straight after a change shows zero bytes moved and looks exactly like a format that does not store the setting.

Open questions

  • The PL's AXI register map is entirely undocumented — this is the whole audio path, and it is the single most important missing piece.
  • The FX board's DSPs are a genuine gap: not the vendor, not the architecture, not how code reaches them. The FX[0] indexing implies more than one.
  • The first-stage bootloader is not in the update file and has never been seen. The A/B banks protect the application images, not it.
  • The debug UART is near-certainly populated (xuartps is linked and printf diagnostics are everywhere) but has never been located on a board.
  • What the rest of the mixer's memory holds. Only two block-RAM halves are initialised at configuration time and those are the ones read out; every table the console writes at runtime — every fader law, every filter coefficient it computes — is invisible to a static bitstream read by construction.
  • Whether the recovered remote-I/O netlist actually behaves. It elaborates in a simulator, which proves it is structurally coherent, not that it is functionally faithful; nothing has been driven through it and no output has been compared against a real device.
  • The arithmetic. The bitstream-to-netlist route has no support for the DSP48 primitive, so the mixer's multiply-accumulate structure — the actual mixing — cannot be recovered by this path at all. Nothing short of a different toolchain or a live bus capture changes that.
  • Which socket class the patch index refers to. MixPad offers Local, SLink, USB and I/O Port tabs and only a Local patch was tested, so whether the class is encoded elsewhere in the record or in a separate table is unknown. The byte alone should not be assumed to identify a connector.
  • Where channel names live, and whether MixPad can write one at all. Both are open, and the second is what decides whether this can be settled without a console.
  • The rest of the 336-byte record — preamp, EQ, dynamics — none of which has been mapped.

Status of this entry. A written teardown exists and its claims carry evidence citations. 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