FP3 custom rom development based on released source code

I’d really like to see the whole procedure explained, how you managed to get to that point :slight_smile: Feels like we all could learn a thing or two.


I’m sure all your questions will be answered in the TWRP-thread :wink:
I will post, if chaosmaster created it…


My phone is back! <3

I tried to boot with the vbmeta 1.0 (no verification) and the stock vbmeta with the --disable-verification option. None of these worked. We will have to pass thru TWRP to flash a gsi


If you mean this k4y0z, then everyone go over there and give the guy a like/thanks :slight_smile: https://forum.xda-developers.com/showpost.php?p=81576433&postcount=23689


exact this k4y0z :wink:


:champagne::tada: Congratulations!
This brings the custom ROMs one big step closer!


Head over here for TWRP:


Even with TWRP, we need to disable dm-verity and AVB.

Someone who have an access to the UART console can try the vbmeta 1.0 and the stock one with --disable-verification and --disable-verity ?


Because edl is very usefull in case of bricked device, I tried the python program mentioned before.
The sbl1.img seems to works as a Loader.

mkdir examples
cp ../stock/sbl1.img examples/sbl1.mbn
./fhloaderparse.py examples

Great thinking. I was hoping about that.

The way I understood this boot chain works is, there’s an on-chip primary bootloder in actual boot ROM. This is what provides ebl through a virtual USB com-port, where one can provide an external loader. Otherwise, it loads a secondary bootloader (sbl) from the sbl partition. However in production devices it is “fuse-locked”, which means it will only run a sbl that matches a checksum that has been permanently flashed into WORM (write once read many) fuse registers - usually in the factory.
As I understand it, the “external” bootloader can be used to flash the initial image unto the device using the firehose protocol - using USB.

The sbl itself (usually) includes a public key, with which it can can check a cryptographic signature on the main bootloader (in our case aboot). Although I don’t know where the signature is stored. But I was wondering (and you just kinda confirmed it) that the “external” sbl used with firehose and the one flashed on the device is actually the same program. Might be worth disassembling that to figure out what it does exactly.

In random browsing on XDA, I found reports on some phones where the sbl had exploitable bugs which could be used to break the verification chain and load arbitrary firmware while the phone still thought it was locked and verified. As I understand it, this cannot be fixed since the CPU will refuse to load any modified sbl that doesn’t fit the checksum, while the third level bootloader (aboot) carries a signature that allows the vendor to sign new versions with the same key. Of course the public key would have to be stored in the sbl, so it cannot be replaced. if the private key is leaked, you can sign arbitrary bootloaders :slight_smile:

the bootloader in turn verifies the signature of the kernel - if the kernel is signed. it will not boot unsigned kernels unless the bootloader is unlocked.

dm-verity (device mapper verification) is actually a linux kernel feature, so it should in theory be enough to patch the kernel so it pretends to userspace that the device is verified, regardless of what happens. of course that changes the kernel, so it breaks the kernel signature, so it won’t be possible to load that kernel with a locked phone.

correct me if I’m wrong.


Regarding AVL and verity, this page has an excellent writeup on how it all works:


TL;DR: If you want to restore your phone to stock, you need to have matching aboot, boot, vbmeta, system, vendor all unmodified and in the correct version.

Changing aboot or sbl will brick the phone (although it should be unbrickable/fixable using firehose/ebl with the correct sbl image) aboot needs to be signed with the crypto-private key for which the matching public key is part of sbl, and sbl cannot be changed. Most likely only Arima™ has that private key, and they most certainly won’t make it public :wink:

changing boot, system, vendor or vbmeta, will fail the AVB chain. A modified system (modded system, vendor and boot) could in theory be signed with the correct crypto-key (so called key_0) for which the public key is included into aboot. However we don’t have key_0. Fairphone™ might have it, but its also possible that only Arima™ has it. Also there might be more keys, where each public key is signed with the private key of the predecessor in a “chain of trust” - so possibly both Fairphone and Arima keys can be used.

As far as I understand it, a phone can still be booted with a failing AVB chain if its unlocked, and it should still work, but doing so will mark the phone as “tampered”

(In case of Fairphone, fastboot oem device-info used to list “device-tampered: false” if it has never been booted into an unsigned kernel. It doesn’t seem to say “device-tampered: true” though, instead the variable simply isn’t listed at all anymore once you booted into TWRP or anything else.) This might be relevant for Warranty-cases, but shouldn’t if its an unrelated hardware issue.

Now the question is, what is necessary to make the phone boot from a modified boot partition for which an existing vbmeta information does not match? Is it necessary to erase the vbmeta partition? Or is the unlocked phone silently ignoring an incorrect vbmeta?

I would suggest playing around with the only bootable non-stock image we have which right now is the TWRP image. If that boots from the “boot” partition regardless of vbmeta contents, then so should any other kernel that passes the “dtb” checks

Edit: As noted in the linked document, some devices, for example Google’s Pixel have a “custom key” partition, into which the user can flash their own public key, then sign their own operating system with that. The phone will accept this custom key in locked mode, which allows users to have a custom OS on their phone, yet have their data protected in case the phone is lost or stolen (since it’s locked)

Considering the above partition list, I don’t think Fairphone/Arima opted for such a user friendly option, but without reverse-engineering the particular aboot on the phone we can’t tell for certain.


