Moog One - Initial Findings

The Linux subsystem to the Moog One was one of the reasons I was drawn to it, the potential hacking on it. Here are some of my initial findings from exploring Linux on the One. These notes are by no means complete or guarenteed to be correct. I hope to expand on each area at some point but wanted to get this out to help with others looking into the One.

When you break something, hold down the main encoder while powering on to go into a recovery mode. You can scroll through a couple firmware options, current, last installed and original v1.0.0.

Holding Home + Settings at the end of boot will launch into a service menu which has a few options. There is a phone home which initiates a SSH tunnel for someone to work on your One remotely. There is a fantastic splash screen for it:

References

A couple very long forum threads, mostly sonic related but there were a few references to system.

Amos discussing Moog’s new synth https://www.youtube.com/watch?v=V7gfaw0JQaE (local mirror Part 1, Part 2, Part 3, Part 4)

Effects

The on board effects are done with SuperCollider. They can take up a good chunk of CPU depending on which are enabled, a breakdown of CPU usage is in /usr/share/las-fx/util/cpu.rtf. This is one area that is definitely ripe for exploring, possibility of GUI elements and adding more SuperCollider effects.

  • /etc/init.d/S42sc launches las-sc which in turn starts a screen session for /usr/share/las-fx/launch-sc-1
  • Effects home /usr/share/las-fx lots of goodies to look through in there.

Firmware Updates

image-right

The firmware update file, eg: moog-one-v1.4.0, is a tar with a few files:

  • IMAGE-SIG GPG signature of rootfs
  • MANIFEST JSON file with some details of the update
  • MANIFEST-SIG GPG signature of the MANIFEST
  • MOOGFW Always 0
  • rootfs GPG Encrypted ext4 filesystem
    {
      "MOOGFW": "0",
      "version" : "las-v1.4.0",
      "format" : "re",
      "image" : "rootfs",
      "packed_size" : "156570496",
      "unpacked_size" : "669948928",
      "sig" : "IMAGE-SIG",
      "ctime" : "2020-06-15T15:10:32+00:00",
      "git" : "NULL"
    }

The rootfs file is encrypted but can be decrypted with keys in the One. /usr/bin/lasfwu handles the updates, verifying and installing. The private key is embedded? (stenography?) in this photo of Bob Moog. It is pulled out using /usr/bin/str which is small, could disassemble to find out for sure, maybe it’s just pulling out the least signifigant bits in the image which is hiding the GPG key.

I’m not sure if the available keys are enough to sign a modified firmware. It doesn’t really matter, we have access to the system no need to package and sign a new firmware. It is nice to be able to decode the firmware updates though. I’ve been doing this and running a diff between versions to identify points of interest.

# Get the keys from in the One
str /etc/bob.bmp 4 > /root/bob-pk

# Transfer these keys off the One:
/root/bob-pk
/usr/share/sec/mmepubk
/usr/share/sec/mmspubk

Now we can use the keys on another system to decrypt the firmware updates. If ever prompted for a password, it is bob.

tar -xf moog-one-v1.4.0
gpg --import mmepubk mmspubk bob-pk
gpg --always-trust --ignore-time-conflict --ignore-valid-from --passphrase bob --output "rootfs-decrypted.ext4" --decrypt rootfs
mkdir -p /mnt/one-fs
mount -t ext4 rootfs-decrypted.ext4 /mnt/one-fs

Open Sound Control (OSC)

This deserves a more thorough look. OSC is used to communicate between the front panel, voice cards, effects and more. I’ve tried, unsuccessfully, to send some simple OSC messages remotely to emulate keyboard input. Maybe missing some iptables rules. Even replaying tcpdumps didn’t work.

The program arguments help identify the different components to the system.

# Sound engine, runs as
$ /usr/bin/las-sc \
  -t vc \
  -f localhost:7775 \
  -l localhost:9300 \
  --vxfw=/usr/share/xmosfw/app_vx_10M_v1.0.14rc8.bin \
  --vxdb=/var/tuning.vxtune \
  --vcfw=/usr/share/xmosfw/app_las_v1.0.17rc2.bin \
  --vcfv=16781570 \
  --temp \
  --expr-syms=/usr/share/vx_ee.scm \
  --panel-state=localhost:9500 \
  -q


