Fairphone 3 unbricking

If you end up in a situation, where your FP3 cannot get into fastboot on either slot, there is now an unbricking solution available using EDL/QDL mode.

In this situation the phone will usually already be in EDL mode (lsusb output):
Bus 001 Device 009: ID 05c6:9008 Qualcomm, Inc. Gobi Wireless Modem (QDL mode)

You can however force EDL mode by holding both volume-buttons during power on.

If your device comes up as:
Bus 001 Device 009: ID 05c6:900e Qualcomm, Inc.
Make sure you cannot enter Fastboot or EDL using the button combinations from a powered off state.
If it still comes up in this mode, refer to this very detailed guide:

For unbricking use GitHub - bkerler/edl: Inofficial Qualcomm Firehose / Sahara / Streaming / Diag Tools :)
And download unbrick.zip

Unzip the file into the same directory where you have edl.py, then run:

./edl.py wl unbrick --loader=unbrick/prog_emmc_firehose_8953_ddr.mbn && ./edl.py reset

After that you should be able to get back into fastboot and then flash the full stock dump from there:
Fairphone_FP3_8901.2.A.0105.20191217_12171325_user_release-keys_dump.zip
You can use This flash script by @pigpig

Thanks to @basxto for helping to get this working.
Thanks to Fairphone/Arima for not setting the fuses and not validating the sbl1/firehose signatures

Disclaimer:
I do not (yet) own an FP3 myself.
If you like my work and want to help me to continue working on the FP3, please consider donating to me, to help me buy one:
PayPal.Me

Thank you all, for your generous donations :slight_smile:
1 * 100
5 * 50
1 * 42.23
2 * 30
3 * 20
1 * 15
2 * 10
Total: 547.23 €

23 Likes

Don’t give them ideas :wink: .

7 Likes

Would have been better, had they set the fuses and given us a signed programmer.
But this way works too :grimacing:

1 Like

Does that mean that with this method you could also install an alternative bootloader (replacing aboot_a or aboot_b) without having the original bootloader unlocked, and hence boot back into android without having your data erased as a consequence of unlocking the bootloader? Or actually simply lock/unlock the bootloader without going through fastboot that would then erase your data?

1 Like

aboots signature is still being checked by sbl1.
You could theoretically replace sbl1.
And you could probably unlock without wiping data.
Just need to find where the unlocking-information is stored.

1 Like

Now that you mention it, sbl1 signature is also checked by the PBL, isn’t it? And the SBL is present in both slots, which means that the slot selection happens already at the PBL level. Any idea where the slot switch actually is? So when we do fastboot --set-active=a what is exactly modified?

And then, in order to unlock the bootloader (aboot if I understand it well), there are two switches to change: one is whether or not bootloader unlocking is allowed (done through the android config GUI), and the other is typically switched with fastboot oem unlock. Any idea where (in which partition) are those switches registered?

I got it that we don’t yet know exactly, I am just asking where to start looking for it :wink:.

The world is getting a bit crazy: billions of people use daily tools like computers and smartphones, and just a few have some little idea of how those work. And what is much worse, almost everyone considers it to be a normal situation. And in the scale of badness, there is actually even worse: a big part of the information is not publicly available (but sometimes reversed engineered), and almost everyone lives happily with the situation and uses the phone as a magic wand. Sorry for the digression, I’m being completely out of topic, I stop here :zipper_mouth_face:.

3 Likes

That’s exactly the point, it isn’t…

Take a look here:

The first flag for allowing unlocking is probably stored on the frp/config partition.
But this flag is only relevant if you want to unlock using fastboot oem unlock
The important flag may be stored on the devinfo or possibly rpmb (which would make it less feasable).

1 Like

Okay, I’m afraid I bricked my phone when testing my backup image to initial stock image :worried:. All seemed to be okay, but after pushing reboot in TWRP the phone would switch off and not come back in any way. I therefore try the unbricking procedure here, and got:

Qualcomm Sahara / Firehose Client (c) B.Kerler 2018-2019.
main - Using loader unbrick/prog_emmc_firehose_8953_ddr.mbn …
main - Waiting for the device
main - Device detected :slight_smile:
Traceback (most recent call last):
File “./edl.py”, line 435, in doconnect
mode, resp = sahara.connect()
File “/home/flavio/Downloads/edl/Library/sahara.py”, line 332, in connect
cmd, pkt = self.get_rsp()
File “/home/flavio/Downloads/edl/Library/sahara.py”, line 260, in get_rsp
pkt = read_object(v[0:0x2*0x4], self.pkt_cmd_hdr)
File “/home/flavio/Downloads/edl/Library/utils.py”, line 264, in read_object
obj[name] = struct.unpack(stype, data[pos:pos+struct.calcsize(stype)])[0]
struct.error: unpack requires a buffer of 4 bytes

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File “./edl.py”, line 1712, in
main()
File “./edl.py”, line 375, in main
mode, resp = doconnect(cdc, loop, mode, resp, sahara)
File “./edl.py”, line 440, in doconnect
mode, resp = sahara.connect()
File “/home/flavio/Downloads/edl/Library/sahara.py”, line 332, in connect
cmd, pkt = self.get_rsp()
File “/home/flavio/Downloads/edl/Library/sahara.py”, line 260, in get_rsp
pkt = read_object(v[0:0x2*0x4], self.pkt_cmd_hdr)
File “/home/flavio/Downloads/edl/Library/utils.py”, line 264, in read_object
obj[name] = struct.unpack(stype, data[pos:pos+struct.calcsize(stype)])[0]
struct.error: unpack requires a buffer of 4 bytes

Trying it again, I get an even worse result:

Qualcomm Sahara / Firehose Client (c) B.Kerler 2018-2019.
main - Using loader unbrick/prog_emmc_firehose_8953_ddr.mbn …
main - Waiting for the device
main - Device detected :slight_smile:
main - Mode detected: sahara
Device is in an unknown state

Is there anything that can still be done?

I can provide the image I was trying to flash in case it may help.

Edit: at that point the return values of mode, resp = sahara.connect() are mode=sahara, and resp={'id': 13, 'status': 1, 'object_size': 8, 'raw_data': bytearray(b'\r\x00\x00\x00\x01\x00\x00\x00')}.

Are you sure, you cannot still access fastboot? (Vol Down + Power)
What exactly did you flash?
Remove the battery and put it back in, plug in to PC. what is detected using lsusb
If it is detected as ID 05c6:9008 Qualcomm, Inc. Gobi Wireless Modem (QDL mode) rerun the unbrick script.

Yes, I am sure I cannot access fastboot. lsusb detects the phone just as you say (in QDL mode), and rerunning the unbrick script reproduces the very last error that I posted, with the Device is in an unknown state message.

Did you remove and replace the battery as I have told you?

Yes I did. I also tried to connect the phone without battery to the computer.

It shouldn’t be in “unknown state” after doing that.
Maybe you need to update your python.

Well, I also checked that. I have python 3.7.2. Note that the response to mode, resp = sahara.connect() in edl.py is mode='sahara'and resp={'id': 13, 'status': 1, 'object_size': 8, 'raw_data': bytearray(b'\r\x00\x00\x00\x01\x00\x00\x00')}.

The Readme of edl.py states
python >= 3.7 64-Bit
I assume your installation is 64 bit?

It should not be in unknown state after removing the battery.
If it is, try forcing EDL mode by holding both volume buttons while powering it on.

Yes, my installation is 64bit. And I had already tried to force EDL mode by holding both volume buttons while plugging the USB cable without having the battery on the phone. It does not change anything.

Try putting the battery back in and then holding all 3 buttons to turn it on.
If it still shows “unknown state” try running as root/sudo.
If that still doesn’t work, try a different PC.

Okay, interestingly the last option (holding all 3 buttons to turn it on) kind of worked. But then, I get again (running as root):

Qualcomm Sahara / Firehose Client (c) B.Kerler 2018-2019.
main - Using loader unbrick/prog_emmc_firehose_8953_ddr.mbn …
main - Waiting for the device
main - Device detected :slight_smile:
Traceback (most recent call last):
File “./edl.py”, line 437, in doconnect
mode, resp = sahara.connect()
File “/home/flavio/Downloads/edl/Library/sahara.py”, line 332, in connect
cmd, pkt = self.get_rsp()
File “/home/flavio/Downloads/edl/Library/sahara.py”, line 260, in get_rsp
pkt = read_object(v[0:0x2*0x4], self.pkt_cmd_hdr)
File “/home/flavio/Downloads/edl/Library/utils.py”, line 264, in read_object
obj[name] = struct.unpack(stype, data[pos:pos+struct.calcsize(stype)])[0]
struct.error: unpack requires a buffer of 4 bytes

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File “./edl.py”, line 1714, in
main()
File “./edl.py”, line 375, in main
mode, resp = doconnect(cdc, loop, mode, resp, sahara)
File “./edl.py”, line 442, in doconnect
mode, resp = sahara.connect()
File “/home/flavio/Downloads/edl/Library/sahara.py”, line 332, in connect
cmd, pkt = self.get_rsp()
File “/home/flavio/Downloads/edl/Library/sahara.py”, line 260, in get_rsp
pkt = read_object(v[0:0x2*0x4], self.pkt_cmd_hdr)
File “/home/flavio/Downloads/edl/Library/utils.py”, line 264, in read_object
obj[name] = struct.unpack(stype, data[pos:pos+struct.calcsize(stype)])[0]
struct.error: unpack requires a buffer of 4 bytes

I guess I will try tomorrow on a different computer.

Did your device ever get an OTA?
If it did, maybe turning it off and on normally using the power button about 8 times may force it to switch to the other slot.
If it never received an OTA, then you’ll have to get edl.py working.

No, it never received an OTA… I’ll try to get edl.py working then.