Skip to content

EDL / 9008 mode — entry, drivers, tooling

What it is

Qualcomm's Emergency Download mode (PID 9008). When the bootloader cannot complete, or when triggered explicitly, the SoC's Primary Boot Loader (PBL) waits over USB for a signed "programmer" payload (a firehose-protocol XBL fragment). With the right programmer in hand, you can dump and write any partition on the UFS — no bootloader cooperation required.

For the RM10 Pro, the relevant programmer is devprg.melf — an ELF that contains both XBL boot code and the firehose protocol strings (configure, rawmode, program, UFS) [#423 p22 BD_Security].

Entering EDL — methods that work

MethodWhen to useReliability
adb reboot edlPhone booted into Android with USB debug enabledAlways works
fastboot reboot edlPhone in fastboot modeAlways works
Vol+ and Vol− held while plugging USB (with cable unplugged first)Bricked / stuck in ZTE MemoryDump mode / fastboot during toolbox unlockMost reliable — gives "clean 9008" without going through ZTE's crash handler [#423 p22, #659 p33]
Let battery die fully, then volume buttonsPhone won't respond to anythingLast resort before test-point
EDL test point on PCBPhone won't enter 9008 by any other methodRequires opening device

Critical: the "ZTE → SWITCH_MODE → 9008" transition that some scripts attempt does not work — it leaves the USB controller in a dirty state, the programmer's USB reset corrupts the handle, Windows takes 60+ s to re-enumerate, and the programmer's 8-second watchdog fires before that completes. Always go directly to 9008 via the volume buttons [#423 p22 BD_Security — saved him 26 hours of debugging].

Identifying the device

StateUSB IDs
Clean PBL 9008VID 05C6 PID 9008 (Qualcomm)
ZTE MemoryDump modeVID 19D2 PID 0112
FastbootVID 0FCE (Nubia)

On Windows: Get-PnpDevice | Where-Object { $_.InstanceId -match "VID_05C6.*PID_9008" } should show Status OK [#423 p22].

Drivers

  • Qualcomm USB Driver v1.0.10065.1 — required on Windows. Without it, the device shows up as Unknown in Device Manager when in 9008. Link in OP: https://transfert.free.fr/DUbB8Nh [#5 p1, #254 p13].
  • After unlock completes, the device sometimes re-enumerates as Unknown — right-click → install drivers → choose Android Boot Interface / ADB drivers [#254 p13 BeFresh_].
  • Do not use Zadig / WinUSB switching unless you have a specific reason; the libusb backend in Python works without it [#423 p22 FAQ].

Linux / bkerler/edl

The community-favorite Linux tool is bkerler/edl (https://github.com/bkerler/edl). For the RM10 Pro you have to patch in the ZTE OEM string or the device firehose refuses the configure XML:

python
# edlclient/Library/firehose.py — add Oem="ZTE" to the configure command.
# Original report put it around line 872-873 [#264]; on a current bkerler/edl
# checkout it's around line 905-906 [#676 p34 Grimish2280] — grep to be sure:
#   grep -n 'SkipWrite\|Oem' edlclient/Library/firehose.py
f"Oem=\"ZTE\" " + \

[#264 p14 DarkestSpawn]. If you pip install'd the package, you'll need to edit both your dev tree and the installed copy under /usr/local/lib/python3.X/dist-packages/edlclient/Library/firehose.py. Without this, the firehose configure step returns "Non-ZTE tool" and refuses to proceed [#514 p26 GigaWrathWave].

Doing a full native-Linux unlock?

Grimish2280 is documenting an end-to-end NX789J unlock on Linux built on this Oem="ZTE" patch plus the uefi_unlock.img payload pulled from ZTE Family Toolbox v1.2.4 (bin/res/NX789J/uefi_unlock.img) [#676 p34]. It's a work in progress — "do not use yet" — but it's the reference for anyone porting the toolbox flow off Windows. See Bootloader unlock → Native-Linux method.

The full configure XML used in working flashes looks like:

xml
<?xml version="1.0" encoding="UTF-8" ?>
<data>
  <configure MemoryName="UFS" Verbose="0" AlwaysValidate="0"
             MaxDigestTableSizeInBytes="2048"
             MaxPayloadSizeToTargetInBytes="1048576"
             ZLPAwareHost="1" SkipStorageInit="0" SkipWrite="0"
             Oem="ZTE"/>
</data>

[#423 p22 BD_Security]

QFIL

Mentioned as a fallback flashing path but no one in-thread reports success with it on RM10 Pro [#514 p26]. Treat as untested.

What works once you're in EDL

  • Dumping partitions (read GPT, dump LUN sectors) — works reliably with bkerler/edl + ZTE Oem patch, and with QLM-based paid services.
  • Programming partitions — works, with two gotchas:
    • For partitions whose size is an exact multiple of the USB packet size (512 or 1024 bytes), send one Zero-Length-Packet at the end, not after every chunk. Sending ZLPs mid-stream corrupts data [#423 p22 — cost BD_Security 10+ hours].
    • Pair init_boot flashes with a vbmeta flag patch (set offset 0x0C to 02 00 00 00) — otherwise AVB rejects boot. See Partitions, AVB, vbmeta.
  • EDL ROM restore (paid R2B service) — works for unbricking but you pay per use.

Common errors and fixes

ErrorCauseFix
"No 9008 device found"Wrong entry method, or driver not installedVolume-button method [above], install QC driver
"Non-ZTE tool" / NAK on configureMissing Oem string in bkerler/edlAdd Oem="ZTE" to firehose.py [#264 p14]
Sahara upload not 38 chunksWrong programmer fileVerify devprg.melf size ~1.6 MB, b'configure' present in binary [#423 p22]
Configure NAK / no responseCame via ZTE crash transition, not clean 9008Re-enter via volume buttons
"Your device is corrupt" after flashvbmeta not patchedSee Partitions, AVB, vbmeta
Windows can't find device after SaharaUSB re-enumeration timingUse scripts that reconnect properly [#423 p22]

Released under the CC BY-SA 4.0 license.