Fairphone 3 unbricking

There should be no response when you plug in the battery.
There should be no cable connected.
You press and hold “Vol Down” + “Power”.
If you still don’t get a response, remove the battery AGAIN and put it back in.
Then hold both volume-buttons while plugging the device in.

Still nothing. I put the battery in (not pressing anything) and held the buttons while connecting it to the pc. Fastboot didn’t find a device and the edl script also didn’t

So you tried the fastboot button-combination?
That didn’t work?
You removed the battery again and replaced it?
Then tried both volume buttons while plugging in?
What USB device does it show?

Yes, nothing of it gave any response.
Bus 001 Device 051: ID 05c6:900e Qualcomm, Inc.

I thought it might be the same problem. I was able to dump the memory, but didn’t know where else to go afterwards.

If you are in the same situation and you have confirmed, that neither of the button combinations works from a powered off state, the only option is to take the device apart and short two testpoints using a resistor (Or sending it in for repair)
You might want to ask someone who has some experience tinkering with electronics to help you.

Oh dang, okay, however, thank you.
What about those EDL cables? Are they worth a try?

If pressing both volume-buttons doesn’t work, the EDL-cable likely won’t either.

What about the SBL?! It was also clear to me that both key combinations or USB-shortening were caught (if caught at all) before aboot. I was also definitely sure that my phone was reaching the SBL (otherwise it would have gone into EDL on its own), so I knew that the key-combinations were caught by the SBL at some later stage than where I was caught. However, I had some hope for the USB-shortening, and it was dissipated both by reading

We also encountered SBLs that test the USB D+/GND pins upon boot (e.g. Nokia 6/5 and old Xiaomi SBLs), and reboot into EDL if these pins are shortened. This is known as the EDL or ‘Deep Flashing’ USB cable. Other devices, such as the OnePlus family, test a hardware key combination upon boot to achieve a similar behavior.

in https://alephsecurity.com/2018/01/22/qualcomm-edl-1/ and by testing myself (I tested with absolutely no hope, given what I had read).

aboot catches the key combination since aboot gives output via UART.

Even if the EDL-cable or key-combinations were caught by sbl1 that should happen way before trying to load other stuff.
So it seems kind of weird it is implemented such, that sbl1 can fall back into memory-dump before catching the button-combination or EDL-cable.
Since as you said @calvofl0, if sbl1 wasn’t working at all, it should go straight into EDL.

