[Redmi 9 / Poco M2 Guides, News, & Discussion] morfikov:
There are some posts on how to root the Xiaomi Redmi 9 (Galahad/Lancelot) phone, but since they have lots of "don't know" phrases (or files of unknown origin), I've managed to do the whole process from scratch.

Lancelot or Galahad​

Basically, the codename for Xiaomi Redmi 9 phone is Lancelot. But when you get shell via ADB, you will see Galahad. This can cause lots of confusion because you may think that Galahad and Lancelot are two different phones. In reality they're the same phone. Moreover, the specs of the Xiaomi Redmi 9 says that the phone has a MT6769T SoC (the info comes from the phone's /proc/cpuinfo). But it looks like the official ROM, TWRP, even CPU-Z treats the phone as if it had the MT6768 SoC. So keep that in mind when you look for some info concerning the phone.

The phone was bought in Europe/Poland last year (the black Friday, 2020) from the official source. Here's some more info:

galahad:/ # getprop | grep -i model
[ro.product.model]: [M2004J19C]
[ro.product.odm.model]: [M2004J19C]
[ro.product.product.model]: [M2004J19C]
[ro.product.system.model]: [M2004J19C]
[ro.product.vendor.model]: [M2004J19C]

galahad:/ # getprop | grep -i ro.build.version.
[ro.build.version.base_os]: [Redmi/galahad_eea/galahad:10/QP1A.190711.020/V12.0.0.1.QJCEUXM:user/release-keys]
[ro.build.version.incremental]: [V12.0.1.0.QJCEUXM]
[ro.build.version.security_patch]: [2021-01-05]

galahad:/ # getprop | grep -i baseband
[gsm.version.baseband]: [MOLY.LR12A.R3.MP.V98.P75,MOLY.LR12A.R3.MP.V98.P75]
[ro.baseband]: [unknown]
[vendor.gsm.project.baseband]: [HUAQIN_Q0MP1_MT6769_SP(LWCTG_CUSTOM)]

$ fastboot getvar all
...
(bootloader) product: lancelot
...
(bootloader) version-baseband: MOLY.LR12A.R3.MP.V98.P75
(bootloader) version-bootloader: lancelot-2b1e22f-20201123162228-2021011
(bootloader) version-preloader:
(bootloader) version: 0.5
...

The bootloader unlock​

Before you even start thinking of flashing the TWRP image to the Xiaomi Redmi 9 (Galahad/Lancelot) phone, you have to unlock it's bootloader first. It's a straightforward operation, but you need some proper tools to achieve that. If you're using windows, use Mi Unlock, if you're on linux, use xiaomitool. I'm a linux user so I can't help with this process those of you who use windows. If you're going to use xiaomitool, there's a bug in the current version (20.7.28 beta), and you have to patch the source yourself to make it work again. It's not hard. There's an article step by step how to do it. It's in Polish, but all the necessary commands are included so you can just ctrl+c and ctrl+v.

When you unlock the bootloader, you can flash the TWRP image, so make sure you have the following in the Developer options:

View attachment 5396483

The TWRP image​

There are some prebuilt TWRP images in the wild, but I wanted source of the files, and I couldn't get any. But I've managed to target this device tree. I attached the twrp-recovery.img (64MiB) file in this post. It looks like the TWRP image built from that source has everything that's needed, so you won't really have to build it yourself. If you want to build the TWRP image yourself from the provided source, you have to go through setting up the android build environment.

Flashing the TWRP image​

When you have the TWRP image, you can flash it to the Xiaomi Redmi 9 (Galahad/Lancelot) phone using fastboot. On Debian, you just install the fastboot package. To flash the TWRP image, turn off you phone, turn it on using volumeDown+power, plug the phone via USB to your desktop/laptop and issue the following command:

$ fastboot flash recovery twrp-recovery.img

Remember one thing. This flashing has only a temporary effect. When you boot the device in a normal mode, the recovery partition will be automatically regenerated and flashed by your phone. So when you issue the command above, boot to recovery via:

$ fastboot reboot recovery

After you boot into TWRP recovery, it will ask for password. This is the password that you use to unlock your phone's lock screen.

Backup the phone's flash​

The temporary TWRP recovery is needed to take the backup of the whole phone's flash. The only partition that has been changed is the recovery partition. Other partitions are intact. In this way, you can backup partitions that hold IMEI, WiFi/BT MACs, and other important stuff. If something goes wrong, you can restore the phone to it's default state (after unlocking) using fastboot and the partition images.

