Как вы заметили я редко пишу узкоспециализированные технические посты, в основном контент расчитан на более широкую аудиторию, но сегодня я не удержался. Предыстория очень простая. Во время сборки кастомного Recovery для одного из аппаратов на чипе от Mediatek я столкнулся с проблемой - тачпад в Recovery не работал, а любые упоминания о mtk-tpd напрочь отсутствовали в /sys/class/input. Надо сказать что mtk-tpd это как раз и есть тот самый MTK Android Linux Touch Panel Device Driver, который отвечает за работу тачпада. Напомню, что в нормальной ситуации, когда тачпад в recovery работает, сделав что-то вроде grep . /sys/class/input/input*/name в консоли мы должны увидеть примерно следующее:
Однако в моей ситуации mtk-tpd отсутствовал. Зная что на одном из форумов есть человек, который уже занимался патчами ядра ARM64 для Mediatek, я обратился к нему с вопросом, а каким образом (честно говоря я рассчитывал на ответ в двух словах, такая-то функция, такая-то проверка) он заставил работать тачпад в recovery и что конкретно он патчил в ядре. Правда здесь я почему-то наткнулся на стену глухого непонимания и какой-то секретности. Ну "секрет" так секрет, настаивать, чтобы кто-то что-то рассказал, если человек сам не хочет бессмысленно. Поэтому я решил провести некий анализ, который занял от минут 30-40 ... теперь голые факты. В MTK существует несколько режимов загрузки, который описаны в заголовочных файлах ядра (mt_boot_common.h), вот они:
Как видно при вызове tpd_i2c_probe проверяется, если boot mode у нас равен RECOVERY_BOOT, то драйвер у нас не инициализируется ;) Т.е. со стороны MTK так и задумано что в recovery тач пользователю не нужен. Но ведь TWRP фактически использует только тач, скажете вы и будете правы. Но девайсы на платформе MTK никогда ведь не идут с TWRP в комплекте, а стоковому recovery тач естественно не нужен. Поэтому сейчас я вам расскажу как найти соответствующую проверку в бинарнике ядра, ну а непосредственно патч будет "домашним заданием" ) Должна же остаться какая-то "изюминка" ... Так вот. Для начала узнаем адрес tpd_i2c_probe, для этого от имени root выполняем:
В результате получаем нужный нам адрес 0xffffffc000760494. Далее загружаем в любом дизассемблер распакованное ядро (архитектура моего CPU - ARM64, поэтому offset нужной нам функции как видите 64-битный) с адреса 0xFFFFFFC000080000 (для 32-bit ядер - 0xC0008000) и переходим по найденному адресу:
На скриншоте выше наглядно видно и исходники и дизассемблированный код. На поиск нужной функции, как вы можете убедиться, и места проверки в ядре у нас ушло не более 5 минут. Теперь нам достаточно убрать условный переход по адресу 0xFFFFFFC0007604D0, заменив его NOP'ами или любой другой "пустой операцией" и собрать boot с модифицированным ядром назад. После чего при загрузке в recovery тачпад будет успешно инициализироваться.
Успехов вам!
p.s. Да, забыл сказать ... в данном примере мы разбирали инициализацию MediaTek gt91xx touch panel driver. Естественно, что в вашем устройстве может быть другой драйвер тача.
/sys/class/input/input0/name:ACCDET
/sys/class/input/input1/name:mtk-kpd
/sys/class/input/input2/name:hwmdata
/sys/class/input/input3/name:m_alsps_input
/sys/class/input/input4/name:m_acc_input
/sys/class/input/input5/name:m_gyro_input
/sys/class/input/input6/name:mtk-tpd
/sys/class/input/input7/name:mtk-tpd-kpd
Однако в моей ситуации mtk-tpd отсутствовал. Зная что на одном из форумов есть человек, который уже занимался патчами ядра ARM64 для Mediatek, я обратился к нему с вопросом, а каким образом (честно говоря я рассчитывал на ответ в двух словах, такая-то функция, такая-то проверка) он заставил работать тачпад в recovery и что конкретно он патчил в ядре. Правда здесь я почему-то наткнулся на стену глухого непонимания и какой-то секретности. Ну "секрет" так секрет, настаивать, чтобы кто-то что-то рассказал, если человек сам не хочет бессмысленно. Поэтому я решил провести некий анализ, который занял от минут 30-40 ... теперь голые факты. В MTK существует несколько режимов загрузки, который описаны в заголовочных файлах ядра (mt_boot_common.h), вот они:
/* boot type definitions */
enum boot_mode_t {
NORMAL_BOOT = 0,
META_BOOT = 1,
RECOVERY_BOOT = 2,
SW_REBOOT = 3,
FACTORY_BOOT = 4,
ADVMETA_BOOT = 5,
ATE_FACTORY_BOOT = 6,
ALARM_BOOT = 7,
#if defined(CONFIG_MTK_KERNEL_POWER_OFF_CHARGING)
KERNEL_POWER_OFF_CHARGING_BOOT = 8,
LOW_POWER_OFF_CHARGING_BOOT = 9,
#endif
DONGLE_BOOT = 10,
UNKNOWN_BOOT
};
В драйвере дисплея в процедуре инициализации тача есть проверка:
static s32 tpd_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
int err = 0;
int count = 0;
GTP_INFO("tpd_i2c_probe start.");
if (RECOVERY_BOOT == get_boot_mode())
return 0;
probe_thread = kthread_run(tpd_registration, client, "tpd_probe");
if (IS_ERR(probe_thread)) {
err = PTR_ERR(probe_thread);
GTP_INFO(TPD_DEVICE " failed to create probe thread: %d\n", err);
return err;
}
do {
msleep(20);
count++;
if (check_flag)
break;
} while (count < 50);
GTP_INFO("tpd_i2c_probe done.count = %d, flag = %d", count, check_flag);
return 0;
}
Как видно при вызове tpd_i2c_probe проверяется, если boot mode у нас равен RECOVERY_BOOT, то драйвер у нас не инициализируется ;) Т.е. со стороны MTK так и задумано что в recovery тач пользователю не нужен. Но ведь TWRP фактически использует только тач, скажете вы и будете правы. Но девайсы на платформе MTK никогда ведь не идут с TWRP в комплекте, а стоковому recovery тач естественно не нужен. Поэтому сейчас я вам расскажу как найти соответствующую проверку в бинарнике ядра, ну а непосредственно патч будет "домашним заданием" ) Должна же остаться какая-то "изюминка" ... Так вот. Для начала узнаем адрес tpd_i2c_probe, для этого от имени root выполняем:
sh -c "echo 0 > /proc/sys/kernel/kptr_restrict"
cat /proc/kallsyms | grep tpd_i2c_probe
В результате получаем нужный нам адрес 0xffffffc000760494. Далее загружаем в любом дизассемблер распакованное ядро (архитектура моего CPU - ARM64, поэтому offset нужной нам функции как видите 64-битный) с адреса 0xFFFFFFC000080000 (для 32-bit ядер - 0xC0008000) и переходим по найденному адресу:
На скриншоте выше наглядно видно и исходники и дизассемблированный код. На поиск нужной функции, как вы можете убедиться, и места проверки в ядре у нас ушло не более 5 минут. Теперь нам достаточно убрать условный переход по адресу 0xFFFFFFC0007604D0, заменив его NOP'ами или любой другой "пустой операцией" и собрать boot с модифицированным ядром назад. После чего при загрузке в recovery тачпад будет успешно инициализироваться.
Успехов вам!
p.s. Да, забыл сказать ... в данном примере мы разбирали инициализацию MediaTek gt91xx touch panel driver. Естественно, что в вашем устройстве может быть другой драйвер тача.
" Правда здесь я почему-то наткнулся на стену глухого непонимания и какой-то секретности. Ну "секрет" так секрет, настаивать, чтобы кто-то что-то рассказал, если человек сам не хочет бессмысленно."
ОтветитьУдалитьЯ всегда удивляюсь таким людям. Ведь, помогая (учишь других) другим, помогаешь (учишься сам) себе.
Добрый день! А возможно ли инвертировать оси тачскрина или акселерометра, не имея исходников ядра?
ОтветитьУдалитьЗдравствуйте. Классная статья, все понятно как делать, но работаю из-под Windows и не могу подобрать дизассемблер под arm64, подскажите, пожалуйста, инструмент. У меня надежда, что bokken откроет, но его с сервера не скачать, internal error.
ОтветитьУдалитьIDA
УдалитьКакие проги нужны? чтоб выполнить по мануалу
ОтветитьУдалить