[GUIDE] [MTK] [ARM only] How to reverse LCM driver

ruben1863

New member
Jan 6, 2019
3
2
3
Hey, this is my guide for reversing MTK lcm driver from stock compiled kernel (32 bit mode) disassembling it. I hope this helps lot of people.

NOTE: This should work with lots of LCMS

1* What do you need?

- common sense and patience 😊

-lcm_drv.h (from the same Alps kernel that your device haves, EXAMPLE: 3.18.19 is alps-mp-m0.mp1)

-You kernel, extracted from your boot.img

-Your kallsyms.txt (see the line on how to get this file)

-7zip

-Notepad ++

-IDA Pro (6.8 or higher)

Optional:

-Ubuntu on Windows 10 (App in Microsoft Store), or Linux in dual boot

-A lcm driver template (to see the structure and to rewrite it with your values)


2* Basic Tutorials

-How to get kallsyms.txt: You need root permission!

#Download a terminal emulator in your phone, grant root permission to the app and paste one by one these commands:
Bash:
su

echo 0 > /proc/sys/kernel/kptr_restrict

cat /proc/kallsyms > /sdcard/kallsyms.txt
Then you will have your kallsyms.txt in /sdcard path

-How to get lcm_drv.h

NOTE: lcm-drv.h is located in drivers/misc/mediatek/lcm/inc/lcm_drv.h

Here some links of alps kernel sources: (MT6580)

-3.18.19 (alps-mp-m0.mp1): Marshmallow lcm_drv.h

-3.18.35 (alps-mp-n0.mp2): Nougat lcm_drv.h

-3.18.79 (alps-mp-o1.mp2): Oreo lcm_drv.h


3* Steps

-At first you need to go to your kernel, and do right click and select “7zip” and then “extract here”, you will have your kernel and another file called “kernel~”, load the other file that 7zip extracted in IDA selecting ARM Little endian as processor type and writing the correct ROM start address and loading address, the value you need to write in both is 0xC0008000

-When you successfully loaded kernel in IDA and the auto analysis finished, then you need to load kallsyms.txt, so it will do the things really clear to see. For load kallsyms you need a IDA script called “kallsyms_loader.idc”

#Download of the script:

kallsyms_loader

Load the kallsyms.txt with the script and wait to the script finishing import all the elements.

-When it finishes you need to do a search of strings and search “lcm_init” (if your device has more than one lcm, IDA will write numbers behind the lcm_init, EXAMPLE: lcm_init, lcm_init_1, lcm_init_1_2; so, you need to know the name of your main lcm and follow the references to your lcm functions and you will know the exact lcm_init function that your main lcm uses)

-Now you need to decompile your lcm functions to get SET_RESET_PIN and MDELAY values, to do that go to the function and press F5, the output will be like this: (SEE PICTURE)


1.png


NOTE:
- SET_RESET_PIN values are only 0 or 1
The 1 and 0 values are alternating. This means that it should start with 1, the next will be 0, the next 1...
- MDELAY can be any value.

All the vC1023EC0 are SET_RESET_PIN values, and all the vC1023ED0 are MDELAY values. In your case these vBlablabla value may vary. You need to take in count this.

There are also some values like “push_table_constrop…”, that are needed for the driver, because they set when the lcm tables are “used”, so you need to write this in all of these cases:

-If is a lcm_init function you need to write on your driver:

push_table(lcm_initialization_setting, sizeof(lcm_initialization_setting) / sizeof(struct LCM_setting_table), 1);
-If is a lcm_suspend function then write:

push_table(lcm_deep_sleep_mode_in_setting, sizeof(lcm_deep_sleep_mode_in_setting) / sizeof(struct LCM_setting_table), 1);
-If is a lcm_resume function then write:

push_table(lcm_sleep_out_setting, sizeof(lcm_sleep_out_setting) / sizeof(struct LCM_setting_table), 1);
Now when you finished to decompile all the other lcm functions and you wrote it in your driver, you need to write your lcm_compare_id, this step is very easy, because you only need to write in your driver “return 1”. Here how do you need to write it:

C:
static unsigned int lcm_compare_id(void)
{
    return 1;
}
-Now you only need to reverse a harder lcm function, the lcm_params, for this step you need your corresponding lcm_drv.h. First go to IDA options, and go to “Compiler…”. Set as compiler “GNU C++”. Go to your lcm_params function and press F5 to decompile it. The output Will be like this: (SEE PICTURE)

2.png


You need to do right click on “int”: (SEE PICTURE)

1611491881285.png


And then click on “Set lvar type”, delete “int a1” text and write “LCM_PARAMS*”, the output Will be like this: (SEE PICTURE)

1611491930371.png


Now you need to right click on “a1”, in the same line as the step before, but now you need to click on “Set lvar name” instead of “Set lvar type”, now delete “a1” text and enter “params”,

now you will have: (SEE PICTURE)

1611491983856.png


You need to copy in your driver from “params->dsi.LANE_NUM = 3;” to “params>dsi.horizontal_blanking_pixel = 60;” both included.