@walamana: I just went out of the very same situation in which you are. The USB-EDL cable will not be helpful in this situation. You really need to disassemble the whole phone. If you are not used to do this kind of things, I recommend that you start that when you are not in a hurry, count 5 hours ahead of you. Before starting, make sure you have read and thoroughly understood every single step here below. If one step does not work, don’t even try to move forward, it will not work and probably lead to a cascade of new problems. If you have any doubt/problem, ask in this thread, people will help you. Don’t follow instructions blindly, make sure you know what you do at each time and why you do it. I hope not to scare you: it is really not that complicated, but it is quite long. Do as follows:

  1. First relax. Open the phone as if you wanted to change the SIM card, make sure it is disconnected from USB and the battery is away
  2. Prepare close to you: a screw-driver like the one provided (or the one provided), a Torx screw-driver of size T5; if you do not have a star-shaped screw-driver, a very small flat one will make the job; prepare also a small box/glass/cup (where you will put extremely small screws you don’t want to lose); a 1KOhm resistor; make sure you are working on a clear surface, without any kind of textile or any stuff carrying electrostatic charges
  3. Prepare all the stuff you will need on the computer: clone https://github.com/bkerler/edl and unzip https://www.androidfilehost.com/?fid=4349826312261722607 in the same folder. Make sure you have Python >= 3.7, qcserial is not running (stop ModemManager if you have it, and killall qcserial), make sure you have followed the installation instructions on the README, and then try to run ./edl.py --help, just to check that all Python stuff is all right; finally prepare on a line the command ./edl.py wl unbrick --loader=unbrick/prog_emmc_firehose_8953_ddr.mbn, that you will not yet execute, and on another shell execute watch -n 0.1 lsusb, which will inform you in live of the plugged USB peripherals; in order to get information about new plugged devices, you might prefer the more verbose sudo dmesg -w, which will provide more detailed information and report all kind of events
  4. Remove all 13 screws from the back
  5. At this point you have to remove the display, best is that you watch the official video https://support.fairphone.com/hc/en-us/articles/115001041206, and keep in mind that it is more difficult than what it looks in the video; don’t force, rather see how they proceed in a more clever way here: https://d3nevzfk7ii3be.cloudfront.net/igi/WW6DNwFaZxDLFQWG.huge. Please take note of the plastic tool used in the picture. If you have long nails, that can also do the job, but NEVER USE A METALLIC STUFF, never use a screw-driver or a knife for separating delicate components!
  6. Now that the display is out, you will see a relatively big metallic plate; it is covering the main board. Touch it with both hands (in order to prevent electrostatic discharge later on to the board that is below), and remove the two smaller black screws that keep this plate where it is
  7. Remove the metallic plate, and carefully disconnect the main board underneath from the modules around
  8. At this point you managed to extract from the phone the main board; further remove the bottom module (the one with the USB plug, you will have to remove 4 additional screws)
  9. Reconnect the bottom module to the main board
  10. Identify the two pins labelled L and K on https://github.com/k65onyx/fp3-notes/blob/master/images/test_point_labels.png
  11. Plug the USB cable to the bottom module (but not yet to the computer), sit comfortably, in such a way that you can hold single-handed the resistor between the two pins, so that one leg of the resistor touches L and the other leg touches K
  12. With your free hand plug the USB to the computer and then remove the resistor
  13. Now check on the shell where lsusb was running that your phone appears in EDL mode (it will say EDL at the end of one line, if that is the case)
  14. Now that you have your phone in EDL mode, go to the EDL shell on your computer and press ENTER to the command that you prepared; if all went well you should see the progression of a variety of images been flashed on your phone
  15. Run ./edl.py reset, disconnect the USB, very carefully reassemble the bottom module first, then the main board (be very careful, make sure it is really completely in, and all the plugs are properly connected to all the modules around) and put back the metal plate
  16. Now you will properly observe the display, check for its connector. You will observe that there are two holes for two screws, around the connector; you will plug back the screen, and put back only these two screws that you have observed: before reassembling the whole lot we want to make sure that all is fine indeed
  17. With Vol- and Power pressed at the same time, plug the USB from the phone to the computer; in the lsusb shell you should now see a Google device; also with fastboot devices you should see your phone appear; if this is okay, you can move forwards
  18. Reflash properly your phone with fastboot, reboot, and check that all works
  19. Put back all the missing screws and
  20. Well done, your phone just resurrected :slight_smile:

NOTE: you need a lot of patience and confidence, and if possible someone experienced next to you. You might have to repeat these steps. Think that at this point FP3 is almost unbrickable in a definitive way, but it is not unbreakable, especially when you start removing screws. So the slowest and more careful you go, the best. Don’t hesitate to take pictures of what you do to help you reassemble. If you don’t find an experienced person to help you, ask any friend to be next to you carefully watching what you do and let that person take the pictures (four eyes often see better than two).

Good luck!

EDIT: the suggestions/corrections of k4y0z in the next post are now accounted for in the above instructions


Thank you @calvofl0 for this very detailed guide, I’ll pin it at the top.
I just have a few minor remarks:

  • In Step 2: The “star-shaped” screws are called Torx and should be of size T5
  • In Step 3: Instead of running watch -n 0.1 lsusb you may just run sudo dmesg -w
  • In Step 15: The command should be ./edl.py reset (no wl)

Thanks a lot @calvofl0 & @k4y0z for your guidance! It worked! With the help of a friend it worked fine even without expert knowledge (at least so far that you can get the phone running).


Magnificent! Then feel free to comment if you wish to improve the unbricking tutorial for the next one to come!

