[Xiaomi Mi A1 ROMs, Kernels, Recoveries, & Other De] CosmicDan:
UPDATE4: New Treble guide is posted here. Ask all your questions here that aren't specific to other parts of Treble (e.g. the ROM or the TWRP). Thread lock requested. Thanks all!

UPDATE3: The new TWRP Installer with Treble Manager (for guided repartitioning) is now released. See this thread.

UDPATE2: Experimental RR builds for Treble is now released. This contains the required Vendor Pack for GSI use. See this thread.

UPDATE: We have succeed in booting a Phh-Treble GSI! See screenshot at Post #57. Stay tuned for user releases!

This thread will be kept for posterity, but I will request locking once we release stuff. Thanks you all for the support, and thanks to @ghpranav for lots of help and @phhusson for pointing me in the right direction on the last stretch.

Original post below

----------------------------------------------

Alright, here is my WIP guide for converting the Mi A1 to a Treble device and ROM.

NOT FOR NEWBIES. This is all manual stuff right now and if you do something wrong you CAN firm-brick your device! The project is incomplete and for developers/researchers only.

Please refrain from "good luck" and "can't wait for this" and "OMG you are the King of Kings ComsicDan, plz have my babies" and such posts.

Also note that you will NEED to get into EDL mode to restore stock partition table, if you need to, by flashing stock factory image with MiFlash or my Low-Level Backup Tool. MiFlash will WIPE your Userdata completely and your persist so you MUST make a low-level backup to restore original persist.img, and manually backup internal storage. But really it's perfectly fine to keep using a non-treble ROM even with partition table changes (there's no need to revert for any functional reason that I can think of, unless you somehow get a ROM that's bigger than 2.4GB). Note that the final update ZIP that will automatically repartition can also restore stock partitions, without the need for EDL stuff.

Prerequisite - Low-level backup, TWRP backup and Internal Storage backup

First make a full backup of all partitions, via EDL (low-level which gets all partitions). You can use my new Low-Level tool here. I recommend using the skip-systems-and-userdata list since it takes like an hour, and you can backup system/userdata faster in TWRP and PC manually.

Make a full TWRP backup of our current ROM. System needs to be erased during this procedure. After re-partitioning however, you can simply restore this backup (unless your system is > 2.4GB for some reason, which is very unlikely).

Make a full manual backup of your internal storage files to PC. Userdata partition needs to be completely erased if/when you restore the original stock partitions and firmware. You can postpone this process to later however, for if/when you want to actually restore to stock partition layour.

Phase 1 - Repartition device for vendor_a and vendor_b

This is relatively simple. Our device has a standard GPT table, so we can use sgdisk which is already included in our TWRP build.

Boot into recovery and fire up an adb shell

View current partition table...

sgdisk /dev/block/mmcblk0 --print

...and confirm these values...

...
25 1185792 7477247 3.0 GiB FFFF system_a
26 7477248 13768703 3.0 GiB FFFF system_b
...
49 14550032 61071326 22.2 GiB FFFF userdata

The important values are the partition numbers (25, 26 and 49), and the next two numbers for both system partitions (start/end sectors). The start/end sector of userdata isn't important, only the partition number of 49 is. If your sector start/ends are different, you will need to adjust some of the values in these steps - that's up to you to figure out. But do please let me know what your differences are, for science.

Remove system_a, and create a new system_a partition of size ~2.4GB. Don't worry, this is plenty - my current RR build with a heavy AROMA Gapps is only ~1.9GB. We're taking off ~600MB, which is 1228800 sectors (600*1024*1024/512) so the new end sector will be 6248447 (7477247 - 1228800):

sgdisk /dev/block/mmcblk0 --delete 25
sgdisk /dev/block/mmcblk0 --new=25:1185792:6248447
sgdisk /dev/block/mmcblk0 --change-name=25:system_a

Create vendor_a with the reclaimed ~600MB:

sgdisk /dev/block/mmcblk0 --new=50:6248448:7477247
sgdisk /dev/block/mmcblk0 --change-name=50:vendor_a

...notice the partition number of 50 - one after the userdata (49).

Do similarly to above, only for system_b and vendor_b:

sgdisk /dev/block/mmcblk0 --delete 26
sgdisk /dev/block/mmcblk0 --new=26:7477248:12539903
sgdisk /dev/block/mmcblk0 --change-name=26:system_b
sgdisk /dev/block/mmcblk0 --new=51:12539904:13768703
sgdisk /dev/block/mmcblk0 --change-name=51:vendor_b

Quit shell and reboot recovery...

adb reboot recovery

...and verify the new partitions exist...

adb shell ls -la /dev/block/bootdevice/by-name/

...should show this at the bottom...

...
lrwxrwxrwx 1 root root 21 Jan 5 1970 userdata -> /dev/block/mmcblk0p49
lrwxrwxrwx 1 root root 21 Jan 5 1970 vendor_a -> /dev/block/mmcblk0p50
lrwxrwxrwx 1 root root 21 Jan 5 1970 vendor_b -> /dev/block/mmcblk0p51