To make the backup of the whole phone's flash, use the following command:

$ adb pull /dev/block/mmcblk0 mmcblk0.img

This command is issued from your desktop/laptop computer, and not from the phone. Of course you could just use the dd command and backup the flash to the external SD card, but my external SD was only 32G, and the phone's flash is 64G. Besides it's better to store the phone's flash on your computer for future use.

The process of taking a backup is rather slow. It took around 2h (14M/s). After it finishes, you can check whether everything with the image is OK by looking into the image using the gdisk tool:

$ adb pull /dev/block/mmcblk0 mmcblk0.img
/dev/block/mmcblk0: 1 file pulled. 14.0 MB/s (62537072640 bytes in 4266.682s)

# gdisk -l /media/Zami/mmcblk0.img
GPT fdisk (gdisk) version 1.0.7

Partition table scan:
MBR: protective
BSD: not present
APM: not present
GPT: present

Found valid GPT with protective MBR; using GPT.
Disk /media/Zami/mmcblk0.img: 122142720 sectors, 58.2 GiB
Sector size (logical): 512 bytes
Disk identifier (GUID): 00000000-0000-0000-0000-000000000000
Partition table holds up to 128 entries
Main partition table begins at sector 2 and ends at sector 33
First usable sector is 34, last usable sector is 122142686
Partitions will be aligned on 16-sector boundaries
Total free space is 61 sectors (30.5 KiB)

Number Start (sector) End (sector) Size Code Name
1 64 131135 64.0 MiB 0700 recovery
2 131136 132159 512.0 KiB 0700 misc
3 132160 133183 512.0 KiB 0700 para
4 133184 174143 20.0 MiB 0700 expdb
5 174144 176191 1024.0 KiB 0700 frp
6 176192 192575 8.0 MiB 0700 vbmeta
7 192576 208959 8.0 MiB 0700 vbmeta_system
8 208960 225343 8.0 MiB 0700 vbmeta_vendor
9 225344 271631 22.6 MiB 0700 md_udc
10 271632 337167 32.0 MiB 0700 metadata
11 337168 402703 32.0 MiB 0700 nvcfg
12 402704 533775 64.0 MiB 0700 nvdata
13 533776 632079 48.0 MiB 0700 persist
14 632080 730383 48.0 MiB 0700 persistbak
15 730384 746767 8.0 MiB 0700 protect1
16 746768 770047 11.4 MiB 0700 protect2
17 770048 786431 8.0 MiB 0700 seccfg
18 786432 790527 2.0 MiB 0700 sec1
19 790528 796671 3.0 MiB 0700 proinfo
20 796672 797695 512.0 KiB 0700 efuse
21 797696 850943 26.0 MiB 0700 boot_para
22 850944 982015 64.0 MiB 0700 nvram
23 982016 998399 8.0 MiB 0700 logo
24 998400 1260543 128.0 MiB 0700 md1img
25 1260544 1262591 1024.0 KiB 0700 spmfw
26 1262592 1274879 6.0 MiB 0700 scp1
27 1274880 1287167 6.0 MiB 0700 scp2
28 1287168 1289215 1024.0 KiB 0700 sspm_1
29 1289216 1291263 1024.0 KiB 0700 sspm_2
30 1291264 1324031 16.0 MiB 0700 gz1
31 1324032 1356799 16.0 MiB 0700 gz2
32 1356800 1360895 2.0 MiB 0700 lk
33 1360896 1364991 2.0 MiB 0700 lk2
34 1364992 1496063 64.0 MiB 0700 boot
35 1496064 1528831 16.0 MiB 0700 dtbo
36 1528832 1539071 5.0 MiB 0700 tee1
37 1539072 1549311 5.0 MiB 0700 tee2
38 1549312 1582079 16.0 MiB 0700 gsort
39 1582080 1844223 128.0 MiB 0700 minidump
40 1844224 2630655 384.0 MiB 0700 exaid
41 2630656 4727807 1024.0 MiB 0700 cust
42 4727808 4744191 8.0 MiB 0700 devinfo
43 4744192 4767743 11.5 MiB 0700 ffu
44 4767744 19447807 7.0 GiB 0700 super
45 19447808 20332543 432.0 MiB 0700 cache
46 20332544 122021823 48.5 GiB 0700 userdata
47 122021824 122109887 43.0 MiB 0700 otp
48 122109888 122142655 16.0 MiB 0700 flashinfo

As you can see, there's the whole flash layout with all the partitions in their stock state (except for the recovery partition, of course). If something goes wrong, you can extract the individual partition by mounting the image on a linux system in the following way:

