Skip to content

Consistent +1 byte-shift in DA status header after EMI-reconnect on MT6769/Helio G88 (BOOT_TO stage2) #321

Description

@shirhobbit-arch

Device

  • Xiaomi Redmi 10 (2021), codename selene, model 21061119DG
  • SoC: MediaTek Helio G88 (MT6769V/CT), HW code 0x707, HW subcode 0x8a00, HW version 0xca00
  • Bootloader unlocked
  • Host OS: Ubuntu (please fill exact version, e.g. lsb_release -a)
  • mtkclient version/commit: (please fill — cd ~/mtkclient && git log -1 --oneline)

Summary

After a successful BROM → Kamakiri → DA stage-1 → DA_SYNC → EMI init → EMI-reconnect sequence, the very first status() call following a successfully-written BOOT_TO command (0x10008) returns a 12-byte XFlash status header where every single byte is shifted by exactly +1 (mod 256) relative to the expected header. This is not random USB noise — the shift is uniform across all 12 bytes and was reproduced identically (same resulting magic value) in two fully independent sessions.

Expected vs received header

Expected: ef ee ee fe 01 00 00 00 04 00 00 00   (magic=0xFEEEEEEF, type=1, length=4)
Received: f0 ef ef ff 02 01 01 01 05 01 01 01   (magic=0xFFEFEFF0)

Byte-by-byte delta (computed, not eyeballed):

pos 00: ef -> f0   delta=+1
pos 01: ee -> ef   delta=+1
pos 02: ee -> ef   delta=+1
pos 03: fe -> ff   delta=+1
pos 04: 01 -> 02   delta=+1
pos 05: 00 -> 01   delta=+1
pos 06: 00 -> 01   delta=+1
pos 07: 00 -> 01   delta=+1
pos 08: 04 -> 05   delta=+1
pos 09: 00 -> 01   delta=+1
pos 10: 00 -> 01   delta=+1
pos 11: 00 -> 01   delta=+1

All 12 bytes: delta == +1, no exceptions.

Reproduction context

  1. Standard flow up through EMI init completes successfully (EMI init status: 0x0).
  2. send_emi() triggers the expected USB disconnect (USBError(5, 'Input/Output Error'), Device disconnected) — this matches the existing # Disconnect after EMI is expected! comment in the code, so this part is not itself the bug.
  3. After DA reinitializes USB, boot_to() is called for stage-2.
  4. xsend(self.cmd.BOOT_TO) — the header write itself sometimes needs a few retries (USB not immediately ready after the EMI-reconnect), but once EP_OUT is valid again, usbwrite() succeeds (xsend result: True, BOOT_TO command sent).
  5. The immediately following self.status() read gets the shifted header above instead of the expected 0xFEEEEEEF magic → "Status error: Wrong magic"boot_to() fails → "Failed to upload da."

What has been ruled out

  • Python-level bug in mtkclient: added raw-byte logging directly inside usbread(), immediately after the underlying EP_IN.read() call (dt = epr(sz)), before any parsing/unpacking. The +1-shifted bytes are already present at that exact point — confirmed against dozens of prior, fully correct status() reads earlier in the same session using the identical single-byte read path. This rules out unpack(), buffering, or any queue/caching bug in the Python code.
  • Stale libusb-level internal queue: usbread()'s self.queue mechanism only gets populated in "fast" mode (self.fast == True), which is only enabled later via reinit()/set_fast_mode() after stage-2 is already running — at the point of this failure, self.fast is still False, so this queue is empty and not implicated.
  • Wrong USB endpoint selection: lsusb -v confirms Interface 1 (CDC Data, class 10) has EP 0x81 IN / EP 0x01 OUT, exactly matching what connect() selects via bInterfaceClass == devclass — Interface 0 (Communications, class 2) has no OUT endpoint at all, ruling out an interface mix-up.
  • A leftover/duplicate process competing for the USB device: checked via ps aux/lsof/fuser — ruled out for the specific captures where this was reproduced.
  • A local retry/off-by-one bug in our reconnect loop: rolling back all local retry-logic patches to xsend() (git checkout to a clean pre-patch state) and re-testing did not change the underlying "Wrong magic" behavior when it did occur, and actually reached WRITING far faster on the clean code (attempt unpack requires a buffer of 12 bytes on unlocking the bootloader #7 vs. hundreds of attempts with the heavier retry logic) — so the issue is not caused or fixed by our local retry additions.

What has NOT been fully ruled out

  • Kernel-level / xHCI-controller-level corruption below libusb (attempted usbmon/Wireshark capture on usbmon1, but the phone's BROM window is only ~200-300ms per cycle, and we were not able to reliably capture the exact failing packet during the capture windows attempted so far).
  • A possible power-stability issue in the phone specifically during/after DRAM (EMI) calibration, which several other users may have also hit under different symptom names (e.g. unpack requires a buffer of 12 bytes errors reported around EMI/DA stage-2 on other MT676x/MT678x devices).

Question

Is this a known DA-side (XFlash) or USB-controller-level quirk specifically tied to the EMI-reconnect → BOOT_TO transition on MT6769/Helio G88 (or MT676x family more broadly)? Has anyone seen a uniform +1 byte-shift pattern like this before, and if so, is there a known workaround (e.g. a specific delay, a different reconnect sequence, or a DA/preloader version known to avoid it)?

Happy to provide the full usbmon capture, complete debug logs, or test any suggested patch — this has been reproduced consistently across many independent sessions.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions