Hardware and software reverse-engineering of the Allen & Heath GLD digital mixer series.
The first step is getting hold of the firmware files, which are available on the Allen & Heath website, by selecting the Legacy Products and GLD-80 options. Luckily, when downloaded, we don't get an encrypted, proprietary file format, but a plain .zip, which when unpacked gives us a complete directory structure:
AllenHeathGLD
| - Firmware.md5
| - Firmware
| - Help
| - iGL-Firmware
| - Library
| - OS
| - Shows
| - Translations
| - Updater
Of these, the iGL-Firmware and OS folders look the most interesting at first glance.
The iGL-Firmware folder contains five key files, plus their version files:
| file | type | role |
|---|---|---|
iGL-Firmware |
i386 ELF, stripped | the main application, this is what runs on the SBC |
iGL-Bootloader |
i386 ELF, not stripped | recovery/update screen |
iGL-DSPBoard.bin |
ARM Cortex-M image | the DSP board's firmware |
iGL-ProcessingBoard.bin |
ARM Cortex-M image | the processing (control surface) board's firmware |
iGL-MotorFader.bin |
ARM Cortex-M image | the motor fader board's firmware |
The OS folder contains Linux shell scripts, kernel modules, configuration files, an ELF executable, deb packages, and udev rules, which form the userspace around the system.
These findings already confirm what the console's boot screen hinted at: a full Linux system runs on the internal SBC, based on a Debian-derived distro.
In xinitrc we find the state machine that starts up the firmware, and it also turns out there's a debug backdoor: if a USB drive is plugged in at boot with an AllenHeathGLD/ah_debug file on it, the system starts an SSH server for remote login, and opens an xterm session instead of launching the firmware. This is enabled by the start on ah_debug line in /etc/init/ssh.conf, meaning sshd doesn't start at all by default, only this event wakes it up.
If we create this file and try to log in, it naturally asks for a password. Fortunately someone has already cracked it, and it's posted on the Allen & Heath forum: https://forums.allen-heath.com/t/linux-login-password-for-gld-80/23380/2. The username is ubuntu, the password is digital.
It's worth rewriting the xinitrc file so that in debug mode it doesn't open the xterm window, but instead continues on to start the firmware. This way, we have an SSH connection to the machine even while the console is in normal use.
On a running console we can also confirm with lsusb what we already knew from the service manual and the firmware updater: the SBC talks to the individual subsystems over USB. All three boards show up under the same A&H vendor ID (22F0), each with its own product ID and character device file:
| USB VID:PID | description | /dev node |
|---|---|---|
22F0:0002 |
USB2SPI | /dev/ah_usb_dsp |
22F0:0003 |
iLive USB2SPI | /dev/ah_usb_proc |
22F0:0004 |
iLive MOTFADS | /dev/ah_usb_motor |
The descriptor strings are still contain "iLive" - the GLD simply reuses the iLive USB descriptors. The same boards are also matched by the .ko kernel module and .bin firmware we already found in the firmware updater.
The live system yields further interesting finds, such as revealing exactly what operating system and motherboard it's running on. The distro is Ubuntu 11.10 (i386), with its own patched kernel (3.16.1.ah.2), running on a Fujitsu D3003-S1 motherboard with an AMD G-T44R (Bobcat) CPU. Beyond that, we can also find data sitting in the rootfs as plain text that should never have made it onto production hardware, but I won't go into further detail on that here.
The service manual and the inspection of the motherboard already outline the structure of the console. The SBC runs the Qt4 UI and controls the fader board, the processing (control surface) board and the DSP board via USB. On each of the three boards, an ARM Cortex-M microcontroller receives USB commands, and dispatches them to the other chips on the board or handles them by itself.
The DSP board is the most interesting one: here, two Spartan-3A FPGAs and eight DSP56300 signal-processing chips do the actual audio processing, while the board's ARM controller is just the intermediate layer. On startup, it uploads the FPGA bitstreams and the DSP code images, and it's the one that receives and dispatches incoming USB commands to the whole audio processing pipeline.
Taking a look at the iGL-Firmware executable with Ghidra reveals a gold mine of information. Although the iGL-Firmware binary is stripped, the __PRETTY_FUNCTION__ and __FILE__ strings left behind in the error-handling branches give away almost the entire source tree. From this, almost a thousand function names and hundreds original source file paths could be recovered. The code decompiled by Ghidra was analyzed with Claude Code, which revealed a lot of useful information about how everything works, essentially the entire source code could be restored this way.
The biggest surprise is that the binary doesn't just control the hardware, it has everything the hardware runs, embedded inside it: all FPGA bitstreams and DSP code images sit right there in the data section, and the SBC uploads them over USB to the boards at power-up. This is fantastic news, since it means we can write our own custom program without ever having to flash anything on the hardware itself.
Searching through the binary, a total of seven bitstreams were found and extracted. The first two are the DSP board's own FPGAs (the IG, presumably responsible for routing, and the AF, the chip that speaks the dSNAKE network protocol), while the other five belong to the various expansion boards (option cards):
| id | part | size | role |
|---|---|---|---|
0x12 |
XC3S400A | 235,820 | DSP board IG FPGA - presumably a routing matrix between the DSP chips and the inputs/outputs |
0x15 |
XC3S200A | 149,516 | dSNAKE FPGA |
0x19 |
XC3S200A | 149,516 | ACE option card |
0x19 |
XC3S200A | 149,516 | MADI option card |
0x19 |
XC3S200A | 149,516 | Mini Multi Out card |
0x19 |
XC3S50A | 54,664 | option card (id 11, purpose currently unidentified) |
0x19 |
XC3S50A | 54,664 | Dante / Waves option card (shared carrier board) |
The eight DSP chips actually hide 16 logical cores, two per chip, as the silkscreen labeling on the board itself already suggests. Six smaller DSP56725AF chips provide cores 0-11, and two larger DSP56720AG chips provide cores 12-15.
Alongside the two larger 56720AG chips sit a total of four 48LC4M16A2 SDRAM chips on the board, split 2-2 across the two core pairs, while the smaller 56725AF chips have no external memory at all. This is because cores 12-15 run the system's FX engines (reverb, delay, and other long, memory-hungry effects), for which the DSP's internal memory would be too small. Cores 0-11, handle input channel processing and mixing and RTA/metering, where the on-chip memory is enough.
Similarly to the FPGA bitstreams, 4 DSP code images turned up the same way from the firmware, and from these we can also tell exactly how large a program each physical DSP core runs:
| cores | chip | words used |
|---|---|---|
| 0-5 | 56725AF | 3394 |
| 6-10 | 56725AF | 2386 |
| 11 | 56725AF | 2572 |
| 12-15 | 56720AG | 3077 |
The FX engine is split across 8 stereo slots on these two chips, 2 slots per core. Each slot gets a 128K-word range from the external SDRAM as its own ringbuffer. A DSP56300 word is 24 bits, so that's 128K × 3 bytes ≈ 384 KB per slot. From this we can already derive the longest available delay time: 131,072 words, at a 48 kHz sample rate that's 131072 / 48000 ≈ 2.73 seconds, which is confirmed by the Stereo Tap Delay FX's help page: "Provides a clean digital delay with a maximum delay time of 2.7 seconds".
The code of the FX programs isn't part of the boot images, but many smaller separate code images that the firmware only loads when a preset is recalled for an FX slot. The 31 code images are located in the binary data section of the iGL-Firmware, similarly to the boot images, each given 1024 words of space, and the firmware delivers them to the right DSP core's FX slot using the same P-memory writing mechanism it used to upload the main program at boot.This dynamic loading is what makes it possible for an FX slot to be reprogrammed to a different effect at any time, over USB, without a DSP reset and thus without any audio dropout, and it also allows a custom-build effect to be placed in a slot instead of the factory 31 code images.
Running the Qt4 UI without hardware in a Podman container, and replacing the GLD hardware with a Python simulation script that impersonates the otherwise USB-connected subsystems via a PTY, made it possible to capture the boot sequence that had previously only been derived from static reverse engineering as real, live traffic. On the DSP board's USB channel (/dev/ah_usb_dsp), the iGL-Firmware brings the board up live in the following order:
-
Version request to every board (
00 03 01frame)The boards send back an 11-byte response starting with
"Version...". If this doesn't come back, the UI immediately switches to a "Boot Failure" screen.
-
Putting the peripherals into an idle state
A sequence of zeroed-out port pins (
SetPortPinon pins12,14,13,10,11), with every FPGA and DSP still held in reset. -
Identifying the IG FPGA
A
target=0x0A opcode=0x10frame gets an'H'or'I'response from the board, which decides which bitstream variant needs to be uploaded. -
Uploading the IG FPGA bitstream
Port pin reset (
5,0then5,1), checking theINIT_Bsignal (GetPortPin(1) == 1), then the bitstream goes out in 235,820 bytes, across 461 blocks of 512 bytes (the bitstream can be found in the extractedfpga_ig_xc3s400a.binfile). The loader waits for theDONEsignal (GetPortPin(3)) in a busy-wait loop; if it never becomes1, the application spins there forever, with a black screen. -
DSP reset and code upload
SetPortPin(9,1), then(15,0)/(15,1)for the DSPs' own reset, followed by uploading the 4×4096-word code image. Each DSP's own internal ROM only loads the first 2048 words to addressP:$0000; the image's own stub, starting at$0100, then pulls in the remaining 2048 words toP:$0800itself. -
Handshake
Y:$12C = 0x555555(the "go" signal) to every core, then a 200 ms wait on the host side, and finally readingX:$5C: all 16 cores must return 57, which signals that the heartbeat counter is running, i.e. the DSP has actually started up. After 5 failed attempts the firmware gives up, with a"DSP Programming failed"error.
The entire chain - IG FPGA upload, DSP reset, code upload, handshake - completes in a live measurement in under 2 seconds (UID Complete in: ~1.8 s). The dSNAKE FPGA and any option card follow the same mechanism, just with different pin assignments and a different bitstream, once the main DSP chain is already up.
It is important that this sequence runs every time the firmware starts, there is no EEPROM in the system, the entire code image and bitstream set comes fresh from the SBC binary every time.