# losetup /dev/loop5 /media/Zami/mmcblk0.img
# losetup -a
/dev/loop5: [64769]:12 (/media/Zami/mmcblk0.img)

The above command uses the /dev/loop5 device to mount the image. Since the image has many partitions, the corresponding devices will be created for each partition, which looks like this:

# ls -al /dev/loop5*
brw-rw---- 1 root disk 7, 320 2021-08-29 02:54:11 /dev/loop5
brw-rw---- 1 root disk 7, 321 2021-08-29 02:54:11 /dev/loop5p1
brw-rw---- 1 root disk 7, 330 2021-08-29 02:54:11 /dev/loop5p10
brw-rw---- 1 root disk 7, 331 2021-08-29 02:54:11 /dev/loop5p11
brw-rw---- 1 root disk 7, 332 2021-08-29 02:54:11 /dev/loop5p12
brw-rw---- 1 root disk 7, 333 2021-08-29 02:54:11 /dev/loop5p13
brw-rw---- 1 root disk 7, 334 2021-08-29 02:54:11 /dev/loop5p14
brw-rw---- 1 root disk 7, 335 2021-08-29 02:54:11 /dev/loop5p15
brw-rw---- 1 root disk 7, 336 2021-08-29 02:54:11 /dev/loop5p16
brw-rw---- 1 root disk 7, 337 2021-08-29 02:54:11 /dev/loop5p17
brw-rw---- 1 root disk 7, 338 2021-08-29 02:54:11 /dev/loop5p18
brw-rw---- 1 root disk 7, 339 2021-08-29 02:54:11 /dev/loop5p19
brw-rw---- 1 root disk 7, 322 2021-08-29 02:54:11 /dev/loop5p2
brw-rw---- 1 root disk 7, 340 2021-08-29 02:54:11 /dev/loop5p20
brw-rw---- 1 root disk 7, 341 2021-08-29 02:54:11 /dev/loop5p21
brw-rw---- 1 root disk 7, 342 2021-08-29 02:54:11 /dev/loop5p22
brw-rw---- 1 root disk 7, 343 2021-08-29 02:54:11 /dev/loop5p23
brw-rw---- 1 root disk 7, 344 2021-08-29 02:54:11 /dev/loop5p24
brw-rw---- 1 root disk 7, 345 2021-08-29 02:54:11 /dev/loop5p25
brw-rw---- 1 root disk 7, 346 2021-08-29 02:54:11 /dev/loop5p26
brw-rw---- 1 root disk 7, 347 2021-08-29 02:54:11 /dev/loop5p27
brw-rw---- 1 root disk 7, 348 2021-08-29 02:54:11 /dev/loop5p28
brw-rw---- 1 root disk 7, 349 2021-08-29 02:54:11 /dev/loop5p29
brw-rw---- 1 root disk 7, 323 2021-08-29 02:54:11 /dev/loop5p3
brw-rw---- 1 root disk 7, 350 2021-08-29 02:54:11 /dev/loop5p30
brw-rw---- 1 root disk 7, 351 2021-08-29 02:54:11 /dev/loop5p31
brw-rw---- 1 root disk 7, 352 2021-08-29 02:54:11 /dev/loop5p32
brw-rw---- 1 root disk 7, 353 2021-08-29 02:54:11 /dev/loop5p33
brw-rw---- 1 root disk 7, 354 2021-08-29 02:54:11 /dev/loop5p34
brw-rw---- 1 root disk 7, 355 2021-08-29 02:54:11 /dev/loop5p35
brw-rw---- 1 root disk 7, 356 2021-08-29 02:54:11 /dev/loop5p36
brw-rw---- 1 root disk 7, 357 2021-08-29 02:54:11 /dev/loop5p37
brw-rw---- 1 root disk 7, 358 2021-08-29 02:54:11 /dev/loop5p38
brw-rw---- 1 root disk 7, 359 2021-08-29 02:54:11 /dev/loop5p39
brw-rw---- 1 root disk 7, 324 2021-08-29 02:54:11 /dev/loop5p4
brw-rw---- 1 root disk 7, 360 2021-08-29 02:54:11 /dev/loop5p40
brw-rw---- 1 root disk 7, 361 2021-08-29 02:54:11 /dev/loop5p41
brw-rw---- 1 root disk 7, 362 2021-08-29 02:54:11 /dev/loop5p42
brw-rw---- 1 root disk 7, 363 2021-08-29 02:54:11 /dev/loop5p43
brw-rw---- 1 root disk 7, 364 2021-08-29 02:54:11 /dev/loop5p44
brw-rw---- 1 root disk 7, 365 2021-08-29 02:54:11 /dev/loop5p45
brw-rw---- 1 root disk 7, 366 2021-08-29 02:54:11 /dev/loop5p46
brw-rw---- 1 root disk 7, 367 2021-08-29 02:54:11 /dev/loop5p47
brw-rw---- 1 root disk 7, 368 2021-08-29 02:54:11 /dev/loop5p48
brw-rw---- 1 root disk 7, 325 2021-08-29 02:54:11 /dev/loop5p5
brw-rw---- 1 root disk 7, 326 2021-08-29 02:54:11 /dev/loop5p6
brw-rw---- 1 root disk 7, 327 2021-08-29 02:54:11 /dev/loop5p7
brw-rw---- 1 root disk 7, 328 2021-08-29 02:54:11 /dev/loop5p8
brw-rw---- 1 root disk 7, 329 2021-08-29 02:54:11 /dev/loop5p9

