U-Boot selects an A/B slot and verifies it [1, 6].
system_a/b is read-only under dm-verity [1, 6]
/data is a separate writable userdata partition [1].
Test 1: Temporary boot parameter
Question: can Linux start a maintenance shell from a one-boot kernel argument?
U-Boot: append init=/bin/sh to the boot arguments temporarily in RAM.
Boot the known _a slot with hb_avb_helper.
We skipped eco_ab_select to avoid updating the A/B boot-attempt record.
Outcome: no shell obtained
UART echoed id and Ctrl-C, but returned no prompt or command output. The echo does not confirm that the shell started. No flash or boot files changed; power-cycle restored the normal environment [1].
Test 2: use the bundled recovery image
boot_a is a FIT bundle with two boot configurations [1, 8]:
Configuration
Contents
boardid-0x2000
Normal mower boot
boardid-0x010202
x5-evb-v2-recovery with a ramdisk
We loaded boot_a into RAM at 0x90000000, then selected recovery:
bootm 0x90000000#boardid-0x010202
This ran the bundled recovery configuration for one boot; it did not install a new bootloader or write the image to flash.
Neither temporary boot gave us a shell
The init=/bin/sh attempt echoed id and Ctrl-C, but returned no prompt or command output.
The recovery configuration gave no UART output, USB device, or normal LAN address.
These tests were inconclusive—not root access. Power-cycle restored normal boot.
Find the boot hook from U-Boot
Read-only inspection: we examined selected files on system_a at U-Boot to trace the startup sequence [1]. No full image dump or system-partition write was involved.
U-Boot tools:ext4ls lists files; ext4load reads them into RAM; md.b displays bytes.
The marker enables agetty but supplies no credentials. I left it absent.
The root shell uses a separate hook: /data/autostart/*.sh, launched after ROS [1]. Neither this hook nor its installation depends on the failed boot-parameter experiment.
Export userdata over USB
Reach U-Boot (UART)
Interrupt autoboot over serial and wait for Hobot>
Send ums 1 mmc 0:10 at the prompt [1].
Export userdata (USB)
U-Boot presents the eMMC filesystem as USB mass storage.
The host detected a 10.5 GiB ext4 disk at /dev/sda.
Install the hook (USB)
Mount the disk on the host
Copy the startup script, sync and unmount before stopping UMS.
Successful route to the root shell
Reach U-Boot: connect UART and interrupt autoboot at Hobot> [1]. No boot-parameter change is needed.
Install the hook: run ums 1 mmc 0:10. Mount the exported ext4 userdata on the host; copy o500/tools/goat_serial_bootstrap.sh to autostart/10-serial-root.sh, set mode 0700, then sync and unmount cleanly.
Boot normally: after ROS starts, autostart.service runs the script as root. It stops serial-getty, configures /dev/ttyS0, and launches Bash. Verify: GOAT# id → uid=0(root).
Separate failed test: init=/bin/sh is unrelated. UMS mapping is firmware-specific. The hook persists in /data; remove it through UMS.
ADB was not a useful route
After the root-shell path was established, the USB-A port was checked: it enumerated as hobot / xj3, but ADB remained unauthorized [1].
No ADB shell or filesystem commands were attempted; this route was not investigated further.
Get Hydra talking locally
Hydra is the mower process that connects to Ecovacs’ MQTT endpoint [1].
Endpoint: jmq-ngiot-*.
Hydra config option mqCa points to a writable TLS trust file: /data/certs/master.pem.
We redirected the MQTT endpoint to a local TLS listener (signed by a short-lived test CA) and placed both certificates (Ecovacs, ours) in /data/certs/master.pem:
❌ Ecovacs CA first: TLS handshake failed.
✅ Test CA first: TLS 1.3 handshake succeeded.
Restored the original trust file, removed the redirect. MQTT authentication or commands not tested.
MQTT framing observed
With the TLS trust path established, our metadata probe acted as a permissive MQTT peer, not a full broker [1]:
It accepted Hydra’s MQTT 3.1.1 CONNECT without checking the username/password.
It did not request a robot client certificate; the live Ecovacs endpoint does.
Hydra sent four QoS-1 subscriptions; the probe acknowledged them.
Implication: a local broker can skip Ecovacs client-certificate and MQTT credential checks. Bumper supports a dedicated MQTT listener, but O500 compatibility has not been tested [2].
Still unknown: command and status topics, payloads, and a working start/stop/status loop. The stock app’s HTTPS API is separate.
UART RX failure ended this test run
Before the interruption
We installed a /data/autostart bootstrap and verified a root shell on normal boot.
We redirected Hydra to a local TLS/MQTT probe and observed CONNECT plus four subscriptions.
Then: UART RX stopped accepting commands. Normal boot still reached GOAT#, but commands returned no output. The echo source and electrical cause remain unverified [1].
Open question: Bumper supports a dedicated MQTT listener, but O500 topic and status handling have not been tested [1, 2].
What we proved and what remains
Proven
/data/autostart yields a root shell.
Successful local TLS 1.3 handshake.
A stub MQTT peer
acceptedCONNECT,
acknowledged four subscriptions,
skipped AuthN/AuthZ.
Still unknown
MQTT command and status topics and payloads.
Whether Bumper can work with the O500.
Whether local start, stop, and status are possible.
How the stock app hands off to MQTT; its API is separate HTTPS.
Afterward: RX damage blocked maintenance access
The earlier UART setup reached U-Boot, accepted commands, and enabled the root-shell installation. After the RX pin was damaged, maintenance input stopped working.
Normal boot still reaches GOAT#, but id produces matching bytes on the adapter RX without visible command output. The echo source is unverified; the command may not be reaching Bash.
The bootstrap remains installed. UART cannot currently remove it, UMS cannot be started, and USB ADB remains unauthorized [1].
Questions
What result would change your mind about local control?
Literature · research & community
[1] Philipp A. Baer. Ecovacs GOAT O500 research log. Field notes, captures, firmware inspection and test results; updated 26 Oct 2026.
[2] Brian Martin. “How does Bumper work?”. Bumper project documentation, GitHub; describes its emulation of Ecovacs cloud services and observed XMPP/MQTT paths. Accessed 26 Oct 2026.
[3] Rickard Nord. Ecovacs Mower for Home Assistant. Open-source integration, GitHub; GOAT-specific MQTT commands and state handling. Accessed 26 Oct 2026.
[5] Ecovacs Robotics. Ecovacs Open Platform. Official developer portal; consulted 26 Oct 2026. Its public API is distinct from the private NG-IoT endpoint discussed here.
[8] Marian Balakowicz, Bartłomiej Sieka, and Simon Glass. Flattened Image Tree Specification, v1.0. Open Source Firmware Foundation, 11 Apr 2026; FIT image components and configurations.
Slide deck changelog
26 Oct 2026 · feat: Generate deck changelog and align graph typography (#35)
26 Oct 2026 · fix(o500): open slides outside VitePress client router (#34)