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
| Method | When to use | Reliability |
|---|---|---|
adb reboot edl | Phone booted into Android with USB debug enabled | Always works |
fastboot reboot edl | Phone in fastboot mode | Always works |
| Vol+ and Vol− held while plugging USB (with cable unplugged first) | Bricked / stuck in ZTE MemoryDump mode / fastboot during toolbox unlock | Most reliable — gives "clean 9008" without going through ZTE's crash handler [#423 p22, #659 p33] |
| Let battery die fully, then volume buttons | Phone won't respond to anything | Last resort before test-point |
| EDL test point on PCB | Phone won't enter 9008 by any other method | Requires 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
| State | USB IDs |
|---|---|
| Clean PBL 9008 | VID 05C6 PID 9008 (Qualcomm) |
| ZTE MemoryDump mode | VID 19D2 PID 0112 |
| Fastboot | VID 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:
# 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 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_bootflashes with avbmetaflag patch (set offset 0x0C to02 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
| Error | Cause | Fix |
|---|---|---|
| "No 9008 device found" | Wrong entry method, or driver not installed | Volume-button method [above], install QC driver |
| "Non-ZTE tool" / NAK on configure | Missing Oem string in bkerler/edl | Add Oem="ZTE" to firehose.py [#264 p14] |
| Sahara upload not 38 chunks | Wrong programmer file | Verify devprg.melf size ~1.6 MB, b'configure' present in binary [#423 p22] |
| Configure NAK / no response | Came via ZTE crash transition, not clean 9008 | Re-enter via volume buttons |
| "Your device is corrupt" after flash | vbmeta not patched | See Partitions, AVB, vbmeta |
| Windows can't find device after Sahara | USB re-enumeration timing | Use scripts that reconnect properly [#423 p22] |