By the way, if you are experimenting a lot it is a good idea to save all of your partitions, with dd, just as I suggested here: FP3 custom rom development based on released source code. The reason is that some partitions are specific to each individual phone, and you will not be able to restore those from the stock images if they get corrupted.

We are close to the point where, provided one makes the correct backups before starting experimenting, the FP3 is essentially unbrickable. Yet, I can imagine at least one way of getting into even bigger troubles than we have been till now: we could corrupt the GPT table. But even then, if we take good note of what is inside, it should be possible to restore it with the programmer in EDL mode.

Here is the GPT table, for future reference:

modem_a: Offset 0x0000000004000000, Length 0x0000000005800000, Flags 0x00004410, Type EFI_BASIC_DATA
modem_b: Offset 0x0000000009800000, Length 0x0000000005800000, Flags 0x0000c010, Type 0x77036cd4
fsc: Offset 0x0000000010000000, Length 0x0000000000000400, Flags 0x00000000, Type 0x57b90a16
ssd: Offset 0x0000000010001000, Length 0x0000000000002000, Flags 0x00000000, Type 0x2c86e742
sbl1_a: Offset 0x0000000010003000, Length 0x0000000000080000, Flags 0x00004400, Type 0xdea0ba2c
sbl1_b: Offset 0x0000000010083000, Length 0x0000000000080000, Flags 0x0000c000, Type 0x77036cd4
rpm_a: Offset 0x0000000010103000, Length 0x0000000000080000, Flags 0x00004400, Type 0x98df793
rpm_b: Offset 0x0000000010183000, Length 0x0000000000080000, Flags 0x0000c000, Type 0x77036cd4
tz_a: Offset 0x0000000010203000, Length 0x0000000000200000, Flags 0x00004400, Type 0xa053aa7f
tz_b: Offset 0x0000000010403000, Length 0x0000000000200000, Flags 0x0000c000, Type 0x77036cd4
devcfg_a: Offset 0x0000000010603000, Length 0x0000000000040000, Flags 0x00004400, Type 0xf65d4b16
devcfg_b: Offset 0x0000000010643000, Length 0x0000000000040000, Flags 0x0000c000, Type 0x77036cd4
dsp_a: Offset 0x0000000010683000, Length 0x0000000001000000, Flags 0x00004400, Type EFI_BASIC_DATA
dsp_b: Offset 0x0000000011683000, Length 0x0000000001000000, Flags 0x0000c000, Type 0x77036cd4
modemst1: Offset 0x0000000012683000, Length 0x0000000000180000, Flags 0x00000000, Type 0xebbeadaf
modemst2: Offset 0x0000000012803000, Length 0x0000000000180000, Flags 0x00000000, Type 0xa288b1f
DDR: Offset 0x0000000014000000, Length 0x0000000000008000, Flags 0x00000010, Type 0x20a0c19c
fsg: Offset 0x0000000014008000, Length 0x0000000000180000, Flags 0x00000010, Type 0x638ff8e2
sec: Offset 0x0000000014188000, Length 0x0000000000004000, Flags 0x00000010, Type 0x303e6ac3
splash: Offset 0x0000000018000000, Length 0x0000000000b00000, Flags 0x00000000, Type 0x20117f86
aboot_a: Offset 0x000000001c000000, Length 0x0000000000300000, Flags 0x00004410, Type 0x400ffdcd
aboot_b: Offset 0x000000001c300000, Length 0x0000000000300000, Flags 0x0000c010, Type 0x77036cd4
dtbo_a: Offset 0x000000001c600000, Length 0x0000000000800000, Flags 0x00004410, Type 0x24d0d418
dtbo_b: Offset 0x000000001ce00000, Length 0x0000000000800000, Flags 0x0000c010, Type 0x77036cd4
vbmeta_a: Offset 0x000000001d600000, Length 0x0000000000010000, Flags 0x00004410, Type 0x4b7a15d6
vbmeta_b: Offset 0x000000001d610000, Length 0x0000000000010000, Flags 0x0000c010, Type 0x77036cd4
boot_a: Offset 0x000000001d620000, Length 0x0000000004000000, Flags 0x00002710, Type 0x20117f86
boot_b: Offset 0x0000000021620000, Length 0x0000000004000000, Flags 0x00003b10, Type 0x77036cd4
devinfo: Offset 0x0000000025620000, Length 0x0000000000100000, Flags 0x00000010, Type 0x1b81e7e6
system_a: Offset 0x0000000025720000, Length 0x00000000c0000000, Flags 0x00004410, Type 0x97d7b011
system_b: Offset 0x00000000e5720000, Length 0x00000000c0000000, Flags 0x0000c010, Type 0x77036cd4
vendor_a: Offset 0x00000001a5720000, Length 0x0000000040000000, Flags 0x00004410, Type 0x97d7b011
vendor_b: Offset 0x00000001e5720000, Length 0x0000000040000000, Flags 0x0000c010, Type 0x77036cd4
persist: Offset 0x0000000228000000, Length 0x0000000002000000, Flags 0x00000000, Type 0x6c95e238
misc: Offset 0x000000022a000000, Length 0x0000000000100000, Flags 0x00000000, Type 0x82acc91f
keystore: Offset 0x000000022a100000, Length 0x0000000000080000, Flags 0x00000000, Type 0xde7d4029
prodinfo: Offset 0x000000022a180000, Length 0x0000000000200000, Flags 0x00000000, Type 0x21130059
config: Offset 0x000000022a380000, Length 0x0000000000008000, Flags 0x00000000, Type 0x91b72d4d
oem: Offset 0x000000022a388000, Length 0x0000000010000000, Flags 0x00000000, Type 0x7db6ac55
limits: Offset 0x000000023c000000, Length 0x0000000000008000, Flags 0x00000010, Type 0x10a0c19c
mota: Offset 0x0000000240000000, Length 0x0000000000080000, Flags 0x00000000, Type EFI_BASIC_DATA
dip: Offset 0x0000000240080000, Length 0x0000000000100000, Flags 0x00000000, Type 0x4114b077
mdtp_a: Offset 0x0000000240180000, Length 0x0000000002000000, Flags 0x00004400, Type 0x3878408a
mdtp_b: Offset 0x0000000242180000, Length 0x0000000002000000, Flags 0x0000c000, Type 0x77036cd4
syscfg: Offset 0x0000000244180000, Length 0x0000000000080000, Flags 0x00000000, Type 0x98df793
mcfg: Offset 0x0000000244200000, Length 0x0000000000400000, Flags 0x00000000, Type EFI_BASIC_DATA
lksecapp_a: Offset 0x0000000248000000, Length 0x0000000000020000, Flags 0x00004410, Type 0xa11d2a7c
lksecapp_b: Offset 0x0000000248020000, Length 0x0000000000020000, Flags 0x0000c010, Type 0x77036cd4
cmnlib_a: Offset 0x0000000248040000, Length 0x0000000000100000, Flags 0x00004410, Type 0x73471795
cmnlib_b: Offset 0x0000000248140000, Length 0x0000000000100000, Flags 0x0000c010, Type 0x77036cd4
cmnlib64_a: Offset 0x0000000248240000, Length 0x0000000000100000, Flags 0x00004410, Type 0x8ea64893
cmnlib64_b: Offset 0x0000000248340000, Length 0x0000000000100000, Flags 0x0000c010, Type 0x77036cd4
keymaster_a: Offset 0x0000000248440000, Length 0x0000000000100000, Flags 0x00004410, Type 0xe8b7cf6e
keymaster_b: Offset 0x0000000248540000, Length 0x0000000000100000, Flags 0x0000c010, Type 0x77036cd4
apdp: Offset 0x000000024c000000, Length 0x0000000000040000, Flags 0x00000000, Type 0xe6e98da2
msadp: Offset 0x000000024c040000, Length 0x0000000000040000, Flags 0x00000000, Type 0xed9e8101
dpo: Offset 0x000000024c080000, Length 0x0000000000002000, Flags 0x00000000, Type 0x11406f35
logdump: Offset 0x000000024c082000, Length 0x0000000004000000, Flags 0x00000000, Type 0x5af80809
frp: Offset 0x0000000250082000, Length 0x0000000000080000, Flags 0x00000000, Type 0x8fa2ad2c
product_a: Offset 0x0000000250102000, Length 0x0000000008000000, Flags 0x00000400, Type 0x9d72d4e4
product_b: Offset 0x0000000258102000, Length 0x0000000008000000, Flags 0x00000000, Type 0x77036cd4
userdata: Offset 0x0000000260102000, Length 0x0000000c2f6f9e00, Flags 0x00000000, Type 0x1b81e7e6