Repartition is done! You can now restore your TWRP backup (only system) and system works perfectly as before.

Roadblocks of Phase 1

How best to deliver this partition table change to users? The obvious answer is an update ZIP that just scripts it all (that's why I used sgdisk in this write-up). But then this requires the user to manually backup, reboot recovery, then restore backup. Is that ideal?

Another solution would be to export the new GPT, and make a MiFlash-flashable package. This could be another option for future, but would require new system and vendor images too - may as well be a whole flash package. That's big. We'll look into that once we actually get a Treble ROM working (e.g. stock).

Phase 1b revert - Restore stock partition map

If you want to go back to original partition table for some reason, you will need to flash an official fastboot ROM via EDL mode in MiFlash. After researching, I have discovered that there is no way around this. The way MiFlash works is it actually adjusts the GPT info dynamically based on *your* partition map (64GB vs 32GB have different userdata sizes) and for this to be done it needs to flash a full package. So, to restore stock partition map, you must flash a stock ROM in MiFlash via EDL mode which wipes everything. I hope you made a low-level and internal-storage backup like I warned - because after that you'll want to restore your backup to get persist and stuff back. Flashing in fastboot mode is not enough because it does not restore stock partition table.

Full steps for restoring to stock:

Boot into EDL mode

Load MiFlash, select any Oreo fastboot image (I use 8.1.10 since it's what I have) > Refresh. Should show COM30 (or whatever your QDLoader COM port is).

Reboot EDL by holding Power + VolDown and then 'fastboot oem edl' again

Run the restore in my Low-level flash tool of your backup

Reboot back into recovery by holding power + volume-up for ~10 seconds.

"Skip" on password screen

Wipe > Format Data > type "yes" to remove stock ROM encryption

Restore your TWRP backup

Done!

Phase 2 - Patch kernel DTB and TWRP

This requires Linux. I use ChaletOS in VirtualBox and have my home folder Samba shared, mapped to a network drive on my Windows host.

Probably when all this is finalized and working, we will use a custom kernel built from source. But for now lets just patch our existing kernel. I assume you already have TWRP installed.

Part 1 - Kernel DTB

Download the DTB split tool from:

https://github.com/dianlujitao/split-appended-dtb

...to your Linux machine. Just get the binary, not the .c source file.

Dump existing boot.img while in TWRP and pull from device:

adb shell dd if=/dev/block/bootdevice/by-name/boot of=/tmp/boot.img
adb pull /tmp/boot.img

Unpack this boot.img. I use AIK by @osm0sis from:

https://xdaforums.com/showthread.php?t=2073775

... In this case, we need boot.img-zImage. Copy it to the Linux machine folder with DTB split.

Split DTB from zImage on Linux machine:

./split-appended-dtb boot.img-zImage

...should produce 1 DTB. Total output will be two files - "kernel" and "dtbdump_1.dtb".

Decompile DTB on Linux machine:

# if you need to install it
sudo apt install device-tree-compiler
dtc -O dts -I dtb -o dtbdump_1.dts dtbdump_1.dtb

Edit dtbdump_1.dts in whatever text editor. Search for fstab and edit the vendor entry, adding "slotselect" to fsmgr_flags (so it's the same as system):

fsmgr_flags = "wait,slotselect";

NOTE: This is on my RR kernel. I need to check any difference with stock or other kernels.

Recompile the dts to dtb and build a new zImage:

dtc -O dtb -I dts -o dtbdump_1_new.dtb dtbdump_1.dts
cat kernel dtbdump_1_new.dtb > boot.img-zImage.new

Copy the boot.img-zImage.new back to your kernel kitchen tool, replacing the old one.

That's the device tree patched to mount seamless/slot vendor. But don't repack the boot.img yet, we need to edit RAMDisk.

Part 2 - TWRP patch

This is just so we can see Vendor (and Persist, because why not) in TWRP. This is so:

Vendor can be formatted (required before use), backed up/restored and flashed to

[Bonus] Persist can be backed up/restored and flashed to (for e.g. Persist repair ZIP's that should come soon).

Only one step is needed - edit /etc/recovery.fstab to add vendor mount (and also persist because why not) with flags:

/vendor ext4 /dev/block/bootdevice/by-name/vendor flags=slotselect;backup=1;wipeingui;display="Vendor"
/persist ext4 /dev/block/bootdevice/by-name/persist flags=backup=1;display="Persist"

That's it.

For your convenience, I have attached a Treble-modded TWRP installer to this thread with these changes. Don't forget to flash Magisk after re-installing TWRP. Big thanks to @ghpranav

Phase 3 - Compile a Treble ROM (for Vendor files)

Already succeeded. We just need to cleanup and push.

Phase 4 - Treble-ize an installed ROM

Is this possible? Not sure... I'll check it out later sometime

Did I miss anything? Probably. Let me know!