# The helpful usage output.
las-sc [options]
 -t, --target=ARG         Xmos Target address
 -l, --listen=ARG         Listen address (default localhost:9300
 -m, --mode=ARG           Put VC in given mode at startup
 -f, --fx=ARG             EFX Server address (optional)
     --manual-fx          Flag to indicate that fx will be booted manually, but that las-sc should still attempt to connect.
     --cli                Command-line interface mode - updates firmware, then exits without launching fx.
     --vcfw=ARG           Voice control firmware file. If not given, VC is not not checked or updated.
     --vcfv=ARG           Expected voice control firmware version.
 -p, --panel-state=ARG    Panel state query address.
     --vxdb=ARG           Voice Card Tuning Data
     --vxfw=ARG           Voice card firmware file. If not given, voice cards are not checked or updated.
     --force-vx-update    Update VX firmware even if versions match.
 -o, --ofs-cache=ARG      Offset cache file. If given, offset data are periodically gathered from the VX and written to this file. At startup, offsets are transmitted back to the cards.
 -v, --version=ARG        Display version information and exit.
     --temp               Enable SOM temperature polling.
 -m, --mod                Flag for VX HW Mod.
 -q, --quiet              Keep silent during operation
     --expr-syms=ARG      File containing symbols for use in expressions.
 -h, --help               Display usage text


The argument options for las-frontend won’t output from command line but this is what I found in the binary.

$ las-frontend \
  --usb-path=/media/thumbdrive \
  --data-path=/var/las-frontend \
  --host-paneloutput=203.0.113.2 \
  --host-performance=vc \
  --host-oleds=203.0.113.2 \
  --affinity-mask=1 \
  --host-systemclock=vc \
  --cookie=1 \
  --affinity-panel=1 \
  --startup-coordination \
  --host-vc=vc

# Usage found in binary
Usage: 
 [ commands ]
Commands:
  --version              Displays detailed version information
  --data-path=<path>     Configure which path to store the data files into
  --startup-coordination Coordinate the startup with the sound engine controller
  --example-data         Populate a seperate DB with example data and use it
  --disable-tests        Force the tests to not run, even for a debug build
  --enable-tests         Force the tests to run, even for a release build
  --cookie=<string>      Cookie value to write out once startup is fully completed
  --port-response=<p>    Sets UDP port to send OSC tree responses to (dflt 
  --port-panelinput=<p>  Sets UDP port to listen to for panel data (dflt 
  --port-paneloutput=<p> Sets UDP port to send panel messages to (dflt 
  --port-oleds=<p>       Sets UDP port to send OSC OLED messages to (dflt 
  --port-perfinput=<p>   Sets UDP port to receive OSC performance messages from (dflt 
  --port-perfoutput=<p>  Sets UDP port to send OSC performance messages to (dflt 
  --port-systemclock=<p> Sets UDP port to send system clock messages to (dflt 
  --port-vc=<p>          Sets UDP port to send OSC VC messages to (dflt 
  --port-efx=<p>         Sets UDP port to send FX server messages to (dflt 
  --host-response=<h>    Address for OSC tree response (dflt 
  --host-panelinput=<h>  Address for OSC panel input messages (dflt 
  --host-paneloutput=<h> Address for OSC panel output messages (dflt 
  --host-oleds=<h>       Address for OSC OLED messages (dflt 
  --host-performance=<h> Address for OSC performance messages (dflt 
  --host-systemclock=<h> Address for system clock messages (dflt 
  --host-efx=<h>         Address for FX server messages (dflt 
  --host-vc=<h>          Address for OSC VC messages (dflt 
  --vx-ee-path=<path>    Path for expression engine scm definition file
  --usb-path=<path>      Path for USB drive
  --firmware-path=<path> Path for firmware updates (overrides USB path)
  --firmware-dry-run     Performs the firmware update in dry-run mode
  --midi-in              Name of MIDI input device
  --midi-out             Name of MIDI output device
  --affinity-mask=<m>    Sets an affinity mask for the frontend threads
  --affinity-panel=<m>   Sets an affinity mask for the panel messages threads
  --enable-osc-sec       Send all sound engine messages through the old osc protocol
  --assume-auto-polling  Assume that auto polling is active by default
  --log-perf-osc         Enable logging of received performance OSC messages
  --log-panel-osc        Enable logging of received panel OSC messages
  --log-tree-osc         Enable logging of sent OSC tree message
  --log-thread-heartbeat Enable logging of thread activity
  --script=<path>        Runs the JavaScript at the provided file path
  --upside-down-ui       Renders the entire UI upside down
  --touch-to-vco         Generate VCO pitch offset messages for touch panel
  --always-on-top        Keep application always at the front of other windows

Other

# Set framebuffer opacity
$ las-fb-config framebuffer [0,1] [ alpha_val[0-255] ]