To extract some partition (for instance the stock boot), use the following command:

# dd if=/dev/loop5p34 of=./34-stock-boot.img

Extracting any of the partitions from the backup creates a file that can be flashed via fastboot or directly via dd from TWRP recovery. So as long as fastboot (or TWRP recovery) works and you are able to switch to that mode, you shouldn't brick the phone for good. All the bricks should be only temporary and they go away when you flash the stock partitions to the changed ones. So pay attention what changes you commit to the phone's flash.

The Magisk app and a bootloop​

To sum up, we have a backup of the phone's flash on our computer, we have flashed a temp TWRP image to the recovery partition, and we are booted in the TWRP recovery mode. Now it's time to flash Magisk and get root on our Xiaomi Redmi 9 (Galahad/Lancelot) phone.

But not so fast. If you just flashed the Magisk apk file using TWRP, you will get a bootloop. This is because of the Android Verified Boot mechanism, which still works even after you unlock the phone. You can read about this AVB mechanism more here. Basically it's all about the boot partition hashes (and possibly other partition hashes as well) which are allowed by manufacturer of the phone to be valid. So only those boot images that have valid hashes can be used in the boot process of the device. Flashing Magisk changes the boot partition, and in this way the hash of the boot partition changes. So, when you try to boot the phone after you flashed Magisk from the TWRP recovery, it will bootloop. Also you will loose access to the recovery partition, so you won't be able to revert the change you did when you flashed the Magisk app. The only way to restore the phone in such state is to flash the stock boot partition. That's why you should make the phone's whole flash backup. I include the stock boot partition here for those who didn't have the backup, but pay attention that this boot image is for Android10/MIUI12 (see the specs above), and I don't know what will happen if you use the image with different software/firmware/ROM.

Install the Magisk app​

To avoid the unpleasant bootloop situation after flashing the Magisk app, you have to deactivate the AVB mechanism. You do this by flashing the stock vbmeta partition using fastboot, i.e. the following command:

# dd if=/dev/loop5p6 of=./6-stock-vbmeta.img
$ fastboot --disable-verity --disable-verification flash vbmeta 6-stock-vbmeta.img

You can proceed with flashing the Magisk app only after you disable the AVB mechanism.

If your phone restored the stock recovery, flash once again the TWRP recovery, and boot into the recovery mode. Download the most recent Magisk app, currently Magisk-v23.0.apk. Yes, I know it's an APK file, and yes, you have to flash the APK file via TWRP recovery. You're going to see some messages about repacking the stock boot and flashing it.

View attachment 5396501

This is the step when the phone stops rewriting the custom recovery partition. So, after installing the Magisk app, the TWRP recovery will be persistent, and you won't have to flash it again.

After flashing the APK file, you have to boot to the phone's OS in order to finish installing Magisk (the OS part/app). You'll be prompted to do this step, so follow what it says and ultimatelly you get the Magisk installed:

View attachment 5396499

SafetyNet​

The next thing is to open the Magisk App. After this, check the SafetyNet. It should fail. Go to the options and "Hide the Magisk app". You also have to activate MagiskHide. After this, check the SafetyNet again. It should pass now.

View attachment 5396493

So now you have the root access on your Xiaomi Redmi 9 (Galahad/Lancelot) and also it passes the SafetyNet.

This HOWTO should work for the Xiaomi Redmi 9 (Galahad/Lancelot) phones, but I'm not sure whether I forgot to mention about something. Anyways, if you have any questions, or something doesn't work, ask.