To anyone to whom this is not obvious, it should be noted that TWRP includes adb in root mode. So if you want to have console root on the phone just to snoop around and look at things, the quickest way is:

  1. unlock the bootloader
  2. fastboot boot twrp.img
  3. adb shell
  4. mount system and vendor read only as seen necessary

no flashing or any eeprom modification needed.
Unfortunately the TWRP minimal busybox does not include any wifi drivers or tools, so no networking.

How hard is it to go from TWRP to a minimal ubuntu/debian image? :wink: If one places the ubuntu system image within the userdata partition, no flashing of the phone would have to happen (as long as one boots via fastboot and external boot image)


On an unlocked device the kernels signature isn’t checked, therefore you can just flash a custom kernel as you wish.
That’s exactly what is happening when flashing Magisk or TWRP (using the twrp-installer) to the device.
They both modify the boot partition.

Installing Magisk actually disables verity so you can modify the system/vendor partitions without breaking it.

Regarding EDL you would typically need a manufacturer signed firehose-programmer.
This is basically sbl1 with the added implementation of the firehose protocol.

The certificate-chain used for verifying sbl1 is apparently using test-certificates ?!:

Subject: C = US, ST = California, L = San Diego, OU = General Use Test Key (for testing 13 only), OU = CDMA Technologies, O = QUALCOMM, CN = QCT Root CA 1
Subject: C = US, ST = CA, L = San Diego, OU = CDMA Technologies, O = QUALCOMM, CN = QUALCOMM Attestation CA
Subject: C = US, CN = SecTools Test User, L = SANDIEGO, O = SecTools, ST = CA, OU = 01 0000000000000000 SW_ID, OU = 02 000BA0E100000000 HW_ID, OU = 04 0000 OEM_ID, OU = 05 00000168 SW_SIZE, OU = 06 0000 MODEL_ID, OU = 07 0001 SHA256, OU = 03 0000000000000002 DEBUG

Do these certificates have expiry dates? One thing test-certificates usually have in common is a very short lifetime. That would kinda suck, if the phone would refuse to boot beyond 2022 or something like that.

How did you extract the certificates? sbl1 strings finds the strings in both sbl1.img and aboot.img

strings also finds debugging symbols in sbl1, source code file names, function names, etc… Oddly enough however objdump claims it’s a stripped binary, that doesn’t add up.


The root CA (which is what matters) expires Dec 13 08:23:22 2038 GMT.
Although I doubt the bootrom actually checks the expiry-date.
What If you had the battery removed, how would it know the current time?

I used binwalk to extract them from sbl1

those may not be debugging symbols, but just prints and similar, although I haven’t looked at sbl1 in detail.


Its possible the ELF header is fake. This isn’t really a file loaded by an OS but an image loaded by the ebl and probably run with a hardcoded start address. I’m surprised they bothered with an ELF header (or something that looks like it) to begin with.

Normally you would extract the raw, headerless binary from the elf with
objcopy -O binary source.elf target.bin
But with the sbl1 that just reports “sbl1 has no sections” - which indicates this isn’t really a valid ELF at all. (Same with aboot)


This is really great news. Is there any estimate how long it might take until there could be a lineage or other Android without Google? Or is that still unlikely?

Is there anything I could help with? I can only program python and some C++ for Arduino microcontrollers.

I don’t have a Fairphone 3 yet, I would buy one soon, if I knew for sure an OS without google would come. Also to maybe help somehow.

1 Like

Yiha! I have lineage on the FP3! (with gsi)

I used the treble_arm64_bvN image.

  1. Install magisk
    Note the slote !

  2. Flash back stock vendor & system, erase userdata

    fastboot getvar current-slot
    fastboot --set-active={slot with magisk} # if needed
    fastboot flash vendor vendor.img # Not sure if needed
    fastboot flash system system.img # Not sure if needed
    fastboot -w

  3. Flash the gsi on the two slots!

    fastboot flash system_a {gsi_image}
    fastboot flash system_b {gsi_image}

  4. Reboot and wait

    fastboot reboot

Note: Can someone try directly from step 3? or only with fastboot -w boot needs to be changed.
Note2: The slots need to have success

fastboot getvar all
(bootloader) current-slot:a
(bootloader) slot-retry-count:b:6
(bootloader) slot-success:b:Yes
(bootloader) slot-active:b:No
(bootloader) slot-unbootable:b:No
(bootloader) slot-retry-count:a:6
(bootloader) slot-success:a:Yes
(bootloader) slot-active:a:Yes
(bootloader) slot-unbootable:a:No

To get a slot-success=Yes, you have to do : (with stock system)

bootloader --set-active=a
bootloader reboot (go until system)
bootloader --set-active=b
bootloader reboot

Note3 :
To get the navigation bar, as mentionned by @dyd0u,

Maybe we could change it directly in the boot props.

Some unwanted packages are still there (because of the way treble works). It is easy to disable/uninstall them.

adb shell pm disable-user --user 0 com.qualcomm.qti.qms.service.telemetry
adb shell pm disable-user --user 0 com.qualcomm.qti.qms.service.connectionsecurity
adb shell pm disable-user --user 0 com.qualcomm.qti.optinoverlay
adb shell pm disable-user --user 0 com.orange.update
adb shell pm disable-user --user 0 com.orange.aura.oobe

Thats really cool! I will probably try install it tomorrow and I will let everyone know how it goes here.


Nice. Is there a newer version of that image? Did you check whether things actually work (GSM, LTE, GPS, camera, power+charge mgmt, whatever)?