--- title: SP Flash Tool on Linux (MT6592): S_COM_PORT_OPEN_FAIL (1013) in BROM, then "PMT changed for the ROM" date: 2026-10-03 summary: Writing /system on an unrooted MT6592 handheld from Linux. BROM port-open fails because new cdc_acm rejects TIOCCBRK; Download refuses with "PMT changed". Use SP Flash Tool v5.1648, an LD_PRELOAD shim, Preloader mode and write-memory at the physical address. tags: firmware, mediatek, mt6592, sp-flash-tool, mtkclient, android, kernel, linux environment: Arch Linux, kernel 7.2.3 (cdc_acm); SP Flash Tool v5.1648 Linux (console mode); mtkclient (git 2026-09-12); target: MT6592 clone handheld, Android 5.1, 8 GB eMMC, unlocked BROM (no SBC/SLA/DAA) author: shaun, written up with Claude status: published --- ## Symptoms Goal: replace one file (`/system/media/bootanimation.zip`) on an unrooted MediaTek MT6592 Android 5.1 device by writing a modified `system` image over USB from Linux. Every tool failed in a different way. **mtkclient** reads the eMMC fine, but every write hangs forever right after the command header: ``` DaHandler - Writing offset 0x5000000 with length 0x100000 DeviceClass - [LIB]: TX:62 ... DeviceClass - [LIB]: TX:00100000 ``` In BROM mode with `--preloader`, it got stuck one step earlier instead: ``` DALegacy - M_EXT_RAM_SIZE : 0xc000000 DALegacy - Uploading stage 2... DALegacy - Waiting for response ... ``` **SP Flash Tool** (Linux, console mode `flash_tool -i config.xml`): - v5.2228: its `MTK_AllInOne_DA.bin` has no MT6592 entry. - v5.1916: `Failed to Connect DA: S_FT_DA_NO_RESPONSE(4001)` right after `100% of DA has been sent`, in both BROM and Preloader mode. - BROM mode (`0e8d:0003`, vol-up held), even when run as root: ``` USB port detected: /dev/ttyACM0 Connect BROM failed: S_COM_PORT_OPEN_FAIL(1013) [COM] Failed to open COM port. ``` - Preloader mode (`0e8d:2000`) with v5.1648, "Download Only" of just the system partition: ``` DA Connected Uncaught BaseException in main(): PMT changed for the ROM; it must be downloaded. Please select "Format All + Download" scene and try again ``` Do **not** follow that hint. "Format All + Download" erases the whole device, userdata and NVRAM included. ## Root cause Four independent problems: 1. **`S_COM_PORT_OPEN_FAIL` is not a permissions problem.** `strace` shows the `open()` of `/dev/ttyACM0` succeeds. SP Flash Tool then calls `ioctl(fd, TIOCCBRK)`, which returns `-1 EOPNOTSUPP`, and the tool gives up. Recent kernels' `cdc_acm` refuses break requests when the device does not advertise break support in its CDC descriptors. The MediaTek BROM does not advertise it, while the Preloader does. That is why only BROM mode fails. Older kernels silently accepted the request, and this 2016–2019 tool assumes that. ``` openat(AT_FDCWD, "/dev/ttyACM0", O_RDWR|O_NOCTTY|O_NONBLOCK) = 10 ioctl(10, TCSETS2, {c_cflag=B115200|CS8|CREAD, ...}) = 0 ioctl(10, TIOCCBRK) = -1 EOPNOTSUPP (Operation not supported) close(10) ``` 2. **The DA version matters.** The download agent (DA) in SP Flash Tool v5.1916 (`MTK_AllInOne_DA_v3.3001.2019-04-24`) never answers on this board. The one in **v5.1648** (`v3.3001.00.00`) works. It is byte-identical to the `MTK_AllInOne_DA_mt6590.bin` that mtkclient ships, which is why mtkclient could always connect and read. 3. **mtkclient can read but not write here.** With the legacy DA it sends `SDMMC_WRITE_DATA` (0x62) and waits for an ACK that never comes, and it has no timeout. Separately, in BROM mode it sends the **first** DRAM (EMI) entry from the preloader rather than the one matching the eMMC ID. This preloader holds four entries; the matching one was number 3 (LPDDR3, 1 GB). The first one is LPDDR2, so stage 2 crashes (note the `M_EXT_RAM_SIZE : 0xc000000`). Reordering the entries in a host-side copy of the preloader fixes the DRAM setup, but the write still hangs. 4. **"PMT changed" is SP Flash Tool's own arithmetic.** Its detailed log (`/tmp/SP_FT_Logs/.../QT_FLASH_TOOL.log`) names the partition: ``` CheckPMTLayoutChange(): PMT changed for : addr<0x7f800000>-->addr<0x7f800000>, len<0x151300000>-->len<0x151b80000> ``` The tool auto-sizes the last partition (userdata) to fill the eMMC, but counts boot1 + boot2 + RPMB (4 + 4 + 0.5 MB = 0x880000) into the total. The device's real table, written at the factory, does not. The scatter file can't override this, because the tool recomputes the size. ## Fix Use the raw **`write-memory`** command instead of "Download". It writes a file to an explicit physical eMMC address and skips the partition-table comparison. It is also unforgiving: you own the address, so take a full dump first and verify placement. **1. Dump everything and find the real layout.** Use mtkclient (reads work). MT65xx devices keep a "PMT" table near the end of the user area, with magic `1vTP1.1`, 96-byte entries (`name[64]`, `size u64`, `region u64` (1 = boot1, 8 = user), `offset u64`, `mask u64`), and a mirror 4 KB later. Here `ANDROID` (system) was at physical `0x5000000`, size `0x60000000`. **2. Shim the break ioctl** so BROM mode works too (Preloader mode does not need it, but it does no harm): ```c // brkshim.c — gcc -shared -fPIC -O2 -o brkshim.so brkshim.c -ldl #define _GNU_SOURCE #include #include #include #include #include int ioctl(int fd, unsigned long req, ...) { static int (*real)(int, unsigned long, ...); if (!real) real = dlsym(RTLD_NEXT, "ioctl"); va_list ap; va_start(ap, req); void *arg = va_arg(ap, void *); va_end(ap); int r = real(fd, req, arg); if (r < 0 && errno == EOPNOTSUPP && (req == TIOCSBRK || req == TIOCCBRK)) { errno = 0; return 0; } return r; } ``` **3. Run SP Flash Tool v5.1648** in console mode with the shim. It also needs `libpng12.so.0`, which ships in the `lib/` of later SP Flash Tool zips: ```sh T=/path/to/SP_Flash_Tool_v5.1648_Linux cd "$T" sudo env LD_PRELOAD=/path/to/brkshim.so LD_LIBRARY_PATH="$T:$T/lib" \ QT_QPA_PLATFORM=offscreen ./flash_tool -r -i /path/to/writemem.xml ``` Then plug the device in powered off, **with no buttons held** (Preloader mode, `0e8d:2000`). In this mode the preloader has already initialised DRAM, so no EMI settings are needed. **4. The `write-memory` config.** A scatter file is still required. Generate it from the PMT (all partitions, `linear_start_addr` = `physical_start_addr`) and add `skip_pmt_operate: true` to its `general` → `info` block so the tool never rewrites the table. If the scatter marks nothing `is_download: true`, the tool aborts during "auto load all roms" (`DL_AutoLoad failed`). So mark exactly one partition downloadable and give it a harmless, disabled rom (here: the original, unmodified system image): ```xml MT6592 EMMC /path/to/SP_Flash_Tool_v5.1648_Linux/MTK_AllInOne_DA.bin /path/to/MT6592_writemem_scatter.txt /path/to/system_original.img /path/to/system_new.img ``` `part-id="8"` is the eMMC user area. Only one `write-memory-item` is allowed per config. Result: `100% of data write to memory, (1610612736 /1610612736)` in about 2.5 minutes (about 10 MB/s), and the device booted with the new boot animation. **Caveats** - **Prove placement first.** Before the real write, I wrote 1 MiB of random bytes into the middle of the CACHE partition (disposable), read an 18 MB window back with mtkclient, and confirmed it landed at exactly the requested address with nothing else changed. - **Always read back.** The first full 1.5 GB attempt stalled after one 1 MiB packet (no CPU, no progress for 30+ minutes). It did not happen again on retries (2 MiB, 94 MiB, then 1.5 GB all completed), so I have no explanation for it. A read-back showed exactly one new 1 MiB chunk had been written. - **The image must be valid for Android**: `e2fsck -fn` clean, and the replaced files must keep their owner, mode and `security.selinux` xattr (`u:object_r:system_file:s0`). Check with `debugfs -R 'ea_list /media/bootanimation.zip' system.img`. - **A hung DA leaves the device unresponsive.** It keeps running on battery and ignores buttons, and the host logs `device descriptor read/64, error -71`. Hold power for 15–20 seconds to reset it. - **BROM mode needs vol-up held at the moment the chip powers up.** Unplug everything, hold vol-up, then connect the data cable. With external power attached it tends to land in Preloader mode instead. ## How it was found - `strace -f -e trace=openat,ioctl,read,write` on `flash_tool` showed the `TIOCCBRK` failure and, later, the per-packet protocol: `Z`, 1 MiB data, 2-byte checksum, then the device replies `i`. - The kernel log showed BROM enumerating cleanly (`cdc_acm …: ttyACM0: USB ACM device`), so the cable and port were fine. - Comparing sha256 sums of the `MTK_AllInOne_DA.bin` files showed mtkclient's working DA is the one from v5.1648. Parsing the DA header (`0xDADA` entries with hw code) showed which tool versions still list MT6592. - SP Flash Tool's detailed logs in `/tmp/SP_FT_Logs/` give the exact reason behind generic errors such as "PMT changed". ## References - mtkclient: - SP Flash Tool Linux builds (older versions are still on the CDN): `https://cdn.spflashtools.com/wp-content/uploads/SP_Flash_Tool_v5.1648_Linux.zip`