I will also note that after the partitions modem_b, fsc, modemst2, sec, splash, vendor_b, oem, limits, mcfg and keymaster_b there is non-allocated space. TODO: check if this space is indeed filled by zeros. In principle one expects partitions to be non-contiguous for alignment reasons, but it is better to check that there is indeed nothing relevant there.

So to keep on the safe side, one should also copy the data before the first partition (from 0x0 to 0x4000000) and the data after the last partition (after 0xe8f7fbe00), and possibly any date that could be hidden in between the partitions.


Now, that you have worked with the firehose-programmer and want to have a perfect backup, I will suggest this:
./edl.py rl <directory> # Read all partitions from flash to a directory
IIRC it also dumps the primary and backup gpt.
But there is also a command for that:
./edl.py gpt <directory> # Save gpt table to given directory
And this also woks on a locked device (which is what I plan to do, as soon as I have an FP3)

I would suggest not messing with the sec, fsc and modemst2 partitions.


Well, at this point you could also use ./edl.py rf <filename> # Read whole flash to file and stay on the safe side. However, does the Vol+/Vol- or EDL cable trick work on a locked device? I guess the “lock” switch is only considered by aboot, but the “can be unlocked” switch might be considered by the SBL, don’t you think? Of course if that is the case, you would just disassemble your phone and force it in EDL mode as we did…