You are done with the lcm_params function 😊

-Now you only need to reverse the lcm tables.

THERE ARE TWO METHODS:

FIRST (SOMETIMES IT DOESN’T WORK BECAUSE ALL TABLES ARE NOT COMPATIBLE):

You need a tool called LK.BIN parser, avaible at: LK.BIN-Parser

So, in your Linux environment open a terminal window and do: git clone https://github.com/Ruben1863/lk.git

Now go to IDA on Windows (because of this I recommend Ubuntu on Windows 10, so you can switch very easy), and go to your lcm functions you want to reverse it table (for the example i will use lcm_init function) and press double click on the references that your lcm_init function haves at his end: (SEE THE PICTURE)

1611492129294.png


Double click on the value or the reference (in some cases is defined by a reference) and you will switch to: (SEE PICTURE)

1611492156818.png


Now don’t move the position of the mouse, because we need to stay in “ROM:C0D202B8”, because in the Hex view of IDA you will see your lcm initializing address of the table you are reversing. So switch to “Hex View-1”

1611492203606.png


Here you can see lots of 00 and other values, but you need to copy only the ROM blue marked values (FF 00 00 00 03 98 81 07), from “FF” to “07”, the other zeros not, because as you can see there are tons of zeros behind. Remember to copy this initializing address because you need it.

Now switch to your Ubuntu and open in the file explorer the LK.bin parser folder, which is “lk”, now do right click no the file called “parser.js”, and click on “edit with Notepad ++”. When the file opened, you will see the structure of the script. You need to go to headers, and copy the first header, and paste it in the second position, like this: (SEE PICTURE)

1611492244836.png


Now you need to replace the name of the header you copied with your lcm “first name”, i mean, if your lcm is “hct_ili9881_dsi_vdo_hd_cpt” you only need to copy “ili_9881”, and in the code you need to copy the values that you copied (FF 00 00 00 03 98 81 07), and replace the header values with yours: (SEE PICTURE)

1611492273848.png


Now save the file, and copy the kernel you extracted with 7zip to the LK.bin parser folder, and rename it to lk.bin. Then open the Ubuntu. Now you need to change the script permissions, so do “chmod -R 777 lk” and then do “cd lk” and “bash installnode.sh”, wait for the file finishing installing all the things, and then type “nodejs parser.js”, it will start to search for headers. When it finishes you will see your lcm possible tables, it can be more than 1 table, but in this case, there is only one possible table: (SEE PICTURE)

1611492369387.png


So, open the table with Notepad ++, and now you need to write “REGFLAG_DELAY” values in table, these values are in the end of the file: (SEE PICTURE)

1611492396988.png


The REGFLAG_DELAY values are easy to see, because one of these lines have only 0x00 written, these values are the 0xfe, delete all the 0x00 in 0xfe, 20…, the output needs to be like this: (SEE PICTURE)

1611492418126.png


Now replace both “0xfe” to “REGFLAG_DELAY”, the output needs to be like this: (SEE PICTURE)

1611492445962.png


Now you only need to copy all the table and paste it in the place of the lcm_table

Now you need to do these steps to reverse all the other lcm tables (like sleep_out and sleep_in), but only if your lcm haves and uses that tables.

METHOD 2 (COMPATIBLE WITH ALL TABLES, BUT MORE TIME NEEDED):

In IDA press double click on the references that your lcm_init function haves at his end: (SEE PICTURE)

1611492523584.png


Double click on the value or the reference (in some cases is defined by a reference) and you will switch to: (SEE PICTURE)

1611492549904.png


Now don’t move the position of the mouse, because we need to stay in the same ROM address “ROM:C0D202B8”, because in the Hex view of IDA you will see your lcm initializing address of the table you are reversing. So, switch to “Hex View-1”

1611492589750.png


Here is where you need a lot of common sense and patience. You have these values (FF 00 00 00 03 98 81 07). Here you need to transcribe every line that are not 00s.

Example:

FF 00 00 00 03 98 81 07 will be transcribed to => {0xFF, 3, {0x98, 0x81, 0x07}}
You need to skip transcribing all these three 00s

NOTE: in some LCMs the three 00s won’t be, that is normal.

Example:

FF 03 98 81 07 will be transcribed to => {0xFF, 3, {0x98, 0x81, 0x07}}
You need to do this with EVERY LINE of data.

Example of the next lines:

1611492687437.png


03 00 00 00 01 20 => {0x03, 1, {0x20}}
04 00 00 00 01 06 => {0x04, 1, {0x06}}
NOTE: the second value (in this case, the fifth, because we are skipping the three 00s) must be transcribed from Hexadecimal to Decimal.

When you arrive to the end of the table you will see it really clear. So, you need to write at the end of the table:

{REGFLAG_END_OF_TABLE, 0x00, {}}
NOW YOU ARE DONE, YOU REVERSED YOUR LCM DRIVER 😊


4* Help needed?

If you can’t get your lcm working properly, or if you got stuck at some point of the guide you can contact me:

Telegram: Ruben1863

Discord: rub3n1863#5484
 
Last edited: