• Introducing XDA Computing: Discussion zones for Hardware, Software, and more!    Check it out!

[GUIDE] How to unlock and root Xiaomi Redmi 9 (Galahad/Lancelot)

Search This thread

morfikov

Senior Member
Oct 22, 2016
111
26
Warsaw
morfikov.github.io
Redmi 9
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:

Code:
    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:

Screenshot_2021-08-27-15-58-07-496_com.android.settings.jpg


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:

Code:
    $ 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:

Code:
    $ 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:

Code:
    $ 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:

Code:
    $ 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:

Code:
    # 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:

Code:
    # 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:

Code:
    # 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:

Code:
    # 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.
Screenshot_2021-08-29-02-46-21.png


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:

Screenshot_2021-08-29-17-37-16-773_onylcwss.r.jpg


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.

Screenshot_2021-08-29-17-37-30-250_onylcwss.r.jpg


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.
 

Attachments

  • 34-stock-boot.img
    64 MB · Views: 136
  • twrp-recovery.img
    64 MB · Views: 194
Last edited:

Christoph21x

Senior Member
May 22, 2009
705
337
Schwyz
Thanks a lot for this great guide.
Small problem here though ;-)

Entering
$ fastboot reboot recovery
leads to:
fastboot: usage: unknown reboot target recovery
Looking at fastboot --help there is no such parameter. Either bootloader or emergency (the latter doesn't work)

Thanks in advance - Chris
 

Christoph21x

Senior Member
May 22, 2009
705
337
Schwyz

Kuba432110

Member
Feb 16, 2017
31
9
Great guide! I even managed to compile latest TWRP from the devicetree you linked. The only thing that I would add is that I had to use losetup -fP <name>.img. The "P" flag forces the loop device to display partitions and "f" just takes the first available device. As for magisk, I had to use the Didgeridoohan's MagiskHide Props Config module in order to pass CTS check. I just had to "Force BASIC key attestation" using the default value "galahad". I suspect that has to do with the fact that i'm running latest EEA rom (Android 11), other than that I use the same phone - European version bought in Poland :)
 
  • Like
Reactions: morfikov

Christoph21x

Senior Member
May 22, 2009
705
337
Schwyz
Another tipp which makes the the deavtivation of the AVB mechanism and flashing the stock vbmeta partition using fastbootmuch easier, fast - and also suitable to Windows machines. It takes all together only 2-3 minutes then:

When you're in TWRP after the first flash, instead of pulling the complete image of your Redmi 9 (which is not bad at all, but the image is not loadable under Win machines), you use the means of TWRP:
  • In TWRP you enter the section "Backup"
  • There you select the storage "Micro SD card"
  • In the list of partitions to be backed up ONLY select "vbmeta". It's only 8 MB. (This only takes a few seconds and requires not more than 9MB on your SD card ;-) )
  • Then "Swipe to Backup"
  • After that you stay in TWRP
Then you copy the tiny backup to your adb/fastboot folder on the PC (as you're in TWRP, you have full access):
  • Copy from your phone the files from Redmi's "External_SD/TWRP/BACKUPS/Redmi_9/<current date/time/ID>" to your adb/fastboot folder on the PC:
    • vbmeta.emmc.win
    • vbmeta.emmc.win.sha2
    • (recovery.log is not needed, it only contains the console output)
  • Within TWRP go back to the main menu and select "Reboot" and select "Fastboot"
    The Smartphone reboots into TWRP / Fastboot mode
  • Now from the PC you turn the the AVB mechanism off by flashing:
    $ fastboot --disable-verity --disable-verification flash vbmeta vbmeta.emmc.win
Now you continue with the guide above - reflashing TWRP & booting in Recovery:
$ fastboot flash recovery twrp-recovery.img
$ fastboot reboot recovery


In TWRP back again, now flash Magisk-vXY.Z.apk and reboot to System after that (to clean Cache & Dalvik is not a bad idea).
The flash of TWRP is now permanent (can be entered anytime from device off --> Press and hold Power and Volume up buttons)
 
Last edited:
  • Like
Reactions: morfikov

Accidd

Senior Member
Aug 16, 2009
108
89
Wroclaw
Any tip for me?

I have J19AG (lancelot at first). The problem is that I can't fix broken Google Play Protect on other roms than EEA. This phone came with EEA rom which had GPP. Then I unlocked bootloader and flashed non EEA rom. I have tried TR, ID, IN, RU fastboot roms but none worked with GPP.

Im now on ID rom and trying to fix it using Magisk modules to change props. But neither galahad or lancelot worked for Force Basic Key attestation. After changing galahad to lancelot my base_os prop is empty. Magisk CTS check is still failed.

Code:
[ro.build.version.all_codenames]: [REL]
[ro.build.version.base_os]: []
[ro.build.version.codename]: [REL]
[ro.build.version.incremental]: [V12.0.3.0.QJCIDXM]
 

Accidd

Senior Member
Aug 16, 2009
108
89
Wroclaw
No I do not want this.
I asked some certain question.
I know exactly what I'm doing and have skills for that.

My goal was to have galahad with rom other than EEA with Google Play protect on.
Currently only EEA <-> Galahad is possible. ID, TW, TR rom have no Google Play protect when unlocked or locked bootloader on galahad (Redmi 9 with NFC).

The trick is to fix Google Play protect with Magisk and TWRP. But above methods didnt work for me.
 

lotiopep

New member
Feb 26, 2011
4
0
Hello.
I'm having a problem using the losetup command. After using
sudo losetup /dev/loop3 mmcblk0.img
and checking out the partitions created with
[I]ls -al /dev/loop3*[/I]
I only get ...
brw-rw---- 1 root disk 7, 3 d’oct. 16 10:40 /dev/loop
When checking mmcblk0.img with command
[I]gdisk -l mmcblk0.img[/I]
I get the same as you.

I understand that losetup doesn't create the partitions other than one so I can't extract anyone in particular. Am I doing something wrong. I'm using an updated Ubuntu 20.04.

Thanks for your help.
 

lotiopep

New member
Feb 26, 2011
4
0
Then edit the kernel cmd line in grub bootloader (or whatever ubuntu is using) and add to it loop.max_part=64 and restart the system.
Thanks again. I'm still trying. In Ubuntu it's different and after doing it it didn't work (and somehow I broke the OS and had to reinstall it).
I think I will try to do it in a virtualised Debian system.
 

Top Liked Posts

  • There are no posts matching your filters.
  • 4
    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:

    Code:
        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:

    Screenshot_2021-08-27-15-58-07-496_com.android.settings.jpg


    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:

    Code:
        $ 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:

    Code:
        $ 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:

    Code:
        $ 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:

    Code:
        $ 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:

    Code:
        # 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:

    Code:
        # 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:

    Code:
        # 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:

    Code:
        # 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.
    Screenshot_2021-08-29-02-46-21.png


    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:

    Screenshot_2021-08-29-17-37-16-773_onylcwss.r.jpg


    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.

    Screenshot_2021-08-29-17-37-30-250_onylcwss.r.jpg


    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.
    1
    It works just fine with my phone:

    Code:
    $ fastboot reboot recovery
    Rebooting into recovery                            OKAY [  0.001s]
    Finished. Total time: 0.252s

    Maybe you need a newer version of the tool?
    1
    Great guide! I even managed to compile latest TWRP from the devicetree you linked. The only thing that I would add is that I had to use losetup -fP <name>.img. The "P" flag forces the loop device to display partitions and "f" just takes the first available device. As for magisk, I had to use the Didgeridoohan's MagiskHide Props Config module in order to pass CTS check. I just had to "Force BASIC key attestation" using the default value "galahad". I suspect that has to do with the fact that i'm running latest EEA rom (Android 11), other than that I use the same phone - European version bought in Poland :)
    1
    The process of taking a backup is rather slow. It took around 2h (14M/s)
    You might have been using a USB 2.0 port.
    It is advised that you use a USB 3.x Port. Throughput here was: 146.5 MB/s. It took around 10-15 Minutes.
    Maybe you want to put that advise in your guide..
    1
    Another tipp which makes the the deavtivation of the AVB mechanism and flashing the stock vbmeta partition using fastbootmuch easier, fast - and also suitable to Windows machines. It takes all together only 2-3 minutes then:

    When you're in TWRP after the first flash, instead of pulling the complete image of your Redmi 9 (which is not bad at all, but the image is not loadable under Win machines), you use the means of TWRP:
    • In TWRP you enter the section "Backup"
    • There you select the storage "Micro SD card"
    • In the list of partitions to be backed up ONLY select "vbmeta". It's only 8 MB. (This only takes a few seconds and requires not more than 9MB on your SD card ;-) )
    • Then "Swipe to Backup"
    • After that you stay in TWRP
    Then you copy the tiny backup to your adb/fastboot folder on the PC (as you're in TWRP, you have full access):
    • Copy from your phone the files from Redmi's "External_SD/TWRP/BACKUPS/Redmi_9/<current date/time/ID>" to your adb/fastboot folder on the PC:
      • vbmeta.emmc.win
      • vbmeta.emmc.win.sha2
      • (recovery.log is not needed, it only contains the console output)
    • Within TWRP go back to the main menu and select "Reboot" and select "Fastboot"
      The Smartphone reboots into TWRP / Fastboot mode
    • Now from the PC you turn the the AVB mechanism off by flashing:
      $ fastboot --disable-verity --disable-verification flash vbmeta vbmeta.emmc.win
    Now you continue with the guide above - reflashing TWRP & booting in Recovery:
    $ fastboot flash recovery twrp-recovery.img
    $ fastboot reboot recovery


    In TWRP back again, now flash Magisk-vXY.Z.apk and reboot to System after that (to clean Cache & Dalvik is not a bad idea).
    The flash of TWRP is now permanent (can be entered anytime from device off --> Press and hold Power and Volume up buttons)