Going directly through EDL to save contents will also allow us to see where exactly the locked/unlocked switches reside, and write some nice code to lock/unlock the bootloader without the need of fastboot.

Also, do you know if there is a switch that is permanently changed when the phone is unlocked for the first time? If that switch exists and is in the eMMC, you would be the first lucky person having a phone unlocked and able to perfectly come back to the initial state. I would be really glad if you could make a whole dump of the flash memory before even booting your phone, then boot it normally (but without internet connection), unlock it, and make again a whole dump, and make available a binary diff of that, maybe excluding the memory range containing the userdata partition :grinning:.

We locked and unlocked my phone last thursday and dumped before and after. So the locking bit is known.


That is also an option, but it’s easier to work wit single partitions :wink:

Yes it works on a locked device.
If you are talking about the “Allow oem unlock”, that is only considered by aboot and is irrelevant for actually unlocking the device.

The bit is already known and due to the weird decision of allowing to flash “critical” partitions even on a locked device, doesn’t even require EDL to be toggled:

So far it doesn’t seem like there is a difference between “locked” and “relocked”.
But as said, I plan to make a full dump, as soon as I receive the device.

As I said, there is space in between the partitions. I would not consider that space to be irrelevant until I have really seen it. Block-alignment is definitely not the only reason, I suspect it is just there so that some of the partitions could become bigger if needed, but one never knows. I’ll check that this evening. Also ./edl.py has an option to backup the GPT, but I see no option to restore it.

@k4y0z: Wonderful! You run too fast without even having a phone! Continue like this and nothing will be left for the other hackers nor to you when you finally get the FP3. Maybe you should consider buying a more challenging phone with a proper PBL that verifies the SBL instead :wink:.

Primary GPT is stored at the very beginning of EMMC and Backup at the very end.
I think you can actually flash to PrimaryGPT and BackupGPT, but I haven’t tested.
Also you can generate an xml-file that will tell you the exact blocks where they are stored:
edl.py gpt <filename> --genxml