Recovering a hard-bricked Xiaomi Mi 9 SE with Qualcomm EDL
A Xiaomi Mi 9 SE that no longer boots at all, with a black screen and no fastboot or recovery, quickly looks like a dead phone.
In my case, there was still one last entry point: Qualcomm EDL 9008 mode.
That mode let me regain access to the device, load a suitable Firehose programmer, bypass Xiaomi’s EDL lock, and reflash enough of the official firmware to bring the phone back to life. Once recovery had been flashed correctly again, I did not keep MIUI for long: I installed /e/OS directly.
The starting point
The phone was a Xiaomi Mi 9 SE, codename grus, with a Snapdragon 712 and UFS storage.
It no longer booted at all:
No MIUI
No recovery
No fastboot
Black screen
When connected to a Linux machine, it still appeared in lsusb:
05c6:9008 Qualcomm, Inc. Gobi Wireless Modem (QDL mode)
That was the important sign: the phone was in Qualcomm Emergency Download mode, also known as EDL or 9008.
Android was dead, but the Qualcomm BootROM was still responding.
Understanding the EDL chain
On a Qualcomm platform, the simplified chain looks like this:
Linux PC
|
| USB 05c6:9008
v
Qualcomm BootROM
|
| Sahara
v
Firehose programmer
|
| Firehose commands
v
UFS storage
Sahara is used to talk to the BootROM and upload a small program called Firehose. Once running, the Firehose programmer provides access to the phone storage.
Without a compatible Firehose, there is no clean way to repair the device.
First attempt with bkerler/edl
On Linux, I used bkerler/edl.
With the phone connected in 9008 mode, this command was enough to confirm that Sahara was responding:
python edl.py printgpt --memory=ufs --debugmode
The tool correctly detected Sahara mode and printed hardware details for the phone, including the HWID, MSM ID, and PK_HASH.
In my case, edl also printed:
Unknown CPU
That was not really worrying: the Snapdragon 712 MSM ID was simply not mapped to a friendly name in the tool’s internal table.
The wrong automatic Firehose
Without an explicit loader, edl tried to select a compatible Firehose automatically.
It found several files matching the same PK_HASH prefix, including a loader intended for the Poco F1.
The problem is obvious:
Poco F1 : Snapdragon 845
Mi 9 SE : Snapdragon 712
Even if devices share a compatible signature chain, their Firehose programmers are not necessarily interchangeable.
When the wrong Firehose was loaded, the phone disappeared from the USB bus, then came back a few seconds later in 9008 mode.
The PK_HASH alone is therefore not enough to choose a Firehose. The programmer must match the target platform.
Official Xiaomi Firehose: the right device, but EDL Auth
I then downloaded the official Mi 9 SE Fastboot ROM:
grus_global_images_V12.5.1.0.RFBMIXM
It contains the official Firehose:
images/prog_ufs_firehose_sdm710_ddr.elf
The sdm710 name may look odd because the Mi 9 SE uses a Snapdragon 712, but this is indeed the programmer shipped in the official grus ROM.
By forcing that loader explicitly:
python edl.py printgpt \
--memory=ufs \
--loader=/path/to/prog_ufs_firehose_sdm710_ddr.elf \
--debugmode
the Firehose finally started correctly.
But Xiaomi added another lock:
firehose - Xiaomi EDL Auth detected.
firehose - Error on EDL Authentification
At that point Qualcomm EDL worked, Sahara worked, and the Firehose started, but Xiaomi blocked the useful commands.
Finding a no-auth Firehose for the Mi 9 SE
The solution was to find a Mi 9 SE-compatible Firehose able to pass Xiaomi EDL authentication.
I used Temblast’s public Firehose Loaders index, which referenced an entry for:
Xiaomi/Auth Skip, Auth Bypass/MI 9 SE
The file came from the Iqinix/Qualcomm-firehoses repository.
After checking it, it was indeed a 64-bit ARM aarch64 ELF. Once used with edl:
python edl.py printgpt \
--memory=ufs \
--loader=/root/mi9se_noauth.elf \
--debugmode
the output finally changed:
firehose - Xiaomi EDL Auth detected.
firehose - EDL Authenticated successfully.
The main lock had been crossed.
The MaxDigestTableSizeInBytes trap
Even after that, things were not fully working yet.
The Firehose returned:
ERROR: NAK: Host wants to send a Hash table 2048 larger than supported 0
The issue came from edlclient/Library/firehose.py.
edl was sending:
MaxDigestTableSizeInBytes="2048"
while this specific Firehose advertised a supported value of:
0
I changed the value from 2048 to 0.
After that adjustment, Firehose configuration finally succeeded:
firehose - Xiaomi EDL Auth detected.
firehose - EDL Authenticated successfully.
firehose - INFO: Calling handler for configure
firehose - INFO: Storage type set to value UFS
From there, access to the UFS storage was actually functional.
A Linux detail: qcserial
On Linux, the Qualcomm 9008 device is often automatically handled by the qcserial driver and appears as /dev/ttyUSB0.
In my case, communication was more reliable when edl used libusb directly.
I detached the driver:
echo "1-3:1.0" > /sys/bus/usb/drivers/qcserial/unbind
or, for testing:
modprobe -r qcserial usb_wwan
Then lsusb -t confirmed:
Class=Vendor Specific Class, Driver=[none]
That setup gave me the cleanest Sahara/Firehose exchanges.
Flashing the official ROM
I then used the files from the official Xiaomi Fastboot ROM, especially:
rawprogram0.xml
rawprogram1.xml
rawprogram2.xml
rawprogram3.xml
rawprogram4.xml
rawprogram5.xml
patch0.xml
patch1.xml
patch2.xml
patch3.xml
patch4.xml
patch5.xml
Those files describe the partitions and the images to write.
During the flash, edl wrote the different components required for boot:
xbl_config.elf
xbl.elf
qupv3fw.elf
devcfg.mbn
aop.mbn
cmnlib.mbn
cmnlib64.mbn
abl.elf
tz.mbn
hyp.mbn
boot.img
vbmeta.img
system.img
vendor.img
...
A successful write was easy to identify:
Writing ...
Progress: 100%
Wrote ...
Back to life
After restoring the official firmware, the Mi 9 SE finally left its hard-bricked state.
MIUI booted again.
Fastboot was available too:
fastboot devices
Then:
fastboot oem device-info
confirmed that the bootloader was still unlocked:
Device unlocked: true
Device critical unlocked: true
The phone was recovered.
Installing /e/OS directly
Once the phone was back in a sane state, I flashed recovery correctly again.
And as soon as recovery worked, I did not wait: I installed /e/OS directly.
The goal was not really to return to MIUI permanently. MIUI mostly served as proof that the phone had been restored, that the critical partitions were coherent again, and that fastboot/recovery could be recovered.
Once that base was back in place, /e/OS was the logical next step.
Summary
The complete path was:
Hard-bricked Xiaomi Mi 9 SE
|
v
Qualcomm EDL 9008 mode
|
v
Sahara OK
|
v
Wrong automatic Firehose
|
v
Official grus Firehose
|
v
Xiaomi EDL Auth lock
|
v
Mi 9 SE no-auth Firehose
|
v
MaxDigestTableSizeInBytes adjustment
|
v
UFS access
|
v
Official firmware flash
|
v
MIUI boots again
|
v
Recovery flashed correctly
|
v
/e/OS installed directly
Conclusion
This Mi 9 SE looked completely dead.
In reality, as long as Qualcomm EDL 9008 mode was still responding, there was still a possible recovery path.
The three critical points were:
finding the right Firehose
bypassing Xiaomi EDL authentication
adapting the Firehose configuration used by edl
Once those obstacles were out of the way, flashing the official ROM brought the phone back.